初始提交

This commit is contained in:
2024-09-28 14:24:04 +08:00
commit c756587541
5564 changed files with 2413077 additions and 0 deletions

90
sbl/Makefile Normal file
View File

@@ -0,0 +1,90 @@
# OUTPUT type
# 1 - .out
# 2 - .a
# 3 - .so
OUTPUT_TYPE = 1
OUTPUT_NAME = kunlun_sbl
ifeq ($(target), kunlun2)
hw_dep = hw2
riscv_dep = riscv2
else
ifeq ($(target), kunlun3)
hw_dep = hw3
riscv_dep = riscv3
else
hw_dep = hw
riscv_dep = riscv
endif
endif
SUB_DIRS = src src/$(hw_dep)
SUB_DIRS += $(TOPDIR)/driver $(TOPDIR)/common lzma
ifeq ($(target), kunlun2)
SUB_DIRS += $(TOPDIR)/sbl/io_lib
endif
# .h files dir
ADD_INCLUDE += $(TOPDIR)/sbl/inc $(TOPDIR)/sbl/inc/${hw_dep} $(TOPDIR)/sbl/lzma
ADD_INCLUDE += $(TOPDIR)/inc/pib $(TOPDIR)/driver/inc $(TOPDIR)/inc
ADD_INCLUDE += $(TOPDIR)/inc/io_lib $(TOPDIR)/inc/os_shim
ADD_INCLUDE += $(TOPDIR)/inc/compiler/gcc $(TOPDIR)/inc/utils
ADD_INCLUDE += $(TOPDIR)/driver/src/$(hw_dep)/inc $(TOPDIR)/inc/driver
ifeq ($(target), kunlun2)
ADD_INCLUDE += $(TOPDIR)/sbl/io_lib/inc
else
ADD_INCLUDE += $(TOPDIR)/common/io_lib/inc
endif
# predefined macro
PRE_MARCO += IOT_BUILD_TYPE=3
LD_SCRIPT = link_sbl.lds
ifeq ($(gcc),arm)
SUB_DIRS += src/cm3
ADD_LIB = cm3
ADD_LIBDIR = $(TOPDIR)/startup/cm3
else
SUB_DIRS += src/riscv
ADD_INCLUDE += $(TOPDIR)/startup/$(riscv_dep)/inc
endif
export ASSIGNED_DIR = sbl/
export COMMON_A_BUILD_TYPE=sbl
ifeq ($(target), kunlun2)
ADD_LIBDIR += $(TOPDIR)/sbl/io_lib
ADD_LIB += io_lib
endif
# lib dir
ADD_LIBDIR += $(TOPDIR)/driver $(TOPDIR)/common lzma
# lib need to ld together
ADD_LIB += lzma driver common
# reduce object code size
EXTRA_OPT_FLAG = -msave-restore
DISABLE_BACKTRACE = 1
#####################################################
ifdef TOPDIR
include $(TOPDIR)/build/makefile.cfg
else
include $(CURDIR)/build/makefile.cfg
TOPDIR = $(CURDIR)
export TOPDIR
endif
dump:
$(OBJDUMP) -D -S -l $(OUTPUT_FULL_NAME) > $(OUTPUT_FULL_NAME).dump
# display the obj files and output name
debug:
@echo TOPDIR=$(TOPDIR)
@echo OUTPUT_LIB=$(OUTPUT_FULL_NAME)
@echo DEPS=$(DEPS)
@echo OBJECTS=$(OBJECTS)
@echo SRCS=$(SRCS)
@echo OBJECTS folder=$(foreach dirname, $(SUB_DIRS), $(addprefix $(BIN_DIR)/, $(dirname)))
@echo output_name=$(OUTPUT_FULL_NAME)

85
sbl/inc/common.h Normal file
View File

