uboot 2011.12, powerpc开发板
---------------------------------
1. 从common/cmd_bootm.c ----> do_bootm开始分析,因为多数启动都是用命令bootm kernel_add ramdisk_addr fdt_addr.
2. 先贴函数的代码:
- int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
- {
- ulong iflag;
- ulong load_end = 0;
- int ret;
- boot_os_fn *boot_fn;
- #ifdef CONFIG_NEEDS_MANUAL_RELOC
- static int relocated = 0;
- /* relocate boot function table */
- if (!relocated) {
- int i;
- for (i = 0; i < ARRAY_SIZE(boot_os); i++)
- if (boot_os[i] != NULL)
- boot_os[i] += gd->reloc_off;
- relocated = 1;
- }
- #endif
- /* determine if we have a sub command */
- if (argc > 1) {
- char *endp;
- simple_strtoul(argv[1], &endp, 16);
- /* endp pointing to NULL means that argv[1] was just a
- * valid number, pass it along to the normal bootm processing
- *
- * If endp is ':' or '#' assume a FIT identifier so pass
- * along for normal processing.
- *
- * Right now we assume the first arg should never be '-'
- */
- if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
- //此函数为bootm的子命令,在多核系统时,通常通过这些子命令来先动其它核,再启动0核
- return do_bootm_subcommand(cmdtp, flag, argc, argv);
- }
- //bootm_start准备内核,并检查内核的完整性
- if (bootm_start(cmdtp, flag, argc, argv))
- return 1;
- static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
- {
- void *os_hdr;
- int ret;
- memset((void *)&images, 0, sizeof(images));
- images.verify = getenv_yesno("verify");
- //设置内存信息,此内存信息会被传到linux kernel
- bootm_start_lmb();
- /* get kernel image header, start address and length */
- //获取kernel的bin文件,os_hdr是tftp或其它方式下载kernel到内存的地址,images_start是压缩kernel(zImage)的头地址,即uImage头地址+0x40,image_len是长度。
- ## Current stack ends at 0x3fe2dbc0
* kernel: cmdline image address = 0x01000000
--- p1_p2_rdb_pc.c show_boot_progress 165 i:1
## Booting kernel from Legacy Image at 01000000 ...
--- p1_p2_rdb_pc.c show_boot_progress 165 i:2
--- p1_p2_rdb_pc.c show_boot_progress 165 i:3
Image Name: Linux-3.0.32-rt52-02290-g11251b1
Created: 2012-06-06 6:44:40 UTC
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 3470673 Bytes = 3.3 MiB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
--- p1_p2_rdb_pc.c show_boot_progress 165 i:4
--- p1_p2_rdb_pc.c show_boot_progress 165 i:5
--- p1_p2_rdb_pc.c show_boot_progress 165 i:6
kernel data at 0x01000040, len = 0x0034f551 (3470673)
- os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
- &images, &images.os.image_start, &images.os.image_len);
- if (images.os.image_len == 0) {
- puts("ERROR: can't get kernel image!\n");
- return 1;
- }
- /* get image parameters */
- switch (genimg_get_format(os_hdr)) {
- case IMAGE_FORMAT_LEGACY:
- //设置image的一些参数,从uImage的64字节头获取
- images.os.type = image_get_type(os_hdr);
- images.os.comp = image_get_comp(os_hdr);
- images.os.os = image_get_os(os_hdr);
- images.os.end = image_get_image_end(os_hdr);
- images.os.load = image_get_load(os_hdr);
- break;
- #if defined(CONFIG_FIT)
- case IMAGE_FORMAT_FIT:
- if (fit_image_get_type(images.fit_hdr_os,
- images.fit_noffset_os, &images.os.type)) {
- puts("Can't get image type!\n");
- show_boot_progress(-109);
- return 1;
- }
- if (fit_image_get_comp(images.fit_hdr_os,
- images.fit_noffset_os, &images.os.comp)) {
- puts("Can't get image compression!\n");
- show_boot_progress(-110);
- return 1;
- }
- if (fit_image_get_os(images.fit_hdr_os,
- images.fit_noffset_os, &images.os.os)) {
- puts("Can't get image OS!\n");
- show_boot_progress(-111);
- return 1;
- }
- images.os.end = fit_get_end(images.fit_hdr_os);
- if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os,
- &images.os.load)) {
- puts("Can't get image load address!\n");
- show_boot_progress(-112);
- return 1;
- }
- break;
- #endif
- default:
- puts("ERROR: unknown image format type!\n");
- return 1;
- }
- /* find kernel entry point */
- if (images.legacy_hdr_valid) {
- //执行此处,因为64Byte头已经做好了备份,即复制到了另一个头结构体中。获取入口地址,通常为0x0.
- images.ep = image_get_ep(&images.legacy_hdr_os_copy);
- #if defined(CONFIG_FIT)
- } else if (images.fit_uname_os) {
- ret = fit_image_get_entry(images.fit_hdr_os,
- images.fit_noffset_os, &images.ep);
- if (ret) {
- puts("Can't get entry point property!\n");
- return 1;
- }
- #endif
- } else {
- puts("Could not find kernel entry point!\n");
- return 1;
- }
- if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
- images.os.load = images.os.image_start;
- images.ep += images.os.load;
- }
- if (((images.os.type == IH_TYPE_KERNEL) ||
- (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
- (images.os.type == IH_TYPE_MULTI)) &&
- (images.os.os == IH_OS_LINUX)) { //执行此处,因为type == IH_TYPE_KERNEL, os == IH_OS_LINUX
- /* find ramdisk */
* ramdisk: cmdline image address = 0x02000000
## Loading init Ramdisk from Legacy Image at 02000000 ...
--- p1_p2_rdb_pc.c show_boot_progress 165 i:9
--- p1_p2_rdb_pc.c show_boot_progress 165 i:10
Image Name: fsl-image-core-p2020rdb-20120406
Created: 2012-04-06 11:43:16 UTC
Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
Data Size: 23085665 Bytes = 22 MiB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
--- p1_p2_rdb_pc.c show_boot_progress 165 i:11
ramdisk start = 0x02000040, ramdisk end = 0x036042a1
- ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH,
- &images.rd_start, &images.rd_end);
- if (ret) {
- puts("Ramdisk image is corrupt or invalid\n");
- return 1;
- }
- #if defined(CONFIG_OF_LIBFDT)
- /* find flattened device tree */
//* fdt: cmdline image address = 0x00c00000
## Checking for 'FDT'/'FDT Image' at 00c00000
Wrong FIT format: no description
* fdt: raw FDT blob
## Flattened Device Tree blob at 00c00000
Booting using the fdt blob at 0x00c00000
of_flat_tree at 0x00c00000 size 0x000032e8
- ret = boot_get_fdt(flag, argc, argv, &images,
- &images.ft_addr, &images.ft_len);
- if (ret) {
- puts("Could not find a valid device tree\n");
- return 1;
- }
- set_working_fdt_addr(images.ft_addr);
- #endif
- }
- images.os.start = (ulong)os_hdr;
- images.state = BOOTM_STATE_START;
- return 0;
- }
- iflag = disable_interrupts();
- #if defined(CONFIG_CMD_USB)
- /*
- * turn off USB to prevent the host controller from writing to the
- * SDRAM while Linux is booting. This could happen (at least for OHCI
- * controller), because the HCCA (Host Controller Communication Area)
- * lies within the SDRAM and the host controller writes continously to
- * this area (as The HccaFrameNumber is for example
- * updated every 1 ms within the HCCA structure in For more
- * details see the OpenHCI specification.
- */
- usb_stop();
- #endif
-
- // 解压缩内核镜相文件,
- Uncompressing Kernel Image ... OK
kernel loaded at 0x00000000, end = 0x006c3b00
--- p1_p2_rdb_pc.c show_boot_progress 165 i:7
- ret = bootm_load_os(images.os, &load_end, 1);
- if (ret < 0) { //加载kernel的错误处理
- if (ret == BOOTM_ERR_RESET)
- do_reset(cmdtp, flag, argc, argv);
- if (ret == BOOTM_ERR_OVERLAP) {
- if (images.legacy_hdr_valid) {
- image_header_t *hdr;
- hdr = &images.legacy_hdr_os_copy;
- if (image_get_type(hdr) == 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;
- }
- }
//把kernel解压后所占的内在预留起来,以免其它程序再用,此参数会传到kernel里
- lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load));
- if (images.os.type == IH_TYPE_STANDALONE) { //不会执行此处
- if (iflag)
- enable_interrupts();
- /* This may return when 'autostart' is 'no' */
- bootm_start_standalone(iflag, argc, argv);
- return 0;
- }
- show_boot_progress(8);
- #ifdef CONFIG_SILENT_CONSOLE
- if (images.os.os == IH_OS_LINUX)
- fixup_silent_linux();
- #endif
- //获取kernel启动函数,此处为:do_bootm_linux,因为images.os.os==5
- 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);
- ------------->不会执行到这里,因为boot_fn函数会启动kernel
- show_boot_progress(-9);
- #ifdef DEBUG
- puts("\n## Control returned to monitor - resetting...\n");
- #endif
- do_reset(cmdtp, flag, argc, argv);
- return 1;
- }
3. boot_fn实际上是do_bootm_linux,接下来分析此函数:
- __attribute__((noinline))
- int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
- {
- int ret;
- if (flag & BOOTM_STATE_OS_CMDLINE) {
- boot_cmdline_linux(images);
- return 0;
- }
- if (flag & BOOTM_STATE_OS_BD_T) {
- boot_bd_t_linux(images);
- return 0;
- }
- if (flag & BOOTM_STATE_OS_PREP) {
- boot_prep_linux(images);
- return 0;
- }
- if (flag & BOOTM_STATE_OS_GO) {
- boot_jump_linux(images);
- return 0;
- }
- //以上flag的处理多数是为多核准备的。
- boot_prep_linux(images); //flush 相关的cache, 此时cache的数据对内核没用
- //分配内存给命令行参数,板子信息,DTB信息等
- ret = boot_body_linux(images);
- if (ret)
- return ret;
- boot_jump_linux(images);
- return 0;
- }
- static void boot_jump_linux(bootm_headers_t *images)
- {
- void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6,
- ulong r7, ulong r8, ulong r9);
- #ifdef CONFIG_OF_LIBFDT
- char *of_flat_tree = images->ft_addr;
- #endif
- //获取kernel入口地址,通常为0x0.
- kernel = (void (*)(bd_t *, ulong, ulong, ulong,
- ulong, ulong, ulong))images->ep;
- printf("## Transferring control to Linux (at address %08lx) ...\n",
- (ulong)kernel);
- show_boot_progress (15);
- #if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
- unlock_ram_in_cache();
- #endif
- #if defined(CONFIG_OF_LIBFDT) //执行此处
- if (of_flat_tree) { /* device tree; boot new style */
- /*
- * Linux Kernel Parameters (passing device tree):
- * r3: pointer to the fdt
- * r4: 0
- * r5: 0
- * r6: epapr magic
- * r7: size of IMA in bytes
- * r8: 0
- * r9: 0
- */
- #if defined(CONFIG_MPC85xx) || defined(CONFIG_440)
- #define EPAPR_MAGIC (0x45504150)
- #else
- #define EPAPR_MAGIC (0x65504150)
- #endif
- printf(" Booting using OF flat tree...\n");
- WATCHDOG_RESET ();
- //开始执行内核代码
- (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
- getenv_bootm_mapsize(), 0, 0);
- /* does not return */
- } else
阅读(819) | 评论(0) | 转发(0) |