Files
6CAR/middleware/sd_boot_img/sd_boot_img.c
2026-04-18 09:16:58 +08:00

405 lines
13 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;
}