@@ -0,0 +1,85 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef __COMMON_H
#define __COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#define CMD_BOOT_DELAY "Press any key to stop AutoBoot \r\n"
#define CMD_PROMPT "kunlun v1.0 > "
#define CMD_BOOT_TIME "Timeout: "
#define CMD_MAXARGS 5
#define CMD_CBSIZE 80
#define PARAM_MAXARGS 2
#define PARAM_BOOT_CNT 5
#define PARAM_NAME_LEN_MAX 11
#define PARAM_VAL_LEN_MAX 19
#define PARAM_END_CHAR 0x0A
#define PARAM_EQUAL_CHAR 0x3D
#define PARAM_MAX_LENGTH 0x20
#define SBL_DEBUG_CMD_ENABLE (0)
#define CMD_DELAY_TIME_CHAR '1'
#define CMD_DELAY_TIME_INT 1
#define CMD_DELAY_TIME_COUNT (1 * 1000000) /* 1 * gptiemr0 clk */
#define REG32(a) (*((volatile uint32_t *)(a)))
typedef struct cmd_tbl_s {
char *name; /* command name */
int minargs; /* minimum number of arguments */
int maxargs; /* maximum number of arguments */
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *desc; /* command description */
char *usage; /* usage message (short) */
} cmd_tbl_t;
typedef struct {
char name[PARAM_NAME_LEN_MAX];
char equal;
char value[PARAM_VAL_LEN_MAX];
char end;
} sbl_param_cmd_t;
/* stdin stdout */
#if SBL_DEBUG_CMD_ENABLE
int do_get(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_rm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_go_at_adr(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
#endif
int do_mem_print(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_set(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_saveenv(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_print(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
int sbl_param_load();
void sbl_main_loop(void);
void sbl_get_start_part(void);
int sbl_info_print(void);
void sbl_fw_uncp_success(void);
#ifdef __cplusplus
}
#endif
#endif /* __COMMON_H */

37
sbl/inc/hw/sbl_boot_hw.h Normal file
View File

@@ -0,0 +1,37 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef SBL_BOOT_HW_H
#define SBL_BOOT_HW_H
#ifdef __cplusplus
extern "C" {
#endif
//Flash address mapping
#define FLASH_BASE_ADDRESS 0x03000000
#define RAM_BASE_ADDRESS 0x00fc0000
#define RAM_END_ADDRESS 0x05000000
#define REG_BASE_ADDRESS 0x40000000
#define REG_END_ADDRESS 0x80000000
//LZMA decompress address
#define LZMA_BUF_ADDR 0x00ff0000
#define LZMA_BUF_SIZE (64 * 1024)
#ifdef __cplusplus
}
#endif
#endif //SBL_BOOT_HW_H

41
sbl/inc/hw2/sbl_boot_hw.h Normal file
View File

@@ -0,0 +1,41 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef SBL_BOOT_HW_H
#define SBL_BOOT_HW_H
#ifdef __cplusplus
extern "C" {
#endif
//Flash address mapping
#define FLASH_BASE_ADDRESS 0x1c000000
#define RAM_BASE_ADDRESS 0x0ffd8000
#define RAM_END_ADDRESS 0x14000000
#define REG_BASE_ADDRESS 0x40000000
#define REG_END_ADDRESS 0x80000000
//LZMA decompress buffer
#if HW_PLATFORM == HW_PLATFORM_SILICON
#define LZMA_BUF_ADDR 0x10300000
#else
#define LZMA_BUF_ADDR 0x73fc0000
#endif
#define LZMA_BUF_SIZE (64 * 1024)
#ifdef __cplusplus
}
#endif
#endif //SBL_BOOT_HW_H

39
sbl/inc/hw3/sbl_boot_hw.h Normal file
View File

@@ -0,0 +1,39 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef SBL_BOOT_HW_H
#define SBL_BOOT_HW_H
#include "chip_reg_base.h"
#include "iot_mem_org.h"
#ifdef __cplusplus
extern "C" {
#endif
/*address mapping. */
#define RAM_BASE_ADDRESS (AHB_RAM0_BASEADDR)
#define RAM_END_ADDRESS (AHB_RAM3_ENDADDR)
#define REG_BASE_ADDRESS (APB_REG_LITE_BASEADDR)
#define REG_END_ADDRESS (ICACHE2_SMC_RAM_BASEADDR - 1)
//LZMA decompress address
#define LZMA_BUF_ADDR MEM_CFG_DECOMPRESS_RAM
#define LZMA_BUF_SIZE MEM_CFG_DECOMPRESS_RAM_SIZE
#ifdef __cplusplus
}
#endif
#endif //SBL_BOOT_HW_H

111
sbl/inc/sbl_boot.h Normal file
View File

@@ -0,0 +1,111 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef SBL_BOOT_H
#define SBL_BOOT_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief sbl_boot_hw_init(): hardware init.
* @return -1: failed; 0: succeed.
*/
uint32_t sbl_boot_hw_init(void);
/**
* @brief sbl_wdg_ena(): enable watchdog.
* @return none.
*/
void sbl_wdg_ena(void);
/**
* @brief sbl_wdg_disable(): disable watchdog.
* @return none.
*/
void sbl_wdg_disable(void);
/**
* @brief sbl_scratch_reg_set(): set scratch regsiter with watchdog reset flag.
* @return none.
*/
void sbl_scratch_reg_set(void);
/**
* @brief sbl_check_reset_by_wdg(): judge reset cause is watchdog or not.
* @return 1 -> is watchdog reset, 0 -> not 1.
*/
uint32_t sbl_check_reset_by_wdg(void);
/**
* @brief sbl_timer_run: start gp-timer.
* @param ms: timeout counter, unit is ms.
* @return none.
*/
void sbl_timer_run(int ms);
/**
* @brief sbl_timer_clr: clear gp-timer interrupt flag.
* @return none.
*/
void sbl_timer_clr(void);
/**
* @brief sbl_timer_cnt_done: get gp-timer cnt_done interrupt state.
* @return none.
*/
int sbl_timer_cnt_done(void);
/**
* @brief sbl_fastboot_flag_set: set(save) fastboot flag.
* @param fboot: fastboot flag.
* @return none.
*/
void sbl_fastboot_flag_set(uint32_t fboot);
/**
* @brief sbl_fastboot_flag_get: get fastboot flag.
* @return 1 -> is fast boot mode, 0 -> not 1.
*/
uint32_t sbl_fastboot_flag_get(void);
/**
* @brief sbl_load_next_firmware(): load custom app or plc app firmware.
* @param run_addr: pointer of run address.
* @param flash_size: flash size
* @param start_part: start part.
* @psram psram_eb: next firmware run in psram or not.
* @return 0: load firmware succeed, 1: load firmware failed.
*/
uint32_t sbl_load_next_firmware(uint32_t *run_addr,
uint32_t flash_size, uint32_t start_part, uint32_t psram_eb);
/**
* @brief sbl_jump_next_firmware(): jump to custom app or plc app firmware.
* @param run_addr: next firmware run address.
* @param mode: firmware run mode.
* @param print_eb: printf function enable or not.
* @param flash_size: flash size.
* @param psram_eb: next firmware run in psram or not.
* @return 0: jump to firmware succeed, 1: jump to firmware failed.
*/
uint32_t sbl_jump_next_firmware(uint32_t run_addr,
int mode, int print_eb, int flash_size, int psram_eb);
#ifdef __cplusplus
}
#endif
#endif //SBL_BOOT_H

34
sbl/inc/sbl_printf.h Normal file
View File

@@ -0,0 +1,34 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef __SBL_PRINTF_H
#define __SBL_PRINTF_H
#include "strformat.h"
#ifdef __cplusplus
extern "C" {
#endif
int8_t getc(void);
int sbl_printf_init(void *sbl_format_str_v, void *sbl_log_ctxt);
int32_t sbl_printf(const char *fmt, ...);
#ifdef __cplusplus
}
#endif
#endif /* __SBL_PRINTF_H */

41
sbl/inc/version.h Normal file
View File

@@ -0,0 +1,41 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "iot_version.h"
/* The major version 5 bits: 0~31*/
#define SBL_FIRMWARE_VERSION_MAJOR AP_FIRMWARE_VERSION_MAJOR
/* The minor version 7 bits: 0~127*/
#define SBL_FIRMWARE_VERSION_MINOR AP_FIRMWARE_VERSION_MINOR
/* The micro version 4 bits: 0~15*/
#define SBL_FIRMWARE_VERSION_MICRO AP_FIRMWARE_VERSION_MICRO
/* The build version 16 bits: 0~65535*/
#define SBL_FIRMWARE_VERSION_BUILD AP_FIRMWARE_VERSION_BUILD
/* Numerically encoded version */
#define SBL_FIRMWARE_VERSION_HEX ((SBL_FIRMWARE_VERSION_MAJOR << 24) | \
(SBL_FIRMWARE_VERSION_MINOR << 16) | \
(SBL_FIRMWARE_VERSION_MICRO << 8) | \
(SBL_FIRMWARE_VERSION_BUILD ))
/**
* @brief sbl_get_firmware_version - get firmware version.
* @param NULL
* @return firmware version.
*/
uint32_t sbl_get_firmware_version( void );

38
sbl/io_lib/Makefile Normal file
View File

@@ -0,0 +1,38 @@
# OUTPUT type
# 1 - .out
# 2 - .a
# 3 - .so
OUTPUT_TYPE = 2
OUTPUT_NAME = io_lib
SUB_DIRS = src
ADD_INCLUDE += inc $(TOPDIR)/inc/driver
# predefined macro
PRE_MARCO +=
# lib dir
ADD_LIBDIR =
# lib need to ld together
ADD_LIB =
ifdef TOPDIR
include $(TOPDIR)/build/makefile.cfg
else
include $(CURDIR)/build/makefile.cfg
TOPDIR = $(CURDIR)
export TOPDIR
endif
# display the obj files and output name
debug:
@echo TOPDIR=$(TOPDIR)
@echo OUTPUT_LIB=$(OUTPUT_FULL_NAME)
@echo DEPS=$(DEPS)
@echo OBJECTS=$(OBJECTS)
@echo SRCS=$(SRCS)
@echo OBJECTS folder=$(foreach dirname, $(SUB_DIRS), $(addprefix $(BIN_DIR)/, $(dirname)))
@echo output_name=$(OUTPUT_FULL_NAME)

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef __STRFORMAT_H__
#define __STRFORMAT_H__
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
#define STRFORMAT_OK 0
#define STRFORMAT_FAILED 1
typedef unsigned int StrFormatResult;
/* The data argument may only be considered valid during the function call */
typedef StrFormatResult (*str_format_write)(void *user_data,
const char *data, unsigned int len);
typedef StrFormatResult (*str_format_enable)(unsigned int enable);
typedef struct _str_format_context
{
str_format_write write_str;
void *user_data;
str_format_enable enable_str;
} str_format_context;
int format_str(const str_format_context *ctxt, const char *format, ...);
int format_str_v(const str_format_context *ctxt, const char *format, va_list ap);
#ifdef __cplusplus
}
#endif
#endif /*__STRFORMAT_H__*/

View File

@@ -0,0 +1,715 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os shim includes */
#include "strformat.h"
/* SBL_PRINT_LEVEL_CONFIG: 0-Simplify 1-Complete */
#define SBL_PRINT_LEVEL_CONFIG 0
#if SBL_PRINT_LEVEL_CONFIG
#define HAVE_DOUBLE
#endif
#define HAVE_LONGLONG
#ifndef LARGEST_SIGNED
#ifdef HAVE_LONGLONG
#define LARGEST_SIGNED long
#else
#define LARGEST_UNSIGNED int
#endif
#endif
#ifndef LARGEST_UNSIGNED
#ifdef HAVE_LONGLONG
#define LARGEST_UNSIGNED unsigned long
#else
#define LARGEST_UNSIGNED unsigned int
#endif
#endif
#ifndef POINTER_INT
#define POINTER_INT unsigned long
#endif
typedef unsigned int FormatFlags;
#define MAKE_MASK(shift,size) (((1 << size) - 1) << (shift))
#define JUSTIFY_SHIFT 0
#define JUSTIFY_SIZE 1
#define JUSTIFY_RIGHT 0x0000
#define JUSTIFY_LEFT 0x0001
#define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT,JUSTIFY_SIZE)
/* How a positive number is prefixed */
#define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE)
#define POSITIVE_SIZE 2
#define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT)
#define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT)
#define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT)
#define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE)
#define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE)
#define ALTERNATE_FORM_SIZE 1
#define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT)
#define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE)
#define PAD_SIZE 1
#define PAD_SPACE (0x0000 << PAD_SHIFT)
#define PAD_ZERO (0x0001 << PAD_SHIFT)
#define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE)
#define SIZE_SIZE 3
#define SIZE_CHAR (0x0001 << SIZE_SHIFT)
#define SIZE_SHORT (0x0002 << SIZE_SHIFT)
#define SIZE_INT (0x0000 << SIZE_SHIFT)
#define SIZE_LONG (0x0003 << SIZE_SHIFT)
#define SIZE_LONGLONG (0x0004 << SIZE_SHIFT)
#define SIZE_MASK MAKE_MASK(SIZE_SHIFT,SIZE_SIZE)
#define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE)
#define CONV_SIZE 3
#define CONV_INTEGER (0x0001 << CONV_SHIFT)
#define CONV_FLOAT (0x0002 << CONV_SHIFT)
#define CONV_POINTER (0x0003 << CONV_SHIFT)
#define CONV_STRING (0x0004 << CONV_SHIFT)
#define CONV_CHAR (0x0005 << CONV_SHIFT)
#define CONV_PERCENT (0x0006 << CONV_SHIFT)
#define CONV_WRITTEN (0x0007 << CONV_SHIFT)
#define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE)
#define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE)
#define RADIX_SIZE 2
#define RADIX_DECIMAL (0x0001 << RADIX_SHIFT)
#define RADIX_OCTAL (0x0002 << RADIX_SHIFT)
#define RADIX_HEX (0x0003 << RADIX_SHIFT)
#define RADIX_MASK MAKE_MASK(RADIX_SHIFT,RADIX_SIZE)
#define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE)
#define SIGNED_SIZE 1
#define SIGNED_NO (0x0000 << SIGNED_SHIFT)
#define SIGNED_YES (0x0001 << SIGNED_SHIFT)
#define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT,SIGNED_SIZE)
#define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE)
#define CAPS_SIZE 1
#define CAPS_NO (0x0000 << CAPS_SHIFT)
#define CAPS_YES (0x0001 << CAPS_SHIFT)
#define CAPS_MASK MAKE_MASK(CAPS_SHIFT,CAPS_SIZE)
#if SBL_PRINT_LEVEL_CONFIG
#define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE)
#define FLOAT_SIZE 2
#define FLOAT_NORMAL (0x0000 << FLOAT_SHIFT)
#define FLOAT_EXPONENT (0x0001 << FLOAT_SHIFT)
#define FLOAT_DEPENDANT (0x0002 << FLOAT_SHIFT)
#define FLOAT_HEX (0x0003 << FLOAT_SHIFT)
#define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE)
#endif
static FormatFlags parse_flags(const char **posp)
{
FormatFlags flags = 0;
const char *pos = *posp;
while (1) {
switch(*pos) {
case '-':
flags |= JUSTIFY_LEFT;
break;
case '+':
flags |= POSITIVE_PLUS;
break;
case ' ':
flags |= POSITIVE_SPACE;
break;
case '#':
flags |= ALTERNATE_FORM;
break;
case '0':
flags |= PAD_ZERO;
break;
default:
*posp = pos;
return flags;
}
pos++;
}
}
static unsigned int parse_uint(const char **posp)
{
unsigned v = 0;
const char *pos = *posp;
char ch;
while((ch = *pos) >= '0' && ch <= '9') {
v = v * 10 + (ch - '0');
pos++;
}
*posp = pos;
return v;
}
#define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4 )
/* Largest number of characters needed for converting an unsigned integer.
*/
#define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3 )
static unsigned int
output_uint_decimal(char **posp, LARGEST_UNSIGNED v)
{
unsigned int len;
char *pos = *posp;
while (v > 0) {
*--pos = (v % 10) + '0';
v /= 10;
}
len = *posp - pos;
*posp = pos;
return len;
}
static unsigned int
output_uint_hex(char **posp, LARGEST_UNSIGNED v, unsigned int flags)
{
unsigned int len;
const char *hex = (flags & CAPS_YES) ?"0123456789ABCDEF":"0123456789abcdef";
char *pos = *posp;
while (v > 0) {
*--pos = hex[(v % 16)];
v /= 16;
}
len = *posp - pos;
*posp = pos;
return len;
}
#if SBL_PRINT_LEVEL_CONFIG
static unsigned int output_uint_octal(char **posp, LARGEST_UNSIGNED v)
{
unsigned int len;
char *pos = *posp;
while (v > 0) {
*--pos = (v % 8) + '0';
v /= 8;
}
len = *posp - pos;
*posp = pos;
return len;
}
#endif
static StrFormatResult fill_space(const str_format_context *ctxt, unsigned int len)
{
StrFormatResult res;
static const char buffer[17] = " ";
while(len > 16) {
res = ctxt->write_str(ctxt->user_data, buffer, 16);
if (res != STRFORMAT_OK) return res;
len -= 16;
}
if (len == 0) return STRFORMAT_OK;
return ctxt->write_str(ctxt->user_data, buffer, len);
}
static StrFormatResult fill_zero(const str_format_context *ctxt, unsigned int len)
{
StrFormatResult res;
static const char buffer[17] = "0000000000000000";
while(len > 16) {
res = ctxt->write_str(ctxt->user_data, buffer, 16);
if (res != STRFORMAT_OK) return res;
len -= 16;
}
if (len == 0) return STRFORMAT_OK;
return ctxt->write_str(ctxt->user_data, buffer, len);
}
#define CHECKCB(res) {if ((res) != STRFORMAT_OK) {va_end(ap); return -1;}}
int format_str(const str_format_context *ctxt, const char *format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = format_str_v(ctxt, format, ap);
va_end(ap);
return ret;
}
int format_str_v(const str_format_context *ctxt, const char *format, va_list ap)
{
unsigned int written = 0;
const char *pos = format;
#if SBL_PRINT_LEVEL_CONFIG
va_list head = ap;
#endif
while(*pos != '\0') {
FormatFlags flags;
unsigned int minwidth = 0;
int precision = -1; /* Negative means no precision */
char ch;
const char *start = pos;
while( (ch = *pos) != '\0' && ch != '%') pos++;
if (pos != start) {
CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start));
written += pos - start;
}
if (*pos == '\0') {
va_end(ap);
return written;
}
pos++;
if (*pos == '\0') {
va_end(ap);
return written;
}
flags = parse_flags(&pos);
/* parse width */
if (*pos >= '1' && *pos <= '9') {
minwidth = parse_uint(&pos);
} else if (*pos == '*') {
int w = va_arg(ap,int);
if (w < 0) {
flags |= JUSTIFY_LEFT;
minwidth = w;
} else {
minwidth = w;
}
pos ++;
}
/* parse precision */
if (*pos == '.') {
pos++;
if (*pos >= '0' && *pos <= '9') {
precision = parse_uint(&pos);
} else if (*pos == '*') {
pos++;
precision = va_arg(ap,int);
}
}
if (*pos == 'l') {
pos++;
if (*pos == 'l') {
flags |= SIZE_LONGLONG;
pos++;
} else {
flags |= SIZE_LONG;
}
} else if (*pos == 'h') {
pos++;
if (*pos == 'h') {
flags |= SIZE_CHAR;
pos++;
} else {
flags |= SIZE_SHORT;
}
}
/* parse conversion specifier */
switch(*pos) {
case 'd':
case 'i':
flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES;
break;
case 'u':
flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO;
break;
#if SBL_PRINT_LEVEL_CONFIG
case 'o':
flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO;
break;
#endif
case 'x':
flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO;
break;
case 'X':
flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES;
break;
#if SBL_PRINT_LEVEL_CONFIG
#ifdef HAVE_DOUBLE
case 'f':
flags |= CONV_FLOAT | FLOAT_NORMAL;
break;
case 'F':
flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES;
break;
case 'e':
flags |= CONV_FLOAT | FLOAT_EXPONENT;
break;
case 'E':
flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES;
break;
case 'g':
flags |= CONV_FLOAT | FLOAT_DEPENDANT;
break;
case 'G':
flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES;
break;
case 'a':
flags |= CONV_FLOAT | FLOAT_HEX;
break;
case 'A':
flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES;
break;
#endif
#endif
case 'c':
flags |= CONV_CHAR;
break;
case 's':
flags |= CONV_STRING;
break;
case 'p':
flags |= CONV_POINTER;
break;
case 'n':
flags |= CONV_WRITTEN;
break;
case '%':
flags |= CONV_PERCENT;
break;
case '\0':
va_end(ap);
return written;
}
pos++;
switch(flags & CONV_MASK) {
case CONV_PERCENT:
CHECKCB(ctxt->write_str(ctxt->user_data, "%", 1));
written++;
break;
case CONV_INTEGER:
{
/* unsigned integers */
char *prefix = 0; /* sign, "0x" or "0X" */
unsigned int prefix_len = 0;
char buffer[MAXCHARS];
char *conv_pos = buffer + MAXCHARS;
unsigned int conv_len = 0;
unsigned int width = 0;
unsigned int precision_fill;
unsigned int field_fill;
LARGEST_UNSIGNED uvalue = 0;
int negative = 0;
if (precision < 0) precision = 1;
else flags &= ~PAD_ZERO;
if (flags & SIGNED_YES) {
/* signed integers */
LARGEST_SIGNED value = 0;
switch(flags & SIZE_MASK) {
case SIZE_CHAR:
value = (signed char)va_arg(ap, int);
break;
case SIZE_SHORT:
value = (short)va_arg(ap, int);
break;
case SIZE_INT:
value = va_arg(ap, int);
break;
#if SBL_PRINT_LEVEL_CONFIG
#ifndef HAVE_LONGLONG
case SIZE_LONGLONG: /* Treat long long the same as long */
#endif
#endif
case SIZE_LONG:
value = va_arg(ap, long);
break;
#if SBL_PRINT_LEVEL_CONFIG
#ifdef HAVE_LONGLONG
case SIZE_LONGLONG:
value = (LARGEST_SIGNED)va_arg(ap, long long);
break;
#endif
#endif
}
if (value < 0) {
uvalue = -value;
negative = 1;
} else {
uvalue = value;
}
} else {
switch(flags & SIZE_MASK) {
case SIZE_CHAR:
uvalue = (unsigned char)va_arg(ap,unsigned int);
break;
case SIZE_SHORT:
uvalue = (unsigned short)va_arg(ap,unsigned int);
break;
case SIZE_INT:
uvalue = va_arg(ap,unsigned int);
break;
#if SBL_PRINT_LEVEL_CONFIG
#ifndef HAVE_LONGLONG
case SIZE_LONGLONG: /* Treat long long the same as long */
#endif
#endif
case SIZE_LONG:
uvalue = va_arg(ap,unsigned long);
break;
#if SBL_PRINT_LEVEL_CONFIG
#ifdef HAVE_LONGLONG
case SIZE_LONGLONG:
uvalue = (LARGEST_UNSIGNED)va_arg(ap,unsigned long long);
break;
#endif
#endif
}
}
switch(flags & (RADIX_MASK)) {
case RADIX_DECIMAL:
conv_len = output_uint_decimal(&conv_pos,uvalue);
break;
#if SBL_PRINT_LEVEL_CONFIG
case RADIX_OCTAL:
conv_len = output_uint_octal(&conv_pos,uvalue);
break;
#endif
case RADIX_HEX:
conv_len = output_uint_hex(&conv_pos,uvalue, flags);
break;
}
width += conv_len;
precision_fill = ((unsigned int)precision > conv_len) ?
precision - conv_len : 0;
#if SBL_PRINT_LEVEL_CONFIG
if ((flags & (RADIX_MASK | ALTERNATE_FORM))
== (RADIX_OCTAL | ALTERNATE_FORM)) {
if (precision_fill < 1) precision_fill = 1;
}
#endif
width += precision_fill;
if ((flags & (RADIX_MASK | ALTERNATE_FORM))
== (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) {
prefix_len = 2;
if (flags & CAPS_YES) {
prefix = "0X";
} else {
prefix = "0x";
}
}
if (flags & SIGNED_YES) {
if (negative) {
prefix = "-";
prefix_len = 1;
} else {
switch(flags & POSITIVE_MASK) {
case POSITIVE_SPACE:
prefix = " ";
prefix_len = 1;
break;
case POSITIVE_PLUS:
prefix = "+";
prefix_len = 1;
break;
}
}
}
width += prefix_len;
field_fill = (minwidth > width) ? minwidth - width : 0;
if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
if (flags & PAD_ZERO) {
precision_fill += field_fill;
field_fill = 0; /* Do not double count padding */
} else {
CHECKCB(fill_space(ctxt,field_fill));
}
}
if (prefix_len > 0)
CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len));
written += prefix_len;
CHECKCB(fill_zero(ctxt,precision_fill));
written += precision_fill;
CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
written += conv_len;
if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
CHECKCB(fill_space(ctxt,field_fill));
}
written += field_fill;
}
break;
case CONV_STRING:
{
unsigned int field_fill;
unsigned int len;
char *str = va_arg(ap,char *);
if (str) {
char *tmp_pos = str;
while(*tmp_pos != '\0') tmp_pos++;
len = tmp_pos - str;
} else {
str = "(null)";
len = 6;
}
if (precision >= 0 && (unsigned int)precision < len) len = precision;
field_fill = (minwidth > len) ? minwidth - len : 0;
if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
CHECKCB(fill_space(ctxt,field_fill));
}
CHECKCB(ctxt->write_str(ctxt->user_data, str,len));
written += len;
if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
CHECKCB(fill_space(ctxt,field_fill));
}
written += field_fill;
}
break;
case CONV_POINTER:
{
LARGEST_UNSIGNED uvalue =
(LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap,void *);
char buffer[MAXCHARS_HEX + 3];
char *conv_pos = buffer + MAXCHARS_HEX+3;
unsigned int conv_len;
unsigned int field_fill;
conv_len = output_uint_hex(&conv_pos,uvalue,flags);
if (conv_len == 0) {
*--conv_pos = '0';
conv_len++;
}
*--conv_pos = 'x';
*--conv_pos = '0';
*--conv_pos = '#';
conv_len += 3;
field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0;
if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
CHECKCB(fill_space(ctxt,field_fill));
}
CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
written += conv_len;
if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
CHECKCB(fill_space(ctxt,field_fill));
}
written += field_fill;
}
break;
case CONV_CHAR:
{
char tmp_ch = (char)va_arg(ap, int);
unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0;
if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
CHECKCB(fill_space(ctxt,field_fill));
written += field_fill;
}
CHECKCB(ctxt->write_str(ctxt->user_data, &tmp_ch, 1));
written++;
if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
CHECKCB(fill_space(ctxt,field_fill));
}
written+= field_fill;
}
break;
case CONV_WRITTEN:
{
int *p = va_arg(ap,int*);
*p = written;
}
break;
#if SBL_PRINT_LEVEL_CONFIG
case CONV_FLOAT:
{
char buffer[MAXCHARS];
char *conv_pos = buffer + MAXCHARS;
unsigned int conv_len = 0;
double fval ;
if ((ap - head + sizeof(int)) & sizeof(int))
ap += sizeof(int);
ap += sizeof(double);
fval = *(double *)(ap - sizeof(double));
int Inte = (int)fval;
int Deci = (int)(100000*(fval - Inte));
int Remain = 0;
int Zeronum = 4;
if(Deci % 10 >= 5) {
Deci = Deci / 10 + 1;
} else {
Deci = Deci / 10;
}
if(Inte < 0 ) {
Inte = Inte *(-1);
Deci = Deci *(-1);
CHECKCB(ctxt->write_str(ctxt->user_data, "-", 1));
written += 1;
}
if(Inte == 0 ){
if(Deci < 0){
Inte = Inte *(-1);
Deci = Deci *(-1);
CHECKCB(ctxt->write_str(ctxt->user_data, "-", 1));
written += 1;
}
CHECKCB(ctxt->write_str(ctxt->user_data, "0", 1));
written += 1;
} else {
conv_pos = buffer + MAXCHARS;;
conv_len = output_uint_decimal(&conv_pos, Inte);
CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
written += conv_len;
}
CHECKCB(ctxt->write_str(ctxt->user_data, ".", 1));
written += 1;
Remain = Deci;
while((Remain > 0)&&(Zeronum > 0)) {
Zeronum--;
Remain = Remain / 10;
}
while(Zeronum > 0) {
CHECKCB(ctxt->write_str(ctxt->user_data, "0", 1));
written += 1;
Zeronum--;
}
if(Deci == 0){
CHECKCB(ctxt->write_str(ctxt->user_data, "0", 1));
written += 1;
} else {
conv_pos = buffer + MAXCHARS;;
conv_len = output_uint_decimal(&conv_pos, Deci);
CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
written += conv_len;
}
}
break;
#endif
}
}
return written;
}

