uboot从bootm跳到内核
main_loop中执行的最重要的操作便是引导内核。引导分两步。第一步先读取内核镜像uImage到内存。然后再使用bootm引导内核。
读取内核只是进行内存复制,因此仅仅需要分析bootm。
-
-
-
- 引导应用程序在内存中的镜像。
- common/cmd_bootm.c
- int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
- {
- ulong iflag;
- ulong load_end = 0;
- int ret;
- boot_os_fn *boot_fn;
- 检查是否有子命令
- if (argc > 1) {
- char *endp;
- simple_strtoul(argv[1], &endp, 16);
-
-
-
-
-
-
-
-
- if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
- return do_bootm_subcommand(cmdtp, flag, argc, argv);
- }
- if (bootm_start(cmdtp, flag, argc, argv))
- return 1;
-
-
-
-
-
- iflag = disable_interrupts();
- ret = bootm_load_os(images.os, &load_end, 1);
- if (ret < 0) {
- if (ret == BOOTM_ERR_RESET)
- do_reset (cmdtp, flag, argc, argv);
- if (ret == BOOTM_ERR_OVERLAP) {
- if (images.legacy_hdr_valid) {
- if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI)
- puts ("WARNING: legacy format multi component "
- "image overwritten/n");
- } else {
- puts ("ERROR: new format image overwritten - "
- "must RESET the board to recover/n");
- show_boot_progress (-113);
- do_reset (cmdtp, flag, argc, argv);
- }
- }
- if (ret == BOOTM_ERR_UNIMPLEMENTED) {
- if (iflag)
- enable_interrupts();
- show_boot_progress (-7);
- return 1;
- }
- }
- lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
- if (images.os.type == IH_TYPE_STANDALONE) {
- if (iflag)
- enable_interrupts();
-
- bootm_start_standalone(iflag, argc, argv);
- return 0;
- }
- show_boot_progress (8);
- boot_fn = boot_os[images.os.os];
- if (boot_fn == NULL) {
- if (iflag)
- enable_interrupts();
- printf ("ERROR: booting os '%s' (%d) is not supported/n",
- genimg_get_os_name(images.os.os), images.os.os);
- show_boot_progress (-8);
- return 1;
- }
- arch_preboot_os();
- boot_fn(0, argc, argv, &images);
- show_boot_progress (-9);
- #ifdef DEBUG
- puts ("/n## Control returned to monitor - resetting.../n");
- #endif
- do_reset (cmdtp, flag, argc, argv);
- return 1;
- }
|
2。boot_os
- static boot_os_fn *boot_os[] = {
- #ifdef CONFIG_BOOTM_LINUX
- [IH_OS_LINUX] = do_bootm_linux,
- #endif
- #ifdef CONFIG_BOOTM_NETBSD
- [IH_OS_NETBSD] = do_bootm_netbsd,
- #endif
- #ifdef CONFIG_LYNXKDI
- [IH_OS_LYNXOS] = do_bootm_lynxkdi,
- #endif
- #ifdef CONFIG_BOOTM_RTEMS
- [IH_OS_RTEMS] = do_bootm_rtems,
- #endif
- #if defined(CONFIG_CMD_ELF)
- [IH_OS_VXWORKS] = do_bootm_vxworks,
- [IH_OS_QNX] = do_bootm_qnxelf,
- #endif
- #ifdef CONFIG_INTEGRITY
- [IH_OS_INTEGRITY] = do_bootm_integrity,
- #endif
- };
|
3。do_bootm_linux
之前所做的引导工作都是与操作系统无关的,接下来都是针对linux 的。
可以看到,参数flag传过来的是0。
- arch/arm/lib/bootm.c
- int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
- {
- bd_t *bd = gd->bd;
- char *s;
- int machid = bd->bi_arch_number;
- void (*theKernel)(int zero, int arch, uint params);
- #ifdef CONFIG_CMDLINE_TAG//如果定义了这个宏,将会把bootargs传给内核。
- char *commandline = getenv ("bootargs");
- #endif
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
- return 1;
- theKernel = (void (*)(int, int, uint))images->ep;
- s = getenv ("machid");
- if (s) {
- machid = simple_strtoul (s, NULL, 16);
- printf ("Using machid 0x%x from environment/n", machid);
- }
- show_boot_progress (15);
- debug ("## Transferring control to Linux (at address %08lx) .../n",
- (ulong) theKernel);
-
- #if defined (CONFIG_SETUP_MEMORY_TAGS) || /
- defined (CONFIG_CMDLINE_TAG) || /
- defined (CONFIG_INITRD_TAG) || /
- defined (CONFIG_SERIAL_TAG) || /
- defined (CONFIG_REVISION_TAG)
- setup_start_tag (bd);
- #ifdef CONFIG_SETUP_MEMORY_TAGS
- setup_memory_tags (bd);
- #endif
- #ifdef CONFIG_CMDLINE_TAG
- setup_commandline_tag (bd, commandline);
- #endif
- #ifdef CONFIG_INITRD_TAG
- if (images->rd_start && images->rd_end)
- setup_initrd_tag (bd, images->rd_start, images->rd_end);
- #endif
- setup_end_tag (bd);
- #endif
-
- printf ("/nStarting kernel .../n/n");
- cleanup_before_linux ();
- theKernel (0, machid, bd->bi_boot_params);
-
- return 1;
- }
|
4.
- arch/arm/include/asm
-
- #define ATAG_CORE 0x54410001
- struct tag_core {
- u32 flags;
- u32 pagesize;
- u32 rootdev;
- };
-
- #define ATAG_CMDLINE 0x54410009
- struct tag_cmdline {
- char cmdline[1];
- };
-
-
-
-
-
- #define ATAG_INITRD 0x54410005
-
- #define ATAG_INITRD2 0x54420005
- struct tag_initrd {
- u32 start;
- u32 size;
- };
-
- #define ATAG_MEM 0x54410002
- struct tag_mem32 {
- u32 size;
- u32 start;
- };
- struct tag_header {
- u32 size;
- u32 tag;
- };
- struct tag {
- struct tag_header hdr;
- union {
- struct tag_core core;
- struct tag_mem32 mem;
- struct tag_videotext videotext;
- struct tag_ramdisk ramdisk;
- struct tag_initrd initrd;
- struct tag_serialnr serialnr;
- struct tag_revision revision;
- struct tag_videolfb videolfb;
- struct tag_cmdline cmdline;
-
-
-
- struct tag_acorn acorn;
-
-
-
- struct tag_memclk memclk;
- } u;
- };
|
5
- arch/arm/include/asm/setup.h
- #define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))//跳到下一个tag地址处
- arch/arm/lib/bootm.c
- static void setup_start_tag (bd_t *bd)
- {
- params = (struct tag *) bd->bi_boot_params;
- params->hdr.tag = ATAG_CORE;
- params->hdr.size = tag_size (tag_core);
- params->u.core.flags = 0;
- params->u.core.pagesize = 0;
- params->u.core.rootdev = 0;
- params = tag_next (params);
- }
- #ifdef CONFIG_SETUP_MEMORY_TAGS
- static void setup_memory_tags (bd_t *bd)
- {
- int i;
- for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
- params->hdr.tag = ATAG_MEM;
- params->hdr.size = tag_size (tag_mem32);
- params->u.mem.start = bd->bi_dram[i].start;
- params->u.mem.size = bd->bi_dram[i].size;
- params = tag_next (params);
- }
- }
- #endif /* CONFIG_SETUP_MEMORY_TAGS */
- static void setup_commandline_tag (bd_t *bd, char *commandline)
- {
- char *p;
- if (!commandline)
- return;
-
- for (p = commandline; *p == ' '; p++);
-
-
-
- if (*p == '/0')
- return;
- params->hdr.tag = ATAG_CMDLINE;
- params->hdr.size =
- (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
- strcpy (params->u.cmdline.cmdline, p);
- params = tag_next (params);
- }
- #ifdef CONFIG_INITRD_TAG
- static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
- {
-
-
-
- params->hdr.tag = ATAG_INITRD2;
- params->hdr.size = tag_size (tag_initrd);
- params->u.initrd.start = initrd_start;
- params->u.initrd.size = initrd_end - initrd_start;
- params = tag_next (params);
- }
- #endif /* CONFIG_INITRD_TAG */
- static void setup_end_tag (bd_t *bd)
- {
- params->hdr.tag = ATAG_NONE;
- params->hdr.size = 0;
- }
|
评论暂时关闭