static int bootm_linux_fdt(int machid, bootm_headers_t *images) { ulong rd_len; void (*kernel_entry)(int zero, int dt_machid, void *dtblob); ulong bootmap_base = getenv_bootm_low(); ulong of_size = images->ft_len; char **of_flat_tree = &images->ft_addr; ulong *initrd_start = &images->initrd_start; ulong *initrd_end = &images->initrd_end; struct lmb *lmb = &images->lmb; int ret; kernel_entry = (void (*)(int, int, void *))images->ep; rd_len = images->rd_end - images->rd_start; ret = boot_ramdisk_high(lmb, images->rd_start, rd_len, initrd_start, initrd_end); if (ret) return ret; ret = boot_relocate_fdt(lmb, bootmap_base, of_flat_tree, &of_size); if (ret) return ret; debug("## Transferring control to Linux (at address %08lx) ...\n", (ulong) kernel_entry); fdt_chosen(*of_flat_tree, 1); fixup_memory_node(*of_flat_tree); fdt_fixup_ethernet(*of_flat_tree); #ifdef CONFIG_DMAMEM fdt_fixup_dmamem(*of_flat_tree); #endif #ifdef CONFIG_SWITCH fdt_fixup_switch(*of_flat_tree); #endif fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); announce_and_cleanup(); kernel_entry(0, machid, *of_flat_tree); /* does not return */ return 1; }
int image_setup_libfdt(bootm_headers_t *images, void *blob, int of_size, struct lmb *lmb) { ulong *initrd_start = &images->initrd_start; ulong *initrd_end = &images->initrd_end; int ret; if (fdt_chosen(blob, 1) < 0) { puts("ERROR: /chosen node create failed"); puts(" - must RESET the board to recover.\n"); return -1; } arch_fixup_memory_node(blob); if (IMAGE_OF_BOARD_SETUP) ft_board_setup(blob, gd->bd); fdt_fixup_ethernet(blob); /* Delete the old LMB reservation */ lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob, (phys_size_t)fdt_totalsize(blob)); ret = fdt_resize(blob); if (ret < 0) return ret; of_size = ret; if (*initrd_start && *initrd_end) { of_size += FDT_RAMDISK_OVERHEAD; fdt_set_totalsize(blob, of_size); } /* Create a new LMB reservation */ lmb_reserve(lmb, (ulong)blob, of_size); fdt_initrd(blob, *initrd_start, *initrd_end, 1); if (!ft_verify_fdt(blob)) return -1; return 0; }
int image_setup_libfdt(bootm_headers_t *images, void *blob, int of_size, struct lmb *lmb) { ulong *initrd_start = &images->initrd_start; ulong *initrd_end = &images->initrd_end; int ret = -EPERM; int fdt_ret; if (fdt_root(blob) < 0) { printf("ERROR: root node setup failed\n"); goto err; } if (fdt_chosen(blob) < 0) { printf("ERROR: /chosen node create failed\n"); goto err; } if (arch_fixup_fdt(blob) < 0) { printf("ERROR: arch-specific fdt fixup failed\n"); goto err; } if (IMAGE_OF_BOARD_SETUP) { fdt_ret = ft_board_setup(blob, gd->bd); if (fdt_ret) { printf("ERROR: board-specific fdt fixup failed: %s\n", fdt_strerror(fdt_ret)); goto err; } } if (IMAGE_OF_SYSTEM_SETUP) { fdt_ret = ft_system_setup(blob, gd->bd); if (fdt_ret) { printf("ERROR: system-specific fdt fixup failed: %s\n", fdt_strerror(fdt_ret)); goto err; } } fdt_fixup_ethernet(blob); /* Delete the old LMB reservation */ lmb_free(lmb, (phys_addr_t)(u32)(uintptr_t)blob, (phys_size_t)fdt_totalsize(blob)); ret = fdt_shrink_to_minimum(blob); if (ret < 0) goto err; of_size = ret; if (*initrd_start && *initrd_end) { of_size += FDT_RAMDISK_OVERHEAD; fdt_set_totalsize(blob, of_size); } /* Create a new LMB reservation */ lmb_reserve(lmb, (ulong)blob, of_size); fdt_initrd(blob, *initrd_start, *initrd_end); if (!ft_verify_fdt(blob)) goto err; #if defined(CONFIG_SOC_KEYSTONE) if (IMAGE_OF_BOARD_SETUP) ft_board_setup_ex(blob, gd->bd); #endif return 0; err: printf(" - must RESET the board to recover.\n\n"); return ret; }
int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images) { /* First parameter is mapped to $r5 for kernel boot args */ void (*thekernel) (char *, ulong, ulong); char *commandline = getenv("bootargs"); ulong rd_data_start, rd_data_end; if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1; int ret; char *of_flat_tree = NULL; #if defined(CONFIG_OF_LIBFDT) /* did generic code already find a device tree? */ if (images->ft_len) of_flat_tree = images->ft_addr; #endif thekernel = (void (*)(char *, ulong, ulong))images->ep; /* find ramdisk */ ret = boot_get_ramdisk(argc, argv, images, IH_ARCH_MICROBLAZE, &rd_data_start, &rd_data_end); if (ret) return 1; bootstage_mark(BOOTSTAGE_ID_RUN_OS); if (!of_flat_tree && argc > 1) of_flat_tree = (char *)simple_strtoul(argv[1], NULL, 16); /* fixup the initrd now that we know where it should be */ if (images->rd_start && images->rd_end && of_flat_tree) ret = fdt_initrd(of_flat_tree, images->rd_start, images->rd_end, 1); if (ret) return 1; #ifdef DEBUG printf("## Transferring control to Linux (at address 0x%08lx) ", (ulong)thekernel); printf("ramdisk 0x%08lx, FDT 0x%08lx...\n", rd_data_start, (ulong) of_flat_tree); #endif #ifdef XILINX_USE_DCACHE flush_cache(0, XILINX_DCACHE_BYTE_SIZE); #endif /* * Linux Kernel Parameters (passing device tree): * r5: pointer to command line * r6: pointer to ramdisk * r7: pointer to the fdt, followed by the board info data */ thekernel(commandline, rd_data_start, (ulong)of_flat_tree); /* does not return */ return 1; }
void arm_cmd_start_linux(int argc, char **argv) { u64 kernel_addr, fdt_addr; u64 initrd_addr, initrd_size; int err; char cfg_str[10]; u64 meminfo[2]; if (argc != 5) { arm_puts ("start_linux: must provide <kernel_addr>, <initrd_addr>, <initrd_size> and <fdt_addr>\n"); return; } /* Parse the arguments from command line */ kernel_addr = arm_hexstr2ulonglong(argv[1]); initrd_addr = arm_hexstr2ulonglong(argv[2]); initrd_size = arm_hexstr2ulonglong(argv[3]); fdt_addr = arm_hexstr2ulonglong(argv[4]); meminfo[0] = arm_board_ram_start(); meminfo[1] = arm_board_ram_size(); /* Fillup/fixup the fdt blob with following: * - initrd start, end * - kernel cmd line * - number of cpus */ if ((err = fdt_fixup_memory_banks((void *)fdt_addr, (&meminfo[0]), (&meminfo[1]), 1))) { arm_printf("%s: fdt_fixup_memory_banks() failed: %s\n", __func__, fdt_strerror(err)); return; } sprintf(cfg_str, " mem=%dM maxcpus=%d", (int)(meminfo[1] >> 20), CONFIG_NR_CPUS); arm_strcat(linux_cmdline, cfg_str); if ((err = fdt_chosen((void *)fdt_addr, 1))) { arm_printf("%s: fdt_chosen() failed: %s\n", __func__, fdt_strerror(err)); return; } if ((err = fdt_initrd((void *)fdt_addr, initrd_addr, initrd_addr + initrd_size, 1))) { arm_printf("%s: fdt_initrd() failed: %s\n", __func__, fdt_strerror(err)); return; } /* Disable interrupts and timer */ arm_board_timer_disable(); arm_irq_disable(); arm_mmu_cleanup(); /* Jump to Linux Kernel * r0 -> dtb address */ arm_puts("Jumping into linux ...\n"); ((linux_entry_t)kernel_addr)(fdt_addr); /* We should never reach here */ while (1); return; }