Uboot启动Linux内核

参考资料来源:
正点原子Linux驱动开发指南
 

image全局变量:

在bootm.c中,存在一个全局变量
bootm_headers_t images;         /* pointers to os/initrd/fdt images */
结构体定义如下:
image全局变量:
在bootm.c中,存在一个全局变量
bootm_headers_t images;         /* pointers to os/initrd/fdt images */
结构体定义如下:
 typedef struct image_info {
         ulong           start, end;             /* start/end of blob */
         ulong           image_start, image_len; /* start of image within blob, len of image */
         ulong           load;                   /* load addr for the image */
         uint8_t         comp, type, os;         /* compression, type of image, os type */
         uint8_t         arch;                   /* CPU architecture */
 } image_info_t;

   /*
  * Legacy and FIT format headers used by do_bootm() and do_bootm_<os>()
  * routines.
  */
 typedef struct bootm_headers {
         /*
          * Legacy os image header, if it is a multi component image
          * then boot_get_ramdisk() and get_fdt() will attempt to get
          * data from second and third component accordingly.
          */
         image_header_t  *legacy_hdr_os;         /* image header pointer */
         image_header_t  legacy_hdr_os_copy;     /* header copy */
         ulong           legacy_hdr_valid;

 #if defined(CONFIG_FIT)
         const char      *fit_uname_cfg; /* configuration node unit name */

         void            *fit_hdr_os;    /* os FIT image header */
         const char      *fit_uname_os;  /* os subimage node unit name */
         int             fit_noffset_os; /* os subimage node offset */

         void            *fit_hdr_rd;    /* init ramdisk FIT image header */
         const char      *fit_uname_rd;  /* init ramdisk subimage node unit name */
         int             fit_noffset_rd; /* init ramdisk subimage node offset */

         void            *fit_hdr_fdt;   /* FDT blob FIT image header */
         const char      *fit_uname_fdt; /* FDT blob subimage node unit name */
         int             fit_noffset_fdt;/* FDT blob subimage node offset */

         void            *fit_hdr_setup; /* x86 setup FIT image header */
         const char      *fit_uname_setup; /* x86 setup subimage node name */
         int             fit_noffset_setup;/* x86 setup subimage node offset */
 #endif

 #ifndef USE_HOSTCC
         image_info_t    os;             /* os image info */
         ulong           ep;             /* entry point of OS */

         ulong           rd_start, rd_end;/* ramdisk start/end */

         char            *ft_addr;       /* flat dev tree address */
         ulong           ft_len;         /* length of flat device tree */

         ulong           initrd_start;
         ulong           initrd_end;
         ulong           cmdline_start;
         ulong           cmdline_end;
         bd_t            *kbd;
 #endif
         int             verify;         /* getenv("verify")[0] != 'n' */

 #define BOOTM_STATE_START       (0x00000001)
 #define BOOTM_STATE_FINDOS      (0x00000002)
 #define BOOTM_STATE_FINDOTHER   (0x00000004)
 #define BOOTM_STATE_LOADOS      (0x00000008)
 #define BOOTM_STATE_RAMDISK     (0x00000010)
 #define BOOTM_STATE_FDT         (0x00000020)
 #define BOOTM_STATE_OS_CMDLINE  (0x00000040)
 #define BOOTM_STATE_OS_BD_T     (0x00000080)
 #define BOOTM_STATE_OS_PREP     (0x00000100)
 #define BOOTM_STATE_OS_FAKE_GO  (0x00000200)    /* 'Almost' run the OS */
 #define BOOTM_STATE_OS_GO       (0x00000400)
         int             state;

 #ifdef CONFIG_LMB
         struct lmb      lmb;            /* for memory mgmt */
 #endif
 } bootm_headers_t;
imx6ull的zImage地址0x80800000,dtb地址为0x83000000
 

bootz命令的执行流程:

 int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
         int ret;

         /* Consume 'bootz' */
         argc--; argv++;

         if (bootz_start(cmdtp, flag, argc, argv, &images))
                 return 1;

         /*
          * We are doing the BOOTM_STATE_LOADOS state ourselves, so must
          * disable interrupts ourselves
          */
         bootm_disable_interrupts();

         images.os.os = IH_OS_LINUX;
         ret = do_bootm_states(cmdtp, flag, argc, argv,
                               BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
                               BOOTM_STATE_OS_GO,
                               &images, 1);

         return ret;
 }
 
bootz执行流程:
bootz
    ->bootz_start
        ->do_bootm_states ->执行BOOTM_STATE_START阶段
            ->bootm_start 对images全局变量清零
        ->images->ep = 0x80800000
        ->bootz_setup 判断zImage是否符合要求
        ->bootm_find_images
            ->boot_get_fdt    找到设备树,然后将设备树起始地址和长度,写入到images的ft_addr和ft_len成员变量中
    ->bootm_disable_interrupts    关闭中断
    ->do_bootm_states    根据不同的BOOT状态执行不同的代码段
        ->bootm_os_get_boot_func    查找linux启动函数。找到linux内核启动函数,赋值给boot_fn
            ->do_bootm_linux
                ->boot_prep_linux    启动之前的一些工作,bootargs传给linux kernel
                ->boot_jump_linux
                    ->announce_and_cleanup    Starting kernel
                    ->kernel_entry    调用zImage里面的0x80800000处的函数
 

boot_jump_linux函数:

 static void boot_jump_linux(bootm_headers_t *images, int flag) {
 ...
         if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {    // 使用设备树
                 r0 = 2;
                 r2 = (unsigned int)images->ft_addr;
         } else {
                 r0 = 1;
                 r2 = (unsigned int)getenv("bootargs");
         }

         smp_set_core_boot_addr((unsigned long)kernel_entry, -1);
         smp_kick_all_cpus();

         if (!fake)
                 kernel_entry(r0, 0, r2);    // 使用设备树的情况下,r2表示设备树的起始地址
...  
}   
 

总体流程图:

0
 
posted @ 2024-03-21 15:30  lethe1203  阅读(14)  评论(0编辑  收藏  举报