#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")

本文深入解析GD全局数据结构及其寄存器优化技术,详细讲解了如何通过寄存器r8存储gd_t类型指针,以及GD全局数据结构在系统初始化阶段的配置与作用。

register volatile gd_t *gd asm ("r8")

如下的两个结构,我们主要的是关心下面一行声明:
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

这个声明告诉编译器使用寄存器r8来存储gd_t类型的指针gd,即这个定义声明了一个指针,并且指明了它的存储位置。
register表示变量放在机器的寄存器
volatile用于指定变量的值可以由外部过程异步修改

并且这个指针在start_armboot()(board.c)中被初始化:
    /* Pointer is writable since we allocated a register for it */
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

这样,gd就指向的一个可用的内存地址了。

==============================================================
typedef struct bd_info {
    unsigned long        bi_baudrate;
    unsigned long        bi_ip_addr;
    unsigned char        bi_enetaddr[6];
    unsigned char        bi_phy_id[4];
    struct environment_s    *bi_env;
    unsigned long        bi_board_number;
    void            *bi_boot_params;
    struct {
        unsigned long    start;
        unsigned long    size;
    }            bi_dram[CONFIG_NR_DRAM_BANKS];
    unsigned long        bi_flashstart;
    unsigned long        bi_flashsize;
    unsigned long        bi_flashoffset;
} bd_t;


#ifndef    __ASM_GBL_DATA_H
#define __ASM_GBL_DATA_H
/*
* The following data structure is placed in some memory wich is
* available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
* some locked parts of the data cache) to allow for a minimum set of
* global variables during system initialization (until we have set
* up the memory controller so that we can use RAM).
*
* Keep it *SMALL* and remember to set CFG_GBL_DATA_SIZE > sizeof(gd_t)
*/

typedef    struct    global_data {
    bd_t        *bd;
    unsigned long    flags;
    unsigned long    baudrate;
    unsigned long    have_console;    /* serial_init() was called */
    unsigned long    reloc_off;    /* Relocation Offset */
    unsigned long    env_addr;    /* Address of Environment struct */
    unsigned long    env_valid;    /* Checksum of Environment valid? */
    unsigned long    fb_base;    /* base address of frame buffer */
#ifdef CONFIG_VFD
    unsigned char    vfd_type;    /* display type */
#endif
#if 0
    unsigned long    cpu_clk;    /* CPU clock in Hz!        */
    unsigned long    bus_clk;
    unsigned long    ram_size;    /* RAM size */
    unsigned long    reset_status;    /* reset status register at boot */
#endif
    void        **jt;        /* jump table */
} gd_t;

/*
* Global Data Flags
*/
#define    GD_FLG_RELOC    0x00001        /* Code was relocated to RAM        */
#define    GD_FLG_DEVINIT    0x00002        /* Devices have been initialized    */
#define    GD_FLG_SILENT    0x00004        /* Silent mode                */

#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