362
sbl/lzma/7zAlloc.c Normal file
View File

@@ -0,0 +1,362 @@
/*
* Buffer-based memory allocator
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#include "7zAlloc.h"
#include <string.h>
#define MAGIC1 0xFF00AA55
#define MAGIC2 0xEE119966
#define MAX_BT 20
typedef struct _memory_header memory_header;
struct _memory_header
{
size_t magic1;
size_t size;
size_t alloc;
memory_header *prev;
memory_header *next;
memory_header *prev_free;
memory_header *next_free;
size_t magic2;
};
typedef struct
{
unsigned char *buf;
size_t len;
memory_header *first;
memory_header *first_free;
int verify;
}
buffer_alloc_ctx;
static buffer_alloc_ctx heap;
static int verify_header( memory_header *hdr )
{
if( hdr->magic1 != MAGIC1 )
{
return( 1 );
}
if( hdr->magic2 != MAGIC2 )
{
return( 1 );
}
if( hdr->alloc > 1 )
{
return( 1 );
}
if( hdr->prev != NULL && hdr->prev == hdr->next )
{
return( 1 );
}
if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free )
{
return( 1 );
}
return( 0 );
}
static int verify_chain()
{
memory_header *prv = heap.first, *cur = heap.first->next;
if( verify_header( heap.first ) != 0 )
{
return( 1 );
}
if( heap.first->prev != NULL )
{
return( 1 );
}
while( cur != NULL )
{
if( verify_header( cur ) != 0 )
{
return( 1 );
}
if( cur->prev != prv )
{
return( 1 );
}
prv = cur;
cur = cur->next;
}
return( 0 );
}
void *buffer_alloc_calloc( size_t n, size_t size )
{
memory_header *new, *cur = heap.first_free;
unsigned char *p;
void *ret;
size_t original_len, len;
if( heap.buf == NULL || heap.first == NULL )
return( NULL );
original_len = len = n * size;
if( n != 0 && len / n != size )
return( NULL );
if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{
len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
// Find block that fits
//
while( cur != NULL )
{
if( cur->size >= len )
break;
cur = cur->next_free;
}
if( cur == NULL )
return NULL;
if( cur->alloc != 0 )
{
return NULL;
}
// Found location, split block if > memory_header + 4 room left
//
if( cur->size - len < sizeof(memory_header) +
MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{
cur->alloc = 1;
// Remove from free_list
//
if( cur->prev_free != NULL )
cur->prev_free->next_free = cur->next_free;
else
heap.first_free = cur->next_free;
if( cur->next_free != NULL )
cur->next_free->prev_free = cur->prev_free;
cur->prev_free = NULL;
cur->next_free = NULL;
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
return NULL;
ret = (unsigned char *) cur + sizeof( memory_header );
memset( ret, 0, original_len );
return( ret );
}
p = ( (unsigned char *) cur ) + sizeof(memory_header) + len;
new = (memory_header *) p;
new->size = cur->size - len - sizeof(memory_header);
new->alloc = 0;
new->prev = cur;
new->next = cur->next;
new->magic1 = MAGIC1;
new->magic2 = MAGIC2;
if( new->next != NULL )
new->next->prev = new;
// Replace cur with new in free_list
//
new->prev_free = cur->prev_free;
new->next_free = cur->next_free;
if( new->prev_free != NULL )
new->prev_free->next_free = new;
else
heap.first_free = new;
if( new->next_free != NULL )
new->next_free->prev_free = new;
cur->alloc = 1;
cur->size = len;
cur->next = new;
cur->prev_free = NULL;
cur->next_free = NULL;
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 )
return NULL;
ret = (unsigned char *) cur + sizeof( memory_header );
memset( ret, 0, original_len );
return( ret );
}
void *buffer_alloc_malloc(size_t size)
{
return buffer_alloc_calloc(1, size);
}
void buffer_alloc_free( void *ptr )
{
memory_header *hdr, *old = NULL;
unsigned char *p = (unsigned char *) ptr;
if( ptr == NULL || heap.buf == NULL || heap.first == NULL )
return;
if( p < heap.buf || p > heap.buf + heap.len )
{
return;
}
p -= sizeof(memory_header);
hdr = (memory_header *) p;
if( verify_header( hdr ) != 0 )
return;
if( hdr->alloc != 1 )
{
return;
}
hdr->alloc = 0;
// Regroup with block before
//
if( hdr->prev != NULL && hdr->prev->alloc == 0 )
{
hdr->prev->size += sizeof(memory_header) + hdr->size;
hdr->prev->next = hdr->next;
old = hdr;
hdr = hdr->prev;
if( hdr->next != NULL )
hdr->next->prev = hdr;
memset( old, 0, sizeof(memory_header) );
}
// Regroup with block after
//
if( hdr->next != NULL && hdr->next->alloc == 0 )
{
hdr->size += sizeof(memory_header) + hdr->next->size;
old = hdr->next;
hdr->next = hdr->next->next;
if( hdr->prev_free != NULL || hdr->next_free != NULL )
{
if( hdr->prev_free != NULL )
hdr->prev_free->next_free = hdr->next_free;
else
heap.first_free = hdr->next_free;
if( hdr->next_free != NULL )
hdr->next_free->prev_free = hdr->prev_free;
}
hdr->prev_free = old->prev_free;
hdr->next_free = old->next_free;
if( hdr->prev_free != NULL )
hdr->prev_free->next_free = hdr;
else
heap.first_free = hdr;
if( hdr->next_free != NULL )
hdr->next_free->prev_free = hdr;
if( hdr->next != NULL )
hdr->next->prev = hdr;
memset( old, 0, sizeof(memory_header) );
}
// Prepend to free_list if we have not merged
// (Does not have to stay in same order as prev / next list)
//
if( old == NULL )
{
hdr->next_free = heap.first_free;
if( heap.first_free != NULL )
heap.first_free->prev_free = hdr;
heap.first_free = hdr;
}
if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 )
return;
}
void mbedtls_memory_buffer_set_verify( int verify )
{
heap.verify = verify;
}
int mbedtls_memory_buffer_alloc_verify()
{
return verify_chain();
}
void memory_buffer_alloc_init( unsigned char *buf, size_t len )
{
memset( &heap, 0, sizeof(buffer_alloc_ctx) );
memset( buf, 0, len );
if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE )
{
/* Adjust len first since buf is used in the computation */
len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
heap.buf = buf;
heap.len = len;
heap.first = (memory_header *) buf;
heap.first->size = len - sizeof(memory_header);
heap.first->magic1 = MAGIC1;
heap.first->magic2 = MAGIC2;
heap.first_free = heap.first;
}
void memory_buffer_alloc_free()
{
memset( &heap, 0x0, sizeof(buffer_alloc_ctx) );
}

78
sbl/lzma/7zAlloc.h Normal file
View File

@@ -0,0 +1,78 @@
/**
* \file memory_buffer_alloc.h
*
* \brief Buffer-based memory allocator
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MEMORY_BUFFER_ALLOC_H
#define MEMORY_BUFFER_ALLOC_H
#include <stddef.h>
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
/* \} name SECTION: Module settings */
#define MBEDTLS_MEMORY_VERIFY_NONE 0
#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0)
#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1)
#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE)
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize use of stack-based memory allocator.
* The stack-based allocator does memory management inside the
* presented buffer and does not call calloc() and free().
* It sets the global mbedtls_calloc() and mbedtls_free() pointers
* to its own functions.
* (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if
* MBEDTLS_THREADING_C is defined)
*
* \note This code is not optimized and provides a straight-forward
* implementation of a stack-based memory allocator.
*
* \param buf buffer to use as heap
* \param len size of the buffer
*/
void memory_buffer_alloc_init( unsigned char *buf, size_t len );
/**
* \brief Free the mutex for thread-safety and clear remaining memory
*/
void memory_buffer_alloc_free( void );
void *buffer_alloc_malloc(size_t size);
void buffer_alloc_free( void *ptr );
#ifdef __cplusplus
}
#endif
#endif /* memory_buffer_alloc.h */

243
sbl/lzma/7zTypes.h Executable file
View File

