405 lines
14 KiB
C
405 lines
14 KiB
C
/**
|
|
* @file sd_boot_img.c
|
|
*
|
|
* Copyright (c) 2021 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*
|
|
* Description: some rom defined data formate is listed here
|
|
*
|
|
* Revision History:
|
|
* -----------------
|
|
*/
|
|
|
|
#include <board.h>
|
|
#include <ctype.h>
|
|
#include <debug.h>
|
|
#include <param.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <types.h>
|
|
#include <debug.h>
|
|
#include "sd_boot_img.h"
|
|
|
|
#define ERROR(format, args...) \
|
|
ssdk_printf(SSDK_CRIT, "[ERROR]SD_BOOT_IMG:%s %d " format "", __func__, \
|
|
__LINE__, ##args);
|
|
#define DBG(format, args...) \
|
|
ssdk_printf(SSDK_CRIT, "[DEBUG]SD_BOOT_IMG:%s %d " format "", __func__, \
|
|
__LINE__, ##args);
|
|
|
|
/** CRC table for the CRC-32. The poly isPoly : 0x04C11DB7 */
|
|
static unsigned int crc32_table_sfs[256] = {
|
|
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
|
|
0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
|
|
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7,
|
|
0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
|
|
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3,
|
|
0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
|
|
0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF,
|
|
0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
|
|
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB,
|
|
0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
|
|
0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
|
|
0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
|
|
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4,
|
|
0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
|
|
0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08,
|
|
0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
|
|
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC,
|
|
0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
|
|
0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050,
|
|
0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
|
|
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
|
|
0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
|
|
0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1,
|
|
0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
|
|
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5,
|
|
0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
|
|
0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9,
|
|
0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
|
|
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD,
|
|
0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
|
|
0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
|
|
0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
|
|
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2,
|
|
0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
|
|
0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E,
|
|
0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
|
|
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A,
|
|
0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
|
|
0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676,
|
|
0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
|
|
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
|
|
0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
|
|
0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4};
|
|
|
|
#ifdef DUMP_TABLE
|
|
/**
|
|
* @brief Claculation sfs crc32
|
|
*/
|
|
static void cal_sfs_crc32_tbl(void)
|
|
{
|
|
unsigned int i = 0;
|
|
unsigned int k = 0;
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
unsigned int nVal = (i << 24);
|
|
|
|
for (k = 0; k < 8; ++k) {
|
|
if (0 != (nVal & 0x80000000UL)) {
|
|
nVal <<= 1;
|
|
nVal ^= 0x04C11DB7;
|
|
} else {
|
|
nVal <<= 1;
|
|
}
|
|
|
|
crc32_table_sfs[i] = nVal;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Sfs's crs calculation
|
|
* @param crc
|
|
* @param buffer
|
|
* @param len
|
|
* @return unsigned int
|
|
*/
|
|
uint32_t sfs_crc32(uint32_t crc, uint8_t *buffer, uint32_t len)
|
|
{
|
|
#ifdef DUMP_TABLE
|
|
unsigned int i = 0;
|
|
cal_sfs_crc32_tbl();
|
|
|
|
for (; i < 256; i += 4) {
|
|
printf("0x%08X, 0x%08X, 0x%08X, 0x%08X,\n", crc32_table_sfs[i],
|
|
crc32_table_sfs[i + 1], crc32_table_sfs[i + 2],
|
|
crc32_table_sfs[i + 3]);
|
|
}
|
|
|
|
#endif
|
|
crc ^= 0xFFFFFFFFUL;
|
|
|
|
while (len--)
|
|
crc = ((crc << 8) & 0xFFFFFF00UL) ^
|
|
crc32_table_sfs[((crc >> 24) & 0xFFUL) ^ (*buffer++)];
|
|
|
|
return crc ^ 0xFFFFFFFFUL;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the sfs information
|
|
* @param sfs inst
|
|
* @param buffer data buffer
|
|
* @param len data buffer length
|
|
* @return int32_t
|
|
*/
|
|
int32_t get_sfs_info(struct sfs *sfs, uint8_t *buffer, uint32_t len)
|
|
{
|
|
uint8_t *temp = buffer;
|
|
uint32_t crc_val = 0;
|
|
uint32_t crc_orig = 0;
|
|
|
|
if (!sfs || !buffer) {
|
|
ERROR("sfs buffer is null\n");
|
|
return 1;
|
|
}
|
|
|
|
if (len < SFS_SIZE) {
|
|
ERROR("sfs size error\n");
|
|
return 2;
|
|
}
|
|
|
|
if (*(uint32_t *)temp != SFS_TAG) {
|
|
ERROR("sfs tag error\n");
|
|
return 3;
|
|
}
|
|
|
|
crc_orig = GET_LWORD_FROM_BYTE(&buffer[SFS_CRC32_OFFSET]);
|
|
crc_val = sfs_crc32(0, buffer, SFS_SIZE - 4);
|
|
|
|
if (crc_val != crc_orig) {
|
|
DBG("sfs crc_orig:0x%0x crc_val:0x%0x!\n", crc_orig, crc_val);
|
|
}
|
|
|
|
sfs->tag = *(uint32_t *)(temp + SFS_TAG_OFFSET);
|
|
sfs->freq = *(temp + SFS_FREQ_OFFSET);
|
|
sfs->normal_img_base = *(uint32_t *)(temp + SFS_NIA_OFFSET);
|
|
sfs->backup_img_base = *(uint32_t *)(temp + SFS_BIA_OFFSET);
|
|
sfs->third_img_base = *(uint32_t *)(temp + SFS_TIA_OFFSET);
|
|
sfs->sw_reset_info = *(uint8_t *)(temp + SFS_SW_RESET);
|
|
sfs->crc32 = *(uint32_t *)(temp + SFS_CRC32_OFFSET);
|
|
|
|
memcpy(sfs->init_act, temp + SFS_INIT_ACT_OFFSET, SFS_INIT_ACT_SIZE);
|
|
memcpy(sfs->xfer_config, temp + SFS_XFER_CONFIG_OFFSET,
|
|
SFS_XFER_CONFIG_SIZE);
|
|
memcpy(sfs->ospi_settings, temp + SFS_IP_SETTINGS_OFFSET,
|
|
SFS_IP_SETTINGS_SIZE);
|
|
memcpy(sfs->training_pattern, temp + SFS_TP_OFFSET, SFS_TP_SIZE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the bpt info of boot package
|
|
* @param bpt
|
|
* @param buffer
|
|
* @param len
|
|
* @return int32_t
|
|
*/
|
|
int32_t get_bpt_info(struct bpt *bpt, uint8_t *buffer, uint32_t len)
|
|
{
|
|
uint8_t *temp = buffer;
|
|
struct iib *iib = NULL;
|
|
struct rcp *rcp = NULL;
|
|
uint8_t i = 0;
|
|
|
|
if (!bpt || !buffer) {
|
|
ERROR("bpt/buffer is null\n");
|
|
return 1;
|
|
}
|
|
|
|
if (len < BPT_SIZE) {
|
|
ERROR("bpt size error! size:%d\n", len);
|
|
return 1;
|
|
}
|
|
|
|
if (*(uint32_t *)temp != BPT_TAG) {
|
|
ERROR("bpt tag error!\n");
|
|
return 1;
|
|
}
|
|
|
|
bpt->tag = *(uint32_t *)(temp + BPT_TAG_OFFSET);
|
|
bpt->size = *(uint16_t *)(temp + BPT_SIZE_OFFSET);
|
|
|
|
if (bpt->size != BPT_SIZE) {
|
|
ERROR("bpt size error!\n");
|
|
return 1;
|
|
}
|
|
|
|
bpt->sec_version = *(uint32_t *)(temp + BPT_SEC_VER_OFFSET);
|
|
bpt->hash_alg = *(temp + BPT_MDA_OFFSET);
|
|
bpt->crc32 = *(uint32_t *)(temp + BPT_CRC32_OFFSET);
|
|
bpt->pac_serial_num = *(uint32_t *)(temp + BPT_PSN_OFFSET);
|
|
bpt->inver_pac_serial_num = *(uint32_t *)(temp + BPT_IPSN_OFFSET);
|
|
memcpy(bpt->signature, temp + BPT_SIG_OFFSET, BPT_SIG_SIZE);
|
|
|
|
temp = buffer + BPT_IIB_OFFSET;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
iib = &bpt->iib[i];
|
|
iib->tag = *(uint16_t *)(temp + IIB_TAG_OFFSET);
|
|
|
|
if ((iib->tag != IIB_TAG)) {
|
|
if (0 == i) {
|
|
ERROR("iib tag error!\n");
|
|
break;
|
|
} else {
|
|
// DBG("iib[%d] is none\n", i);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
iib->size = *(uint16_t *)(temp + IIB_SIZE_OFFSET);
|
|
iib->image_type = *(uint8_t *)(temp + IIB_IMG_TYPE_OFFSET);
|
|
iib->target_core = *(uint8_t *)(temp + IIB_TG_CORE_OFFSET);
|
|
iib->decryp_ctl = *(uint8_t *)(temp + IIB_DCB_OFFSET);
|
|
iib->dev_logic_page = *(uint32_t *)(temp + IIB_DLP_OFFSET);
|
|
iib->image_size = *(uint32_t *)(temp + IIB_IMG_SZ_OFFSET);
|
|
iib->load_base = *(uint32_t *)(temp + IIB_LOAD_BASE_OFFSET);
|
|
iib->entry_point = *(uint32_t *)(temp + IIB_EP_OFFSET);
|
|
|
|
memcpy(iib->dcc, temp + IIB_DCC_OFFSET, IIB_DCC_OFFSET);
|
|
memcpy(iib->did, temp + IIB_DID_OFFSET, IIB_DID_SIZE);
|
|
memcpy(iib->initial_vec, temp + IIB_IV_OFFSET, IIB_IV_SIZE);
|
|
memcpy(iib->hash, temp + IIB_HASH_OFFSET, IIB_HASH_SIZE);
|
|
|
|
temp = temp + IIB_SIZE;
|
|
}
|
|
|
|
temp = buffer + BPT_RCP_OFFSET;
|
|
rcp = &bpt->rcp;
|
|
rcp->tag = *(uint16_t *)(temp + RCP_TAG_OFFSET);
|
|
|
|
if (rcp->tag != RCP_TAG) {
|
|
ERROR("rcp tag error!\n");
|
|
}
|
|
|
|
rcp->size = *(uint16_t *)(temp + RCP_SIZE_OFFSET);
|
|
|
|
if (rcp->size != RCP_SIZE) {
|
|
ERROR("rcp size error:%d\n", rcp->size);
|
|
}
|
|
|
|
rcp->id = *(temp + RCP_ID_OFFSET);
|
|
rcp->pk_type = *(temp + RCP_PKT_OFFSET);
|
|
memcpy(rcp->pk, temp + RCP_PK_OFFSET, RCP_PK_SIZE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Check whether a RFD region is valid, and if the RFD region is valid,
|
|
* the corresponding bit is set
|
|
* @param xspi_base xspi base addr
|
|
* @param rfd_valid_mask output parameter for rfd:
|
|
* bit0 = 1 means rfd region 0 is valid, 0 is invalid
|
|
* bit1 = 1 means rfd region 1 is valid, 0 is invalid
|
|
* bit2 = 1 means rfd region 2 is valid, 0 is invalid
|
|
* bit3 = 1 means rfd region 3 is valid, 0 is invalid
|
|
* @return 0 is success, 1 is error
|
|
*/
|
|
int32_t check_rfd(uint32_t xspi_base, uint8_t *rfd_valid_mask)
|
|
{
|
|
uint8_t i = 0;
|
|
uint32_t crc32_val = 0;
|
|
uint32_t rfd_addr = 0;
|
|
|
|
if (!rfd_valid_mask) {
|
|
return 1;
|
|
}
|
|
|
|
rfd_addr = xspi_base + RFD_OFFSET;
|
|
*rfd_valid_mask = 0;
|
|
|
|
for (i = 0; i < RFD_REGION_NUM; i++) {
|
|
crc32_val = sfs_crc32(0, (uint8_t *)(rfd_addr + RFD_CRC_SIZE + i * RFD_REGION_SIZE),
|
|
RFD_REGION_SIZE);
|
|
if(crc32_val == *(uint32_t *)(rfd_addr + i * sizeof(uint32_t))) {
|
|
*rfd_valid_mask |= (1UL << i);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool is_msfs_data(const void *data)
|
|
{
|
|
msfs_t *msfs;
|
|
if(data) {
|
|
msfs = (msfs_t *)(data);
|
|
if((msfs->magic == MSFS_MAGIC) && (msfs->count != 0)
|
|
&& (msfs->count <= MULTI_SFS_MAX_CNT)) {
|
|
DBG("The image is multi-sfs image!\n");
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @brief get the right sfs data form a msfs buffer
|
|
* @param flash_id the flash id
|
|
* @param data the address of data buffer pointer
|
|
* @param sz the address of data buffer size
|
|
* @param crc the original msfs data crc
|
|
* @return 0 is success, -1 is error
|
|
*/
|
|
int32_t get_matched_sfs(const uint8_t* flash_id, void **data, uint32_t *sz)
|
|
{
|
|
uint32_t i;
|
|
flash_seq_info_t *seq_info;
|
|
msfs_t *msfs = (msfs_t *)(*data);
|
|
uint64_t flash_id_mask = ((0x1ull << FLASH_ID_BITS_LEN) - 1);
|
|
uint64_t expect_flash_id = 0;
|
|
uint8_t *temp;
|
|
uint32_t crc_val = 0;
|
|
uint32_t crc_orig = 0;
|
|
|
|
if(!flash_id || !data || !*data || !sz) {
|
|
ERROR("get matched sfs input error\n");
|
|
return -1;
|
|
}
|
|
|
|
if(msfs->magic != MSFS_MAGIC ||
|
|
msfs->count == 0 ||
|
|
msfs->count > MULTI_SFS_MAX_CNT ) {
|
|
DBG("The msfs image magic or count error!\n");
|
|
return -1;
|
|
}
|
|
|
|
DBG("The sfs image is multi-sfs image!\n");
|
|
memcpy((uint8_t*)&expect_flash_id, flash_id, FLASH_ID_BYTE_LEN);
|
|
|
|
seq_info = (flash_seq_info_t *)((uint8_t *)msfs + msfs->offset);
|
|
|
|
for (i = 0; i < msfs->count; i++, seq_info++) {
|
|
DBG("flash_id:0x%0llx seq id:0x%0llx!\n", expect_flash_id, seq_info->flash_id);
|
|
|
|
if (!((expect_flash_id ^ seq_info->flash_id) & flash_id_mask)) {
|
|
*data = (uint8_t *)msfs + seq_info->offset;
|
|
*sz = seq_info->size;
|
|
DBG("matched, flash_id:0x%0llx seq id:0x%0llx mask:0x%0llx!\n",
|
|
expect_flash_id, seq_info->flash_id, flash_id_mask);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == msfs->count) {
|
|
ERROR("No matched sfs, flash_id:0x%0llx!\n", flash_id);
|
|
return -1;
|
|
}
|
|
|
|
if (*sz != SFS_SIZE) {
|
|
ERROR("the sfs from msfs size error, sz= %d\n", *sz);
|
|
return -1;
|
|
}
|
|
|
|
temp = (uint8_t *)*data;
|
|
if (*(uint32_t *)temp != SFS_TAG) {
|
|
ERROR("the sfs from msfs tag error\n");
|
|
return -1;
|
|
}
|
|
|
|
crc_orig = GET_LWORD_FROM_BYTE(&temp[SFS_CRC32_OFFSET]);
|
|
crc_val = sfs_crc32(0, temp, SFS_SIZE - 4);
|
|
|
|
if (crc_val != crc_orig) {
|
|
ERROR("the sfs from msfs crc_orig:0x%0x crc_val:0x%0x!\n", crc_orig, crc_val);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
} |