#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "PrjCfg.h" #include "sys_fwload.h" #include "sys_storage_partition.h" #include "DxHunting.h" //#NT#PARTIAL_COMPRESS, we use rtos-main size + 1 block size #define FW_PARTIAL_COMPRESS_WORK_BUF_SIZE 0x320000 #define CFG_MAX_FW_SIZE 0x800000 //for rtos boot linux, the original fw size must be smaller #if defined(_FW_TYPE_PARTIAL_) || defined(_FW_TYPE_PARTIAL_COMPRESS_) static ID fwload_flg_id = 0; //This array is sort by section id static UINT32 UserSection_Load[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //This array is sort by loading order static UINT32 UserSection_Order_common[] = { CODE_SECTION_02, CODE_SECTION_03, CODE_SECTION_04, CODE_SECTION_05, CODE_SECTION_06, CODE_SECTION_07, CODE_SECTION_08, CODE_SECTION_09, CODE_SECTION_10, FWSRV_PL_BURST_END_TAG }; static UINT32 UserSection_Order_movie_fast_mode2[] = { CODE_SECTION_02, CODE_SECTION_03, CODE_SECTION_04, CODE_SECTION_06, CODE_SECTION_05, CODE_SECTION_07, CODE_SECTION_08, CODE_SECTION_09, CODE_SECTION_10, FWSRV_PL_BURST_END_TAG }; int fwload_init(void) { vos_flag_create(&fwload_flg_id, NULL, "fwload_flg_id"); vos_flag_clr(fwload_flg_id, (FLGPTN)-1); // CODE_SECTION_01 has loaded by loader or u-boot vos_flag_set(fwload_flg_id, (FLGPTN)(1 << CODE_SECTION_01)); return 0; } int fwload_set_done(CODE_SECTION section) { vos_perf_list_mark("pl", __LINE__, (int)section); vos_flag_set(fwload_flg_id, (FLGPTN)(1 << section)); return 0; } int fwload_wait_done(CODE_SECTION section) { FLGPTN flgptn; vos_flag_wait(&flgptn, fwload_flg_id, (FLGPTN)(1 << section), TWF_ANDW); return 0; } static void UserSection_LoadCb(const UINT32 Idx) { DBG_DUMP("Section-%.2ld: (LOAD)\r\n", Idx + 1); UserSection_Load[Idx] = 1; //mark loaded fwload_set_done(Idx); } #if defined(_FW_TYPE_PARTIAL_COMPRESS_) static void *gz_alloc(void *x, unsigned items, unsigned size) { void *p = malloc(size * items); if (p) { memset(p, 0, size * items); } return p; } static void gz_free(void *x, void *addr, unsigned nb) { free(addr); } static int unzip(unsigned char *in, unsigned char *out, unsigned int insize, unsigned int outsize) { int err; z_stream stream = {0}; stream.next_in = (z_const Bytef *)in; stream.avail_in = insize; stream.next_out = (z_const Bytef *)out; stream.avail_out = outsize; stream.zalloc = (alloc_func)gz_alloc; stream.zfree = (free_func)gz_free; stream.opaque = (voidpf)0; err = inflateInit(&stream); if (err != Z_OK) { DBG_ERR("Failed to inflateInit, err = %d\r\n", err); inflateEnd(&stream); return err; } err = inflate(&stream, Z_NO_FLUSH); inflateEnd(&stream); if (err == Z_STREAM_END) { return 0; } return err; } #endif int fwload_partload(void) { extern BININFO bin_info; SHMINFO *p_shm; FWSRV_INIT Init = {0}; FWSRV_CMD Cmd = {0}; FWSRV_PL_LOAD_BURST_IN pl_in = {0}; unsigned char *p_fdt = (unsigned char *)fdt_get_base(); if (p_fdt == NULL) { DBG_ERR("p_fdt is NULL.\n"); return -1; } int len; int nodeoffset; const void *nodep; /* property node pointer */ // read SHMEM_PATH nodeoffset = fdt_path_offset(p_fdt, SHMEM_PATH); if (nodeoffset < 0) { DBG_ERR("failed to offset for %s = %d \n", SHMEM_PATH, nodeoffset); } else { DBG_DUMP("offset for %s = %d \n", SHMEM_PATH, nodeoffset); } nodep = fdt_getprop(p_fdt, nodeoffset, "reg", &len); if (len == 0 || nodep == NULL) { DBG_ERR("failed to access reg.\n"); return 0; } else { unsigned int *p_data = (unsigned int *)nodep; p_shm = (SHMINFO *)be32_to_cpu(p_data[0]); DBG_DUMP("p_shm = 0x%08X\n", (int)p_shm); } // init fwsrv Init.uiApiVer = FWSRV_API_VERSION; Init.StrgMap.pStrgFdt = EMB_GETSTRGOBJ(STRG_OBJ_FW_FDT); Init.StrgMap.pStrgApp = EMB_GETSTRGOBJ(STRG_OBJ_FW_APP); Init.StrgMap.pStrgUboot = EMB_GETSTRGOBJ(STRG_OBJ_FW_UBOOT); Init.StrgMap.pStrgRtos = EMB_GETSTRGOBJ(STRG_OBJ_FW_RTOS); Init.PlInit.uiApiVer = PARTLOAD_API_VERSION; Init.PlInit.pStrg = EMB_GETSTRGOBJ(STRG_OBJ_FW_RTOS); #if defined(_FW_TYPE_PARTIAL_COMPRESS_) Init.PlInit.DataType = PARTLOAD_DATA_TYPE_COMPRESS_GZ; Init.PlInit.uiWorkingAddr = (UINT32)malloc(FW_PARTIAL_COMPRESS_WORK_BUF_SIZE); Init.PlInit.uiWorkingSize = FW_PARTIAL_COMPRESS_WORK_BUF_SIZE ; #else Init.PlInit.DataType = PARTLOAD_DATA_TYPE_UNCOMPRESS; Init.PlInit.uiWorkingAddr = (UINT32)malloc(_EMBMEM_BLK_SIZE_); Init.PlInit.uiWorkingSize = _EMBMEM_BLK_SIZE_ ; #endif Init.PlInit.uiAddrBegin = _BOARD_RTOS_ADDR_ + p_shm->boot.LdLoadSize; FwSrv_Init(&Init); FwSrv_Open(); // start partial load void (*LoadCallback)(const UINT32 Idx) = UserSection_LoadCb; UINT32 *SecOrderTable = NULL; if(DrvGPIO_GetPhotoMovieModeFromMonitor() == DX_HUNTING_MODE_MOVIE2){ SecOrderTable = UserSection_Order_movie_fast_mode2; } else{ SecOrderTable = UserSection_Order_common; } LoadCallback(CODE_SECTION_01); // 1st part has loaded by loader // partial load not support on T.bin if ((p_shm->boot.LdCtrl2 & LDCF_BOOT_CARD) == 0 && p_shm->boot.LdLoadSize != bin_info.head.BinLength) { ER er; pl_in.puiIdxSequence = SecOrderTable; pl_in.fpLoadedCb = LoadCallback; Cmd.Idx = FWSRV_CMD_IDX_PL_LOAD_BURST; //continue load Cmd.In.pData = &pl_in; Cmd.In.uiNumByte = sizeof(pl_in); Cmd.Prop.bExitCmdFinish = TRUE; er = FwSrv_Cmd(&Cmd); if (er != FWSRV_ER_OK) { FwSrv_Close(); free((void *)Init.PlInit.uiWorkingAddr); DBG_ERR("Process failed!\r\n"); return -1; } else { FwSrv_Close(); free((void *)Init.PlInit.uiWorkingAddr); } } else { #if defined(_FW_TYPE_PARTIAL_COMPRESS_) UINT32 part1_size = *(UINT32 *)(bin_info.head.CodeEntry + CODE_SECTION_OFFSET + 4); NVTPACK_BFC_HDR *p_bfc = (NVTPACK_BFC_HDR *)(bin_info.head.CodeEntry + part1_size); // if boot rtos by u-boot, it has decompressed. // only boot rtos from loader needing to decode by rtos itself if (p_bfc->uiFourCC == MAKEFOURCC('B', 'C', 'L', '1')) { unsigned int gzip_image_len = be32_to_cpu((unsigned int)p_bfc->uiSizeComp); if (gzip_image_len > CFG_MAX_FW_SIZE) { DBG_ERR("compressed fw size too large: %d bytes\r\n", gzip_image_len); return -1; } unsigned char *gzip_image = (unsigned char *)malloc(gzip_image_len); if (gzip_image == NULL) { DBG_ERR("failed to malloc gzip_image, need: %d bytes\r\n", gzip_image_len); return -1; } memcpy(gzip_image, &p_bfc[1], gzip_image_len); unsigned int unzip_image_len = be32_to_cpu((unsigned int)p_bfc->uiSizeUnComp); if (unzip_image_len > CFG_MAX_FW_SIZE) { DBG_ERR("original fw size too large: %d bytes\r\n", unzip_image_len); free(gzip_image); return -1; } if (unzip(gzip_image, (unsigned char *) p_bfc, gzip_image_len, unzip_image_len) != 0) { DBG_ERR("failed to unzip partial compressed rtos image.\r\n"); free(gzip_image); return -1; } free(gzip_image); } #endif UINT32 i; for (i = CODE_SECTION_02; i <= CODE_SECTION_10; i++) { if (i == CODE_SECTION_10) { FwSrv_Close(); free((void *)Init.PlInit.uiWorkingAddr); } LoadCallback(i); } } return 0; } #else int fwload_init(void) { return 0; } int fwload_set_done(CODE_SECTION section) { return 0; } int fwload_wait_done(CODE_SECTION section) { return 0; } int fwload_partload(void) { //only POWERON_MODE_BOOT_LINUX needs FwSrv #if (POWERON_MODE == POWERON_MODE_BOOT_LINUX) FWSRV_INIT Init = {0}; // init fwsrv Init.uiApiVer = FWSRV_API_VERSION; Init.StrgMap.pStrgFdt = EMB_GETSTRGOBJ(STRG_OBJ_FW_FDT); Init.StrgMap.pStrgApp = EMB_GETSTRGOBJ(STRG_OBJ_FW_APP); Init.StrgMap.pStrgUboot = EMB_GETSTRGOBJ(STRG_OBJ_FW_UBOOT); Init.StrgMap.pStrgRtos = EMB_GETSTRGOBJ(STRG_OBJ_FW_RTOS); Init.PlInit.uiApiVer = PARTLOAD_API_VERSION; Init.PlInit.pStrg = EMB_GETSTRGOBJ(STRG_OBJ_FW_RTOS); Init.PlInit.DataType = PARTLOAD_DATA_TYPE_UNCOMPRESS; FwSrv_Init(&Init); #endif return 0; } #endif