/** * boot_get_kbd - allocate and initialize kernel copy of board info * @lmb: pointer to lmb handle, will be used for memory mgmt * @kbd: double pointer to board info data * * boot_get_kbd() allocates space for kernel copy of board info data below * BOOTMAPSZ + getenv_bootm_low() address and kernel board info is initialized * with the current u-boot board info data. * * returns: * 0 - success * -1 - failure */ int boot_get_kbd(struct lmb *lmb, bd_t **kbd) { *kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, getenv_bootm_mapsize() + getenv_bootm_low()); if (*kbd == NULL) return -1; **kbd = *(gd->bd); debug("## kernel board info at 0x%08lx\n", (ulong)*kbd); #if defined(DEBUG) && defined(CONFIG_CMD_BDI) do_bdinfo(NULL, 0, 0, NULL); #endif return 0; }
/** * boot_get_cmdline - allocate and initialize kernel cmdline * @lmb: pointer to lmb handle, will be used for memory mgmt * @cmd_start: pointer to a ulong variable, will hold cmdline start * @cmd_end: pointer to a ulong variable, will hold cmdline end * * boot_get_cmdline() allocates space for kernel command line below * BOOTMAPSZ + getenv_bootm_low() address. If "bootargs" U-boot environemnt * variable is present its contents is copied to allocated kernel * command line. * * returns: * 0 - success * -1 - failure */ int boot_get_cmdline(struct lmb *lmb, ulong *cmd_start, ulong *cmd_end) { char *cmdline; char *s; cmdline = (char *)(ulong)lmb_alloc_base(lmb, CONFIG_SYS_BARGSIZE, 0xf, getenv_bootm_mapsize() + getenv_bootm_low()); if (cmdline == NULL) return -1; if ((s = getenv("bootargs")) == NULL) s = ""; strcpy(cmdline, s); *cmd_start = (ulong) & cmdline[0]; *cmd_end = *cmd_start + strlen(cmdline); debug("## cmdline at 0x%08lx ... 0x%08lx\n", *cmd_start, *cmd_end); return 0; }
/** * boot_relocate_fdt - relocate flat device tree * @lmb: pointer to lmb handle, will be used for memory mgmt * @of_flat_tree: pointer to a char* variable, will hold fdt start address * @of_size: pointer to a ulong variable, will hold fdt length * * boot_relocate_fdt() allocates a region of memory within the bootmap and * relocates the of_flat_tree into that region, even if the fdt is already in * the bootmap. It also expands the size of the fdt by CONFIG_SYS_FDT_PAD * bytes. * * of_flat_tree and of_size are set to final (after relocation) values * * returns: * 0 - success * 1 - failure */ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) { void *fdt_blob = *of_flat_tree; void *of_start = NULL; char *fdt_high; ulong of_len = 0; int err; int disable_relocation = 0; /* nothing to do */ if (*of_size == 0) return 0; if (fdt_check_header(fdt_blob) != 0) { fdt_error("image is not a fdt"); goto error; } /* position on a 4K boundary before the alloc_current */ /* Pad the FDT by a specified amount */ of_len = *of_size + CONFIG_SYS_FDT_PAD; /* If fdt_high is set use it to select the relocation address */ fdt_high = getenv("fdt_high"); if (fdt_high) { void *desired_addr = (void *)simple_strtoul(fdt_high, NULL, 16); if (((ulong) desired_addr) == ~0UL) { /* All ones means use fdt in place */ of_start = fdt_blob; lmb_reserve(lmb, (ulong)of_start, of_len); disable_relocation = 1; } else if (desired_addr) { of_start = (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, (ulong)desired_addr); if (of_start == NULL) { puts("Failed using fdt_high value for Device Tree"); goto error; } } else { of_start = (void *)(ulong) lmb_alloc(lmb, of_len, 0x1000); } } else { of_start = (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, getenv_bootm_mapsize() + getenv_bootm_low()); } if (of_start == NULL) { puts("device tree - allocation error\n"); goto error; } if (disable_relocation) { /* * We assume there is space after the existing fdt to use * for padding */ fdt_set_totalsize(of_start, of_len); printf(" Using Device Tree in place at %p, end %p\n", of_start, of_start + of_len - 1); } else { debug("## device tree at %p ... %p (len=%ld [0x%lX])\n", fdt_blob, fdt_blob + *of_size - 1, of_len, of_len); printf(" Loading Device Tree to %p, end %p ... ", of_start, of_start + of_len - 1); err = fdt_open_into(fdt_blob, of_start, of_len); if (err != 0) { fdt_error("fdt move failed"); goto error; } puts("OK\n"); } *of_flat_tree = of_start; *of_size = of_len; set_working_fdt_addr((ulong)*of_flat_tree); return 0; error: return 1; }
/** * boot_ramdisk_high - relocate init ramdisk * @lmb: pointer to lmb handle, will be used for memory mgmt * @rd_data: ramdisk data start address * @rd_len: ramdisk data length * @initrd_start: pointer to a ulong variable, will hold final init ramdisk * start address (after possible relocation) * @initrd_end: pointer to a ulong variable, will hold final init ramdisk * end address (after possible relocation) * * boot_ramdisk_high() takes a relocation hint from "initrd_high" environment * variable and if requested ramdisk data is moved to a specified location. * * Initrd_start and initrd_end are set to final (after relocation) ramdisk * start/end addresses if ramdisk image start and len were provided, * otherwise set initrd_start and initrd_end set to zeros. * * returns: * 0 - success * -1 - failure */ int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, ulong *initrd_start, ulong *initrd_end) { char *s; ulong initrd_high; int initrd_copy_to_ram = 1; if ((s = getenv("initrd_high")) != NULL) { /* a value of "no" or a similar string will act like 0, * turning the "load high" feature off. This is intentional. */ initrd_high = simple_strtoul(s, NULL, 16); if (initrd_high == ~0) initrd_copy_to_ram = 0; } else { initrd_high = getenv_bootm_mapsize() + getenv_bootm_low(); } #ifdef CONFIG_LOGBUFFER /* Prevent initrd from overwriting logbuffer */ lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE); #endif debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n", initrd_high, initrd_copy_to_ram); if (rd_data) { if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ debug(" in-place initrd\n"); *initrd_start = rd_data; *initrd_end = rd_data + rd_len; lmb_reserve(lmb, rd_data, rd_len); } else { if (initrd_high) *initrd_start = (ulong)lmb_alloc_base(lmb, rd_len, 0x1000, initrd_high); else *initrd_start = (ulong)lmb_alloc(lmb, rd_len, 0x1000); if (*initrd_start == 0) { puts("ramdisk - allocation error\n"); goto error; } bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK); *initrd_end = *initrd_start + rd_len; printf(" Loading Ramdisk to %08lx, end %08lx ... ", *initrd_start, *initrd_end); memmove_wd((void *)*initrd_start, (void *)rd_data, rd_len, CHUNKSZ); #ifdef CONFIG_MP /* * Ensure the image is flushed to memory to handle * AMP boot scenarios in which we might not be * HW cache coherent */ flush_cache((unsigned long)*initrd_start, rd_len); #endif puts("OK\n"); } } else { *initrd_start = 0; *initrd_end = 0; } debug(" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n", *initrd_start, *initrd_end); return 0; error: return -1; }