@@ -0,0 +1,243 @@
/* Types.h -- Basic types
2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
#include <stddef.h>
#ifdef _WIN32
#include <windows.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define SZ_OK 0
#define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17
typedef int SRes;
#ifdef _WIN32
typedef DWORD WRes;
#else
typedef int WRes;
#endif
#ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif
typedef unsigned char Byte;
typedef short Int16;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef long Int32;
typedef unsigned long UInt32;
#else
typedef int Int32;
typedef unsigned int UInt32;
#endif
#ifdef _SZ_NO_INT_64
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
NOTES: Some code will work incorrectly in that case! */
typedef long Int64;
typedef unsigned long UInt64;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n
#else
typedef long long int Int64;
typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL
#endif
#endif
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
typedef size_t SizeT;
#endif
typedef int Bool;
#define True 1
#define False 0
#ifdef _MSC_VER
#if _MSC_VER >= 1300
#define MY_NO_INLINE __declspec(noinline)
#else
#define MY_NO_INLINE
#endif
#define MY_CDECL __cdecl
#define MY_FAST_CALL __fastcall
#else
#define MY_CDECL
#define MY_FAST_CALL
#endif
/* The following interfaces use first parameter as pointer to structure */
typedef struct
{
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn;
typedef struct
{
void (*Write)(void *p, Byte b);
} IByteOut;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
} ISeqInStream;
/* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
typedef struct
{
size_t (*Write)(void *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
} ISeqOutStream;
typedef enum
{
SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2
} ESzSeek;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ISeekInStream;
typedef struct
{
SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */
SRes (*Skip)(void *p, size_t offset);
/* offset must be <= output(*size) of Look */
SRes (*Read)(void *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ILookInStream;
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
#define LookToRead_BUF_SIZE (1 << 14)
typedef struct
{
ILookInStream s;
ISeekInStream *realStream;
size_t pos;
size_t size;
Byte buf[LookToRead_BUF_SIZE];
} CLookToRead;
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
void LookToRead_Init(CLookToRead *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p);
typedef struct
{
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress;
typedef struct
{
void *(*Alloc)(void *p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */
} ISzAlloc;
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
#ifdef _WIN32
#define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\"
#else
#define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/"
#endif
#ifdef __cplusplus
}
#endif
#endif

1024
sbl/lzma/LzmaDec.c Executable file

File diff suppressed because it is too large Load Diff

232
sbl/lzma/LzmaDec.h Executable file
View File

@@ -0,0 +1,232 @@
/* LzmaDec.h -- LZMA Decoder
2009-02-07 : Igor Pavlov : Public domain */
#ifndef __LZMA_DEC_H
#define __LZMA_DEC_H
#include "7zTypes.h"
#ifdef __cplusplus
extern "C" {
#endif
/* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */
#ifdef _LZMA_PROB32
#define CLzmaProb UInt32
#else
#define CLzmaProb UInt16
#endif
/* ---------- LZMA Properties ---------- */
#define LZMA_PROPS_SIZE 5
typedef struct _CLzmaProps
{
unsigned lc, lp, pb;
UInt32 dicSize;
} CLzmaProps;
/* LzmaProps_Decode - decodes properties
Returns:
SZ_OK
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
/* ---------- LZMA Decoder state ---------- */
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
#define LZMA_REQUIRED_INPUT_MAX 20
typedef struct
{
CLzmaProps prop;
CLzmaProb *probs;
Byte *dic;
const Byte *buf;
UInt32 range, code;
SizeT dicPos;
SizeT dicBufSize;
UInt32 processedPos;
UInt32 checkDicSize;
unsigned state;
UInt32 reps[4];
unsigned remainLen;
int needFlush;
int needInitState;
UInt32 numProbs;
unsigned tempBufSize;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
} CLzmaDec;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
void LzmaDec_Init(CLzmaDec *p);
/* There are two types of LZMA streams:
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
typedef enum
{
LZMA_FINISH_ANY, /* finish at any point */
LZMA_FINISH_END /* block must be finished at the end */
} ELzmaFinishMode;
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
You must use LZMA_FINISH_END, when you know that current output buffer
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
and output value of destLen will be less than output buffer size limit.
You can check status result also.
You can use multiple checks to test data integrity after full decompression:
1) Check Result and "status" variable.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
You must use correct finish mode in that case. */
typedef enum
{
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
} ELzmaStatus;
/* ELzmaStatus is used only as output value for function call */
/* ---------- Interfaces ---------- */
/* There are 3 levels of interfaces:
1) Dictionary Interface
2) Buffer Interface
3) One Call Interface
You can select any of these interfaces, but don't mix functions from different
groups for same object. */
/* There are two variants to allocate state for Dictionary Interface:
1) LzmaDec_Allocate / LzmaDec_Free
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
You can use variant 2, if you set dictionary buffer manually.
For Buffer Interface you must always use variant 1.
LzmaDec_Allocate* can return:
SZ_OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
/* ---------- Dictionary Interface ---------- */
/* You can use it, if you want to eliminate the overhead for data copying from
dictionary to some other external buffer.
You must work with CLzmaDec variables directly in this interface.
STEPS:
LzmaDec_Constr()
LzmaDec_Allocate()
for (each new stream)
{
LzmaDec_Init()
while (it needs more decompression)
{
LzmaDec_DecodeToDic()
use data from CLzmaDec::dic and update CLzmaDec::dicPos
}
}
LzmaDec_Free()
*/
/* LzmaDec_DecodeToDic
The decoding to internal dictionary buffer (CLzmaDec::dic).
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
finishMode:
It has meaning only if the decoding reaches output limit (dicLimit).
LZMA_FINISH_ANY - Decode just dicLimit bytes.
LZMA_FINISH_END - Stream must be finished after dicLimit.
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
*/
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- Buffer Interface ---------- */
/* It's zlib-like interface.
See LzmaDec_DecodeToDic description for information about STEPS and return results,
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
to work with CLzmaDec variables manually.
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
*/
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */
/* LzmaDecode
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc);
#ifdef __cplusplus
}
#endif
#endif

318
sbl/lzma/LzmaTools.c Executable file
View File

@@ -0,0 +1,318 @@
/*
* Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.65
*
* Copyright (C) 2007-2009 Industrie Dial Face S.p.A.
* Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com)
*
* Copyright (C) 1999-2005 Igor Pavlov
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*
* LZMA_Alone stream format:
*
* uchar Properties[5]
* uint64 Uncompressed size
* uchar data[*]
*
*/
#define LZMA_PROPERTIES_OFFSET 0
#define LZMA_SIZE_OFFSET LZMA_PROPS_SIZE
#define LZMA_DATA_OFFSET LZMA_SIZE_OFFSET+sizeof(uint64_t)
#include "os_types.h"
#include "LzmaTools.h"
#include "LzmaDec.h"
#include <string.h>
#include "7zAlloc.h"
#include "iot_config.h"
#include "flash.h"
#include "ahb.h"
#include "iot_mtd.h"
#include "sbl_boot_hw.h"
#define min(a, b) (((a) < (b)) ? (a) : (b))
/* LZMA decoder need 1M size buffer */
#define BUF_SZ LZMA_BUF_SIZE
#define BUF_ADDR LZMA_BUF_ADDR
static unsigned char *heap_buf = (unsigned char*)BUF_ADDR;
static void *SzAlloc(void *p, size_t size) { return buffer_alloc_malloc(size); }
static void SzFree(void *p, void *address) { buffer_alloc_free(address); }
struct dataStream
{
const unsigned char * inData;
size_t inLen;
unsigned char * outData;
size_t outLen;
};
struct dataStream ds;
static uint32_t start_addr = 0, end_addr = 0;
static void flash_erase_blocks(uint32_t addr, uint32_t size)
{
flash_write_param_t param = {
.sw_mode = MOD_SW_MODE_DIS,
.erase_mode = MODE_ERASE_BLOCK64
};
start_addr = (addr + BLOCK_ERASE_64K_MASK) & (~BLOCK_ERASE_64K_MASK);
end_addr = (addr + size) & (~BLOCK_ERASE_64K_MASK);
/* disable cache space */
ahb_cache_space_dis_for_flash_write();
for (uint32_t erase_addr = start_addr; erase_addr < end_addr;
erase_addr += BLOCK_ERASE_64K_SIZE) {
flash_erase(erase_addr, &param);
}
/* enable cache space again */
ahb_cache_space_ena_for_flash_write();
}
static int
inputCallback(void *ctx, void *buf, size_t * size)
{
size_t rd = 0;
rd = (ds.inLen < *size) ? ds.inLen : *size;
if (rd > 0) {
memcpy(buf, (void *) ds.inData, rd);
ds.inData += rd;
ds.inLen -= rd;
}
*size = rd;
return 0;
}
static size_t
outputCallback(void *ctx, const void *buf, size_t size)
{
#if RUN_IN_PSRAM
if (size > 0) {
memcpy((void *) (ds.outData + ds.outLen), buf, size);
ds.outLen += size;
}
#else
flash_write_param_t param = {0};
/*write to the FW addr in flash*/
param.read_mode = MOD_SFC_READ_QUAD_IO_FAST;
param.write_mode = MOD_SFC_PROG_STAND;
param.is_erase = 1;
param.sw_mode = MOD_SW_MODE_DIS;
/* disable cache space */
ahb_cache_space_dis_for_flash_write();
if ((start_addr <= (uint32_t)(ds.outData + ds.outLen)) &&
((uint32_t)(ds.outData + ds.outLen + size) <= end_addr)) {
param.is_erase = 0;
}
flash_write(buf, (uint32_t)(ds.outData + ds.outLen), (uint32_t)size, &param);
/* enable cache space again */
ahb_cache_space_ena_for_flash_write();
ds.outLen += (uint32_t)size;
#endif
return size;
}
#define IN_BUF_SIZE (1 << 14)
#define OUT_BUF_SIZE (1 << 14)
Byte inBuf[IN_BUF_SIZE];
Byte outBuf[OUT_BUF_SIZE];
static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream,
UInt64 unpackSize)
{
int thereIsSize = (unpackSize != (UInt64)(Int64)-1);
size_t inPos = 0, inSize = 0, outPos = 0;
LzmaDec_Init(state);
for (;;)
{
if (inPos == inSize)
{
inSize = IN_BUF_SIZE;
RINOK(inStream->Read(inStream, inBuf, &inSize));
inPos = 0;
}
{
SRes res;
SizeT inProcessed = inSize - inPos;
SizeT outProcessed = OUT_BUF_SIZE - outPos;
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
ELzmaStatus status;
if (thereIsSize && outProcessed > unpackSize)
{
outProcessed = (SizeT)unpackSize;
finishMode = LZMA_FINISH_END;
}
res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed,
inBuf + inPos, &inProcessed, finishMode, &status);
inPos += inProcessed;
outPos += outProcessed;
unpackSize -= outProcessed;
if (outStream)
if (outStream->Write(outStream, outBuf, outPos) != outPos)
return SZ_ERROR_WRITE;
outPos = 0;
if (res != SZ_OK || (thereIsSize && unpackSize == 0))
return res;
if (inProcessed == 0 && outProcessed == 0)
{
if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
return SZ_ERROR_DATA;
return res;
}
}
}
}
int BufferDecode(uint8_t *dst, uint32_t *dstLen, uint8_t *src, uint32_t srcLen )
{
ISeqOutStream outStream;
ISeqInStream inStream;
ISzAlloc g_Alloc;
UInt64 unpackSize;
int i;
size_t header_size;
SRes res = 0;
CLzmaDec state;
outStream.Write= outputCallback;
inStream.Read = inputCallback;
ds.inData = src;
ds.inLen = srcLen;
ds.outData = dst;
ds.outLen = 0;
/* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
unsigned char header[LZMA_PROPS_SIZE + 8];
/* Read and parse header */
header_size = sizeof(header);
inStream.Read(&inStream, header, &header_size);
unpackSize = 0;
for (i = 0; i < 8; i++)
unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
flash_erase_blocks((uint32_t)dst, (uint32_t)unpackSize);
memory_buffer_alloc_init(heap_buf, BUF_SZ);
g_Alloc.Alloc = SzAlloc;
g_Alloc.Free = SzFree;
LzmaDec_Construct(&state);
LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
res = Decode2(&state, &outStream, &inStream, unpackSize);
LzmaDec_Free(&state, &g_Alloc);
*dstLen = ds.outLen;
return res;
}
int lzmaBuffToBuffDecompress (unsigned char *outStream, uint32_t *uncompressedSize,
unsigned char *inStream, uint32_t length)
{
#if RUN_IN_PSRAM
int res = SZ_ERROR_DATA;
int i;
ISzAlloc g_Alloc;
SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */
SizeT outProcessed;
SizeT outSize;
SizeT outSizeHigh;
ELzmaStatus state;
SizeT compressedSize = (SizeT)(length - LZMA_PROPS_SIZE);
memset(&state, 0, sizeof(state));
outSize = 0;
outSizeHigh = 0;
/* Read the uncompressed size */
for (i = 0; i < 8; i++) {
unsigned char b = inStream[LZMA_SIZE_OFFSET + i];
if (i < 4) {
outSize += (UInt32)(b) << (i * 8);
} else {
outSizeHigh += (UInt32)(b) << ((i - 4) * 8);
}
}
outSizeFull = (SizeT)outSize;
if (sizeof(SizeT) >= 8) {
/*
* SizeT is a 64 bit uint => We can manage files larger than 4GB!
*
*/
outSizeFull |= (((SizeT)outSizeHigh << 16) << 16);
} else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) {
/*
* SizeT is a 32 bit uint => We cannot manage files larger than
* 4GB! Assume however that all 0xf values is "unknown size" and
* not actually a file of 2^64 bits.
*
*/
if (outSizeHigh != (SizeT)-1 || outSize != (SizeT)-1) {
return SZ_ERROR_DATA;
}
}
memory_buffer_alloc_init(heap_buf, BUF_SZ);
g_Alloc.Alloc = SzAlloc;
g_Alloc.Free = SzFree;
/* Short-circuit early if we know the buffer can't hold the results. */
if (outSizeFull != (SizeT)-1 && *uncompressedSize < outSizeFull)
return SZ_ERROR_OUTPUT_EOF;
/* Decompress */
outProcessed = min(outSizeFull, *uncompressedSize);
res = LzmaDecode(
outStream, &outProcessed,
inStream + LZMA_DATA_OFFSET, &compressedSize,
inStream, LZMA_PROPS_SIZE, LZMA_FINISH_END, &state, &g_Alloc);
*uncompressedSize = outProcessed;
if (res != SZ_OK) {
return res;
}
return res;
#else
return BufferDecode(outStream, uncompressedSize, inStream, length);
#endif
}

28
sbl/lzma/LzmaTools.h Executable file
View File

@@ -0,0 +1,28 @@
/*
* Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.65
*
* Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
* Luigi 'Comio' Mantellini (luigi.mantellini@idf-hit.com)
*
* Copyright (C) 1999-2005 Igor Pavlov
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __LZMA_TOOL_H__
#define __LZMA_TOOL_H__
#include "7zTypes.h"
#ifdef __cplusplus
extern "C" {
#endif
extern int lzmaBuffToBuffDecompress (unsigned char *outStream, uint32_t *uncompressedSize,
unsigned char *inStream, uint32_t length);
#ifdef __cplusplus
}
#endif
#endif

38
sbl/lzma/Makefile Normal file
View File

@@ -0,0 +1,38 @@
# OUTPUT type
# 1 - .out
# 2 - .a
# 3 - .so
OUTPUT_TYPE = 2
OUTPUT_NAME = lzma
SUB_DIRS =
# .h files dir
ADD_INCLUDE += .
# predefined macro
PRE_MARCO +=
#####################################################
ifdef TOPDIR
include $(TOPDIR)/build/makefile.cfg
else
include $(CURDIR)/build/makefile.cfg
TOPDIR = $(CURDIR)
export TOPDIR
endif
dump:
$(OBJDUMP) -D -S -l $(OUTPUT_FULL_NAME) > $(OUTPUT_FULL_NAME).dump
# display the obj files and output name
debug:
@echo TOPDIR=$(TOPDIR)
@echo OUTPUT_LIB=$(OUTPUT_FULL_NAME)
@echo DEPS=$(DEPS)
@echo OBJECTS=$(OBJECTS)
@echo SRCS=$(SRCS)
@echo OBJECTS folder=$(foreach dirname, $(SUB_DIRS), $(addprefix $(BIN_DIR)/, $(dirname)))
@echo output_name=$(OUTPUT_FULL_NAME)

19
sbl/lzma/decomp.c Normal file
View File

@@ -0,0 +1,19 @@
#include "os_types.h"
#include <string.h>
#include "LzmaTools.h"
int fw_image_decompress(uint8_t *src, uint8_t *dst, uint32_t len)
{
int ret;
uint32_t src_len = len, dst_len = ~0UL;
ret = lzmaBuffToBuffDecompress(dst, &dst_len, src, src_len);
if (ret != SZ_OK)
return 1;
return 0;
}

29
sbl/lzma/decomp.h Normal file
View File

@@ -0,0 +1,29 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#ifndef DECOMPRESS_H_
#define DECOMPRESS_H_
#ifdef __cplusplus
extern "C" {
#endif
int fw_image_decompress(uint8_t *src, uint8_t *dst, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif //DECOMPRESS_H_

81
sbl/src/boot.c Normal file
View File

@@ -0,0 +1,81 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "os_types.h"
#include "flash.h"
#include "iot_config.h"
#include "iot_flash_layout.h"
#include "common.h"
#include "sbl_boot.h"
#include "sbl_printf.h"
#define SBL_FLASH_SIZE_MAX FLASH_4M
uint32_t g_flash_size = FLASH_1M; /*1M flash by default*/
void hang()
{
sbl_printf("#### start_boot failed. ####\r\n");
for(;;);
}
uint32_t display_banner(void)
{
sbl_printf("\r\n\r\n/*******************************************/\r\n");
sbl_info_print();
sbl_printf("/*******************************************/\r\n");
return 0;
}
void start_boot(void)
{
if (sbl_boot_hw_init() != 0) {
hang();
}
display_banner();
g_flash_size = flash_get_dev_size();
sbl_printf("flash_size is : %dM\r\n", 1 << (g_flash_size - FLASH_1M));
/* now, we only support 4m flash at most */
if (g_flash_size > SBL_FLASH_SIZE_MAX) {
g_flash_size = SBL_FLASH_SIZE_MAX;
}
iot_layout_init_index(FLASH_LAYOUT_INDEX, g_flash_size, RUN_IN_PSRAM);
sbl_param_load();
/* main loop */
for(;;) {
sbl_main_loop();
}
}
int sbl_main(int fboot_flag)
{
sbl_fastboot_flag_set((uint32_t)fboot_flag);
start_boot();
return 0;
// This value is meaningless, but
// since this code should never be reached,
// make it non-zero.
return (1234567);
}

237
sbl/src/cm3/sbl.S Normal file
View File

