/* Copyright (C) 2018 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. */ #include "hal_config.h" #include "boot_config.h" #include "boot_platform.h" #include "boot_fdl.h" #include "hal_chip.h" #include "boot_debuguart.h" #include "boot_mem.h" #include "boot_entry.h" #include "cmsis_core.h" #include "boot_secure.h" #include "boot_spi_flash.h" #include "boot_vfs.h" #include "boot_mmu.h" #include "boot_timer.h" #include "boot_irq.h" #include "boot_bsl_cmd.h" #include "boot_pdl.h" #include "hal_adi_bus.h" #include "hal_spi_flash.h" #include "flash_block_device.h" #include "fupdate.h" #include "fupdate_security.h" #include "fs_mount.h" #include "osi_log.h" #include "osi_api.h" #include "drv_names.h" #include "calclib/simage.h" #include #include "string.h" #include "boot_efuse.h" #include "hwregs.h" #include "quec_proj_config.h" #include "quec_boot_log.h" #include "quec_boot_pff.h" #include "quec_internal_cfg.h" #ifdef CONFIG_QUEC_PROJECT_FEATURE_FOTA #include "quec_boot_fota.h" #include "quec_boot_pin_cfg.h" #endif #if (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_NAND_FLASH || defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI6_NAND) #include "quec_boot_nand.h" #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_URC #include "quec_boot_uart.h" #endif #ifdef QUEC_PROJECT_FEATURE_BOOT_SD_EMMC #include "quec_boot_sdmmc.h" #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR #include "quec_spi6_ext_norflash_cfg.h" #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI4_EXTNSFFS #include "fs_mount_spiflash.h" #include "ql_boot_spi4_exnsffs_cfg.h" #endif #define ROM_LOADPAR_NORMAL (0) #define ROM_LOADPAR_FROM_BOOT2 (0x10) #define FLASH_SECTOR_SIZE (0x1000) #define FLASH_PAGE_SIZE (256) #define SLAVE_ACCESS_NO (0) #define SLAVE_ACCESS_SECURE_ONLY (1) #define SLAVE_ACCESS_NONSECURE_ONLY (2) #define SLAVE_ACCESS_SECURE_NONESECURE (3) #define AON_WDT_HZ (32768) #define RESTART_WDT_MARGIN_TIME (1800000) #define WDT_RESET_MIN (10) static void bootSetFirewall() { // unset firewall set by sysrom hwp_memFwSpiflash1->seg_0_first_addr = 0xffffffff; hwp_memFwSpiflash1->seg_0_last_addr = 0; hwp_memFwAonImem->seg_0_first_addr = 0xffffffff; hwp_memFwAonImem->seg_0_last_addr = 0; hwp_memFwApImem->seg_0_first_addr = 0xffffffff; hwp_memFwApImem->seg_0_last_addr = 0; hwp_slvFwApAhb->id0_first_addr_0 = 0xffffffff; hwp_slvFwApAhb->id0_last_addr_0 = 0; hwp_slvFwLpsIfc->id0_first_addr_0 = 0xffffffff; hwp_slvFwLpsIfc->id0_last_addr_0 = 0; hwp_slvFwApIfc->id0_first_addr_0 = 0xffffffff; hwp_slvFwApIfc->id0_last_addr_0 = 0; // unset flash,uart,keypad, usb firewall REGT_FIELD_CHANGE(hwp_slvFwApAhb->rd_sec_1, REG_SLV_FW_AP_AHB_RD_SEC_1_T, spiflash1_reg_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->wr_sec_1, REG_SLV_FW_AP_AHB_WR_SEC_1_T, spiflash1_reg_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->rd_sec_1, REG_SLV_FW_AP_AHB_RD_SEC_1_T, med_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->wr_sec_1, REG_SLV_FW_AP_AHB_WR_SEC_1_T, med_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwLpsIfc->rd_sec_0, REG_SLV_FW_LPS_IFC_RD_SEC_0_T, keypad_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwLpsIfc->wr_sec_0, REG_SLV_FW_LPS_IFC_WR_SEC_0_T, keypad_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApIfc->rd_sec_0, REG_SLV_FW_AP_IFC_RD_SEC_0_T, uart4_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApIfc->wr_sec_0, REG_SLV_FW_AP_IFC_WR_SEC_0_T, uart4_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwLpsIfc->rd_sec_0, REG_SLV_FW_LPS_IFC_RD_SEC_0_T, uart1_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwLpsIfc->wr_sec_0, REG_SLV_FW_LPS_IFC_WR_SEC_0_T, uart1_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->rd_sec_1, REG_SLV_FW_AP_AHB_RD_SEC_1_T, usb_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->wr_sec_1, REG_SLV_FW_AP_AHB_WR_SEC_1_T, usb_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); // unset emmc firewall REGT_FIELD_CHANGE(hwp_slvFwApAhb->rd_sec_0, REG_SLV_FW_AP_AHB_RD_SEC_0_T, emmc_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->wr_sec_0, REG_SLV_FW_AP_AHB_WR_SEC_0_T, emmc_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_mstCtrlAp->rd_sec_0, REG_MST_CTRL_AP_RD_SEC_0_T, emmc_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_mstCtrlAp->wr_sec_0, REG_MST_CTRL_AP_WR_SEC_0_T, emmc_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->rd_sec_1, REG_SLV_FW_AP_AHB_RD_SEC_1_T, ce_sec_rd_sec, SLAVE_ACCESS_SECURE_NONESECURE); REGT_FIELD_CHANGE(hwp_slvFwApAhb->wr_sec_1, REG_SLV_FW_AP_AHB_WR_SEC_1_T, ce_sec_wr_sec, SLAVE_ACCESS_SECURE_NONESECURE); } static void bootUsbParamCalibration() { uint32_t usb_cfg; uint8_t tuneotg = 0; uint8_t tfregres = 0; uint8_t tfhsres = 0; bool low = bootEfuseRead(true, HAL_EFUSE_DOUBLE_BLOCK_USB, &usb_cfg); if(low && (usb_cfg & 0x1) == 1) { tfhsres = usb_cfg >> 4; tfregres = usb_cfg >> 9; tuneotg = usb_cfg >> 1; hwp_analogG2->analog_usb20_usb20_trimming &= ~ANALOG_G2_ANALOG_USB20_USB20_TFHSRES(0x1f); hwp_analogG2->analog_usb20_usb20_trimming &= ~ANALOG_G2_ANALOG_USB20_USB20_TFREGRES(0x3f); hwp_analogG2->analog_usb20_usb20_trimming &= ~ANALOG_G2_ANALOG_USB20_USB20_TUNEOTG(0x7); hwp_analogG2->analog_usb20_usb20_trimming |= ANALOG_G2_ANALOG_USB20_USB20_TFHSRES(tfhsres); hwp_analogG2->analog_usb20_usb20_trimming |= ANALOG_G2_ANALOG_USB20_USB20_TFREGRES(tfregres); hwp_analogG2->analog_usb20_usb20_trimming |= ANALOG_G2_ANALOG_USB20_USB20_TUNEOTG(tuneotg); } } OSI_UNUSED static bool bootWdtStart(uint32_t reset_ms) { if (reset_ms < WDT_RESET_MIN) return false; uint32_t reload = (reset_ms * (uint64_t)AON_WDT_HZ) / 1000; REG_PMIC_RTC_ANA_MODULE_EN0_T module_en0; REG_PMIC_RTC_ANA_RTC_CLK_EN0_T rtc_clk_en0; REG_PMIC_WDT_WDG_CTRL_T wdg_ctrl; halAdiBusBatchChange( &hwp_pmicWdt->wdg_ctrl, HAL_ADI_BUS_OVERWITE(0), // wdg_run &hwp_pmicRtcAna->module_en0, REG_FIELD_MASKVAL1(module_en0, wdg_en, 1), &hwp_pmicRtcAna->rtc_clk_en0, REG_FIELD_MASKVAL1(rtc_clk_en0, rtc_wdg_en, 1), &hwp_pmicWdt->wdg_load_high, HAL_ADI_BUS_OVERWITE(reload >> 16), &hwp_pmicWdt->wdg_load_low, HAL_ADI_BUS_OVERWITE(reload & 0xffff), &hwp_pmicWdt->wdg_ctrl, REG_FIELD_MASKVAL2(wdg_ctrl, wdg_open, 1, wdg_rst_en, 1), HAL_ADI_BUS_CHANGE_END); return true; } OSI_UNUSED static void bootWdtStop() { REG_PMIC_RTC_ANA_MODULE_EN0_T module_en0; REG_PMIC_RTC_ANA_RTC_CLK_EN0_T rtc_clk_en0; halAdiBusBatchChange(&hwp_pmicWdt->wdg_ctrl,HAL_ADI_BUS_OVERWITE(0), // wdg_run &hwp_pmicRtcAna->module_en0,REG_FIELD_MASKVAL1(module_en0, wdg_en, 0), &hwp_pmicRtcAna->rtc_clk_en0,REG_FIELD_MASKVAL1(rtc_clk_en0, rtc_wdg_en, 0), HAL_ADI_BUS_CHANGE_END); } static void bootWdtInit() { #ifdef CONFIG_WDT_ENABLE bootWdtStart(RESTART_WDT_MARGIN_TIME); #else // WDT is enabled by default. Later complete WDT management is needed. bootWdtStop(); #endif } OSI_UNUSED static bool prvCheckNormalPowerUp() { #ifndef CONFIG_CHARGER_POWERUP return (bootPowerOnCause() != OSI_BOOTCAUSE_CHARGE); #endif return true; } void bootSetUartIomux() { #ifdef CONFIG_CHIP_8850_V3_BOARD hwp_iomux->gpio_2 = 0x1c; //UART2_cts hwp_iomux->keyout_4 = 0xc; // UART_4_RX hwp_iomux->keyout_5 = 0xc; // UART_4_TX hwp_iomux->keyout_4 &= ~IOMUX_PAD_KEYOUT_4_DRV(0x3); hwp_iomux->keyout_4 |= IOMUX_PAD_KEYOUT_4_DRV(2); hwp_iomux->keyout_4 &= ~IOMUX_WPU; hwp_iomux->keyout_4 |= IOMUX_WPU; hwp_iomux->keyout_5 &= ~IOMUX_PAD_KEYOUT_5_DRV(0x3); hwp_iomux->keyout_5 |= IOMUX_PAD_KEYOUT_5_DRV(2); #else hwp_iomux->gpio_16 = 0x18; //UART2 hwp_iomux->uart_2_cts = 0x10; // UART_4_RX hwp_iomux->uart_2_rts = 0x10; // UART_4_TX hwp_iomux->pad_uart_2_cts &= ~IOMUX_PAD_UART_2_CTS_DRV(0x3); hwp_iomux->pad_uart_2_cts |= IOMUX_PAD_UART_2_CTS_DRV(2); hwp_iomux->pad_uart_2_cts &= ~IOMUX_WPU; hwp_iomux->pad_uart_2_cts |= IOMUX_WPU; hwp_iomux->pad_uart_2_rts &= ~IOMUX_PAD_UART_2_RTS_DRV(0x3); hwp_iomux->pad_uart_2_rts |= IOMUX_PAD_UART_2_RTS_DRV(2); #endif } OSI_UNUSED static bool prvFlashCopy(uint32_t fromaddr, uint32_t toaddr, uint32_t psize) { //OSI_LOGI(0xffffffff, "dual boot copy from 0x%x to 0x%x, size 0x%x", fromaddr, toaddr, psize); bootSpiFlash_t *flash = bootSpiFlashOpen(DRV_NAME_SPI_FLASH); if (flash == NULL) return false; uint32_t to_off = HAL_FLASH_OFFSET(toaddr); uint32_t esize = OSI_ALIGN_UP(psize, FLASH_SECTOR_SIZE); if (!bootSpiFlashErase(flash, to_off, esize)) return false; // bootSpiFlashWrite data can't be located in the same flash // fromaddr should be always sector aligned uint8_t ramdata[FLASH_PAGE_SIZE]; const uint8_t *data = (const uint8_t *)fromaddr; while (psize > 0) { unsigned wr = OSI_MIN(unsigned, psize, FLASH_PAGE_SIZE); memcpy(ramdata, data, wr); if (!bootSpiFlashWrite(flash, to_off, ramdata, wr)) return false; psize -= wr; to_off += wr; data += wr; } return true; } static void prvDualSplCheck(uint32_t param) { //此处不需要检测,展锐代码有问题,spl超过64KB就会死机,所以这里直接跳过 #ifdef CONFIG_QUEC_PROJECT_FEATURE return; #endif if (param == ROM_LOADPAR_NORMAL) { const simageHeader_t *header = (const simageHeader_t *)CONFIG_SPL1_FLASH_ADDRESS; if (header->image_size > CONFIG_SPL_SIZE) osiPanic(); if (memcmp((void *)CONFIG_SPL1_FLASH_ADDRESS, (void *)CONFIG_SPL2_FLASH_ADDRESS, header->image_size) == 0) return; if (!prvFlashCopy(CONFIG_SPL1_FLASH_ADDRESS, CONFIG_SPL2_FLASH_ADDRESS, header->image_size)) osiPanic(); } else if (param == ROM_LOADPAR_FROM_BOOT2) { const simageHeader_t *header = (const simageHeader_t *)CONFIG_SPL2_FLASH_ADDRESS; if (header->image_size > CONFIG_SPL_SIZE) osiPanic(); // Most likely, they are different. However, comparing them anyway. if (memcmp((void *)CONFIG_SPL2_FLASH_ADDRESS, (void *)CONFIG_SPL1_FLASH_ADDRESS, header->image_size) == 0) return; if (!prvFlashCopy(CONFIG_SPL2_FLASH_ADDRESS, CONFIG_SPL1_FLASH_ADDRESS, header->image_size)) osiPanic(); } } static void prvFirmwareUpdatePreProgress(int block_count, int block) { fupdateContentType_t type = FUPDATE_CONTENT_INVALID; type = fupdateGetUpdatingType(); if (type == FUPDATE_CONTENT_FLASH) { fupdateFlashContent_t flash_content = {}; bool result = fupdateGetFlashUpdatingContent(&flash_content); OSI_LOGI(0x10009078, "FUPDATE PreProgress ret %d flash name/offset %4c/0x%x", result, flash_content.device_name, flash_content.offset); } else { OSI_LOGI(0x10009079, "FUPDATE PreProgress current type %d", type); } } static void prvFirmwareUpdateProgress(int block_count, int block) { OSI_LOGI(0x10009056, "FUPDATE block: %d/%d", block, block_count); #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_URC quec_boot_fota_urc_output(block_count, block); #endif } #ifdef QUEC_PROJECT_FEATURE_BOOT_SD_EMMC extern ql_boot_sdmmc_cfg_t ql_boot_sdmmc_cfg; //sdmmc配置 #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE_FOTA extern quec_boot_fs_type_e quec_boot_fs_type; extern ql_boot_fat_mount_pt_e quec_partition_num; static void quec_boot_ext_flash_init() { switch(quec_boot_fs_type) { case QUEC_BOOT_SFFS_EXT: #if (defined CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR) && (!defined CONFIG_APP_FLASH2_ENABLED) && (!defined CONFIG_APPIMG_FLASH2_ENABLED) quec_boot_spi6_ext_norflash_init(); #endif break; case QUEC_BOOT_FAT_SDMMC: //SDMMC1 #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 = QL_BOOT_SDMMC_CLK_FREQ_SDHC; //400000 <= freq <= 50000000, //default sdcard clk is 50MHz(SDHC) or 25MHz(NOT SDHC). #if (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RDONLY) quec_boot_sdmmc_init(quec_partition_num); #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW) quec_boot_sdmmc_init_ex(quec_partition_num); #endif /* CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT */ #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 = QL_BOOT_SDMMC_CLK_FREQ_SD; //default emmc clk is 25MHz #if (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RDONLY) quec_boot_emmc_init(quec_partition_num); #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW) quec_boot_emmc_init_ex(quec_partition_num); #endif /* CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT */ //SDMMC2 #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_SDMMC2) ql_boot_sdmmc_cfg.sdmmc_clk = QL_BOOT_SDMMC_CLK_FREQ_SDHC; //400000 <= freq <= 50000000, //default sdcard clk is 50MHz(SDHC) or 25MHz(NOT SDHC). #if (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RDONLY) quec_boot_sdmmc2_init(quec_partition_num); #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW) quec_boot_sdmmc2_init_ex(quec_partition_num); #endif /* CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT */ #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_EMMC2) ql_boot_sdmmc_cfg.sdmmc_clk = QL_BOOT_SDMMC_CLK_FREQ_SD; //default emmc clk is 25MHz #if (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RDONLY) quec_boot_emmc2_init(quec_partition_num); #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT_RW) quec_boot_emmc2_init_ex(quec_partition_num); #endif /* CONFIG_QUEC_PROJECT_FEATURE_BOOT_FAT */ #endif /* CONFIG_QUEC_PROJECT_FEATURE_BOOT_SDMMC */ break; case QUEC_BOOT_FAT_EXNAND_FLASH: #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_NAND_FLASH quec_boot_nand_init(QL_BOOT_SPI_PORT_1); #elif (defined CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI6_NAND) quec_boot_nand_init_spi6(QL_BOOT_SPI_PORT_1,QL_BOOT_NAND_TYPE_QUAD_SPI); //quec_boot_nand_init_spi6(QL_BOOT_SPI_PORT_1,QL_BOOT_NAND_TYPE_DUAL_SPI); /*ql_boot_spi6_nand_config_s config = { .port = QL_BOOT_SPI_PORT_1, .clk = BOOT_SPI6_NAND_FLASH_CLK_200MHZ, //时钟源 .clk_div = 5, //再分频 ,flash时钟=clk/clk_div .quad_mode = 1, .sample_delay = 3, //此值与clk和驱动能力相关,需要配置波形设置(主要用于调节数据的采样点在时钟的有效位置,尽可能的在中间),一般频率越高此值越大 .isslow = 0, }; quec_boot_nand_init_spi6_ex(config);*/ #endif break; case QUEC_BOOT_SFFS_SPI4EXTNOR: #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI4_EXTNSFFS ql_boot_spi4_nor_flash_init(); fsMountGeneralSpiFlash(false); #endif break; default: break; } } #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR //是否在boot中跳过初始化Spi6ExtNor,为了兼容不使用Spi6ExtNor,用作其他功能的用户 extern bool quec_skip_spi6_ext_nor_flash_init; #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE extern void quec_boot_fota_force_finish(void); #endif OSI_UNUSED static fupdateResult_t prvFirmwareUpdate(void) { #ifdef CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR //如果是外置flash挂载成UFS分区,不能在挂载成EFS所以要跳过挂载EFS分区。 //如果是外置flash不挂载成UFS分区且使能xip和自动挂载功能,fsMountAll时需要将外置flash挂载成EFS(/ext)。 if(ql_ext_flash_cfg.xip_flag && ql_ext_flash_cfg.mount_sffs_flag && QUEC_EXT_FLASH_TO_UFS != ql_ext_flash_cfg.ufs_mapping_select) { //if defined CONFIG_APP_FLASH2_ENABLED || CONFIG_APPIMG_FLASH2_ENABLED,it will check ext flash during fota upgrade. //so,here need to initialize ext flash first,otherwise old flash crc mismatch. quec_skip_spi6_ext_nor_flash_init = false;//在fsMountAll时挂载外置flash } else { quec_skip_spi6_ext_nor_flash_init = true;//在fsMountAll时跳过Spi6ExtNor初始化和挂载 } #endif fsMountSetScenario(FS_SCENRARIO_BOOTLOADER); if (!fsMountAll()) return FUPDATE_RESULT_NOT_READY; #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI4_NORFLASH void quec_boot_spi4_nor_flash_example(); //quec_boot_spi4_nor_flash_example(); #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE_FOTA quec_boot_fota_init(); quec_boot_ext_flash_init(); #endif //默认关闭,如果需要检查签名可以在components\firmwareupdate\Kconfig或者target_config中自行打开CONFIG_FUPDATE_SUPPORT_SIGNATURE_CHECK宏 #ifdef CONFIG_FUPDATE_SUPPORT_SIGNATURE_CHECK //quectel update bool check = fupdateCheckSignedPack(); if (!check) { OSI_LOGE(0x10009057, "FUPDATE sign check failed"); fsUmountAll(); return FUPDATE_RESULT_NOT_READY; } #endif #ifdef CONFIG_FUPDATE_SUPPORT_CHECK_TMP_SPACE //默认关闭,在kernel中检查 #ifdef CONFIG_QUEC_PROJECT_FEATURE fupdateStatus_t state = fupdateGetStatus(); if (state == FUPDATE_STATUS_READY) #else if (fupdateGetStatus() == FUPDATE_STATUS_READY) #endif { bool fcheck = fupdateIsTmpSpaceEnough(); //quectel update if (!fcheck) { #ifdef CONFIG_QUEC_PROJECT_FEATURE if (state == FUPDATE_STATUS_READY) { //防止校验不通过,开不了机 quec_boot_fota_force_finish(); } #endif fsUmountAll(); return FUPDATE_RESULT_CANNT_START; } } #endif #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_URC quec_boot_urc_init(); #endif //urc fota start #ifdef CONFIG_QUEC_PROJECT_FEATURE_FOTA //Check whether the FOTA package is correct in boot.This code cannot be masked. quec_boot_fota_pack_verify(); #endif #ifdef CONFIG_QL_OPEN_EXPORT_PKG #if 0 /* 可视情况使用,如果按正常流程,内核验证完后,复位,中途不会有pack包的修改操作,不用开 这部分代码会占用boot 1632bytes */ bool space_ok = fupdateIsTmpSpaceEnough(); if (!space_ok) { OSI_LOGI(0, "no space"); return; } #endif #endif //fupdateResult_t result = fupdateRun(prvFirmwareUpdateProgress); fupdateResult_t result = fupdateRunV2(prvFirmwareUpdatePreProgress, prvFirmwareUpdateProgress); OSI_LOGI(0x10009058, "FUPDATE: %d", result); //urc fota end err_code if (result == FUPDATE_RESULT_FAILED) bootReset(BOOT_RESET_NORMAL); // 解决FOTA升级后,查询FOTA空间多出fota.type文件的问题 #ifndef CONFIG_QUEC_PROJECT_FEATURE_FOTA else if (result == FUPDATE_RESULT_FINISHED) fupdateSetBootAfterFota(FUPDATE_RESULT_FINISHED); #endif fsUmountAll(); return result; } static bool splVerifySimage(simageHeader_t *header, unsigned max_size) { if (!simageValid(header, max_size)) return false; #ifdef CONFIG_QUEC_PROJECT_FEATURE_SECURE_BOOT return bootSimageCheckSign(header); #else return true; #endif } // check the signatures of SML, TOS, Boot, App static simageHeader_t *splCheckSignatures() { simageHeader_t *header_go = NULL; simageHeader_t *header_verify = NULL; // boot header_verify = (simageHeader_t *)CONFIG_APP_RAM_ADDRESS; memcpy(header_verify, (void *)CONFIG_BOOT_FLASH_ADDRESS, CONFIG_BOOT_FLASH_SIZE); if (!splVerifySimage(header_verify, CONFIG_BOOT_FLASH_SIZE)) return NULL; header_go = header_verify; // app header_verify = (simageHeader_t *)CONFIG_APP_FLASH_ADDRESS; if (!splVerifySimage(header_verify, CONFIG_APP_FLASH_SIZE)) return NULL; #ifdef CONFIG_TRUSTZONE_SUPPORT // sml header_verify = (simageHeader_t *)CONFIG_TZ_SML_FLASH_ADDRESS; if (!splVerifySimage(header_verify, CONFIG_TZ_SML_FLASH_SIZE)) return NULL; memcpy((void *)header_verify->data_entry, (void *)(CONFIG_TZ_SML_FLASH_ADDRESS + header_verify->data_offset), header_verify->data_size); header_go = header_verify; // tos header_verify = (simageHeader_t *)CONFIG_TZ_TOS_FLASH_ADDRESS; if (!splVerifySimage(header_verify, CONFIG_TZ_TOS_FLASH_SIZE)) return NULL; memcpy((void *)header_verify->data_entry, (void *)(CONFIG_TZ_TOS_FLASH_ADDRESS + header_verify->data_offset), header_verify->data_size); #endif return header_go; } static void prvSetFlashWriteProhibit(void) { // ATTENTION: This will set write prohibit for bootloader // // If there are requiement (though not reasonable) to change bootloader // the followings should be changed. And when there are more regions are // known never changed, more regions can be added. bootSpiFlash_t *flash = bootSpiFlashOpen(HAL_FLASH_DEVICE_NAME(CONFIG_BOOT_FLASH_ADDRESS)); bootSpiFlashSetRangeWriteProhibit(flash, HAL_FLASH_OFFSET(CONFIG_BOOT_FLASH_ADDRESS), HAL_FLASH_OFFSET(CONFIG_BOOT_FLASH_ADDRESS) + CONFIG_BOOT_FLASH_SIZE); } /********************************************************************************************************************************* * example: how to set pin function as gpio and how to set or get gpio level (take GPIO0 as an example) * Attention: 1. the register name can refer to quec_pin_cfg_ECXXXG.c; 2. gpio corresponding function can refer to quec_pin_cfg_ECXXXG.c; 3. some pins need to open the voltage domain before use , V_PAD_1V8 voltage domain is on by default and does not need to be set ***********************************************************************************************************************************/ void quec_boot_gpio_example() { //set GPIO_0 as gpio function hwp_iomux->gpio_0 = (0 << 2); /*** Output High Level ***/ //set GPIO_0 direction to output // if GPIO num < 16 hwp_gpio1->gpio_clr_reg = (1 << 0); hwp_gpio1->gpio_oen_set_out = (1 << 0); // if GPIO num > 16 (example GPIO17) //hwp_gpio2->gpio_clr_reg = (1 << (17 - 16)); //hwp_gpio2->gpio_oen_set_out = (1 << (17 - 16)); //set GPIO_0 output high level // if GPIO num < 16 hwp_gpio1->gpio_set_reg = (1 << 0); // if GPIO num > 16 (example GPIO17) //hwp_gpio2->gpio_set_reg = (1 << (17 - 16)); //set GPIO_0 output low level // if GPIO num < 16 //hwp_gpio1->gpio_clr_reg = (1 << 0); // if GPIO num > 16 (example GPIO17) //hwp_gpio2->gpio_clr_reg = (1 << (17 - 16)); /*** Input Pull Up ***/ //set GPIO_0 direction to input // if GPIO num < 16 //hwp_gpio1->gpio_oen_set_in = (1 << 0); // if GPIO num > 16 (example GPIO17) //hwp_gpio2->gpio_oen_set_in = (1 << (17 - 16)); //set GPIO_0 input pull_up // Attention!!! It's anareg!!! have a extra [pad] in reg name!!! //hwp_iomux->pad_gpio_0 &= ~(1<<6); //wpdo = 0 //hwp_iomux->pad_gpio_0 |= (1<<7); //wpu = 1 //hwp_iomux->pad_gpio_0 &= ~(1<<12); //wpus = 0 //get gpio level status, gpio_lvl=1 indicates high level, gpio_lvl=0 indicates low level // if GPIO num < 16 uint32_t reg_value = hwp_gpio1->gpio_set_reg & (1 << 0); // if GPIO num > 16 (example GPIO17) //uint32_t reg_value = hwp_gpio2->gpio_set_reg & (1 << 17); int gpio_lvl = (reg_value >> 0) & 0x1; OSI_LOGI(0, "gpio_lvl=%d", gpio_lvl); } /********************************************************************************************************************************* * example: how to use spi4 nor flash in boot * Attention: 1. the SPI port currently used in boot,it can be configured in quec_boot_pin_cfg.h; ***********************************************************************************************************************************/ #ifdef CONFIG_QUEC_PROJECT_FEATURE_BOOT_SPI4_NORFLASH #include "quec_boot_spi.h" #include "ql_boot_spi4_nor_flash.h" //Note:the SPI port currently used in boot,it can be configured in quec_boot_pin_cfg.h extern uint8_t ql_boot_cur_spi4_port; void quec_boot_spi4_nor_flash_example() { //Initialize pin to SPI function quec_boot_spi_pin_init(ql_boot_cur_spi4_port); //Configure nor Flash initialization parameters ql_boot_spi_nor_config_s flash_config = {0}; flash_config.port = ql_boot_cur_spi4_port; flash_config.spiclk = QL_BOOT_SPI_CLK_25MHZ; flash_config.input_sel = QL_BOOT_SPI_DI_1; flash_config.transmode = QL_BOOT_SPI_DIRECT_POLLING;//BOOT中不支持DMA模式 flash_config.cs = QL_BOOT_SPI_CS0; ql_boot_spi_nor_init_ext(flash_config); OSI_LOGI(0, "ql_boot_spi4_nor_flash_init"); unsigned int addr = 0x000008; unsigned int len = 0; unsigned char *data = NULL; int i = 0; if(ql_boot_spi_nor_erase_sector(ql_boot_cur_spi4_port, addr) != QL_BOOT_SPI_SUCCESS) { return; } len = 1024; data = bootExtRamCalloc(1,len+1); if (data == NULL) { return; } for (i = 0; i < len; i++) { data[i] = 'b'; } QUEC_BOOT_LOG("write data:%s", data); if(ql_boot_spi_nor_write(ql_boot_cur_spi4_port, data, addr, len) == QL_BOOT_SPI_SUCCESS) { memset(data,0x00,len+1); ql_boot_spi_nor_read(ql_boot_cur_spi4_port, data, addr, len); QUEC_BOOT_LOG("read data:%s", data); } bootFree(data); } #endif void bootStart(uint32_t param) { OSI_CLEAR_SECTION(bss); bootSpiFlashOpen(DRV_NAME_SPI_FLASH); // ensure accessible halClockInit(HAL_CLOCK_INIT_BOOTLOADER); bootSetFirewall(); bootUsbParamCalibration(); halRamInit(); bootMmuEnable(); __FPU_Enable(); _REENT_INIT_PTR_ZEROED(_impure_ptr); halAdiBusInit(); bootResetPinEnable(); bootWdtInit(); bootGetEfuseCtx(); #if 0 if (bootIsFromPsmSleep()) { #ifdef CONFIG_TRUSTZONE_SUPPORT simageHeader_t *header = bootloaderJumpImageEntry(); if(header == NULL) goto failed; SmlJumpImageEntry(); #else simageHeader_t *header = (simageHeader_t *)CONFIG_APP_FLASH_ADDRESS; simageJumpEntry(header, OSI_SHUTDOWN_PSM_SLEEP); // never return #endif } #endif if (!prvCheckNormalPowerUp()) { osiDelayUS(1000 * 10); bootPowerOff(); #ifdef CONFIG_QUEC_PROJECT_FEATURE while(1); // 上电后,若插上USB,boot层会跑到这里满足if条件,执行强制关机 // 但关机需要一段时间,boot层代码会继续执行到prvFirmwareUpdate中的fsMountAll才完成关机 // 添加while(1)是为了避免boot层代码的继续执行,在此等待关机完成 #endif } bool trace_enable = false; #ifdef CONFIG_BOOT_LOG_ENABLED trace_enable = true; #endif bootSetUartIomux(); bootTraceInit(trace_enable); bootPlatformInit(); extern uint32_t __sram_heap_start[]; extern uint32_t __sram_heap_end[]; extern uint32_t __ram_heap_start[]; extern uint32_t __ram_heap_end[]; unsigned sram_heap_size = OSI_PTR_DIFF(__sram_heap_end, __sram_heap_start); unsigned ram_heap_size = OSI_PTR_DIFF(__ram_heap_end, __ram_heap_start); bootHeapInit(__sram_heap_start, sram_heap_size, __ram_heap_start, ram_heap_size); bootHeapDefaultExtRam(); #ifndef CONFIG_QUEC_PROJECT_FEATURE halPmuExtFlashPowerOn(); #else #if (defined CONFIG_QUEC_PROJECT_FEATURE_EXT_MAPPING_UFS || defined CONFIG_QUEC_PROJECT_FEATURE_SPI6_EXT_NOR) //1、如果是外置flash挂载成UFS分区,需要先初始化外置flash,否则fsMountAll时会有问题 //2、如果使能外置flash使用xip功能,都初始化外置flash if(ql_ext_flash_cfg.xip_flag) { halPmuExtFlashPowerOn(); } #endif #endif fupdateResult_t result = prvFirmwareUpdate(); if(result == FUPDATE_RESULT_FINISHED) { #ifdef CONFIG_QUEC_PROJECT_FEATURE OSI_LOGI(0, "update done rst"); osiDelayUS(1000 * 10); //加点延时避免有log来不及打印就复位了 #endif bootReset(BOOT_RESET_NORMAL); } prvDualSplCheck(param); //bootloader 写保护功能默认开启 prvSetFlashWriteProhibit(); #ifdef CONFIG_QUEC_PROJECT_FEATURE_SECURE_BOOT if (!bootUpdateVersion()) goto failed; #endif simageHeader_t *header = splCheckSignatures(); if(header == NULL) goto failed; simageJumpEntry(header, 0); // never return failed: OSI_DEAD_LOOP; }