初始提交
This commit is contained in:
90
sbl/Makefile
Normal file
90
sbl/Makefile
Normal 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
85
sbl/inc/common.h
Normal 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
37
sbl/inc/hw/sbl_boot_hw.h
Normal 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
41
sbl/inc/hw2/sbl_boot_hw.h
Normal 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
39
sbl/inc/hw3/sbl_boot_hw.h
Normal 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
111
sbl/inc/sbl_boot.h
Normal 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
34
sbl/inc/sbl_printf.h
Normal 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
41
sbl/inc/version.h
Normal 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
38
sbl/io_lib/Makefile
Normal 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)
|
50
sbl/io_lib/inc/strformat.h
Normal file
50
sbl/io_lib/inc/strformat.h
Normal 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__*/
|
715
sbl/io_lib/src/iot_strformat.c
Normal file
715
sbl/io_lib/src/iot_strformat.c
Normal 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
362
sbl/lzma/7zAlloc.c
Normal 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
78
sbl/lzma/7zAlloc.h
Normal 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
243
sbl/lzma/7zTypes.h
Executable 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
1024
sbl/lzma/LzmaDec.c
Executable file
File diff suppressed because it is too large
Load Diff
232
sbl/lzma/LzmaDec.h
Executable file
232
sbl/lzma/LzmaDec.h
Executable 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
318
sbl/lzma/LzmaTools.c
Executable 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, ¶m);
|
||||
}
|
||||
/* 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, ¶m);
|
||||
/* 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
28
sbl/lzma/LzmaTools.h
Executable 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
38
sbl/lzma/Makefile
Normal 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
19
sbl/lzma/decomp.c
Normal 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
29
sbl/lzma/decomp.h
Normal 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
81
sbl/src/boot.c
Normal 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
237
sbl/src/cm3/sbl.S
Normal 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
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
470
sbl/src/hw/sbl_boot.c
Normal 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, ¶m);
|
||||
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, ¶m) != 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
469
sbl/src/hw2/sbl_boot.c
Normal 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, ¶m);
|
||||
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, ¶m) != 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
530
sbl/src/hw3/sbl_boot.c
Executable 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
96
sbl/src/riscv/entry_def.S
Normal 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
38
sbl/src/riscv/sbl.S
Normal 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
90
sbl/src/sbl_printf.c
Normal 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
44
sbl/src/version.c
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user