@@ -0,0 +1,237 @@
.syntax unified
.arch armv7-m
/* define stack size */
.section .stack
.align 3
.equ Stack_Size, 0x400
.equ BootRAM, 0xF1E0F85F
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
/* define heap size */
.section .heap
.align 3
.equ Heap_Size, 0x200
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.space Heap_Size
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .isr_vector
.align 2
.globl __isr_vector
__isr_vector:
.word __StackTop
.word Reset_Handler
.word NMI_Handler
.word hal_default_exception_vsr
.word hal_default_exception_vsr
.word hal_default_exception_vsr
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* external interrupts */
.word WWDG_IRQHandler
.word PVD_IRQHandler
.word TAMPER_IRQHandler
.word RTC_IRQHandler
.word FLASH_IRQHandler
.word RCC_IRQHandler
.word EXTI0_IRQHandler
.word EXTI1_IRQHandler
.word intc_handler
.word EXTI3_IRQHandler
.word EXTI4_IRQHandler
.word DMA1_Channel1_IRQHandler
.word DMA1_Channel2_IRQHandler
.word DMA1_Channel3_IRQHandler
.word DMA1_Channel4_IRQHandler
.word DMA1_Channel5_IRQHandler
.word DMA1_Channel6_IRQHandler
.word DMA1_Channel7_IRQHandler
.word ADC1_2_IRQHandler
.word USB_HP_CAN1_TX_IRQHandler
.word USB_LP_CAN1_RX0_IRQHandler
.word CAN1_RX1_IRQHandler
.word CAN1_SCE_IRQHandler
.word EXTI9_5_IRQHandler
.word TIM1_BRK_IRQHandler
.word TIM1_UP_IRQHandler
.word TIM1_TRG_COM_IRQHandler
.word TIM1_CC_IRQHandler
.word TIM2_IRQHandler
.word TIM3_IRQHandler
.word TIM4_IRQHandler
.word I2C1_EV_IRQHandler
.word I2C1_ER_IRQHandler
.word I2C2_EV_IRQHandler
.word I2C2_ER_IRQHandler
.word SPI1_IRQHandler
.word SPI2_IRQHandler
.word USART1_IRQHandler
.word USART2_IRQHandler
.word USART3_IRQHandler
.word EXTI15_10_IRQHandler
.word RTCAlarm_IRQHandler
.word USBWakeUp_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
/* vector size */
.size __isr_vector, . - __isr_vector
.text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =__StackTop
ldr r0, =__stext
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
.flash_to_ram_loop:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .flash_to_ram_loop
/* clear bss */
ldr r0, =0
ldr r1, =__bss_start__
ldr r2, =__bss_end__
clear_bss_loop:
cmp r1, r2
beq clear_bss_loop_end
str r0, [r1], #4
b clear_bss_loop
clear_bss_loop_end:
/* jump to main */
ldr r0, =SystemInit
blx r0
ldr r0, =main
bx r0
exit_loop:
nop
b exit_loop
.global hal_default_exception_vsr
.thumb
.thumb_func
.type hal_default_exception_vsr, %function
hal_default_exception_vsr:
mrs r0,psp // Get process stack
sub r1,r0,#(4*12) // Make space for saved state
msr psp,r1 // Ensure PSP is up to date
mov r1,#1 // R1 = exception state type
mrs r2,ipsr // R2 = vector number
mrs r3,basepri // R3 = basepri
stmfd r0!,{r1-r11,lr} // Push type, vector, basepri, r4-11
mov r4,r0 // R4 = saved state pointer
bl hal_deliver_exception
mov r0,r4 // R0 = state saved across call
ldmfd r0!,{r1-r11,lr} // Pop type, vec, basepri, registers and LR
msr psp,r0 // Restore PSP
msr basepri,r3 // Restore basepri
bx lr // Return
.pool
.size Reset_Handler, . - Reset_Handler
.macro def_default_handler handler_name
.align 1
.thumb_func
.weak \handler_name
.type \handler_name, %function
\handler_name :
b .
.size \handler_name, . - \handler_name
.endm
def_default_handler NMI_Handler
# def_default_handler HardFault_Handler
# def_default_handler MemManage_Handler
# def_default_handler BusFault_Handler
def_default_handler UsageFault_Handler
def_default_handler SVC_Handler
def_default_handler DebugMon_Handler
def_default_handler PendSV_Handler
def_default_handler SysTick_Handler
def_default_handler WWDG_IRQHandler
def_default_handler PVD_IRQHandler
def_default_handler TAMPER_IRQHandler
def_default_handler RTC_IRQHandler
def_default_handler FLASH_IRQHandler
def_default_handler RCC_IRQHandler
def_default_handler EXTI0_IRQHandler
def_default_handler EXTI1_IRQHandler
def_default_handler intc_handler
def_default_handler EXTI3_IRQHandler
def_default_handler EXTI4_IRQHandler
def_default_handler DMA1_Channel1_IRQHandler
def_default_handler DMA1_Channel2_IRQHandler
def_default_handler DMA1_Channel3_IRQHandler
def_default_handler DMA1_Channel4_IRQHandler
def_default_handler DMA1_Channel5_IRQHandler
def_default_handler DMA1_Channel6_IRQHandler
def_default_handler DMA1_Channel7_IRQHandler
def_default_handler ADC1_2_IRQHandler
def_default_handler USB_HP_CAN1_TX_IRQHandler
def_default_handler USB_LP_CAN1_RX0_IRQHandler
def_default_handler CAN1_RX1_IRQHandler
def_default_handler CAN1_SCE_IRQHandler
def_default_handler EXTI9_5_IRQHandler
def_default_handler TIM1_BRK_IRQHandler
def_default_handler TIM1_UP_IRQHandler
def_default_handler TIM1_TRG_COM_IRQHandler
def_default_handler TIM1_CC_IRQHandler
def_default_handler TIM2_IRQHandler
def_default_handler TIM3_IRQHandler
def_default_handler TIM4_IRQHandler
def_default_handler I2C1_EV_IRQHandler
def_default_handler I2C1_ER_IRQHandler
def_default_handler I2C2_EV_IRQHandler
def_default_handler I2C2_ER_IRQHandler
def_default_handler SPI1_IRQHandler
def_default_handler SPI2_IRQHandler
def_default_handler USART1_IRQHandler
def_default_handler USART2_IRQHandler
def_default_handler USART3_IRQHandler
def_default_handler EXTI15_10_IRQHandler
def_default_handler RTCAlarm_IRQHandler
def_default_handler USBWakeUp_IRQHandler
.end

1232
sbl/src/common.c Normal file

File diff suppressed because it is too large Load Diff

470
sbl/src/hw/sbl_boot.c Normal file
View File

@@ -0,0 +1,470 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "os_types.h"
#include "ahb.h"
#include "apb.h"
#include "flash.h"
#include "common.h"
#include "decomp.h"
#include "watchdog.h"
#include "iot_mtd.h"
#include "iot_img_hdr.h"
#include "iot_system.h"
#include "iot_flash_layout.h"
#include "iot_crc_api.h"
#include "iot_errno_api.h"
#include "sbl_boot.h"
#include "sbl_boot_hw.h"
#include "sbl_printf.h"
/* Timer reg */
#define GP_TMR_BASE_ADDR 0x44003000
#define GTMR0_CTRL_CFG_ADDR (GP_TMR_BASE_ADDR + 0x04)
#define GTMR0_CFG_ADDR (GP_TMR_BASE_ADDR + 0x08)
#define GTMR0_INT_STS_ADDR (GP_TMR_BASE_ADDR + 0x0c)
#define GTMR0_CLR_ADDR (GP_TMR_BASE_ADDR + 0x14)
#define GTMR0_CNT_DONE (0x2)
//FW address mapping
#define FW_FLASH_ADDR 0x03020000
#define FW_RAM_ADDR 0x04000000
extern uint32_t g_is_first_run;
extern char sbl_fw_uncp[PARAM_VAL_LEN_MAX];
extern void os_mem_cpy(void *dst, const void *src, uint32_t len);
extern void os_mem_move(void *dst, const void *src, uint32_t len);
extern int32_t os_mem_cmp(const void *dst, const void *src, uint32_t len);
extern void os_mem_set(void *ptr, uint8_t value, uint32_t len);
extern str_format_context rom_log_ctxt;
extern int rom_format_str_v(const str_format_context *ctxt, const char *format,
va_list ap);
/**
* @brief sbl_boot_hw_init(): hardware init.
* @return -1: failed; 0: succeed.
*/
uint32_t sbl_boot_hw_init(void)
{
flash_init(0);
sbl_printf_init(rom_format_str_v, &rom_log_ctxt);
return 0;
}
/**
* @brief sbl_wdg_ena(): enable watchdog.
* @return none.
*/
void sbl_wdg_ena(void)
{
uint32_t cpu = 0;
apb_enable(APB_WDG0);
wdg_set_cmp(cpu, SET_WDG_INTC_CMP);
wdg_set_timeout_cmp(cpu, SET_WDG_TIMEOUT_CMP);
wdg_set_cpurst_cmp(cpu, SET_WDG_CPURST_CMP);
wdg_set_fullrst_cmp(cpu, SET_WDG_FULLRST_CMP);
wdg_cnt_enable(cpu);
wdg_enable(cpu);
}
/**
* @brief sbl_wdg_disable(): disable watchdog.
* @return none.
*/
void sbl_wdg_disable(void)
{
uint32_t cpu = 0;
wdg_cnt_disable(cpu);
wdg_disable(cpu);
}
/**
* @brief sbl_scratch_reg_set(): set scratch regsiter with watchdog reset flag.
* @return none.
*/
void sbl_scratch_reg_set(void)
{
ahb_scratch_r0_set(WDT_RESET_FLAG);
}
/**
* @brief sbl_check_reset_by_wdg(): judge reset cause is watchdog or not.
* @return 1 -> is watchdog reset, 0 -> not 1.
*/
uint32_t sbl_check_reset_by_wdg(void)
{
if (ahb_scratch_r0_get() == WDT_RESET_FLAG) {
return 1;
}
return 0;
}
/**
* @brief sbl_timer_run: start gp-timer.
* @param ms: timeout counter, unit is ms.
* @return none.
*/
void sbl_timer_run(int ms)
{
REG32(GTMR0_CFG_ADDR) = ms;
REG32(GTMR0_CTRL_CFG_ADDR) = (1<<4) | (1<<1); /*(1MHz enable)*/
}
/**
* @brief sbl_timer_clr: clear gp-timer interrupt flag.
* @return none.
*/
void sbl_timer_clr(void)
{
REG32(GTMR0_CLR_ADDR) = (1<<0) | (1<<1); /* intc and cnt clr */
}
/**
* @brief sbl_timer_cnt_done: get gp-timer cnt_done interrupt state.
* @return none.
*/
int sbl_timer_cnt_done(void)
{
return (REG32(GTMR0_INT_STS_ADDR) & GTMR0_CNT_DONE) ? 1 : 0;
}
/**
* @brief sbl_fastboot_flag_set: set(save) fastboot flag.
* @param fboot: fastboot flag.
* @return none.
*/
void sbl_fastboot_flag_set(uint32_t fboot)
{
/* kl1 not support rom passing fastboot flag */
(void)fboot;
}
/**
* @brief sbl_fastboot_flag_get: get fastboot flag.
* @return 1 -> is fast boot mode, 0 -> not 1.
*/
uint32_t sbl_fastboot_flag_get(void)
{
return 0;
}
/**
* @brief image_check() Check for valid fw at the specified address.
* @param addr: addr to check.
* @param hdr: pointer to store header information.
* @param crc_flag: CRC check mark or not.
* @return -1: no valid header; 0: valid header.
*/
static int image_check(uint32_t addr, imgHdr *hdr, uint8_t crc_flag)
{
char block[HEADER_TOLTAL_SIZE];
uint8_t *src = (uint8_t *)addr;
uint32_t len_total = 0;
uint8_t reason = 0;
/* clear i/dcache */
ahb_cache_clear();
os_mem_cpy(block, src, sizeof(imgHdr));
img_header_construct(hdr, block);
if (iot_imghdr_get_guard(hdr) != IMAGE_GUARD) {
reason = 1;
goto err;
}
if (crc_flag) {
uint32_t img_crc = iot_imghdr_get_imgCRC(hdr);
len_total = iot_imghdr_get_imgSize(hdr);
len_total = IMAGE_LEN_FOR_CRC(len_total);
uint32_t crc = iot_getcrc32((uint8_t *)addr + HEADER_TOLTAL_SIZE, len_total);
if (crc != img_crc) {
reason = 2;
goto err;
}
}
return 0;
err:
sbl_printf("image_check error, addr:0x%x, reason:%d\r\n", addr, reason);
return -1;
}
/**
* @brief image_copy(): copy firmware to specified address.
* @param src & dst: source and destination addresses(partition start location).
* @param hdr: pointer to store header information.
* @param header_move: if you copy the header,
you need to erase the header information of the source address.
* @return -1: no valid header; 0: valid header.
*/
static int image_copy(uint8_t *src, uint8_t *dst, imgHdr *hdr, uint8_t header_move)
{
int rc = 0;
flash_write_param_t param = {0};
uint32_t len_image = 0;
uint32_t len_copy = 0;
uint8_t *addr_crc = NULL;
uint8_t *src_copy = src;
uint8_t *dst_copy = dst;
uint8_t reason = 0;
len_image = iot_imghdr_get_imgSize(hdr);
len_image = IMAGE_LEN_FOR_CRC(len_image);
if (header_move) {
len_copy = len_image + HEADER_TOLTAL_SIZE;
addr_crc = dst_copy + HEADER_TOLTAL_SIZE;
} else {
src_copy += HEADER_TOLTAL_SIZE;
dst_copy += HEADER_TOLTAL_SIZE;
len_copy = len_image;
addr_crc = dst_copy;
}
/*write to the FW addr in flash*/
param.read_mode = MOD_SFC_READ_QUAD_IO_FAST;
param.write_mode = MOD_SFC_PROG_QUAD;
param.is_erase = 1;
param.sw_mode = MOD_SW_MODE_DIS;
param.erase_mode = MODE_ERASE_SECTOR;
rc = flash_write(src_copy, (uint32_t)dst_copy, len_copy, &param);
if(rc != 0 ) {
reason = 1;
goto err;
} else {
sbl_printf("fw image copied into flash \r\n");
if (iot_imghdr_get_imgCRC(hdr) != 0 ) {
uint32_t img_crc = iot_imghdr_get_imgCRC(hdr);
uint32_t crc = iot_getcrc32(addr_crc, len_image);
if ( crc != img_crc) {
reason = 2;
goto err;
}
}
}
if (header_move) {
if (flash_erase((uint32_t)src, &param) != ERR_OK) {
reason = 3;
goto err;
}
}
return 0;
err:
sbl_printf("image_copy error, reason:%d\r\n", reason);
return -1;
}
/**
* @brief get_fw_addr_info(): get firmware storage and running address.
* @param fw_addr: pointer to save storage address.
* @param run_addr: pointer to save run address.
* @param flash_size: flash size, see flash_size_t.
* @param start_part: pointer of sbl_start_part.
* @return -1: no valid header; 0: valid header.
*/
static int get_fw_addr_info(uint32_t *fw_addr, uint32_t *run_addr,
uint8_t flash_size, uint32_t start_part)
{
int ret = 0;
imgHdr hdr = {0};
/* get run address, fixed address */
#if RUN_IN_PSRAM
*run_addr = FW_RAM_ADDR;
#else
*run_addr = FW_FLASH_ADDR + HEADER_TOLTAL_SIZE;
#endif
/* get firmware address */
if (start_part == 0) { //fw1
iot_layout_get_part_offset(PART_NUM_FW1, fw_addr);
} else { //fw2
iot_layout_get_part_offset(PART_NUM_FW2, fw_addr);
}
*fw_addr += FLASH_BASE_ADDRESS;
/* check image integrity */
if (g_is_first_run) {
if (image_check(*fw_addr, &hdr, 1) < 0) {
ret = -1;
goto out;
}
}
out:
sbl_printf("get fw addr:0x%x, run addr:0x%x\r\n", *fw_addr, *run_addr);
return ret;
}
/**
* @brief fw_image_decompress_to_psram(): decompress image to psram.
* @param fw_addr: firmware address.
* @param run_addr: run address.
* @return -1: failed; 0: succeed.
*/
int fw_image_decompress_to_psram(uint32_t fw_addr, uint32_t run_addr)
{
uint8_t *src = NULL;
uint8_t *dst = NULL;
int rc = 0;
imgHdr hdr = {0};
/* the compressed or valid data does not contain a header */
src = (uint8_t *)fw_addr + HEADER_TOLTAL_SIZE;
dst = (uint8_t *)run_addr;
if (image_check(fw_addr, &hdr, 0) < 0) {
return -1;
}
rc = fw_image_decompress(src, dst, iot_imghdr_get_imgSize(&hdr));
if(rc != 0 ){
os_mem_cpy(dst, src, iot_imghdr_get_imgSize(&hdr));
//ahb_dmc_cache_flush((uint32_t)dst, hdr._imgSize);
}
sbl_printf("decompressed fw image into RAM \r\n");
return 0;
}
/**
* @brief fw_image_decompress_to_flash(): decompress image to flash.
* @param fw_addr: firmware address.
* @param run_addr: run address.
* @return -1: failed; 0: succeed.
*/
int fw_image_decompress_to_flash(uint32_t fw_addr, uint32_t run_addr)
{
uint8_t *src = NULL;
uint8_t *dst = NULL;
int rc = 0;
imgHdr hdr = {0};
src = (uint8_t *)fw_addr;
dst = (uint8_t *)run_addr;
if (image_check(fw_addr, &hdr, 0) < 0) {
return -1;
}
/* compatable with 1M image upgrade */
if (iot_imghdr_get_imgType(&hdr) == imgFRW) {
if (image_copy(src, dst - HEADER_TOLTAL_SIZE, &hdr, 0) < 0) {
return -1;
}
} else {
rc = fw_image_decompress(src+sizeof(imgHdr), dst, iot_imghdr_get_imgSize(&hdr));
if(rc != 0 ) {
sbl_printf("fw image decompressed ERROR! \r\n");
return -1;
} else {
uint32_t fw_crc = 0, crc = 0;
sbl_printf("fw image decompressed into flash \r\n");
fw_crc = iot_imghdr_get_fwCRC(&hdr);
crc = iot_getcrc32(dst, iot_imghdr_get_fwSize(&hdr));
if (crc != fw_crc) {
sbl_printf("decompress fw crc error\r\n");
return -1;
}
}
}
return 0;
}
/**
* @brief sbl_load_next_firmware(): load custom app or plc app firmware.
* @param run_addr: pointer of run address.
* @param flash_size: flash size
* @param start_part: start part.
* @psram psram_eb: next firmware run in psram or not.
* @return 0: load firmware succeed, 1: load firmware failed.
*/
uint32_t sbl_load_next_firmware(uint32_t *run_addr,
uint32_t flash_size, uint32_t start_part, uint32_t psram_eb)
{
uint32_t fw_addr = 0;
(void)psram_eb;
if (get_fw_addr_info(&fw_addr, run_addr, (uint8_t)flash_size, start_part) < 0) {
sbl_printf("No valid firmware found......\r\n");
while(1);
}
#if RUN_IN_PSRAM
if(fw_image_decompress_to_psram(fw_addr, *run_addr) < 0) {
/* copy image failed */
sbl_printf("......\r\n");
while(1);
}
#else
if (flash_size == FLASH_1M) {
/* 1m flash firmware is uncompressed and there is no run partition */
if (start_part) {
uint32_t offset1, offset2, size;
sbl_printf("re-mapping flash space\r\n");
iot_layout_get_part_offset(PART_NUM_FW1, &offset1);
iot_layout_get_part_offset(PART_NUM_FW2, &offset2);
iot_layout_get_part_size(PART_NUM_FW1, &size);
if (flash_addr_mapping(offset1, offset2, size) != 0) {
sbl_printf("re-mapping error\r\n");
while(1);
}
}
} else if ((os_mem_cmp(sbl_fw_uncp, "0", 1) == 0)) {
/* 2m and 4m flash firmware needs to be decompressed */
if(fw_image_decompress_to_flash(fw_addr, *run_addr) < 0) {
/* decompress image failed */
sbl_printf("......\r\n");
while(1);
} else{
/*decompress success*/
sbl_fw_uncp_success();
}
}
#endif
return 0;
}
/**
* @brief sbl_jump_next_firmware(): jump to custom app or plc app firmware.
* @param run_addr: next firmware run address.
* @param mode: firmware run mode.
* @param print_eb: printf function enable or not.
* @param flash_size: flash size.
* @param psram_eb: next firmware run in psram or not.
* @return 0: jump to firmware succeed, 1: jump to firmware failed.
*/
uint32_t sbl_jump_next_firmware(uint32_t run_addr,
int mode, int print_eb, int flash_size, int psram_eb)
{
typedef void(*pgm_start_t)(int, int, int, int);
pgm_start_t pgm_start = (pgm_start_t)run_addr;
sbl_printf("\r\njump@0x%x\r\n", (int)pgm_start);
pgm_start(mode, print_eb, flash_size, psram_eb);
return 0;
}

