nt9856x/loader/LibExt/LIBExt_src/Ctrl_Flow/bl_func.c

3326 lines
105 KiB
C
Executable File

/*
Main control function
This file is implement by user mode
@file bl_func.c
Copyright Novatek Microelectronics Corp. 2014. All rights reserved.
*/
#include "fuart.h"
#include "fat.h"
#include "rtc.h"
#include "timer.h"
#include "StorageDef.h"
#include "global.h"
#include "Clock.h"
#include "bl_func.h"
#include "Cache.h"
#include "string.h"
#include "lz.h"
#include "debug.h"
#include "CC.h"
#include "loader.h"
#include "nvtpack.h"
#include "dram_partition_info.h"
#include "emb_partition_info.h"
#include "modelext_parser.h"
#include "bin_info.h"
#include "shm_info.h"
#include "gic.h"
#include "libfdt.h"
#include <stdlib.h>
#include "bl_u2.h"
#include "crypto.h"
#include "nand.h"
#include "nor.h"
//#if (LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
//static uint32_t global_timer_freq = 3000000; //3MHz = 3000000 Hz
//#endif
PSTORAGE_OBJ int_strg_obj = NULL;
#define FW_PART1_SIZE_OFFSET (CODE_SECTION_OFFSET + 0x04) //ref to CodeInfo.S on rtos (addr of _section_01_size)
//#define TEE_HEADER_SIZE 0x1C // refer to: optee_header_t
#define _THUMB2 __attribute__((target("thumb2")))
#define bl_memcpy utl_memcpy
#define bl_memset utl_memset
#define ALIGN_FLOOR(value, base) ((value) & ~((base)-1))
#define ALIGN_CEIL(value, base) ALIGN_FLOOR((value) + ((base)-1), base)
#define SIZE_PRELOAD 0x400
#define SIZE_PRESERVE_USB 0x2000
#define HEADINFO_UBOOT(p_parti) ((HEADINFO *)(p_parti->uboot_addr + BIN_INFO_OFFSET_UBOOT))
#define HEADINFO_TEEOS(p_parti) ((HEADINFO *)(p_parti->teeos_addr + BIN_INFO_OFFSET_TEEOS))
#define IS_BIN_OVERLAP(addr1, size1, addr2, size2) (!(((addr1 + size1 - 1) < addr2) || (addr1 > (addr2 + size2 - 1))))
#if (STORAGE_EXT_TYPE != STORAGE_EXT_USB)
extern void set_usb_suspend(void);
#endif
#if (_ROM_PUBLIC_API_ == 1)
#define ROM_LZMA_POSITION 0x7fd0
UINT8 lzma_temp_buffer[65536];
int (*rom_lzma_inflate)(UINT8 *in_ptr, UINT32 in_size, UINT8 *out_ptr, UINT32 out_size, UINT8 *p_tmp, UINT32 tmp_size);
#endif
extern char _loader_exec_compres_start[];
//extern char _load_nand_table_start_base[];
extern char _load_LOADER_CONFIGRAM_FREQ_PARAM_end_base[];
extern void core1_reset(void);
// Function from Timer.c
//extern UINT32 timer_getLdrElapse(void);
// Define in MakeConfig.txt
static UINT8 UPDATE_FW_NAME[] = {"FW98520A.BIN"};
static UINT8 UPDATE_LOADER_NAME[] = {"LD98520A.BIN"};
static UINT8 RUN_FW_NAME[] = {"FW98520T.BIN"};
static UINT8 *LOADER_START_STR = {(UINT8 *)"\r\nLoader Start ..."};
//#if !USB_WRITELOADER
#if (STORAGE_EXT_TYPE != STORAGE_EXT_USB)
//static UINT8 *RUN_WRKEY_NAME = {(UINT8 *)"WRKEY.BIN"};
#if UPDATE_SIM_CODE
static UINT8 *RUN_WRKEY_NAME = {(UINT8 *)"SIM.BIN"};
#endif
#endif
static UINT8 RECOVERY_FW_NAME[] = {"FW98520R.BIN"};
static UINT32 g_uiPartitionID = 2;
static UINT32 g_uiVersion = 0;
// Error message
static char FWErrorMsg[] = "\r\nFW check fail\r\n";
static char RWErrorMsg[] = "\r\nR/W error\r\n";
static char LoaderErrorMsg[] = "\r\nLoader check fail\r\n";
UINT32 TopOfStack;
UINT32 BaseOfStack;
extern char _loader_heap_base[];
static BOOL g_is_flash_open = FALSE; // indicate flash is open for updating non-fully all-in-one bin.
static LDR_FASTBOOT_KEY_CB gFastbootKeyCallBack = NULL;
static LDR_SPECIAL_KEY_CB gSpecialKeyCallBack = NULL;
static LDR_CARD_DETECT_CB gCardDetectCallBack = NULL;
static STORAGEINT gStorageIntType = STORAGEINT_UNOKNOWN;
static LDR_RECOVERY_TRIGGER_CB gRecoveryTriggerCallBack = NULL;
//#if (!USB_WRITELOADER)
//#if (STORAGE_EXT_TYPE != STORAGE_EXT_USB)
//static BOOL g_is_recovery_triggered = FALSE; // indicate recovery flow is triggered.
//#endif
_THUMB2 static int bl_is_smp(unsigned char *p_fdt);
static UINT32 g_uiStartBlkUpdateFW = StartNandBlkUpdateFW;
static UINT32 g_uiNandBlkSize = 0;
static UINT32 g_rtos_load_addr = 0;
static UINT32 g_rtos_target_addr = 0;
static UINT32 g_rtos_size = 0;
#if (FDT_SUPPORT)
#define PATH_MEM_DRAM "/nvt_memory_cfg/dram"
#define PATH_MEM_LOADER "/nvt_memory_cfg/loader"
#define PATH_MEM_UBOOT "/nvt_memory_cfg/uboot"
#define PATH_MEM_FDT "/nvt_memory_cfg/fdt"
#define PATH_MEM_SHMEM "/nvt_memory_cfg/shmem"
#define PATH_MEM_RTOS "/nvt_memory_cfg/rtos"
#define PATH_MEM_NUTTX "/nvt_memory_cfg/nuttx"
#define PATH_MEM_TEEOS "/nvt_memory_cfg/teeos"
#define PATH_MEM_HDAL "/hdal-memory/media"
#define PATH_MEM_CORE2_ENTRY1 "/nvt_memory_cfg/core2entry1"
#define PATH_MEM_CORE2_ENTRY2 "/nvt_memory_cfg/core2entry2"
#define PATH_NVT_INFO "/nvt_info"
#define PATH_NVTPACK_INDEX "nvtpack/index"
#define PATH_PARTITION_LOADER "partition_loader"
#define PATH_PARTITION_FDT "partition_fdt"
#define PATH_PARTITION_UBOOT "partition_uboot"
#define PATH_PARTITION_NUTTX "partition_nuttx"
#define PATH_PARTITION_TEEOS "partition_teeos"
#define PATH_PARTITION_RTOS "partition_rtos"
#define PROPERTY_REG "reg"
#define PROPERTY_LABEL "label"
#define PROPERTY_PARTITION_NAME "partition_name"
#define PROPERTY_NVT_LINUX_SMP "NVT_LINUX_SMP"
static DRAM_PARTITION g_dram_partition = {0};
static EMB_PARTITION g_emb_uboot = {0};
static EMB_PARTITION g_emb_teeos = {0};
static EMB_PARTITION g_emb_rtos = {0};
#else // NO FDT_SUPPORT
// refer to met-tbl.dtsi /nvt_memory_cfg
static DRAM_PARTITION g_dram_partition = {
.dram_addr = 0x00000000,
.dram_size = 0x20000000,
.rev_addr = 0x00007E00, ///< shmem
.rev_size = 0x00000200, ///< shmem
.loader_addr = 0x01000000,
.loader_size = 0x00800000,
.fdt_addr = 0x01800000,
.fdt_size = 0x00040000,
.uboot_addr = 0x1E000000,
.uboot_size = 0x01FC0000,
.rtos_addr = 0x01840000, ///< optional, only for fast-boot,
.rtos_size = 0x00780000, ///< optional, only for fast-boot
.core2_entry1_addr = 0x00000000, ///< optional, only for dual core IC (fixed here, and must be)
.core2_entry1_size = 0x00004000, ///< optional, only for dual core IC
.core2_entry2_addr = 0x1FFC0000, ///< optional, only for dual core IC (address better in the bottom of dram to avoid memory space overlap)
.core2_entry2_size = 0x00040000, ///< optional, only for dual core IC
};
// refer to storage-partition.dtsi
static EMB_PARTITION g_emb_uboot = {
.PartitionOffset = 0xC0000,
.PartitionSize = 0xA0000,
};
static EMB_PARTITION g_emb_rtos = { ///< optional, only for fast-boot,
.PartitionOffset = 0x2B40000,
.PartitionSize = 0xA00000,
};
static EMB_PARTITION g_emb_teeos = { ///< optional, only for optee,
.PartitionOffset = 0,
.PartitionSize = 0,
};
//following just for processing all-in-one bin (nvtpack)
//refer to nvtpack.dtsi
#define NVTPACK_IDX_UBOOT 3
#define NVTPACK_IDX_TEEOS -1
#define NVTPACK_IDX_RTOS 10
#endif
#if (UART_UPDATE_ == ENABLE)
static char g_strLength[80]; // buffer to store length string
#endif
//---------------------------------------------------------------------------
// Static function
//---------------------------------------------------------------------------
int bl_boot_uboot(unsigned char *p_fdt);
/**
Display error message.
Display error message.
CPU loop forever and LED is red.
@param Msg: Message to display
@return void
*/
_THUMB2 static void bl_displayErrMsg(char *Msg)
{
// Display error message to UART
debug_msg(Msg);
// Loop forever
while (1) {
;
}
}
/**
Invert endianess of input word
@param[in] a input word
@return translated word
*/
_THUMB2 static UINT32 invertEndian(UINT32 a)
{
return __builtin_bswap32(a);
}
/**
Check FW code.
Check FW code and file length.
The FW binary file must be post-proecessd by encrypt_bin.exe.
This function must sync to encrypt_bin.exe.
If FW checking is fail, the CPU will loop forever and LED is red.
@param[in] uiAddress FW code in DRAM starting address
@param[in] uiFileLen FW code length
@return void
*/
_THUMB2 static void bl_checkFW(UINT32 uiAddress, UINT32 uiFileLen)
{
NVTPACK_MEM mem = {0};
mem.p_data = (void *)uiAddress;
mem.len = uiFileLen;
if (nvtpack_calc_nvt_sum(&mem) != 0) {
bl_displayErrMsg(FWErrorMsg);
}
}
/**
Check boot loader code.
Check boot loader code.
@return void
*/
_THUMB2 static void bl_checkLoader(UINT32 uiAddr, UINT32 uiSize)
{
UINT16 *puiValue, uiSum;
UINT32 i;
puiValue = (UINT16 *)uiAddr;
uiSum = 0;
for (i = 0; i < (uiSize >> 1); i++) {
uiSum += (*puiValue + i);
puiValue++;
}
if ((*(UINT16 *)(uiAddr + LOADER_TAG_OFFSET) != LOADER_TAG_VALUE) ||
(uiSum != 0)) {
bl_displayErrMsg(LoaderErrorMsg);
}
}
#if (SECURE_DECRYPT_UBOOT || SECURE_DECRYPT_OPTEE_OS)
_THUMB2 static void get_bininfo_size_offset(unsigned char* bininfo,unsigned int* size,unsigned int *offset)
{
/****this headinfo is for encrypt header
BinInfo will set partition offset and size
BinInfo_1[0~3] public key offset
BinInfo_1[4~7] public key length
BinInfo_2[0~3] signature offset
BinInfo_2[4~7] signature length
BinInfo_3[0~3] encrypted offset
BinInfo_3[4~7] encrypted size
BinLength total bin size
Checksum total bin checksum
others parameters set 0
*/
*size = bininfo[4] | bininfo[5]<<8 | bininfo[6] << 16 | bininfo[7] << 24;
*offset = bininfo[0] | bininfo[1] << 8 | bininfo[2] << 16 | bininfo[3] <<24;
}
_THUMB2 static int decrypt_aes_cbc(unsigned int input, unsigned int output, unsigned int len)
{
CRYPT_OP crypt_op_param;
if(len &0x0f)
{
debug_msg_var("enc size", len);
debug_err("not align 16\r\n");
return -21;
}
if((input & 0x03) || (output & 0x03) || (len & 0x03) ){ //check word alignment
//debug_msg_var("input", input);
//debug_msg_var("output", output);
//debug_msg_var("len", len);
//debug_err("not word align\r\n");
return -22;
}
crypt_op_param.op_mode = CRYPTO_CBC;
crypt_op_param.en_de_crypt = CRYPTO_DECRYPT;
crypt_op_param.src_addr = input;
crypt_op_param.dst_addr = output;
crypt_op_param.length = len; //Need align to 16bytes align
//debug_msg_var("src",(unsigned int)crypt_op_param.src_addr);
//debug_msg_var("dst",(unsigned int)crypt_op_param.dst_addr);
#if 0
debug_msg_var("input",input);
debug_msg_var("output",output);
debug_msg_var("len",len);
unsigned char *tmp = (unsigned char *) crypt_op_param.src_addr;
int i=0;
debug_msg_var("encryped buf addr",(unsigned int)tmp);
for(i=0;i<16;i++){
debug_msg_var("encryped buf",(unsigned int)tmp[i]);
}
#endif
if(crypto_data_operation(EFUSE_OTP_1ST_KEY_SET_FIELD, crypt_op_param) != 0)
{
//debug_err("aes dec fail\r\n");
return -23;
}
#if 0
unsigned char *tmp = (unsigned char *) crypt_op_param.src_addr;
int i=0;
tmp = (unsigned char *) crypt_op_param.dst_addr;
debug_msg_var("decryped addr",(unsigned int)&tmp[0]);
for(i=0;i<16;i++){
debug_msg_var("decryped buf",(unsigned int)tmp[i]);
}
#endif
return 0;
}
#if (SECURE_SIGNATURE_BY_AES == 0)
_THUMB2 static void data_reverse(unsigned char* input_data, unsigned int size)
{
unsigned int i=0;
unsigned char tmp=0;
for(i=0;i< (size/2);i++)
{
tmp = input_data[size - 1 - i];
input_data[size - 1 - i] = input_data[i];
input_data[i] = tmp;
}
}
#endif
_THUMB2 static int do_decrypt_aes(unsigned int input_data, unsigned int output_data, unsigned int* output_size,unsigned int partition_size)
{
unsigned int encrypt_offset =0;
unsigned int encrypt_size =0;
unsigned int data_size = 0;
HEADINFO *p_headinfo = (HEADINFO *)input_data;
int er=0;
get_bininfo_size_offset((unsigned char *)p_headinfo->BinInfo_3, &encrypt_size, &encrypt_offset);
data_size = p_headinfo->BinLength - encrypt_offset;
#if 1 //for signature check
unsigned int signature_offset =0;
unsigned int signature_size = 0;
UINT32 hash_buf[8];
unsigned int sha256_align_size =0;
UINT32 * signature_buff = NULL;
get_bininfo_size_offset((unsigned char *)p_headinfo->BinInfo_2, &signature_size, &signature_offset);
#if (SECURE_SIGNATURE_BY_AES == 0)
unsigned int key_offset =0;
unsigned int key_size =0;
unsigned int n_size=0;
unsigned int e_size=0;
UINT32 sign_rsa_output[64];
UINT32 *key_n = NULL;
UINT32 *key_e = NULL;
UINT32 *signature_addr = NULL;
get_bininfo_size_offset((unsigned char *)p_headinfo->BinInfo_1, &key_size, &key_offset);
n_size = signature_size;// if rsa 2048 , signature_size should be 256 bytes
e_size = key_size - n_size;
key_n = (UINT32 *)(input_data + key_offset);
// now only support rsa 2048
key_e = (UINT32 *)(input_data + key_offset + signature_size); // signature_size should be 256 bytes, n key should be 256
data_reverse((unsigned char *)(key_n),n_size);
data_reverse((unsigned char *)(key_e),e_size);
er = rsa_keycheck(key_n, 1);// check rsa n key in efuse 1 and 2 field, 0 field for aes key
if(er == 0)
{
debug_err("key fail\r\n");
return -20;
}
signature_addr = (UINT32 *)(input_data + signature_offset);
data_reverse((unsigned char *)signature_addr, signature_size);
//decrypt signature
rsa_decrypt(signature_addr, signature_size, key_n, n_size, key_e, e_size,sign_rsa_output);
data_reverse((unsigned char *)sign_rsa_output, signature_size);
//remove pending data 0, the last 32 bytes will be signature data
signature_buff = (UINT32 *)&sign_rsa_output[(sizeof(sign_rsa_output)/4 ) - (32/4 )];// offset need devided by 4, because of UINT32 type
#else
//UINT32 sign_aes_output[8];
er = decrypt_aes_cbc((UINT32 )(input_data + signature_offset), output_data,signature_size);
if(er != 0)
{
debug_err("decrypt_aes_cbc fail\r\n");
return -20;
}
signature_buff =(UINT32 *)output_data;
#endif
//hash encrypt data
if((data_size & 0x3f) != 0)
{
// hardware sha256 need align 64, need set pending 0
sha256_align_size = ((data_size/0x40) + 1)*0x40;
bl_memset((unsigned char *)(input_data + encrypt_offset + data_size),0, sha256_align_size - data_size);
}
else
{
sha256_align_size = data_size;
}
shahw((unsigned char *)(input_data + encrypt_offset), sha256_align_size, hash_buf);
//compare signature and current hash
if(memcmp((void *)hash_buf, (void *)signature_buff, sizeof(hash_buf)) != 0)
{
debug_err("sig fail\r\n");
return -20;
}
#endif
//decrypt data
//dma addr should 4 alignment, input_data address is 4 alignment
if((input_data + encrypt_offset) & 0x03)
{
utl_memcpy((void *)input_data,(unsigned char*)(input_data + encrypt_offset), data_size);
er = decrypt_aes_cbc(input_data, output_data, encrypt_size);
}
else
{
er = decrypt_aes_cbc(input_data + encrypt_offset, output_data, encrypt_size);
}
if(er != 0)
{
debug_err("aes fail\r\n");
return er;
}
*output_size = data_size;
//add plaintext data to output buf--> aes should 16 alignment, if data not alignment, the last bytes we will not encrypt data
int plaintext_size = data_size - encrypt_size;
unsigned char *p_output = (unsigned char *)output_data;
if( plaintext_size > 0)
{
utl_memcpy(&p_output[encrypt_size], (unsigned char*)(input_data + encrypt_offset+ encrypt_size),plaintext_size);
}
return 0;
}
#endif
//#NT#2013/04/25#Steven Wang -begin
//#NT#Show Duty calibration log
#if (_LOADER_DUTY_CALIBRATION_ == ENABLE && _LOADER_DUTY_CALIBRATION_LOG_ == ENABLE)
void BL_showROMLog(UINT32 buffer)
{
UINT32 value;
UINT32 index;
UINT32 P_duty;
UINT32 N_duty;
UINT32 diff;
index = 0;
diff = 0;
P_duty = 0;
N_duty = 0;
uart_putSystemUARTStr("\r\n");
while (1) {
value = INREG32(buffer + index);
if ((value & 0xF0000000) == 0xF0000000) {
value &= ~(0x40000000);
uart_putSystemUARTStr(Dec2HexStr(value));
uart_putSystemUARTStr(" = ");
}
else if ((value & 0xF0000000) == 0x50000000) {
uart_putSystemUARTStr(Dec2HexStr(value & 0xFFFFFFF));
uart_putSystemUARTStr("\r\n");
}
else if ((value & 0xF0000000) == 0x20000000) {
// uart_putSystemUARTStr("P_duty = ");
P_duty = value & 0xFFFFFFF;
//uart_putSystemUARTStr(Dec2HexStr(value & 0xFFFFFFF));
uart_putSystemUARTStr(Dec2HexStr(P_duty));
uart_putSystemUARTStr("\r\n");
}
else if ((value & 0xF0000000) == 0x30000000) {
// uart_putSystemUARTStr("N_duty = ");
N_duty = value & 0xFFFFFFF;
//uart_putSystemUARTStr(Dec2HexStr(value & 0xFFFFFFF));
uart_putSystemUARTStr(Dec2HexStr(N_duty));
uart_putSystemUARTStr("\r\n");
if (P_duty > N_duty) {
if (diff == 2) {
uart_putSystemUARTStr("============\r\n");
P_duty = 0;
N_duty = 0;
diff = 0;
// diff = 3;
} else {
diff = 1;
}
} else {
if (diff == 1) {
uart_putSystemUARTStr("============\r\n");
P_duty = 0;
N_duty = 0;
diff = 0;
// diff = 3;
} else {
diff = 2;
}
}
} else if ((value & 0xF0000000) == 0x60000000) {
uart_putSystemUARTStr("N+P = ");
uart_putSystemUARTStr(Dec2HexStr(value & 0xFFFFFFF));
uart_putSystemUARTStr("\r\n");
} else if ((value & 0xF0000000) == 0x70000000) {
if ((value & 0xFFFFFFF) == 0x0654321) {
break;
}
} else {
uart_putSystemUARTStr("Unknow \r\n");
}
index += 4;
}
uart_putSystemUARTStr("\r\n[0xC0001000] = 0x");
uart_putSystemUARTStr(Dec2HexStr(INREG32(0xC0001000)));
uart_putSystemUARTStr(" [0xC000101C] = 0x");
uart_putSystemUARTStr(Dec2HexStr(INREG32(0xC000101C)));
uart_putSystemUARTStr("\r\n");
}
#endif
//#NT#2013/04/25#Steven Wang -end
#if (DRAM_RANGE_SCAN_EN == ENABLE)
/**
Check Sram code.
Check is dram scan code or not
@param[in] uiAddress Scan FW code in DRAM starting address
@return void
*/
static BOOL bl_checkDramScanFW(UINT32 uiAddress)
{
if ((*(UINT32 *)uiAddress & SRAM_TAG) == SRAM_TAG) {
return TRUE;
} else {
return FALSE;
}
}
#endif
#if 0
static BOOL bl_spiIdentify(UINT32 uiMfgID, UINT32 uiTypeID, UINT32 uiCapacityID, PSPI_IDENTIFY pIdentify)
{
// Sample to support SST25VF032
if ((uiMfgID == 0xBF) &&
(uiCapacityID == 0x4A)) {
pIdentify->bDualRead = FALSE;
pIdentify->bSupportAAI = TRUE;
pIdentify->bSupportEWSR = TRUE;
pIdentify->uiFlashSize = 4 * 1024 * 1024;
return TRUE;
}
return FALSE;
}
#endif
/*
Update multi-binary image
@param[in] uiFwBuf buffer store fw read from card
@return
-@ b TRUE: success
-@ b FALSE: fail
*/
#if !REMOVED_FLASH
#if 0
static void bl_interrupt_init(void)
{
debug_msg("arm_gic_distif_setup\r\n");
arm_gic_distif_setup();
debug_msg("arm_gic_cpuif_setup\r\n");
arm_gic_cpuif_setup();
//
//debug_dump_addr(0xF1500000+0x1000,0x500);
//debug_dump_addr(0xF1500000+0x2000,0x100);
}
#endif
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
#define OUTW(addr,value) (*(UINT32 volatile *)(addr) = (UINT32)(value))
#define INW(addr) (*(UINT32 volatile *)(addr))
static void bl_cpu_timer_init(UINT32 value)
{
UINT32 dwVal;
OUTW(configARM_TIMER_BASEADDR + ARM_TIMER_LOAD_OFFSET, value);
dwVal = INW(configARM_TIMER_BASEADDR + ARM_TIMER_CONTROL_OFFSET);
/* Enable Auto reload mode. */
dwVal |= ARM_TIMER_CONTROL_AUTO_RELOAD_MASK;
/* Clear prescaler control bits */
dwVal &= ~ARM_TIMER_CONTROL_PRESCALER_MASK;
/* Set prescaler value */
dwVal |= ((CYGHWR_HAL_RTC_PRESCALER - 1) << ARM_TIMER_CONTROL_PRESCALER_SHIFT);
/* Enable the decrementer */
//dwVal |= ARM_TIMER_CONTROL_ENABLE_MASK;
/* Enable the interrupt */
dwVal |= ARM_TIMER_CONTROL_IRQ_ENABLE_MASK;
OUTW(configARM_TIMER_BASEADDR + ARM_TIMER_CONTROL_OFFSET, dwVal);
OUTW(configARM_TIMER_BASEADDR + ARM_TIMER_ISR_OFFSET,
ARM_TIMER_ISR_EVENT_FLAG_MASK);
}
#endif
#endif
_THUMB2 int bl_flash_open(void)
{
int er;
//UINT32 uiStorageVersion = (UINT32)&_load_nand_table_start_base;
if (g_is_flash_open) {
return 0;
}
//==========================================================================
//= User define SPI-NAND id table sample code =
//= You can remove // to use it =
//==========================================================================
//int_strg_obj->flash_setConfig(FLASH_CFG_ID_SPI_IDENTIFY_CB, (UINT32)nand_identify);
//==========================================================================
//= User define SPI-NOR id table sample code =
//= You can remove // to use it =
//==========================================================================
//int_strg_obj->flash_installIdentifyCB(nor_identify);
er = int_strg_obj->flash_open();
if (er < 0) {
debug_err("flash open fail\r\n");
return -1;
}
//OUTREG32(NAND_TABLE_VERSION_ADDR, INREG32(uiStorageVersion));
//if (er == E_OK) {
// OUTREG32(NAND_TABLE_FLAG_ADDR, 0x46495053); //'S''P''I''F'
//} else { // E_OK_TABLE_FOUND(1) or E_OK_TABLE_NOT_FOUND(2)
// OUTREG32(NAND_TABLE_FLAG_ADDR, er);
//}
g_uiNandBlkSize = int_strg_obj->flash_getBlockSize();
if (g_uiNandBlkSize == 0x10000) {
debug_msg("SPI NOR\r\n");
g_uiStartBlkUpdateFW = 1;
} else if (g_uiNandBlkSize == EMMC_BLOCK_SIZE) {
debug_msg("EMMC\r\n");
g_uiStartBlkUpdateFW = FDT_OFFSET / EMMC_BLOCK_SIZE;
} else {
g_uiStartBlkUpdateFW = StartNandBlkUpdateFW;
}
g_is_flash_open = TRUE;
return 0;
}
#if 0 //[-Werror=unused-function]
static int bl_flash_close(void)
{
if (!g_is_flash_open) {
return 0;
}
flash_close();
g_is_flash_open = FALSE;
return 0;
}
#endif
#if (FDT_SUPPORT)
_THUMB2 static const void *bl_get_fdt_property(const void *p_dtb, const char *p_path, const char *p_property, int *len)
{
int nodeoffset; /* next node offset from libfdt */
const void *nodep; /* property node pointer */
nodeoffset = fdt_path_offset(p_dtb, p_path);
if (nodeoffset < 0) {
return NULL;
}
nodep = fdt_getprop(p_dtb, nodeoffset, p_property, len);
if (len == 0) {
return NULL;
}
return nodep;
}
_THUMB2 static const void *bl_get_fdt_nvt_memory_cfg_property(const void *p_dtb, const char *p_path, const char *p_property, int *len)
{
static int nodeoffset_nvt_memory_cfg = -FDT_ERR_NOTFOUND;; /* next node offset from libfdt */
int nodeoffset;
const void *nodep; /* property node pointer */
if (strncmp(p_path, "/nvt_memory_cfg/", 3) != 0) {
debug_err("path prefix must be /nvt_memory_cfg/\r\n");
return NULL;
}
if (nodeoffset_nvt_memory_cfg == -FDT_ERR_NOTFOUND) {
nodeoffset_nvt_memory_cfg = fdt_path_offset(p_dtb, "/nvt_memory_cfg");
}
nodeoffset = fdt_subnode_offset(p_dtb, nodeoffset_nvt_memory_cfg, &p_path[16]);
if (nodeoffset < 0) {
return NULL;
}
nodep = fdt_getprop(p_dtb, nodeoffset, p_property, len);
if (len == 0) {
return NULL;
}
return nodep;
}
#endif
_THUMB2 static unsigned char *bl_get_fdt_cfg(const void *p_dtb, MODELEXT_TYPE type)
{
#if (FDT_SUPPORT)
int len;
const int *nodep;
UINT8 *p_rt = NULL;
switch (type) {
case MODELEXT_TYPE_DRAM_PARTITION:
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_DRAM, PROPERTY_REG, &len);
if (nodep == NULL) {
debug_err("dtb get dram fail\r\n");
return NULL;
}
g_dram_partition.dram_addr = be32_to_cpu(nodep[0]);
g_dram_partition.dram_size = be32_to_cpu(nodep[1]);
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_LOADER, PROPERTY_REG, &len);
if (nodep == NULL) {
debug_err("dtb get loader fail\r\n");
return NULL;
}
g_dram_partition.loader_addr = be32_to_cpu(nodep[0]);
g_dram_partition.loader_size = be32_to_cpu(nodep[1]);
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_UBOOT, PROPERTY_REG, &len);
if (nodep == NULL) {
debug_err("dtb get uboot fail\r\n");
return NULL;
}
g_dram_partition.uboot_addr = be32_to_cpu(nodep[0]);
g_dram_partition.uboot_size = be32_to_cpu(nodep[1]);
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_FDT, PROPERTY_REG, &len);
if (nodep == NULL) {
debug_err("dtb get fdt fail\r\n");
return NULL;
}
g_dram_partition.fdt_addr = be32_to_cpu(nodep[0]);
g_dram_partition.fdt_size = be32_to_cpu(nodep[1]);
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_RTOS, PROPERTY_REG, &len);
if (nodep != NULL) {
g_dram_partition.rtos_addr = be32_to_cpu(nodep[0]);
g_dram_partition.rtos_size = be32_to_cpu(nodep[1]);
}
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_NUTTX, PROPERTY_REG, &len);
if (nodep != NULL) {
g_dram_partition.nuttx_addr = be32_to_cpu(nodep[0]);
g_dram_partition.nuttx_size = be32_to_cpu(nodep[1]);
}
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_TEEOS, PROPERTY_REG, &len);
if (nodep != NULL) {
g_dram_partition.teeos_addr = be32_to_cpu(nodep[0]);
g_dram_partition.teeos_size = be32_to_cpu(nodep[1]);
}
p_rt = (UINT8 *)&g_dram_partition;
break;
case MODELEXT_TYPE_BIN_INFO:
nodep = (const int *)bl_get_fdt_nvt_memory_cfg_property(p_dtb, PATH_MEM_SHMEM, PROPERTY_REG, &len);
if (nodep == NULL) {
debug_err("dtb get shmem fail\r\n");
return NULL;
}
if (sizeof(SHMINFO) > be32_to_cpu(nodep[1])) {
debug_err("shmem size mismatch\r\n");
return NULL;
}
p_rt = (UINT8 *)be32_to_cpu(nodep[0]);
break;
default:
debug_err_var("not handle type\r\n", type);
return NULL;
}
return p_rt;
#else // NO FDT_SUPPORT
switch (type) {
case MODELEXT_TYPE_DRAM_PARTITION:
return (UINT8 *)&g_dram_partition;
case MODELEXT_TYPE_BIN_INFO:
return (UINT8 *)g_dram_partition.rev_addr;
default:
return NULL;
}
#endif
}
_THUMB2 int bl_chk_valid_all_in_one(NVTPACK_MEM *p_mem_all_in_one)
{
NVTPACK_ER er;
NVTPACK_VER ver;
er = nvtpack_getver(p_mem_all_in_one, &ver);
if (er != NVTPACK_ER_SUCCESS) {
return -1;
}
if (ver == NVTPACK_VER_16072017) {
return 0;
}
return -1;
}
#if !REMOVED_FLASH
_THUMB2 int bl_chk_fdt(unsigned int addr, unsigned int size)
{
DRAM_PARTITION *p_dram_partition = NULL;
if (fdt_check_full((void *)addr, size) != 0) {
debug_err("invalid dtb\r\n");
return -1;
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)addr, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("invalid dram_partition\r\n");
return -1;
}
// check tmp memory (file load) cannot overlap with uboot and teeos
// we allow to overlap with linux, root-fs because uboot will reload bin file later
debug_msg_var("tmp_addr", SDRAM_Start_FW);
// if ((addr < p_dram_partition->uboot_addr && addr + size > p_dram_partition->uboot_addr) ||
// (addr > p_dram_partition->uboot_addr && addr + size < p_dram_partition->uboot_addr + p_dram_partition->uboot_size)) {
if (IS_BIN_OVERLAP(addr, size, p_dram_partition->uboot_addr, p_dram_partition->uboot_size)) {
debug_err_var("a", addr);
debug_err_var("s", size);
debug_err("uboot olp\r\n");
return -1;
}
#if 1
//if ((addr < p_dram_partition->teeos_addr && addr + size > p_dram_partition->teeos_addr) ||
// (addr > p_dram_partition->teeos_addr && addr + size < p_dram_partition->teeos_addr + p_dram_partition->teeos_size)) {
if (p_dram_partition->teeos_size) {
if (IS_BIN_OVERLAP(addr, size, p_dram_partition->teeos_addr, p_dram_partition->teeos_size)) {
debug_err_var("a", addr);
debug_err_var("s", size);
debug_err("teeos olp\r\n");
return -1;
}
}
#endif
// check if memory size matched real size
UINT32 ld_dram1_size = dma_get_dram_capacity(DMA_ID_1);
if (p_dram_partition->dram_size > ld_dram1_size) {
debug_err_var("fw_d1_s", p_dram_partition->dram_size);
debug_err_var("ld_d1_s", ld_dram1_size);
debug_err("d1 s not matched.\r\n");
return -1;
}
return 0;
}
#endif
#if !REMOVED_FLASH
_THUMB2 int bl_chk_uboot(unsigned int addr, unsigned int size)
{
#if (_FPGA_EMULATION_ == 0)
NVTPACK_MEM mem = {0};
mem.p_data = (void *)addr;
mem.len = size;
if (nvtpack_calc_nvt_sum(&mem) != 0) {
debug_err("uboot check sum fail");
return -1;
}
#endif
return 0;
}
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
static void bl_core2_reset(void)
{
UINT32 core_reg;
debug_msg("core2_reset\r\n");
core_reg = *(volatile UINT32 *)0xF0E400F0;
core_reg &= ~(1<<3);
core_reg &= ~(1<<11);
*(volatile UINT32 *)0xF0E400F0 = core_reg;
core_reg |= (1<<2)|(1<<10) | (1<<21);
core_reg |= (1<<17);
*(volatile UINT32 *)0xF0E400F0 = core_reg;
}
static void bl_core2_prepare(DRAM_PARTITION *p_dram_partition, unsigned int last_addr)
{
extern char _load_core2_jump_program_start_base[];
extern char _load_core2_jump_program_end_base[];
extern char _load_core2_entry_program_start_base[];
extern char _load_core2_entry_program_end_base[];
UINT32 code2JumpCodelen, code2EntryCodelen;
//check core2_entry1 must at addr 0
if (p_dram_partition->core2_entry1_addr != CORE2_JUMP_ADDR) {
bl_displayErrMsg("core2entry1 != 0");
}
// copy core2 jump code to dram 0x0
code2JumpCodelen = _load_core2_jump_program_end_base - _load_core2_jump_program_start_base;
utl_memcpy((void *)p_dram_partition->core2_entry1_addr, _load_core2_jump_program_start_base, code2JumpCodelen);
// CPUflushWriteCache(p_dram_partition->core2_entry1_addr, code2JumpCodelen);
debug_msg_var("core2_jump_program", (int)_load_core2_jump_program_start_base);
debug_msg_var("code2JumpCodelen", (int)code2JumpCodelen);
debug_msg_var("core2_entry2_addr", (int)p_dram_partition->core2_entry2_addr);
// copy core2 entry code to dram specified by fdt
*(volatile UINT32 *)(NVT_CORE2_START) = p_dram_partition->core2_entry2_addr;
code2EntryCodelen = _load_core2_entry_program_end_base - _load_core2_entry_program_start_base;
utl_memcpy((void *)p_dram_partition->core2_entry2_addr, _load_core2_entry_program_start_base, code2EntryCodelen);
// CPUflushWriteCache(p_dram_partition->core2_entry2_addr, code2EntryCodelen);
debug_msg_var("core2_entry_program", (int)_load_core2_entry_program_start_base);
debug_msg_var("code2EntryCodelen", (int)code2EntryCodelen);
*(volatile UINT32 *)0xF07F8000 = last_addr;
debug_msg_var("0xF07F8000=", (int)*(volatile UINT32 *)0xF07F8000);
}
static int bl_smp_start(unsigned char *p_modelext, UINT32 uboot_entry)
{
SHMINFO *p_bininfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_modelext, MODELEXT_TYPE_BIN_INFO);
if (p_bininfo == NULL) {
debug_err("null p_bininfo\r\n");
return -1;
}
DRAM_PARTITION *p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_modelext, MODELEXT_TYPE_DRAM_PARTITION);
if (p_bininfo == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
debug_msg_var("fdt", (UINT32)p_modelext);
debug_msg_var("shm", (UINT32)p_bininfo);
p_bininfo->boot.fdt_addr = (UINT32)p_modelext;
debug_msg_var("p_bininfo->boot.fdt_addr", p_bininfo->boot.fdt_addr);
utl_memset(p_bininfo->boot.LdInfo_1, 0, sizeof(p_bininfo->boot.LdInfo_1));
utl_memcpy(p_bininfo->boot.LdInfo_1, "LD_NVT", 6);
// clear cc_core1_addr, cc_core2_addr
#if USB_WRITELOADER
if(utl_get_bootsrc() == BOOT_SOURCE_UART) {
p_bininfo->comm.Resv[0] = BOOT_REASON_FROM_UART;
} else if(USB_WRITELOADER || utl_get_bootsrc() == BOOT_SOURCE_USB) {
p_bininfo->comm.Resv[0] = BOOT_REASON_FROM_USB;
} else {
p_bininfo->comm.Resv[0] = BOOT_REASON_NORMAL;
}
#else
// if (card_get_type() == EXT_STORAGE_TYPE_ETH)
// p_bininfo->comm.Resv[0] = BOOT_REASON_FROM_ETH;
// else if (g_is_recovery_triggered)
// p_bininfo->comm.Resv[0] = BOOT_REASON_RECOVERY_SYS;
// else
#if (STORAGE_EXT_TYPE == STORAGE_EXT_ETH)
p_bininfo->comm.Resv[0] = BOOT_REASON_FROM_ETH;
#else
p_bininfo->comm.Resv[0] = BOOT_REASON_NORMAL;
#endif
#endif
p_bininfo->comm.Resv[1] = 0; // COMM_CORE1_START
p_bininfo->comm.Resv[2] = 0; // COMM_CORE2_START
p_bininfo->comm.Resv[3] = 0; // COMM_UITRON_COMP_ADDR
p_bininfo->comm.Resv[4] = 0; // COMM_UITRON_COMP_LEN
debug_msg("smp(no tee)\r\n");
bl_core2_prepare(p_dram_partition, 0);
//#if USB_WRITELOADER
#if 0
USBStateMachine();
uart_putSystemUARTStr("USB update Done\n\r");
timer_delay(1000000);
USBOTGReset();
#endif
//invalid Instruciton and data cache
CPUCleanInvalidateDCacheAll();
CPUInvalidateICacheAll();
//reset core2
bl_core2_reset();
{
typedef void (*BRANCH_CB)(void);
BRANCH_CB p_func = (BRANCH_CB)uboot_entry;
debug_msg_var("jump", uboot_entry);
p_func();
}
return 0;
}
#endif
_THUMB2 static int bl_entry_boot(unsigned char *p_fdt, UINT32 uboot_entry)
{
SHMINFO *p_bininfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_BIN_INFO);
if (p_bininfo == NULL) {
debug_err("null p_bininfo\r\n");
return -1;
}
debug_msg_var("fdt", (UINT32)p_fdt);
debug_msg_var("shm", (UINT32)p_bininfo);
p_bininfo->boot.fdt_addr = (UINT32)p_fdt;
utl_memset(p_bininfo->boot.LdInfo_1, 0, sizeof(p_bininfo->boot.LdInfo_1));
utl_memcpy(p_bininfo->boot.LdInfo_1, "LD_NVT", 6);
// clear cc_core1_addr, cc_core2_addr
#if USB_WRITELOADER
CPUflushWriteCache((UINT32)p_bininfo, sizeof(BININFO));
if(utl_get_bootsrc() == BOOT_SOURCE_USB) {
p_bininfo->comm.Resv[0] = BOOT_REASON_FROM_USB;
} else {
p_bininfo->comm.Resv[0] = BOOT_REASON_FROM_UART;
}
#else
if (card_get_type() == EXT_STORAGE_TYPE_ETH)
p_bininfo->comm.Resv[0] = BOOT_REASON_FROM_ETH;
// else if (g_is_recovery_triggered)
// p_bininfo->comm.Resv[0] = BOOT_REASON_RECOVERY_SYS;
else
p_bininfo->comm.Resv[0] = BOOT_REASON_NORMAL;
#endif
p_bininfo->comm.Resv[1] = 0; // COMM_CORE1_START
p_bininfo->comm.Resv[2] = 0; // COMM_CORE2_START
p_bininfo->comm.Resv[3] = 0; // COMM_UITRON_COMP_ADDR
p_bininfo->comm.Resv[4] = 0; // COMM_UITRON_COMP_LEN
//invalid Instruciton and data cache
CPUCleanInvalidateDCacheAll();
CPUInvalidateICacheAll();
{
typedef void (*BRANCH_CB)(void);
BRANCH_CB p_func = (BRANCH_CB)uboot_entry;
debug_msg_var("jump", uboot_entry);
p_func();
}
return 0;
}
_THUMB2 int bl_copy_fdt_to_fdt_addr(unsigned char *p_fdt /*IN*/, unsigned char **pp_fdt /*OUT*/)
{
DRAM_PARTITION *p_dram_partition;
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("bl_copy_fdt_to_fdt_addr failed.\r\n");
return -1;
}
// load fdt to fdt buffer
utl_memcpy((void *)p_dram_partition->fdt_addr, p_fdt, fdt_totalsize(p_fdt));
*pp_fdt = (unsigned char *)p_dram_partition->fdt_addr;
//reset shminfo
SHMINFO *p_bininfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_BIN_INFO);
bl_memset(p_bininfo, 0, sizeof(SHMINFO));
return 0;
}
_THUMB2 static int bl_load_fdt_from_all_in_one(unsigned char *p_all_in_one, unsigned int all_in_one_size, unsigned char **pp_fdt /*OUT*/)
{
NVTPACK_ER er;
NVTPACK_MEM emb_fdt;
NVTPACK_VERIFY_OUTPUT np_verify = {0};
NVTPACK_GET_PARTITION_INPUT np_get_input;
NVTPACK_MEM mem_in = {(void *)p_all_in_one, (unsigned int)all_in_one_size};
if (nvtpack_verify(&mem_in, &np_verify) != NVTPACK_ER_SUCCESS) {
debug_err("packbin verify failed.\r\n");
return -1;
}
np_get_input.id = 1; // fdt must always put in partition[1]
np_get_input.mem = mem_in;
er = nvtpack_get_partition(&np_get_input, &emb_fdt);
if (er == NVTPACK_ER_NOT_FOUND) {
return -2;
} else if (er == NVTPACK_ER_SUCCESS) {
debug_msg_var("fdt addr", (int)emb_fdt.p_data);
debug_msg_var("fdt size", (int)emb_fdt.len);
if (bl_chk_fdt((unsigned int)emb_fdt.p_data, emb_fdt.len) == 0) {
return bl_copy_fdt_to_fdt_addr(emb_fdt.p_data, pp_fdt);
}
}
return -1;
}
_THUMB2 static unsigned int bl_load_rtos_from_all_in_one(unsigned char *p_all_in_one, unsigned int all_in_one_size, unsigned char **pp_fdt /*OUT*/)
{
UINT32 uItron_fw_addr= 0;
NVTPACK_ER er;
NVTPACK_MEM emb_fdt;
NVTPACK_VERIFY_OUTPUT np_verify = {0};
NVTPACK_GET_PARTITION_INPUT np_get_input;
NVTPACK_MEM mem_in = {(void *)p_all_in_one, (unsigned int)all_in_one_size};
HEADINFO *p_headinfo;
if (nvtpack_verify(&mem_in, &np_verify) != NVTPACK_ER_SUCCESS) {
debug_err("packbin verify failed.\r\n");
return 0;
}
np_get_input.id = 5; // rtos must always put in partition[5] for now
np_get_input.mem = mem_in;
er = nvtpack_get_partition(&np_get_input, &emb_fdt);//&np_get_input, &emb_fdt);
if (er == NVTPACK_ER_NOT_FOUND) {
return 0;
} else if (er == NVTPACK_ER_SUCCESS) {
debug_msg("get rtos partition ok\r\n");
p_headinfo = (HEADINFO *)(emb_fdt.p_data + BIN_INFO_OFFSET_RTOS);
uItron_fw_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
utl_memcpy((void *)uItron_fw_addr, emb_fdt.p_data, emb_fdt.len);
CPUflushWriteCache(uItron_fw_addr, emb_fdt.len);
}
debug_msg_var("uItron_fw_addr=", uItron_fw_addr);
return uItron_fw_addr;
}
_THUMB2 static int bl_load_fdt_from_flash(unsigned char *p_tmp, unsigned int tmp_size, unsigned char **pp_fdt /*OUT*/)
{
// read first block to get dtb size
int blk_size = (int)int_strg_obj->flash_getBlockSize();
int er = int_strg_obj->flash_readSectors(g_uiStartBlkUpdateFW, blk_size, p_tmp, NAND_RW_FIRMWARE);
if (er < 0) {
debug_err("bl_load_fdt_from_flash");
return -1;
}
int total_size = ALIGN_CEIL(fdt_totalsize(p_tmp), blk_size);
if ((int)tmp_size < total_size) {
debug_err_var("tmp_size too small, require:", fdt_totalsize(p_tmp));
return -1;
}
total_size -= blk_size;
if (total_size > 0) {
// read remain to get uboot starting addr on dram and offset in flash
er = int_strg_obj->flash_readSectors(g_uiStartBlkUpdateFW+1, total_size, p_tmp+blk_size, NAND_RW_FIRMWARE);
if (er < 0) {
debug_err("bl_load_fdt_from_flash");
return -1;
}
}
if (bl_chk_fdt((unsigned int)p_tmp, fdt_totalsize(p_tmp)) == 0) {
return bl_copy_fdt_to_fdt_addr(p_tmp, pp_fdt);
}
return -1;
}
#if (FDT_SUPPORT)
_THUMB2 static int bl_get_partition_fdt_offset(unsigned char *p_fdt)
{
static int nodeoffset= -FDT_ERR_NOTFOUND;
if (nodeoffset > 0) {
return nodeoffset;
}
const static char *p_names[3] = {
"/nand",
"/nor",
"/mmc@f0510000"
};
const char *name = NULL;
switch(gStorageIntType) {
case STORAGEINT_SPI_NAND:
name = p_names[0];
break;
case STORAGEINT_SPI_NOR:
name = p_names[1];
break;
case STORAGEINT_EMMC:
name = p_names[2];
break;
default:
debug_err("loader_setStorageIntType needs.\r\n");
return NULL;
}
nodeoffset = fdt_path_offset(p_fdt, name);
if (nodeoffset < 0) {
debug_err("E:bl_get_partition_name\r\n");
}
return nodeoffset;
}
#endif
#if (FDT_SUPPORT)
_THUMB2 static const void *bl_get_fdt_partition_property(const void *p_dtb, const char *p_path, const char *p_property, int *len)
{
int nodeoffset_partition = bl_get_partition_fdt_offset((unsigned char *)p_dtb);
int nodeoffset;
const void *nodep; /* property node pointer */
if (nodeoffset_partition < 0) {
debug_err("nodeoffset_partition invalid \r\n");
return NULL;
}
nodeoffset = fdt_subnode_offset(p_dtb, nodeoffset_partition, p_path);
if (nodeoffset < 0) {
return NULL;
}
nodep = fdt_getprop(p_dtb, nodeoffset, p_property, len);
if (len == 0) {
return NULL;
}
return nodep;
}
#endif
#if (FDT_SUPPORT)
_THUMB2 static int bl_get_partition(unsigned char *p_fdt /*IN*/, char *p_emb_name /*IN*/, EMB_PARTITION *p_emb/*OUT*/, int *p_id)
{
int len;
const unsigned long long *nodep;
// get partition offset and size
nodep = (const unsigned long long *)bl_get_fdt_partition_property(p_fdt, p_emb_name, PROPERTY_REG, &len);
if (nodep == NULL) {
debug_err("bl_get_partition-1\r\n");
return -1;
}
p_emb->PartitionOffset = be64_to_cpu(nodep[0]);
p_emb->PartitionSize = be64_to_cpu(nodep[1]);
// get partition label
char *p_label_name = (char *)bl_get_fdt_partition_property(p_fdt, p_emb_name, PROPERTY_LABEL, &len);
if (p_label_name == NULL) {
debug_err("bl_get_partition-2\r\n");
return -1;
}
// get id
int nodeoffset_partition = bl_get_partition_fdt_offset(p_fdt);
int nodeoffset = fdt_subnode_offset(p_fdt, nodeoffset_partition, "nvtpack");
nodeoffset = fdt_subnode_offset(p_fdt, nodeoffset, "index");
for (nodeoffset = fdt_first_subnode(p_fdt, nodeoffset);
(nodeoffset >= 0);
(nodeoffset = fdt_next_subnode(p_fdt, nodeoffset))) {
const struct fdt_property *prop;
if (!(prop = fdt_get_property(p_fdt, nodeoffset, PROPERTY_PARTITION_NAME, &len))) {
break;
}
const char *p_id_name = fdt_get_name(p_fdt, nodeoffset, &len);
if (strcmp(p_label_name, (char *)prop->data) == 0) {
*p_id = atoi(p_id_name + strlen("id"));
return 0;
}
}
return -1;
}
#endif
_THUMB2 static void *bl_get_uboot_partition(unsigned char *p_fdt /*IN*/, int *p_id /*OUT*/)
{
#if (FDT_SUPPORT)
if (bl_get_partition(p_fdt, PATH_PARTITION_UBOOT, &g_emb_uboot, p_id) != 0) {
return NULL;
}
#else
*p_id = NVTPACK_IDX_UBOOT;
#endif
g_emb_uboot.EmbType = EMBTYPE_UBOOT;
return &g_emb_uboot;
}
_THUMB2 static void *bl_get_rtos_partition(unsigned char *p_fdt /*IN*/, int *p_id /*OUT*/)
{
#if (FDT_SUPPORT)
if (bl_get_partition(p_fdt, PATH_PARTITION_RTOS, &g_emb_rtos, p_id) != 0) {
return NULL;
}
#else
*p_id = NVTPACK_IDX_RTOS;
#endif
g_emb_rtos.EmbType = EMBTYPE_RTOS;
return &g_emb_rtos;
}
#if (NUTTX_SUPPORT)
_THUMB2 static void *bl_get_nuttx_partition(unsigned char *p_fdt /*IN*/, int *p_id /*OUT*/)
{
if (bl_get_partition(p_fdt, PATH_PARTITION_NUTTX, &g_emb_nuttx, p_id) != 0) {
return NULL;
}
g_emb_nuttx.EmbType = EMBTYPE_NUTTX;
return &g_emb_nuttx;
}
#endif
_THUMB2 static void *bl_get_teeos_partition(unsigned char *p_fdt /*IN*/, int *p_id /*OUT*/)
{
#if (FDT_SUPPORT)
if (bl_get_partition(p_fdt, PATH_PARTITION_TEEOS, &g_emb_teeos, p_id) != 0) {
return NULL;
}
#else
*p_id = NVTPACK_IDX_TEEOS;
#endif
g_emb_teeos.EmbType = EMBTYPE_TEEOS;
return &g_emb_teeos;
}
#endif
// return decompress_fw_size
_THUMB2 static unsigned int bl_decompress_rtos(UINT32 compress_addr, UINT32 compress_size, UINT32 fw_base_addr)
{
UINT32 decoded_size;
NVTPACK_BFC_HDR *pBfc = (NVTPACK_BFC_HDR *)compress_addr;
UINT32 size_comp_le = invertEndian(pBfc->uiSizeComp);
UINT32 size_uncomp_le = invertEndian(pBfc->uiSizeUnComp);
size_comp_le = (compress_size < size_comp_le) ? compress_size : size_comp_le;
decoded_size = LZ_Un_compress((UINT8 *)compress_addr + sizeof(NVTPACK_BFC_HDR), (UINT8 *)fw_base_addr, size_comp_le);
//because some padding bytes are decoded, we must return real rtos size
return (decoded_size < size_uncomp_le) ? decoded_size : size_uncomp_le;
}
#if !REMOVED_FLASH
_THUMB2 static int bl_load_uboot_from_all_in_one(unsigned char *p_fdt, unsigned char *p_all_in_one, unsigned int all_in_one_size)
{
NVTPACK_ER er;
NVTPACK_MEM mem_uboot;
int uboot_partition_id;
NVTPACK_GET_PARTITION_INPUT input;
DRAM_PARTITION *p_dram_partition = NULL;
EMB_PARTITION *p_emb_partition_uboot = bl_get_uboot_partition(p_fdt, &uboot_partition_id);
if (p_emb_partition_uboot == NULL) {
debug_err("null p_emb_partition_uboot\r\n");
return -1;
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
// get partition data address and size
input.id = (unsigned int)uboot_partition_id;
input.mem.p_data = (void *)p_all_in_one;
input.mem.len = all_in_one_size;
er = nvtpack_get_partition(&input, &mem_uboot);
if (er == NVTPACK_ER_NOT_FOUND) {
return -2;
}
if (er != NVTPACK_ER_SUCCESS) {
return -1;
}
debug_msg_var("uboot_addr", p_dram_partition->uboot_addr);
// debug_msg_var("uboot_size", p_dram_partition->uboot_size);
# if 0
if(0) {
#else
#if (_FPGA_EMULATION_ == 0)
if(is_secure_enable() == 0) {
#else
if (1) {
#endif
#endif
if (bl_chk_uboot((unsigned int)mem_uboot.p_data, mem_uboot.len) != 0) {
return -1;
}
// flow to handle compressed u-boot and uncompressed one.
HEADINFO *p_headinfo = (HEADINFO *)(mem_uboot.p_data + BIN_INFO_OFFSET_UBOOT); // describe uncompressed u-boot
NVTPACK_BFC_HDR *pBfc = (NVTPACK_BFC_HDR *)mem_uboot.p_data; // describe compressed u-boot
// load uboot bin to dram partiton location
//debug_msg_var("uboot_addr", p_dram_partition->uboot_addr);
//debug_msg_var("uboot_size", p_dram_partition->uboot_size);
if (pBfc->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) {
if((cpu_to_be32(pBfc->uiAlgorithm) & 0xFF ) == 11) {
#if (_ROM_PUBLIC_API_ == 1)
UINT32 lzma_addr = *(UINT32 *)ROM_LZMA_POSITION;
UINT32 size_comp_le = invertEndian(pBfc->uiSizeComp);
UINT32 size_uncomp_le = invertEndian(pBfc->uiSizeUnComp);
rom_lzma_inflate = (int (*)(UINT8 *, UINT32 , UINT8 * , UINT32 , UINT8 *, UINT32 ))((lzma_addr));
rom_lzma_inflate(mem_uboot.p_data + sizeof(NVTPACK_BFC_HDR), size_comp_le, (unsigned char *) p_dram_partition->uboot_addr, size_uncomp_le, (UINT8 *)lzma_temp_buffer, 65536);
debug_msg("lzma ");
#else
debug_msg("Can not support LZMA\r\n");
#endif
} else {
UINT32 size_comp_le = invertEndian(pBfc->uiSizeComp);
LZ_Un_compress(mem_uboot.p_data + sizeof(NVTPACK_BFC_HDR), (unsigned char *) p_dram_partition->uboot_addr, size_comp_le);
debug_msg("lz");
}
} else {
debug_msg("nml");
utl_memcpy((void *)p_dram_partition->uboot_addr, mem_uboot.p_data, p_headinfo->BinLength);
}
} else {
#if (SECURE_DECRYPT_UBOOT)
utl_memcpy((void *)p_dram_partition->uboot_addr, mem_uboot.p_data, mem_uboot.len);
unsigned int plaintext_size =0;
if((er = do_decrypt_aes(p_dram_partition->uboot_addr, p_dram_partition->uboot_addr, &plaintext_size, p_dram_partition->uboot_size))!= 0 )
{
//debug_err("aes fail\r\n");
return er;
}
if (bl_chk_uboot((unsigned int)p_dram_partition->uboot_addr, plaintext_size) != 0) {
return -1;
}
#else
debug_msg("please enable SECURE_DECRYPT_UBOOT\r\n");
return -1;
#endif
}
return 0;
}
#if (NUTTX_SUPPORT)
_THUMB2 static int bl_load_nuttx_from_all_in_one(unsigned char *p_fdt, unsigned char *p_all_in_one, unsigned int all_in_one_size)
{
NVTPACK_ER er;
NVTPACK_MEM mem_nuttx;
int nuttx_partition_id;
NVTPACK_GET_PARTITION_INPUT input;
DRAM_PARTITION *p_dram_partition = NULL;
EMB_PARTITION *p_emb_partition_nuttx = bl_get_nuttx_partition(p_fdt, &nuttx_partition_id);
if (p_emb_partition_nuttx == NULL) {
debug_err("null p_emb_partition_nuttx\r\n");
return -1;
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
// get partition data address and size
input.id = (unsigned int)nuttx_partition_id;
input.mem.p_data = (void *)p_all_in_one;
input.mem.len = all_in_one_size;
er = nvtpack_get_partition(&input, &mem_nuttx);
if (er == NVTPACK_ER_NOT_FOUND) {
return -2;
}
if (er != NVTPACK_ER_SUCCESS) {
return -1;
}
// using check uboot's check sum is ok
if (bl_chk_uboot((unsigned int)mem_nuttx.p_data, mem_nuttx.len) != 0) {
return -1;
}
// flow to handle compressed u-boot and uncompressed one.
HEADINFO *p_headinfo = (HEADINFO *)(mem_nuttx.p_data + BIN_INFO_OFFSET_NUTTX); // describe uncompressed u-boot
NVTPACK_BFC_HDR *pBfc = (NVTPACK_BFC_HDR *)mem_nuttx.p_data; // describe compressed u-boot
// load nuttx bin to dram partiton location
debug_msg_var("nuttx_addr", p_dram_partition->nuttx_addr);
debug_msg_var("nuttx_size", p_dram_partition->nuttx_size);
if (pBfc->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) {
UINT32 size_comp_le = invertEndian(pBfc->uiSizeComp);
LZ_Un_compress(mem_nuttx.p_data + sizeof(NVTPACK_BFC_HDR), (unsigned char *) p_dram_partition->nuttx_addr, size_comp_le);
} else {
utl_memcpy((void *)p_dram_partition->nuttx_addr, mem_nuttx.p_data, p_headinfo->BinLength);
}
return 0;
}
#endif
_THUMB2 static int bl_load_teeos_from_all_in_one(unsigned char *p_fdt, unsigned char *p_all_in_one, unsigned int all_in_one_size)
{
NVTPACK_ER er;
NVTPACK_MEM mem_teeos;
int teeos_partition_id;
NVTPACK_GET_PARTITION_INPUT input;
DRAM_PARTITION *p_dram_partition = NULL;
EMB_PARTITION *p_emb_partition_teeos = bl_get_teeos_partition(p_fdt, &teeos_partition_id);
HEADINFO *p_headinfo = NULL;
if (p_emb_partition_teeos == NULL) {
debug_err("null p_emb_partition_teeos\r\n");
return -1;
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
// get partition data address and size
input.id = (unsigned int)teeos_partition_id;
input.mem.p_data = (void *)p_all_in_one;
input.mem.len = all_in_one_size;
er = nvtpack_get_partition(&input, &mem_teeos);
if (er == NVTPACK_ER_NOT_FOUND) {
return -2;
}
if (er != NVTPACK_ER_SUCCESS) {
return -1;
}
#if 0
if(1){
#else
if(is_secure_enable()) {
#endif
#if (SECURE_DECRYPT_OPTEE_OS)
unsigned int plaintext_size =0;
utl_memcpy((void *)p_dram_partition->teeos_addr, mem_teeos.p_data, mem_teeos.len);
if((er = do_decrypt_aes(p_dram_partition->teeos_addr, p_dram_partition->teeos_addr,&plaintext_size, p_dram_partition->teeos_size))!= 0)
{
//debug_err("aes fail\r\n");
return er;
}
//this is the second headinfo information , not encrpyted headinfo
p_headinfo = (HEADINFO *)(p_dram_partition->teeos_addr + BIN_INFO_OFFSET_TEEOS);
#else
debug_err("please enable SECURE_DECRYPT_OPTEE_OS");
return -1;
#endif
}
else{
p_headinfo = (HEADINFO *)(mem_teeos.p_data + BIN_INFO_OFFSET_TEEOS); // describe uncompressed u-boot
utl_memcpy((void *)p_dram_partition->teeos_addr, (unsigned char*)mem_teeos.p_data, p_headinfo->BinLength);
}
UINT32 teeos_addr = p_headinfo->Resv1[HEADINFO_TEEOS_RESV_IDX_LOAD_ADDR];
//check addr matched or not
debug_msg_var("teeos_addr", p_dram_partition->teeos_addr);
if (teeos_addr != p_dram_partition->teeos_addr) {
debug_msg_var("teeos_addr(bin)", teeos_addr);
debug_err("teeos addr not matched.\r\n");
return -1;
}
// using check uboot's check sum is ok
if (bl_chk_uboot((unsigned int)teeos_addr, p_headinfo->BinLength) != 0) {
return -1;
}
return 0;
}
_THUMB2 static int bl_load_uboot_from_flash(unsigned char *p_fdt, unsigned char *p_tmp)
{
int er;
int uboot_partition_id;
DRAM_PARTITION *p_dram_partition = NULL;
unsigned int blk_size = int_strg_obj->flash_getBlockSize();
EMB_PARTITION *p_emb_partition_uboot = bl_get_uboot_partition(p_fdt, &uboot_partition_id);
if (p_emb_partition_uboot == NULL) {
debug_err("null p_emb_partition_uboot\r\n");
return -1;
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg(p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
#if (SECURE_DECRYPT_UBOOT)
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_uboot->PartitionOffset / blk_size,
ALIGN_CEIL(BIN_INFO_OFFSET_UBOOT + sizeof(HEADINFO), blk_size), p_tmp, NAND_RW_FIRMWARE)) < 0)
{
debug_err_var("bl_load_uboot_from_flash,er=", er);
bl_displayErrMsg(RWErrorMsg); // read uboot failed
return -1;
}
#else
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_uboot->PartitionOffset / blk_size,
ALIGN_CEIL(BIN_INFO_OFFSET_UBOOT + sizeof(HEADINFO), blk_size), p_tmp, NAND_RW_FIRMWARE)) < 0)
{
debug_err_var("bl_load_uboot_from_flash,er=", er);
bl_displayErrMsg(RWErrorMsg); // read uboot failed
return -1;
}
#endif
debug_msg_var("uboot_addr", p_dram_partition->uboot_addr);
debug_msg_var("uboot_size", p_dram_partition->uboot_size);
#if 0
if(0){
#else
if(is_secure_enable() == 0) {
#endif
HEADINFO *p_headinfo = (HEADINFO *)(p_tmp + BIN_INFO_OFFSET_UBOOT); // describe uncompressed u-boot
NVTPACK_BFC_HDR *pBfc = (NVTPACK_BFC_HDR *)p_tmp; // describe compressed u-boot
if (pBfc->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1'))
{
UINT32 size_comp_le = invertEndian(pBfc->uiSizeComp);
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_uboot->PartitionOffset / blk_size,
ALIGN_CEIL(size_comp_le, blk_size),p_tmp, NAND_RW_FIRMWARE)) < 0)
{
debug_err_var("bl_load_uboot_from_flash_comp,er=", er); // read bfc-uboot failed
bl_displayErrMsg(RWErrorMsg);
}
if((cpu_to_be32(pBfc->uiAlgorithm) & 0xFF ) == 11) {
#if (_ROM_PUBLIC_API_ == 1)
UINT32 lzma_addr = *(UINT32 *)ROM_LZMA_POSITION;
UINT32 size_comp_le = invertEndian(pBfc->uiSizeComp);
UINT32 size_uncomp_le = invertEndian(pBfc->uiSizeUnComp);
rom_lzma_inflate = (int (*)(UINT8 *, UINT32 , UINT8 * , UINT32 , UINT8 *, UINT32 ))((lzma_addr));
rom_lzma_inflate(p_tmp + sizeof(NVTPACK_BFC_HDR), size_comp_le, (unsigned char *) p_dram_partition->uboot_addr, size_uncomp_le, (UINT8 *)lzma_temp_buffer, 65536);
debug_msg("lzma ");
#else
debug_msg("Can not support LZMA\r\n");
#endif
} else {
LZ_Un_compress(p_tmp + sizeof(NVTPACK_BFC_HDR), (unsigned char *)p_dram_partition->uboot_addr, size_comp_le);
}
}
else
{
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_uboot->PartitionOffset / blk_size,
ALIGN_CEIL(p_headinfo->BinLength, blk_size),
(UINT8 *)p_dram_partition->uboot_addr, NAND_RW_FIRMWARE)) < 0)
{
debug_err_var("bl_load_uboot_from_flash,er=", er); // read bfc-uboot failed
bl_displayErrMsg(RWErrorMsg);
}
}
}
else
{
#if (SECURE_DECRYPT_UBOOT)
HEADINFO *p_headinfo = (HEADINFO *)(p_tmp); // describe uncompressed u-boot
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_uboot->PartitionOffset / blk_size,
ALIGN_CEIL(p_headinfo->BinLength, blk_size),
(UINT8 *)p_dram_partition->uboot_addr, NAND_RW_FIRMWARE)) < 0)
{
debug_err_var("bl_load_uboot_from_flash,er=", er); // read bfc-uboot failed
bl_displayErrMsg(RWErrorMsg);
}
unsigned int plaintext_size=0;
if((er =do_decrypt_aes(p_dram_partition->uboot_addr, p_dram_partition->uboot_addr, &plaintext_size, p_dram_partition->uboot_size))!= 0)
{
//debug_err("aes fail\r\n");
return er;
}
#else
debug_msg("plase enable SECURE_DECRYPT_UBOOT config\r\n");
return -1;
#endif
}
return 0;
}
_THUMB2 static int bl_load_rtos_from_flash(unsigned char *p_fdt, unsigned char *p_tmp)
{
int er;
int rtos_partition_id;
DRAM_PARTITION *p_dram_partition = NULL;
unsigned int blk_size = int_strg_obj->flash_getBlockSize();
EMB_PARTITION *p_emb_partition_rtos = bl_get_rtos_partition(p_fdt, &rtos_partition_id);
SHMINFO *p_shminfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_BIN_INFO);
if (p_emb_partition_rtos == NULL) {
debug_err("null p_emb_partition_rtos\r\n");
return -1;
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg(p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
if(bl_is_smp(p_fdt)) {
bl_core2_prepare(p_dram_partition, 0);
//invalid Instruciton and data cache
CPUCleanInvalidateDCacheAll();
bl_core2_reset();
}
#endif
// load 1st block of rtos to tmp dram (to detect compressed u-boot)
unsigned int bininfo_preload_size = ALIGN_CEIL(BIN_INFO_OFFSET_RTOS + sizeof(HEADINFO), blk_size);
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_rtos->PartitionOffset / blk_size, bininfo_preload_size, p_tmp, NAND_RW_FIRMWARE)) < 0) {
debug_err_var("bl_load_rtos_from_flash,er=", er);
bl_displayErrMsg(RWErrorMsg); // read rtos failed
}
// flow to handle compressed u-boot and uncompressed one.
NVTPACK_BFC_HDR *pBfc = (NVTPACK_BFC_HDR *)p_tmp; // describe compressed u-boot
// load rtos bin to dram partiton location
//debug_msg_var("rtos_addr", p_dram_partition->rtos_addr);
//debug_msg_var("rtos_size", p_dram_partition->rtos_size);
if (pBfc->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) {
if((cpu_to_be32(pBfc->uiAlgorithm) & 0xFF ) == 11)
{
/* lzma compressed image*/
debug_msg("lzma, use uboot\r\n");
er = bl_load_uboot_from_flash((unsigned char *)p_dram_partition->fdt_addr, p_tmp);
if (er != 0) {
bl_displayErrMsg("load uboot failed\r\n");
}
// boot uboot
er = bl_boot_uboot((unsigned char *)p_dram_partition->fdt_addr);
if (er != 0) {
bl_displayErrMsg("boot uboot failed\r\n");
}
} else {
UINT32 size_comp_le = invertEndian(pBfc->uiSizeComp);
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_rtos->PartitionOffset / blk_size, ALIGN_CEIL(size_comp_le, blk_size), p_tmp, NAND_RW_FIRMWARE)) < 0) {
debug_err_var("bl_load_rtos_from_flash_comp,er=", er); // read bfc-rtos failed
bl_displayErrMsg(RWErrorMsg);
}
LZ_Un_compress(p_tmp + sizeof(NVTPACK_BFC_HDR), (unsigned char *)p_dram_partition->rtos_addr, size_comp_le);
}
} else {
BININFO *p_bininfo = (BININFO *)(p_tmp + BIN_INFO_OFFSET_RTOS); // describe uncompressed u-boot
if (p_bininfo->head.Resv1[HEADINFO_RESV_IDX_BOOT_FLAG] & BOOT_FLAG_PARTLOAD_EN) {
// copy bininfo_preload to rtos_addr
bl_memcpy((UINT8 *)p_dram_partition->rtos_addr, p_tmp, bininfo_preload_size);
// preload some to get part-1 size for partial load and partial compressed load
UINT32 preload_size = ALIGN_CEIL(FW_PART1_SIZE_OFFSET, blk_size) - bininfo_preload_size;
if (preload_size!= 0) {
er = int_strg_obj->flash_readSectors(
(p_emb_partition_rtos->PartitionOffset + bininfo_preload_size) / blk_size,
preload_size,
(UINT8 *)(p_dram_partition->rtos_addr + bininfo_preload_size), NAND_RW_FIRMWARE
);
if (er < 0) {
debug_err_var("bl_load_rtos_from_flash_pl1,er=", er); // read bfc-uboot failed
bl_displayErrMsg(RWErrorMsg);
}
}
UINT32 part1_size = *(UINT32 *)(p_dram_partition->rtos_addr + FW_PART1_SIZE_OFFSET);
debug_msg_var("part1_size",part1_size);
part1_size = ALIGN_CEIL(part1_size, blk_size);
//debug_msg_var("part1_size_aligned",part1_size);
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_rtos->PartitionOffset / blk_size, part1_size, (UINT8 *)p_dram_partition->rtos_addr, NAND_RW_FIRMWARE)) < 0) {
debug_err_var("bl_load_rtos_from_flash_pl1,er=", er);
bl_displayErrMsg(RWErrorMsg);
}
// update loaded size
p_shminfo->boot.LdLoadSize = part1_size;
} else {
// full load
debug_msg_var("rtos_size", p_bininfo->head.BinLength);
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_rtos->PartitionOffset /blk_size, ALIGN_CEIL(p_bininfo->head.BinLength, blk_size), (UINT8 *)p_dram_partition->rtos_addr, NAND_RW_FIRMWARE)) < 0) {
debug_err_var("bl_load_rtos_from_flash,er=", er); // read bfc-uboot failed
bl_displayErrMsg(RWErrorMsg);
}
// update loaded size
p_shminfo->boot.LdLoadSize = p_bininfo->head.BinLength;
}
}
return 0;
}
_THUMB2 static int bl_load_teeos_from_flash(unsigned char *p_fdt, unsigned char *p_tmp)
{
int er;
int teeos_partition_id;
DRAM_PARTITION *p_dram_partition = NULL;
unsigned int blk_size = int_strg_obj->flash_getBlockSize();
EMB_PARTITION *p_emb_partition_teeos = bl_get_teeos_partition(p_fdt, &teeos_partition_id);
if (p_emb_partition_teeos == NULL) {
debug_err("null p_emb_partition_teeos\r\n");
return -1;
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg(p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
// load 1st block of u-boot to tmp dram (to detect compressed u-boot)
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_teeos->PartitionOffset / blk_size, ALIGN_CEIL(BIN_INFO_OFFSET_TEEOS + sizeof(HEADINFO), blk_size), p_tmp, NAND_RW_FIRMWARE)) < 0) {
debug_err_var("bl_load_teeos_from_flash,er=", er);
bl_displayErrMsg(RWErrorMsg); // read teeos failed
}
// flow to handle compressed u-boot and uncompressed one.
#if (SECURE_DECRYPT_OPTEE_OS)
HEADINFO *p_headinfo = (HEADINFO *)(p_tmp); // describe uncompressed u-boot
#else
HEADINFO *p_headinfo = (HEADINFO *)(p_tmp + BIN_INFO_OFFSET_TEEOS); // describe uncompressed u-boot
#endif
if ((er = int_strg_obj->flash_readSectors(p_emb_partition_teeos->PartitionOffset / blk_size, ALIGN_CEIL(p_headinfo->BinLength, blk_size), (UINT8 *)p_dram_partition->teeos_addr, NAND_RW_FIRMWARE)) < 0) {
debug_err_var("bl_load_teeos_from_flash,er=", er); // read bfc-teeos failed
bl_displayErrMsg(RWErrorMsg);
}
#if 0
if(1){
#else
if(is_secure_enable()) {
#endif
#if (SECURE_DECRYPT_OPTEE_OS)
unsigned int plaintext_size=0;
if((er = do_decrypt_aes(p_dram_partition->teeos_addr, p_dram_partition->teeos_addr, &plaintext_size, p_dram_partition->teeos_size)) != 0)
{
//debug_err("aes fail\r\n");
return er;
}
p_headinfo = (HEADINFO *)(p_dram_partition->teeos_addr + BIN_INFO_OFFSET_TEEOS); // describe uncompressed u-boot
#else
debug_err("please ENABLE SECURE_DECRYPT_OPTEE_OS config\n");
return -1;
#endif
}
// load teeos bin to dram partiton location
UINT32 teeos_addr = p_headinfo->Resv1[HEADINFO_TEEOS_RESV_IDX_LOAD_ADDR];
debug_msg_var("teeos_addr", p_dram_partition->teeos_addr);
if (teeos_addr != p_dram_partition->teeos_addr) {
debug_msg_var("teeos_addr(bin)", teeos_addr);
debug_err("teeos addr not matched.\r\n");
return -1;
}
//check check sum
if (bl_chk_uboot((unsigned int)teeos_addr, p_headinfo->BinLength) != 0) {
return -1;
}
return 0;
}
#endif
#if !(USB_WRITELOADER || UART_UPDATE)
_THUMB2 static int bl_load_rtos_from_non_nvtpack(unsigned int src_addr, unsigned int src_size, unsigned int *p_dst_addr, unsigned int *p_dst_size)
{
NVTPACK_BFC_HDR *pBFC = (NVTPACK_BFC_HDR *)src_addr;
HEADINFO *p_headinfo = (HEADINFO *)(src_addr + BIN_INFO_OFFSET_RTOS);
if (pBFC->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) {
// to avoid rtos_addr is overlapped by src_addr, we need extract some bits to get real rtos addr.
// compressed firmware
debug_msg("compressed t.bin\r\n");
// decode some bytes to get uncompressed address
bl_decompress_rtos(src_addr, SIZE_PRELOAD, src_addr + SIZE_PRELOAD);
p_headinfo = (HEADINFO *)(src_addr + SIZE_PRELOAD + BIN_INFO_OFFSET_RTOS);
// check if valid after decode
if ((strncmp(p_headinfo->BinInfo_1, "NT", 2) == 0) ||
(strncmp(p_headinfo->BinInfo_1, "NC", 2) == 0)) {
UINT32 uncompress_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
UINT32 uncompress_size = p_headinfo->BinLength;
UINT32 compress_size = invertEndian(pBFC->uiSizeComp) + sizeof(NVTPACK_BFC_HDR);
//adjust src_addr that lay compressed f.w followed by uncomppressed f.w
src_addr = uncompress_addr + uncompress_size;
src_addr = ALIGN_CEIL(src_addr, 4);
src_size = fat_read_rootfile((UINT8 *)src_addr, compress_size);
} else {
return -1;
}
} else if ((strncmp(p_headinfo->BinInfo_1, "NT", 2) == 0) ||
(strncmp(p_headinfo->BinInfo_1, "NC", 2) == 0)) {
// uncompressed firmware
UINT32 uncompress_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
UINT32 uncompress_size = p_headinfo->BinLength;
src_size = fat_read_rootfile((UINT8 *)src_addr, uncompress_size);
src_addr = uncompress_addr;
src_size = uncompress_size;
debug_msg("uncompressed t.bin\r\n");
#if (DRAM_RANGE_SCAN_EN == ENABLE)
} else if (utl_is_sram_fw(src_addr) == TRUE) {
debug_msg("detected as SRAM fw\r\n");
src_size = fat_read_rootfile((UINT8 *)src_addr, FAT_READ_TOTAL_FILE_LENGTH);
#endif
} else {
return -1;
}
*p_dst_addr = src_addr;
*p_dst_size = src_size;
return 0;
}
#endif
#if 0//(STORAGE_EXT_TYPE == STORAGE_EXT_USB)
_THUMB2 static int bl_load_rtos_from_usb_raw(unsigned int src_addr, unsigned int src_size, unsigned int *p_dst_addr, unsigned int *p_dst_size)
{
NVTPACK_BFC_HDR *pBFC = (NVTPACK_BFC_HDR *)src_addr;
HEADINFO *p_headinfo = (HEADINFO *)(src_addr + BIN_INFO_OFFSET_RTOS);
if (pBFC->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) {
// to avoid rtos_addr is overlapped by src_addr, we need extract some bits to get real rtos addr.
// compressed firmware
debug_msg("compressed t.bin\r\n");
// decode some bytes to get uncompressed address
// assume usb write loader receive full fw at 0x0200_0000, decompress it to smaller address
bl_decompress_rtos(src_addr, SIZE_PRELOAD, src_addr - SIZE_PRESERVE_USB);
p_headinfo = (HEADINFO *)(src_addr - SIZE_PRESERVE_USB + BIN_INFO_OFFSET_RTOS);
// check if valid after decode
if ((strncmp(p_headinfo->BinInfo_1, "NT", 2) == 0) ||
(strncmp(p_headinfo->BinInfo_1, "NC", 2) == 0)) {
UINT32 uncompress_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
UINT32 uncompress_size = p_headinfo->BinLength;
UINT32 compress_size = invertEndian(pBFC->uiSizeComp) + sizeof(NVTPACK_BFC_HDR);
//adjust src_addr that lay compressed f.w followed by uncomppressed f.w
utl_memcpy((void *)(uncompress_addr + uncompress_size), (void *)src_addr, compress_size);
src_addr = uncompress_addr + uncompress_size;
src_addr = ALIGN_CEIL(src_addr, 4);
src_size = compress_size;
} else {
return -1;
}
} else if ((strncmp(p_headinfo->BinInfo_1, "NT", 2) == 0) ||
(strncmp(p_headinfo->BinInfo_1, "NC", 2) == 0)) {
// uncompressed firmware
UINT32 uncompress_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
UINT32 uncompress_size = p_headinfo->BinLength;
debug_msg("uncompressed t.bin\r\n");
utl_memcpy((void *)uncompress_addr, (void *)src_addr, uncompress_size);
src_size = uncompress_size;
#if (DRAM_RANGE_SCAN_EN == ENABLE)
} else if (utl_is_sram_fw(src_addr) == TRUE) {
debug_msg("detected as SRAM fw. NOt Support from USB\r\n");
#endif
} else {
return -1;
}
*p_dst_addr = src_addr;
*p_dst_size = src_size;
return 0;
}
#endif
//#if !USB_WRITELOADER
#if !((STORAGE_EXT_TYPE == STORAGE_EXT_USB) || (STORAGE_EXT_TYPE == STORAGE_EXT_UART))
_THUMB2 static int bl_load_rtos_from_uart(unsigned int src_addr, unsigned int src_size, unsigned int *p_dst_addr, unsigned int *p_dst_size)
{
#if UART_UPDATE_
UINT32 tick_kms = 10; // timeout 1000 ms
char key;
debug_msg("UART press Enter to\r\n");
while (--tick_kms) {
uart_chkChar(&key);
if (key != 0x00) {
break;
}
timer_delay(100000); //100000
debug_msg(".");
}
if (tick_kms) {
UINT32 uiLength;
debug_msg("\r\nEnter uboot length (Decimal):\r\n"); //must \r\n at the end because of auto_test tool
uart_getStr_polling(g_strLength);
uiLength = DecStr2Int(g_strLength);
debug_msg("\r\nPlz pass uboot bin > ");
uart_getBinary((char *)src_addr, uiLength); // Temp Receive to DRAM start
debug_msg("\r\nGot it\r\n");
#if (DRAM_RANGE_SCAN_EN == ENABLE)
// First word is code entry point address, once if entry address is 0xC000XXXX
// represent code is running on sram.
if (bl_checkDramScanFW(src_addr) == TRUE) {
UINT32 i;
// Enable sram usage
SETREG32(0xF0900128, 0x00000002);
SETREG32(0xF0800128, 0x00000006);
SETREG32(0xF0020060, 0x00030002);
uiLength = ((uiLength + 3) & 0xFFFFFFFC);
for (i = 0; i < uiLength; i += 4) {
*(UINT32 *)(src_addr + i) = *(UINT32 *)(src_addr + i);
}
*(UINT32 *)(src_addr) = *(UINT32 *)(src_addr);
return 1;
}
#endif
if (*(UINT32 *)src_addr == MAKEFOURCC('B', 'C', 'L', '1')) {
HEADINFO *p_headinfo = NULL;
NVTPACK_BFC_HDR *pBFC = (NVTPACK_BFC_HDR *)src_addr;
bl_checkFW(src_addr, uiLength);
debug_msg_var("uiLength", uiLength);
debug_msg("compressed t.bin\r\n");
// decode some bytes to get uncompressed address
bl_decompress_rtos(src_addr, SIZE_PRELOAD, src_addr + uiLength);
p_headinfo = (HEADINFO *)(src_addr + uiLength + BIN_INFO_OFFSET_RTOS);
// check if valid after decode
if ((strncmp(p_headinfo->BinInfo_1, "NT", 2) == 0) ||
(strncmp(p_headinfo->BinInfo_1, "NC", 2) == 0)) {
UINT32 uncompress_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
UINT32 uncompress_size = p_headinfo->BinLength;
UINT32 compress_size = invertEndian(pBFC->uiSizeComp) + sizeof(NVTPACK_BFC_HDR);
unsigned int ori_src_addr = src_addr;
//adjust src_addr that lay compressed f.w followed by uncomppressed f.w
src_addr = uncompress_addr + uncompress_size;
src_addr = ALIGN_CEIL(src_addr, 4);
src_size = uncompress_size;
utl_memcpy((void *)src_addr, (void *)ori_src_addr, uiLength);
*p_dst_addr = src_addr;
*p_dst_size = compress_size;
return 0;
} else {
return -1;
}
return 0;
}
}
#endif
return -1;
}
#endif
_THUMB2 static void bl_update_uItron_headInfo(UINT32 fw_base_addr, DRAM_PARTITION *p_dram_partition)
{
HEADINFO *pHeadInfo;
#if (UITRON_FW == ENABLE)
BININFO *pBinInfo;
#endif
pHeadInfo = (HEADINFO *)(fw_base_addr + BIN_INFO_OFFSET_RTOS);
if (p_dram_partition) {
pHeadInfo->ModelextAddr = p_dram_partition->fdt_addr;
} else {
pHeadInfo->ModelextAddr = 0;
#if (UITRON_FW == ENABLE)
pBinInfo = (BININFO *)(fw_base_addr + BIN_INFO_OFFSET_RTOS);
pBinInfo->ld.Resv[0] = LoaderInternalInfo[1];
pBinInfo->ld.LdPackage = (LoaderInternalInfo[3] & 0xFFFF);
#endif
}
}
_THUMB2 static int bl_update_loader_bininfo(unsigned char *p_fdt, unsigned int ld_flag, unsigned int rtos_loaded_size)
{
BOOTINFO *p_ld;
SHMINFO *p_shminfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_BIN_INFO);
DRAM_PARTITION *p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
BININFO *p_bininfo = (BININFO *)(p_dram_partition->rtos_addr + BIN_INFO_OFFSET_RTOS);
p_ld = &p_shminfo->boot;
if (!(p_bininfo->head.Resv1[HEADINFO_RESV_IDX_BOOT_FLAG] & BOOT_FLAG_PARTLOAD_EN)) {
// LdLoadSize updated on uboot or bl_load_rtos_from_flash(), if BOOT_FLAG_PARTLOAD_EN
p_ld->LdLoadSize = rtos_loaded_size;
}
p_ld->LdLoadTime = timer_getLdrElapse();
p_ld->LdResvSize = 0; //unused
p_ld->FWResvSize = 0; //unused
return 0;
}
_THUMB2 static int bl_is_smp(unsigned char *p_fdt)
{
#if (FDT_SUPPORT)
int len;
const char *nodep;
nodep = (const char *)bl_get_fdt_property(p_fdt, PATH_NVT_INFO, PROPERTY_NVT_LINUX_SMP, &len);
debug_msg_var("nodep", (UINT32)nodep);
if (nodep == NULL) {
return 0;
}
debug_msg((char *)nodep);
if (strcmp(nodep, "NVT_LINUX_SMP_ON") == 0) {
return 1;
}
return 0;
#else
return 0;
#endif
}
#if !REMOVED_FLASH
_THUMB2 int bl_boot_uboot(unsigned char *p_fdt)
{
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
UINT32 No_CPU;
#endif
DRAM_PARTITION *p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
// update shminfo
SHMINFO *p_shminfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_BIN_INFO);
unsigned int *p_param = (unsigned int *)(&_load_LOADER_CONFIGRAM_FREQ_PARAM_start_base[0]);
p_shminfo->boot.LdPackage = p_param[3] & 0xFFFF;
p_shminfo->boot.LdStorage = (p_param[3] >> 16) & 0xFF;
// update headinfo as real u-boot address
HEADINFO *p_headinfo = (HEADINFO *)(p_dram_partition->uboot_addr + BIN_INFO_OFFSET_UBOOT);
if (bl_chk_uboot(p_dram_partition->uboot_addr, p_headinfo->BinLength) != 0) {
return -1;
}
// start cpu2
if (p_dram_partition->uboot_addr != p_headinfo->CodeEntry) {
debug_err_var("drampat-uboot_addr ", (int)p_dram_partition->uboot_addr);
debug_err_var("bin-uboot_addr ", (int)p_headinfo->CodeEntry);
return -1;
}
// for uboot to indicate this boot is all-in-one fw or non-all-in-one boot from uart or usb
// if boot from uart or usb with non-all-in-one fw, the uboot's ModelextAddr will be zero
p_headinfo->ModelextAddr = p_dram_partition->fdt_addr;
CPUflushWriteCache(p_headinfo->CodeEntry, p_headinfo->BinLength);
UINT32 isSMP = bl_is_smp(p_fdt);
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
No_CPU = *(UINT32 *)0xFFD00004;
No_CPU &= 0x3;
debug_msg_var("core No.=", No_CPU+1);
#endif
// init cpu timer
// bl_cpu_timer_init(CPU_TIMER_SETTING);
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
if (!isSMP || !No_CPU)
#else
if (!isSMP)
#endif
{
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
debug_msg_var("Bin core=", isSMP+1);
#endif
bl_entry_boot(p_fdt, p_headinfo->CodeEntry);
} else {
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
// init cpu timer
bl_cpu_timer_init(global_timer_freq);
bl_smp_start(p_fdt, p_headinfo->CodeEntry);
// boot u-boot and never return back to loader
#else
//bl_smp_start(p_fdt, p_headinfo->CodeEntry);
debug_err("not support smp\r\n");
#endif
}
return 0;
}
#if (NUTTX_SUPPORT)
_THUMB2 static int bl_boot_nuttx(unsigned char *p_fdt)
{
DRAM_PARTITION *p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
// update headinfo as real u-boot address
HEADINFO *p_headinfo = (HEADINFO *)(p_dram_partition->nuttx_addr + BIN_INFO_OFFSET_NUTTX);
if (bl_chk_uboot(p_dram_partition->nuttx_addr, p_headinfo->BinLength) != 0) {
return -1;
}
// start cpu2
if (p_dram_partition->nuttx_addr != p_headinfo->CodeEntry) {
debug_err_var("drampat-nuttx_addr ", (int)p_dram_partition->nuttx_addr);
debug_err_var("bin-nuttx_addr ", (int)p_headinfo->CodeEntry);
return -1;
}
CPUflushWriteCache(p_headinfo->CodeEntry, p_headinfo->BinLength);
// init cpu timer
bl_cpu_timer_init(CPU_TIMER_SETTING);
bl_entry_boot(p_fdt, p_headinfo->CodeEntry);
// boot nuttx and never return back to loader
return 0;
}
#endif
_THUMB2 static int bl_boot_teeos(unsigned char *p_fdt)
{
DRAM_PARTITION *p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition == NULL) {
debug_err("null p_dram_partition\r\n");
return -1;
}
// update headinfo as real u-boot address
HEADINFO *p_headinfo = (HEADINFO *)(p_dram_partition->teeos_addr + BIN_INFO_OFFSET_TEEOS);
// update uboot addr for teeos
p_headinfo->Resv1[HEADINFO_TEEOS_RESV_IDX_UBOOT_ADDR] = p_dram_partition->uboot_addr;
#if 0 //do not checksum, because teeos header has removed cause checksum failed
if (bl_chk_uboot(p_dram_partition->teeos_addr, p_headinfo->BinLength) != 0) {
return -1;
}
#endif
//flush uboot
CPUflushWriteCache(p_dram_partition->uboot_addr, p_dram_partition->uboot_size);
//flush teeos
CPUflushWriteCache(p_headinfo->CodeEntry, p_headinfo->BinLength);
// init cpu timer
#if 0//(LOADER_TYPE == STAND_ALONE_LOADER_528) || (LOADER_TYPE == COMBINATION_528)
bl_cpu_timer_init(CPU_TIMER_SETTING);
// boot core2 (after teeos is loaded)
if (HEADINFO_UBOOT(p_dram_partition)->BinCtrl & 0x00000002) {
//if SMP, trigger core2
debug_msg("smp(tee)\r\n");
bl_core2_prepare(p_dram_partition, p_headinfo->CodeEntry);
//invalid Instruciton and data cache
CPUCleanInvalidateDCacheAll();
bl_core2_reset();
} else {
debug_msg_var("not smp\r\n", p_headinfo->BinCtrl);
}
#endif
bl_entry_boot(p_fdt, p_headinfo->CodeEntry);
// boot teeos and never return back to loader
return 0;
}
_THUMB2 static int bl_update_loader_flag(unsigned char *p_fdt, UINT32 uiLoaderFunc)
{
SHMINFO *p_bininfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_BIN_INFO);
utl_memcpy(p_bininfo->boot.LdInfo_1, "LD_NVT", 6);
p_bininfo->boot.LdCtrl2 = 0;
if (uiLoaderFunc & FUNC_UPDATE_FW) {
p_bininfo->boot.LdCtrl2 |= LDCF_UPDATE_FW;
}
if (uiLoaderFunc & FUNC_UPDATE_LOADER) {
p_bininfo->boot.LdCtrl2 |= LDCF_UPDATE_LD;
}
if (uiLoaderFunc & FUNC_RUN_CARD) {
p_bininfo->boot.LdCtrl2 |= LDCF_BOOT_CARD;
}
if (uiLoaderFunc & FUNC_RUN_FLASH) {
p_bininfo->boot.LdCtrl2 |= LDCF_BOOT_FLASH;
}
//CPUflushWriteCache((UINT32)p_bininfo, sizeof(BININFO));
debug_msg_var("LdCtrl2", p_bininfo->boot.LdCtrl2);
unsigned int ver;
SHMINFO *p_shminfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_fdt, MODELEXT_TYPE_BIN_INFO);
BOOTINFO *p_ld = &p_shminfo->boot;
utl_memset(p_ld->LdInfo_1, 0, sizeof(p_ld->LdInfo_1));
utl_memcpy(p_ld->LdInfo_1, "LD_NVT", 6);
ver = (((LoaderInternalInfo[1] >> 28) & 0xF) << 24) |
(((LoaderInternalInfo[1] >> 24) & 0xF) << 16) |
((LoaderInternalInfo[1] >> 16) & 0xFF);
if (g_uiVersion == 0) {
g_uiVersion = ver;
}
utl_memcpy(&p_ld->LdInfo_1[8], &g_uiVersion, sizeof(g_uiVersion));
unsigned int *p_param = (unsigned int *)(&_load_LOADER_CONFIGRAM_FREQ_PARAM_start_base[0]);
p_ld->LdPackage = p_param[3] & 0xFFFF;
p_ld->LdStorage = (p_param[3] >> 16) & 0xFF;
return 0;
}
// return uItron_fw_addr
_THUMB2 unsigned int bl_process_all_in_one(UINT32 uiFwBuf, UINT32 uiFwBufSize, DRAM_PARTITION **pOut_dram_partition, UINT32 uiLoaderFunc, UINT32 *p_comp_addr, UINT32 *p_comp_size)
{
int er;
unsigned char *p_fdt = NULL;
DRAM_PARTITION *p_dram_partition = NULL;
//p_tmp for the case of all-in-one without fdt or uboot
unsigned char *p_tmp = (unsigned char *)(uiFwBuf + ALIGN_CEIL(uiFwBufSize, 4));
// load fdt
er = bl_load_fdt_from_all_in_one((unsigned char *)uiFwBuf, uiFwBufSize, &p_fdt);
if (er == -2) { // try to load from nand
debug_msg("fdt from flash.\r\n");
// open flash
if (bl_flash_open() != 0) { // dont move flash open outside section, consider that T without flash device.
bl_displayErrMsg("flash open failed\r\n");
}
//p_tmp for the case of all-in-one without fdt or uboot
unsigned char *p_tmp = (unsigned char *)(uiFwBuf + ALIGN_CEIL(uiFwBufSize, 4));
er = bl_load_fdt_from_flash(p_tmp, 0x2000000, &p_fdt); // dtb size less than 32MB to be safer.
if (er != 0) {
bl_displayErrMsg("load fdt failed\r\n");
}
}
// update loader flag
bl_update_loader_flag(p_fdt, uiLoaderFunc);
if (uiLoaderFunc & FUNC_UPDATE_FW) {
SHMINFO *p_bininfo = (SHMINFO *)bl_get_fdt_cfg(p_fdt, MODELEXT_TYPE_BIN_INFO);
if (p_bininfo == NULL) {
debug_err("null p_bininfo\r\n");
return -1;
}
p_bininfo->comm.Resv[5] = uiFwBuf; // COMM_FW_UPD_ADDR
p_bininfo->comm.Resv[6] = uiFwBufSize; // COMM_FW_UPD_LEN
debug_msg_var("upd_src_addr=", uiFwBuf);
debug_msg_var("upd_src_size=", uiFwBufSize);
}
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg(p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
//check loader addr is matched with loader self.
extern char _loader_exec_compres_start[];
if (p_dram_partition->loader_addr != (UINT32)_loader_exec_compres_start) {
debug_msg_var("p_dram_partition->loader_addr", p_dram_partition->loader_addr);
debug_msg_var("_loader_exec_compres_start", (UINT32)_loader_exec_compres_start);
bl_displayErrMsg("loader addr is not match.");
}
//when rtos boot from flash, the boot from loader directly,
//but when rtos need to burn image, the uboot is still required.
//so, any one need to burn image, uboot is always needed to boot.
//if ((uiLoaderFunc & FUNC_UPDATE_FW) || p_dram_partition->rtos_addr == 0) {
if (1) {
// always use uboot to handle all-in-one bin
if (p_dram_partition->nuttx_size == 0 && p_dram_partition->teeos_size == 0) {
// load uboot
er = bl_load_uboot_from_all_in_one((unsigned char *)p_dram_partition->fdt_addr, (unsigned char *)uiFwBuf, uiFwBufSize);
if (er == -2) { // try to load from nand
debug_msg("uboot from flash.\r\n");
// open flash
if (bl_flash_open() != 0) { // dont move flash open outside section, consider that T without flash device.
bl_displayErrMsg("flash open failed\r\n");
}
er = bl_load_uboot_from_flash((unsigned char *)p_dram_partition->fdt_addr, p_tmp);
if (er != 0) {
bl_displayErrMsg("load uboot failed\r\n");
}
}
er = bl_boot_uboot((unsigned char *)p_dram_partition->fdt_addr);
if (er != 0) {
bl_displayErrMsg("boot uboot failed\r\n");
}
} else if (p_dram_partition->nuttx_size) {
#if (NUTTX_SUPPORT)
// load nuttx
er = bl_load_nuttx_from_all_in_one((unsigned char *)p_dram_partition->fdt_addr, (unsigned char *)uiFwBuf, uiFwBufSize);
if (er != 0) {
bl_displayErrMsg("load nuttx failed\r\n");
}
er = bl_boot_nuttx((unsigned char *)p_dram_partition->fdt_addr);
if (er != 0) {
bl_displayErrMsg("boot nuttx failed\r\n");
}
#else
bl_displayErrMsg("NUTTX_SUPPORT disabled\r\n");
#endif
} else if (p_dram_partition->teeos_size) {
// load teeos
er = bl_load_teeos_from_all_in_one((unsigned char *)p_dram_partition->fdt_addr, (unsigned char *)uiFwBuf, uiFwBufSize);
if (er != 0) {
bl_displayErrMsg("load teeos failed\r\n");
}
// load uboot
er = bl_load_uboot_from_all_in_one((unsigned char *)p_dram_partition->fdt_addr, (unsigned char *)uiFwBuf, uiFwBufSize);
if (er != 0) {
bl_displayErrMsg("load uboot failed\r\n");
}
// boot teeos
er = bl_boot_teeos((unsigned char *)p_dram_partition->fdt_addr);
if (er != 0) {
bl_displayErrMsg("boot teeos failed\r\n");
}
}
return er;
} else {
// update rtos information
// the following is for uncompressed-rtos only, others needing uboot
SHMINFO *p_bininfo = (SHMINFO *)bl_get_fdt_cfg((const void *)p_dram_partition->fdt_addr, MODELEXT_TYPE_BIN_INFO);
if (p_bininfo == NULL) {
debug_err("null p_bininfo\r\n");
return -1;
}
*p_comp_addr = p_bininfo->comm.Resv[3]; // COMM_UITRON_COMP_ADDR
*p_comp_size = p_bininfo->comm.Resv[4]; // COMM_UITRON_COMP_LEN
*pOut_dram_partition = p_dram_partition;
return bl_load_rtos_from_all_in_one((unsigned char *)uiFwBuf, uiFwBufSize, &p_fdt);
}
}
#endif
// return uItron_fw_addr, no need to fully decode
_THUMB2 static unsigned int bl_process_rtos_only(UINT32 uiFwBuf, UINT32 uiFwBufSize, UINT32 uiLoaderFunc, UINT32 *p_comp_addr, UINT32 *p_comp_size)
{
UINT32 uItron_fw_addr;
NVTPACK_BFC_HDR *pBFC;
HEADINFO *p_headinfo;
debug_msg("\r\nbl_process_rtos_only\r\n");
pBFC = (NVTPACK_BFC_HDR *)uiFwBuf;
if (pBFC->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) {
UINT32 compressSize;
unsigned char *p_tmp = (unsigned char *)(uiFwBuf + ALIGN_CEIL(uiFwBufSize, 4));
LZ_Un_compress((UINT8 *)uiFwBuf + LDC_HEADER_SIZE, p_tmp, SIZE_PRELOAD);
p_headinfo = (HEADINFO *)(p_tmp + BIN_INFO_OFFSET_RTOS);
uItron_fw_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
#if UITRON_FW
uItron_fw_addr = p_headinfo->CodeEntry - CODE_ENTRY_OFFSET; // cliff
#endif
if ((uItron_fw_addr & 0x0000FFFF) != 0) { //cc engine's limitation
debug_err_var("rtos addr must match (&0x0000FFFF)==0", uItron_fw_addr); // but 660 allow
uItron_fw_addr = uItron_fw_addr & 0xFFFF0000;
}
compressSize = invertEndian(pBFC->uiSizeComp) + sizeof(NVTPACK_BFC_HDR);
//debug_dump_addr(tmpBuf,0x200);
debug_msg_var("F compress uItron_fw_addr", uItron_fw_addr);
// uiFwBuf has adjusted on bl_load_rtos_from_non_nvtpack()
*p_comp_addr = uiFwBuf;
*p_comp_size = compressSize;
} else {
p_headinfo = (HEADINFO *)(uiFwBuf + BIN_INFO_OFFSET_RTOS);
uItron_fw_addr = p_headinfo->CodeEntry - CODE_SECTION_OFFSET;
#if UITRON_FW
uItron_fw_addr = p_headinfo->CodeEntry - CODE_ENTRY_OFFSET; // cliff
#endif
if ((uItron_fw_addr & 0x0000FFFF) != 0) { //cc engine's limitation
debug_err_var("rtos addr must match (&0x0000FFFF)==0", uItron_fw_addr); // but 660 allow
uItron_fw_addr = uItron_fw_addr & 0xFFFF0000;
}
debug_msg_var("Normal uItron_fw_addr", uItron_fw_addr);
*p_comp_addr = 0;
*p_comp_size = 0;
}
return uItron_fw_addr;
}
#if !UPDATE_EMU_CODE && !REMOVED_FLASH
_THUMB2 static unsigned int bl_process_flash_boot(unsigned char *p_tmp, DRAM_PARTITION **pOut_dram_partition, UINT32 uiLoaderFunc, UINT32 *p_comp_addr, UINT32 *p_comp_size)
{
int er;
unsigned char *p_fdt = NULL;
DRAM_PARTITION *p_dram_partition = NULL;
// open flash
if (bl_flash_open() != 0) {
bl_displayErrMsg("flash open failed\r\n");
}
// load fdt
er = bl_load_fdt_from_flash(p_tmp, SDRAM_Start_FW, &p_fdt); // dtb size less than 32MB to be safer.
if (er != 0) {
bl_displayErrMsg("load fdt failed\r\n");
}
// update loader flag
bl_update_loader_flag(p_fdt, uiLoaderFunc);
p_dram_partition = (DRAM_PARTITION *)bl_get_fdt_cfg(p_fdt, MODELEXT_TYPE_DRAM_PARTITION);
if (p_dram_partition->teeos_size) {
// load teeos
er = bl_load_teeos_from_flash((unsigned char *)p_dram_partition->fdt_addr, p_tmp);
if (er != 0) {
bl_displayErrMsg("load teeos failed\r\n");
}
// load uboot
er = bl_load_uboot_from_flash((unsigned char *)p_dram_partition->fdt_addr, p_tmp);
if (er != 0) {
bl_displayErrMsg("load uboot failed\r\n");
}
// boot teeos
er = bl_boot_teeos((unsigned char *)p_dram_partition->fdt_addr);
if (er != 0) {
bl_displayErrMsg("boot teeos failed\r\n");
}
}
#if 1
else if (p_dram_partition->rtos_addr == 0 || DUAL_RTOS_SUPPORT || (gFastbootKeyCallBack == NULL) || (!gFastbootKeyCallBack())) {
// load uboot
er = bl_load_uboot_from_flash((unsigned char *)p_dram_partition->fdt_addr, p_tmp);
if (er != 0) {
bl_displayErrMsg("load uboot failed\r\n");
}
// boot uboot
er = bl_boot_uboot((unsigned char *)p_dram_partition->fdt_addr);
if (er != 0) {
bl_displayErrMsg("boot uboot failed\r\n");
}
}
#endif
else {
// load rtos
er = bl_load_rtos_from_flash((unsigned char *)p_dram_partition->fdt_addr, p_tmp);
if (er != 0) {
bl_displayErrMsg("load rtos failed\r\n");
}
debug_msg("sf load rtos\r\n");
}
// update compressed rtos information
SHMINFO *p_bininfo = (SHMINFO *)bl_get_fdt_cfg((unsigned char *)p_dram_partition->fdt_addr, MODELEXT_TYPE_BIN_INFO);
if (p_bininfo == NULL) {
debug_err("null p_bininfo\r\n");
return -1;
}
*p_comp_addr = p_bininfo->comm.Resv[3]; // COMM_UITRON_COMP_ADDR
*p_comp_size = p_bininfo->comm.Resv[4]; // COMM_UITRON_COMP_LEN
*pOut_dram_partition = p_dram_partition;
return p_dram_partition->rtos_addr;
}
#endif
/**
bl_process_update_loader.
Write loader will update loader binary file
@param[in] loader_addr loader in DRAM starting address
@param[in] loader_size loader code length (from loader header offset 0x24)
@return void
*/
_THUMB2 static int bl_process_update_loader(unsigned int loader_addr, unsigned int loader_size)
{
unsigned int reload_addr;
// Check boot loader read from SD card
if(is_data_area_encrypted() == 0) {
#if ((STORAGE_EXT_TYPE == STORAGE_EXT_ETH)|(STORAGE_EXT_TYPE == STORAGE_EXT_USB))
//UINT32 uiOffset;
//uiOffset = *((UINT32 *)(loader_addr + 0x80));
//if(uiOffset) {//Combo loader
// if(*(UINT32*)0xF00100F0 == 0x50210000) {
// debug_msg("combo loader 528\r\n");
// bl_checkLoader(loader_addr+uiOffset, COMBINATION_LOADER_SIZE - uiOffset); //check 528
// } else{
// debug_msg("combo loader 52X\r\n");
// bl_checkLoader(loader_addr, loader_size); //check 52x
// }
//}else
bl_checkLoader(loader_addr, loader_size);
#else
#if 0//(LOADER_TYPE == COMBINATION_528)
debug_msg("CB8\r\n");
bl_checkLoader(loader_addr + loader_size, (COMBINATION_LOADER_SIZE - loader_size));
#else //STAND_ALONE_LOADER or combination 52x loader
//debug_msg("STD\r\n");
bl_checkLoader(loader_addr, loader_size);
#endif
#endif
}
debug_msg("update loader\r\n");
// open flash
if (bl_flash_open() != 0) {
bl_displayErrMsg("flash open failed\r\n");
}
// Program loader
#if 0
#if ((STORAGE_EXT_TYPE == STORAGE_EXT_ETH)|(STORAGE_EXT_TYPE == STORAGE_EXT_USB))
UINT32 uiOffset;
uiOffset = *((UINT32 *)(loader_addr + 0x80));
if(uiOffset) //Combo loader
loader_size = COMBINATION_LOADER_SIZE;
//If single loader , it already got
#else
#if (LOADER_TYPE == STAND_ALONE_LOADER_560) || (LOADER_TYPE == STAND_ALONE_LOADER_528)
#else //Combination loader
loader_size = COMBINATION_LOADER_SIZE;
#endif
#endif
#endif
if (int_strg_obj->flash_writeSectors(StartNandBlkUpdateLoader, loader_size, (UINT8 *)loader_addr, NAND_RW_LOADER) < 0) {
bl_displayErrMsg(RWErrorMsg);
}
// Read back
reload_addr = loader_addr + loader_size;
if (int_strg_obj->flash_readSectors(StartNandBlkUpdateLoader, loader_size, (UINT8 *)reload_addr, NAND_RW_LOADER) < 0) {
bl_displayErrMsg("rd fail\r\n");
}
// Verify
if (memcmp((void *)loader_addr, (void *)reload_addr, loader_size) != 0) {
bl_displayErrMsg("verify fail\r\n");
}
return 0;
}
#if UPDATE_EMU_CODE
_THUMB2 static int bl_process_update_emu_firmware(unsigned int emu_addr, unsigned int emu_size)
{
unsigned int reload_addr;
// Check boot loader read from SD card
// bl_checkFW(emu_addr, emu_size);
debug_msg("update emu firmware size");
uart_putSystemUARTStr(Dec2HexStr(emu_size));
uart_putSystemUARTStr("\r\n");
// open flash
if (bl_flash_open() != 0) {
bl_displayErrMsg("flash open failed\r\n");
}
// Program firmware
if (int_strg_obj->flash_writeSectors(g_uiStartBlkUpdateFW, emu_size, (UINT8 *)emu_addr, NAND_RW_FIRMWARE) < 0) {
bl_displayErrMsg(RWErrorMsg);
}
// Read back
reload_addr = emu_addr + emu_size;
if (int_strg_obj->flash_readSectors(g_uiStartBlkUpdateFW, emu_size, (UINT8 *)reload_addr, NAND_RW_FIRMWARE) < 0) {
bl_displayErrMsg("rd fail\r\n");
}
// Verify
if (memcmp((void *)emu_addr, (void *)reload_addr, emu_size) != 0) {
bl_displayErrMsg("verify fail\r\n");
}
return 0;
}
#endif
_THUMB2 void bl_read_rtos_addr(UINT32 *pLoadAddr, UINT32 *pTargetAddr, UINT32 *pSize)
{
*pLoadAddr = g_rtos_load_addr;
*pTargetAddr = g_rtos_target_addr;
*pSize = g_rtos_size;
}
/**
main flow code
If there is Calibration Firmware code store in NAND, running flow as follow
O's work flow
@return fw base addr
*/
_THUMB2 UINT32 bl_mainFlow(void)
{
UINT32 uiUpdateFileLen = 0;
UINT32 uiLoaderFunc = 0;
UINT32 uiLoaderSize = 32 * 1024; // pre-assume 32KB, actual size is parsed from loader
//Show Duty calibration log
#if (_LOADER_DUTY_CALIBRATION_ == ENABLE && _LOADER_DUTY_CALIBRATION_LOG_ == ENABLE)
UINT32 uiLoaderAddress;
UINT32 uiLogSramAddress;
#endif
#if !(USB_WRITELOADER || UART_UPDATE)
unsigned int adjusted_addr = 0;
unsigned int adjusted_size = 0;
#endif
UINT32 uiFwBaseAddr = SDRAM_Start_FW; // FW base address
DRAM_PARTITION *p_dram_partition = NULL;
// BaseOfStack is initialized at doRemapLZ.s
UINT32 uiheapBufferAddr = (UINT32)_loader_heap_base;
// UINT32 uiheapBufferAddr = BaseOfStack + 0x40000; // reserve 16KB for tmp buffer usage
UINT32 uiTmpBufferAddr = uiheapBufferAddr + FAT_HEAP_BUFFER_SIZE;
UINT32 uiUpdateBootloaderBufAddr = uiTmpBufferAddr + 0x4000;
UINT32 uiUpdateMainBinBufAddr = SDRAM_Start_FW;
// UART initial sequence
//uart_openSystemUART();
// rtc reset shutdown timer
// rtc_resetShutDownTimer();
#if 0
// adjust PAD driving (if required)
bl_adjustDriving();
/*
- @b RTC_PWR_SW_STS: Power on source is PWR_SW
- @b RTC_PWR_VBAT_STS: Power on source is PWR_VBAT
- @b RTC_PWR_VBUS_STS: Power on source is PWR_VBUS
*/
uiPowerOnSrc = rtc_getPWRONSource();
if (uiPowerOnSrc & RTC_PWR_SW_STS) {
uart_putSystemUARTStr("\r\nSW PON\r\n");
} else if (uiPowerOnSrc & RTC_PWR_VBAT_STS) {
uart_putSystemUARTStr("\r\nVBAT PON\r\n");
} else if (uiPowerOnSrc & RTC_PWR_VBUS_STS) {
uart_putSystemUARTStr("\r\nVBUS PON\r\n");
} else if (rtc_getIsAlarmPowerOn()) {
uart_putSystemUARTStr("\r\nPwrAlarm PON\r\n");
} else {
uart_putSystemUARTStr("\r\nPOR PON\r\n");
}
#endif
// Display Loader Version
debug_msg((char *)LOADER_START_STR);
UTL_setDrvTmpBufferAddress(uiTmpBufferAddr);
#if 0 // for now, reduce code size
if (rtc_chkS3boot()) {
UINT32 resume_addr;
uart_putSystemUARTStr("main selfing..\r\n");
resume_addr = bl_resume_cpu1((unsigned char *)_BOARD_IPC_ADDR_);
if (resume_addr == 0) {
// in codition for MODELEXT_BUILT_IN_ON
resume_addr = RESUME_ADDR;
}
return resume_addr;
} else {
uart_putSystemUARTStr("main not selfing..\r\n");
}
#endif
#if 0
// Sample to hook spi flash extending function
flash_installIdentifyCB(bl_spiIdentify);
#endif
prj_main();
#if !(USB_WRITELOADER)
set_usb_suspend();
#endif
if(utl_get_bootsrc() == BOOT_SOURCE_UART)
{
#if UART_UPDATE
debug_msg("Boot from UART ...\r\n");
bl_uart();//never returned.
#else
bl_displayErrMsg("UART_UPDATE must enable on loader\r\n");
#endif
}
if(USB_WRITELOADER || utl_get_bootsrc() == BOOT_SOURCE_USB)
{
#if USB_WRITELOADER
debug_msg("Boot from USB ...\r\n");
bl_usb(); //never returned.
#else
bl_displayErrMsg("USB_WRITELOADER must enable on loader\r\n");
#endif
}
#if !(USB_WRITELOADER || UART_UPDATE)
if (bl_load_rtos_from_uart(uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH, &adjusted_addr, &adjusted_size) == 0) {
//specail case, load small rtos from uart
uiUpdateMainBinBufAddr = adjusted_addr;
uiUpdateFileLen = adjusted_size;
uiLoaderFunc |= FUNC_RUN_CARD;
} else if ((int_strg_obj->flash_getBlockSize() == EMMC_BLOCK_SIZE) && gRecoveryTriggerCallBack && gRecoveryTriggerCallBack()) {
debug_msg("Recovery triggered not support currently.\r\n");
#if 0
// open flash
if (bl_flash_open() != 0) {
bl_displayErrMsg("flash open failed\r\n");
} else {
flash_mount_fs(0, BaseOfStack + 0x4000, FAT_HEAP_BUFFER_SIZE);
if (flash_mount_partition(g_uiPartitionID) == E_OK) {
if (flash_open_file(RECOVERY_FW_NAME) == TRUE) {
NVTPACK_MEM mem_in ;
flash_read_file((UINT8 *)uiUpdateMainBinBufAddr, SIZE_PRELOAD);
mem_in.p_data = (void *)uiUpdateMainBinBufAddr;
mem_in.len = uiUpdateFileLen;
// all in one bin
if (bl_chk_valid_all_in_one(&mem_in) == 0) {
// Read all
uiUpdateFileLen = flash_read_file((UINT8 *)uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
uiLoaderFunc |= FUNC_UPDATE_FW;
g_is_recovery_triggered = TRUE;
} else {
debug_msg("Recovery should be all in one bin!\r\n");
}
} else {
debug_msg("no recovery bin!\r\n");
}
} else {
debug_msg("Partition error!\r\n");
}
}
#endif
}
#if 1
else if ((gSpecialKeyCallBack()) && (gCardDetectCallBack())) {
if (card_open() == TRUE && fat_initFAT(uiheapBufferAddr, FAT_HEAP_BUFFER_SIZE) == TRUE) {
#if UPDATE_SIM_CODE
BOOL bWDTInit = UTL_canUpdateSecKey();
if (bWDTInit && fat_open_rootfile(RUN_WRKEY_NAME) == TRUE) {
debug_msg("sim.bin exist\r\n"); // the others A or T are skipped.
// Read byte count specified in file directory entry
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
uiLoaderFunc |= FUNC_RUN_WRBIN;
} else { // exclude others update if FUNC_RUN_WRBIN is existing.
#endif
// Update loader or not, loader is fixed to 16 KB
if (fat_open_rootfile(UPDATE_LOADER_NAME) == TRUE) {
// Read byte count specified in file directory entry
fat_read_rootfile((UINT8 *)uiUpdateBootloaderBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
uiLoaderFunc |= FUNC_UPDATE_LOADER;
uiLoaderSize = *((UINT32 *)(uiUpdateBootloaderBufAddr + 0x24));
}
// "Update FW" or "Run FW" function
// Update FW has higher priority
if (fat_open_rootfile(UPDATE_FW_NAME) == TRUE) {
NVTPACK_MEM mem_in ;
fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, SIZE_PRELOAD);
mem_in.p_data = (void *)uiUpdateMainBinBufAddr;
mem_in.len = uiUpdateFileLen;
// all in one bin
if (bl_chk_valid_all_in_one(&mem_in) == 0) {
// Read all
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
uiLoaderFunc |= FUNC_UPDATE_FW;
} else {
// only rtos
debug_msg("not all-in-one, force behavior as T bin.\r\n");
adjusted_addr = 0;
adjusted_size = 0;
if (bl_load_rtos_from_non_nvtpack(uiUpdateMainBinBufAddr, uiUpdateFileLen, &adjusted_addr, &adjusted_size) == 0) {
uiFwBaseAddr = adjusted_addr; //fix compressed fit bl_checkDramScanFW() after copy its to temp area, see commit log
uiUpdateFileLen = adjusted_size;
} else {
bl_displayErrMsg("invalid firmware");
}
#if UPDATE_EMU_CODE
uiLoaderFunc |= FUNC_UPDATE_FW;
#else
uiLoaderFunc |= FUNC_RUN_CARD;
#endif
}
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
}
// Run FW has lower priority
else if (fat_open_rootfile(RUN_FW_NAME) == TRUE) {
NVTPACK_MEM mem_in ;
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, SIZE_PRELOAD);
mem_in.p_data = (void *)uiUpdateMainBinBufAddr;
mem_in.len = uiUpdateFileLen;
if (bl_chk_valid_all_in_one(&mem_in) == 0) {
// Read all
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
} else {
// Read rtos
unsigned int adjusted_addr = 0;
unsigned int adjusted_size = 0;
if (bl_load_rtos_from_non_nvtpack(uiUpdateMainBinBufAddr, uiUpdateFileLen, &adjusted_addr, &adjusted_size) != 0) {
bl_displayErrMsg("invalid firmware");
} else {
uiFwBaseAddr = adjusted_addr; //fix compressed fit bl_checkDramScanFW() after copy its to temp area, see commit log
uiUpdateFileLen = adjusted_size;
}
uiLoaderFunc |= FUNC_RUN_CARD;
}
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
uiLoaderFunc |= FUNC_RUN_CARD;
}
#if UPDATE_SIM_CODE
}
#endif
debug_msg("card close\r\n");
card_close();
} else {
debug_msg("card open fail\r\n");
// while (1);
}
}
#endif
#if 0
else if (((gCardDetectCallBack == NULL) || gCardDetectCallBack()))
{
debug_msg("sf gCardDetectCallBack gCardDetectCallBack\r\n");
if (card_open() == TRUE && fat_initFAT(uiheapBufferAddr, FAT_HEAP_BUFFER_SIZE) == TRUE) {
#if UPDATE_SIM_CODE
BOOL bWDTInit = UTL_canUpdateSecKey();
if (bWDTInit && fat_open_rootfile(RUN_WRKEY_NAME) == TRUE) {
debug_msg("sim.bin exist\r\n"); // the others A or T are skipped.
// Read byte count specified in file directory entry
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
uiLoaderFunc |= FUNC_RUN_WRBIN;
} else { // exclude others update if FUNC_RUN_WRBIN is existing.
#endif
// Update loader or not, loader is fixed to 16 KB
if (fat_open_rootfile(UPDATE_LOADER_NAME) == TRUE) {
// Read byte count specified in file directory entry
fat_read_rootfile((UINT8 *)uiUpdateBootloaderBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
debug_msg("sf ld\r\n"); // for line end RRRRRRR....
uiLoaderFunc |= FUNC_UPDATE_LOADER;
uiLoaderSize = *((UINT32 *)(uiUpdateBootloaderBufAddr + 0x24));
}
// "Update FW" or "Run FW" function
// Update FW has higher priority
if (fat_open_rootfile(UPDATE_FW_NAME) == TRUE) {
NVTPACK_MEM mem_in ;
fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, SIZE_PRELOAD);
mem_in.p_data = (void *)uiUpdateMainBinBufAddr;
mem_in.len = uiUpdateFileLen;
// all in one bin
debug_msg("sf fw\r\n"); // for line end RRRRRRR....
if (bl_chk_valid_all_in_one(&mem_in) == 0) {
// Read all
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
uiLoaderFunc |= FUNC_UPDATE_FW;
} else {
// only rtos
debug_msg("not all-in-one, force behavior as T bin.\r\n");
adjusted_addr = 0;
adjusted_size = 0;
if (bl_load_rtos_from_non_nvtpack(uiUpdateMainBinBufAddr, uiUpdateFileLen, &adjusted_addr, &adjusted_size) == 0) {
uiFwBaseAddr = adjusted_addr; //fix compressed fit bl_checkDramScanFW() after copy its to temp area, see commit log
uiUpdateFileLen = adjusted_size;
} else {
bl_displayErrMsg("invalid firmware");
}
#if UPDATE_EMU_CODE
uiLoaderFunc |= FUNC_UPDATE_FW;
#else
uiLoaderFunc |= FUNC_RUN_CARD;
#endif
}
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
}
// Run FW has lower priority
else if (fat_open_rootfile(RUN_FW_NAME) == TRUE) {
NVTPACK_MEM mem_in ;
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, SIZE_PRELOAD);
mem_in.p_data = (void *)uiUpdateMainBinBufAddr;
mem_in.len = uiUpdateFileLen;
if (bl_chk_valid_all_in_one(&mem_in) == 0) {
// Read all
uiUpdateFileLen = fat_read_rootfile((UINT8 *)uiUpdateMainBinBufAddr, FAT_READ_TOTAL_FILE_LENGTH);
} else {
// Read rtos
unsigned int adjusted_addr = 0;
unsigned int adjusted_size = 0;
if (bl_load_rtos_from_non_nvtpack(uiUpdateMainBinBufAddr, uiUpdateFileLen, &adjusted_addr, &adjusted_size) != 0) {
bl_displayErrMsg("invalid firmware");
} else {
uiFwBaseAddr = adjusted_addr; //fix compressed fit bl_checkDramScanFW() after copy its to temp area, see commit log
uiUpdateFileLen = adjusted_size;
}
uiLoaderFunc |= FUNC_RUN_CARD;
}
fat_close_rootfile();
debug_msg("\r\n"); // for line end RRRRRRR....
uiLoaderFunc |= FUNC_RUN_CARD;
}
#if UPDATE_SIM_CODE
}
#endif
card_close();
} else {
debug_msg("card open fail\r\n");
// while (1);
}
}
#endif
else if (((gSpecialKeyCallBack == NULL) || gSpecialKeyCallBack()) &&
((gCardDetectCallBack != NULL) || (gCardDetectCallBack() == FALSE))) {
debug_msg("No card inserted\r\n");
}
#endif
if (uiLoaderFunc & FUNC_UPDATE_LOADER) {
bl_process_update_loader(uiUpdateBootloaderBufAddr, uiLoaderSize);
}
// Run FW
UINT32 comp_addr = 0;
UINT32 comp_size = 0;
if (uiLoaderFunc & (FUNC_RUN_CARD | FUNC_UPDATE_FW)) {
debug_msg("RC\r\n");
NVTPACK_MEM mem_in ;
int chk_valid_all_in_one;
#if (DRAM_RANGE_SCAN_EN == ENABLE)
// First word is code entry point address, once if entry address is 0xC000XXXX
// represent code is running on sram.
debug_msg("Check SRAM fw\r\n");
if (bl_checkDramScanFW(uiUpdateMainBinBufAddr) == TRUE) {
debug_msg("This fw is on SRAM\r\n");
// Enable sram usage
SETREG32(0xF0900128, 0x00000002);
SETREG32(0xF0800128, 0x00000006);
SETREG32(0xF0020060, 0x00030002);
debug_msg(Dec2HexStr(*((UINT32 *)SRAM_Start_FW)));
debug_msg("before jump\r\n");
// while (b_debug_go == FALSE);
load_dram_scan(uiUpdateMainBinBufAddr, uiUpdateFileLen);
return *((UINT32 *)SRAM_Start_FW);
}
#endif
mem_in.p_data = (void *)uiUpdateMainBinBufAddr;
mem_in.len = uiUpdateFileLen;
chk_valid_all_in_one = bl_chk_valid_all_in_one(&mem_in);
if (chk_valid_all_in_one == 0) {
// all-in-one flow
// File len got from fat_read_rootfile() may exceed actual file size.
// In such condition, we should use info in NVTPACK_FW_HDR2
if (((NVTPACK_FW_HDR2 *)uiUpdateMainBinBufAddr)->TotalSize < uiUpdateFileLen) {
uiUpdateFileLen = ((NVTPACK_FW_HDR2 *)uiUpdateMainBinBufAddr)->TotalSize;
mem_in.len = uiUpdateFileLen;
}
#if (REMOVED_FLASH == ENABLE)
bl_displayErrMsg("cannot process all-in-one fw");
#else
uiFwBaseAddr = bl_process_all_in_one(uiUpdateMainBinBufAddr, uiUpdateFileLen, &p_dram_partition, uiLoaderFunc, &comp_addr, &comp_size);
#endif
} else {
// non-all-in-one flow
// check valid
if (uiLoaderFunc & FUNC_UPDATE_FW) {
#if UPDATE_EMU_CODE
bl_process_update_emu_firmware(uiUpdateMainBinBufAddr, uiUpdateFileLen);
#else
bl_displayErrMsg("cannot write non-all-in-one fw");
#endif
}
uiFwBaseAddr = bl_process_rtos_only(uiUpdateMainBinBufAddr, mem_in.len, uiLoaderFunc, &comp_addr, &comp_size);
}
// here uiFwBaseAddr is ready to use.
if (comp_addr == 0) {
HEADINFO *p_headinfo = (HEADINFO *)(uiFwBaseAddr + BIN_INFO_OFFSET_RTOS);
debug_msg("Nrml\r\n");
if (chk_valid_all_in_one == 0) {
uiUpdateFileLen = p_headinfo->BinLength;
uiUpdateMainBinBufAddr = uiFwBaseAddr;
} else {
// uiUpdateFileLen is already set when file is loaded
}
} else {
debug_msg("Fcompress\r\n");
//for speed up, u-boot only copy compressed rtos and loader needs to decode it
uiUpdateFileLen = bl_decompress_rtos(comp_addr, comp_size, uiFwBaseAddr);
uiUpdateMainBinBufAddr = uiFwBaseAddr;
}
debug_msg_var("uiUpdateFileLen", uiUpdateFileLen);
//boot from flash or update fw is no need to check sanity because of ecc, turn on it just for debug
if (uiLoaderFunc & FUNC_RUN_CARD) {
bl_checkFW(uiUpdateMainBinBufAddr, uiUpdateFileLen);
}
if (chk_valid_all_in_one == 0) {
bl_update_uItron_headInfo(uiFwBaseAddr, p_dram_partition);
} else {
debug_msg_var("fw load addr", uiUpdateMainBinBufAddr);
bl_update_uItron_headInfo(uiUpdateMainBinBufAddr, p_dram_partition);
}
} else { //boot from flash
#if (REMOVED_FLASH == DISABLE)
#if UPDATE_EMU_CODE
// UINT32 uiNandBlkSize;
// open flash
if (bl_flash_open() != 0) {
bl_displayErrMsg("flash open failed\r\n");
}
debug_msg("RFlash\r\n");
if (int_strg_obj->flash_readSectors(g_uiStartBlkUpdateFW, g_uiNandBlkSize, (UINT8 *)SDRAM_Start_FW, NAND_RW_FIRMWARE) < 0) {
bl_displayErrMsg(RWErrorMsg);
}
uiUpdateFileLen = *(volatile UINT32 *)(SDRAM_Start_FW + 0x168);
if (int_strg_obj->flash_readSectors(g_uiStartBlkUpdateFW + 1, uiUpdateFileLen - g_uiNandBlkSize, (UINT8 *)(SDRAM_Start_FW + g_uiNandBlkSize), NAND_RW_FIRMWARE) < 0) {
bl_displayErrMsg(RWErrorMsg);
}
uiFwBaseAddr = bl_process_rtos_only(SDRAM_Start_FW, uiUpdateFileLen, uiLoaderFunc, &comp_addr, &comp_size);
bl_checkFW(SDRAM_Start_FW, uiUpdateFileLen);
uiUpdateMainBinBufAddr = SDRAM_Start_FW;
if (comp_addr == 0) {
debug_msg("Nrml\r\n");
} else {
debug_msg("Fcompress not support\r\n");
}
#else
uiFwBaseAddr = bl_process_flash_boot((UINT8 *)SDRAM_Start_FW, &p_dram_partition, uiLoaderFunc, &comp_addr, &comp_size);
if (comp_addr == 0) {
uiUpdateMainBinBufAddr = uiFwBaseAddr;
} else {
//for speed up, u-boot only copy compressed rtos and loader needs to decode it
uiUpdateFileLen = bl_decompress_rtos(comp_addr, comp_size, uiFwBaseAddr);
uiUpdateMainBinBufAddr = uiFwBaseAddr;
}
// no need to bl_checkFW, because check sanity in flash_read
bl_update_uItron_headInfo(uiFwBaseAddr, p_dram_partition);
#endif
#endif
}
if (p_dram_partition) {
bl_update_loader_bininfo((unsigned char *)p_dram_partition->fdt_addr, uiLoaderFunc, uiUpdateFileLen);
}
#if UPDATE_EMU_CODE
debug_msg_var("emu fw len", uiUpdateFileLen);
#endif
g_rtos_load_addr = uiUpdateMainBinBufAddr;
g_rtos_target_addr = uiFwBaseAddr;
g_rtos_size = uiUpdateFileLen;
//invalid Instruciton and data cache
CPUCleanInvalidateDCacheAll();
CPUInvalidateICacheAll();
debug_msg_var("rtos start", uiFwBaseAddr);
return uiFwBaseAddr;
}
_THUMB2 void loader_setUpdateFwName(char *fileName)
{
strncpy((char *)UPDATE_FW_NAME, fileName, sizeof(UPDATE_FW_NAME));
}
_THUMB2 void loader_setUpdateLdrName(char *fileName)
{
strncpy((char *)UPDATE_LOADER_NAME, fileName, sizeof(UPDATE_LOADER_NAME));
}
_THUMB2 void loader_setRunFwName(char *fileName)
{
strncpy((char *)RUN_FW_NAME, fileName, sizeof(RUN_FW_NAME));
}
_THUMB2 void loader_setRecoveryFwName(char *fileName)
{
strncpy((char *)RECOVERY_FW_NAME, fileName, sizeof(RECOVERY_FW_NAME));
}
_THUMB2 void loader_setRecoveryPartitionID(UINT32 partition_id)
{
g_uiPartitionID = partition_id;
}
_THUMB2 void loader_setVersion(UINT32 version)
{
g_uiVersion = version;
}
_THUMB2 void loader_installSpecialKeyCB(LDR_SPECIAL_KEY_CB callback)
{
gSpecialKeyCallBack = callback;
}
_THUMB2 void loader_installCardDetectCB(LDR_CARD_DETECT_CB callback)
{
gCardDetectCallBack = callback;
}
_THUMB2 void loader_installRecoveryTriggerCB(LDR_RECOVERY_TRIGGER_CB callback)
{
gRecoveryTriggerCallBack = callback;
}
_THUMB2 void loader_installFastbootKeyCB(LDR_FASTBOOT_KEY_CB callback)
{
gFastbootKeyCallBack = callback;
}
_THUMB2 void loader_setStorageIntType(STORAGEINT type, PSTORAGE_OBJ strg_obj)
{
gStorageIntType = type;
int_strg_obj = strg_obj;
}