summaryrefslogtreecommitdiff
path: root/common/spl
diff options
context:
space:
mode:
Diffstat (limited to 'common/spl')
-rw-r--r--common/spl/Kconfig45
-rw-r--r--common/spl/spl_fit.c98
-rw-r--r--common/spl/spl_imx_container.c13
3 files changed, 96 insertions, 60 deletions
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index a21b71ad5d1..0618f42c941 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -220,7 +220,7 @@ source "common/spl/Kconfig.nxp"
config HANDOFF
bool "Pass hand-off information from SPL to U-Boot proper"
- depends on BLOBLIST
+ depends on BLOBLIST_FIXED
help
It is useful to be able to pass information from SPL to U-Boot
proper to preserve state that is known in SPL and is needed in U-Boot.
@@ -541,7 +541,7 @@ config SPL_SYS_MMCSD_RAW_MODE
ARCH_MX6 || ARCH_MX7 || \
ARCH_ROCKCHIP || ARCH_MVEBU || ARCH_SOCFPGA_GEN5 || \
ARCH_AT91 || ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \
- OMAP54XX || AM33XX || AM43XX || \
+ OMAP44XX || OMAP54XX || AM33XX || AM43XX || \
TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED
help
Support booting from an MMC without a filesystem.
@@ -585,7 +585,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
default 0x100 if ARCH_UNIPHIER
default 0x0 if ARCH_MVEBU
default 0x200 if ARCH_SOCFPGA_GEN5 || ARCH_AT91
- default 0x300 if ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || \
+ default 0x300 if ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || OMAP44XX || \
OMAP54XX || AM33XX || AM43XX || ARCH_K3
default 0x4000 if ARCH_ROCKCHIP
default 0x822 if TARGET_SIFIVE_UNLEASHED || TARGET_SIFIVE_UNMATCHED
@@ -1151,7 +1151,7 @@ config SPL_DM_SPI_FLASH
config SPL_NET
bool "Support networking"
- depends on NET
+ depends on NET_LEGACY
select SPL_USE_TINY_PRINTF_POINTER_SUPPORT if SPL_USE_TINY_PRINTF
help
Enable support for network devices (such as Ethernet) in SPL.
@@ -1160,6 +1160,9 @@ config SPL_NET
the network stack uses a number of environment variables. See also
SPL_ETH.
+config SPL_NET_LEGACY
+ def_bool y if SPL_NET
+
config SPL_NET_VCI_STRING
string "BOOTP Vendor Class Identifier string sent by SPL"
depends on SPL_NET
@@ -1318,10 +1321,10 @@ config SPL_PCI
config SPL_PCI_ENDPOINT
bool "Support for PCI endpoint drivers"
help
- Enable this configuration option to support configurable PCI
- endpoints at SPL. This should be enabled if the platform has
- a PCI controllers that can operate in endpoint mode (as a device
- connected to PCI host or bridge).
+ Enable this configuration option to support configurable PCI
+ endpoints at SPL. This should be enabled if the platform has
+ a PCI controllers that can operate in endpoint mode (as a device
+ connected to PCI host or bridge).
config SPL_PCH
bool "Support PCH drivers"
@@ -1549,18 +1552,18 @@ config SPL_SPI_FLASH_TINY
depends on !SPI_FLASH_BAR
default y if SPI_FLASH
help
- Enable lightweight SPL SPI Flash support that supports just reading
- data/images from flash. No support to write/erase flash. Enable
- this if you have SPL size limitations and don't need full
- fledged SPI flash support.
+ Enable lightweight SPL SPI Flash support that supports just reading
+ data/images from flash. No support to write/erase flash. Enable
+ this if you have SPL size limitations and don't need full
+ fledged SPI flash support.
config SPL_SPI_FLASH_SFDP_SUPPORT
bool "SFDP table parsing support for SPI NOR flashes"
depends on !SPI_FLASH_BAR && !SPL_SPI_FLASH_TINY
help
- Enable support for parsing and auto discovery of parameters for
- SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP)
- tables as per JESD216 standard in SPL.
+ Enable support for parsing and auto discovery of parameters for
+ SPI NOR flashes using Serial Flash Discoverable Parameters (SFDP)
+ tables as per JESD216 standard in SPL.
config SPL_SPI_FLASH_MTD
bool "Support for SPI flash MTD drivers in SPL"
@@ -1581,22 +1584,22 @@ config SYS_SPI_U_BOOT_OFFS
default 0x0
depends on SPL_SPI_LOAD || SPL_SPI_SUNXI
help
- Address within SPI-Flash from where the u-boot payload is fetched
- from.
+ Address within SPI-Flash from where the u-boot payload is fetched
+ from.
config SYS_SPI_KERNEL_OFFS
hex "Falcon mode: address of kernel payload in SPI flash"
depends on SPL_SPI_FLASH_SUPPORT && SPL_OS_BOOT
help
- Address within SPI-Flash from where the kernel payload is fetched
- in falcon boot.
+ Address within SPI-Flash from where the kernel payload is fetched
+ in falcon boot.
config SYS_SPI_ARGS_OFFS
hex "Falcon mode: address of args payload in SPI flash"
depends on SPL_SPI_FLASH_SUPPORT && SPL_OS_BOOT_ARGS
help
- Address within SPI-Flash from where the args payload (usually the
- dtb) is fetched in falcon boot.
+ Address within SPI-Flash from where the args payload (usually the
+ dtb) is fetched in falcon boot.
config SYS_SPI_ARGS_SIZE
hex "Falcon mode: size of args payload in SPI flash"
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 46ebcabe56a..18bff7b8d4a 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -204,6 +204,9 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size,
* 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, if load_addr is not 0
+ * @max_size: maximum number of bytes that may be written to the
+ * destination; an image whose data exceeds this is rejected
+ * before it is read from the device
*
* Return: 0 on success, -EBADSLT if this image is not the correct phase
* (for CONFIG_BOOTMETH_VBE_SIMPLE_FW), or another negative error number on
@@ -211,7 +214,7 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size,
*/
static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
const struct spl_fit_info *ctx, int node,
- struct spl_image_info *image_info)
+ struct spl_image_info *image_info, ulong max_size)
{
int offset;
size_t length;
@@ -291,6 +294,23 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
return 0;
}
+ /*
+ * data-size is excluded from the configuration signature (it
+ * is in exc_prop[] in image-fit-sig.c), so it stays attacker
+ * controlled even after fit_config_verify() succeeds. The
+ * image hash is only verified after the device read below, so
+ * an oversized value has to be rejected here.
+ *
+ * Bail out before get_aligned_image_size() runs on a hostile
+ * len: that helper does its arithmetic in int and would
+ * invoke signed-integer overflow on a value close to or above
+ * INT_MAX. The block-aligned check further down is the
+ * mathematically binding one, since size is len rounded up to
+ * the device block length.
+ */
+ if ((ulong)len > max_size)
+ goto too_big;
+
if (spl_decompression_enabled() &&
(image_comp == IH_COMP_GZIP || image_comp == IH_COMP_LZMA))
src_ptr = map_sysmem(ALIGN(CONFIG_SYS_LOAD_ADDR, ARCH_DMA_MINALIGN), len);
@@ -302,6 +322,15 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
size = get_aligned_image_size(info, length, offset);
read_offset = fit_offset + get_aligned_image_offset(info,
offset);
+
+ /*
+ * info->read() transfers the block-aligned size into the
+ * destination, so this is the bound that actually matters;
+ * len was rejected above only to keep this computation safe.
+ */
+ if (size > max_size)
+ goto too_big;
+
log_debug("reading from offset %x / %lx size %lx to %p: ",
offset, read_offset, size, src_ptr);
@@ -372,6 +401,11 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
upl_add_image(fit, node, load_addr, length);
return 0;
+
+too_big:
+ printf("%s: FIT image too large (data-size %u, max %lu)\n",
+ __func__, (u32)len, max_size);
+ return -EFBIG;
}
static bool os_takes_devicetree(uint8_t os)
@@ -427,7 +461,8 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
spl_image->fdt_addr = map_sysmem(image_info.load_addr, size);
memcpy(spl_image->fdt_addr, gd->fdt_blob, size);
} else {
- ret = load_simple_fit(info, offset, ctx, node, &image_info);
+ ret = load_simple_fit(info, offset, ctx, node, &image_info,
+ CONFIG_SYS_BOOTM_LEN);
if (ret < 0)
return ret;
@@ -479,7 +514,8 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
}
image_info.load_addr = (ulong)tmpbuffer;
ret = load_simple_fit(info, offset, ctx, node,
- &image_info);
+ &image_info,
+ CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ);
if (ret == -EBADSLT)
continue;
else if (ret < 0)
@@ -687,7 +723,8 @@ static int spl_fit_load_fpga(struct spl_fit_info *ctx,
warn_deprecated("'fpga' property in config node. Use 'loadables'");
/* Load the image and set up the fpga_image structure */
- ret = load_simple_fit(info, offset, ctx, node, &fpga_image);
+ ret = load_simple_fit(info, offset, ctx, node, &fpga_image,
+ CONFIG_SYS_BOOTM_LEN);
if (ret) {
printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
return ret;
@@ -775,7 +812,7 @@ static int spl_simple_fit_parse(struct spl_fit_info *ctx)
if (ctx->conf_node < 0)
return -EINVAL;
- if (IS_ENABLED(CONFIG_SPL_FIT_SIGNATURE)) {
+ if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
printf("## Checking hash(es) for config %s ... ",
fit_get_name(ctx->fit, ctx->conf_node, NULL));
if (fit_config_verify(ctx->fit, ctx->conf_node))
@@ -849,7 +886,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
}
/* Load the image and set up the spl_image structure */
- ret = load_simple_fit(info, offset, &ctx, node, spl_image);
+ ret = load_simple_fit(info, offset, &ctx, node, spl_image,
+ CONFIG_SYS_BOOTM_LEN);
if (ret)
return ret;
@@ -890,7 +928,8 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
continue;
image_info.load_addr = 0;
- ret = load_simple_fit(info, offset, &ctx, node, &image_info);
+ ret = load_simple_fit(info, offset, &ctx, node, &image_info,
+ CONFIG_SYS_BOOTM_LEN);
if (ret < 0 && ret != -EBADSLT) {
printf("%s: can't load image loadables index %d (ret = %d)\n",
__func__, index, ret);
@@ -955,22 +994,12 @@ int spl_load_fit_image(struct spl_image_info *spl_image,
int idx, conf_noffset;
int ret;
-#ifdef CONFIG_SPL_FIT_SIGNATURE
- images.verify = 1;
-#endif
+ images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE);
+
ret = fit_image_load(&images, virt_to_phys((void *)header),
- NULL, &fit_uname_config,
- IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
- FIT_LOAD_OPTIONAL, &fw_data, &fw_len);
- if (ret >= 0) {
- printf("DEPRECATED: 'standalone = ' property.");
- printf("Please use either 'firmware =' or 'kernel ='\n");
- } else {
- ret = fit_image_load(&images, virt_to_phys((void *)header),
- NULL, &fit_uname_config, IH_ARCH_DEFAULT,
- IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL,
- &fw_data, &fw_len);
- }
+ NULL, &fit_uname_config, IH_ARCH_DEFAULT,
+ IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL,
+ &fw_data, &fw_len);
if (ret < 0) {
ret = fit_image_load(&images, virt_to_phys((void *)header),
@@ -993,21 +1022,21 @@ int spl_load_fit_image(struct spl_image_info *spl_image,
debug(PHASE_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n",
spl_image->name, spl_image->load_addr, spl_image->size);
-#ifdef CONFIG_SPL_FIT_SIGNATURE
- images.verify = 1;
-#endif
+ images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE);
+
ret = fit_image_load(&images, virt_to_phys((void *)header), NULL,
&fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_FLATDT,
-1, FIT_LOAD_OPTIONAL, &dt_data, &dt_len);
if (ret >= 0) {
- spl_image->fdt_addr = (void *)dt_data;
-
if (spl_image->os == IH_OS_U_BOOT) {
/* HACK: U-Boot expects FDT at a specific address */
- fdt_hack = spl_image->load_addr + spl_image->size;
- fdt_hack = (fdt_hack + 3) & ~3;
- debug("Relocating FDT to %p\n", spl_image->fdt_addr);
- memcpy((void *)fdt_hack, spl_image->fdt_addr, dt_len);
+ fdt_hack = ALIGN(spl_image->load_addr + spl_image->size, 8);
+ debug("Relocating FDT to %p\n", (void *)fdt_hack);
+ memcpy(map_sysmem(fdt_hack, dt_len),
+ map_sysmem(dt_data, 0), dt_len);
+ spl_image->fdt_addr = (void *)fdt_hack;
+ } else {
+ spl_image->fdt_addr = (void *)dt_data;
}
}
@@ -1021,10 +1050,9 @@ int spl_load_fit_image(struct spl_image_info *spl_image,
FIT_LOADABLE_PROP, idx,
NULL), uname;
idx++) {
-#ifdef CONFIG_SPL_FIT_SIGNATURE
- images.verify = 1;
-#endif
- ret = fit_image_load(&images, (ulong)header,
+ images.verify = CONFIG_IS_ENABLED(FIT_SIGNATURE);
+
+ ret = fit_image_load(&images, virt_to_phys((void *)header),
&uname, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_LOADABLE, -1,
FIT_LOAD_OPTIONAL_NON_ZERO,
diff --git a/common/spl/spl_imx_container.c b/common/spl/spl_imx_container.c
index 79d021f81dc..57cd75b9b5e 100644
--- a/common/spl/spl_imx_container.c
+++ b/common/spl/spl_imx_container.c
@@ -88,6 +88,7 @@ static int read_auth_container(struct spl_image_info *spl_image,
struct spl_load_info *info, ulong offset)
{
struct container_hdr *container = NULL;
+ struct container_hdr *authhdr;
u16 length;
int i, size, ret = 0;
@@ -140,15 +141,19 @@ static int read_auth_container(struct spl_image_info *spl_image,
}
}
+ authhdr = container;
+
#ifdef CONFIG_AHAB_BOOT
- ret = ahab_auth_cntr_hdr(container, length);
- if (ret)
+ authhdr = ahab_auth_cntr_hdr(authhdr, length);
+ if (!authhdr) {
+ ret = -EINVAL;
goto end_auth;
+ }
#endif
- for (i = 0; i < container->num_images; i++) {
+ for (i = 0; i < authhdr->num_images; i++) {
struct boot_img_t *image = read_auth_image(spl_image, info,
- container, i,
+ authhdr, i,
offset);
if (!image) {