flash upload content md5

本文介绍如何使用 AS3CoreLib 中的 MD5Stream 类来实现 Flex 应用程序的数据加密功能。通过详细的步骤说明和代码示例,帮助读者掌握 MD5Stream 的基本用法。
[url]http://ntt.cc/2008/12/29/as3corelib-tutorial-how-to-use-md5stream-class-in-flex.html[/url]
int processUboot(void) { int ret = 0; UPBOOT_INFO *upboot_info = NULL; TP_HEADER *header_up = NULL; char *base = NULL; unsigned char md5Tmp[MD5SUM_LEN] = {0}; ret = readFlash(UPBOOT_OFFSET, (uint8_t*)WEBFAILSAFE_UPLOAD_RAM_ADDRESS, sizeof(UPBOOT_INFO)); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } upboot_info = (UPBOOT_INFO *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS; if (strncmp(upboot_info->magic, UP_BOOT_MAGIC, sizeof(UP_BOOT_MAGIC))) { DBG("UPBOOT_INFO is not written, skip..."); return 0; } if (ntohl(upboot_info->reserved_block) < 2) { printf("reserved_block between upboot_info and upboot is too short\n"); return 0; } if (upboot_info->fwStatus) /* 升级时将up_boot.bin中的主要内容写入后, 该字段才会为零 */ { printf("No need to update uboot\n"); return 0; } printf("fwLen:0x%08x, fwStatus:0x%08x\n", ntohl(upboot_info->fwLen), ntohl(upboot_info->fwStatus)); printf("up_contents:0x%08x\n", ntohl(upboot_info->up_contents)); /* 固件升级时uboot不一定需要更新, nsd模块的upgrade会在将upboot写入flash之前进行检查是否改变 */ if (ntohl(upboot_info->up_contents) & CONTENT_TYPE_BOOTLOADER) { DBG("uboot need to upgrade"); base = WEBFAILSAFE_UPLOAD_RAM_ADDRESS + NAND_BLOCK_SIZE; header_up = (TP_HEADER *)(base + BOOTLOADER_LEN); /* 待升级固件的tp_header */ /* read length ubootlen + tp_header or ntohl(upboot_info->fwLen) ? */ uint32_t upboot_content_offset = UPBOOT_OFFSET + NAND_BLOCK_SIZE * ntohl(upboot_info->reserved_block); uint32_t upboot_content_length = BOOTLOADER_LEN + TP_HEADER_LEN; ret = readFlash(upboot_content_offset, (uint8_t *)base, upboot_content_length); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } memset(md5Tmp, 0, MD5SUM_LEN); calcMd5((char *)(base), (int)BOOTLOADER_LEN, (char *)md5Tmp); // debug_print_md5(md5Tmp); // debug_print_md5(header_up->ubootCRC); if (memcmp(md5Tmp, header_up->ubootCRC, MD5SUM_LEN) == 0) { printf("uboot in up_boot check ok\n"); eraseFlash(BOOTLOADER_OFFSET, TP_HEADER_OFFSET - BOOTLOADER_OFFSET); writeFlash(BOOTLOADER_OFFSET, (uint8_t *)base, BOOTLOADER_LEN); } } /* set fwStatus flag to record upgrade status */ writeUpgradeStatsToFlash(upboot_info, FW_UBOOT_UPGRADED); return 0; }
10-12
#include <common.h> #include <command.h> #include "md5.h" #include "tapo_nand_upgrade.h" #define ERR_NONE 0 #define ERR_GENERIC -1 #define ERR_RSA_CHECK_FAIL -2 #define ERR_HWID_NOT_FOUND -3 #define ERR_FWID_NOT_FOUND -4 #define ERR_HWID_NOT_SUPPORTED -5 #define ERR_FWID_NOT_SUPPORTED -6 #define ERR_PARTITION_TYPE_NOT_SUPPORTED -7 #define ERR_INCORRECT_FILE_SIZE -8 #define ERR_READ_FLASH -9 #define ERR_WRITE_FLASH -10 #define ERR_ERASE_FLASH -11 #define ERR_BAD_ADDRESS -12 #define ERR_MEMORY_ALLOC -13 #define ERR_INVALID_TP_HEADER -14 #define ERR_PARTITION_VALIDATION_FAILED -15 #define CFG_FLASH_BASE (0x0) #define DEFAULT_8MB_FLASH_SIZE (8*1024*1024) #ifndef FLASH_SIZE_IN_MB #define CFG_FLASH_SIZE (DEFAULT_8MB_FLASH_SIZE) #else #define CFG_FLASH_SIZE (FLASH_SIZE_IN_MB*1024*1024) #endif #define CFG_FLASH_SECTOR_SIZE (64*1024) #if defined(U_BOOT_COMPILE) || defined(DBG_U_BOOT_COMPILE) /* 地址和factory_boot中使用的WEBFAILSAFE_UPLOAD_RAM_ADDRESS一样 */ #ifdef CONFIG_LOADADDR #undef CONFIG_LOADADDR #endif #define CONFIG_LOADADDR 0x24000000 #endif #define MD5SUM_LEN 16 #define FW_ID_LEN 16 /* content type flags. */ #define CONTENT_TYPE_BOOTLOADER 0x0001 #define CONTENT_TYPE_KERNEL 0x0002 #define CONTENT_TYPE_ROMFS 0x0004 #define CONTENT_TYPE_JFFS2FS 0x0008 /* partition type flags. */ #define PARTITION_TYPE_BOOTLOADER CONTENT_TYPE_BOOTLOADER #define PARTITION_TYPE_KERNEL CONTENT_TYPE_KERNEL #define PARTITION_TYPE_ROOTFS_DATA CONTENT_TYPE_JFFS2FS /* define tp header */ #define MAGIC_LEN 20 #define CRC_LEN 16 #define FW_DESC_LEN 12 #define ERR(fmt, ...) { \ printf("error: " fmt "\n", \ ## __VA_ARGS__ ); \ } #define DBG(fmt, ...) { \ printf( fmt "\n", ## __VA_ARGS__ ); \ } typedef struct _TP_HEADER { unsigned int headerVersion; unsigned char magicNumber[MAGIC_LEN]; unsigned int kernelLoadAddress; unsigned int kernelEntryPoint; unsigned short vendorId; unsigned short zoneCode; unsigned int partitionNum; unsigned int factoryBootOffset; unsigned int factoryBootLen; unsigned int factoryInfoOffset; unsigned int factoryInfoLen; unsigned int radioOffset; unsigned int radioLen; unsigned int ucOffset; unsigned int ucLen; unsigned int bootloaderOffset; unsigned int bootloaderLen; unsigned int tpHeaderOffset; unsigned int tpHeaderLen; unsigned int kernelOffset; unsigned int kernelLen; unsigned int romFsOffset; unsigned int romFsLen; unsigned int jffs2FsOffset; unsigned int jffs2FsLen; unsigned char factoryInfoCRC[CRC_LEN]; unsigned char radioCRC[CRC_LEN]; unsigned char ubootCRC[CRC_LEN]; unsigned char kernelAndRomfsCRC[CRC_LEN]; unsigned char fwId[FW_ID_LEN]; unsigned char fwDescription[FW_DESC_LEN]; unsigned int fwIdBLNum; unsigned char fwIdBL[0][FW_ID_LEN]; unsigned char serviceCRC[CRC_LEN]; unsigned int isVerified; unsigned int jffs2RealFsLen; } TP_HEADER; /* content type flags. */ #define CONTENT_TYPE_BOOTLOADER 0x0001 #define CONTENT_TYPE_KERNEL 0x0002 #define CONTENT_TYPE_ROMFS 0x0004 #define CONTENT_TYPE_JFFS2FS 0x0008 #define CONTENT_TYPE_EXT_FW 0x0010 typedef enum { FW_TO_BEUPGRADE = 0, FW_UBOOT_UPGRADED, FW_WHOLE_UPGRADED }; #define UP_BOOT_MAGIC "nand_upboot.bin" #define NAND_BLOCK_SIZE ( 0x20000 ) #define UPBOOT_INFO_RSV_LEN 202 typedef struct _UPBOOT_INFO { char magic[16]; char md5[16]; int fwLen; int fwStatus; int up_contents; int reserved_block; /* UPBOOT_INFO和UPBOOT_CONTENT之间的块数 */ char mac[6]; /* 用于uboot中isp升级判断 */ char reserve[UPBOOT_INFO_RSV_LEN]; } UPBOOT_INFO; #define MAX_BLOCK_NUM 64 #define BLOCK_MAGIC_NUMBER_LEN 4 #define BLOCK_HEADER_RSV_LEN 504 #define BLOCK_MAX_SIZE 0x10000 typedef struct _BLOCK_INFO { unsigned int type; unsigned int length; } BLOCK_INFO; typedef struct _BLOCK_HEADER { unsigned char magicNumber[BLOCK_MAGIC_NUMBER_LEN]; unsigned int num; BLOCK_INFO info[MAX_BLOCK_NUM]; unsigned char reserve[BLOCK_HEADER_RSV_LEN]; } BLOCK_HEADER; #define EXT_FW_HEADER_VERSION 0x00000001 #define SW_VER_LEN 64 #define RSV_LEN 96 #define EXT_FW_DEVNAME_LEN 64 typedef struct _EXT_FW_HEADER { unsigned int headerVersion; unsigned char devName[EXT_FW_DEVNAME_LEN]; unsigned int compressType; unsigned int version; unsigned int length; unsigned char md5[CRC_LEN]; unsigned char swVer[SW_VER_LEN]; unsigned char reserve[RSV_LEN]; } EXT_FW_HEADER; #define EXT_FW_NOT_CHANGED 0 #define EXT_FW_CHANGED 1 typedef struct _EXT_FW_BLOCK_HANDLER { unsigned int type; /* type of block_handler, corresponding to block type */ unsigned int bNeedUpgrade; /* 1 means this kind of block need to be upgraded */ EXT_FW_HEADER* block; /* pointer to target block used for upgrading */ int (*checkExtFw)(BLOCK_HEADER* blockHdr, void* thisHandler); int (*upgradeExtFw)(EXT_FW_HEADER* block); } EXT_FW_BLOCK_HANDLER; typedef enum { LOCAL_FW = 0, UPGRADE_FW, } FW_TYPE_E; struct _STRUCT_SIZE_CHECK { char buf1[sizeof(EXT_FW_HEADER) == 256 ? 1 : -1]; char buf2[sizeof(BLOCK_HEADER) == 1024 ? 1 : -1]; }; static unsigned char blockHdrMagicNumber[] = {0x12, 0x34, 0x56, 0x78}; #ifdef ISP_IN_FLASH static int checkFirmwareIsp(BLOCK_HEADER* blockHdr, void* thisHandler); static int upgradeFirmwareIsp(EXT_FW_HEADER* block); #endif static EXT_FW_BLOCK_HANDLER blockHdrTbl[] = { #ifdef ISP_IN_FLASH { CONTENT_TYPE_EXT_FW, EXT_FW_NOT_CHANGED, NULL, checkFirmwareIsp, upgradeFirmwareIsp }, #endif { 0, 0, NULL, NULL, NULL } }; static unsigned char gTpHeaderMagicNumber[MAGIC_LEN] = {0x55, 0xAA, 0x9D, 0xD1, 0xA8, 0xC8, 0x83, 0x31, 0xC9, 0x69, 0xFB, 0xBF, 0xBC, 0xF0, 0xD4, 0x32, 0x70, 0xC7, 0xAA, 0x55}; static int addr_flash(void* addr) { if((unsigned long)addr < 0 || (unsigned long)addr >= CFG_FLASH_SIZE) { printf("%p: Not a valid flash address!", addr); return ERR_BAD_ADDRESS; } return 0; } static int readFlash(uint32_t addrOffset, uint8_t* buf, uint32_t buflen) { int ret = 0; char cmdbuf[70]; //TODO:need to detect address type. ret = addr_flash((void*)addrOffset); if(ret < 0) { return ret; } // ret = addr_mem(buf); // if(ret < 0) // { // return ret; // } #ifdef USE_NAND_FLASH sprintf(cmdbuf, "nand read.e 0x%x 0x%x 0x%x", (uint32_t)buf, addrOffset, buflen); #else sprintf(cmdbuf, "sf probe 0;sf read 0x%x 0x%x 0x%x", (uint32_t)buf, addrOffset, buflen); #endif if(run_command(cmdbuf, 0) < 0) { return ERR_READ_FLASH; } return 0; } static int writeFlash(uint32_t addrOffset, uint8_t* buf, uint32_t buflen) { int ret = 0; char cmdbuf[70]; //TODO:need to detect address type. ret = addr_flash((void*)addrOffset); if(ret < 0) { return ret; } // ret = addr_mem(buf); // if(ret < 0) // { // return ret; // } #ifdef USE_NAND_FLASH sprintf(cmdbuf, "nand write.e 0x%x 0x%x 0x%x", (uint32_t)buf, addrOffset, buflen); #else sprintf(cmdbuf, "sf probe 0;sf erase 0x%x 0x%x;sf write 0x%x 0x%x 0x%x", addrOffset, buflen, (uint32_t)buf, addrOffset, buflen); #endif if(run_command(cmdbuf, 0) < 0) { return ERR_READ_FLASH; } return 0; } /* * Function Name: eraseFlash * Author: CaiBin * Date: 2014-11-07 * Description: Erase flash content of a given flash address. * Parameter: * addrOffset: Flash address to erase. * eraselen: Erase length in bytes. * buflen: Length of the data buf in bytes. * return: * 0: Succeeded; * ERR_ERASE_FLASH: Erase command execution error. * ERR_BAD_ADDRESS: Invalid address values passed. */ static int eraseFlash(uint32_t addrOffset, uint32_t eraselen) { int ret; char cmdbuf[70]; ret = addr_flash((void*)addrOffset); if (ret < 0) { return ret; } //if addr offset or eraselen is not on sector boundary, return err. if (0 != (addrOffset % CFG_FLASH_SECTOR_SIZE)) { ERR("%s: addrOffset is 0x%08x\n, not on sector boundary!", __func__, addrOffset); return ERR_BAD_ADDRESS; } if (0 != (eraselen % CFG_FLASH_SECTOR_SIZE)) { ERR("%s: eraselen is 0x%08x\n, not on sector boundary!", __func__, eraselen); return ERR_BAD_ADDRESS; } //TODO:need to detect address type. #ifdef USE_NAND_FLASH sprintf(cmdbuf, "nand erase 0x%x 0x%x", addrOffset, eraselen); #else sprintf(cmdbuf, "sf probe 0;sf erase 0x%x 0x%x", addrOffset, eraselen); #endif if (run_command(cmdbuf, 0) < 0) { return ERR_ERASE_FLASH; } return 0; } /* --------------------------------MD5 计算相关函数---------------------------*/ static void debug_print_md5(unsigned char *digest) { int i = 0; for (i = 0; i < 16; i++) printf("%02x", digest[i]); printf("\n"); } static void calcMd5(char *data, int size, char *md5) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, data, size); MD5_Final(md5, &ctx); } /* 向UPBOOT_OFFSET的前一个分区写入升级状态 */ static inline void writeUpgradeStatsToFlash(UPBOOT_INFO *upboot_info, const int state) { upboot_info->fwStatus = ntohl(state); eraseFlash(UPBOOT_OFFSET, NAND_BLOCK_SIZE * ntohl(upboot_info->reserved_block)); writeFlash(UPBOOT_OFFSET, (uint8_t *)upboot_info, sizeof(UPBOOT_INFO)); } #ifdef FACTORY_BOOT_COMPILE int processUboot(void) { int ret = 0; UPBOOT_INFO *upboot_info = NULL; TP_HEADER *header_up = NULL; char *base = NULL; unsigned char md5Tmp[MD5SUM_LEN] = {0}; ret = readFlash(UPBOOT_OFFSET, (uint8_t*)WEBFAILSAFE_UPLOAD_RAM_ADDRESS, sizeof(UPBOOT_INFO)); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } upboot_info = (UPBOOT_INFO *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS; if (strncmp(upboot_info->magic, UP_BOOT_MAGIC, sizeof(UP_BOOT_MAGIC))) { DBG("UPBOOT_INFO is not written, skip..."); return 0; } if (ntohl(upboot_info->reserved_block) < 2) { printf("reserved_block between upboot_info and upboot is too short\n"); return 0; } if (upboot_info->fwStatus) /* 升级时将up_boot.bin中的主要内容写入后, 该字段才会为零 */ { printf("No need to update uboot\n"); return 0; } printf("fwLen:0x%08x, fwStatus:0x%08x\n", ntohl(upboot_info->fwLen), ntohl(upboot_info->fwStatus)); printf("up_contents:0x%08x\n", ntohl(upboot_info->up_contents)); /* 固件升级时uboot不一定需要更新, nsd模块的upgrade会在将upboot写入flash之前进行检查是否改变 */ if (ntohl(upboot_info->up_contents) & CONTENT_TYPE_BOOTLOADER) { DBG("uboot need to upgrade"); base = WEBFAILSAFE_UPLOAD_RAM_ADDRESS + NAND_BLOCK_SIZE; header_up = (TP_HEADER *)(base + BOOTLOADER_LEN); /* 待升级固件的tp_header */ /* read length ubootlen + tp_header or ntohl(upboot_info->fwLen) ? */ uint32_t upboot_content_offset = UPBOOT_OFFSET + NAND_BLOCK_SIZE * ntohl(upboot_info->reserved_block); uint32_t upboot_content_length = BOOTLOADER_LEN + TP_HEADER_LEN; ret = readFlash(upboot_content_offset, (uint8_t *)base, upboot_content_length); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } memset(md5Tmp, 0, MD5SUM_LEN); calcMd5((char *)(base), (int)BOOTLOADER_LEN, (char *)md5Tmp); // debug_print_md5(md5Tmp); // debug_print_md5(header_up->ubootCRC); if (memcmp(md5Tmp, header_up->ubootCRC, MD5SUM_LEN) == 0) { printf("uboot in up_boot check ok\n"); eraseFlash(BOOTLOADER_OFFSET, TP_HEADER_OFFSET - BOOTLOADER_OFFSET); writeFlash(BOOTLOADER_OFFSET, (uint8_t *)base, BOOTLOADER_LEN); } } /* set fwStatus flag to record upgrade status */ writeUpgradeStatsToFlash(upboot_info, FW_UBOOT_UPGRADED); return 0; } #endif #if defined(U_BOOT_COMPILE) || defined(DBG_U_BOOT_COMPILE) #ifdef ISP_IN_FLASH static bool IspPartitionIsDefault(EXT_FW_HEADER *localIspHdr) { EXT_FW_HEADER defultValue; memset((char *)&defultValue, 0xFF, sizeof(EXT_FW_HEADER)); //default value for ISP is FF when mkslpfw if(0 == memcmp((char *)localIspHdr, (char *)&defultValue, sizeof(EXT_FW_HEADER))) { return true; } else { return false; } } /****************************************************************************** * FUNCTION : checkFirmwareIsp() * AUTHOR : He Shufan (heshufan@tp-link.com.cn) * DESCRIPTION : check isp content and if they are newer or not. * INPUT : BLOCK_HEADER, pointer to block_handler of this function * * OUTPUT : N/A * RETURN : ret code * OTHERS : ******************************************************************************/ static int checkFirmwareIsp(BLOCK_HEADER* hdr, void* thisHandler) { int ret = 0; int i = 0; int blockNum = 0; char md5Tmp[MD5SUM_LEN] = {0}; char* base = (char*)hdr; EXT_FW_HEADER localIspHdr; EXT_FW_HEADER* iHdr = NULL; EXT_FW_BLOCK_HANDLER* pointer = thisHandler; if (NULL == hdr || NULL == thisHandler) { ERR("NULL pointer!"); ret = ERR_GENERIC; goto out; } blockNum = ntohl(hdr->num); DBG("blockNum is %d",blockNum); base += sizeof(BLOCK_HEADER); memset((char *)&localIspHdr, 0, sizeof(EXT_FW_HEADER)); ret = readFlash(ISP_OFFSET, &localIspHdr, sizeof(EXT_FW_HEADER)); if (ret) { ERR("read flash failed"); goto out; } if(IspPartitionIsDefault(&localIspHdr)) { DBG("Isp partition is default"); /* Tapo的ext_fw.config没有Default-devName_Default-hwVer, 固件中一定会有机型名对应的isp */ return ERR_GENERIC; #if 0 if(MacIsDefault()) { //use default device name in factory info, to match isp DBG("Mac is default"); //getDeviceName(localIspHdr.devName); memcpy(localIspHdr.devName, localInfo.devName, EXT_FW_DEVNAME_LEN); } else { ERR("Isp partition is default but mac is not default"); return ERR_GENERIC; } #endif } for (i = 0; i < blockNum; i++) { if (CONTENT_TYPE_EXT_FW == ntohl(hdr->info[i].type)) { iHdr = (EXT_FW_HEADER*)base; if (0 == memcmp(iHdr->devName, localIspHdr.devName, strlen(localIspHdr.devName))) { pointer->block = iHdr; DBG("checkFirmwareIsp: device name %s supported", localIspHdr.devName); break; } } base += ntohl(hdr->info[i].length); } if (i == blockNum) { ERR("isp: device name not supported"); return ERR_GENERIC; } calcMd5((char*)iHdr + sizeof(EXT_FW_HEADER), ntohl(iHdr->length), md5Tmp); ret = memcmp(iHdr->md5, md5Tmp, MD5SUM_LEN); if (ret) { ERR("Invalid isp data in firmware"); return ERR_GENERIC; } ret = memcmp(&(iHdr->version), &(localIspHdr.version), sizeof(unsigned int)); if (ret) { DBG("isp is changed"); pointer->bNeedUpgrade = EXT_FW_CHANGED; return ERR_NONE; } ret = memcmp(iHdr->md5, localIspHdr.md5, CRC_LEN); if (ret) { DBG("isp is changed"); pointer->bNeedUpgrade = EXT_FW_CHANGED; return ERR_NONE; } ret = memcmp(iHdr->swVer, localIspHdr.swVer, SW_VER_LEN); if (ret) { DBG("isp is not changed but software version is changed"); pointer->bNeedUpgrade = EXT_FW_CHANGED; return ERR_NONE; } DBG("isp is not changed"); pointer->bNeedUpgrade = EXT_FW_NOT_CHANGED; out: return ret; } /****************************************************************************** * FUNCTION : upgradeFirmwareIsp() * AUTHOR : He Shufan (heshufan@tp-link.com.cn) * DESCRIPTION : upgrade isp in flash * INPUT : EXT_FW_HEADER * * OUTPUT : N/A * RETURN : ret code * OTHERS : ******************************************************************************/ static int upgradeFirmwareIsp(EXT_FW_HEADER* block) { int ret = 0; char ispBuf[ISP_LEN] = {0}; uint32_t addrOffset = 0; uint32_t size = 0; if (NULL == block) { ERR("NULL pointer"); ret = ERR_GENERIC; return ret; } size = ntohl(block->length) + sizeof(EXT_FW_HEADER); memset(ispBuf, 0xff, ISP_LEN); memcpy(ispBuf, (void *)block, size); #ifdef USE_NAND_FLASH ret = eraseFlash(ISP_OFFSET, UC_OFFSET - ISP_OFFSET); #else ret = eraseFlash(ISP_OFFSET, ISP_LEN); #endif if (ret) { return ret; } //ret = writePartitionData(ISP, ispBuf); ret = writeFlash(ISP_OFFSET, ispBuf, ISP_LEN); if (ret) { return ret; } DBG("upgrade isp done"); return ERR_NONE; } #endif /* #ifdef ISP_IN_FLASH */ #ifdef CONFIG_EXT_FW_UPGRADE static int checkEXTFirmware(/*UPGRADE_HEADER* uHeader*/ unsigned char *buf) { int i = 0; // unsigned short upContents = 0; BLOCK_HEADER* blockHdr = NULL; TP_HEADER* header; // unsigned char* buf = (unsigned char*)uHeader; int ret = 0; // upContents = ntohs(uHeader->contentTypes); header = (TP_HEADER*)(buf + /*ntohs(uHeader->tagLength) + */BOOTLOADER_LEN); blockHdr = (BLOCK_HEADER*)((char*)header + ntohl(header->tpHeaderLen) + ntohl(header->kernelLen) + ntohl(header->romFsLen)); if (0 != memcmp(blockHdrMagicNumber, blockHdr->magicNumber, BLOCK_MAGIC_NUMBER_LEN)) { ERR("invalid ext_fw block header"); return ERR_GENERIC; } for (i = 0; i < sizeof(blockHdrTbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) { if (0 != (blockHdrTbl[i].type /* & upContents*/ )) { ret = blockHdrTbl[i].checkExtFw(blockHdr, &blockHdrTbl[i]); if (ret < 0) { ERR("check ext_fw failed, type:0x%x", blockHdrTbl[i].type); return ERR_PARTITION_TYPE_NOT_SUPPORTED; } } } // printf("checkEXTFirmware done\n"); return ERR_NONE; } static int upgradeEXTFirmware(void) { int i = 0; int ret = ERR_NONE; // printf("blockHdrTbl[i].bNeedUpgrade is %d, %d\n", i, blockHdrTbl[i].bNeedUpgrade); for (i = 0; i < sizeof(blockHdrTbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) { // printf("blockHdrTbl[i].bNeedUpgrade is %d, %d\n", i, blockHdrTbl[i].bNeedUpgrade); if (blockHdrTbl[i].bNeedUpgrade) { ret = blockHdrTbl[i].upgradeExtFw(blockHdrTbl[i].block); if (ret) { ERR("upgrade ext_fw failed, type:0x%x", blockHdrTbl[i].type); return ret; } } } return ret; } #endif static int executeUpgrade_nand(TP_HEADER* header) { int ret = 0; int i =0; uint32_t offset[] = { TP_HEADER_OFFSET, KERNEL_OFFSET, ntohl(header->romFsOffset) }; uint32_t eraseLen[] = { KERNEL_OFFSET - TP_HEADER_OFFSET, ntohl(header->romFsOffset) - KERNEL_OFFSET, ntohl(header->jffs2FsOffset) - ntohl(header->romFsOffset) }; uint32_t writeLen[] = { TP_HEADER_LEN, ntohl(header->kernelLen), ntohl(header->romFsLen) }; uint8_t* baseArr[] = { (uint8_t*)header, (uint8_t*)((uint8_t*)header + TP_HEADER_LEN), (uint8_t*)((uint8_t*)header + TP_HEADER_LEN + ntohl(header->kernelLen)) }; printf("execute nand flash upgrade...\n"); for (i = 0; i < sizeof(offset) / sizeof(uint32_t); i++) { ret = eraseFlash(offset[i], eraseLen[i]); if (ret < 0) { goto error_exit; } //start to write firmware. printf("write offset: 0x%x, from: %p, size: 0x%x\n", offset[i], baseArr[i], writeLen[i]); ret = writeFlash(offset[i], baseArr[i], writeLen[i]); if (ret < 0) { goto error_exit; } } return 0; error_exit: ERR("erase or write nand flash failed!"); return ret; } int validateFirmwareWithUpgrade(void) { int ret = 0; UPBOOT_INFO *upboot_info = NULL; ret = readFlash(UPBOOT_OFFSET, (uint8_t*)CONFIG_LOADADDR, sizeof(UPBOOT_INFO)); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } upboot_info = (UPBOOT_INFO *)CONFIG_LOADADDR; if (strncmp(upboot_info->magic, UP_BOOT_MAGIC, sizeof(UP_BOOT_MAGIC))) { DBG("UPBOOT_INFO is not written, skip..."); return 0; } if (ntohl(upboot_info->fwStatus) != FW_UBOOT_UPGRADED) /* factory_boot中已经处理完uboot升级逻辑 */ { printf("No need to upgrade firmware\n"); return 0; } printf("fwLen:0x%08x, fwStatus:%d\n", ntohl(upboot_info->fwLen), ntohl(upboot_info->fwStatus)); TP_HEADER* header_up = NULL; char *base = CONFIG_LOADADDR + NAND_BLOCK_SIZE; header_up = (TP_HEADER *)(base + BOOTLOADER_LEN); unsigned char md5Tmp[MD5SUM_LEN] = {0}; /* 根据upboot_info中的fwLen读取待升级固件 */ uint32_t upboot_content_offset = UPBOOT_OFFSET + NAND_BLOCK_SIZE * ntohl(upboot_info->reserved_block); ret = readFlash(upboot_content_offset, (uint8_t *)base, ntohl(upboot_info->fwLen)); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } /* check fwLen */ if (ntohl(upboot_info->fwLen) < \ ntohl(header_up->bootloaderLen) + ntohl(header_up->tpHeaderLen) + ntohl(header_up->kernelLen) + ntohl(header_up->romFsLen)) { return 0; } memset(md5Tmp, 0, MD5SUM_LEN); calcMd5((char *)(base + ntohl(header_up->bootloaderLen) + ntohl(header_up->tpHeaderLen)), \ (int)(ntohl(header_up->kernelLen) + ntohl(header_up->romFsLen)), (char *)md5Tmp); // debug_print_md5(md5Tmp); // debug_print_md5(header_up->kernelAndRomfsCRC); /* 由于升级时固件版本会变, 导致kernelAndromfs一定会变, 在此不再判断up_contents */ if (memcmp(md5Tmp, header_up->kernelAndRomfsCRC, MD5SUM_LEN) == 0) { printf("uboot check kernelAndromfs in up_boot.bin ok\n"); executeUpgrade_nand(header_up); } /* isp也会改变, 不再判断up_contents, 升级ISP */ #ifdef CONFIG_EXT_FW_UPGRADE checkEXTFirmware(base); upgradeEXTFirmware(); #endif /* set fwStatus flag to record upgrade status */ writeUpgradeStatsToFlash(upboot_info, FW_WHOLE_UPGRADED); return 0; } #endif /* #ifdef U_BOOT_COMPILE */
09-05
int validateLocalFirmware(void) { int ret = 0; TP_HEADER* header = (TP_HEADER*)(UIP_FLASH_BASE + TP_HEADER_OFFSET); uint32_t partitions = PARTITION_TYPE_BOOTLOADER | PARTITION_TYPE_KERNEL; /* * Note: As TP Header may be upgraded with crc's of these partitions changed, but the * content of these partitions is never changed during upgrading. Normal check may result error. */ #ifdef WEBFAILSAFE_DO_FULL_LOCAL_VALIDATION partitions |= (PARTITION_TYPE_FACTORY_INFO | PARTITION_TYPE_RADIO_DATA); #endif #ifdef WEBFAILSAFE_LOCAL_VALIDATION_IN_RAM #ifdef USE_NAND_FLASH ret = readFlash(TP_HEADER_OFFSET, (uint8_t*)WEBFAILSAFE_UPLOAD_RAM_ADDRESS, TP_HEADER_LEN); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } header = (TP_HEADER*)(WEBFAILSAFE_UPLOAD_RAM_ADDRESS); #else //copy flash image to RAM. printf("copying flash to 0x%x", WEBFAILSAFE_UPLOAD_RAM_ADDRESS); ret = readFlash(0, (uint8_t*)WEBFAILSAFE_UPLOAD_RAM_ADDRESS, UIP_FLASH_SIZE); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } header = (TP_HEADER*)(WEBFAILSAFE_UPLOAD_RAM_ADDRESS + TP_HEADER_OFFSET); #endif #endif printf("validate local firmware...\nTP Header at %p", header); #ifdef UIP_CACHE_OPERATION uip_cache_enable(); #endif ret = validatePartitions(header, partitions, LOCAL_FW); #ifdef ISP_IN_FLASH if (0 == ret) { EXT_FW_HEADER *localIspHdr = NULL; #ifdef USE_NAND_FLASH ret = readFlash(ISP_OFFSET, (uint8_t*)WEBFAILSAFE_UPLOAD_RAM_ADDRESS, ISP_LEN); if (ret < 0) { ERR("reading flash to RAM failed."); return ret; } localIspHdr = (EXT_FW_HEADER *)(WEBFAILSAFE_UPLOAD_RAM_ADDRESS); #else localIspHdr = (EXT_FW_HEADER *)(WEBFAILSAFE_UPLOAD_RAM_ADDRESS + ISP_OFFSET); #endif if (IspPartitionIsDefault(localIspHdr)) { ret = ERR_GENERIC; DBG("Local isp partition is default, need upgrade."); } else { ret = validateLocalIspPartition(localIspHdr); } } #endif #ifdef UIP_CACHE_OPERATION uip_cache_disable(); #endif return ret; }
09-05
Delphi 12.3 作为一款面向 Windows 平台的集成开发环境,由 Embarcadero Technologies 负责其持续演进。该环境以 Object Pascal 语言为核心,并依托 Visual Component Library(VCL)框架,广泛应用于各类桌面软件、数据库系统及企业级解决方案的开发。在此生态中,Excel4Delphi 作为一个重要的社区开源项目,致力于搭建 Delphi 与 Microsoft Excel 之间的高效桥梁,使开发者能够在自研程序中直接调用 Excel 的文档处理、工作表管理、单元格操作及宏执行等功能。 该项目以库文件与组件包的形式提供,开发者将其集成至 Delphi 工程后,即可通过封装良好的接口实现对 Excel 的编程控制。具体功能涵盖创建与编辑工作簿、格式化单元格、批量导入导出数据,乃至执行内置公式与宏指令等高级操作。这一机制显著降低了在财务分析、报表自动生成、数据整理等场景中实现 Excel 功能集成的技术门槛,使开发者无需深入掌握 COM 编程或 Excel 底层 API 即可完成复杂任务。 使用 Excel4Delphi 需具备基础的 Delphi 编程知识,并对 Excel 对象模型有一定理解。实践中需注意不同 Excel 版本间的兼容性,并严格遵循项目文档进行环境配置与依赖部署。此外,操作过程中应遵循文件访问的最佳实践,例如确保目标文件未被独占锁定,并实施完整的异常处理机制,以防数据损毁或程序意外中断。 该项目的持续维护依赖于 Delphi 开发者社区的集体贡献,通过定期更新以适配新版开发环境与 Office 套件,并修复已发现的问题。对于需要深度融合 Excel 功能的 Delphi 应用而言,Excel4Delphi 提供了经过充分测试的可靠代码基础,使开发团队能更专注于业务逻辑与用户体验的优化,从而提升整体开发效率与软件质量。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值