123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518 |
- /* Copyright (C) 2019 RDA Technologies Limited and/or its affiliates("RDA").
- * All rights reserved.
- *
- * This software is supplied "AS IS" without any warranties.
- * RDA assumes no responsibility or liability for the use of the software,
- * conveys no license or title under any patent, copyright, or mask work
- * right to the product. RDA reserves the right to make changes in the
- * software without notification. RDA also make no representation or
- * warranty that such application will be suitable for the specified use
- * without further testing or modification.
- */
- #define OSI_LOCAL_LOG_TAG OSI_MAKE_LOG_TAG('F', 'D', 'L', 'D')
- // #define OSI_LOCAL_LOG_LEVEL OSI_LOG_LEVEL_DEBUG
- #include "boot_fdl.h"
- #include "boot_platform.h"
- #include "boot_spi_flash.h"
- #include "hal_chip.h"
- #include "boot_secure.h"
- #include "boot_bsl_cmd.h"
- #include "hal_config.h"
- #include "osi_log.h"
- #include "osi_api.h"
- #include "drv_names.h"
- #include "fs_mount.h"
- #include "vfs.h"
- #include "nvm.h"
- #include "calclib/crc32.h"
- #include "calclib/sha256.h"
- #include "calclib/simage.h"
- #include "cpio_parser.h"
- #include <stdint.h>
- #include <string.h>
- #include <stdlib.h>
- #include <assert.h>
- #include "quec_boot_log.h"
- #include "quec_cust_patch.h"
- #include "quec_proj_config.h"
- #include "quec_boot_file_cfg.h"
- #ifdef CONFIG_QUEC_PROJECT_FEATURE
- #include "fupdate_config.h"
- #endif
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI4_EXTNSFFS
- #include "fs_mount_spiflash.h"
- #include "ql_boot_spi4_exnsffs_cfg.h"
- #endif
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW
- #include "fs_config.h"
- #include "quec_boot_pff.h"
- #if (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_SDMMC) || (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_EMMC)
- #include "quec_boot_sdmmc.h"
- #include "drv_sdmmc_imp.h"
- extern ql_boot_sdmmc_cfg_t ql_boot_sdmmc_cfg; //sdmmc配置
- #endif
- #endif
- // Work memory size in context
- #define WORKMEM_SIZE (CONFIG_NVBIN_FIXED_SIZE < 0x10000 ? 0x10000 : CONFIG_NVBIN_FIXED_SIZE)
- #ifdef __QUEC_OEM_VER_TY__
- #define PACKAGE_FILE_MAX_SIZE 0x100000
- #else
- #ifdef CONFIG_QUEC_PROJECT_FEATURE
- #define PACKAGE_FILE_MAX_SIZE 0x180000
- #else
- #define PACKAGE_FILE_MAX_SIZE 0x10000
- #endif
- #endif
- #ifdef CONFIG_QUEC_PROJECT_FEATURE
- #define TTS_PREPACK_FILE_PATH "/qsfs/quectel_pcm_resource.bin"
- #define TTS_EN_PREPACK_FILE_PATH "/qsfs/quectel_pcm_english.bin"
- #define GNSS_BOOT_FILE_PATH "/user/boot"
- #define GNSS_FIRM_FILE_PATH "/user/firm"
- #define QL_TTS_RESOURCE_APPEND_BIN "/qsfs/quectel_pcm_resource_append.bin"
- #define QL_TTS_RESOURCE_END_BIN "/qsfs/quectel_pcm_resource_ff.bin"
- #define QL_TTS_RESOURCE_PACKET_MAX 10
- #endif
- // Logic addresses, which should match the value used in pac file
- #define ERASE_RUNNING_NV_LOGIC_ADDRESS 0xFE000001
- #define PHASECHECK_LOGIC_ADDRESS 0xFE000002
- #define FIXNV_LOGIC_ADDRESS 0xFE000003
- #define PRE_PACK_FILE_LOGIC_ADDRESS 0xFE000004
- #define DEL_APPIMG_LOGIC_ADDRESS 0xFE000005
- #define FMT_FLASH_LOGIC_ADDRESS 0xFE000006
- #define FLASH_ERASE_ALL 0x00000000
- #define FLASH_ERASE_ALL_SIZE 0xFFFFFFFF
- #define FLASH_PAGE_SIZE (256)
- #define FLASH_SECTOR_SIZE (0x1000)
- #define FDL_SIZE_4K (0x1000)
- // 8910 encrypt
- #define BOOT_SIGN_SIZE (0xbd40)
- #define ENCRYPT_OFF 0x1000
- #define ENCRYPT_LEN 0x400
- #define DELAY_POWEROFF_TIMEOUT (2000)
- #define ERR_REP_RETURN(fdl, err) OSI_DO_WHILE0(fdlEngineSendRespNoData(fdl, err); return;)
- #if (defined CONFIG_BOARD_WITH_EXT_FLASH) || (defined CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR)
- #define IS_FLASH_ADDRESS(address) (HAL_FLASH_DEVICE_NAME(address) == DRV_NAME_SPI_FLASH || HAL_FLASH_DEVICE_NAME(address) == DRV_NAME_SPI_FLASH_EXT)
- #else /*#ifndef CONFIG_BOARD_WITH_EXT_FLASH*/
- #define IS_FLASH_ADDRESS(address) (HAL_FLASH_DEVICE_NAME(address) == DRV_NAME_SPI_FLASH)
- #endif/*CONFIG_BOARD_WITH_EXT_FLASH*/
- #ifdef QUEC_PATCH_FACTORY_UPDATE
- bool g_upgrade_by_factory = false;
- #endif
- enum
- {
- FS_PREPARE_WRITE_PHASECHEK,
- FS_PREPARE_WRITE_FIXEDNV,
- FS_PREPARE_WRITE_PREPACK,
- FS_PREPARE_READ_PHASECHECK,
- FS_PREPARE_READ_FIXEDNV,
- FS_PREPARE_ERASE_RUNNINGNV,
- FS_PREPARE_ERASE_PHASECHECK,
- FS_PREPARE_ERASE_APPIMG_FILE,
- FS_PREPARE_BACKUP_PHASE_CHECK,
- };
- typedef struct
- {
- cpioStream_t *cpio;
- fdlDataDnld_t dnld;
- bool running_cleared;
- bool phasecheck_backed;
- bool fixednv_backed;
- unsigned init_nvbin_size;
- unsigned init_nvbin_crc;
- bool secure_boot_enable;
- bool delay_poweroff;
- bool flash_write_whole;
- unsigned device_type;
- fdlChannel_t *channel;
- unsigned max_packet_len;
- osiElapsedTimer_t connect_timer;
- phaseCheckHead_t phasecheck_back;
- char fixednv_back[CONFIG_NVBIN_FIXED_SIZE];
- char work_mem[WORKMEM_SIZE];
- char *flash_mem;
- } fdlContext_t;
- /**
- * When needed, hacks for nv on factory partition
- */
- static bool prvFactoryNvHack(fdlContext_t *d)
- {
- #ifdef CONFIG_SOC_8910
- // HACK: ResearchDownload needs that nvid 2 must exist, and
- // previously this nv isn't added in 8910. Due to this nv isn't actually
- // used. So, at the beginning of FDL2, this will be written to make
- // ResearchDownload happy.
- if (nvmReadItem(NVID_CALIB_PARAM, NULL, 0) <= 0)
- {
- // Refer to CMakeLists.txt about these 2 external symbols.
- extern const unsigned gDefCalibParam[];
- extern const unsigned gDefCalibParamSize[];
- nvmWriteItem(NVID_CALIB_PARAM, gDefCalibParam, (unsigned)gDefCalibParamSize);
- }
- // HACK: GSM calibration data size is changed from 7706 to 8192. The
- // size of existed GSM calibration data may be 7706. And it is needed
- // to pad the existed GSM calibration data to 8192, to make NVEditor
- // work, and make nv backup work.
- int calib_gsm_size = nvmReadFixedItem(0x26d, NULL, 0);
- if (calib_gsm_size > 0 && calib_gsm_size < 8192)
- {
- char *calib_gsm_bin = &d->work_mem[0];
- memset(calib_gsm_bin, 0, 8192);
- nvmReadFixedItem(0x26d, calib_gsm_bin, 8192);
- nvmWriteFixedItem(0x26d, calib_gsm_bin, 8192);
- }
- #endif
- return true;
- }
- /**
- * Mount factory partition
- */
- static bool prvMountFactory(fdlContext_t *d)
- {
- if (!fsMountFsPath(CONFIG_FS_FACTORY_MOUNT_POINT, false))
- return false;
- return prvFactoryNvHack(d);
- }
- /**
- * Mount factory partition, and format on fail
- */
- static bool prvMountFormatFactory(fdlContext_t *d)
- {
- if (!fsMountFsPath(CONFIG_FS_FACTORY_MOUNT_POINT, true))
- return false;
- return prvFactoryNvHack(d);
- }
- /**
- * Mount modem partition
- */
- static bool prvMountModem(fdlContext_t *d)
- {
- #ifdef CONFIG_FS_MODEM_MOUNT_POINT
- return fsMountFsPath(CONFIG_FS_MODEM_MOUNT_POINT, false);
- #else
- return true;
- #endif
- }
- /**
- * Prepare file system for various senario
- */
- static bool prvFsPrepare(fdlContext_t *d, unsigned kind)
- {
- switch (kind)
- {
- case FS_PREPARE_WRITE_PHASECHEK:
- case FS_PREPARE_WRITE_FIXEDNV:
- case FS_PREPARE_WRITE_PREPACK:
- case FS_PREPARE_ERASE_RUNNINGNV:
- case FS_PREPARE_ERASE_APPIMG_FILE:
- return prvMountFormatFactory(d) && fsMountWithFormatAll();
- case FS_PREPARE_READ_PHASECHECK:
- case FS_PREPARE_ERASE_PHASECHECK:
- return prvMountFactory(d);
- case FS_PREPARE_READ_FIXEDNV:
- prvMountModem(d); // ignore error
- return prvMountFactory(d);
- default:
- return false;
- }
- }
- /**
- * Calculate nvbin size and CRC. It will reuse \p work_mem.
- */
- static void prvInitNvBinSizeCrc(fdlContext_t *d)
- {
- d->init_nvbin_size = 0;
- if (!prvFsPrepare(d, FS_PREPARE_READ_FIXEDNV))
- return;
- int nvbin_size = nvmReadFixedBin(NULL, 0);
- if (nvbin_size <= 0 || nvbin_size > CONFIG_NVBIN_FIXED_SIZE)
- return;
- char *nvbin = &d->work_mem[0];
- memset(nvbin, 0xff, CONFIG_NVBIN_FIXED_SIZE);
- nvmReadFixedBin(nvbin, CONFIG_NVBIN_FIXED_SIZE);
- d->init_nvbin_crc = crc32Calc(nvbin, CONFIG_NVBIN_FIXED_SIZE);
- d->init_nvbin_size = nvbin_size;
- }
- /**
- * Check whether running should be cleared. It will reuse \p work_mem.
- * It is only called after write fixednv.
- */
- static void prvCheckClearRunning(fdlContext_t *d)
- {
- #ifdef CONFIG_SOC_8910
- if (d->running_cleared)
- return;
- if (!prvFsPrepare(d, FS_PREPARE_READ_FIXEDNV) ||
- !prvFsPrepare(d, FS_PREPARE_ERASE_RUNNINGNV))
- return;
- int nvbin_size = nvmReadFixedBin(NULL, 0);
- if (d->init_nvbin_size > 0 && nvbin_size == d->init_nvbin_size)
- {
- char *nvbin = &d->work_mem[0];
- memset(nvbin, 0xff, CONFIG_NVBIN_FIXED_SIZE);
- nvmReadFixedBin(nvbin, CONFIG_NVBIN_FIXED_SIZE);
- // do nothing if the nvbin CRC matches
- if (crc32Calc(nvbin, CONFIG_NVBIN_FIXED_SIZE) == d->init_nvbin_crc)
- return;
- }
- nvmClearRunning();
- d->running_cleared = true;
- #endif
- }
- /**
- * BSL_CMD_CONNECT, the timestamp is recorded.
- */
- static void prvConnect(fdlEngine_t *fdl, fdlContext_t *d)
- {
- OSI_LOGI(0x10009061, "FDL: connect");
- osiElapsedTimerStart(&d->connect_timer);
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- }
- /**
- * check whether flash need erase
- *
- */
- static bool prvFlashSkipEraseCheck(bootSpiFlash_t *d, uint32_t offset, size_t size)
- {
- const uint32_t pattern = 0xffffffff;
- const void *fl = bootSpiFlashMapAddress(d, offset);
- uint32_t *f_addr = (uint32_t *)fl;
- for (int i = 0; i <= size / sizeof(uint32_t); i++)
- {
- if (f_addr[i] != pattern)
- {
- OSI_LOGI(0, "CheckFlash: need erase 0x%x/0x%x", f_addr, size);
- return false;
- }
- }
- OSI_LOGI(0, "CheckFlash need not erase 0x%x/0x%x", f_addr, size);
- return true;
- }
- /**
- * Flash download start. The common information start/total/received has
- * already initialized. Return response error code.
- */
- static int prvFlashStart(fdlContext_t *d)
- {
- fdlDataDnld_t *dn = &d->dnld;
- // Though it doesn't look reasonable, unaligned start address is supported.
- // In this case, the write address is not the same as erase address.
- dn->write_address = dn->start_address;
- dn->erase_address = OSI_ALIGN_DOWN(dn->start_address, FLASH_SECTOR_SIZE);
- unsigned faddress = HAL_FLASH_OFFSET(dn->erase_address);
- unsigned fend = HAL_FLASH_OFFSET(OSI_ALIGN_UP(dn->start_address + dn->total_size, FLASH_SECTOR_SIZE));
- int esize = fend - faddress;
- if (prvFlashSkipEraseCheck(dn->flash, faddress, fend - faddress))
- {
- dn->skip_erase_flash = 1;
- }
- else
- {
- dn->skip_erase_flash = 0;
- esize = bootSpiFlashEraseNoWait(dn->flash, faddress, fend - faddress);
- OSI_LOGD(0, "FDL2 start flash erase no wait 0x%x/0x%x/%d", dn->start_address, fend - faddress, esize);
- }
- if (esize < 0)
- {
- dn->flash_stage = FLASH_STAGE_NONE;
- OSI_LOGE(0x10009063, "FDL: flash start failed 0x%x/0x%x", dn->start_address, dn->total_size);
- return -BSL_REP_DOWN_DEST_ERROR;
- }
- dn->erase_address += esize;
- dn->flash_stage = FLASH_STAGE_ERASE;
- dn->data_verify = crc32Init();
- return 0;
- }
- /**
- * Flash polling, called in FDL polling, midst and end. Don't access
- * \p dnld.received_size, rather the parameter should be used.
- */
- static void prvFlashPolling(fdlContext_t *d, unsigned received)
- {
- fdlDataDnld_t *dn = &d->dnld;
- if (dn->flash_stage == FLASH_STAGE_NONE ||
- dn->flash_stage == FLASH_STAGE_FINISH)
- return;
- if (dn->flash_stage == FLASH_STAGE_ERASE)
- {
- if (!bootSpiFlashIsDone(dn->flash))
- return;
- dn->flash_stage = FLASH_STAGE_WAIT_DATA;
- }
- else if (dn->flash_stage == FLASH_STAGE_WAIT_DATA)
- {
- int avail = received - (dn->write_address - dn->start_address);
- if (avail < FLASH_PAGE_SIZE || dn->write_address >= dn->erase_address)
- return;
- unsigned waddress = HAL_FLASH_OFFSET(dn->write_address);
- void *wdata = &d->work_mem[dn->write_address % WORKMEM_SIZE];
- int wsize = bootSpiFlashWriteNoWait(dn->flash, waddress, wdata, FLASH_PAGE_SIZE);
- OSI_LOGV(0x10009064, "FDL2 flash write no wait 0x%x/0x%x", waddress, wsize);
- dn->write_address += wsize;
- dn->flash_stage = FLASH_STAGE_WRITE;
- }
- else if (dn->flash_stage == FLASH_STAGE_WRITE)
- {
- if (!bootSpiFlashIsDone(dn->flash))
- return;
- if (dn->write_address < dn->erase_address)
- {
- dn->flash_stage = FLASH_STAGE_WAIT_DATA;
- return;
- }
- unsigned faddress = HAL_FLASH_OFFSET(dn->erase_address);
- unsigned fend = HAL_FLASH_OFFSET(OSI_ALIGN_UP(dn->start_address + dn->total_size, FLASH_SECTOR_SIZE));
- if (faddress >= fend)
- {
- dn->flash_stage = FLASH_STAGE_FINISH;
- return;
- }
- int esize = fend - faddress;
- if (dn->skip_erase_flash != 1)
- {
- esize = bootSpiFlashEraseNoWait(dn->flash, faddress, fend - faddress);
- OSI_LOGD(0, "FDL2 flash erase no wait 0x%x/0x%x/%d", faddress, fend - faddress, esize);
- }
- dn->erase_address += esize;
- dn->flash_stage = FLASH_STAGE_ERASE;
- }
- }
- /**
- * Flash midst
- */
- static void prvFlashMidst(fdlContext_t *d, const void *data, unsigned size)
- {
- fdlDataDnld_t *dn = &d->dnld;
- dn->data_verify = crc32Update(dn->data_verify, data, size);
- // work_mem is reused as ring buffer. The index is address rather than
- // size. So, page write can always use linear buffer.
- unsigned mem_pos = (dn->start_address + dn->received_size) % WORKMEM_SIZE;
- unsigned tail = WORKMEM_SIZE - mem_pos;
- if (tail >= size)
- {
- memcpy(&d->work_mem[mem_pos], data, size);
- }
- else
- {
- memcpy(&d->work_mem[mem_pos], data, tail);
- memcpy(&d->work_mem[0], (const char *)data + tail, size - tail);
- }
- // Polling to make sure there are room for the next packet data.
- unsigned received = dn->received_size + size;
- unsigned received_address = dn->start_address + dn->received_size + size;
- while (received_address - dn->write_address > WORKMEM_SIZE - d->max_packet_len)
- prvFlashPolling(d, received);
- }
- /**
- * Flash end, write the remaining data and check crc.
- */
- static int prvFlashEnd(fdlContext_t *d)
- {
- fdlDataDnld_t *dn = &d->dnld;
- // size may be unaligned. So, polling to make sure the remaining data
- // less than a page.
- unsigned received_address = dn->start_address + dn->received_size;
- while (dn->write_address + FLASH_PAGE_SIZE <= received_address)
- prvFlashPolling(d, dn->received_size);
- // Write the remaining data, if exists.
- bootSpiFlashWaitDone(dn->flash);
- int remained = received_address - dn->write_address;
- if (remained > 0)
- {
- // It is possible that the remaining are located at unerased sector
- unsigned faddress = HAL_FLASH_OFFSET(dn->erase_address);
- unsigned fend = HAL_FLASH_OFFSET(OSI_ALIGN_UP(dn->start_address + dn->total_size, FLASH_SECTOR_SIZE));
- if (faddress < fend)
- {
- int esize = fend - faddress;
- if (dn->skip_erase_flash != 1)
- {
- esize = bootSpiFlashErase(dn->flash, faddress, fend - faddress);
- OSI_LOGD(0, "FDL2 flash erase 0x%x/0x%x/%d", faddress, fend - faddress, esize);
- }
- dn->erase_address += esize;
- }
- unsigned waddress = HAL_FLASH_OFFSET(dn->write_address);
- void *wdata = &d->work_mem[dn->write_address % WORKMEM_SIZE];
- bootSpiFlashWrite(dn->flash, waddress, wdata, remained);
- OSI_LOGV(0x10009066, "FDL2 flash write 0x%x/0x%x", waddress, remained);
- }
- unsigned fstart = HAL_FLASH_OFFSET(dn->start_address);
- const void *fptr = bootSpiFlashMapAddress(dn->flash, fstart);
- unsigned fverify = crc32Calc(fptr, dn->total_size);
- dn->flash_stage = FLASH_STAGE_NONE;
- dn->flash = NULL;
- if (fverify != dn->data_verify)
- {
- OSI_LOGE(0x10009067, "FDL2 flash crc error, start/0x%x size/0x%x crc/0x%x calc/0x%x",
- dn->start_address, dn->total_size, dn->data_verify, fverify);
- return -BSL_REP_VERIFY_ERROR;
- }
- return 0;
- }
- /**
- * Write flash after all data received.
- */
- static int prvFlashWhole(fdlContext_t *d)
- {
- unsigned start_addr = d->dnld.start_address;
- if (d->secure_boot_enable)
- {
- #ifdef CONFIG_SOC_8910
- bool sigcheck = false;
- if (start_addr == CONFIG_BOOT_FLASH_ADDRESS)
- sigcheck = true;
- if (start_addr == CONFIG_APP_FLASH_ADDRESS)
- sigcheck = true;
- #ifdef CONFIG_FDL_FLASH_SIGCHECK_BEFORE_WRITE
- if (start_addr == CONFIG_APPIMG_FLASH_ADDRESS)
- sigcheck = true;
- #endif
- if (sigcheck)
- {
- // It is magic. Boot check size is fixed, and others has 512 is the cert
- // at the end and should be excluded at check.
- unsigned check_size = (start_addr == CONFIG_BOOT_FLASH_ADDRESS)
- ? BOOT_SIGN_SIZE
- : d->dnld.total_size - 512;
- OSI_LOGI(0x100090b0, "FDL: image verify 0x%x size %d", (void *)start_addr, check_size);
- if (!bootSecureEmbeddedSigCheck(d->flash_mem, check_size))
- {
- OSI_LOGE(0x100090b1, "FDL: bootloader secure boot verify fail");
- return -BSL_REP_VERIFY_ERROR;
- }
- if (start_addr == CONFIG_BOOT_FLASH_ADDRESS)
- {
- char *pbuf = d->flash_mem + ENCRYPT_OFF;
- bootAntiCloneEncryption(pbuf, ENCRYPT_LEN);
- }
- }
- #endif
- #ifdef CONFIG_SOC_8811
- bool sigcheck = false;
- if (start_addr == CONFIG_BOOT1_FLASH_ADDRESS ||
- start_addr == CONFIG_BOOT2_FLASH_ADDRESS)
- sigcheck = true;
- if (sigcheck)
- {
- OSI_LOGI(0x100090b0, "FDL: image verify 0x%x size %d", (void *)start_addr, d->dnld.total_size);
- const simageHeader_t *header = (const simageHeader_t *)d->flash_mem;
- if (!bootSimageCheckSign(header))
- {
- OSI_LOGE(0x100090b2, "FDL: secure boot verify fail");
- return -BSL_REP_OPERATION_FAILED;
- }
- }
- #endif
- }
- unsigned end_addr = start_addr + d->dnld.total_size;
- unsigned erase_offset = OSI_ALIGN_DOWN(HAL_FLASH_OFFSET(start_addr), FLASH_SECTOR_SIZE);
- unsigned erase_size = OSI_ALIGN_UP(HAL_FLASH_OFFSET(end_addr) - erase_offset, FLASH_SECTOR_SIZE);
- unsigned write_offset = HAL_FLASH_OFFSET(start_addr);
- unsigned write_size = d->dnld.total_size;
- if (!prvFlashSkipEraseCheck(d->dnld.flash, erase_offset, erase_size))
- {
- if (!bootSpiFlashErase(d->dnld.flash, erase_offset, erase_size))
- return -BSL_REP_VERIFY_ERROR;
- }
- if (!bootSpiFlashWrite(d->dnld.flash, write_offset, d->flash_mem, write_size))
- return -BSL_REP_VERIFY_ERROR;
- // For 8910, modem won't be written as a whole. So, there are no
- // processing after flash is written.
- return 0;
- }
- /**
- * Post check after progressive flash write.
- */
- static int prvFlashPostCheck(fdlContext_t *d)
- {
- unsigned start_addr = d->dnld.start_address;
- (void)start_addr;
- #ifdef CONFIG_SOC_8910
- if (start_addr == CONFIG_FS_MODEM_FLASH_ADDRESS)
- {
- // Modem file system is written by image. So, the block device and
- // file system is changed. And it is needed to umount/mount the
- // block device and file system. The easiest method is to
- // umount/mount all. It will waste some time, and the dynamic memory
- // may be considered in memory tight system.
- fsUmountAll();
- return 0;
- }
- // The followings are only for secure boot
- if (!d->secure_boot_enable)
- return 0;
- if (start_addr == CONFIG_BOOT_FLASH_ADDRESS)
- {
- OSI_LOGI(0x100090b4, "FDL: boot image verify 0x%x size %d", (void *)start_addr, d->dnld.total_size);
- if (!bootSecureEmbeddedSigCheck((void *)start_addr, BOOT_SIGN_SIZE))
- {
- OSI_LOGE(0x100090b1, "FDL: bootloader secure boot verify fail");
- return -BSL_REP_VERIFY_ERROR;
- }
- // reuse the working memory
- char *pbuf = &d->work_mem[0];
- memcpy(pbuf, (void *)(start_addr + ENCRYPT_OFF), FDL_SIZE_4K);
- bootAntiCloneEncryption(pbuf, ENCRYPT_LEN);
- bootSpiFlash_t *flash = bootSpiFlashOpen(DRV_NAME_SPI_FLASH);
- unsigned flash_offset = HAL_FLASH_OFFSET(start_addr);
- if (!bootSpiFlashErase(flash, flash_offset + ENCRYPT_OFF, FDL_SIZE_4K))
- return -BSL_REP_VERIFY_ERROR;
- if (!bootSpiFlashWrite(flash, flash_offset + ENCRYPT_OFF, pbuf, FDL_SIZE_4K))
- return -BSL_REP_VERIFY_ERROR;
- return 0;
- }
- if (start_addr == CONFIG_APP_FLASH_ADDRESS)
- {
- OSI_LOGI(0x100090b5, "FDL: AP image verify 0x%x size %d", (void *)start_addr, d->dnld.total_size);
- // It is magic. 512 is the cert at the end and should be excluded at check.
- if (!bootSecureEmbeddedSigCheck((void *)start_addr, d->dnld.total_size - 512))
- {
- OSI_LOGE(0x100090b1, "FDL: bootloader secure boot verify fail");
- return -BSL_REP_VERIFY_ERROR;
- }
- return 0;
- }
- #ifdef CONFIG_APPIMG_SIGCHECK_ENABLE
- if (start_addr == CONFIG_APPIMG_FLASH_ADDRESS)
- {
- OSI_LOGI(0x100090b6, "FDL: appimg verify 0x%x size %d", (void *)start_addr, d->dnld.total_size);
- // It is magic. 512 is the cert at the end and should be excluded at check.
- if (!bootSecureEmbeddedSigCheck((void *)start_addr, d->dnld.total_size - 512))
- {
- OSI_LOGE(0x100090b1, "FDL: bootloader secure boot verify fail");
- return -BSL_REP_VERIFY_ERROR;
- }
- return 0;
- }
- #endif
- #endif
- #ifdef CONFIG_SOC_8811
- // The followings are only for secure boot
- if (!d->secure_boot_enable)
- return 0;
- if (start_addr == CONFIG_BOOT1_FLASH_ADDRESS ||
- start_addr == CONFIG_BOOT2_FLASH_ADDRESS ||
- start_addr == CONFIG_APP_FLASH_ADDRESS)
- {
- OSI_LOGI(0x100090b0, "FDL: image verify 0x%x size %d", (void *)start_addr, d->dnld.total_size);
- const simageHeader_t *header = (const simageHeader_t *)start_addr;
- if (!bootSimageCheckSign(header))
- {
- OSI_LOGE(0x100090b2, "FDL: secure boot verify fail");
- return -BSL_REP_OPERATION_FAILED;
- }
- return 0;
- }
- #endif
- return 0;
- }
- /**
- * Write one file from cpio.
- */
- static void prvPackageFile(cpioFile_t *f)
- {
- char name[VFS_PATH_MAX + 1] = "/";
- bool isdir = f->mode & S_IFDIR;
- memcpy(name + 1, f->name, strlen(f->name) + 1);
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW
- QUEC_BOOT_LOG("package file %s (%d/%u)", name, isdir, f->data_size);
- #endif
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR
- extern bool quec_spi6_ext_norflash_get_mount_status(void);
- if(!quec_spi6_ext_norflash_get_mount_status())
- {
- if(strncmp(name, CONFIG_FS_SPI6_EXT_NOR_SFFS_MOUNT_POINT, 4) == 0)
- {
- QUEC_BOOT_LOG("/ext is not ready to down file");
- return;
- }
- }
- #endif
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI4_EXTNSFFS
- if(!quec_spi4_exnsffs_is_mount())
- {
- if(strncmp(name, CONFIG_FS_SPI4_EXT_NOR_SFFS_MOUNT_POINT, 6) == 0)
- {
- QUEC_BOOT_LOG("/ext4n is not ready to down file");
- return;
- }
- }
- #endif
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW
- if(strncmp(name, CONFIG_FS_SDCARD_MOUNT_POINT, 7) == 0) //"/sdcard0" || "/sdcard1"
- {
- char *file_name = name + 8; //skip "/sdcard0" || "/sdcard1"
- ql_boot_fat_mount_pt_e pt = (name[7] == '0') ? QL_BOOT_FAT_MOUNT_PARTITION_1 : QL_BOOT_FAT_MOUNT_PARTITION_2;
- if(ql_boot_fat_open_ex(pt,file_name,QL_BOOT_FAT_OPEN_CREATE) == 0) //Only new and read files are supported
- {
- if(ql_boot_fat_write_ex (pt,(const void*)f->data, f->data_size) != f->data_size) //Write data to a file
- {
- QUEC_BOOT_LOG("%s download failed",name);
- return;
- }
- ql_boot_fat_close_ex (pt);
- return;
- }
- QUEC_BOOT_LOG("%s open failed",name);
- return;
- }
- #endif
- OSI_LOGXD(OSI_LOGPAR_SII, 0, "package file %s (%d/%u)", name, isdir, f->data_size);
- if (isdir)
- {
- vfs_mkpath(name, 0);
- }
- else
- {
- vfs_mkfilepath(name, 0);
- vfs_file_write(name, f->data, f->data_size);
- }
- }
- /**
- * BSL_CMD_START_DATA
- * When file system access is needed, it should be chcked here.
- */
- static void prvDataStart(fdlEngine_t *fdl, fdlPacket_t *pkt, fdlContext_t *d)
- {
- int result = 0;
- uint32_t *ptr = (uint32_t *)pkt->content;
- uint32_t start_addr = OSI_FROM_BE32(*ptr++);
- uint32_t file_size = OSI_FROM_BE32(*ptr++);
- OSI_LOGI(0x10009068, "FDL: data start, start_addr/0x%x, size/0x%x", start_addr, file_size);
- d->dnld.start_address = start_addr;
- d->dnld.total_size = file_size;
- d->dnld.received_size = 0;
- if (start_addr == PHASECHECK_LOGIC_ADDRESS)
- {
- #ifdef QUEC_PATCH_FACTORY_UPDATE
- g_upgrade_by_factory = true;
- #endif
- if (file_size != sizeof(phaseCheckHead_t))
- {
- OSI_LOGE(0x100090b7, "FDL: invalid phasecheck data size %d", file_size);
- ERR_REP_RETURN(fdl, BSL_REP_DOWN_SIZE_ERROR);
- }
- if (!prvFsPrepare(d, FS_PREPARE_WRITE_PHASECHEK))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- }
- else if (start_addr == FIXNV_LOGIC_ADDRESS)
- {
- if (file_size > CONFIG_NVBIN_FIXED_SIZE)
- {
- OSI_LOGE(0x100090b8, "FDL: invalid fixnv data size %d", file_size);
- ERR_REP_RETURN(fdl, BSL_REP_DOWN_SIZE_ERROR);
- }
- if (!prvFsPrepare(d, FS_PREPARE_WRITE_FIXEDNV))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- }
- else if (start_addr == PRE_PACK_FILE_LOGIC_ADDRESS)
- {
- if (!prvFsPrepare(d, FS_PREPARE_WRITE_PREPACK))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- cpioStreamCfg_t cfg = {.file_size_max = PACKAGE_FILE_MAX_SIZE, .file_path_max = VFS_PATH_MAX};
- d->cpio = cpioStreamCreate(&cfg);
- if (d->cpio == NULL)
- ERR_REP_RETURN(fdl, BSL_PHONE_NOT_ENOUGH_MEMORY);
- }
- else if (IS_FLASH_ADDRESS(start_addr))
- {
- bootSpiFlash_t *flash = bootSpiFlashOpen(HAL_FLASH_DEVICE_NAME(start_addr));
- if (flash == NULL)
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- d->dnld.flash = flash;
- d->flash_write_whole = false;
- d->dnld.skip_erase_flash = 0;
- #ifdef CONFIG_SOC_8910
- if (d->secure_boot_enable)
- {
- if (start_addr == CONFIG_BOOT_FLASH_ADDRESS)
- d->flash_write_whole = true;
- #ifdef CONFIG_FDL_FLASH_SIGCHECK_BEFORE_WRITE
- if (start_addr == CONFIG_APP_FLASH_ADDRESS)
- d->flash_write_whole = true;
- if (start_addr == CONFIG_APPIMG_FLASH_ADDRESS)
- d->flash_write_whole = true;
- #endif
- }
- #endif
- #ifdef CONFIG_SOC_8811
- if (d->secure_boot_enable)
- {
- if (start_addr == CONFIG_BOOT1_FLASH_ADDRESS ||
- start_addr == CONFIG_BOOT2_FLASH_ADDRESS)
- d->flash_write_whole = true;
- }
- #endif
- if (d->flash_write_whole)
- {
- d->flash_mem = malloc(d->dnld.total_size);
- if (d->flash_mem == NULL)
- ERR_REP_RETURN(fdl, BSL_PHONE_NOT_ENOUGH_MEMORY);
- }
- else
- {
- if ((result = prvFlashStart(d)) < 0)
- ERR_REP_RETURN(fdl, -result);
- }
- }
- else
- {
- OSI_LOGE(0x100090b9, "FDL: invalid data start address 0x%x", start_addr);
- fdlEngineSendRespNoData(fdl, BSL_REP_DOWN_DEST_ERROR);
- return;
- }
- d->dnld.stage = SYS_STAGE_START;
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- }
- /**
- * BSL_CMD_MIDST_DATA
- */
- static void prvDataMidst(fdlEngine_t *fdl, fdlPacket_t *pkt, fdlContext_t *d)
- {
- uint16_t data_len = pkt->size;
- uint32_t start_addr = d->dnld.start_address;
- OSI_LOGD(0x10009069, "FDL: data midst, start_addr/0x%x, size/0x%x, received/0x%x, len/0x%x, stage/0x%x",
- d->dnld.start_address, d->dnld.total_size, d->dnld.received_size,
- data_len, d->dnld.stage);
- if ((d->dnld.stage != SYS_STAGE_START) && (d->dnld.stage != SYS_STAGE_GATHER))
- {
- d->dnld.flash_stage = FLASH_STAGE_NONE;
- d->dnld.flash = NULL;
- ERR_REP_RETURN(fdl, BSL_REP_DOWN_NOT_START);
- }
- if (d->dnld.received_size + data_len > d->dnld.total_size)
- {
- d->dnld.flash_stage = FLASH_STAGE_NONE;
- d->dnld.flash = NULL;
- ERR_REP_RETURN(fdl, BSL_REP_DOWN_SIZE_ERROR);
- }
- if (start_addr == PRE_PACK_FILE_LOGIC_ADDRESS)
- {
- #ifdef __QUEC_OEM_VER_TY__
- static bool isClear = false;
- if (isClear == false)
- {
- vfs_rmchildren(CONFIG_FS_SYS_MOUNT_POINT);
- isClear = true;
- }
- #endif
- cpioStreamPushData(d->cpio, pkt->content, data_len);
- cpioFile_t *f;
- while ((f = cpioStreamPopFile(d->cpio)))
- {
- #if defined(CONFIG_SOC_8910) && defined(CONFIG_APPIMG_LOAD_FILE) && \
- defined(CONFIG_APPIMG_LOAD_FILE_NAME) && defined(CONFIG_APPIMG_SIGCHECK_ENABLE)
- if (d->secure_boot_enable && strcmp(f->name, &CONFIG_APPIMG_LOAD_FILE_NAME[1]) == 0)
- {
- OSI_LOGI(0x1000906a, "FDL: appimg file verify size %d", f->data_size);
- // It is magic. The length of bootSecureEmbeddedSigCheck is raw data plus sig.
- // However, there are 512 bytes cert in appimg.
- if (!bootSecureEmbeddedSigCheck(f->data, f->data_size - 512))
- {
- OSI_LOGE(0x100090b1, "FDL: bootloader secure boot verify fail");
- ERR_REP_RETURN(fdl, BSL_REP_VERIFY_ERROR);
- }
- }
- #endif
- prvPackageFile(f);
- cpioStreamDestroyFile(d->cpio, f);
- }
- }
- else if (IS_FLASH_ADDRESS(start_addr))
- {
- if (d->flash_write_whole)
- memcpy(&d->flash_mem[0] + d->dnld.received_size, pkt->content, data_len);
- else
- prvFlashMidst(d, pkt->content, data_len);
- }
- else if (d->dnld.received_size + data_len > WORKMEM_SIZE)
- {
- ERR_REP_RETURN(fdl, BSL_REP_DOWN_SIZE_ERROR);
- }
- else
- {
- memcpy(&d->work_mem[0] + d->dnld.received_size, pkt->content, data_len);
- }
- d->dnld.received_size += data_len;
- d->dnld.stage = SYS_STAGE_GATHER;
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- }
- /**
- * BSL_CMD_END_DATA
- */
- static void prvDataEnd(fdlEngine_t *fdl, fdlContext_t *d)
- {
- int result = 0;
- uint32_t start_addr = d->dnld.start_address;
- OSI_LOGI(0x1000906b, "FDL: data end, start_addr/0x%x, size/0x%x, received/0x%x, stage/0x%x",
- d->dnld.start_address, d->dnld.total_size, d->dnld.received_size,
- d->dnld.stage);
- if ((d->dnld.stage != SYS_STAGE_START) && (d->dnld.stage != SYS_STAGE_GATHER))
- {
- d->dnld.flash_stage = FLASH_STAGE_NONE;
- d->dnld.flash = NULL;
- ERR_REP_RETURN(fdl, BSL_REP_DOWN_NOT_START);
- }
- if (d->dnld.received_size != d->dnld.total_size)
- {
- d->dnld.flash_stage = FLASH_STAGE_NONE;
- d->dnld.flash = NULL;
- ERR_REP_RETURN(fdl, BSL_REP_DOWN_SIZE_ERROR);
- }
- if (start_addr == PHASECHECK_LOGIC_ADDRESS)
- {
- phaseCheckHead_t *phase_check = (phaseCheckHead_t *)&d->work_mem[0];
- if (!nvmWritePhaseCheck(phase_check))
- {
- OSI_LOGE(0x100090ba, "FDL: write phase check failed");
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- }
- }
- else if (start_addr == FIXNV_LOGIC_ADDRESS)
- {
- char *nvbin = &d->work_mem[0];
- #ifdef QUEC_PATCH_FACTORY_UPDATE
- if (nvmWriteFixedBin_v2(nvbin, d->dnld.received_size, g_upgrade_by_factory) < 0)
- #else
- if (nvmWriteFixedBin(nvbin, d->dnld.received_size) < 0)
- #endif
- {
- OSI_LOGE(0x100090bb, "FDL: write nv bin failed");
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- }
- if (d->phasecheck_backed)
- {
- d->phasecheck_backed = false;
- if (!nvmWritePhaseCheck(&d->phasecheck_back))
- {
- OSI_LOGE(0x100090bc, "FDL: write phasecheck fail after erase all");
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- }
- }
- d->fixednv_backed = false;
- prvCheckClearRunning(d);
- }
- else if (start_addr == PRE_PACK_FILE_LOGIC_ADDRESS)
- {
- cpioStreamDestroy(d->cpio);
- d->cpio = NULL;
- }
- else if (IS_FLASH_ADDRESS(start_addr))
- {
- if (d->flash_write_whole)
- {
- d->flash_write_whole = false;
- result = prvFlashWhole(d);
- free(d->flash_mem);
- d->flash_mem = NULL;
- if (result < 0)
- ERR_REP_RETURN(fdl, -result);
- }
- else
- {
- if ((result = prvFlashEnd(d)) < 0)
- ERR_REP_RETURN(fdl, -result);
- if ((result = prvFlashPostCheck(d)) < 0)
- ERR_REP_RETURN(fdl, -result);
- }
- }
- d->dnld.stage = SYS_STAGE_END;
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- }
- /**
- * BSL_CMD_NORMAL_RESET
- */
- static void prvResetNormal(fdlEngine_t *fdl, fdlContext_t *d)
- {
- OSI_LOGI(0x1000906c, "FDL: reset to normal");
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- osiDelayUS(2000);
- bootReset(BOOT_RESET_NORMAL);
- }
- /**
- * Polling for delayed poweroff
- */
- static void prvPowerOffPolling(fdlContext_t *d)
- {
- if (!d->delay_poweroff)
- return;
- if (BOOT_DNLD_FROM_UART(d->device_type))
- {
- unsigned ms = osiElapsedTime(&d->connect_timer);
- if (ms > DELAY_POWEROFF_TIMEOUT)
- {
- OSI_LOGI(0x1000906d, "FDL: poweroff timeout", ms);
- bootPowerOff();
- // ideally, we shouldn't come here
- OSI_LOGE(0x1000906e, "FDL: poweroff failed");
- d->delay_poweroff = false;
- }
- }
- if (BOOT_DNLD_FROM_USERIAL(d->device_type))
- {
- if (!d->channel->connected(d->channel))
- {
- OSI_LOGI(0x1000906f, "FDL: device not connected, poweroff");
- bootPowerOff();
- // ideally, we shouldn't come here
- OSI_LOGE(0x1000906e, "FDL: poweroff failed");
- d->delay_poweroff = false;
- }
- }
- }
- /**
- * BSL_CMD_POWER_OFF
- */
- static void prvPowerOff(fdlEngine_t *fdl, fdlContext_t *d)
- {
- OSI_LOGI(0x10009070, "FDL: poweroff");
- d->delay_poweroff = true;
- osiElapsedTimerStart(&d->connect_timer);
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- }
- /**
- * BSL_CMD_READ_FLASH
- */
- static void prvReadFlash(fdlEngine_t *fdl, fdlPacket_t *pkt, fdlContext_t *d)
- {
- uint32_t *ptr = (uint32_t *)pkt->content;
- uint32_t addr = OSI_FROM_BE32(*ptr++);
- uint32_t size = OSI_FROM_BE32(*ptr++);
- uint32_t offset = OSI_FROM_BE32(*ptr++); // not all address has this parameter
- if (offset == 0)
- OSI_LOGI(0x10009071, "FDL: read flash, addr/0x%x, size/0x%x, offset/0x%x", addr, size, offset);
- else
- OSI_LOGD(0x10009071, "FDL: read flash, addr/0x%x, size/0x%x, offset/0x%x", addr, size, offset);
- if (addr == PHASECHECK_LOGIC_ADDRESS)
- {
- if (!prvFsPrepare(d, FS_PREPARE_READ_PHASECHECK))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- // reuse the working memory
- phaseCheckHead_t *phase_check = (phaseCheckHead_t *)&d->work_mem[0];
- memset(phase_check, 0, sizeof(phaseCheckHead_t));
- if (!nvmReadPhasecheck(phase_check))
- {
- OSI_LOGE(0x100090bd, "FDL: read phasecheck failed");
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- }
- fdlEngineSendRespData(fdl, BSL_REP_READ_FLASH, phase_check, sizeof(phaseCheckHead_t));
- }
- else if (addr == FIXNV_LOGIC_ADDRESS)
- {
- // Assuming the read will be started with offset 0, and continuous
- char *nvbin = &d->work_mem[0];
- if (offset == 0)
- {
- if (d->fixednv_backed)
- {
- d->fixednv_backed = false;
- memcpy(nvbin, d->fixednv_back, CONFIG_NVBIN_FIXED_SIZE);
- }
- else
- {
- if (!prvFsPrepare(d, FS_PREPARE_READ_FIXEDNV))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- memset(nvbin, 0xff, CONFIG_NVBIN_FIXED_SIZE);
- if (nvmReadFixedBin(nvbin, CONFIG_NVBIN_FIXED_SIZE) < 0)
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- }
- }
- if (offset >= CONFIG_NVBIN_FIXED_SIZE)
- ERR_REP_RETURN(fdl, BSL_REP_INVALID_CMD);
- unsigned send_size = OSI_MIN(unsigned, CONFIG_NVBIN_FIXED_SIZE - offset, size);
- fdlEngineSendRespData(fdl, BSL_REP_READ_FLASH, nvbin + offset, send_size);
- }
- else if (IS_FLASH_ADDRESS(addr))
- {
- bootSpiFlash_t *flash = bootSpiFlashOpen(HAL_FLASH_DEVICE_NAME(addr));
- if (flash == NULL)
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- // valid flash offset not includes the end address
- if (!bootSpiFlashMapAddressValid(flash, (void *)(addr + size - 1)))
- ERR_REP_RETURN(fdl, BSL_REP_INVALID_CMD);
- uint32_t flash_offset = HAL_FLASH_OFFSET(addr);
- const void *fdata = bootSpiFlashMapAddress(flash, flash_offset);
- fdlEngineSendRespData(fdl, BSL_REP_READ_FLASH, fdata, size);
- }
- else
- {
- fdlEngineSendRespNoData(fdl, BSL_REP_INVALID_CMD);
- return;
- }
- }
- /**
- * BSL_CMD_ERASE_FLASH
- */
- static void prvEraseFlash(fdlEngine_t *fdl, fdlPacket_t *pkt, fdlContext_t *d)
- {
- uint32_t *ptr = (uint32_t *)pkt->content;
- uint32_t addr = OSI_FROM_BE32(*ptr++);
- uint32_t size = OSI_FROM_BE32(*ptr++);
- OSI_LOGI(0x10009072, "FDL: erase flash, addr/0x%x, size/0x%x", addr, size);
- if (addr == ERASE_RUNNING_NV_LOGIC_ADDRESS)
- {
- if (!prvFsPrepare(d, FS_PREPARE_ERASE_RUNNINGNV))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- nvmClearRunning(); // ignore error
- d->running_cleared = true;
- }
- else if (addr == PHASECHECK_LOGIC_ADDRESS)
- {
- if (!prvFsPrepare(d, FS_PREPARE_ERASE_PHASECHECK))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- nvmClearPhaseCheck(); // ignore error
- }
- else if (addr == DEL_APPIMG_LOGIC_ADDRESS)
- {
- #if defined(CONFIG_APPIMG_LOAD_FLASH) && defined(CONFIG_APPIMG_LOAD_FILE_NAME)
- if (!prvFsPrepare(d, FS_PREPARE_ERASE_APPIMG_FILE))
- ERR_REP_RETURN(fdl, BSL_REP_INCOMPATIBLE_PARTITION);
- vfs_unlink(CONFIG_APPIMG_LOAD_FILE_NAME); // ignore error
- #endif
- }
- else if (addr == FMT_FLASH_LOGIC_ADDRESS)
- {
- // "size" is the flash block device name
- if (!fsMountFormatFlash(size))
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- }
- else if (FLASH_ERASE_ALL == addr && FLASH_ERASE_ALL_SIZE == size)
- {
- if (prvFsPrepare(d, FS_PREPARE_READ_PHASECHECK) &&
- nvmReadPhasecheck(&d->phasecheck_back))
- d->phasecheck_backed = true;
- if (prvFsPrepare(d, FS_PREPARE_READ_FIXEDNV))
- {
- int nvsize = nvmReadFixedBin(d->fixednv_back, CONFIG_NVBIN_FIXED_SIZE);
- if (nvsize > 0 && nvsize <= CONFIG_NVBIN_FIXED_SIZE)
- d->fixednv_backed = true;
- }
- fsUmountAll();
- bootSpiFlash_t *flash = bootSpiFlashOpen(DRV_NAME_SPI_FLASH);
- if (flash == NULL)
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- uint32_t capcaity = bootSpiFlashCapacity(flash);
- if (!prvFlashSkipEraseCheck(flash, 0, capcaity))
- {
- bootSpiFlashChipErase(flash);
- }
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR
- bootSpiFlash_t *flash_ext = bootSpiFlashOpen(DRV_NAME_SPI_FLASH_EXT);
- if (flash_ext != NULL)
- {
- bootSpiFlashChipErase(flash_ext);
- }
- #else
- #ifdef CONFIG_BOARD_WITH_EXT_FLASH
- bootSpiFlash_t *flash_ext = bootSpiFlashOpen(DRV_NAME_SPI_FLASH_EXT);
- if (flash_ext == NULL)
- ERR_REP_RETURN(fdl, BSL_REP_OPERATION_FAILED);
- uint32_t capcaity_ext = bootSpiFlashCapacity(flash_ext);
- if (!prvFlashSkipEraseCheck(flash_ext, 0, capcaity_ext))
- {
- bootSpiFlashChipErase(flash_ext);
- }
- #endif
- #endif
- }
- else if (IS_FLASH_ADDRESS(addr))
- {
- bootSpiFlash_t *flash = bootSpiFlashOpen(HAL_FLASH_DEVICE_NAME(addr));
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR
- if (flash != NULL)
- {
- uint32_t flash_offset = HAL_FLASH_OFFSET(addr);
- if (!bootSpiFlashErase(flash, flash_offset, size))
- {
- ERR_REP_RETURN(fdl, BSL_REP_INVALID_CMD);
- }
- }
- #else
- uint32_t flash_offset = HAL_FLASH_OFFSET(addr);
- if (!prvFlashSkipEraseCheck(flash, flash_offset, size))
- {
- if (!bootSpiFlashErase(flash, flash_offset, size))
- ERR_REP_RETURN(fdl, BSL_REP_INVALID_CMD);
- }
- #endif
- }
- else
- {
- fdlEngineSendRespNoData(fdl, BSL_REP_INVALID_CMD);
- return;
- }
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- }
- /**
- * BSL_CMD_CHANGE_BAUD
- */
- static void prvSetBaud(fdlEngine_t *fdl, fdlPacket_t *pkt, fdlContext_t *d)
- {
- uint32_t *ptr = (uint32_t *)pkt->content;
- uint32_t baud = OSI_FROM_BE32(*ptr++);
- OSI_LOGD(0x10009073, "FDL: change baud %d", baud);
- // This is special, ACK must be sent in old baud rate.
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- fdlEngineSetBaud(fdl, baud);
- }
- /**
- * Process packet, called by engine.
- */
- static void prvProcessPkt(fdlEngine_t *fdl, fdlPacket_t *pkt, void *param)
- {
- if (fdl == NULL || pkt == NULL)
- osiPanic();
- OSI_LOGV(0x10009074, "FDL: pkt type/0x%x, size/0x%x", pkt->type, pkt->size);
- fdlContext_t *d = (fdlContext_t *)param;
- switch (pkt->type)
- {
- case BSL_CMD_CONNECT:
- prvConnect(fdl, d);
- break;
- case BSL_CMD_START_DATA:
- prvDataStart(fdl, pkt, d);
- break;
- case BSL_CMD_MIDST_DATA:
- prvDataMidst(fdl, pkt, d);
- break;
- case BSL_CMD_END_DATA:
- prvDataEnd(fdl, d);
- break;
- case BSL_CMD_NORMAL_RESET:
- prvResetNormal(fdl, d);
- break;
- case BSL_CMD_READ_FLASH:
- prvReadFlash(fdl, pkt, d);
- break;
- case BSL_CMD_REPARTITION:
- OSI_LOGI(0x100090be, "FDL: repartition");
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- break;
- case BSL_CMD_ERASE_FLASH:
- prvEraseFlash(fdl, pkt, d);
- break;
- case BSL_CMD_POWER_OFF:
- prvPowerOff(fdl, d);
- break;
- case BSL_CMD_CHANGE_BAUD:
- prvSetBaud(fdl, pkt, d);
- break;
- case BSL_CMD_ENABLE_DEBUG_MODE:
- fdlEngineSendRespNoData(fdl, BSL_REP_ACK);
- break;
- default:
- OSI_LOGE(0x100090bf, "FDL: cmd not support yet 0x%x", pkt->type);
- fdlEngineSendRespNoData(fdl, BSL_REP_INVALID_CMD);
- break;
- }
- }
- /**
- * Polling. Called by engine
- */
- static void prvPolling(fdlEngine_t *fdl, void *param)
- {
- fdlContext_t *d = (fdlContext_t *)param;
- prvFlashPolling(d, d->dnld.received_size);
- prvPowerOffPolling(d);
- }
- /**
- * Start download
- */
- bool fdlDnldStart(fdlEngine_t *fdl, unsigned devtype)
- {
- fdlContext_t *d = calloc(1, sizeof(fdlContext_t));
- if (d == NULL)
- return false;
- halPmuExtFlashPowerOn();
- d->device_type = devtype;
- d->channel = fdlEngineGetChannel(fdl);
- d->max_packet_len = fdlEngineGetMaxPacketLen(fdl);
- d->secure_boot_enable = bootSecureBootEnable();
- fsMountSetScenario(FS_SCENRARIO_FDL);
- prvInitNvBinSizeCrc(d);
- #if 0
- /*
- If you want to down file to ext spi6 nor flash, you can open this code to mount it,
- then the file will be download to ext spi6 nor flash
- */
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR
- extern void ql_boot_set_skip_spi6_ext_norflash_init(bool onff);
- OSI_LOGE(0, "demo: boot not skip ext spi6 norflash");
- ql_boot_set_skip_spi6_ext_norflash_init(false);
- #endif
- #endif
- #if 0
- /*
- If you want to down file to extn spi4 nor flash, you can open this code to mount it,
- then the file will be download to extn spi4 nor flash
- */
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI4_EXTNSFFS
- ql_boot_spi4_nor_flash_init(); //Initial spi4 nor Flash
- if(fsMountGeneralSpiFlash(false)) //Mount the SFFS file system
- {
- //Whether to format if the mount fails
- //fsMountGeneralSpiFlash(true); //Format the SFFS file system
- }
- #endif
- #endif
- #if 0
- /*
- If you want to down file to sdmmc, you can open this code to init sdmmc & mount it,
- then the file will be download to "/sdcard0"
- */
- #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW
- #if (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_SDMMC)
- //挂载预置文件的路径选择,可以同时挂载两个分区
- ql_boot_sdmmc_cfg.power_mv = POWER_LEVEL_3200MV; //default sdcard voltage is 3.2 V
- ql_boot_sdmmc_cfg.sdmmc_clk = SDMMC_CLK_FREQ_SDHC; //400000 <= freq <= 50000000,
- //default sdcard clk is 50MHz(SDHC) or 25MHz(NOT SDHC).
- quec_boot_sdmmc_init_ex(QL_BOOT_FAT_MOUNT_PARTITION_1); // "/sdcard0" 挂载分区1,如果没有分区,
- 默认分区1
- //quec_boot_sdmmc_init_ex(QL_BOOT_FAT_MOUNT_PARTITION_2); // "/sdcard1" 挂载分区2
- #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_EMMC)
- //挂载预置文件的路径选择,可以同时挂载两个分区
- ql_boot_sdmmc_cfg.power_mv = POWER_LEVEL_1800MV; //default emmc voltage is 1.8 V
- ql_boot_sdmmc_cfg.sdmmc_clk = SDMMC_CLK_FREQ_SD; //default emmc clk is 25MHz
- quec_boot_emmc_init_ex(QL_BOOT_FAT_MOUNT_PARTITION_1); // "/sdcard0" 挂载分区1,如果没有分区,默认分区1
- //quec_boot_emmc_init_ex(QL_BOOT_FAT_MOUNT_PARTITION_2); // "/sdcard1" 挂载分区2
- #endif
- #endif
- #endif
- #if 0
- /*
- If you want to format user file system when download firmware, you can open this code to do it,
- it will delete all files at the flash partition which for file system.
-
- Be careful,do not open this part of the code,if you have already opened QUEC_PROJECT_FEATURE_PROG_FW_FMTEXT in your target.config.
- */
- fsMountFormat(CONFIG_FS_SYS_MOUNT_POINT);
- #endif
- //20221012 modified by ryan.yi。将TTS改成QUECTEL宏控。无论TTS是否打开,烧录时,默认删除预置文件
- #ifdef CONFIG_QUEC_PROJECT_FEATURE
- vfs_unlink(TTS_PREPACK_FILE_PATH);
- //20210926 之前的版本英文TTS使用此文件名,后续TTS资源文件名将统一使用TTS_PREPACK_FILE_PATH
- vfs_unlink(TTS_EN_PREPACK_FILE_PATH);
- //ryan.yi added 20220217 tts资源文件拆分成多个资源文件
- vfs_unlink(QL_TTS_RESOURCE_APPEND_BIN);
- vfs_unlink(QL_TTS_RESOURCE_END_BIN);
- int i =0;
- char tts_append_name[256] = {0};
- for (i=0; i<QL_TTS_RESOURCE_PACKET_MAX; i++)
- {
- //只是用来先确定有没有预置文件要合并
- memset(tts_append_name, 0x00, sizeof(tts_append_name));
- snprintf(tts_append_name, sizeof(tts_append_name), "/qsfs/quectel_pcm_resource_%02d.bin", i);
- vfs_unlink(tts_append_name);
- }
- #endif
- #ifdef CONFIG_QUEC_PROJECT_FEATURE
- //When downloading, the FOTA stage file is deleted by default, prevent repeated restart failure caused by downloading the file during FOTA upgrade
- vfs_unlink(FUPDATE_STAGE_FILE_NAME);
- #endif
- fdlEngineProcess(fdl, prvProcessPkt, prvPolling, d);
- // In normal case, we won't come here.
- free(d);
- return false;
- }
|