#endif /* __ASM_GBL_DATA_H */
// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2021 Netfactory */ #include <common.h> #include <cpu_func.h> #include <debug_uart.h> #include <hang.h> #include <init.h> #include <asm/global_data.h> #include <spl.h> #include <cli.h> #include <linux/delay.h> #include <spi_flash.h> #include <asm/io.h> #include "nand.h" //#include "ddr_init.h" //#if BOOT_OS_LITEOS /*LITEOS 单NOR,双NOR,片外双BOOT 启动场景1*/ #define CONFIG_NORDOUBOOT_LITEOS_MAIN 0xC0000 #define CONFIG_NORDOUBOOT_LITEOS_BACKUP 0x4C0000 /*LITEOS 单NOR,双NOR,片内,片外*/ #define CONFIG_NORBOOT_LITEOS_MAIN 0x140000 #define CONFIG_NORBOOT_LITEOS_BACKUP 0x540000 //#define CONFIG_NORBOOT_UBOOT_MAIN 0x140000 //#define CONFIG_NORBOOT_UBOOT_BACKUP 0x2C0000 //#else /*Linux 2M nand 分区大小 片内片外*/ #define CONFIG_2M_NANDBOOT_UBOOT_MAIN 0x600000 #define CONFIG_2M_NANDBOOT_UBOOT_BACKUP 0xE00000 /*Linux 4M nand 分区大小 片内片外*/ #define CONFIG_4M_NANDBOOT_UBOOT_MAIN 0xC00000 #define CONFIG_4M_NANDBOOT_UBOOT_BACKUP 0x1400000 /*Linux FMC1 NOR 双boot*/ #define CONFIG_NORDOUBOOT_UBOOT_MAIN (0x800000 + 0x10000000) #define CONFIG_NORDOUBOOT_UBOOT_BACKUP (0xC00000 + 0x10000000) /*Linux FMC1 NOR 片内安全*/ #define CONFIG_NORBOOT_UBOOT_MAIN (0x140000 + 0x10000000) #define CONFIG_NORBOOT_UBOOT_BACKUP (0x540000 + 0x10000000) /*片外片内norflash启动 */ //#define CONFIG_NORBOOT_UBOOT_MAIN 0x300000 //#define CONFIG_NORBOOT_UBOOT_BACKUP 0x700000 //#endif #if 0 /* 片外nor硬件双boot */ #define CONFIG_STARTCODE_NORBOOT_UBOOT_MAIN 0x140000 //to be fix #define CONFIG_STARTCODE_NORBOOT_UBOOT_BACKUP 0xc00000 //to be fix /* nand启动 */ #define CONFIG_NANDBOOT_UBOOT_MAIN 0xC00000 #define CONFIG_NANDBOOT_UBOOT_BACKUP 0x1400000 #endif DECLARE_GLOBAL_DATA_PTR; unsigned int spl_get_mru_reg(uint64_t addr) { return (*(volatile unsigned int*)(addr)); } unsigned int spl_get_bootsel(void) { unsigned int bootsel = spl_get_mru_reg(MRU_CFG1); return ((bootsel & MRU_CFG1_BOOTSEL_MASK) >> MRU_CFG1_BOOTSEL_SHIFT); } #ifdef EXEC_ENV_2125_EVB unsigned long spl_nor_get_uboot_base(void) { unsigned int bootmod = ((spl_get_mru_reg(MRU_CFG1) & MRU_CFG1_BOOTMOD_MASK ) >> MRU_CFG1_BOOTMOD_SHIFT); unsigned int bootsel1 = (spl_get_bootsel() >> 0x1); unsigned int mru_remap = spl_get_mru_reg(MRU_REMAP); unsigned int mru_reg7 = (spl_get_mru_reg(MRU_REG7) & 0x1); unsigned int ns_forbid = spl_get_mru_reg(SEC_NS_FORBIT); if (ns_forbid != NONE_SECURE_BOOT_FLAG) { printf("SPL: secure boot, nsforbid(%u)\n", ns_forbid); printf("SPL: boot area %s, mrureg7(%u)\n", (mru_reg7 ? "back" : "main"), mru_reg7); #if BOOT_OS_LITEOS return (mru_reg7 ? CONFIG_NORBOOT_LITEOS_BACKUP : CONFIG_NORBOOT_LITEOS_MAIN); #else return (mru_reg7 ? (CONFIG_NORBOOT_UBOOT_BACKUP - 0x10000000) : (CONFIG_NORBOOT_UBOOT_MAIN - 0x10000000)); #endif } /* 片内rom启动 */ if (bootmod == 0x1) { printf("SPL: boot from %s, bootmod(%u)\n", (bootmod ? "rom" : "norflash"), bootmod); printf("SPL: boot area %s, mru_reg7(%u)\n", (mru_reg7 ? "backup" : "main"), mru_reg7); #if BOOT_OS_LITEOS return (mru_reg7 ? CONFIG_NORBOOT_LITEOS_BACKUP : CONFIG_NORBOOT_LITEOS_MAIN); #else return (mru_reg7 ? (CONFIG_NORBOOT_UBOOT_BACKUP - 0x10000000) : (CONFIG_NORBOOT_UBOOT_MAIN - 0x10000000)); #endif } printf("SPL: boot from %s, bootsel1(%u)\n", (bootsel1 ? "norflash remap is disabled" : "norflash remap is enabled"), bootsel1); /* 片外nor双boot启动 */ if (bootsel1 == 0x0) { printf("SPL: boot %s, mru_remap(%u)\n", (mru_remap ? "backup" : "main"), mru_remap); #if BOOT_OS_LITEOS return (mru_reg7 ? CONFIG_NORDOUBOOT_LITEOS_BACKUP : CONFIG_NORDOUBOOT_LITEOS_MAIN); #else return (mru_reg7 ? (CONFIG_NORDOUBOOT_UBOOT_BACKUP - 0x10000000) : (CONFIG_NORDOUBOOT_UBOOT_MAIN - 0x10000000)); #endif } /* 片外nof启动,带safetycode */ printf("SPL: boot from %s, mru_reg7(%u)\n", (mru_reg7 ? "backup" : "main"), mru_reg7); #if BOOT_OS_LITEOS return (mru_reg7 ? CONFIG_NORBOOT_LITEOS_BACKUP : CONFIG_NORBOOT_LITEOS_MAIN); #else return (mru_reg7 ? (CONFIG_NORBOOT_UBOOT_BACKUP - 0x10000000) : (CONFIG_NORBOOT_UBOOT_MAIN - 0x10000000)); #endif } #else unsigned int spl_get_spinor_doubleboot(void) { unsigned int bootmod = ((spl_get_mru_reg(MRU_CFG1) & MRU_CFG1_BOOTMOD_MASK ) >> MRU_CFG1_BOOTMOD_SHIFT); unsigned int bootsel = spl_get_bootsel(); unsigned int bootsel0 = (bootsel >> 0 ) & 0x1; unsigned int bootsel1 = (bootsel >> 1 ) & 0x1; unsigned int bootsel2 = (bootsel >> 2 ) & 0x1; unsigned int bootsel3 = (bootsel >> 3 ) & 0x1; /*仅当片外Nor启动:BOOT_SEL1 表示 SPI Nor双boot使能*/ if (bootmod == 0x0) //片外启动 { if(bootsel0 == 0 && bootsel2 == 0) //从FMC0 启动 NOR 启动 { printf_spl("SPL: boot from fmc0 %s, bootsel1(%u)\n", (bootsel1 ? "norflash remap is disabled" : "norflash remap is enabled"), bootsel1); return 0; } if(bootsel0 == 1 && bootsel3 == 1) {//从FMC1 启动 NOR 启动 printf_spl("SPL: boot from fmc1 %s, bootsel1(%u)\n", (bootsel1 ? "norflash remap is disabled" : "norflash remap is enabled"), bootsel1); return 0; } return -1; } else { return -1; } } unsigned long spl_nor_get_uboot_base(void) { unsigned int bootmod = ((spl_get_mru_reg(MRU_CFG1) & MRU_CFG1_BOOTMOD_MASK ) >> MRU_CFG1_BOOTMOD_SHIFT); unsigned int bootsel = spl_get_bootsel(); unsigned int bootsel0 = (bootsel >> 0 ) & 0x1; unsigned int bootsel1 = (bootsel >> 1 ) & 0x1; unsigned int bootsel2 = (bootsel >> 2 ) & 0x1; unsigned int mru_remap = spl_get_mru_reg(MRU_REMAP); unsigned int mru_reg7 = (spl_get_mru_reg(MRU_REG7) & 0x1); unsigned int ns_forbid = spl_get_mru_reg(SEC_NS_FORBIT); printf_spl("SPL: %s secure boot, nsforbid(%u)\n", (ns_forbid == NONE_SECURE_BOOT_FLAG ? "non" : ""), ns_forbid); printf_spl("SPL: boot from %s, bootmod(%u)\n", (bootmod ? "rom" : "norflash"), bootmod); spl_get_spinor_doubleboot(); #if BOOT_OS_LITEOS /*启动方式1 无管理双boot*/ if (ns_forbid == NONE_SECURE_BOOT_FLAG && bootmod == 0 && bootsel0 == 0 && bootsel1 == 0 && bootsel2 == 0) { printf_spl("SPL: boot %s, mru_remap(%u)\n", (mru_remap ? "back" : "main"), mru_remap); return (mru_reg7 ? CONFIG_NORDOUBOOT_LITEOS_BACKUP : CONFIG_NORDOUBOOT_LITEOS_MAIN); } /*启动方式2, 9, 14*/ if ((ns_forbid == NONE_SECURE_BOOT_FLAG && bootmod == 0 && bootsel0 == 0 && bootsel2 == 0 && bootsel1 == 1) || \ (ns_forbid == NONE_SECURE_BOOT_FLAG && bootsel0 == 0 && bootsel2 == 0 && bootmod == 1) || \ (ns_forbid != NONE_SECURE_BOOT_FLAG && bootsel0 == 0 && bootsel2 == 0 )) { printf_spl("SPL: boot area %s, mrureg7(%u)\n", (mru_reg7 ? "back" : "main"), mru_reg7); return (mru_reg7 ? CONFIG_NORBOOT_LITEOS_BACKUP : CONFIG_NORBOOT_LITEOS_MAIN); } #else /*启动方式7 有管理双boot*/ if (ns_forbid == NONE_SECURE_BOOT_FLAG && bootmod == 0 && bootsel0 == 1 && bootsel1 == 0 && bootsel2 == 1) { printf_spl("SPL: boot %s, mru_remap(%u)\n", (mru_remap ? "back" : "main"), mru_remap); return (mru_reg7 ? CONFIG_NORDOUBOOT_UBOOT_BACKUP : CONFIG_NORDOUBOOT_UBOOT_MAIN); } /*启动方式13,18*/ if ((ns_forbid == NONE_SECURE_BOOT_FLAG && bootmod == 1 && bootsel0 == 1 && bootsel2 == 1) || \ (ns_forbid != NONE_SECURE_BOOT_FLAG && bootsel0 == 1 && bootsel2 == 1 )) { printf_spl("SPL: boot area %s, mrureg7(%u)\n", (mru_reg7 ? "back" : "main"), mru_reg7); return (mru_reg7 ? CONFIG_NORBOOT_UBOOT_BACKUP : CONFIG_NORBOOT_UBOOT_MAIN); } #endif printf("SPL: not support boot type\n"); return -1; } #endif #define FMC_NAND_BL_INDEX2 2 #define FMC_NOR_WL_INDEX2 2 #define FMC_NOR_WL_INDEX3 3 #define FMC0_SPI_NAND_UBOOT_SIZE 0x800000 #define FMC0_SPI_NOR_LITEOS_SIZE 0x400000 #define FMC1_DOUBLE_NOR_DOUBLE_BOOT_LITEOS_MAIN_BASE 0x0 #define FMC0_SINGLE_NOR_DOUBLE_BOOT_LITEOS_BASE 0x800000 #define FMC0_SINGLE_NOR_SINGLE_BOOT_LITEOS_BASE 0x940000 #define FMC1_SPI_NOR_UBOOT_SIZE 0x400000 uint32_t spl_nand_get_uboot_raw_page(void); void spl_set_flash_protect(void) { unsigned int bootsel = spl_get_bootsel(); unsigned int bootsel0 = (bootsel >> 0 ) & 0x1; unsigned int bootsel2 = (bootsel >> 2 ) & 0x1; unsigned int nor_next_boot_base; #if !BOOT_OS_LITEOS unsigned int nand_next_boot_base; #endif if ((bootsel0 == 0) && (bootsel2 == 1)) { // nand启动 #if !BOOT_OS_LITEOS nand_next_boot_base = spl_nand_get_uboot_raw_page(); (void)fmc_nand_bl_with_addr_config_addr(0, FMC_NAND_BL_INDEX2, nand_next_boot_base, nand_next_boot_base + FMC0_SPI_NAND_UBOOT_SIZE); (void)fmc_nand_lock_config(0, 1); #endif } else { // nor启动 nor_next_boot_base = spl_nor_get_uboot_base(); #if BOOT_OS_LITEOS /* code区 */ (void)spi_flash_lock_config(0, 1); (void)spi_flash_wl_addr_config_addr(0, FMC_NOR_WL_INDEX2, nor_next_boot_base, nor_next_boot_base + FMC0_SPI_NOR_LITEOS_SIZE); #else if (nor_next_boot_base > 0x10000000) { nor_next_boot_base = nor_next_boot_base - 0x10000000; } (void)spi_flash_wl_addr_config_addr(1, FMC_NOR_WL_INDEX2, nor_next_boot_base, nor_next_boot_base + FMC1_SPI_NOR_UBOOT_SIZE); (void)spi_flash_lock_config(1, 1); #endif } } #if BOOT_OS_LITEOS void spl_set_flash_liteos_run_protect(void) { unsigned int bootsel = spl_get_bootsel(); unsigned int bootsel1 = (bootsel >> 1 ) & 0x1; unsigned int bootsel3 = (bootsel >> 3 ) & 0x1; unsigned int bootmod = ((spl_get_mru_reg(MRU_CFG1) & MRU_CFG1_BOOTMOD_MASK ) >> MRU_CFG1_BOOTMOD_SHIFT); unsigned int ns_forbid = spl_get_mru_reg(SEC_NS_FORBIT); /* run区 */ if (bootsel3 == 1) { // 双nor (void)spi_flash_lock_config(1, 1); (void)spi_flash_wl_addr_config_addr(1, FMC_NOR_WL_INDEX3, FMC1_DOUBLE_NOR_DOUBLE_BOOT_LITEOS_MAIN_BASE, FMC1_DOUBLE_NOR_DOUBLE_BOOT_LITEOS_MAIN_BASE + FMC0_SPI_NOR_LITEOS_SIZE - 1); (void)spi_flash_xip_addr_protect(1, 0, FMC1_DOUBLE_NOR_DOUBLE_BOOT_LITEOS_MAIN_BASE, FMC1_DOUBLE_NOR_DOUBLE_BOOT_LITEOS_MAIN_BASE + FMC0_SPI_NOR_LITEOS_SIZE - 1); } else if ((bootsel3 == 0) && (bootsel1 == 0) && (bootmod == 0) && (ns_forbid == NONE_SECURE_BOOT_FLAG)) { //单nor 双boot (void)spi_flash_wl_addr_config_addr(0, FMC_NOR_WL_INDEX3, FMC0_SINGLE_NOR_DOUBLE_BOOT_LITEOS_BASE, FMC0_SINGLE_NOR_DOUBLE_BOOT_LITEOS_BASE + FMC0_SPI_NOR_LITEOS_SIZE - 1); (void)spi_flash_xip_addr_protect(0, 0, FMC0_SINGLE_NOR_DOUBLE_BOOT_LITEOS_BASE, FMC0_SINGLE_NOR_DOUBLE_BOOT_LITEOS_BASE + FMC0_SPI_NOR_LITEOS_SIZE - 1); } else { //单nor 单boot (void)spi_flash_wl_addr_config_addr(0, FMC_NOR_WL_INDEX3, FMC0_SINGLE_NOR_SINGLE_BOOT_LITEOS_BASE, FMC0_SINGLE_NOR_SINGLE_BOOT_LITEOS_BASE + FMC0_SPI_NOR_LITEOS_SIZE - 1); (void)spi_flash_xip_addr_protect(0, 0, FMC0_SINGLE_NOR_SINGLE_BOOT_LITEOS_BASE, FMC0_SINGLE_NOR_SINGLE_BOOT_LITEOS_BASE + FMC0_SPI_NOR_LITEOS_SIZE - 1); } } #endif #ifdef EXEC_ENV_2125_EVB uint32_t spl_nand_get_uboot_raw_page(void) { unsigned int mru_reg7 = (spl_get_mru_reg(MRU_REG7) & 0x1); printf("SPL: boot from %s, mru_reg7(%u)\n", (mru_reg7 ? "backup" : "main"), mru_reg7); return (mru_reg7 ? CONFIG_4M_NANDBOOT_UBOOT_BACKUP : CONFIG_4M_NANDBOOT_UBOOT_MAIN); } #else #if !BOOT_OS_LITEOS uint32_t spl_nand_get_uboot_raw_page(void) { unsigned int mru_reg7 = (spl_get_mru_reg(MRU_REG7) & 0x1); unsigned int bootsel = spl_get_bootsel(); unsigned int bootsel0 = (bootsel >> 0 ) & 0x1; unsigned int bootsel1 = (bootsel >> 1 ) & 0x1; unsigned int bootsel2 = (bootsel >> 2 ) & 0x1; if (bootsel0 == 0 && bootsel2 == 1 && bootsel1 == 0) { printf_spl("SPL: boot area %s, mrureg7(%u)\n", (mru_reg7 ? "back" : "main"), mru_reg7); return (mru_reg7 ? CONFIG_2M_NANDBOOT_UBOOT_BACKUP : CONFIG_2M_NANDBOOT_UBOOT_MAIN); } if (bootsel0 == 0 && bootsel2 == 1 && bootsel1 == 1) { printf_spl("SPL: boot area %s, mrureg7(%u)\n", (mru_reg7 ? "back" : "main"), mru_reg7); return (mru_reg7 ? CONFIG_4M_NANDBOOT_UBOOT_BACKUP : CONFIG_4M_NANDBOOT_UBOOT_MAIN); } printf("SPL: not support boot type\n"); return -1; } #endif #endif #ifdef EXEC_ENV_2125_EVB u32 spl_boot_device(void) { unsigned int bootsel0 = (spl_get_bootsel() & 0x1); printf("SPL: boot from %s, bootsel0(%u)\n", (bootsel0 ? "nandflash" : "norflash"), bootsel0); return (bootsel0 ? BOOT_DEVICE_NAND : BOOT_DEVICE_SPI); } #else u32 spl_boot_device(void) { unsigned int bootsel = spl_get_bootsel(); unsigned int bootsel0 = (bootsel >> 0 ) & 0x1; unsigned int bootsel2 = (bootsel >> 2 ) & 0x1; unsigned int bootsel3 = (bootsel >> 3 ) & 0x1; printf_spl("SPL: bootsel0(%u),bootsel2(%u), bootsel3(%u)\n", bootsel0 , bootsel2, bootsel3); if (bootsel0 == 0) { printf_spl("SPL: boot from FMC0 %s, bootsel2(%u)\n", (bootsel2 ? "nand" : "spinor") ,bootsel2); /*当bootsel2 =1 时必为有管理场景;当bootsel2 =0 时必为无管理场景,此时需要通过FMC NOR驱动读写LITEOS到运行地址*/ return (bootsel2 ? BOOT_DEVICE_NAND : BOOT_DEVICE_SPI); } else { if(bootsel3 == 1) { // printf_spl("SPL: boot from FMC1 nor\n"); /*必为有管理场景,SPI通过boot方式拷贝uboot到DDR*/ return (BOOT_DEVICE_NOR); } else { printf_spl("SPL: boot from FMC1 but no flash in FMC1\n"); return -1; } } } #endif unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash) { return spl_nor_get_uboot_base(); } #if 1 //#ifdef MBIST_EN #define SECTION_RAM_CODE __attribute__((section(".ram_code"))) #if 0 void SECTION_RAM_CODE mbist_l2_test(void) { int cnt = 0x80000; char *pdest = 0x30080000; //清空L2数据,检测是否有异常情况发生 while ((cnt)-- > 0) { *pdest++ = 0; } //启动Mbist //等待硬件mbist完成?软件如何感知 //置位老化结束标志 *(volatile uint64_t *)(MBIST_FINISH_FLAG_ADDR) = MBIST_FINISH_FLAG_VALUE; //开内狗等待狗超时 *(volatile uint64_t *)(0x3022A000 + 0x0) = 1; //切换为软件喂外狗 *(volatile uint64_t *)(0x3022D000 + 0x4) = 1; asm volatile("b ."); } #endif static void raw_write_daif(unsigned int daif) { __asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory"); } static void hardware_feed_wdg_switch(int num) { //切换回硬件喂狗时,需要先鉴权 writel(0xAA5555AA, (HFD_BASE + HFD_AUTH_OFFSET)); writel(0xAABBCCDD, (HFD_BASE + HFD_AUTH_OFFSET)); //需要设置喂外狗次数为无限次,否则喂6次就会停 writel(num, (HFD_BASE + HFD_NUM_OFFSET)); //此时才能切换回硬件喂狗 writel(0, (HFD_BASE + HFD_SFDEN_OFFSET)); } static void designware_wdt_disable(uint64_t base) { /*由于WDG CR的bit0 无法直接写0,需要特殊流程进行解锁寄存器 (DW_WDT_AUTH为额外设计的寄存器)*/ writel(0x5555aaaa, (base + 0X1C)); writel(0xaaaa5555, (base + 0X1C)); writel(0, (base + 0X00)); } static unsigned int designware_wdt_is_enabled(uint64_t base) { return readl(base + 0x00) & BIT(0); } static void hw_watchdog_reset(uint64_t base) { if (designware_wdt_is_enabled(base)) /* restart the watchdog counter */ writel(0x76, (0x3022A000 + 0x0C)); } static void designware_wdt_stop(uint64_t base) { hw_watchdog_reset(base); designware_wdt_disable(base); } void mbist_start(void) { /*读 RAM 空间是否有老化标志,且老化标志未结束*/ int mbist_enable = readl(MBIST_ENBALE_FLAG_ADDR); int mbist_finish = readl(MBIST_FINISH_FLAG_ADDR); if(mbist_enable == MBIST_ENBALE_FLAG_VALUE && mbist_finish != MBIST_FINISH_FLAG_VALUE) { printf_spl("SPL: prepare Mbist test\n"); //关闭内狗 designware_wdt_stop(0x3022A000); //外狗切换为硬件喂狗 hardware_feed_wdg_switch(0); //关闭中断 raw_write_daif((1<<6 | 1<<7 | 1<<8 | 1<<9)); #if 0 mbist_l2_test(); #else #if BOOT_OS_LITEOS memcpy((void *)(uintptr_t)(0x30060000),(void *)(uintptr_t)(0x300A3300+0x3bd00) ,32*1024); #else memcpy((void *)(uintptr_t)(0x30060000),(void *)(uintptr_t)(0x300A3300+0x54d00) ,32*1024); #endif void ( *entry ) ( void ); /* Jump to the target entry */ entry = ( void ( * ) ( void ) ) 0x30060000; printf_spl("SPL :Jump to Mbist.\n" ); udelay(10); entry(); #endif } //拷贝MBIST 到FLASH if(mbist_finish == MBIST_FINISH_FLAG_VALUE) { printf_spl("MBIST: test finish, result OK\n"); //清除32K SRAM数据 memset((void *)CONFIG_SYS_INIT_RAM_ADDR, 0, CONFIG_SYS_INIT_RAM_SIZE); } } #endif void board_init_f(ulong dummy) { int ret; unsigned int bootsel0 = (spl_get_bootsel() & 0x1); bootsel0 = bootsel0 ? BOOT_DEVICE_NAND : BOOT_DEVICE_NOR; #ifdef CONFIG_DEBUG_UART /* * Debug UART can be used from here if required: * * debug_uart_init(); * printch('a'); * printhex8(0x1234); * printascii("string"); */ //Repeat Call in crt0_64.S,printf //debug_uart_init(); #endif mbist_start(); board_early_init_f(); ret = spl_early_init(); if (ret) { debug("spl_early_init() failed: %d\n", ret); hang(); } timer_init(); preloader_console_init(); arch_cpu_init(); pll_init(); #ifndef EXEC_ENV_2125_EVB spl_set_flash_protect(); #endif } /* Override weak function defined in SPL framework to enable validation * of main u-boot image before jumping to u-boot image. */ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) { typedef void __noreturn (*image_entry_noargs_t)(void); image_entry_noargs_t image_entry = (image_entry_noargs_t)(spl_image->entry_point); /* Validation codes */ printf("Jumping to U-Boot at address 0x%lx\n", spl_image->entry_point); image_entry(); } static int spl_abortboot(int abort_times, int bootdelay) { int abort = 0; int abort_ascl = 0; unsigned long ts; if (abort_times == 0) { printf("Press 'ctrl+C/c' to stop autoboot: %2d ", bootdelay); abort_ascl = 0x3; } else { printf("Press 'ctrl+D/d' to stop autoboot: %2d ", bootdelay); abort_ascl = 0x4; } /* * Check if key already pressed */ if (tstc()) { /* we got a key press */ if(abort_ascl == getchar()) /* consume input */ { puts("\b\b\b 0"); abort = 1; /* don't auto boot */ } } while ((bootdelay > 0) && (!abort)) { --bootdelay; /* delay 1000 ms */ ts = get_timer(0); do { if (tstc()) { /* we got a key press */ if(abort_ascl == getchar()) { abort = 1; /* don't auto boot */ bootdelay = 0; /* no more delay */ break; } } #ifdef PLD_EMU /*PLD环境下延时需要减少*/ udelay(10); #else udelay(10000); #endif } while (!abort && get_timer(ts) < 1000); printf("\b\b\b%2d ", bootdelay); } putc('\n'); return abort; } /* for SPL command line */ void spl_shell_poll(int abort_times) { //Generic_Timer_init(); if(spl_abortboot(abort_times, 1)) { printf("spl enter cli_loop \n"); cli_simple_loop(); } } void spl_shell_enter(void) { printf("spl enter cli_loop \n"); cli_simple_loop(); } void spl_board_prepare_for_boot(void) { } 这是spl的代码,是厂家提供的代码,没有修改过,原来是nor+nand启动,就能正常初始化ddr的,为什么穷改成单nand启动了,就不行了?
09-23
/* * Copyright 1994, 1995, 2000 Neil Russell. * (See License) * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de */ #include "http_upgrade.h" #include <command.h> #include <net.h> #include <asm/byteorder.h> #include "lib_uip.h" #include "rsaVerify.h" #include "md5.h" #include "malloc.h" #include "uip_drv.h" DECLARE_GLOBAL_DATA_PTR; #ifdef CFG_EXTRA_FW #define WORD_ALIGN(p) (((unsigned int)(p)+3)&~3) typedef struct _FileBlockEntry { uint32_t blk_type; uint32_t length; }FileBlockEntry; /* * file block partition format is as this: * file_block_header - block entries - file block 1 - file block 2 ... */ typedef struct file_block_header { uint32_t nBlk; FileBlockEntry BlkEntries[1]; }file_block_header_t; #endif #ifndef UIP_FLASH_BASE #define UIP_FLASH_BASE CFG_FLASH_BASE #endif #ifndef UIP_FLASH_SIZE #define UIP_FLASH_SIZE CFG_FLASH_SIZE #endif #define MD5SUM_LEN 16 #define HW_ID_LEN 16 #define FW_ID_LEN 16 #define FINFO_DEVNAME_LEN 64 #define FINFO_HWVER_LEN 21 #define FACTORY_INFO_MAC_KEY "mac:" #define FACTORY_INFO_HWID_KEY "hwId:" #define FACTORY_INFO_FWID_KEY "RcvrfwId:" #define FACTORY_INFO_DEV_NAME_KEY "devName:" #define FACTORY_INFO_HW_VER_KEY "hwVer:" /* Vendor Id's. */ #define VENDOR_ID_TP 0x00 #define VENDOR_ID_MECURY 0x01 #define VENDOR_ID_FAST 0x02 #define VENDOR_ID_PROWARE 0x35 /* RSA public Keys. */ char publicKeyTP[] = "BgIAAACkAABSU0ExAAQAAAEAAQA1Ccyu85b65TawjvSQTaryGNk1gBJVn6kEIJq6m0hagsqkiy32v4ui41ucp6tKfaoqb7AHDBq41dcEMgM6YBF2e3aRKQqZ6EwgCvAi3O81n7UbE97lD+FhvqlYxyqqMbSdvNmCiAoujheUs9DUaOCHq4K3McDxATMVOnCtT1H+wQ=="; char publicKeyMercury[] = "BgIAAACkAABSU0ExAAQAAAEAAQD7Bk7f7fdnL9drucbr+P9wA2JUlYP/OH4zvIS69eY3KKmUB1fs9ND06EINqTQ4vQ4gCeekU1dRi3WiZLgVjo/UzovplddUezNMWq0gk4TVbsGf/xzXZN+pDWid9zYsSr9qvINId6cnMR+s/wXB1TOE6t6wfzHvnbkJR0r1mqG4yA=="; char publicKeyFast[] = "BgIAAACkAABSU0ExAAQAAAEAAQAHNt5fFl0BUlLkPjKJloZFlVFkegFjEsVJCRjwbRD6i646tpvc/Z5MK6SuXcz3yizxDGMnZ6BJdqCR9SJTdd3b11F7Q+pgetcAgX5X9NZTzo1MCvpkKAlEyZG0rXMpSbADNNqtACNT0BLhHu4nyiDBBIIOSZljQAzHiqSquxHDsg=="; char publicKeyProware[] = "BgIAAACkAABSU0ExAAQAAAEAAQArjNXuvBeCGfOD19AGJGmceW+ip5W76C+sOHk0bJgrtZhk+t/ZzZwAv/TLA+MwNipNZSd+fOysmqDsA53cEIKdzor0WbWGq0n/BYr1o8fh4Pm656mOn9C6LH6nCf6w48Nog84Pc+NuwHcB93p6Wj0y3YVl8sGn+eeokA8ltZzLnA=="; /* Firmware information structure. */ typedef struct _FW_INFO { unsigned char* buf; int size; int uhTagLength; int local_fw_size; }FW_INFO; static FW_INFO fw_info = {0}; /* Local uboot infomation structure. */ typedef struct _LOCAL_INFO { uint8_t hwID[HW_ID_LEN]; uint8_t fwID[FW_ID_LEN]; uint8_t mac[6]; #ifdef UNIFY_FIRMWARE uint8_t device_model[FINFO_DEVNAME_LEN]; uint8_t hw_version[FINFO_HWVER_LEN]; #endif } LOCAL_INFO; static LOCAL_INFO localInfo = {{0}}; /* define tp header */ #define TP_HEADER_VERSION 0x00000100 #define MAGIC_LEN 20 #define CRC_LEN 16 #define FW_DESC_LEN 12 #define PARTITION_NUMBER 9 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]; } 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_ISP_CONFIG 0x0010 /* partition type flags. */ #define PARTITION_TYPE_BOOTLOADER CONTENT_TYPE_BOOTLOADER #define PARTITION_TYPE_KERNEL CONTENT_TYPE_KERNEL #define PARTITION_TYPE_FACTORY_INFO 0x0100 #define PARTITION_TYPE_RADIO_DATA 0x0200 /* firmware bin contents */ #define PARTS_UP_BOOT (CONTENT_TYPE_BOOTLOADER | CONTENT_TYPE_KERNEL | CONTENT_TYPE_ROMFS | CONTENT_TYPE_JFFS2FS) #define PARTS_UP (CONTENT_TYPE_KERNEL | CONTENT_TYPE_ROMFS | CONTENT_TYPE_JFFS2FS) #define PARTS_UP_BOOT_NOJFS (CONTENT_TYPE_BOOTLOADER | CONTENT_TYPE_KERNEL | CONTENT_TYPE_ROMFS) #define PARTS_UP_NOJFS (CONTENT_TYPE_KERNEL | CONTENT_TYPE_ROMFS) /* define upgrade header */ #define UPGRADE_HEADER_VERSION 0x00000100 #define UPGRADE_HEADER_LEN 512 #define UPGRADE_HEADER_LEN_WIDE (2 * UPGRADE_HEADER_LEN) #define RSA_SIGN_LEN 128 #define FWID_FL_MASK_LEN 12 #define HW_ID_LEN 16 typedef struct _UPGRADE_HEADER { unsigned int headerVersion; unsigned char magicNumber[MAGIC_LEN]; unsigned short tagLength; unsigned short vendorId; unsigned short zoneCode; unsigned short contentTypes; unsigned char rsaSignature[RSA_SIGN_LEN]; unsigned short hwIdNum; unsigned short fwIdFLNum; unsigned char fwIdFLMask[FWID_FL_MASK_LEN]; unsigned char hwIdList[0][HW_ID_LEN]; // unsigned char fwIdFL[0][FW_ID_LEN]; } UPGRADE_HEADER; /* Allowed recovery FwID */ const char RECOVERY_FW_ID[FW_ID_LEN] = {WEBFAILSAFE_FW_ID}; #ifdef UNIFY_FIRMWARE static unsigned char blockHdrMagicNumber[] = {0x12, 0x34, 0x56, 0x78}; static int checkFirmwareIsp(BLOCK_HEADER* blockHdr, void* thisHandler); static int upgradeFirmwareIsp(EXT_FW_HEADER* block); static EXT_FW_BLOCK_HANDLER blockHdrTbl[] = { { CONTENT_TYPE_ISP_CONFIG, EXT_FW_CHANGED, NULL, checkFirmwareIsp, upgradeFirmwareIsp }, { 0, 0, NULL, NULL, NULL } }; #endif void get_eth_addr(uint8_t* addr) { memcpy(addr, localInfo.mac, 6); } /* * Function Name: localInfoInit * Author: CaiBin * Date: 2014-11-07 * Description: Initialize local firmware information(currently only HwID). * Parameter: * VOID * return: * 0: Succeeded; * ERR_GENERIC: No HwID found. * ERR_READ_FLASH: Read command execution error. * ERR_BAD_ADDRESS: Invalid address values passed. */ static int localInfoInit(void) { int ret = 0; uint8_t *buf = NULL; uint8_t *p = NULL; memset(&localInfo, 0, sizeof(localInfo)); memcpy(localInfo.fwID, RECOVERY_FW_ID, FW_ID_LEN); buf = (uint8_t*)malloc(FACTORY_INFO_LEN); if (!buf) { ERR("malloc failed."); ret = ERR_MEMORY_ALLOC; goto out; } ret = readFlash(FACTORY_INFO_OFFSET, buf, FACTORY_INFO_LEN); if (ret < 0) { ERR("read flash failed."); goto out_free_buf; } #ifdef RECOVERY_UPGRADE_UNIT_TEST { int i; DBG_UNIT("content:"); for (i=0, p = buf; i < FACTORY_INFO_LEN; p++, i++) { if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9')) { printf("%c ", *p); } else { printf("%02X ", (int)*p); } } printf("\n"); } #endif //read mac address p = (uint8_t *)memmem(buf, FACTORY_INFO_LEN, FACTORY_INFO_MAC_KEY, strlen(FACTORY_INFO_MAC_KEY)); if (NULL == p) { ERR("no mac address found"); ret = ERR_HWID_NOT_FOUND; goto out_free_buf; } DBG_UNIT("find offset:%d", p-buf); memcpy(localInfo.mac, p + strlen(FACTORY_INFO_MAC_KEY), 6); //read hwID p = (uint8_t *)memmem(buf, FACTORY_INFO_LEN, FACTORY_INFO_HWID_KEY, strlen(FACTORY_INFO_HWID_KEY)); if (NULL == p) { ERR("no HwID found"); ret = ERR_HWID_NOT_FOUND; goto out_free_buf; } DBG_UNIT("find offset:%d", p-buf); memcpy(localInfo.hwID, p + strlen(FACTORY_INFO_HWID_KEY), HW_ID_LEN); //read fwID #ifdef FETCH_FW_ID_FROM_FACTORY_INFO p = (uint8_t *)memmem(buf, FACTORY_INFO_LEN, FACTORY_INFO_FWID_KEY, strlen(FACTORY_INFO_FWID_KEY)); if (NULL == p) { ERR("no FwID found"); ret = ERR_FWID_NOT_FOUND; goto out_free_buf; } DBG_UNIT("find offset:%d", p-buf); memcpy(localInfo.fwID, p + strlen(FACTORY_INFO_FWID_KEY), FW_ID_LEN); #endif #ifdef UNIFY_FIRMWARE //read device_model p = (uint8_t *)memmem(buf, FACTORY_INFO_LEN, FACTORY_INFO_DEV_NAME_KEY, strlen(FACTORY_INFO_DEV_NAME_KEY)); if (NULL == p || strlen(FACTORY_INFO_DEV_NAME_KEY) == strlen(p)) { ERR("no device_model found"); ret = ERR_DEV_NAME_NOT_FOUND; goto out_free_buf; } memcpy(localInfo.device_model, p + strlen(FACTORY_INFO_DEV_NAME_KEY), strlen(p) - strlen(FACTORY_INFO_DEV_NAME_KEY)); DBG_UNIT("localInfo.device_model: %s", localInfo.device_model); //read hw_version p = (uint8_t *)memmem(buf, FACTORY_INFO_LEN, FACTORY_INFO_HW_VER_KEY, strlen(FACTORY_INFO_HW_VER_KEY)); if (NULL == p|| strlen(FACTORY_INFO_HW_VER_KEY) == strlen(p)) { ERR("no hw_version found"); ret = ERR_HW_VER_NOT_FOUND; goto out_free_buf; } memcpy(localInfo.hw_version, p + strlen(FACTORY_INFO_HW_VER_KEY), strlen(p) - strlen(FACTORY_INFO_HW_VER_KEY)); DBG_UNIT("localInfo.hw_version: %s", localInfo.hw_version); #endif #ifdef RECOVERY_UPGRADE_UNIT_TEST { int i; DBG_UNIT("got MAC:"); for(i=0; i<6; i++) { printf("%02X ",localInfo.mac[i]); } printf("\n"); DBG_UNIT("got hwID:"); for(i=0; i<HW_ID_LEN; i++) { printf("%02X ",localInfo.hwID[i]); } printf("\n"); DBG_UNIT("got fwID:"); for(i=0; i<FW_ID_LEN; i++) { printf("%02X ",localInfo.fwID[i]); } printf("\n"); } #endif out_free_buf: free(buf); out: return ret; } /* * Function Name: check_file_size * Author: CaiBin * Date: 2014-11-07 * Description: Check if firmware has valid size. * Parameter: * size: Size of the firmware in bytes. * return: * 0: Succeeded; * ERR_INCORRECT_FILE_SIZE: File size is incorrect. */ static int check_file_size(ulong size) { #ifdef UNIFY_FIRMWARE if (size < BOOTLOADER_LEN) #else if ((size < BOOTLOADER_LEN) || (size > CFG_FLASH_SIZE)) #endif { ERR("data size check failed."); return ERR_INCORRECT_FILE_SIZE; } return 0; } /* * Function Name: calcMd5 * Author: CaiBin * Date: 2014-11-07 * Description: Compute MD5 checksum. * Parameter: * data: Source data . * size: Source data length. * md5: return the result md5 value. * return: * VOID */ static void calcMd5(char *data, int size, char *md5) { MD5_CTX ctx; MD5_Init(&ctx); MD5_Update(&ctx, data, size); MD5_Final(md5, &ctx); } /* * Function Name: checkFirmwareRSA * Author: CaiBin * Date: 2014-11-07 * Description: Check RSA signature of the upgrading firmware. * Parameter: * uHeader: Points to the upgrade header of the firmware. * info: Points to the information of the firmware. * return: * 0: Succeeded; * ERR_RSA_CHECK_FAIL: Signature is incorrect. */ static int checkFirmwareRSA(UPGRADE_HEADER* uHeader, FW_INFO* info) { int signCheckOk = 0; /* for RSA sign check result */ unsigned char md5Tmp[MD5SUM_LEN] = {0}; unsigned char rsaTmp[RSA_SIGN_LEN] = {0}; char* publicKey = NULL; //get public key by vendorId. switch (ntohs(uHeader->vendorId)) { case VENDOR_ID_TP: DBG_UNIT("TP key selected."); publicKey = publicKeyTP; break; case VENDOR_ID_MECURY: DBG_UNIT("Mercury key selected."); publicKey = publicKeyMercury; break; case VENDOR_ID_FAST: DBG_UNIT("Fast key selected."); publicKey = publicKeyFast; break; case VENDOR_ID_PROWARE: DBG_UNIT("Proware key selected."); publicKey = publicKeyProware; break; default: DBG_UNIT("no key available."); //VendorID not exist, regard as RSA check failed. ERR("RSA check failed."); return ERR_RSA_CHECK_FAIL; } //backup RSA sign first. memcpy(rsaTmp, uHeader->rsaSignature, RSA_SIGN_LEN); memset(uHeader->rsaSignature, 0x0, RSA_SIGN_LEN); DBG_UNIT("calc MD5.") calcMd5((char*)uHeader, info->size, (char*)md5Tmp); #ifdef RECOVERY_UPGRADE_UNIT_TEST { int i; DBG_UNIT("Desired RSA:"); for (i=0; i<RSA_SIGN_LEN; i++) { printf("%02X ",rsaTmp[i]); } printf("\n"); DBG_UNIT("MD5:"); for (i=0; i<MD5SUM_LEN; i++) { printf("%02X ",md5Tmp[i]); } printf("\n"); } #endif DBG_UNIT("RSA verify..."); signCheckOk = rsaVerifySignByBase64EncodePublicKeyBlob( (unsigned char*)publicKey, strlen(publicKey), md5Tmp, MD5SUM_LEN, rsaTmp, RSA_SIGN_LEN); if (!signCheckOk) { ERR("RSA check failed."); return ERR_RSA_CHECK_FAIL; } //restore RSA sign. memcpy(uHeader->rsaSignature, rsaTmp, RSA_SIGN_LEN); DBG("firmware RSA signiture check OK"); return 0; } /* * Function Name: checkFirmwareHwList * Author: CaiBin * Date: 2014-11-07 * Description: Check if HwID is supported in the HwID List of the firmware. * Parameter: * uHeader: Points to the upgrade header of the firmware. * return: * 0: Succeeded; * ERR_HWID_NOT_SUPPORTED: HwID is not supported. */ static int checkFirmwareHwList(UPGRADE_HEADER* uHeader) { int i = 0; int hwIdIsSupported = ERR_HWID_NOT_SUPPORTED; for (i = 0; i < ntohs(uHeader->hwIdNum); i++) { int j; DBG_UNIT("HwID:"); #ifdef RECOVERY_UPGRADE_UNIT_TEST for (j = 0; j < HW_ID_LEN; j++) { printf("%02X ", uHeader->hwIdList[i][j]); } printf("\n"); #endif if (memcmp(localInfo.hwID, uHeader->hwIdList[i], HW_ID_LEN) == 0) { DBG("firmware support my HwID"); hwIdIsSupported = 0; break; } } if (hwIdIsSupported < 0) { DBG("firmware not support my HwID"); } return hwIdIsSupported; } /* * Function Name: checkFirmwareID * Author: CaiBin * Date: 2014-11-07 * Description: Check if FwID is supported in the HwID List of the firmware. * Only the designated FwID is permitted. * Parameter: * Header: Points to the TP Header of the upgrading firmware. * return: * 0: Succeeded; * ERR_FWID_NOT_SUPPORTED: FwID is not supported. */ static int checkFirmwareID(TP_HEADER* header) { if(memcmp(header->fwId, localInfo.fwID, FW_ID_LEN) != 0) { ERR("Firmware ID not supported."); return ERR_FWID_NOT_SUPPORTED; } return 0; } /* * Function Name: checkFirmwarePartition * Author: CaiBin * Date: 2014-11-07 * Description: Check if firmware has all partitions. * Parameter: * uHeader: Points to the upgrade header of the firmware. * info: Points to the information of the firmware. * return: * 0: Succeeded; * ERR_PARTITION_TYPE_NOT_SUPPORTED: Firmware has not all partitions. */ static int checkFirmwarePartition(UPGRADE_HEADER* uHeader, FW_INFO* info) { //firmware content type. uint32_t fwContents = 0x0; //get the content parts of firmware. fwContents = ntohs(uHeader->contentTypes); //up_boot.bin only. if ((fwContents & PARTS_UP_BOOT) != PARTS_UP_BOOT) { ERR("content-type not supported."); return ERR_PARTITION_TYPE_NOT_SUPPORTED; } return 0; } /* * Function Name: validatePartitions * Author: CaiBin * Date: 2014-11-07 * Description: Check valid firmware partitions. * Validate partition offsets,lengths and CRC's in TP Header. * Parameter: * header: Points to the TP Header partition of the firmware image to validate. * return: * 0: Succeeded; * ERR_INVALID_TP_HEADER: Firmware has not all partitions. * ERR_PARTITION_VALIDATION_FAILED: Partition CRC verification failed. */ static int validatePartitions(TP_HEADER* header, uint32_t partition_type) { int ret = 0; //array of validation crc's. unsigned char* crc[] = {header ->factoryInfoCRC, header->radioCRC, header->ubootCRC, header->kernelAndRomfsCRC}; //array of partition offsets. uint32_t offset[] = {FACTORY_INFO_OFFSET, RADIO_OFFSET, BOOTLOADER_OFFSET, KERNEL_ROMFS_OFFSET}; //array of partition lengths. uint32_t length[] = {FACTORY_INFO_LEN, RADIO_LEN, BOOTLOADER_LEN, ntohl(header->kernelLen) + ntohl(header->romFsLen)}; //array of messages. char* dbg_msg[] = {"factory info", "radio data", "uboot", "kernel and romfs"}; //array of partition type flags to decide which partition to be validated. uint32_t partition_flags[] = {PARTITION_TYPE_FACTORY_INFO, PARTITION_TYPE_RADIO_DATA, PARTITION_TYPE_BOOTLOADER, PARTITION_TYPE_KERNEL}; unsigned char md5Tmp[MD5SUM_LEN] = {0}; unsigned char* base = NULL; int i; #ifndef CONFIG_RELOC_FIXUP_WORKS //relocate pointers for (i=0; i<sizeof(dbg_msg)/sizeof(char*); i++) { dbg_msg[i] += gd->reloc_off; } #endif DBG_UNIT("Validating partitions..."); DBG_UNIT("Factory Boot Offset: %x, Length: %x", ntohl(header->factoryBootOffset), ntohl(header->factoryBootLen)); if(ntohl(header->factoryBootOffset) != FACTORY_BOOT_OFFSET || ntohl(header->factoryBootLen) != FACTORY_BOOT_LEN) { return ERR_INVALID_TP_HEADER; } DBG_UNIT("Factory Info Offset: %x, Length: %x", ntohl(header->factoryInfoOffset), ntohl(header->factoryInfoLen)); if(ntohl(header->factoryInfoOffset) != FACTORY_INFO_OFFSET || ntohl(header->factoryInfoLen) != FACTORY_INFO_LEN) { return ERR_INVALID_TP_HEADER; } DBG_UNIT("Radio Offset: %x, Length: %x", ntohl(header->radioOffset), ntohl(header->radioLen)); if(ntohl(header->radioOffset) != RADIO_OFFSET || ntohl(header->radioLen) != RADIO_LEN) { return ERR_INVALID_TP_HEADER; } DBG_UNIT("User Config Offset: %x, Length: %x", ntohl(header->ucOffset), ntohl(header->ucLen)); if(ntohl(header->ucOffset) != UC_OFFSET || ntohl(header->ucLen) != UC_LEN) { return ERR_INVALID_TP_HEADER; } DBG_UNIT("UBoot Offset: %x, Length: %x", ntohl(header->bootloaderOffset), ntohl(header->bootloaderLen)); if(ntohl(header->bootloaderOffset) != BOOTLOADER_OFFSET || ntohl(header->bootloaderLen) != BOOTLOADER_LEN) { return ERR_INVALID_TP_HEADER; } DBG_UNIT("TP Header Offset: %x, Length: %x", ntohl(header->tpHeaderOffset), ntohl(header->tpHeaderLen)); if(ntohl(header->tpHeaderOffset) != TP_HEADER_OFFSET || ntohl(header->tpHeaderLen) != TP_HEADER_LEN) { return ERR_INVALID_TP_HEADER; } DBG_UNIT("Kernel Offset: %x, Length: %x", ntohl(header->kernelOffset), ntohl(header->kernelLen)); if(ntohl(header->kernelOffset) != KERNEL_ROMFS_OFFSET) { return ERR_INVALID_TP_HEADER; } DBG_UNIT("Romfs Offset: %x, Length: %x", ntohl(header->romFsOffset), ntohl(header->romFsLen)); DBG_UNIT("JFFS2 Offset: %x, Length: %x", ntohl(header->jffs2FsOffset), ntohl(header->jffs2FsLen)); if(ntohl(header->kernelLen) + ntohl(header->romFsLen) + ntohl(header->jffs2FsLen) + KERNEL_ROMFS_OFFSET != UIP_FLASH_SIZE) { return ERR_INVALID_TP_HEADER; } //verifying partition CRC. base = (char *)header - ntohl(header->tpHeaderOffset); for (i = 0; i < sizeof(crc)/sizeof(char*); i++) { if(partition_type & partition_flags[i]) { DBG("verifying %s partition...", dbg_msg[i]); memset(md5Tmp, 0, MD5SUM_LEN); DBG_UNIT("base: %p, offset: %p, length: %x", base, base+offset[i], (int)length[i]); calcMd5((char *)(base+offset[i]), (int)length[i], (char *)md5Tmp); if (memcmp(md5Tmp, crc[i], MD5SUM_LEN) == 0) { DBG("ok"); } else { DBG("failed"); ret = ERR_PARTITION_VALIDATION_FAILED; break; } } } return ret; } /* * Function Name: checkFirmware * Author: CaiBin * Date: 2014-11-07 * Description: Check if firmware is valid. * Parameter: * info: Points to the information of the firmware. * return: * 0: Succeeded; * ERR_INCORRECT_FILE_SIZE: File size is incorrect. * ERR_RSA_CHECK_FAIL: Signature is incorrect. * ERR_HWID_NOT_SUPPORTED: HwID is not supported. * ERR_PARTITION_TYPE_NOT_SUPPORTED: Firmware has not all partitions. */ static int checkFirmware(FW_INFO* info) { int ret = 0; UPGRADE_HEADER* uHeader = NULL; TP_HEADER* header; unsigned char* buf = info->buf; uHeader = (UPGRADE_HEADER*)buf; //get firmware's upgrade header length and get its tp header. info->uhTagLength = ntohs(uHeader->tagLength); header = (TP_HEADER*)(buf + info->uhTagLength + BOOTLOADER_LEN); DBG_UNIT("taglength: %d", info->uhTagLength); //check file size. ret = check_file_size(info->size); if(ret < 0) { return ret; } #ifdef WEBFAILSAFE_UPGRADE_CHECK_RSA //check rsa signiture if needed. ret = checkFirmwareRSA(uHeader, info); if (ret < 0) { return ret; } #endif //check if HwID in firmware support HwID list. ret = checkFirmwareHwList(uHeader); if (ret < 0) { ERR("Hardware not supported."); return ret; } //check FwID of the upgrading firmware. /*ret = checkFirmwareID(header); if(ret < 0) { return ret; }*/ //check firmware partitions are enough and if contents are changed ret = checkFirmwarePartition(uHeader, info); if (ret < 0) { return ret; } //validate uploaded firmware partitions. ret = validatePartitions(header, ntohs(uHeader->contentTypes)); if (ret < 0) { return ret; } DBG("firmware check finished, ok to upgrade"); return 0; } /* * Function Name: executeUpgrade * Author: CaiBin * Date: 2014-11-07 * Description: Do actual upgrade work. * Parameter: * addrOffset: Flash address to be copyed to. * base: Points to the data to be copyed. * size: Data size to be copyed in bytes. * return: * 0: Succeeded; * ERR_WRITE_FLASH: Write command execution error. * ERR_READ_FLASH: Read command execution error. * ERR_ERASE_FLASH: Erase command execution error. * ERR_BAD_ADDRESS: Invalid address values passed. */ static int executeUpgrade(uint32_t addrOffset, char* base, uint32_t size) { int ret = 0; DBG("execute upgrade..."); DBG_UNIT("write offset: %x, from: %p, size: %x", addrOffset, base, size); //erase copy region. ret = eraseFlash(addrOffset, size); if (ret < 0) { ERR("erase flash failed!"); return ret; } //start to write firmware. ret = writeFlash(addrOffset, (uint8_t*)base, size); if (ret < 0) { ERR("write flash failed!"); return ret; } return 0; } /* * Function Name: upgradeFirmware * Author: CaiBin * Date: 2014-11-07 * Description: Do upgrade. * Parameter: * info: Points to the information of the firmware. * return: * 0: Succeeded; * ERR_WRITE_FLASH: Write command execution error. * ERR_READ_FLASH: Read command execution error. * ERR_ERASE_FLASH: Erase command execution error. * ERR_BAD_ADDRESS: Invalid address values passed. */ static int upgradeFirmware(FW_INFO* info) { int ret = 0; TP_HEADER* header; char* base = 0; uint32_t size = 0; char* buf = (char*)info->buf; uint32_t addrOffset; base = buf + info->uhTagLength; header = (TP_HEADER*)(buf + info->uhTagLength + BOOTLOADER_LEN); #ifdef UNIFY_FIRMWARE /* 共用固件方案的升级文件尾部还有各机型的ISP_CONFIG文件 */ size = ntohl(header->bootloaderLen) + ntohl(header->tpHeaderLen) + ntohl(header->kernelLen) + ntohl(header->romFsLen) + ntohl(header->jffs2FsLen); #else size = info->size - info->uhTagLength; #endif addrOffset = ntohl(header->bootloaderOffset); ret = executeUpgrade(addrOffset, base, size); if (ret < 0) { printf("%s failed\n", __func__); return ret; } #if 0 /* erase user config */ addrOffset = ntohl(header->ucOffset); ret = eraseFlash(addrOffset, ntohl(header->ucLen)); #endif return ret; } #ifdef UNIFY_FIRMWARE /****************************************************************************** * 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 devName[EXT_FW_DEVNAME_LEN + 1] = {0}; char* base = (char*)hdr; EXT_FW_HEADER* iHdr = NULL; EXT_FW_BLOCK_HANDLER* pointer = thisHandler; if (NULL == hdr || NULL == thisHandler) { ret = ERR_GENERIC; goto out; } blockNum = ntohl(hdr->num); base += sizeof(BLOCK_HEADER); /* 由device_model和hw_version通过"_"拼凑而成 */ snprintf(devName, EXT_FW_DEVNAME_LEN, "%s_%s", localInfo.device_model, localInfo.hw_version); DBG("Local devName: %s", devName); for (i = 0; i < blockNum; i++) { if (CONTENT_TYPE_ISP_CONFIG == ntohl(hdr->info[i].type)) { iHdr = (EXT_FW_HEADER *)base; DBG("iHdr->devName = %s", iHdr->devName); if (0 == memcmp(iHdr->devName, devName, strlen(devName))) { pointer->block = iHdr; DBG("isp: device name supported"); break; } } base += ntohl(hdr->info[i].length); } if (i == blockNum) { DBG("isp: device name not supported"); ret = ERR_SLP_BAD_EXT_FW; goto out; } calcMd5((char*)iHdr + sizeof(EXT_FW_HEADER), ntohl(iHdr->length), md5Tmp); ret = memcmp(iHdr->md5, md5Tmp, MD5SUM_LEN); if (ret) { DBG("Invalid isp data in firmware"); goto out; } 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[RADIO_LEN] = {0}; uint32_t addrOffset = 0; uint32_t size = 0; if (NULL == block) { return ERR_GENERIC; } addrOffset = RADIO_OFFSET; size = ntohl(block->length) + sizeof(EXT_FW_HEADER); memset(ispBuf, 0xff, RADIO_LEN); memcpy(ispBuf, (void *)block, size); ret = eraseFlash(addrOffset, RADIO_LEN); if (ret < 0) { DBG("erase radio flash failed!"); return ret; } ret = writeFlash(addrOffset, ispBuf, RADIO_LEN); if (ret) { return ret; } DBG("upgrade isp done"); return ERR_NONE; } static int checkExtFirmware(FW_INFO* info) { int i = 0; int ret = 0; unsigned short handlerFound = 0; unsigned short upContents = 0; BLOCK_HEADER* blockHdr = NULL; UPGRADE_HEADER* uHeader = NULL; TP_HEADER *header = NULL; if (NULL == info) { return ERR_GENERIC; } uHeader = (UPGRADE_HEADER*)info->buf; header = (TP_HEADER*)(info->buf + info->uhTagLength + BOOTLOADER_LEN); upContents = ntohs(uHeader->contentTypes); /* 新nvmp平台去除了jffs2FsLen的部分,因此将header->jffs2FsLen去除 */ blockHdr = (BLOCK_HEADER*)((char*)header + ntohl(header->jffs2FsOffset - header->tpHeaderOffset/* + header->jffs2FsLen*/)); if (0 != memcmp(blockHdrMagicNumber, blockHdr->magicNumber, BLOCK_MAGIC_NUMBER_LEN)) { DBG("invalid ext_fw block header"); return ERR_SLP_BAD_EXT_FW; } for (i = 0; i < sizeof(blockHdrTbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) { if (0 != blockHdrTbl[i].type & upContents) { handlerFound |= blockHdrTbl[i].type; ret = blockHdrTbl[i].checkExtFw(blockHdr, &blockHdrTbl[i]); if (ret) { DBG("check ext_fw failed, type:0x%x", blockHdrTbl[i].type); return ERR_SLP_BAD_EXT_FW; } } } if ((upContents & ~(PARTS_UP_BOOT)) != handlerFound) { return ERR_SLP_BAD_EXT_FW; } DBG("ext_fw check ok."); return ERR_NONE; } static int upgradeExtFirmware() { int i = 0; int ret = 0; for (i = 0; i < sizeof(blockHdrTbl) / sizeof(EXT_FW_BLOCK_HANDLER); i++) { if (blockHdrTbl[i].bNeedUpgrade) { ret = blockHdrTbl[i].upgradeExtFw(blockHdrTbl[i].block); if (ret) { DBG("upgrade ext_fw failed, type:0x%x", blockHdrTbl[i].type); return ret; } } } DBG("ext_fw upgrade ok."); return ERR_NONE; } #endif /* * Function Name: validateLocalFirmware * Author: CaiBin * Date: 2014-11-07 * Description: Check if local firmware is valid. * Validate partition offsets,lengths and CRC's in TP Header. * Note: According to the newly designed flash layout and upload firmware * layout. Only uboot partition, TP Header partition, kernel and fs partitions * is validated. * Parameter: * header: Points to the TP Header partition of the firmware image to validate. * return: * 0: Succeeded; * ERR_INVALID_TP_HEADER: Firmware has not all partitions. * ERR_PARTITION_VALIDATION_FAILED: Partition CRC verification failed. */ int validateLocalFirmware(void) { volatile 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 //copy flash image to RAM. DBG("copying flash to 0x%x", WEBFAILSAFE_UPLOAD_RAM_ADDRESS); ret = readFlash(0, 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 DBG_UNIT("validate local firmware...\nTP Header at %p", header); #ifdef UIP_CACHE_OPERATION uip_cache_enable(); #endif ret = validatePartitions(header, partitions); #ifdef UIP_CACHE_OPERATION uip_cache_disable(); #endif return ret; } /* * Function Name: upgrade_init * Author: CaiBin * Date: 2014-11-07 * Description: Initiate local data and server page info. * Parameter: * N/A * return: * 0: Succeeded; * ERR_HWID_NOT_FOUND: current hardware id not found. * ERR_FWID_NOT_FOUND: allowed firmware id not found. * ERR_READ_FLASH: Read command execution error. * ERR_BAD_ADDRESS: Invalid address values passed. * ERR_GENERIC: Web content error. */ int upgrade_init() { int ret = 0; //init local IDs. ret = localInfoInit(); if (ret < 0) { DBG("local info init failed, exit"); return ret; } return 0; } /* * Function Name: do_http_check * Author: CaiBin * Date: 2014-11-07 * Description: Firmware check. * Parameter: * size: Upgrading firmware size. * return: * 0: Succeeded; * ERR_INCORRECT_FILE_SIZE: File size is incorrect. * ERR_RSA_CHECK_FAIL: Signature is incorrect. * ERR_HWID_NOT_SUPPORTED: HwID is not supported. * ERR_PARTITION_TYPE_NOT_SUPPORTED: Firmware has not all partitions. * ERR_WRITE_FLASH: Write command execution error. * ERR_READ_FLASH: Read command execution error. * ERR_BAD_ADDRESS: Invalid address values passed. */ int do_http_check(const ulong size) { volatile int ret = 0; fw_info.buf = (unsigned char*)WEBFAILSAFE_UPLOAD_RAM_ADDRESS; fw_info.size = size; fw_info.uhTagLength = 0; #ifdef UIP_CACHE_OPERATION uip_cache_enable(); #endif //check firmware size, RSA signature, HwID, content type, and validate partitions. ret = checkFirmware(&fw_info); #ifdef UNIFY_FIRMWARE if (ret < 0) { goto goon; } ret = checkExtFirmware(&fw_info); #endif goon: #ifdef UIP_CACHE_OPERATION uip_cache_disable(); #endif if (ret < 0) { DBG("check firmware failed, exit"); return ret; } return ret; } /* * Function Name: do_http_upgrade * Author: CaiBin * Date: 2014-11-07 * Description: Firmware upgrade. * Parameter: * size: Upgrading firmware size. * return: * 0: Succeeded; * ERR_WRITE_FLASH: Write command execution error. * ERR_READ_FLASH: Read command execution error. * ERR_ERASE_FLASH: Erase command execution error. * ERR_BAD_ADDRESS: Invalid address values passed. */ int do_http_upgrade(const ulong size) { int ret = 0; //write upgrade data into flash. ret = upgradeFirmware(&fw_info); if (ret < 0) { DBG("upgrade firmware failed, exit"); return ret; } #ifdef UNIFY_FIRMWARE ret = upgradeExtFirmware(); #endif return ret; } // info about current progress of failsafe mode int do_http_progress(const int state){ unsigned char i = 0; /* toggle LED's here */ switch(state){ case WEBFAILSAFE_PROGRESS_START: /* turn on sys led. */ all_leds_on(1); printf("HTTP server is ready!\n\n"); break; case WEBFAILSAFE_PROGRESS_TIMEOUT: //printf("Waiting for request...\n"); break; case WEBFAILSAFE_PROGRESS_UPLOAD_READY: all_leds_on(0); printf("HTTP upload is done! Upgrading...\n"); break; case WEBFAILSAFE_PROGRESS_UPGRADE_READY: all_leds_on(0); printf("HTTP ugrade is done! Rebooting...\n\n"); break; case WEBFAILSAFE_PROGRESS_UPGRADE_ABORTED: all_leds_on(0); printf("\nWeb failsafe mode aborted!\n\n"); break; case WEBFAILSAFE_PROGRESS_UPGRADE_FAILED: all_leds_on(0); printf("## Error: HTTP ugrade failed!\n\n"); // wait 1 sec milisecdelay(1000); break; } return(0); }解析一下
09-04
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值