打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
uboot 启动流程分析(二)

在 uboot 第一阶段启动完成后将会调用 start_armboot 开始第二阶段的启动流程,这个阶段的代码由 c 语言编写,分析如下:

一、基础数据结构

第二阶段主要用到了两个数据结构即 gd_t bd_t,其定义如下:

  1. /* 全局数据结构 */  
  2. typedef struct  global_data {  
  3.     bd_t            *bd;            /* 指向板级信息结构 */  
  4.     unsigned long   flags;          /* 标记位 */  
  5.     unsigned long   baudrate;       /* 串口波特率 */  
  6.     unsigned long   have_console;   /* serial_init() was called */  
  7.     unsigned long   env_addr;       /* 环境参数地址 */  
  8.     unsigned long   env_valid;      /* 环境参数 CRC 校验有效标志 */  
  9.     unsigned long   fb_base;        /* fb 起始地址 */  
  10. #ifdef CONFIG_VFD  
  11.     unsigned char   vfd_type;       /* 显示器类型(VFD代指真空荧光屏) */  
  12. #endif  
  13. #if 0  
  14.     unsigned long   cpu_clk;        /* cpu 频率*/  
  15.     unsigned long   bus_clk;        /* bus 频率 */  
  16.     phys_size_t     ram_size;       /* ram 大小 */  
  17.     unsigned long   reset_status;   /* reset status register at boot */  
  18. #endif  
  19.     void            **jt;           /* 跳转函数表 */  
  20. } gd_t;  
  21.   
  22. /* Global Data Flags */  
  23. #define GD_FLG_RELOC    0x00001     /* 代码已经转移到 RAM */  
  24. #define GD_FLG_DEVINIT  0x00002     /* 设备已经完成初始化 */  
  25. #define GD_FLG_SILENT   0x00004     /* 静音模式 */  
  26. #define GD_FLG_POSTFAIL 0x00008     /* Critical POST test failed */  
  27. #define GD_FLG_POSTSTOP 0x00010     /* POST seqeunce aborted */  
  28. #define GD_FLG_LOGINIT  0x00020     /* Log Buffer has been initialized  */  
  29. #define GD_FLG_DISABLE_CONSOLE  0x00040     /* Disable console (in & out)    */  
  30. /* 定义一个寄存器变量,占用寄存器r8,作为 gd_t 的全局指针 */  
  31. #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")  
  32.   
  33. /* 板级信息结构 */  
  34. typedef struct bd_info {  
  35.     int                   bi_baudrate;     /* serial console baudrate */  
  36.     unsigned long         bi_ip_addr;      /* IP Address */  
  37.     struct environment_s  *bi_env;         /* 板子的环境变量 */  
  38.     ulong                 bi_arch_number;  /* 板子的 id */  
  39.     ulong                 bi_boot_params;  /* 板子的启动参数 */  
  40.     struct                                 /* RAM 配置 */  
  41.     {  
  42.         ulong start;  
  43.         ulong size;  
  44.     } bi_dram[CONFIG_NR_DRAM_BANKS];  
  45. } bd_t;  
  46.   
  47. /************************************************************************** 
  48.  * 
  49.  * 每个环境变量以形如"name=value"的字符串存储并以'\0'结尾,环境变量的尾部以两个'\0'结束。 
  50.  * 新增的环境变量都依次添加在尾部,如果删除一个环境变量需要将其后面的向前移动 
  51.  * 如果替换一个环境变量需要先删除再新增。 
  52.  * 
  53.  * 环境变量采用 32 bit CRC 校验. 
  54.  * 
  55.  ************************************************************************** 
  56.  */  
  57.   
  58. /* 我们平台定义了8kB大小的环境变量存储区,地址空间位于4M ~ 6M */  
  59. #define CONFIG_ENV_IS_IN_NAND  
  60. #define CONFIG_ENV_OFFSET  0x00400000   /* 4M ~ 6M */  
  61. #define CONFIG_ENV_SIZE    8192         /* 8KB */  
  62. #define CONFIG_ENV_RANGE   0x00200000  
  63.   
  64. #define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE)  
  65. /* 环境变量结构 */  
  66. typedef struct environment_s {  
  67.     uint32_t  crc;                 /* CRC32 over data bytes */  
  68. #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT  
  69.     unsigned char flags;           /* active/obsolete flags */  
  70. #endif  
  71.     unsigned char data[ENV_SIZE];  /* Environment data */  
  72. } env_t;  

