diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 9 | ||||
-rw-r--r-- | common/Makefile | 4 | ||||
-rw-r--r-- | common/board_f.c | 2 | ||||
-rw-r--r-- | common/bootm.c | 10 | ||||
-rw-r--r-- | common/bootm_os.c | 5 | ||||
-rw-r--r-- | common/env_common.c | 1 | ||||
-rw-r--r-- | common/env_mmc.c | 8 | ||||
-rw-r--r-- | common/env_nand.c | 24 | ||||
-rw-r--r-- | common/fb_nand.c | 32 | ||||
-rw-r--r-- | common/fdt_support.c | 120 | ||||
-rw-r--r-- | common/image-fit.c | 11 | ||||
-rw-r--r-- | common/image.c | 94 | ||||
-rw-r--r-- | common/init/board_init.c | 5 | ||||
-rw-r--r-- | common/main.c | 6 | ||||
-rw-r--r-- | common/scsi.c | 2 | ||||
-rw-r--r-- | common/spl/spl.c | 62 | ||||
-rw-r--r-- | common/spl/spl_fat.c | 36 | ||||
-rw-r--r-- | common/spl/spl_fit.c | 80 | ||||
-rw-r--r-- | common/spl/spl_mmc.c | 10 | ||||
-rw-r--r-- | common/spl/spl_nand.c | 37 | ||||
-rw-r--r-- | common/spl/spl_ymodem.c | 98 | ||||
-rw-r--r-- | common/splash_source.c | 4 | ||||
-rw-r--r-- | common/usb.c | 2 |
23 files changed, 551 insertions, 111 deletions
diff --git a/common/Kconfig b/common/Kconfig index 067545d8a3..4d17b101a1 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -97,6 +97,15 @@ config BOOTSTAGE_STASH_SIZE endmenu +config BOOTDELAY + int "delay in seconds before automatically booting" + default 0 + help + Delay before automatically running bootcmd; + set to -1 to disable autoboot. + set to -2 to autoboot with no delay and not check for abort + (even when CONFIG_ZERO_BOOTDELAY_CHECK is defined). + config CONSOLE_RECORD bool "Console recording" help diff --git a/common/Makefile b/common/Makefile index 0562d5cea4..1557a044de 100644 --- a/common/Makefile +++ b/common/Makefile @@ -26,8 +26,8 @@ obj-y += bootretry.o endif # boards -obj-$(CONFIG_SYS_GENERIC_BOARD) += board_f.o -obj-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o +obj-y += board_f.o +obj-y += board_r.o obj-$(CONFIG_DISPLAY_BOARDINFO) += board_info.o obj-$(CONFIG_DISPLAY_BOARDINFO_LATE) += board_info.o diff --git a/common/board_f.c b/common/board_f.c index 109025a68d..d405b5b407 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -274,7 +274,7 @@ static int setup_mon_len(void) gd->mon_len = CONFIG_SYS_MONITOR_LEN; #elif defined(CONFIG_NDS32) gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start); -#else +#elif defined(CONFIG_SYS_MONITOR_BASE) /* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */ gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE; #endif diff --git a/common/bootm.c b/common/bootm.c index c965326db4..49414142dc 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -246,6 +246,16 @@ int bootm_find_images(int flag, int argc, char * const argv[]) #endif #if IMAGE_ENABLE_FIT +#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_XILINX) + /* find bitstreams */ + ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT, + NULL, NULL); + if (ret) { + printf("FPGA image is corrupted or invalid\n"); + return 1; + } +#endif + /* find all of the loadables */ ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT, NULL, NULL); diff --git a/common/bootm_os.c b/common/bootm_os.c index cb83f4a9bd..9ec84bd0db 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -484,9 +484,8 @@ int boot_selected_os(int argc, char * const argv[], int state, state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */ return 0; bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED); -#ifdef DEBUG - puts("\n## Control returned to monitor - resetting...\n"); -#endif + debug("\n## Control returned to monitor - resetting...\n"); + return BOOTM_ERR_RESET; } diff --git a/common/env_common.c b/common/env_common.c index af59c72e1f..13db7dc3f7 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -123,6 +123,7 @@ void set_default_env(const char *s) error("Environment import failed: errno = %d\n", errno); gd->flags |= GD_FLG_ENV_READY; + gd->flags |= GD_FLG_ENV_DEFAULT; } diff --git a/common/env_mmc.c b/common/env_mmc.c index c7fef188cd..16f6a17514 100644 --- a/common/env_mmc.c +++ b/common/env_mmc.c @@ -128,12 +128,12 @@ static inline int write_env(struct mmc *mmc, unsigned long size, unsigned long offset, const void *buffer) { uint blk_start, blk_cnt, n; + struct blk_desc *desc = mmc_get_blk_desc(mmc); blk_start = ALIGN(offset, mmc->write_bl_len) / mmc->write_bl_len; blk_cnt = ALIGN(size, mmc->write_bl_len) / mmc->write_bl_len; - n = mmc->block_dev.block_write(&mmc->block_dev, blk_start, - blk_cnt, (u_char *)buffer); + n = blk_dwrite(desc, blk_start, blk_cnt, (u_char *)buffer); return (n == blk_cnt) ? 0 : -1; } @@ -197,12 +197,12 @@ static inline int read_env(struct mmc *mmc, unsigned long size, unsigned long offset, const void *buffer) { uint blk_start, blk_cnt, n; + struct blk_desc *desc = mmc_get_blk_desc(mmc); blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; - n = mmc->block_dev.block_read(&mmc->block_dev, blk_start, blk_cnt, - (uchar *)buffer); + n = blk_dread(desc, blk_start, blk_cnt, (uchar *)buffer); return (n == blk_cnt) ? 0 : -1; } diff --git a/common/env_nand.c b/common/env_nand.c index b32eeac9d7..fc99a5e3fc 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -132,15 +132,15 @@ static int writeenv(size_t offset, u_char *buf) size_t blocksize, len; u_char *char_ptr; - blocksize = nand_info[0].erasesize; + blocksize = nand_info[0]->erasesize; len = min(blocksize, (size_t)CONFIG_ENV_SIZE); while (amount_saved < CONFIG_ENV_SIZE && offset < end) { - if (nand_block_isbad(&nand_info[0], offset)) { + if (nand_block_isbad(nand_info[0], offset)) { offset += blocksize; } else { char_ptr = &buf[amount_saved]; - if (nand_write(&nand_info[0], offset, &len, char_ptr)) + if (nand_write(nand_info[0], offset, &len, char_ptr)) return 1; offset += blocksize; @@ -164,7 +164,7 @@ static int erase_and_write_env(const struct env_location *location, int ret = 0; printf("Erasing %s...\n", location->name); - if (nand_erase_opts(&nand_info[0], &location->erase_opts)) + if (nand_erase_opts(nand_info[0], &location->erase_opts)) return 1; printf("Writing to %s... ", location->name); @@ -247,20 +247,20 @@ static int readenv(size_t offset, u_char *buf) size_t blocksize, len; u_char *char_ptr; - blocksize = nand_info[0].erasesize; + blocksize = nand_info[0]->erasesize; if (!blocksize) return 1; len = min(blocksize, (size_t)CONFIG_ENV_SIZE); while (amount_loaded < CONFIG_ENV_SIZE && offset < end) { - if (nand_block_isbad(&nand_info[0], offset)) { + if (nand_block_isbad(nand_info[0], offset)) { offset += blocksize; } else { char_ptr = &buf[amount_loaded]; - if (nand_read_skip_bad(&nand_info[0], offset, + if (nand_read_skip_bad(nand_info[0], offset, &len, NULL, - nand_info[0].size, char_ptr)) + nand_info[0]->size, char_ptr)) return 1; offset += blocksize; @@ -276,7 +276,7 @@ static int readenv(size_t offset, u_char *buf) #endif /* #if defined(CONFIG_SPL_BUILD) */ #ifdef CONFIG_ENV_OFFSET_OOB -int get_nand_env_oob(nand_info_t *nand, unsigned long *result) +int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result) { struct mtd_oob_ops ops; uint32_t oob_buf[ENV_OFFSET_SIZE / sizeof(uint32_t)]; @@ -288,14 +288,14 @@ int get_nand_env_oob(nand_info_t *nand, unsigned long *result) ops.ooblen = ENV_OFFSET_SIZE; ops.oobbuf = (void *)oob_buf; - ret = nand->read_oob(nand, ENV_OFFSET_SIZE, &ops); + ret = mtd->read_oob(mtd, ENV_OFFSET_SIZE, &ops); if (ret) { printf("error reading OOB block 0\n"); return ret; } if (oob_buf[0] == ENV_OOB_MARKER) { - *result = oob_buf[1] * nand->erasesize; + *result = oob_buf[1] * mtd->erasesize; } else if (oob_buf[0] == ENV_OOB_MARKER_OLD) { *result = oob_buf[1]; } else { @@ -387,7 +387,7 @@ void env_relocate_spec(void) ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); #if defined(CONFIG_ENV_OFFSET_OOB) - ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset); + ret = get_nand_env_oob(nand_info[0], &nand_env_oob_offset); /* * If unable to read environment offset from NAND OOB then fall through * to the normal environment reading code below diff --git a/common/fb_nand.c b/common/fb_nand.c index 9ca8602a73..e55ea3872f 100644 --- a/common/fb_nand.c +++ b/common/fb_nand.c @@ -19,7 +19,7 @@ static char *response_str; struct fb_nand_sparse { - nand_info_t *nand; + struct mtd_info *nand; struct part_info *part; }; @@ -34,7 +34,7 @@ __weak int board_fastboot_write_partition_setup(char *name) } static int fb_nand_lookup(const char *partname, char *response, - nand_info_t **nand, + struct mtd_info **nand, struct part_info **part) { struct mtd_device *dev; @@ -62,12 +62,12 @@ static int fb_nand_lookup(const char *partname, char *response, return -EINVAL; } - *nand = &nand_info[dev->id->num]; + *mtd = nand_info[dev->id->num]; return 0; } -static int _fb_nand_erase(nand_info_t *nand, struct part_info *part) +static int _fb_nand_erase(struct mtd_info *mtd, struct part_info *part) { nand_erase_options_t opts; int ret; @@ -80,7 +80,7 @@ static int _fb_nand_erase(nand_info_t *nand, struct part_info *part) printf("Erasing blocks 0x%llx to 0x%llx\n", part->offset, part->offset + part->size); - ret = nand_erase_opts(nand, &opts); + ret = nand_erase_opts(mtd, &opts); if (ret) return ret; @@ -90,7 +90,7 @@ static int _fb_nand_erase(nand_info_t *nand, struct part_info *part) return 0; } -static int _fb_nand_write(nand_info_t *nand, struct part_info *part, +static int _fb_nand_write(struct mtd_info *mtd, struct part_info *part, void *buffer, unsigned int offset, unsigned int length, size_t *written) { @@ -100,7 +100,7 @@ static int _fb_nand_write(nand_info_t *nand, struct part_info *part, flags |= WITH_DROP_FFS; #endif - return nand_write_skip_bad(nand, offset, &length, written, + return nand_write_skip_bad(mtd, offset, &length, written, part->size - (offset - part->offset), buffer, flags); } @@ -131,13 +131,13 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id, char *response) { struct part_info *part; - nand_info_t *nand = NULL; + struct mtd_info *mtd = NULL; int ret; /* initialize the response buffer */ response_str = response; - ret = fb_nand_lookup(partname, response, &nand, &part); + ret = fb_nand_lookup(partname, response, &mtd, &part); if (ret) { error("invalid NAND device"); fastboot_fail(response_str, "invalid NAND device"); @@ -152,10 +152,10 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id, struct fb_nand_sparse sparse_priv; sparse_storage_t sparse; - sparse_priv.nand = nand; + sparse_priv.nand = mtd; sparse_priv.part = part; - sparse.block_sz = nand->writesize; + sparse.block_sz = mtd->writesize; sparse.start = part->offset / sparse.block_sz; sparse.size = part->size / sparse.block_sz; sparse.name = part->name; @@ -167,7 +167,7 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id, printf("Flashing raw image at offset 0x%llx\n", part->offset); - ret = _fb_nand_write(nand, part, download_buffer, part->offset, + ret = _fb_nand_write(mtd, part, download_buffer, part->offset, download_bytes, NULL); printf("........ wrote %u bytes to '%s'\n", @@ -185,13 +185,13 @@ void fb_nand_flash_write(const char *partname, unsigned int session_id, void fb_nand_erase(const char *partname, char *response) { struct part_info *part; - nand_info_t *nand = NULL; + struct mtd_info *mtd = NULL; int ret; /* initialize the response buffer */ response_str = response; - ret = fb_nand_lookup(partname, response, &nand, &part); + ret = fb_nand_lookup(partname, response, &mtd, &part); if (ret) { error("invalid NAND device"); fastboot_fail(response_str, "invalid NAND device"); @@ -202,9 +202,9 @@ void fb_nand_erase(const char *partname, char *response) if (ret) return; - ret = _fb_nand_erase(nand, part); + ret = _fb_nand_erase(mtd, part); if (ret) { - error("failed erasing from device %s", nand->name); + error("failed erasing from device %s", mtd->name); fastboot_fail(response_str, "failed erasing from device"); return; } diff --git a/common/fdt_support.c b/common/fdt_support.c index 42e5d8a1d2..5d8eb12f10 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -964,10 +964,40 @@ static void of_dump_addr(const char *s, const fdt32_t *addr, int na) static void of_dump_addr(const char *s, const fdt32_t *addr, int na) { } #endif -/* Callbacks for bus specific translators */ +/** + * struct of_bus - Callbacks for bus specific translators + * @name: A string used to identify this bus in debug output. + * @addresses: The name of the DT property from which addresses are + * to be read, typically "reg". + * @match: Return non-zero if the node whose parent is at + * parentoffset in the FDT blob corresponds to a bus + * of this type, otherwise return zero. If NULL a match + * is assumed. + * @count_cells:Count how many cells (be32 values) a node whose parent + * is at parentoffset in the FDT blob will require to + * represent its address (written to *addrc) & size + * (written to *sizec). + * @map: Map the address addr from the address space of this + * bus to that of its parent, making use of the ranges + * read from DT to an array at range. na and ns are the + * number of cells (be32 values) used to hold and address + * or size, respectively, for this bus. pna is the number + * of cells used to hold an address for the parent bus. + * Returns the address in the address space of the parent + * bus. + * @translate: Update the value of the address cells at addr within an + * FDT by adding offset to it. na specifies the number of + * cells used to hold the address being translated. Returns + * zero on success, non-zero on error. + * + * Each bus type will include a struct of_bus in the of_busses array, + * providing implementations of some or all of the functions used to + * match the bus & handle address translation for its children. + */ struct of_bus { const char *name; const char *addresses; + int (*match)(void *blob, int parentoffset); void (*count_cells)(void *blob, int parentoffset, int *addrc, int *sizec); u64 (*map)(fdt32_t *addr, const fdt32_t *range, @@ -1022,8 +1052,70 @@ static int of_bus_default_translate(fdt32_t *addr, u64 offset, int na) return 0; } +#ifdef CONFIG_OF_ISA_BUS + +/* ISA bus translator */ +static int of_bus_isa_match(void *blob, int parentoffset) +{ + const char *name; + + name = fdt_get_name(blob, parentoffset, NULL); + if (!name) + return 0; + + return !strcmp(name, "isa"); +} + +static void of_bus_isa_count_cells(void *blob, int parentoffset, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 2; + if (sizec) + *sizec = 1; +} + +static u64 of_bus_isa_map(fdt32_t *addr, const fdt32_t *range, + int na, int ns, int pna) +{ + u64 cp, s, da; + + /* Check address type match */ + if ((addr[0] ^ range[0]) & cpu_to_be32(1)) + return OF_BAD_ADDR; + + cp = of_read_number(range + 1, na - 1); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr + 1, na - 1); + + debug("OF: ISA map, cp=%" PRIu64 ", s=%" PRIu64 + ", da=%" PRIu64 "\n", cp, s, da); + + if (da < cp || da >= (cp + s)) + return OF_BAD_ADDR; + return da - cp; +} + +static int of_bus_isa_translate(fdt32_t *addr, u64 offset, int na) +{ + return of_bus_default_translate(addr + 1, offset, na - 1); +} + +#endif /* CONFIG_OF_ISA_BUS */ + /* Array of bus specific translators */ static struct of_bus of_busses[] = { +#ifdef CONFIG_OF_ISA_BUS + /* ISA */ + { + .name = "isa", + .addresses = "reg", + .match = of_bus_isa_match, + .count_cells = of_bus_isa_count_cells, + .map = of_bus_isa_map, + .translate = of_bus_isa_translate, + }, +#endif /* CONFIG_OF_ISA_BUS */ /* Default */ { .name = "default", @@ -1034,6 +1126,28 @@ static struct of_bus of_busses[] = { }, }; +static struct of_bus *of_match_bus(void *blob, int parentoffset) +{ + struct of_bus *bus; + + if (ARRAY_SIZE(of_busses) == 1) + return of_busses; + + for (bus = of_busses; bus; bus++) { + if (!bus->match || bus->match(blob, parentoffset)) + return bus; + } + + /* + * We should always have matched the default bus at least, since + * it has a NULL match field. If we didn't then it somehow isn't + * in the of_busses array or something equally catastrophic has + * gone wrong. + */ + assert(0); + return NULL; +} + static int of_translate_one(void * blob, int parent, struct of_bus *bus, struct of_bus *pbus, fdt32_t *addr, int na, int ns, int pna, const char *rprop) @@ -1113,7 +1227,7 @@ static u64 __of_translate_address(void *blob, int node_offset, const fdt32_t *in parent = fdt_parent_offset(blob, node_offset); if (parent < 0) goto bail; - bus = &of_busses[0]; + bus = of_match_bus(blob, parent); /* Cound address cells & copy address locally */ bus->count_cells(blob, parent, &na, &ns); @@ -1142,7 +1256,7 @@ static u64 __of_translate_address(void *blob, int node_offset, const fdt32_t *in } /* Get new parent bus and counts */ - pbus = &of_busses[0]; + pbus = of_match_bus(blob, parent); pbus->count_cells(blob, parent, &pna, &pns); if (!OF_CHECK_COUNTS(pna, pns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__, diff --git a/common/image-fit.c b/common/image-fit.c index c86b7c6b11..98739572a1 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -422,7 +422,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { + (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK) || + (type == IH_TYPE_FPGA)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) @@ -1483,6 +1484,10 @@ void fit_conf_print(const void *fit, int noffset, const char *p) if (uname) printf("%s FDT: %s\n", p, uname); + uname = (char *)fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL); + if (uname) + printf("%s FPGA: %s\n", p, uname); + /* Print out all of the specified loadables */ for (loadables_index = 0; fdt_get_string_index(fit, noffset, @@ -1567,6 +1572,8 @@ static const char *fit_get_image_type_property(int type) return FIT_SETUP_PROP; case IH_TYPE_LOADABLE: return FIT_LOADABLE_PROP; + case IH_TYPE_FPGA: + return FIT_FPGA_PROP; } return "unknown"; @@ -1681,7 +1688,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr, fit_image_check_type(fit, noffset, IH_TYPE_KERNEL_NOLOAD)); - os_ok = image_type == IH_TYPE_FLATDT || + os_ok = image_type == IH_TYPE_FLATDT || IH_TYPE_FPGA || fit_image_check_os(fit, noffset, IH_OS_LINUX) || fit_image_check_os(fit, noffset, IH_OS_OPENRTOS); diff --git a/common/image.c b/common/image.c index 26d6c9a592..0be09e5c63 100644 --- a/common/image.c +++ b/common/image.c @@ -32,6 +32,8 @@ #if IMAGE_ENABLE_FIT || IMAGE_ENABLE_OF_LIBFDT #include <libfdt.h> #include <fdt_support.h> +#include <fpga.h> +#include <xilinx.h> #endif #include <u-boot/md5.h> @@ -159,6 +161,8 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_RKSD, "rksd", "Rockchip SD Boot Image" }, { IH_TYPE_RKSPI, "rkspi", "Rockchip SPI Boot Image" }, { IH_TYPE_ZYNQIMAGE, "zynqimage", "Xilinx Zynq Boot Image" }, + { IH_TYPE_ZYNQMPIMAGE, "zynqmpimage", "Xilinx ZynqMP Boot Image" }, + { IH_TYPE_FPGA, "fpga", "FPGA Image" }, { -1, "", "", }, }; @@ -1210,6 +1214,96 @@ int boot_get_setup(bootm_headers_t *images, uint8_t arch, } #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; + char *uname, *name; + 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); + + err = fdt_get_string_index(buf, conf_noffset, FIT_FPGA_PROP, 0, + (const char **)&uname); + if (err < 0) { + 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 + int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images, uint8_t arch, const ulong *ld_start, ulong * const ld_len) { diff --git a/common/init/board_init.c b/common/init/board_init.c index d17bb298d7..ef01a9aeaa 100644 --- a/common/init/board_init.c +++ b/common/init/board_init.c @@ -146,3 +146,8 @@ void board_init_f_init_reserve(ulong base) base += CONFIG_SYS_MALLOC_F_LEN; #endif } + +/* + * Board-specific Platform code can reimplement show_boot_progress () if needed + */ +__weak void show_boot_progress(int val) {} diff --git a/common/main.c b/common/main.c index 42bbb50733..2116a9e0a2 100644 --- a/common/main.c +++ b/common/main.c @@ -47,12 +47,6 @@ void main_loop(void) bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); -#ifndef CONFIG_SYS_GENERIC_BOARD - puts("Warning: Your board does not use generic board. Please read\n"); - puts("doc/README.generic-board and take action. Boards not\n"); - puts("upgraded by the late 2014 may break or be removed.\n"); -#endif - #ifdef CONFIG_VERSION_VARIABLE setenv("ver", version_string); /* set version variable */ #endif /* CONFIG_VERSION_VARIABLE */ diff --git a/common/scsi.c b/common/scsi.c index 8ac28dd416..dbbf4043b2 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -584,7 +584,7 @@ U_BOOT_DRIVER(scsi_blk) = { }; #else U_BOOT_LEGACY_BLK(scsi) = { - .if_typename = "sata", + .if_typename = "scsi", .if_type = IF_TYPE_SCSI, .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE, .desc = scsi_dev_desc, diff --git a/common/spl/spl.c b/common/spl/spl.c index 93f9bd13fc..840910a684 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -36,6 +36,11 @@ struct spl_image_info spl_image; static bd_t bdata __attribute__ ((section(".data"))); /* + * Board-specific Platform code can reimplement show_boot_progress () if needed + */ +__weak void show_boot_progress(int val) {} + +/* * Default function to determine if u-boot or the OS should * be started. This implementation always returns 1. * @@ -64,6 +69,11 @@ __weak void spl_board_prepare_for_linux(void) /* Nothing to do! */ } +__weak void spl_board_prepare_for_boot(void) +{ + /* Nothing to do! */ +} + void spl_set_header_raw_uboot(void) { spl_image.size = CONFIG_SYS_MONITOR_LEN; @@ -135,20 +145,47 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) image_entry(); } +#ifndef CONFIG_SPL_LOAD_FIT_ADDRESS +# define CONFIG_SPL_LOAD_FIT_ADDRESS 0 +#endif + #ifdef CONFIG_SPL_RAM_DEVICE +static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + debug("%s: sector %lx, count %lx, buf %lx\n", + __func__, sector, count, (ulong)buf); + memcpy(buf, (void *)(CONFIG_SPL_LOAD_FIT_ADDRESS + sector), count); + return count; +} + static int spl_ram_load_image(void) { - const struct image_header *header; + struct image_header *header; - /* - * Get the header. It will point to an address defined by handoff - * which will tell where the image located inside the flash. For - * now, it will temporary fixed to address pointed by U-Boot. - */ - header = (struct image_header *) - (CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); + header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS; - spl_parse_image_header(header); + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.bl_len = 1; + load.read = spl_ram_load_read; + spl_load_simple_fit(&load, 0, header); + } else { + debug("Legacy image\n"); + /* + * Get the header. It will point to an address defined by + * handoff which will tell where the image located inside + * the flash. For now, it will temporary fixed to address + * pointed by U-Boot. + */ + header = (struct image_header *) + (CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); + + spl_parse_image_header(header); + } return 0; } @@ -160,6 +197,9 @@ int spl_init(void) debug("spl_init()\n"); #if defined(CONFIG_SYS_MALLOC_F_LEN) +#ifdef CONFIG_MALLOC_F_ADDR + gd->malloc_base = CONFIG_MALLOC_F_ADDR; +#endif gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN; gd->malloc_ptr = 0; #endif @@ -404,6 +444,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) #endif debug("loaded - jumping to U-Boot..."); + spl_board_prepare_for_boot(); jump_to_image_no_args(&spl_image); } @@ -453,9 +494,6 @@ ulong spl_relocate_stack_gd(void) #ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) { - if (!(gd->flags & GD_FLG_SPL_INIT)) - panic_str("spl_init must be called before heap reloc"); - ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; gd->malloc_base = ptr; gd->malloc_limit = CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN; diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 5b0d96925e..db676186d3 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -15,6 +15,7 @@ #include <fat.h> #include <errno.h> #include <image.h> +#include <libfdt.h> static int fat_registered; @@ -39,6 +40,20 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition) return err; } +static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, + ulong size, void *buf) +{ + loff_t actread; + int ret; + char *filename = (char *)load->filename; + + ret = fat_read_file(filename, buf, file_offset, size, &actread); + if (ret) + return ret; + + return actread; +} + int spl_load_image_fat(struct blk_desc *block_dev, int partition, const char *filename) @@ -57,11 +72,24 @@ int spl_load_image_fat(struct blk_desc *block_dev, if (err <= 0) goto end; - err = spl_parse_image_header(header); - if (err) - goto end; + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT\n"); + load.read = spl_fit_read; + load.bl_len = 1; + load.filename = (void *)filename; + load.priv = NULL; - err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0); + return spl_load_simple_fit(&load, 0, header); + } else { + err = spl_parse_image_header(header); + if (err) + goto end; + + err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0); + } end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 26842ba285..987470896c 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -67,9 +67,7 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp) *fdt_offsetp = fdt_getprop_u32(fdt, fdt_node, "data-offset"); len = fdt_getprop_u32(fdt, fdt_node, "data-size"); -#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - printf("FIT: Selected '%s'\n", name); -#endif + debug("FIT: Selected '%s'\n", name); return len; } @@ -79,7 +77,7 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp) for (node = fdt_first_subnode(fdt, conf); node >= 0; node = fdt_next_subnode(fdt, node)) { - name = fdt_getprop(fdt, node, "name", &len); + name = fdt_getprop(fdt, node, "description", &len); printf(" %s\n", name); } #endif @@ -87,6 +85,42 @@ static int spl_fit_select_fdt(const void *fdt, int images, int *fdt_offsetp) return -ENOENT; } +static int get_aligned_image_offset(struct spl_load_info *info, int offset) +{ + /* + * If it is a FS read, get the first address before offset which is + * aligned to ARCH_DMA_MINALIGN. If it is raw read return the + * block number to which offset belongs. + */ + if (info->filename) + return offset & ~(ARCH_DMA_MINALIGN - 1); + + return offset / info->bl_len; +} + +static int get_aligned_image_overhead(struct spl_load_info *info, int offset) +{ + /* + * If it is a FS read, get the difference between the offset and + * the first address before offset which is aligned to + * ARCH_DMA_MINALIGN. If it is raw read return the offset within the + * block. + */ + if (info->filename) + return offset & (ARCH_DMA_MINALIGN - 1); + + return offset % info->bl_len; +} + +static int get_aligned_image_size(struct spl_load_info *info, int data_size, + int offset) +{ + if (info->filename) + return data_size + get_aligned_image_overhead(info, offset); + + return (data_size + info->bl_len - 1) / info->bl_len; +} + int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) { int sectors; @@ -96,7 +130,7 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) void *load_ptr; int fdt_offset, fdt_len; int data_offset, data_size; - int base_offset; + int base_offset, align_len = ARCH_DMA_MINALIGN - 1; int src_sector; void *dst; @@ -122,8 +156,9 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) * In fact the FIT has its own load address, but we assume it cannot * be before CONFIG_SYS_TEXT_BASE. */ - fit = (void *)(CONFIG_SYS_TEXT_BASE - size - info->bl_len); - sectors = (size + info->bl_len - 1) / info->bl_len; + fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len - + align_len) & ~align_len); + sectors = get_aligned_image_size(info, size, 0); count = info->read(info, sector, sectors, fit); debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n", sector, sectors, fit, count); @@ -156,19 +191,23 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) * byte will be at 'load'. This may mean we need to load it starting * before then, since we can only read whole blocks. */ - sectors = (data_size + info->bl_len - 1) / info->bl_len; data_offset += base_offset; + sectors = get_aligned_image_size(info, data_size, data_offset); load_ptr = (void *)load; debug("U-Boot size %x, data %p\n", data_size, load_ptr); - dst = load_ptr - (data_offset % info->bl_len); + dst = load_ptr; /* Read the image */ - src_sector = sector + data_offset / info->bl_len; - debug("image: data_offset=%x, dst=%p, src_sector=%x, sectors=%x\n", - data_offset, dst, src_sector, sectors); + src_sector = sector + get_aligned_image_offset(info, data_offset); + debug("Aligned image read: dst=%p, src_sector=%x, sectors=%x\n", + dst, src_sector, sectors); count = info->read(info, src_sector, sectors, dst); if (count != sectors) return -EIO; + debug("image: dst=%p, data_offset=%x, size=%x\n", dst, data_offset, + data_size); + memcpy(dst, dst + get_aligned_image_overhead(info, data_offset), + data_size); /* Figure out which device tree the board wants to use */ fdt_len = spl_fit_select_fdt(fit, images, &fdt_offset); @@ -178,13 +217,15 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) /* * Read the device tree and place it after the image. There may be * some extra data before it since we can only read entire blocks. + * And also align the destination address to ARCH_DMA_MINALIGN. */ - dst = load_ptr + data_size; + dst = (void *)((load + data_size + align_len) & ~align_len); fdt_offset += base_offset; - count = info->read(info, sector + fdt_offset / info->bl_len, sectors, - dst); - debug("fit read %x sectors to %x, dst %p, data_offset %x\n", - sectors, spl_image.load_addr, dst, fdt_offset); + sectors = get_aligned_image_size(info, fdt_len, fdt_offset); + src_sector = sector + get_aligned_image_offset(info, fdt_offset); + count = info->read(info, src_sector, sectors, dst); + debug("Aligned fdt read: dst %p, src_sector = %x, sectors %x\n", + dst, src_sector, sectors); if (count != sectors) return -EIO; @@ -193,7 +234,10 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) * After this we will have the U-Boot image and its device tree ready * for us to start. */ - memcpy(dst, dst + fdt_offset % info->bl_len, fdt_len); + debug("fdt: dst=%p, data_offset=%x, size=%x\n", dst, fdt_offset, + fdt_len); + memcpy(load_ptr + data_size, + dst + get_aligned_image_overhead(info, fdt_offset), fdt_len); return 0; } diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 5676acdde3..ef8583a1a6 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -34,9 +34,8 @@ static int mmc_load_legacy(struct mmc *mmc, ulong sector, mmc->read_bl_len; /* Read the header too to avoid extra memcpy */ - count = mmc->block_dev.block_read(&mmc->block_dev, sector, - image_size_sectors, - (void *)(ulong)spl_image.load_addr); + count = blk_dread(mmc_get_blk_desc(mmc), sector, image_size_sectors, + (void *)(ulong)spl_image.load_addr); debug("read %x sectors to %x\n", image_size_sectors, spl_image.load_addr); if (count != image_size_sectors) @@ -50,7 +49,7 @@ static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, { struct mmc *mmc = load->dev; - return mmc->block_dev.block_read(&mmc->block_dev, sector, count, buf); + return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf); } static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) @@ -63,7 +62,7 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) sizeof(struct image_header)); /* read image header to find the image size & load address */ - count = mmc->block_dev.block_read(&mmc->block_dev, sector, 1, header); + count = blk_dread(mmc_get_blk_desc(mmc), sector, 1, header); debug("hdr read sector %lx, count=%lu\n", sector, count); if (count == 0) { ret = -EIO; @@ -77,6 +76,7 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) debug("Found FIT\n"); load.dev = mmc; load.priv = NULL; + load.filename = NULL; load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; ret = spl_load_simple_fit(&load, sector, header); diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index bbd9546987..7cf0d1b986 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -9,6 +9,8 @@ #include <spl.h> #include <asm/io.h> #include <nand.h> +#include <libfdt_env.h> +#include <fdt.h> #if defined(CONFIG_SPL_NAND_RAW_ONLY) int spl_nand_load_image(void) @@ -24,6 +26,19 @@ int spl_nand_load_image(void) return 0; } #else + +static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs, + ulong size, void *dst) +{ + int ret; + + ret = nand_spl_load_image(offs, size, dst); + if (!ret) + return size; + else + return 0; +} + static int spl_nand_load_element(int offset, struct image_header *header) { int err; @@ -32,12 +47,24 @@ static int spl_nand_load_element(int offset, struct image_header *header) if (err) return err; - err = spl_parse_image_header(header); - if (err) - return err; + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; - return nand_spl_load_image(offset, spl_image.size, - (void *)(unsigned long)spl_image.load_addr); + debug("Found FIT\n"); + load.dev = NULL; + load.priv = NULL; + load.filename = NULL; + load.bl_len = 1; + load.read = spl_nand_fit_read; + return spl_load_simple_fit(&load, offset, header); + } else { + err = spl_parse_image_header(header); + if (err) + return err; + return nand_spl_load_image(offset, spl_image.size, + (void *)(ulong)spl_image.load_addr); + } } int spl_nand_load_image(void) diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 4f26ea5d21..5402301c78 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -14,15 +14,60 @@ #include <xyzModem.h> #include <asm/u-boot.h> #include <asm/utils.h> +#include <libfdt.h> #define BUF_SIZE 1024 +/* + * Information required to load image using ymodem. + * + * @image_read: Now of bytes read from the image. + * @buf: pointer to the previous read block. + */ +struct ymodem_fit_info { + int image_read; + char *buf; +}; + static int getcymodem(void) { if (tstc()) return (getc()); return -1; } +static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, + ulong size, void *addr) +{ + int res, err; + struct ymodem_fit_info *info = load->priv; + char *buf = info->buf; + + while (info->image_read < offset) { + res = xyzModem_stream_read(buf, BUF_SIZE, &err); + if (res <= 0) + return res; + info->image_read += res; + } + + if (info->image_read > offset) { + res = info->image_read - offset; + memcpy(addr, &buf[BUF_SIZE - res], res); + addr = addr + res; + } + + while (info->image_read < offset + size) { + res = xyzModem_stream_read(buf, BUF_SIZE, &err); + if (res <= 0) + return res; + + memcpy(addr, buf, res); + info->image_read += res; + addr += res; + } + + return size; +} + int spl_ymodem_load_image(void) { int size = 0; @@ -31,30 +76,55 @@ int spl_ymodem_load_image(void) int ret; connection_info_t info; char buf[BUF_SIZE]; - ulong store_addr = ~0; ulong addr = 0; info.mode = xyzModem_ymodem; ret = xyzModem_stream_open(&info, &err); + if (ret) { + printf("spl: ymodem err - %s\n", xyzModem_error(err)); + return ret; + } + + res = xyzModem_stream_read(buf, BUF_SIZE, &err); + if (res <= 0) + goto end_stream; + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic((struct image_header *)buf) == FDT_MAGIC) { + struct spl_load_info load; + struct ymodem_fit_info info; + + debug("Found FIT\n"); + load.dev = NULL; + load.priv = (void *)&info; + load.filename = NULL; + load.bl_len = 1; + info.buf = buf; + info.image_read = BUF_SIZE; + load.read = ymodem_read_fit; + ret = spl_load_simple_fit(&load, 0, (void *)buf); + size = info.image_read; - if (!ret) { - while ((res = - xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) { - if (addr == 0) { - ret = spl_parse_image_header((struct image_header *)buf); - if (ret) - return ret; - } - store_addr = addr + spl_image.load_addr; + while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) + size += res; + } else { + spl_parse_image_header((struct image_header *)buf); + ret = spl_parse_image_header((struct image_header *)buf); + if (ret) + return ret; + addr = spl_image.load_addr; + memcpy((void *)addr, buf, res); + size += res; + addr += res; + + while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) { + memcpy((void *)addr, buf, res); size += res; addr += res; - memcpy((char *)(store_addr), buf, res); } - } else { - printf("spl: ymodem err - %s\n", xyzModem_error(err)); - return ret; } +end_stream: xyzModem_stream_close(&err); xyzModem_stream_terminate(false, &getcymodem); diff --git a/common/splash_source.c b/common/splash_source.c index a09dd4b46e..f86a78a436 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -45,9 +45,9 @@ static int splash_sf_read_raw(u32 bmp_load_addr, int offset, size_t read_size) #ifdef CONFIG_CMD_NAND static int splash_nand_read_raw(u32 bmp_load_addr, int offset, size_t read_size) { - return nand_read_skip_bad(&nand_info[nand_curr_device], offset, + return nand_read_skip_bad(nand_info[nand_curr_device], offset, &read_size, NULL, - nand_info[nand_curr_device].size, + nand_info[nand_curr_device]->size, (u_char *)bmp_load_addr); } #else diff --git a/common/usb.c b/common/usb.c index 8d9efe516b..b3ba487890 100644 --- a/common/usb.c +++ b/common/usb.c @@ -1182,7 +1182,7 @@ int usb_new_device(struct usb_device *dev) * with the device. So a get_descriptor will fail before any * of that is done for XHCI unlike EHCI. */ -#ifdef CONFIG_USB_XHCI +#ifdef CONFIG_USB_XHCI_HCD do_read = false; #endif err = usb_setup_device(dev, do_read, dev->parent); |