469
sbl/src/hw2/sbl_boot.c Normal file
View File

@@ -0,0 +1,469 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "os_types.h"
#include "ahb.h"
#include "apb.h"
#include "flash.h"
#include "common.h"
#include "decomp.h"
#include "watchdog.h"
#include "iot_mtd.h"
#include "iot_img_hdr.h"
#include "iot_system.h"
#include "iot_flash_layout.h"
#include "iot_crc_api.h"
#include "iot_errno_api.h"
#include "sbl_boot.h"
#include "sbl_boot_hw.h"
#include "sbl_printf.h"
/* Timer reg */
#define GP_TMR_BASE_ADDR 0x44003000
#define GTMR0_CTRL_CFG_ADDR (GP_TMR_BASE_ADDR + 0x04)
#define GTMR0_CFG_ADDR (GP_TMR_BASE_ADDR + 0x08)
#define GTMR0_INT_STS_ADDR (GP_TMR_BASE_ADDR + 0x0c)
#define GTMR0_CLR_ADDR (GP_TMR_BASE_ADDR + 0x14)
#define GTMR0_CNT_DONE (0x2)
//FW address mapping
#define FW_FLASH_ADDR 0x1c020000
#define FW_RAM_ADDR 0x18000000
extern uint32_t g_is_first_run;
extern char sbl_fw_uncp[PARAM_VAL_LEN_MAX];
extern void os_mem_cpy(void *dst, const void *src, uint32_t len);
extern void os_mem_move(void *dst, const void *src, uint32_t len);
extern int32_t os_mem_cmp(const void *dst, const void *src, uint32_t len);
extern void os_mem_set(void *ptr, uint8_t value, uint32_t len);
extern str_format_context log_ctxt;
extern int format_str_v(const str_format_context *ctxt, const char *format,
va_list ap);
/**
* @brief sbl_boot_hw_init(): hardware init.
* @return -1: failed; 0: succeed.
*/
uint32_t sbl_boot_hw_init(void)
{
flash_init(0);
sbl_printf_init(format_str_v, &log_ctxt);
return 0;
}
/**
* @brief sbl_wdg_ena(): enable watchdog.
* @return none.
*/
void sbl_wdg_ena(void)
{
uint32_t cpu = 0;
apb_enable(APB_WDG0);
wdg_set_cmp(cpu, SET_WDG_INTC_CMP);
wdg_set_timeout_cmp(cpu, SET_WDG_TIMEOUT_CMP);
wdg_set_cpurst_cmp(cpu, SET_WDG_CPURST_CMP);
wdg_set_fullrst_cmp(cpu, SET_WDG_FULLRST_CMP);
wdg_cnt_enable(cpu);
wdg_enable(cpu);
}
/**
* @brief sbl_wdg_disable(): disable watchdog.
* @return none.
*/
void sbl_wdg_disable(void)
{
uint32_t cpu = 0;
wdg_cnt_disable(cpu);
wdg_disable(cpu);
}
/**
* @brief sbl_scratch_reg_set(): set scratch regsiter with watchdog reset flag.
* @return none.
*/
void sbl_scratch_reg_set(void)
{
ahb_scratch_r0_set(WDT_RESET_FLAG);
}
/**
* @brief sbl_check_reset_by_wdg(): judge reset cause is watchdog or not.
* @return 1 -> is watchdog reset, 0 -> not 1.
*/
uint32_t sbl_check_reset_by_wdg(void)
{
if (ahb_scratch_r0_get() == WDT_RESET_FLAG) {
return 1;
}
return 0;
}
/**
* @brief sbl_timer_run: start gp-timer.
* @param ms: timeout counter, unit is ms.
* @return none.
*/
void sbl_timer_run(int ms)
{
REG32(GTMR0_CFG_ADDR) = ms;
REG32(GTMR0_CTRL_CFG_ADDR) = (1<<4) | (1<<1); /*(1MHz enable)*/
}
/**
* @brief sbl_timer_clr: clear gp-timer interrupt flag.
* @return none.
*/
void sbl_timer_clr(void)
{
REG32(GTMR0_CLR_ADDR) = (1<<0) | (1<<1); /* intc and cnt clr */
}
/**
* @brief sbl_timer_cnt_done: get gp-timer cnt_done interrupt state.
* @return none.
*/
int sbl_timer_cnt_done(void)
{
return (REG32(GTMR0_INT_STS_ADDR) & GTMR0_CNT_DONE) ? 1 : 0;
}
/**
* @brief sbl_fastboot_flag_set: set(save) fastboot flag.
* @param fboot: fastboot flag.
* @return none.
*/
void sbl_fastboot_flag_set(uint32_t fboot)
{
/* kl2 not support rom passing fastboot flag */
(void)fboot;
}
/**
* @brief sbl_fastboot_flag_get: get fastboot flag.
* @return 1 -> is fast boot mode, 0 -> not 1.
*/
uint32_t sbl_fastboot_flag_get(void)
{
return 0;
}
/**
* @brief image_check() Check for valid fw at the specified address.
* @param addr: addr to check.
* @param hdr: pointer to store header information.
* @param crc_flag: CRC check mark or not.
* @return -1: no valid header; 0: valid header.
*/
static int image_check(uint32_t addr, imgHdr *hdr, uint8_t crc_flag)
{
char block[HEADER_TOLTAL_SIZE];
uint8_t *src = (uint8_t *)addr;
uint32_t len_total = 0;
uint8_t reason = 0;
/* clear i/dcache */
ahb_cache_clear();
os_mem_cpy(block, src, sizeof(imgHdr));
img_header_construct(hdr, block);
if (iot_imghdr_get_guard(hdr) != IMAGE_GUARD) {
reason = 1;
goto err;
}
if (crc_flag) {
uint32_t img_crc = iot_imghdr_get_imgCRC(hdr);
len_total = iot_imghdr_get_imgSize(hdr);
len_total = IMAGE_LEN_FOR_CRC(len_total);
uint32_t crc = iot_getcrc32((uint8_t *)addr + HEADER_TOLTAL_SIZE, len_total);
if (crc != img_crc) {
reason = 2;
goto err;
}
}
return 0;
err:
sbl_printf("image_check error, addr:0x%x, reason:%d\r\n", addr, reason);
return -1;
}
/**
* @brief image_copy(): copy firmware to specified address.
* @param src & dst: source and destination addresses(partition start location).
* @param hdr: pointer to store header information.
* @param header_move: if you copy the header,
you need to erase the header information of the source address.
* @return -1: no valid header; 0: valid header.
*/
static int image_copy(uint8_t *src, uint8_t *dst, imgHdr *hdr, uint8_t header_move)
{
int rc = 0;
flash_write_param_t param = {0};
uint32_t len_image = 0;
uint32_t len_copy = 0;
uint8_t *addr_crc = NULL;
uint8_t *src_copy = src;
uint8_t *dst_copy = dst;
uint8_t reason = 0;
len_image = iot_imghdr_get_imgSize(hdr);
len_image = IMAGE_LEN_FOR_CRC(len_image);
if (header_move) {
len_copy = len_image + HEADER_TOLTAL_SIZE;
addr_crc = dst_copy + HEADER_TOLTAL_SIZE;
} else {
src_copy += HEADER_TOLTAL_SIZE;
dst_copy += HEADER_TOLTAL_SIZE;
len_copy = len_image;
addr_crc = dst_copy;
}
/*write to the FW addr in flash*/
param.read_mode = MOD_SFC_READ_QUAD_IO_FAST;
param.write_mode = MOD_SFC_PROG_QUAD;
param.is_erase = 1;
param.sw_mode = MOD_SW_MODE_DIS;
param.erase_mode = MODE_ERASE_SECTOR;
rc = flash_write(src_copy, (uint32_t)dst_copy, len_copy, &param);
if(rc != 0 ) {
reason = 1;
goto err;
} else {
sbl_printf("fw image copied into flash \r\n");
if (iot_imghdr_get_imgCRC(hdr) != 0 ) {
uint32_t img_crc = iot_imghdr_get_imgCRC(hdr);
uint32_t crc = iot_getcrc32(addr_crc, len_image);
if ( crc != img_crc) {
reason = 2;
goto err;
}
}
}
if (header_move) {
if (flash_erase((uint32_t)src, &param) != ERR_OK) {
reason = 3;
goto err;
}
}
return 0;
err:
sbl_printf("image_copy error, reason:%d\r\n", reason);
return -1;
}
/**
* @brief get_fw_addr_info(): get firmware storage and running address.
* @param fw_addr: pointer to save storage address.
* @param run_addr: pointer to save run address.
* @param flash_size: flash size, see flash_size_t.
* @param start_part: pointer of sbl_start_part.
* @return -1: no valid header; 0: valid header.
*/
static int get_fw_addr_info(uint32_t *fw_addr, uint32_t *run_addr,
uint8_t flash_size, uint32_t start_part)
{
int ret = 0;
imgHdr hdr = {0};
#if RUN_IN_PSRAM
*run_addr = FW_RAM_ADDR;
#else
*run_addr = FW_FLASH_ADDR + HEADER_TOLTAL_SIZE;
#endif
/* get firmware address */
if (start_part == 0) { //fw1
iot_layout_get_part_offset(PART_NUM_FW1, fw_addr);
} else { //fw2
iot_layout_get_part_offset(PART_NUM_FW2, fw_addr);
}
*fw_addr += FLASH_BASE_ADDRESS;
/* check image integrity */
if (g_is_first_run) {
if (image_check(*fw_addr, &hdr, 1) < 0) {
ret = -1;
goto out;
}
}
out:
sbl_printf("get fw addr:0x%x, run addr:0x%x\r\n", *fw_addr, *run_addr);
return ret;
}
/**
* @brief fw_image_decompress_to_psram(): decompress image to psram.
* @param fw_addr: firmware address.
* @param run_addr: run address.
* @return -1: failed; 0: succeed.
*/
int fw_image_decompress_to_psram(uint32_t fw_addr, uint32_t run_addr)
{
uint8_t *src = NULL;
uint8_t *dst = NULL;
int rc = 0;
imgHdr hdr = {0};
/* the compressed or valid data does not contain a header */
src = (uint8_t *)fw_addr + HEADER_TOLTAL_SIZE;
dst = (uint8_t *)run_addr;
if (image_check(fw_addr, &hdr, 0) < 0) {
return -1;
}
rc = fw_image_decompress(src, dst, iot_imghdr_get_imgSize(&hdr));
if(rc != 0 ){
os_mem_cpy(dst, src, iot_imghdr_get_imgSize(&hdr));
//ahb_dmc_cache_flush((uint32_t)dst, hdr._imgSize);
}
sbl_printf("decompressed fw image into RAM \r\n");
return 0;
}
/**
* @brief fw_image_decompress_to_flash(): decompress image to flash.
* @param fw_addr: firmware address.
* @param run_addr: run address.
* @return -1: failed; 0: succeed.
*/
int fw_image_decompress_to_flash(uint32_t fw_addr, uint32_t run_addr)
{
uint8_t *src = NULL;
uint8_t *dst = NULL;
int rc = 0;
imgHdr hdr = {0};
src = (uint8_t *)fw_addr;
dst = (uint8_t *)run_addr;
if (image_check(fw_addr, &hdr, 0) < 0) {
return -1;
}
/*compatable with 1M image upgrade*/
if (iot_imghdr_get_imgType(&hdr) == imgFRW) {
if (image_copy(src, dst - HEADER_TOLTAL_SIZE, &hdr, 0) < 0) {
return -1;
}
} else {
rc = fw_image_decompress(src+sizeof(imgHdr), dst, iot_imghdr_get_imgSize(&hdr));
if(rc != 0 ) {
sbl_printf("fw image decompressed ERROR! \r\n");
return -1;
} else {
uint32_t fw_crc = 0, crc = 0;
sbl_printf("fw image decompressed into flash \r\n");
fw_crc = iot_imghdr_get_fwCRC(&hdr);
crc = iot_getcrc32(dst, iot_imghdr_get_fwSize(&hdr));
if (crc != fw_crc) {
sbl_printf("decompress fw crc error\r\n");
return -1;
}
}
}
return 0;
}
/**
* @brief sbl_load_next_firmware(): load custom app or plc app firmware.
* @param run_addr: pointer of run address.
* @param flash_size: flash size
* @param start_part: start part.
* @psram psram_eb: next firmware run in psram or not.
* @return 0: load firmware succeed, 1: load firmware failed.
*/
uint32_t sbl_load_next_firmware(uint32_t *run_addr,
uint32_t flash_size, uint32_t start_part, uint32_t psram_eb)
{
uint32_t fw_addr = 0;
(void)psram_eb;
if (get_fw_addr_info(&fw_addr, run_addr, (uint8_t)flash_size, start_part) < 0) {
sbl_printf("No valid firmware found......\r\n");
while(1);
}
#if RUN_IN_PSRAM
if(fw_image_decompress_to_psram(fw_addr, *run_addr) < 0) {
/* copy image failed */
sbl_printf("......\r\n");
while(1);
}
#else
if (flash_size == FLASH_1M) {
/* 1m flash firmware is uncompressed and there is no run partition */
if (start_part) {
uint32_t offset1, offset2, size;
sbl_printf("re-mapping flash space\r\n");
iot_layout_get_part_offset(PART_NUM_FW1, &offset1);
iot_layout_get_part_offset(PART_NUM_FW2, &offset2);
iot_layout_get_part_size(PART_NUM_FW1, &size);
if (flash_addr_mapping(offset1, offset2, size) != 0) {
sbl_printf("re-mapping error\r\n");
while(1);
}
}
} else if ((os_mem_cmp(sbl_fw_uncp, "0", 1) == 0)) {
/* 2m and 4m flash firmware needs to be decompressed */
if(fw_image_decompress_to_flash(fw_addr, *run_addr) < 0) {
/* decompress image failed */
sbl_printf("......\r\n");
while(1);
} else{
/*decompress success*/
sbl_fw_uncp_success();
}
}
#endif
return 0;
}
/**
* @brief sbl_jump_next_firmware(): jump to custom app or plc app firmware.
* @param run_addr: next firmware run address.
* @param mode: firmware run mode.
* @param print_eb: printf function enable or not.
* @param flash_size: flash size.
* @param psram_eb: next firmware run in psram or not.
* @return 0: jump to firmware succeed, 1: jump to firmware failed.
*/
uint32_t sbl_jump_next_firmware(uint32_t run_addr,
int mode, int print_eb, int flash_size, int psram_eb)
{
typedef void(*pgm_start_t)(int, int, int, int);
pgm_start_t pgm_start = (pgm_start_t)run_addr;
sbl_printf("\r\njump@0x%x\r\n", (int)pgm_start);
pgm_start(mode, print_eb, flash_size, psram_eb);
return 0;
}