这两个类型变量记录了刚启动时的信息,还将记录作为引导内核和文件系统的参数,如 bootargs 等,并且将来还会在启动内核时,由 uboot 交由 kernel 时会有所用。

二、启动流程

1、init_sequence

start_armboot 首先为全局数据结构和板级信息结构分配内存,代码如下:

  1. #define CONFIG_UNCONTINUOUS_MEM  
  2. #define CONFIG_SYS_MALLOC_END  (MDDR_BASE_ADDR + 0x00600000)  
  3. #define CONFIG_SYS_MALLOC_LEN  0x00100000  /* 1MB */  
  4.   
  5. gd = (gd_t*)(CONFIG_SYS_MALLOC_END - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));  
  6.   
  7. __asm__ __volatile__("": : :"memory");  
  8.   
  9. memset ((void*)gd, 0, sizeof (gd_t));        /* 将全局数据清零 */  
  10. gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));  /* 取得板级信息数据结构的起始地址 */  
  11. memset (gd->bd, 0, sizeof (bd_t));           /* 将板级信息清零 */  
  12.   
  13. gd->flags |= GD_FLG_RELOC;  /* 标记为代码已经转移到 RAM */  

可以看到 bd_t 、gd_t 以及 MALLOC 区域是紧挨着的。然后依次调用 init_sequence数组中的函数指针完成各部分的初始化,代码如下:

  1. typedef int (init_fnc_t) (void);  
  2.   
  3. int print_cpuinfo (void);  
  4.   
  5. init_fnc_t *init_sequence[] = {  
  6. #if defined(CONFIG_ARCH_CPU_INIT)  
  7.     arch_cpu_init,          /* 与处理器架构相关的初始化 */  
  8. #endif  
  9.     board_init,             /* 板级特殊设备初始化 */  
  10. #if defined(CONFIG_USE_IRQ)  
  11.     interrupt_init,         /* 初始化中断 */  
  12. #endif  
  13.     timer_init,             /* 初始化定时器 */  
  14.     env_init,               /* 初始化环境变量 */  
  15.     init_baudrate,          /* 初始化波特率 */  
  16.     serial_init,            /* 初始化串口 */  
  17.     console_init_f,         /* 控制台初始化第一阶段 */  
  18.     display_banner,         /* 打印uboot版本信息 */  
  19. #if defined(CONFIG_DISPLAY_CPUINFO)  
  20.     print_cpuinfo,          /* 打印cpu信息及各总线频率 */  
  21. #endif  
  22. #if defined(CONFIG_DISPLAY_BOARDINFO)  
  23.     checkboard,             /* 打印板级信息 */  
  24. #endif  
  25. #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)  
  26.     init_func_i2c,          /* 初始化i2c */  
  27. #endif  
  28.     dram_init,              /* 配置有效的内存区 */  
  29. #if defined(CONFIG_CMD_PCI) || defined (CONFIG_PCI)  
  30.     arm_pci_init,  
  31. #endif  
  32.     display_dram_config,    /* 打印内存区配置信息 */  
  33.     NULL,  
  34. };  
  35.   
  36. for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {  
  37.     if ((*init_fnc_ptr)() != 0) {  
  38.         hang ();  
  39.     }  
  40. }  
  41.   
  42. void hang (void)  
  43. {  
  44.     puts ("### ERROR ### Please RESET the board ###\n");  
  45.     for (;;);  
  46. }  

