原创地址:http://blog.chinaunix.net/uid-361890-id-3248478.html
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;
- }
-
static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
点击(此处)折叠或打开
-
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;
- }
点击(此处)折叠或打开
-
__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