Newer
Older
int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
uint8_t arch, ulong *rd_start, ulong *rd_end)
ulong rd_addr, rd_load;
ulong rd_data, rd_len;
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
const image_header_t *rd_hdr;
#ifdef CONFIG_SUPPORT_RAW_INITRD
#if IMAGE_ENABLE_FIT
const char *fit_uname_config = images->fit_uname_cfg;
const char *fit_uname_ramdisk = NULL;
ulong default_addr;
int rd_noffset;
*rd_start = 0;
*rd_end = 0;
#ifdef CONFIG_ANDROID_BOOT_IMAGE
/*
* Look for an Android boot image.
*/
buf = map_sysmem(images->os.start, 0);
if (buf && genimg_get_format(buf) == IMAGE_FORMAT_ANDROID)
select = argv[0];
#endif
/*
* Look for a '-' which indicates to ignore the
* ramdisk argument
*/
rd_len = rd_data = 0;
} else if (select || genimg_has_config(images)) {
#if IMAGE_ENABLE_FIT
Marian Balakowicz
committed
/*
* If the init ramdisk comes from the FIT image and
* the FIT image address is omitted in the command
* line argument, try to use os FIT image address or
* default load address.
*/
if (images->fit_uname_os)
default_addr = (ulong)images->fit_hdr_os;
else
default_addr = load_addr;
if (fit_parse_conf(select, default_addr,
&rd_addr, &fit_uname_config)) {
debug("* ramdisk: config '%s' from image at "
"0x%08lx\n",
Marian Balakowicz
committed
fit_uname_config, rd_addr);
} else if (fit_parse_subimage(select, default_addr,
Marian Balakowicz
committed
&rd_addr, &fit_uname_ramdisk)) {
debug("* ramdisk: subimage '%s' from image at "
"0x%08lx\n",
Marian Balakowicz
committed
fit_uname_ramdisk, rd_addr);
} else
Marian Balakowicz
committed
{
debug("* ramdisk: cmdline image address = "
"0x%08lx\n",
Marian Balakowicz
committed
rd_addr);
}
#if IMAGE_ENABLE_FIT
Marian Balakowicz
committed
} else {
/* use FIT configuration provided in first bootm
* command argument. If the property is not defined,
* quit silently.
Marian Balakowicz
committed
*/
rd_addr = map_to_sysmem(images->fit_hdr_os);
rd_noffset = fit_get_node_from_config(images,
FIT_RAMDISK_PROP, rd_addr);
if (rd_noffset == -ENOENT)
else if (rd_noffset < 0)
return 1;
Marian Balakowicz
committed
#endif
/* copy from dataflash if needed */
/*
* Check if there is an initrd image at the
* address provided in the second bootm argument
* check image type, for FIT images get FIT node.
*/
buf = map_sysmem(rd_addr, 0);
switch (genimg_get_format(buf)) {
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
case IMAGE_FORMAT_LEGACY:
printf("## Loading init Ramdisk from Legacy "
"Image at %08lx ...\n", rd_addr);
bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK);
rd_hdr = image_get_ramdisk(rd_addr, arch,
images->verify);
if (rd_hdr == NULL)
return 1;
rd_data = image_get_data(rd_hdr);
rd_len = image_get_data_size(rd_hdr);
rd_load = image_get_load(rd_hdr);
#if IMAGE_ENABLE_FIT
case IMAGE_FORMAT_FIT:
rd_noffset = fit_image_load(images,
&fit_uname_config, arch,
IH_TYPE_RAMDISK,
BOOTSTAGE_ID_FIT_RD_START,
FIT_LOAD_OPTIONAL_NON_ZERO,
&rd_data, &rd_len);
images->fit_hdr_rd = map_sysmem(rd_addr, 0);
images->fit_uname_rd = fit_uname_ramdisk;
Marian Balakowicz
committed
images->fit_noffset_rd = rd_noffset;
break;
#endif
#ifdef CONFIG_ANDROID_BOOT_IMAGE
case IMAGE_FORMAT_ANDROID:
android_image_get_ramdisk((void *)images->os.start,
&rd_data, &rd_len);
break;
#endif
default:
end = NULL;
if (select)
end = strchr(select, ':');
if (end) {
rd_len = simple_strtoul(++end, NULL, 16);
rd_data = rd_addr;
} else
#endif
{
puts("Wrong Ramdisk Image Format\n");
rd_data = rd_len = rd_load = 0;
return 1;
}
}
} else if (images->legacy_hdr_valid &&
image_check_type(&images->legacy_hdr_os_copy,
IH_TYPE_MULTI)) {
* Now check if we have a legacy mult-component image,
* get second entry data start address and len.
bootstage_mark(BOOTSTAGE_ID_RAMDISK);
printf("## Loading init Ramdisk from multi component "
"Legacy Image at %08lx ...\n",
(ulong)images->legacy_hdr_os);
image_multi_getimg(images->legacy_hdr_os, 1, &rd_data, &rd_len);
/*
* no initrd image
*/
bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK);
rd_len = rd_data = 0;
}
if (!rd_data) {
} else {
*rd_start = rd_data;
*rd_end = rd_data + rd_len;
}
debug(" ramdisk start = 0x%08lx, ramdisk end = 0x%08lx\n",
*rd_start, *rd_end);
return 0;
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
* 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.
*
* 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 */
*initrd_start = rd_data;
*initrd_end = rd_data + rd_len;
lmb_reserve(lmb, rd_data, rd_len);
*initrd_start = (ulong)lmb_alloc_base(lmb,
rd_len, 0x1000, initrd_high);
*initrd_start = (ulong)lmb_alloc(lmb, rd_len,
0x1000);
bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);
*initrd_end = *initrd_start + rd_len;
printf(" Loading Ramdisk to %08lx, end %08lx ... ",
*initrd_start, *initrd_end);
(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
}
} else {
*initrd_start = 0;
*initrd_end = 0;
}
debug(" ramdisk load start = 0x%08lx, ramdisk load end = 0x%08lx\n",
*initrd_start, *initrd_end);
#endif /* CONFIG_SYS_BOOT_RAMDISK_HIGH */
int boot_get_setup(bootm_headers_t *images, uint8_t arch,
ulong *setup_start, ulong *setup_len)
{
#if IMAGE_ENABLE_FIT
return boot_get_setup_fit(images, arch, setup_start, setup_len);
#else
return -ENOENT;
#endif
}
#if IMAGE_ENABLE_FIT
#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_XILINX)
int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
uint8_t arch, const ulong *ld_start, ulong * const ld_len)
{
ulong tmp_img_addr, img_data, img_len;
void *buf;
int conf_noffset;
int fit_img_result;
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
int err;
int devnum = 0; /* TODO support multi fpga platforms */
const fpga_desc * const desc = fpga_get_desc(devnum);
xilinx_desc *desc_xilinx = desc->devdesc;
/* Check to see if the images struct has a FIT configuration */
if (!genimg_has_config(images)) {
debug("## FIT configuration was not specified\n");
return 0;
}
/*
* Obtain the os FIT header from the images struct
* copy from dataflash if needed
*/
tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
tmp_img_addr = genimg_get_image(tmp_img_addr);
buf = map_sysmem(tmp_img_addr, 0);
/*
* Check image type. For FIT images get FIT node
* and attempt to locate a generic binary.
*/
switch (genimg_get_format(buf)) {
case IMAGE_FORMAT_FIT:
conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0,
NULL);
if (!uname) {
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
debug("## FPGA image is not specified\n");
return 0;
}
fit_img_result = fit_image_load(images,
tmp_img_addr,
(const char **)&uname,
&(images->fit_uname_cfg),
arch,
IH_TYPE_FPGA,
BOOTSTAGE_ID_FPGA_INIT,
FIT_LOAD_OPTIONAL_NON_ZERO,
&img_data, &img_len);
debug("FPGA image (%s) loaded to 0x%lx/size 0x%lx\n",
uname, img_data, img_len);
if (fit_img_result < 0) {
/* Something went wrong! */
return fit_img_result;
}
if (img_len >= desc_xilinx->size) {
name = "full";
err = fpga_loadbitstream(devnum, (char *)img_data,
img_len, BIT_FULL);
if (err)
err = fpga_load(devnum, (const void *)img_data,
img_len, BIT_FULL);
} else {
name = "partial";
err = fpga_loadbitstream(devnum, (char *)img_data,
img_len, BIT_PARTIAL);
if (err)
err = fpga_load(devnum, (const void *)img_data,
img_len, BIT_PARTIAL);
}
printf(" Programming %s bitstream... ", name);
if (err)
printf("failed\n");
else
printf("OK\n");
break;
default:
printf("The given image format is not supported (corrupt?)\n");
return 1;
}
return 0;
}
#endif
static void fit_loadable_process(uint8_t img_type,
ulong img_data,
ulong img_len)
{
int i;
const unsigned int count =
ll_entry_count(struct fit_loadable_tbl, fit_loadable);
struct fit_loadable_tbl *fit_loadable_handler =
ll_entry_start(struct fit_loadable_tbl, fit_loadable);
/* For each loadable handler */
for (i = 0; i < count; i++, fit_loadable_handler++)
/* matching this type */
if (fit_loadable_handler->type == img_type)
/* call that handler with this image data */
fit_loadable_handler->handler(img_data, img_len);
}
int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
uint8_t arch, const ulong *ld_start, ulong * const ld_len)
{
/*
* These variables are used to hold the current image location
* in system memory.
*/
ulong tmp_img_addr;
/*
* These two variables are requirements for fit_image_load, but
* their values are not used
*/
ulong img_data, img_len;
void *buf;
int loadables_index;
int conf_noffset;
int fit_img_result;
uint8_t img_type;
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
/* Check to see if the images struct has a FIT configuration */
if (!genimg_has_config(images)) {
debug("## FIT configuration was not specified\n");
return 0;
}
/*
* Obtain the os FIT header from the images struct
* copy from dataflash if needed
*/
tmp_img_addr = map_to_sysmem(images->fit_hdr_os);
tmp_img_addr = genimg_get_image(tmp_img_addr);
buf = map_sysmem(tmp_img_addr, 0);
/*
* Check image type. For FIT images get FIT node
* and attempt to locate a generic binary.
*/
switch (genimg_get_format(buf)) {
case IMAGE_FORMAT_FIT:
conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
for (loadables_index = 0;
uname = fdt_stringlist_get(buf, conf_noffset,
FIT_LOADABLE_PROP, loadables_index,
NULL), uname;
loadables_index++)
{
fit_img_result = fit_image_load(images,
tmp_img_addr,
&(images->fit_uname_cfg), arch,
IH_TYPE_LOADABLE,
BOOTSTAGE_ID_FIT_LOADABLE_START,
FIT_LOAD_OPTIONAL_NON_ZERO,
&img_data, &img_len);
if (fit_img_result < 0) {
/* Something went wrong! */
return fit_img_result;
}
fit_img_result = fit_image_get_node(buf, uname);
if (fit_img_result < 0) {
/* Something went wrong! */
return fit_img_result;
}
fit_img_result = fit_image_get_type(buf,
fit_img_result,
&img_type);
if (fit_img_result < 0) {
/* Something went wrong! */
return fit_img_result;
}
fit_loadable_process(img_type, img_data, img_len);
}
break;
default:
printf("The given image format is not supported (corrupt?)\n");
return 1;
}
return 0;
}
#endif
#ifdef CONFIG_SYS_BOOT_GET_CMDLINE
* 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);
#endif /* CONFIG_SYS_BOOT_GET_CMDLINE */
#ifdef CONFIG_SYS_BOOT_GET_KBD
* 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
#endif /* CONFIG_SYS_BOOT_GET_KBD */
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
#ifdef CONFIG_LMB
int image_setup_linux(bootm_headers_t *images)
{
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;
ulong rd_len;
int ret;
if (IMAGE_ENABLE_OF_LIBFDT)
boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
if (IMAGE_BOOT_GET_CMDLINE) {
ret = boot_get_cmdline(lmb, &images->cmdline_start,
&images->cmdline_end);
if (ret) {
puts("ERROR with allocation of cmdline\n");
return ret;
}
}
if (IMAGE_ENABLE_RAMDISK_HIGH) {
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;
}
if (IMAGE_ENABLE_OF_LIBFDT) {
ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
if (ret)
return ret;
}
if (IMAGE_ENABLE_OF_LIBFDT && of_size) {
ret = image_setup_libfdt(images, *of_flat_tree, of_size, lmb);
if (ret)
return ret;
}
return 0;
}
#endif /* CONFIG_LMB */