在我们平台比较重要的初始化函数有 board_init 以及 env_init,代码如下:

  1. /* 板级特殊设备初始化 */  
  2. int board_init(void)  
  3. {  
  4.     uint32_t val;  
  5.     uint32_t adc_vol;  
  6.     uint32_t adc_per_vol;  
  7.     uint32_t adc_per_vol_res;  
  8.   
  9.     mmu_cache_on(memory_map);  /* 初始化mmu */  
  10.     clock_init();              /* 初始化时钟 */  
  11.   
  12.     calibrate_delay();         /* 延时校准 */  
  13.   
  14.     /*enable power */  
  15.     xx_request_gpio(GPIO_PMU_WAKEUP);  
  16.     xx_set_gpio_direction(GPIO_PMU_WAKEUP, 0);  
  17.     xx_gpio_set(GPIO_PMU_WAKEUP,0);  
  18.   
  19.     xx_request_gpio(GPIO_PMU_MODE);  
  20.     xx_set_gpio_direction(GPIO_PMU_MODE, 0);  
  21.     xx_gpio_set(GPIO_PMU_MODE,0);  
  22.   
  23.     i2c_init();  
  24.   
  25.     adc_init();  
  26.   
  27.     pmu_init();  
  28.   
  29.     keypad_init();  
  30.   
  31.     /* arch number of board */  
  32.     gd->bd->bi_arch_number = MACH_TYPE_XXX;  
  33.     /* adress of boot parameters */  
  34.     gd->bd->bi_boot_params = CONFIG_ATAG_ADDR;  
  35.   
  36.     return 0;  
  37. }  
  38.   
  39. /* 初始化环境变量 */  
  40. int env_init(void)  
  41. {  
  42.     gd->env_addr  = (ulong)&default_environment[0];  /* 设定默认的环境变量 */  
  43.     gd->env_valid = 1;  
  44.   
  45.     return (0);  
  46. }  

在环境变量 default_environment 中我们设置了很多参数,列表如下:

  1. uchar default_environment[] = {  
  2.     /* #define CONFIG_UBOOT_OFFSET  0x00200000 */  
  3.     "uboot-nandoff="MK_STR(CONFIG_UBOOT_OFFSET) "\0"  
  4.     /* #define CONFIG_UBOOT_LADDR   0x88007e00 */  
  5.     "uboot-laddr="  MK_STR(CONFIG_UBOOT_LADDR)  "\0"  
  6.   
  7.     /* #define CONFIG_BOOTARGS_SD    "console=ttyS0,921600n8 console=ttyMTD androidboot.console=ttyS0 \ 
  8.                                       mtdparts=atxx_nd:32M(boot),2M(ttyMTD),-(system) quiet" */  
  9.     "bootargs_sd="  CONFIG_BOOTARGS_SD      "\0"  
  10.     /* #define CONFIG_BOOTCOMMAND_SD "fatload mmc 1 0x89807e00 kboot.img; hdcvt 89807e00; bootm 89807fc0" */  
  11.     "bootcmd_sd="   CONFIG_BOOTCOMMAND_SD       "\0"  
  12.   
  13.     /* 各总线时钟频率 
  14.      * #define CONFIG_CLK_ARM    1001000000 
  15.      * #define CONFIG_CLK_AXI    312000000 
  16.      * #define CONFIG_CLK_APP    104000000 
  17.      * #define CONFIG_CLK_MDDR   201000000 
  18.      * #define CONFIG_CLK_GCLK   312000000 
  19.      * #define CONFIG_CLK_VPCLK  156000000 
  20.      * #define CONFIG_CLK_VSCLK  403000000 
  21.      */  
  22.     "clk-arm="     MK_STR(CONFIG_CLK_ARM)   "\0"  
  23.     "clk-axi="     MK_STR(CONFIG_CLK_AXI)   "\0"  
  24.     "clk-app="     MK_STR(CONFIG_CLK_APP)   "\0"  
  25.     "clk-mddr="    MK_STR(CONFIG_CLK_MDDR)  "\0"  
  26.     "clk-gclk="    MK_STR(CONFIG_CLK_GCLK)  "\0"  
  27.     "clk-vpclk="   MK_STR(CONFIG_CLK_VPCLK) "\0"  
  28.     "clk-vsclk="   MK_STR(CONFIG_CLK_VSCLK) "\0"  
  29.   
  30.     /* #define CONFIG_BOOTARGS  "console=ttyS0,921600n8 console=ttyMTD androidboot.console=ttyS0 mtdparts=\ 
  31.            atxx_nd:32M(boot),2M(ttyMTD),-(system) init=/init ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs ro" */  
  32.     "bootargs=" CONFIG_BOOTARGS         "\0"  
  33.     /* #define CONFIG_BOOTCOMMAND  "nand read 89807e00 600000 200000; hdcvt 89807e00; bootm 89807fc0" */  
  34.     "bootcmd="  CONFIG_BOOTCOMMAND      "\0"  
  35.     "clocks_in_mhz=1\0"  
  36. #ifdef  CONFIG_EXTRA_ENV_SETTINGS  
  37.     CONFIG_EXTRA_ENV_SETTINGS  
  38. #endif  
  39.     "\0"  
  40. };  