530
sbl/src/hw3/sbl_boot.c Executable file
View File

@@ -0,0 +1,530 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "os_types.h"
#include "ahb.h"
#include "apb.h"
#include "flash.h"
#include "clk_hw.h"
#include "clk.h"
#include "smc.h"
#include "sram.h"
#include "watchdog.h"
#include "system_hw.h"
#include "efuse.h"
#include "ana_hw.h"
#include "iot_img_hdr.h"
#include "iot_mem_org.h"
#include "iot_flash_layout.h"
#include "iot_crc_api.h"
#include "iot_errno_api.h"
#include "decomp.h"
#include "common.h"
#include "sbl_boot.h"
#include "sbl_boot_hw.h"
#include "sbl_printf.h"
/* Timer reg */
#define GP_TMR_BASE_ADDR GTMR0_BASEADDR
#define GTMR0_CTRL_CFG_ADDR (GP_TMR_BASE_ADDR + 0x04)
#define GTMR0_CFG_ADDR (GP_TMR_BASE_ADDR + 0x08)
#define GTMR0_INT_STS_ADDR (GP_TMR_BASE_ADDR + 0x0c)
#define GTMR0_CLR_ADDR (GP_TMR_BASE_ADDR + 0x14)
#define GTMR0_CNT_DONE (0x2)
/* kl3 support rom passing fastboot flag */
uint32_t g_sbl_fastboot_flag = 0;
extern uint32_t g_is_first_run;
extern char sbl_fw_uncp[PARAM_VAL_LEN_MAX];
extern str_format_context rom_log_ctxt;
extern int rom_format_str_v(const str_format_context *ctxt, const char *format,
va_list ap);
/**
* @brief sbl_calib_code_load(): load calib code from efuse, and set to register.
* calib code loading sequence: vbg -> iccal -> dcdc -> mdll ldo -> ldo.
* this function needs to be called before clk set function.
* @return none.
*/
static void sbl_calib_code_load(void)
{
uint8_t flag, vbg, iccal, dcdc, ldo_1p8, mdll_ldo;
flag = efuse_get_ft_pass_flag();
vbg = efuse_get_d_bg_vbg_cntl();
iccal = efuse_get_d_bg_iccal();
dcdc = efuse_get_dcdc_trim();
ldo_1p8 = efuse_get_flash_ldo_out_trim();
mdll_ldo = efuse_get_d_mdll_ldo_vref_trim();
if (flag == EFUSE_FT_PASS_FLAG_EVB_ANA_ALL || flag == EFUSE_FT_PASS_FLAG_ATE) {
ana_vbg_trim_code_set(vbg);
ana_iccal_trim_code_set(iccal);
}
if (dcdc != 0 || flag != EFUSE_FT_PASS_FLAG_INVALID) {
/* dcdc trim code needs to be set in the xtal clock. */
ahb_clk_clock_set(0, 0, 0);
ana_dcdc_vref_code_set(dcdc);
}
if (flag == EFUSE_FT_PASS_FLAG_EVB_ANA_ALL || flag == EFUSE_FT_PASS_FLAG_ATE) {
/* mdll ldo needs to be set before pll calibration */
ana_mdll_ldo_trim_code_set(mdll_ldo);
}
if (ldo_1p8 != 0 || flag != EFUSE_FT_PASS_FLAG_INVALID) {
ana_ldo_trim_code_set(ldo_1p8);
}
for (volatile uint32_t i = 0; i < 100; i++);
}
/**
* @brief sbl_boot_hw_init(): hardware init.
* @return -1: failed; 0: succeed.
*/
uint32_t sbl_boot_hw_init(void)
{
efuse_init();
sbl_calib_code_load();
ahb_emc_disable();
ahb_emc_enable();
//change CPU core to 150M.
clk_system_clock_tree_config(CLK_FRQ_GP_IDX_FAST);
//flash init
flash_init(1);
sbl_printf_init(rom_format_str_v, &rom_log_ctxt);
/* psram init */
#if RUN_IN_PSRAM
sram_qspi_init();
sram_qspi_enter();
hal_smc_qspi_quad_cfg(0);
#endif
/* cache init */
/* core0 - cus core use icache0 and dcache0 */
cache_disable(AHB_CACHE_I0);
cache_enable(AHB_CACHE_I0);
cache_fill_valid_space(AHB_CACHE_I0);
#if RUN_IN_PSRAM
cache_disable(AHB_CACHE_D0);
cache_enable(AHB_CACHE_D0);
cache_fill_valid_space(AHB_CACHE_D0);
#else
cache_enable(AHB_CACHE_D0);
cache_set_buffer_mode(AHB_CACHE_D0, 1);
#endif
/* core1 - plc core use icache1 and dcache1 */
cache_disable(AHB_CACHE_I1);
cache_enable(AHB_CACHE_I1);
cache_fill_valid_space(AHB_CACHE_I1);
#if RUN_IN_PSRAM
cache_disable(AHB_CACHE_D1);
cache_enable(AHB_CACHE_D1);
cache_fill_valid_space(AHB_CACHE_D1);
#else
cache_enable(AHB_CACHE_D1);
cache_set_buffer_mode(AHB_CACHE_D1, 1);
#endif
/* core2 - no cache used. */
cache_enable(AHB_CACHE_I2);
cache_set_buffer_mode(AHB_CACHE_I2, 1);
return 0;
}
/**
* @brief sbl_wdg_ena(): enable watchdog.
* @return none.
*/
void sbl_wdg_ena(void)
{
uint32_t cpu = 0;
apb_enable(APB_WDG0);
wdg_set_cmp(cpu, SET_WDG_INTC_CMP);
wdg_set_timeout_cmp(cpu, SET_WDG_TIMEOUT_CMP);
#if (HW_PLATFORM == HW_PLATFORM_FPGA)
// fpga sfc clock freq is low, it takes a long time to decompress
wdg_set_cpurst_cmp(cpu, SET_WDG_CPURST_CMP * 2);
wdg_set_fullrst_cmp(cpu, SET_WDG_FULLRST_CMP * 2);
#else
wdg_set_cpurst_cmp(cpu, SET_WDG_CPURST_CMP);
wdg_set_fullrst_cmp(cpu, SET_WDG_FULLRST_CMP);
#endif
wdg_cnt_enable(cpu);
wdg_enable(cpu);
}
/**
* @brief sbl_wdg_disable(): disable watchdog.
* @return none.
*/
void sbl_wdg_disable(void)
{
uint32_t cpu;
cpu = 0;
wdg_cnt_disable(cpu);
wdg_disable(cpu);
cpu = 1;
wdg_cnt_disable(cpu);
wdg_disable(cpu);
cpu = 2;
wdg_cnt_disable(cpu);
wdg_disable(cpu);
}
/**
* @brief sbl_scratch_reg_set(): set scratch regsiter with watchdog reset flag.
* @return none.
*/
void sbl_scratch_reg_set(void)
{
scratch_p_set_wdg_reset(0, true);
scratch_p_set_wdg_reset(1, true);
}
/**
* @brief sbl_check_reset_by_wdg(): judge reset cause is watchdog or not.
* @return 1 -> is watchdog reset, 0 -> not 1.
*/
uint32_t sbl_check_reset_by_wdg(void)
{
if (scratch_p_get_wdg_reset(0)) {
sbl_printf("core0 wdg rst\n");
return 1;
} else if (scratch_p_get_wdg_reset(1)) {
sbl_printf("core1 wdg rst\n");
return 1;
}
return 0;
}
/**
* @brief sbl_timer_run: start gp-timer.
* @param ms: timeout counter, unit is ms.
* @return none.
*/
void sbl_timer_run(int ms)
{
REG32(GTMR0_CFG_ADDR) = ms;
REG32(GTMR0_CTRL_CFG_ADDR) = (1<<4) | (1<<1); /*(1MHz enable)*/
}
/**
* @brief sbl_timer_clr: clear gp-timer interrupt flag.
* @return none.
*/
void sbl_timer_clr(void)
{
REG32(GTMR0_CLR_ADDR) = (1<<0) | (1<<1); /* intc and cnt clr */
}
/**
* @brief sbl_timer_cnt_done: get gp-timer cnt_done interrupt state.
* @return none.
*/
int sbl_timer_cnt_done(void)
{
return (REG32(GTMR0_INT_STS_ADDR) & GTMR0_CNT_DONE) ? 1 : 0;
}
/**
* @brief sbl_fastboot_flag_set: set(save) fastboot flag.
* @param fboot: fastboot flag.
* @return none.
*/
void sbl_fastboot_flag_set(uint32_t fastboot)
{
g_sbl_fastboot_flag = fastboot;
}
/**
* @brief sbl_fastboot_flag_get: get fastboot flag.
* @return 1 -> is fast boot mode, 0 -> not 1.
*/
uint32_t sbl_fastboot_flag_get(void)
{
return g_sbl_fastboot_flag;
}
/**
* @brief image_check() Check for valid fw at the specified address.
* @param addr: addr to check.
* @param hdr: pointer to store header information.
* @param crc_flag: CRC check mark or not.
* @return -1: no valid header; 0: valid header.
*/
static int image_check(uint32_t addr, imgHdr *hdr, uint8_t crc_flag)
{
char block[HEADER_TOLTAL_SIZE];
uint8_t *src = (uint8_t *)addr;
uint32_t len_total = 0;
uint8_t reason = 0;
/* clear i/dcache */
ahb_cache_clear();
os_mem_cpy(block, src, sizeof(imgHdr));
img_header_construct(hdr, block);
if (iot_imghdr_get_guard(hdr) != IMAGE_GUARD) {
reason = 1;
goto err;
}
if (crc_flag) {
uint32_t img_crc = iot_imghdr_get_imgCRC(hdr);
len_total = iot_imghdr_get_imgSize(hdr);
len_total = IMAGE_LEN_FOR_CRC(len_total);
uint32_t crc = iot_getcrc32((uint8_t *)addr + HEADER_TOLTAL_SIZE, len_total);
if (crc != img_crc) {
reason = 2;
goto err;
}
}
return 0;
err:
sbl_printf("image_check error, addr:0x%x, , reason:%d\r\n", addr, reason);
return -1;
}
/**
* @brief get_fw_addr_info(): get firmware storage and running address.
* @param fw_addr: pointer to save storage address.
* @param run_addr: pointer to save run address.
* @param plc_only_fw: plc only firmware flag.
* @param phdr: point to the img header info.
* @param start_part: pointer of sbl_start_part.
* @return -1: no valid header; 0: valid header.
*/
static int get_fw_addr_info(uint32_t *fw_addr, uint32_t *run_addr,
uint8_t *plc_only_fw, imgHdr *phdr, uint32_t start_part)
{
uint8_t need_crc = 0;
int ret = 0;
uint32_t run_offset = 0;
/* get firmware address */
if (start_part == 0) { //fw1
/* if custom fw partition exist */
if (iot_layout_get_part_offset(PART_NUM_CUS_FW1, fw_addr) == ERR_OK) {
*plc_only_fw = 0;
} else {
iot_layout_get_part_offset(PART_NUM_FW1, fw_addr);
}
} else { //fw2
/* if custom fw partition exist */
if (iot_layout_get_part_offset(PART_NUM_CUS_FW2, fw_addr) == ERR_OK) {
*plc_only_fw = 0;
} else {
iot_layout_get_part_offset(PART_NUM_FW2, fw_addr);
}
}
*fw_addr += FLASH_BASE_ADDRESS;
if (g_is_first_run) {
need_crc = 1;
}
/* check image integrity */
if (image_check(*fw_addr, phdr, need_crc) < 0) {
ret = -1;
goto out;
}
/* fixed run address, header information exists after kl3 is decompressed */
#if RUN_IN_PSRAM
if (*plc_only_fw) {
run_offset = MEM_CFG_RAM_CORE0_RUN_OFFSET;
*run_addr = run_offset + HEADER_TOLTAL_SIZE + PSRAM_CORE0_BASE_ADDRESS;
} else {
if (iot_imghdr_get_zipType(phdr) == zipType_none) {
iot_layout_get_part_offset(PART_NUM_CUS_RUN, &run_offset);
*run_addr = run_offset + HEADER_TOLTAL_SIZE + FLASH_BASE_ADDRESS;
} else {
run_offset = MEM_CFG_RAM_CORE0_RUN_OFFSET;
*run_addr = run_offset + HEADER_TOLTAL_SIZE + PSRAM_CORE0_BASE_ADDRESS;
}
}
#else
if (*plc_only_fw) {
iot_layout_get_part_offset(PART_NUM_RUN, &run_offset);
} else {
if (iot_imghdr_get_zipType(phdr) == zipType_none) {
iot_layout_get_part_offset(PART_NUM_CUS_FW1, &run_offset);
} else {
iot_layout_get_part_offset(PART_NUM_CUS_RUN, &run_offset);
}
}
*run_addr = run_offset + HEADER_TOLTAL_SIZE + FLASH_BASE_ADDRESS;
#endif
out:
sbl_printf("get fw addr:0x%x, run addr:0x%x\r\n", *fw_addr, *run_addr);
return ret;
}
/**
* @brief fw_image_decompress_to_psram(): decompress image to psram.
* @param fw_addr: firmware address.
* @param run_addr: run address.
* @param hdr: image header pointer.
* @return -1: failed; 0: succeed.
*/
static int sbl_decompress_image(uint32_t fw_addr, uint32_t run_addr, imgHdr *hdr)
{
uint8_t *src = NULL;
uint8_t *dst = NULL;
int rc = 0;
/* the compressed or valid data does not contain a header */
src = (uint8_t *)fw_addr + HEADER_TOLTAL_SIZE;
dst = (uint8_t *)run_addr - HEADER_TOLTAL_SIZE;
sbl_printf("decompressed fw image into run addr, [0x%p -> 0x%p]\n", src, dst);
rc = fw_image_decompress(src, dst, iot_imghdr_get_imgSize(hdr));
if(rc != 0 ){
sbl_printf("decompressed failed\n");
return -1;
} else {
uint32_t fw_crc = 0, crc = 0;
fw_crc = iot_imghdr_get_fwCRC(hdr);
crc = iot_getcrc32(dst, IMAGE_LEN_FOR_CRC(iot_imghdr_get_fwSize(hdr)));
if (crc != fw_crc) {
sbl_printf("decompress fw crc error\n");
return -1;
}
}
return 0;
}
/**
* @brief sbl_load_next_firmware(): load custom app or plc app firmware.
* @param run_addr: pointer of run address.
* @param flash_size: flash size
* @param start_part: start part.
* @psram psram_eb: next firmware run in psram or not.
* @return 0: load firmware succeed, 1: load firmware failed.
*/
uint32_t sbl_load_next_firmware(uint32_t *run_addr,
uint32_t flash_size, uint32_t start_part, uint32_t psram_eb)
{
uint32_t fw_addr = 0;
imgHdr hdr = {0};
uint8_t plc_only_fw = 1;
(void)psram_eb;
(void)flash_size;
if (get_fw_addr_info(&fw_addr, run_addr, &plc_only_fw, &hdr, start_part) < 0) {
sbl_printf("No valid firmware found......\r\n");
while(1);
}
#if RUN_IN_PSRAM
if (iot_imghdr_get_zipType(&hdr) == zipType_none) {
/* cus fw supports fast startup, firmware is not compressed */
if (start_part) {
uint32_t offset1, offset2, size;
sbl_printf("re-mapping flash space\r\n");
iot_layout_get_part_offset(PART_NUM_CUS_FW1, &offset1);
iot_layout_get_part_offset(PART_NUM_CUS_FW2, &offset2);
iot_layout_get_part_size(PART_NUM_CUS_FW1, &size);
if (flash_addr_mapping(offset1, offset2, size) != 0) {
sbl_printf("re-mapping error\r\n");
while(1);
}
}
} else {
if(sbl_decompress_image(fw_addr, *run_addr, &hdr) < 0) {
/* decompressed image failed */
sbl_printf("......\r\n");
while(1);
}
}
#else
if (iot_imghdr_get_zipType(&hdr) == zipType_none) {
/* cus fw supports fast startup, firmware is not compressed */
if (start_part) {
uint32_t offset1, offset2, size;
sbl_printf("re-mapping flash space\r\n");
iot_layout_get_part_offset(PART_NUM_CUS_FW1, &offset1);
iot_layout_get_part_offset(PART_NUM_CUS_FW2, &offset2);
iot_layout_get_part_size(PART_NUM_CUS_FW1, &size);
if (flash_addr_mapping(offset1, offset2, size) != 0) {
sbl_printf("re-mapping error\r\n");
while(1);
}
}
} else {
if (os_mem_cmp(sbl_fw_uncp, "0", 1) == 0) {
/* 2m and 4m flash firmware needs to be decompressed */
if(sbl_decompress_image(fw_addr, *run_addr, &hdr) < 0) {
/* decompress image failed */
sbl_printf("......\r\n");
while(1);
} else{
sbl_fw_uncp_success();
}
}
}
#endif
return 0;
}
/**
* @brief sbl_jump_next_firmware(): jump to custom app or plc app firmware.
* @param run_addr: next firmware run address.
* @param mode: firmware run mode.
* @param print_eb: printf function enable or not.
* @param flash_size: flash size.
* @param psram_eb: next firmware run in psram or not.
* @return 0: jump to firmware succeed, 1: jump to firmware failed.
*/
uint32_t sbl_jump_next_firmware(uint32_t run_addr,
int mode, int print_eb, int flash_size, int psram_eb)
{
/* kl3 passes parameters through the scratch register */
sbl_param_input_t sbl_parm;
sbl_parm.run_in_psram = psram_eb;
sbl_parm.flash_size = flash_size;
sbl_parm.fw_mode = mode;
sbl_parm.print_ena = print_eb;
system_set_fw_boot_param(&sbl_parm);
typedef void(*pgm_start_t)(void);
pgm_start_t pgm_start = (pgm_start_t)run_addr;
sbl_printf("\r\njump@0x%x\r\n", (int)pgm_start);
pgm_start();
return 0;
}

