启动内核时执行的命令是:
run run_kern:
(booti ${loadaddr} ${rd_spec} ${fdtaddr})
(booti 0x82000000 - 88000000)
}
我们的内核是非压缩的
ulong image_load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */
./arch/arm/lib/bootm.c:382:int
/* Main Entry point for arm bootm implementation
*
* Modeled after the powerpc implementation
* DIFFERENCE: Instead of calling prep and go at the end
* they are called if subcommand is equal 0.
*/
int do_bootm_linux(int flag, struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
/* No need for those on ARM */
if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
return -1;
if (flag & BOOTM_STATE_OS_PREP) {
boot_prep_linux(images);
return 0;
}
if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
boot_jump_linux(images, flag);
return 0;
}
boot_prep_linux(images);
boot_jump_linux(images, flag);
return 0;
}
调用的函数是:
int do_booti(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct bootm_info bmi;
int states;
int ret;
/* Consume 'booti' */
argc--; argv++; //去掉命令头
for (int i = 0; i < argc; i++) {
printf("i: %d, argv: %s\n", i, argv[i]);
}
bootm_init(&bmi);// 结构体清零, bmi->images = &images; 这个我不知道有什么用
printf("legacy_hdr_os: 0x%x, legacy_hdr_os_copy: 0x%x\n", bmi.images->legacy_hdr_os->ih_load, bmi.images->legacy_hdr_os_copy.ih_load);
if (argc)
bmi.addr_img = argv[0];
if (argc > 1)
bmi.conf_ramdisk = argv[1];
if (argc > 2)
bmi.conf_fdt = argv[2];
bmi.boot_progress = true;
bmi.cmd_name = "booti";
/* do not set up argc and argv[] since nothing uses them */
if (booti_start(&bmi))
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;
if (IS_ENABLED(CONFIG_RISCV_SMODE))
images.os.arch = IH_ARCH_RISCV;
else if (IS_ENABLED(CONFIG_ARM64))
images.os.arch = IH_ARCH_ARM64;
states = BOOTM_STATE_MEASURE | BOOTM_STATE_OS_PREP |
BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO;
if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
states |= BOOTM_STATE_RAMDISK;
ret = bootm_run_states(&bmi, states);
return ret;
}
static int bootm_start(void)
{
memset((void *)&images, 0, sizeof(images));
images.verify = env_get_yesno("verify");
printf("verify: %d\n", images.verify);
boot_start_lmb(&images); // 这个又是干嘛的, 有点像是初始化内存
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
images.state = BOOTM_STATE_START;
return 0;
}
int bootm_run_states(struct bootm_info *bmi, int states)
{
struct bootm_headers *images = bmi->images;
boot_os_fn *boot_fn;
ulong iflag = 0;
int ret = 0, need_boot_fn;
images->state |= states;
/*
* Work through the states and see how far we get. We stop on
* any error.
*/
if (states & BOOTM_STATE_START)
ret = bootm_start();
......
}
/*
* Image booting support
*/
static int booti_start(struct bootm_info *bmi)
{
struct bootm_headers *images = bmi->images;
int ret;
ulong ld;
ulong relocated_addr;
ulong image_size;
uint8_t *temp;
ulong dest;
ulong dest_end;
unsigned long comp_len;
unsigned long decomp_len;
int ctype;
ret = bootm_run_states(bmi, BOOTM_STATE_START);
/* Setup Linux kernel Image entry point */
if (!bmi->addr_img) {
ld = image_load_addr;
debug("* kernel: default image load address = 0x%08lx\n",
image_load_addr);
} else {
ld = hextoul(bmi->addr_img, NULL);
debug("* kernel: cmdline image address = 0x%08lx\n", ld);
}
// 这段我们不用在乎,因为我们用的是非压缩的
temp = map_sysmem(ld, 0);
ctype = image_decomp_type(temp, 2);
if (ctype > 0) {
dest = env_get_ulong("kernel_comp_addr_r", 16, 0);
comp_len = env_get_ulong("kernel_comp_size", 16, 0);
if (!dest || !comp_len) {
puts("kernel_comp_addr_r or kernel_comp_size is not provided!\n");
return -EINVAL;
}
if (dest < gd->ram_base || dest > gd->ram_top) {
puts("kernel_comp_addr_r is outside of DRAM range!\n");
return -EINVAL;
}
debug("kernel image compression type %d size = 0x%08lx address = 0x%08lx\n",
ctype, comp_len, (ulong)dest);
decomp_len = comp_len * 10;
ret = image_decomp(ctype, 0, ld, IH_TYPE_KERNEL,
(void *)dest, (void *)ld, comp_len,
decomp_len, &dest_end);
if (ret)
return ret;
/* dest_end contains the uncompressed Image size */
memmove((void *) ld, (void *)dest, dest_end);
}
unmap_sysmem((void *)ld);
ret = booti_setup(ld, &relocated_addr, &image_size, false);
if (ret || IS_ENABLED(CONFIG_SANDBOX))
return 1;
/* Handle BOOTM_STATE_LOADOS */
if (relocated_addr != ld) {
printf("Moving Image from 0x%lx to 0x%lx, end=%lx\n", ld,
relocated_addr, relocated_addr + image_size);
memmove((void *)relocated_addr, (void *)ld, image_size);
}
images->ep = relocated_addr;
images->os.start = relocated_addr;
images->os.end = relocated_addr + image_size;
lmb_reserve(&images->lmb, images->ep, le32_to_cpu(image_size));
/*
* Handle the BOOTM_STATE_FINDOTHER state ourselves as we do not
* have a header that provide this informaiton.
*/
if (bootm_find_images(image_load_addr, bmi->conf_ramdisk, bmi->conf_fdt,
relocated_addr, image_size))
return 1;
return 0;
}
void bootm_init(struct bootm_info *bmi)
{
memset(bmi, '\0', sizeof(struct bootm_info));
bmi->boot_progress = true;
if (IS_ENABLED(CONFIG_CMD_BOOTM)) {
printf("test aa bb cc dd\n");
bmi->images = &images; // 为啥要这样设置 这个结构体不知道干嘛的
}
}