我们可以在 uboot 命令行模式下输入 printenv 命令查看当前的环境变量值。

2、start_armboot

start_armboot 在接下来的流程中还做了如下操作:

  1. void start_armboot (void)  
  2. {  
  3.     init_fnc_t **init_fnc_ptr;  
  4.     char *s;  
  5.     unsigned long addr;  
  6.     mem_malloc_init (CONFIG_SYS_MALLOC_END - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);  
  7.   
  8.     ...  
  9.     /* board init may have inited fb_base */  
  10.     if (!gd->fb_base) {  
  11.         /* 
  12.          * reserve memory for LCD display (always full pages) 
  13.          */  
  14.         /* bss_end is defined in the board-specific linker script */  
  15.         addr = CONFIG_SYS_MALLOC_END;  
  16.         lcd_setmem (addr);  
  17.         gd->fb_base = addr;  
  18.     }  
  19.   
  20.     nand_init();          /* 初始化 NAND */  
  21.   
  22.     env_relocate ();      /* 重定位环境变量,将其从 NAND 拷贝到内存中 */  
  23.   
  24.     serial_initialize();  /* 初始化串口 */  
  25.   
  26.     gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");  /* IP Address */  
  27.   
  28.     stdio_init ();        /* 初始化外设 */  
  29.   
  30.     jumptable_init ();    /* 初始化跳转函数表 */  
  31.   
  32.     console_init_r ();    /* 控制台初始化第二阶段 */  
  33.   
  34.     misc_init_r ();       /* 杂项设备初始化, eg:battery */  
  35.   
  36.     enable_interrupts (); /* enable exceptions */  
  37.   
  38.     /* #define CONFIG_SYS_LOAD_ADDR  (MDDR_BASE_ADDR + 0x00807e00) */  
  39.     /* 如果存在则从环境变量中读取装载地址,其默认为 ulong load_addr = CONFIG_SYS_LOAD_ADDR; */  
  40.     if ((s = getenv ("loadaddr")) != NULL) {  
  41.         load_addr = simple_strtoul (s, NULL, 16);  
  42.     }  
  43.   
  44.     /* main_loop() can return to retry autoboot, if so just run it again. */  
  45.     for (;;) {  
  46.         main_loop (); /* 进入主循环 common/main.c */  
  47.     }  
  48.   
  49.     /* NOTREACHED - no way out of command loop except booting */  
  50. }  
其中工作比较多的是 stdio_init 完成了部分外设的初始化:
  1. int stdio_init (void)  
  2. {  
  3.     /* 初始化设备链表 */  
  4.     INIT_LIST_HEAD(&(devs.list));  
  5.   
  6.     drv_lcd_init ();       /* 初始化 lcd,显示 Logo */  
  7.     drv_system_init ();    /* 初始化stdio设备系统 */  
  8.     serial_stdio_init ();  /* 初始化串口 */  
  9.   
  10.     return (0);  
  11. }  
start_armboot 最终进入 main_loop 函数,首先判断用户选择的启动模式,如果是命令模式则等待输入命令然后执行,代码如下:
  1. void main_loop (void)  
  2. {  
  3.     static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };  
  4.     int len;  
  5.     int rc = 1;  
  6.     int flag;  
  7.     char *s;  
  8.     int bootdelay;  
  9.   
  10.     s = getenv ("bootdelay");  
  11.     bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;  /* 获取超时信息 */  
  12.     s = getenv ("bootcmd");  /* 获取启动命令 */  
  13.   
  14.     /* abortboot会判断用户选择的启动模式,如果是命令模式就会返回1,如果是其他模式就不再返回 */  
  15.     if (bootdelay >= 0 && s && !abortboot (bootdelay)) {  
  16.         s = getenv ("bootcmd");  
  17.         run_command (s, 0);  
  18.     }  
  19.   
  20.     for (;;) {  
  21.         len = readline (CONFIG_SYS_PROMPT);        /* 读取输入 */  
  22.   
  23.         flag = 0;  
  24.         if (len > 0)  
  25.             strcpy (lastcommand, console_buffer);  /* 将输入保存到历史记录中 */  
  26.         else if (len == 0)  
  27.             flag |= CMD_FLAG_REPEAT;               /* 如果没有输入则重复上次 */  
  28.   
  29.         if (len == -1)  
  30.             puts ("<INTERRUPT>\n");  
  31.         else  
  32.             rc = run_command (lastcommand, flag);  /* 执行命令 */  
  33.   
  34.         if (rc <= 0) {  /* 执行错误的命令从历史记录中删除 */  
  35.             lastcommand[0] = 0;  
  36.         }  
  37.     }  
  38. }  