96
sbl/src/riscv/entry_def.S Normal file
View File

@@ -0,0 +1,96 @@
// See LICENSE for license details
#ifndef ENTRY_S
#define ENTRY_S
#include "encoding.h"
#include "bits.h"
.section .text.entry
.align 2
.global def_trap_entry
def_trap_entry:
addi sp, sp, -32*REGBYTES
STORE x1, 1*REGBYTES(sp)
STORE x2, 2*REGBYTES(sp)
STORE x3, 3*REGBYTES(sp)
STORE x4, 4*REGBYTES(sp)
STORE x5, 5*REGBYTES(sp)
STORE x6, 6*REGBYTES(sp)
STORE x7, 7*REGBYTES(sp)
STORE x8, 8*REGBYTES(sp)
STORE x9, 9*REGBYTES(sp)
STORE x10, 10*REGBYTES(sp)
STORE x11, 11*REGBYTES(sp)
STORE x12, 12*REGBYTES(sp)
STORE x13, 13*REGBYTES(sp)
STORE x14, 14*REGBYTES(sp)
STORE x15, 15*REGBYTES(sp)
STORE x16, 16*REGBYTES(sp)
STORE x17, 17*REGBYTES(sp)
STORE x18, 18*REGBYTES(sp)
STORE x19, 19*REGBYTES(sp)
STORE x20, 20*REGBYTES(sp)
STORE x21, 21*REGBYTES(sp)
STORE x22, 22*REGBYTES(sp)
STORE x23, 23*REGBYTES(sp)
STORE x24, 24*REGBYTES(sp)
STORE x25, 25*REGBYTES(sp)
STORE x26, 26*REGBYTES(sp)
STORE x27, 27*REGBYTES(sp)
STORE x28, 28*REGBYTES(sp)
STORE x29, 29*REGBYTES(sp)
STORE x30, 30*REGBYTES(sp)
STORE x31, 31*REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
call handle_trap
csrw mepc, a0
# Remain in M-mode after mret
li t0, MSTATUS_MPP
csrs mstatus, t0
LOAD x1, 1*REGBYTES(sp)
LOAD x2, 2*REGBYTES(sp)
LOAD x3, 3*REGBYTES(sp)
LOAD x4, 4*REGBYTES(sp)
LOAD x5, 5*REGBYTES(sp)
LOAD x6, 6*REGBYTES(sp)
LOAD x7, 7*REGBYTES(sp)
LOAD x8, 8*REGBYTES(sp)
LOAD x9, 9*REGBYTES(sp)
LOAD x10, 10*REGBYTES(sp)
LOAD x11, 11*REGBYTES(sp)
LOAD x12, 12*REGBYTES(sp)
LOAD x13, 13*REGBYTES(sp)
LOAD x14, 14*REGBYTES(sp)
LOAD x15, 15*REGBYTES(sp)
LOAD x16, 16*REGBYTES(sp)
LOAD x17, 17*REGBYTES(sp)
LOAD x18, 18*REGBYTES(sp)
LOAD x19, 19*REGBYTES(sp)
LOAD x20, 20*REGBYTES(sp)
LOAD x21, 21*REGBYTES(sp)
LOAD x22, 22*REGBYTES(sp)
LOAD x23, 23*REGBYTES(sp)
LOAD x24, 24*REGBYTES(sp)
LOAD x25, 25*REGBYTES(sp)
LOAD x26, 26*REGBYTES(sp)
LOAD x27, 27*REGBYTES(sp)
LOAD x28, 28*REGBYTES(sp)
LOAD x29, 29*REGBYTES(sp)
LOAD x30, 30*REGBYTES(sp)
LOAD x31, 31*REGBYTES(sp)
addi sp, sp, 32*REGBYTES
mret
.weak handle_trap
handle_trap:
1:
j 1b
#endif

38
sbl/src/riscv/sbl.S Normal file
View File

@@ -0,0 +1,38 @@
// See LICENSE for license details.
.section .init
.globl _start
.type _start,@function
_start:
/* Save rom input param */
add a7, zero, a0
la a0, _start
la gp, _gp
la sp, _sp
la a0, _data_lma
la a1, _data
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
/* Clear bss section */
la a0, __bss_start
la a1, _end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
add a0, zero, a7
call sbl_main
# tail exit
1: j 1b

90
sbl/src/sbl_printf.c Normal file
View File

@@ -0,0 +1,90 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os shim includes */
#include "os_types.h"
#include "iot_errno.h"
#include "dbg_io.h"
#include "sbl_printf.h"
#include "uart.h"
#define SBL_DEBUG_UART_PORT 0
extern struct uart_ctrl uart_e_ctrl;
extern uint32_t g_is_print_enable;
static int (*format_str_v_fn)(const str_format_context *ctxt, const char *format,
va_list ap);
static str_format_context *p_log_ctxt;
static void sbl_fifo_flush(void)
{
while (uart_e_ctrl.tx_fifo_cnt(SBL_DEBUG_UART_PORT)) __asm volatile("nop\n");
return;
}
static StrFormatResult
sbl_uart_printf(void *user_data, const char *data, unsigned int len)
{
(void)user_data;
uint8_t c;
int i = 0;
while (i < len) {
c = *(data+i);
if (c == '\n'){
uart_e_ctrl.try_putc(SBL_DEBUG_UART_PORT,'\r');
}
uart_e_ctrl.try_putc(SBL_DEBUG_UART_PORT,c);
i++;
}
sbl_fifo_flush();
return 0;
}
int8_t getc(void)
{
int32_t c;
c = uart_e_ctrl.getc(SBL_DEBUG_UART_PORT);
if (c == -ERR_AGAIN)
return 0;
else
return (int8_t)c;
}
int sbl_printf_init(void *sbl_format_str_v, void *sbl_log_ctxt)
{
format_str_v_fn = sbl_format_str_v;
p_log_ctxt = sbl_log_ctxt;
p_log_ctxt->write_str = sbl_uart_printf;
return 0;
}
int32_t sbl_printf(const char *fmt, ...)
{
int res;
va_list ap;
if (g_is_print_enable == 0)
return 0;
va_start(ap, fmt);
res = format_str_v_fn(p_log_ctxt, fmt, ap);
va_end(ap);
return res;
}

44
sbl/src/version.c Normal file
View File

@@ -0,0 +1,44 @@
/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "os_types.h"
#include "version.h"
static const uint32_t sbl_firmware_version = SBL_FIRMWARE_VERSION_HEX;
uint8_t sbl_firmware_version_major(void)
{
return SBL_FIRMWARE_VERSION_MAJOR;
}
uint8_t sbl_firmware_version_minor(void)
{
return SBL_FIRMWARE_VERSION_MINOR;
}
uint8_t sbl_firmware_version_micro(void)
{
return SBL_FIRMWARE_VERSION_MICRO;
}
uint16_t sbl_firmware_version_build(void)
{
return SBL_FIRMWARE_VERSION_BUILD;
}
uint32_t sbl_get_firmware_version( void )
{
return sbl_firmware_version;
}