#include <gzip.h>
#include <image.h>
#include <log.h>
-#include <malloc.h>
+#include <memalign.h>
+#include <mapmem.h>
#include <spl.h>
#include <sysinfo.h>
#include <asm/cache.h>
* no string in the property for this index. Check if the
* sysinfo-level code can supply one.
*/
+ rc = sysinfo_detect(sysinfo);
+ if (rc)
+ return rc;
+
rc = sysinfo_get_fit_loadable(sysinfo, index - i - 1, type,
&str);
if (rc && rc != -ENOENT)
* @image_info: will be filled with information about the loaded image
* If the FIT node does not contain a "load" (address) property,
* the image gets loaded to the address pointed to by the
- * load_addr member in this struct.
+ * load_addr member in this struct, if load_addr is not 0
*
* Return: 0 on success or a negative error number.
*/
size_t length;
int len;
ulong size;
- ulong load_addr, load_ptr;
+ ulong load_addr;
+ void *load_ptr;
void *src;
ulong overhead;
int nr_sectors;
- int align_len = ARCH_DMA_MINALIGN - 1;
uint8_t image_comp = -1, type = -1;
const void *data;
const void *fit = ctx->fit;
debug("%s ", genimg_get_comp_name(image_comp));
}
- if (fit_image_get_load(fit, node, &load_addr))
+ if (fit_image_get_load(fit, node, &load_addr)) {
+ if (!image_info->load_addr) {
+ printf("Can't load %s: No load address and no buffer\n",
+ fit_get_name(fit, node, NULL));
+ return -ENOBUFS;
+ }
load_addr = image_info->load_addr;
+ }
if (!fit_image_get_data_position(fit, node, &offset)) {
external_data = true;
}
if (external_data) {
+ void *src_ptr;
+
/* External data */
if (fit_image_get_data_size(fit, node, &len))
return -ENOENT;
- load_ptr = (load_addr + align_len) & ~align_len;
+ /* Dont bother to copy 0 byte data, but warn, though */
+ if (!len) {
+ log_warning("%s: Skip load '%s': image size is 0!\n",
+ __func__, fit_get_name(fit, node, NULL));
+ return 0;
+ }
+
+ src_ptr = map_sysmem(ALIGN(load_addr, ARCH_DMA_MINALIGN), len);
length = len;
overhead = get_aligned_image_overhead(info, offset);
if (info->read(info,
sector + get_aligned_image_offset(info, offset),
- nr_sectors, (void *)load_ptr) != nr_sectors)
+ nr_sectors, src_ptr) != nr_sectors)
return -EIO;
- debug("External data: dst=%lx, offset=%x, size=%lx\n",
- load_ptr, offset, (unsigned long)length);
- src = (void *)load_ptr + overhead;
+ debug("External data: dst=%p, offset=%x, size=%lx\n",
+ src_ptr, offset, (unsigned long)length);
+ src = src_ptr + overhead;
} else {
/* Embedded data */
if (fit_image_get_data(fit, node, &data, &length)) {
}
debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
(unsigned long)length);
- src = (void *)data;
+ src = (void *)data; /* cast away const */
}
if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
printf("## Checking hash(es) for Image %s ... ",
fit_get_name(fit, node, NULL));
- if (!fit_image_verify_with_data(fit, node, src, length))
+ if (!fit_image_verify_with_data(fit, node, gd_fdt_blob(), src,
+ length))
return -EPERM;
puts("OK\n");
}
if (CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS))
- board_fit_image_post_process(&src, &length);
+ board_fit_image_post_process(fit, node, &src, &length);
+ load_ptr = map_sysmem(load_addr, length);
if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) {
size = length;
- if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN,
- src, &size)) {
+ if (gunzip(load_ptr, CONFIG_SYS_BOOTM_LEN, src, &size)) {
puts("Uncompressing error\n");
return -EIO;
}
length = size;
} else {
- memcpy((void *)load_addr, src, length);
+ memcpy(load_ptr, src, length);
}
if (image_info) {
}
/* Make the load-address of the FDT available for the SPL framework */
- spl_image->fdt_addr = (void *)image_info.load_addr;
+ spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0);
if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY))
return 0;
* depending on how the overlay is stored, so
* don't fail yet if the allocation failed.
*/
- tmpbuffer = malloc(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ);
+ size_t size = CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ;
+
+ tmpbuffer = malloc_cache_aligned(size);
if (!tmpbuffer)
debug("%s: unable to allocate space for overlays\n",
__func__);
ret = fdt_record_loadable(blob, index, name, image->load_addr,
image->size, image->entry_point,
fdt_getprop(ctx->fit, node, "type", NULL),
- fdt_getprop(ctx->fit, node, "os", NULL));
+ fdt_getprop(ctx->fit, node, "os", NULL),
+ fdt_getprop(ctx->fit, node, "arch", NULL));
return ret;
}
+static int spl_fit_image_is_fpga(const void *fit, int node)
+{
+ const char *type;
+
+ if (!IS_ENABLED(CONFIG_SPL_FPGA))
+ return 0;
+
+ type = fdt_getprop(fit, node, FIT_TYPE_PROP, NULL);
+ if (!type)
+ return 0;
+
+ return !strcmp(type, "fpga");
+}
+
static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
{
if (!CONFIG_IS_ENABLED(FIT_IMAGE_TINY) || CONFIG_IS_ENABLED(OS_BOOT))
{
void *buf;
- buf = malloc(size);
+ buf = malloc_cache_aligned(size);
if (!buf) {
pr_err("Could not get FIT buffer of %lu bytes\n", (ulong)size);
pr_err("\tcheck CONFIG_SYS_SPL_MALLOC_SIZE\n");
return buf;
}
+__weak void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
+{
+ return spl_get_fit_load_buffer(sectors * bl_len);
+}
+
/*
* Weak default function to allow customizing SPL fit loading for load-only
* use cases by allowing to skip the parsing/processing of the FIT contents
return false;
}
+/*
+ * Weak default function to allow fixes after fit header
+ * is loaded.
+ */
+__weak void *spl_load_simple_fit_fix_load(const void *fit)
+{
+ return (void *)fit;
+}
+
+static void warn_deprecated(const char *msg)
+{
+ printf("DEPRECATED: %s\n", msg);
+ printf("\tSee doc/uImage.FIT/source_file_format.txt\n");
+}
+
+static int spl_fit_upload_fpga(struct spl_fit_info *ctx, int node,
+ struct spl_image_info *fpga_image)
+{
+ const char *compatible;
+ int ret;
+ int devnum = 0;
+ int flags = 0;
+
+ debug("FPGA bitstream at: %x, size: %x\n",
+ (u32)fpga_image->load_addr, fpga_image->size);
+
+ compatible = fdt_getprop(ctx->fit, node, "compatible", NULL);
+ if (!compatible) {
+ warn_deprecated("'fpga' image without 'compatible' property");
+ } else {
+ if (CONFIG_IS_ENABLED(FPGA_LOAD_SECURE))
+ flags = fpga_compatible2flag(devnum, compatible);
+ if (strcmp(compatible, "u-boot,fpga-legacy"))
+ debug("Ignoring compatible = %s property\n",
+ compatible);
+ }
+
+ ret = fpga_load(devnum, (void *)fpga_image->load_addr,
+ fpga_image->size, BIT_FULL, flags);
+ if (ret) {
+ printf("%s: Cannot load the image to the FPGA\n", __func__);
+ return ret;
+ }
+
+ puts("FPGA image loaded from FIT\n");
+
+ return 0;
+}
+
+static int spl_fit_load_fpga(struct spl_fit_info *ctx,
+ struct spl_load_info *info, ulong sector)
+{
+ int node, ret;
+
+ struct spl_image_info fpga_image = {
+ .load_addr = 0,
+ };
+
+ node = spl_fit_get_image_node(ctx, "fpga", 0);
+ if (node < 0)
+ return node;
+
+ warn_deprecated("'fpga' property in config node. Use 'loadables'");
+
+ /* Load the image and set up the fpga_image structure */
+ ret = spl_load_fit_image(info, sector, ctx, node, &fpga_image);
+ if (ret) {
+ printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
+ return ret;
+ }
+
+ return spl_fit_upload_fpga(ctx, node, &fpga_image);
+}
+
static int spl_simple_fit_read(struct spl_fit_info *ctx,
struct spl_load_info *info, ulong sector,
const void *fit_header)
* For FIT with external data, data is not loaded in this step.
*/
sectors = get_aligned_image_size(info, size, 0);
- buf = spl_get_fit_load_buffer(sectors * info->bl_len);
+ buf = board_spl_fit_buffer_addr(size, sectors, info->bl_len);
count = info->read(info, sector, sectors, buf);
ctx->fit = buf;
if (spl_load_simple_fit_skip_processing())
return 0;
+ ctx.fit = spl_load_simple_fit_fix_load(ctx.fit);
+
ret = spl_simple_fit_parse(&ctx);
if (ret < 0)
return ret;
-#ifdef CONFIG_SPL_FPGA
- node = spl_fit_get_image_node(&ctx, "fpga", 0);
- if (node >= 0) {
- /* Load the image and set up the spl_image structure */
- ret = spl_load_fit_image(info, sector, &ctx, node, spl_image);
- if (ret) {
- printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
- return ret;
- }
-
- debug("FPGA bitstream at: %x, size: %x\n",
- (u32)spl_image->load_addr, spl_image->size);
-
- ret = fpga_load(0, (const void *)spl_image->load_addr,
- spl_image->size, BIT_FULL);
- if (ret) {
- printf("%s: Cannot load the image to the FPGA\n",
- __func__);
- return ret;
- }
-
- puts("FPGA image loaded from FIT\n");
- node = -1;
- }
-#endif
+ if (IS_ENABLED(CONFIG_SPL_FPGA))
+ spl_fit_load_fpga(&ctx, info, sector);
/*
* Find the U-Boot image using the following search order:
if (firmware_node == node)
continue;
+ image_info.load_addr = 0;
ret = spl_load_fit_image(info, sector, &ctx, node, &image_info);
if (ret < 0) {
printf("%s: can't load image loadables index %d (ret = %d)\n",
return ret;
}
+ if (spl_fit_image_is_fpga(ctx.fit, node))
+ spl_fit_upload_fpga(&ctx, node, &image_info);
+
if (!spl_fit_image_get_os(ctx.fit, node, &os_type))
debug("Loadable is %s\n", genimg_get_os_name(os_type));
}
/*
- * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's
+ * If a platform does not provide CFG_SYS_UBOOT_START, U-Boot's
* Makefile will set it to 0 and it will end up as the entry point
* here. What it actually means is: use the load address.
*/