附:启动命令解析

在 uboot 进入主循环后默认会进入 nand 启动模式,会依次执行 3 个命令:

  1. bootcmd=nand read 89807e00 600000 200000; hdcvt 89807e00; bootm 89807fc0  
1、nand 命令

该命令用于进行各种 nand 操作,用法如下:

  1. nand - NAND sub-system  
  2.   
  3. Usage:  
  4. nand info - show available NAND devices  
  5. nand device [dev] - show or set current device  
  6. nand read - addr off|partition size  
  7. nand write - addr off|partition size  
  8.     read/write 'size' bytes starting at offset 'off'  
  9.     to/from memory address 'addr', skipping bad blocks.  
  10. nand bad - show bad blocks  
  11. nand dump[.oob] off - dump page  
  12. nand scrub - really clean NAND erasing bad blocks (UNSAFE)  
  13. nand markbad off [...] - mark bad block(s) at offset (UNSAFE)  
  14. nand biterr off - make a bit error at offset (UNSAFE)  
在启动命令中用到了

  1. nand read 89807e00 600000 200000;  
即从 nand 偏移为 0x600000 的地方读取长度为 0x200000 字节(2M)的数据到内存 0x89807e00 地址处。对于这几个参数的解释需要了解 内存地址空间 nand 地址空间 是怎么分配的:
  1. /* we have 1 bank of DRAM */  
  2. #define CONFIG_NR_DRAM_BANKS            1  
  3. #define MDDR_BASE_ADDR                  0x88000000      /* 物理内存的起始地址 */  
  4.   
  5. #define CONFIG_SYS_MALLOC_END           (MDDR_BASE_ADDR + 0x00600000)   /* MALLOC 区结束地址 */  
  6. #define CONFIG_SYS_MALLOC_LEN           0x00100000                      /* MALLOC 区长度 1MB */  
  7.   
  8. /* u-boot run address */  
  9. #define CONFIG_SYS_UBOOT_BASE           (MDDR_BASE_ADDR + 0x00008000)   /* uboot 加载的起始地址 */  
  10. #define CONFIG_UBOOT_LADDR              0x88007e00  
  11.   
  12. /* default load address for reading (i.e. kernel zImage with header) */  
  13. #define CONFIG_SYS_LOAD_ADDR            (MDDR_BASE_ADDR + 0x00807e00)   /* kernel 加载的起始地址 */  
  14. #define CONFIG_SYS_KERN_ADDR            (MDDR_BASE_ADDR + 0x00808000)   /* kernel 入口地址 */  
  15. #define CONFIG_ATAG_ADDR                (MDDR_BASE_ADDR + 0x01800100)   /* kernel 启动参数地址 */  
  16.   
  17. /* xloader 存储的起始地址为 0,长度为 2M */  
  18. #define CONFIG_XLOADER_OFFSET           0x00000000    /* 0M ~ 2M */  
  19. #define CONFIG_XLOADER_MSIZE            0x00200000  
  20.   
  21. /* uboot 存储的起始地址为 2M,长度为 2M */  
  22. #define CONFIG_UBOOT_OFFSET             0x00200000    /* 2M ~ 4M */  
  23. #define CONFIG_UBOOT_MSIZE              0x00200000  
  24.   
  25. /* 环境变量存储的起始地址为 4M,默认长度为 8k */  
  26. #define CONFIG_ENV_OFFSET               0x00400000    /* 4M ~ 6M */  
  27. #define CONFIG_ENV_SIZE                 8192          /* 8KB */  
  28. #define CONFIG_ENV_RANGE                0x00200000  
  29.   
  30. /* kernel 存储的起始地址为 6M,长度为 3M */  
  31. #define CONFIG_KERNEL_OFFSET            0x00600000    /* 6M ~ 9M */  
  32. #define CONFIG_KERNEL_MSIZE             0x00300000  
在烧录镜像到 nand 的时候程序会按照上表将 xloader、uboot、kernel 分别烧录到其对应空间,这段 nand 空间是以 1M 为单位对齐的。

2、hdcvt 命令

自动启动中用到的第二个命令是:

  1. hdcvt 89807e00  
该命令将位于内存 0x89807e00 的平台镜像头转换为标准的镜像头,用法介绍如下:

  1. Usage:  
  2. hdcvt usage: hdcvt addr_from [addr_to] [body_addr]  
生成的标准镜像头存储起始地址为:addr_to = addr_from - sizeof(xx_image_header_t) - sizeof(image_header_t)。这里涉及到两个新的结构体struct xx_image_header 和 struct image_header:前者是平台的镜像头,后者为标准镜像头,定义如下:
  1. /* 平台镜像头,长度512Byte,填充在kernel的加载地址与入口地址之间的区域:0x89807e00 ~ 0x89808000 */  
  2. typedef struct xx_image_header {  
  3.     unsigned char       iv[IV_SIZE];  
  4.     unsigned int        boot_signature;  
  5.     unsigned int        load_address;             /* 加载地址 = 镜像入口 - 标准镜像头长度(64Byte) */  
  6.     unsigned int        run_address;              /* 镜像入口 */  
  7.     unsigned int        firm_size;                /* 镜像长度 */  
  8.     unsigned int        nand_offset;  
  9.     unsigned int        image_type;               /* 镜像类型 */  
  10.     unsigned char       board_name[16];  
  11.     unsigned char       reserved[40];  
  12.     unsigned char       certificate[CERT_SIZE];  
  13.     unsigned char       signature[SIGE_SIZE];  
  14. } xx_image_header_t;  
  15.   
  16. /* 标准镜像头,长度64Byte,填充在kernel入口地址之前:0x89807fc0 ~ 0x89808000 */  
  17. typedef struct image_header {  
  18.     uint32_t    ih_magic;   /* 魔数,用于检测是否存在镜像头*/  
  19.     uint32_t    ih_hcrc;    /* 镜像头校验和*/  
  20.     uint32_t    ih_time;    /* 镜像创建时间 */  
  21.     uint32_t    ih_size;    /* 镜像大小 */  
  22.     uint32_t    ih_load;    /* 镜像加载地址 */  
  23.     uint32_t    ih_ep;      /* 镜像入口地址 */  
  24.     uint32_t    ih_dcrc;    /* 镜像校验和 */  
  25.     uint8_t     ih_os;      /* 系统类型 */  
  26.     uint8_t     ih_arch;    /* 处理器类型 */  
  27.     uint8_t     ih_type;    /* 镜像类型 */  
  28.     uint8_t     ih_comp;    /* 压缩类型 */  
  29.     uint8_t     ih_name[IH_NMLEN];  /* 镜像名称 */  
  30. } image_header_t;  
3、bootm 命令

bootm 用于启动 linux,参数为镜像的加载地址:

  1. bootm 89807fc0  

可以看到加载地址为 0x89807fc0,这个地址在镜像头中保存,计算方法:ih_load = ih_ep - sizeof(struct image_header) 即:0x89807fc0 = 0x89808000 - 0x40。该命令执行时串口信息如下:

  1. Booting kernel from Legacy Image at 89807fc0 ...  
  2.    Image Name:   Linux-2.6.32.9  
  3.    Image Type:   ARM Linux Kernel Image (uncompressed)  
  4.    Data Size:    1964376 Bytes =  1.9 MB  
  5.    Load Address: 89807fc0  
  6.    Entry Point:  89808000  
  7.    Verifying Checksum ... OK  
  8.    XIP Kernel Image ... OK  
  9. OK  
  10.   
  11. Starting kernel ...  

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
uboot 分析之 启动流程
【已解决】*** Warning - bad CRC or NAND, using default environment
Warning - bad CRC or NAND, using default environment
uboot环境变量实现分析
uboot移植到S3C44B0X开发板的经历(转载)
Uboot 大全 | uboot 启动流程(一)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服