Merge branch '2020-12-07-bootm-and-spl-atf-improvements' into next
- Series to improve "bootm" by allowing variable evaluation within the cmdline we would be passing. This will help with Chrome OS but can be useful elsewhere. - Improve ATF (TF-A) support within SPL.
This commit is contained in:
@@ -146,6 +146,8 @@ config SANDBOX
|
||||
imply ACPI_PMC_SANDBOX
|
||||
imply CMD_PMC
|
||||
imply CMD_CLONE
|
||||
imply SILENT_CONSOLE
|
||||
imply BOOTARGS_SUBST
|
||||
|
||||
config SH
|
||||
bool "SuperH architecture"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/armv8/sec_firmware.h>
|
||||
|
||||
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
int psci_update_dt(void *fdt)
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#endif
|
||||
#include <fsl_sec.h>
|
||||
#include <asm/arch-fsl-layerscape/soc.h>
|
||||
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
#include <asm/armv8/sec_firmware.h>
|
||||
#endif
|
||||
#include <asm/arch/speed.h>
|
||||
@@ -81,7 +81,7 @@ void ft_fixup_cpu(void *blob)
|
||||
"device_type", "cpu", 4);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT) && \
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT) && \
|
||||
defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI)
|
||||
int node;
|
||||
u32 psci_ver;
|
||||
@@ -383,7 +383,7 @@ static void fdt_fixup_msi(void *blob)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
/* Remove JR node used by SEC firmware */
|
||||
void fdt_fixup_remove_jr(void *blob)
|
||||
{
|
||||
@@ -488,7 +488,7 @@ void ft_cpu_setup(void *blob, struct bd_info *bd)
|
||||
else {
|
||||
ccsr_sec_t __iomem *sec;
|
||||
|
||||
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
fdt_fixup_remove_jr(blob);
|
||||
fdt_fixup_kaslr(blob);
|
||||
#endif
|
||||
|
||||
@@ -192,6 +192,7 @@ ENTRY(lowlevel_init)
|
||||
#endif
|
||||
|
||||
/* Initialize GIC Secure Bank Status */
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
|
||||
branch_if_slave x0, 1f
|
||||
bl get_gic_offset
|
||||
@@ -205,6 +206,7 @@ ENTRY(lowlevel_init)
|
||||
bl gic_init_secure_percpu
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
100:
|
||||
branch_if_master x0, x1, 2f
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#elif defined(CONFIG_FSL_LSCH2)
|
||||
#include <asm/arch/immap_lsch2.h>
|
||||
#endif
|
||||
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
#include <asm/armv8/sec_firmware.h>
|
||||
#endif
|
||||
#ifdef CONFIG_CHAIN_OF_TRUST
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
ethernet3 = &enetc6;
|
||||
};
|
||||
|
||||
binman {
|
||||
binman: binman {
|
||||
filename = "u-boot.rom";
|
||||
pad-byte = <0xff>;
|
||||
|
||||
@@ -80,21 +80,18 @@
|
||||
conf-1 {
|
||||
description = "fsl-ls1028a-kontron-sl28";
|
||||
firmware = "uboot";
|
||||
loadables = "uboot";
|
||||
fdt = "fdt-1";
|
||||
};
|
||||
|
||||
conf-2 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var3";
|
||||
firmware = "uboot";
|
||||
loadables = "uboot";
|
||||
fdt = "fdt-2";
|
||||
};
|
||||
|
||||
conf-3 {
|
||||
description = "fsl-ls1028a-kontron-sl28-var4";
|
||||
firmware = "uboot";
|
||||
loadables = "uboot";
|
||||
fdt = "fdt-3";
|
||||
};
|
||||
};
|
||||
@@ -102,6 +99,81 @@
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SL28_SPL_LOADS_ATF_BL31
|
||||
&binman {
|
||||
fit {
|
||||
images {
|
||||
bl31 {
|
||||
description = "ARM Trusted Firmware (bl31)";
|
||||
type = "firmware";
|
||||
arch = "arm";
|
||||
os = "arm-trusted-firmware";
|
||||
compression = "none";
|
||||
load = <CONFIG_SL28_BL31_ENTRY_ADDR>;
|
||||
entry = <CONFIG_SL28_BL31_ENTRY_ADDR>;
|
||||
|
||||
blob-ext {
|
||||
filename = "bl31.bin";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configurations {
|
||||
conf-1 {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
|
||||
conf-2 {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
|
||||
conf-3 {
|
||||
firmware = "bl31";
|
||||
loadables = "uboot";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SL28_SPL_LOADS_OPTEE_BL32
|
||||
&binman {
|
||||
fit {
|
||||
images {
|
||||
bl32 {
|
||||
description = "OP-TEE Trusted OS (bl32)";
|
||||
type = "firmware";
|
||||
arch = "arm";
|
||||
os = "tee";
|
||||
compression = "none";
|
||||
load = <CONFIG_SL28_BL32_ENTRY_ADDR>;
|
||||
entry = <CONFIG_SL28_BL32_ENTRY_ADDR>;
|
||||
|
||||
blob-ext {
|
||||
filename = "tee.bin";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configurations {
|
||||
conf-1 {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
|
||||
conf-2 {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
|
||||
conf-3 {
|
||||
loadables = "uboot", "bl32";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
&i2c0 {
|
||||
rtc: rtc@32 {
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ int arch_fixup_fdt(void *blob)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV8_PSCI) || \
|
||||
defined(CONFIG_SEC_FIRMWARE_ARMV8_PSCI)
|
||||
CONFIG_IS_ENABLED(SEC_FIRMWARE_ARMV8_PSCI)
|
||||
ret = psci_update_dt(blob);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/psci.h>
|
||||
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
#include <asm/armv8/sec_firmware.h>
|
||||
#endif
|
||||
|
||||
@@ -64,7 +64,7 @@ int fdt_psci(void *fdt)
|
||||
return nodeoff;
|
||||
|
||||
init_psci_node:
|
||||
#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
psci_ver = sec_firmware_support_psci_version();
|
||||
#elif defined(CONFIG_ARMV7_PSCI_1_0) || defined(CONFIG_ARMV8_PSCI)
|
||||
psci_ver = ARM_PSCI_VER_1_0;
|
||||
@@ -85,7 +85,7 @@ init_psci_node:
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
#if !CONFIG_IS_ENABLED(ARMV8_SEC_FIRMWARE_SUPPORT)
|
||||
/*
|
||||
* The Secure firmware framework isn't able to support PSCI version 0.1.
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define LOG_CATEGORY LOGC_BOOT
|
||||
|
||||
#include <common.h>
|
||||
#include <bootm.h>
|
||||
#include <command.h>
|
||||
#include <env.h>
|
||||
#include <irq_func.h>
|
||||
@@ -330,7 +331,12 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
|
||||
}
|
||||
|
||||
if (cmd_line) {
|
||||
int max_size = 0xff;
|
||||
int ret;
|
||||
|
||||
log_debug("Setup cmdline\n");
|
||||
if (bootproto >= 0x0206)
|
||||
max_size = hdr->cmdline_size;
|
||||
if (bootproto >= 0x0202) {
|
||||
hdr->cmd_line_ptr = (uintptr_t)cmd_line;
|
||||
} else if (bootproto >= 0x0200) {
|
||||
@@ -346,6 +352,14 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
|
||||
strcpy(cmd_line, (char *)cmdline_force);
|
||||
else
|
||||
build_command_line(cmd_line, auto_boot);
|
||||
ret = bootm_process_cmdline(cmd_line, max_size, BOOTM_CL_ALL);
|
||||
if (ret) {
|
||||
printf("Cmdline setup failed (err=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
printf("Kernel command line: \"");
|
||||
puts(cmd_line);
|
||||
printf("\"\n");
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_INTEL_MID) && bootproto >= 0x0207)
|
||||
|
||||
@@ -15,4 +15,37 @@ config SYS_CONFIG_NAME
|
||||
config SYS_TEXT_BASE
|
||||
default 0x96000000
|
||||
|
||||
config SL28_SPL_LOADS_ATF_BL31
|
||||
bool "SPL loads BL31 of the ARM Trusted Firmware"
|
||||
select SPL_ATF
|
||||
select SPL_ATF_LOAD_IMAGE_V2
|
||||
select ARMV8_SEC_FIRMWARE_SUPPORT
|
||||
select SEC_FIRMWARE_ARMV8_PSCI
|
||||
help
|
||||
Enable this to load a BL31 image by the SPL. You have to
|
||||
provde a bl31.bin in u-boot's root directory.
|
||||
|
||||
if SL28_SPL_LOADS_ATF_BL31
|
||||
|
||||
config SL28_BL31_ENTRY_ADDR
|
||||
hex "Entry point of the BL31 image"
|
||||
default 0xfbe00000
|
||||
|
||||
endif
|
||||
|
||||
config SL28_SPL_LOADS_OPTEE_BL32
|
||||
bool "SPL loads OP-TEE Trusted OS as BL32"
|
||||
depends on SL28_SPL_LOADS_ATF_BL31
|
||||
help
|
||||
Enable this to load a BL32 image by the SPL. You have to
|
||||
provde a tee.bin in u-boot's root directory.
|
||||
|
||||
if SL28_SPL_LOADS_OPTEE_BL32
|
||||
|
||||
config SL28_BL32_ENTRY_ADDR
|
||||
hex "Entry point of the BL32 image"
|
||||
default 0xfc000000
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
@@ -5,4 +5,8 @@ obj-y += sl28.o cmds.o
|
||||
endif
|
||||
|
||||
obj-y += common.o ddr.o
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||
|
||||
ifdef CONFIG_SPL_BUILD
|
||||
obj-y += spl.o
|
||||
obj-$(CONFIG_SPL_ATF) += spl_atf.o
|
||||
endif
|
||||
|
||||
@@ -50,6 +50,7 @@ int ft_board_setup(void *blob, struct bd_info *bd)
|
||||
u64 base[CONFIG_NR_DRAM_BANKS];
|
||||
u64 size[CONFIG_NR_DRAM_BANKS];
|
||||
int nbanks = CONFIG_NR_DRAM_BANKS;
|
||||
int node;
|
||||
int i;
|
||||
|
||||
ft_cpu_setup(blob, bd);
|
||||
@@ -64,5 +65,11 @@ int ft_board_setup(void *blob, struct bd_info *bd)
|
||||
|
||||
fdt_fixup_icid(blob);
|
||||
|
||||
if (CONFIG_IS_ENABLED(SL28_SPL_LOADS_OPTEE_BL32)) {
|
||||
node = fdt_node_offset_by_compatible(blob, -1, "linaro,optee-tz");
|
||||
if (node)
|
||||
fdt_set_node_status(blob, node, FDT_STATUS_OKAY, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
54
board/kontron/sl28/spl_atf.c
Normal file
54
board/kontron/sl28/spl_atf.c
Normal file
@@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* LS1028A TF-A calling support
|
||||
*
|
||||
* Copyright (c) 2020 Michael Walle <michael@walle.cc>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <asm/io.h>
|
||||
#include <atf_common.h>
|
||||
#include <spl.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct region_info {
|
||||
u64 addr;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
struct dram_regions_info {
|
||||
u64 num_dram_regions;
|
||||
u64 total_dram_size;
|
||||
struct region_info region[CONFIG_NR_DRAM_BANKS];
|
||||
};
|
||||
|
||||
struct bl_params *bl2_plat_get_bl31_params_v2(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr)
|
||||
{
|
||||
static struct dram_regions_info dram_regions_info = { 0 };
|
||||
struct bl_params *bl_params;
|
||||
struct bl_params_node *node;
|
||||
void *dcfg_ccsr = (void *)DCFG_BASE;
|
||||
int i;
|
||||
|
||||
dram_regions_info.num_dram_regions = CONFIG_NR_DRAM_BANKS;
|
||||
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||
dram_regions_info.region[i].addr = gd->bd->bi_dram[i].start;
|
||||
dram_regions_info.region[i].size = gd->bd->bi_dram[i].size;
|
||||
dram_regions_info.total_dram_size += gd->bd->bi_dram[i].size;
|
||||
}
|
||||
|
||||
bl_params = bl2_plat_get_bl31_params_v2_default(bl32_entry, bl33_entry,
|
||||
fdt_addr);
|
||||
|
||||
for_each_bl_params_node(bl_params, node) {
|
||||
if (node->image_id == ATF_BL31_IMAGE_ID) {
|
||||
node->ep_info->args.arg3 = (uintptr_t)&dram_regions_info;
|
||||
node->ep_info->args.arg4 = in_le32(dcfg_ccsr + DCFG_PORSR1);
|
||||
}
|
||||
}
|
||||
|
||||
return bl_params;
|
||||
}
|
||||
@@ -266,7 +266,9 @@ static int _do_env_set(int flag, int argc, char *const argv[], int env_flag)
|
||||
/* Delete only ? */
|
||||
if (argc < 3 || argv[2] == NULL) {
|
||||
int rc = hdelete_r(name, &env_htab, env_flag);
|
||||
return !rc;
|
||||
|
||||
/* If the variable didn't exist, don't report an error */
|
||||
return rc && rc != -ENOENT ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -895,7 +897,7 @@ static int do_env_delete(struct cmd_tbl *cmdtp, int flag,
|
||||
while (--argc > 0) {
|
||||
char *name = *++argv;
|
||||
|
||||
if (!hdelete_r(name, &env_htab, env_flag))
|
||||
if (hdelete_r(name, &env_htab, env_flag))
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -322,7 +322,8 @@ static int label_localboot(struct pxe_label *label)
|
||||
if (label->append) {
|
||||
char bootargs[CONFIG_SYS_CBSIZE];
|
||||
|
||||
cli_simple_process_macros(label->append, bootargs);
|
||||
cli_simple_process_macros(label->append, bootargs,
|
||||
sizeof(bootargs));
|
||||
env_set("bootargs", bootargs);
|
||||
}
|
||||
|
||||
@@ -430,7 +431,8 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
|
||||
strcat(bootargs, ip_str);
|
||||
strcat(bootargs, mac_str);
|
||||
|
||||
cli_simple_process_macros(bootargs, finalbootargs);
|
||||
cli_simple_process_macros(bootargs, finalbootargs,
|
||||
sizeof(finalbootargs));
|
||||
env_set("bootargs", finalbootargs);
|
||||
printf("append: %s\n", finalbootargs);
|
||||
}
|
||||
|
||||
@@ -865,6 +865,23 @@ config BOOTARGS
|
||||
CONFIG_BOOTARGS goes into the environment value "bootargs". Note that
|
||||
this value will also override the "chosen" node in FDT blob.
|
||||
|
||||
config BOOTARGS_SUBST
|
||||
bool "Support substituting strings in boot arguments"
|
||||
help
|
||||
This allows substituting string values in the boot arguments. These
|
||||
are applied after the commandline has been built.
|
||||
|
||||
One use for this is to insert the root-disk UUID into the command
|
||||
line where bootargs contains "root=${uuid}"
|
||||
|
||||
setenv bootargs "console= root=${uuid}"
|
||||
# Set the 'uuid' environment variable
|
||||
part uuid mmc 2:2 uuid
|
||||
|
||||
# Command-line substitution will put the real uuid into the
|
||||
# kernel command line
|
||||
bootm
|
||||
|
||||
config USE_BOOTCOMMAND
|
||||
bool "Enable a default value for bootcmd"
|
||||
help
|
||||
|
||||
174
common/bootm.c
174
common/bootm.c
@@ -7,6 +7,7 @@
|
||||
#ifndef USE_HOSTCC
|
||||
#include <common.h>
|
||||
#include <bootstage.h>
|
||||
#include <cli.h>
|
||||
#include <cpu_func.h>
|
||||
#include <env.h>
|
||||
#include <errno.h>
|
||||
@@ -19,6 +20,7 @@
|
||||
#include <net.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/sizes.h>
|
||||
#if defined(CONFIG_CMD_USB)
|
||||
#include <usb.h>
|
||||
#endif
|
||||
@@ -35,6 +37,8 @@
|
||||
#define CONFIG_SYS_BOOTM_LEN 0x800000
|
||||
#endif
|
||||
|
||||
#define MAX_CMDLINE_SIZE SZ_4K
|
||||
|
||||
#define IH_INITRD_ARCH IH_ARCH_DEFAULT
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
@@ -465,18 +469,34 @@ ulong bootm_disable_interrupts(void)
|
||||
return iflag;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
|
||||
#define CONSOLE_ARG "console="
|
||||
#define CONSOLE_ARG_SIZE sizeof(CONSOLE_ARG)
|
||||
|
||||
#define CONSOLE_ARG "console="
|
||||
#define CONSOLE_ARG_LEN (sizeof(CONSOLE_ARG) - 1)
|
||||
|
||||
static void fixup_silent_linux(void)
|
||||
/**
|
||||
* fixup_silent_linux() - Handle silencing the linux boot if required
|
||||
*
|
||||
* This uses the silent_linux envvar to control whether to add/set a "console="
|
||||
* parameter to the command line
|
||||
*
|
||||
* @buf: Buffer containing the string to process
|
||||
* @maxlen: Maximum length of buffer
|
||||
* @return 0 if OK, -ENOSPC if @maxlen is too small
|
||||
*/
|
||||
static int fixup_silent_linux(char *buf, int maxlen)
|
||||
{
|
||||
char *buf;
|
||||
const char *env_val;
|
||||
char *cmdline = env_get("bootargs");
|
||||
int want_silent;
|
||||
char *cmdline;
|
||||
int size;
|
||||
|
||||
/*
|
||||
* Move the input string to the end of buffer. The output string will be
|
||||
* built up at the start.
|
||||
*/
|
||||
size = strlen(buf) + 1;
|
||||
if (size * 2 > maxlen)
|
||||
return -ENOSPC;
|
||||
cmdline = buf + maxlen - size;
|
||||
memmove(cmdline, buf, size);
|
||||
/*
|
||||
* Only fix cmdline when requested. The environment variable can be:
|
||||
*
|
||||
@@ -486,44 +506,132 @@ static void fixup_silent_linux(void)
|
||||
*/
|
||||
want_silent = env_get_yesno("silent_linux");
|
||||
if (want_silent == 0)
|
||||
return;
|
||||
return 0;
|
||||
else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
debug("before silent fix-up: %s\n", cmdline);
|
||||
if (cmdline && (cmdline[0] != '\0')) {
|
||||
if (*cmdline) {
|
||||
char *start = strstr(cmdline, CONSOLE_ARG);
|
||||
|
||||
/* Allocate space for maximum possible new command line */
|
||||
buf = malloc(strlen(cmdline) + 1 + CONSOLE_ARG_LEN + 1);
|
||||
if (!buf) {
|
||||
debug("%s: out of memory\n", __func__);
|
||||
return;
|
||||
}
|
||||
/* Check space for maximum possible new command line */
|
||||
if (size + CONSOLE_ARG_SIZE > maxlen)
|
||||
return -ENOSPC;
|
||||
|
||||
if (start) {
|
||||
char *end = strchr(start, ' ');
|
||||
int num_start_bytes = start - cmdline + CONSOLE_ARG_LEN;
|
||||
int start_bytes;
|
||||
|
||||
strncpy(buf, cmdline, num_start_bytes);
|
||||
start_bytes = start - cmdline + CONSOLE_ARG_SIZE - 1;
|
||||
strncpy(buf, cmdline, start_bytes);
|
||||
if (end)
|
||||
strcpy(buf + num_start_bytes, end);
|
||||
strcpy(buf + start_bytes, end);
|
||||
else
|
||||
buf[num_start_bytes] = '\0';
|
||||
buf[start_bytes] = '\0';
|
||||
} else {
|
||||
sprintf(buf, "%s %s", cmdline, CONSOLE_ARG);
|
||||
}
|
||||
env_val = buf;
|
||||
if (buf + strlen(buf) >= cmdline)
|
||||
return -ENOSPC;
|
||||
} else {
|
||||
buf = NULL;
|
||||
env_val = CONSOLE_ARG;
|
||||
if (maxlen < sizeof(CONSOLE_ARG))
|
||||
return -ENOSPC;
|
||||
strcpy(buf, CONSOLE_ARG);
|
||||
}
|
||||
debug("after silent fix-up: %s\n", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* process_subst() - Handle substitution of ${...} fields in the environment
|
||||
*
|
||||
* Handle variable substitution in the provided buffer
|
||||
*
|
||||
* @buf: Buffer containing the string to process
|
||||
* @maxlen: Maximum length of buffer
|
||||
* @return 0 if OK, -ENOSPC if @maxlen is too small
|
||||
*/
|
||||
static int process_subst(char *buf, int maxlen)
|
||||
{
|
||||
char *cmdline;
|
||||
int size;
|
||||
int ret;
|
||||
|
||||
/* Move to end of buffer */
|
||||
size = strlen(buf) + 1;
|
||||
cmdline = buf + maxlen - size;
|
||||
if (buf + size > cmdline)
|
||||
return -ENOSPC;
|
||||
memmove(cmdline, buf, size);
|
||||
|
||||
ret = cli_simple_process_macros(cmdline, buf, cmdline - buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bootm_process_cmdline(char *buf, int maxlen, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Check config first to enable compiler to eliminate code */
|
||||
if (IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
|
||||
!IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) &&
|
||||
(flags & BOOTM_CL_SILENT)) {
|
||||
ret = fixup_silent_linux(buf, maxlen);
|
||||
if (ret)
|
||||
return log_msg_ret("silent", ret);
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && (flags & BOOTM_CL_SUBST)) {
|
||||
ret = process_subst(buf, maxlen);
|
||||
if (ret)
|
||||
return log_msg_ret("silent", ret);
|
||||
}
|
||||
|
||||
env_set("bootargs", env_val);
|
||||
debug("after silent fix-up: %s\n", env_val);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bootm_process_cmdline_env(int flags)
|
||||
{
|
||||
const int maxlen = MAX_CMDLINE_SIZE;
|
||||
bool do_silent;
|
||||
const char *env;
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
/* First check if any action is needed */
|
||||
do_silent = IS_ENABLED(CONFIG_SILENT_CONSOLE) &&
|
||||
!IS_ENABLED(CONFIG_SILENT_U_BOOT_ONLY) && (flags & BOOTM_CL_SILENT);
|
||||
if (!do_silent && !IS_ENABLED(CONFIG_BOOTARGS_SUBST))
|
||||
return 0;
|
||||
|
||||
env = env_get("bootargs");
|
||||
if (env && strlen(env) >= maxlen)
|
||||
return -E2BIG;
|
||||
buf = malloc(maxlen);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
if (env)
|
||||
strcpy(buf, env);
|
||||
else
|
||||
*buf = '\0';
|
||||
ret = bootm_process_cmdline(buf, maxlen, flags);
|
||||
if (!ret) {
|
||||
ret = env_set("bootargs", buf);
|
||||
|
||||
/*
|
||||
* If buf is "" and bootargs does not exist, this will produce
|
||||
* an error trying to delete bootargs. Ignore it
|
||||
*/
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
}
|
||||
free(buf);
|
||||
if (ret)
|
||||
return log_msg_ret("env", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_SILENT_CONSOLE */
|
||||
|
||||
/**
|
||||
* Execute selected states of the bootm command.
|
||||
@@ -627,10 +735,12 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
if (!ret && (states & BOOTM_STATE_OS_BD_T))
|
||||
ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
|
||||
if (!ret && (states & BOOTM_STATE_OS_PREP)) {
|
||||
#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
|
||||
if (images->os.os == IH_OS_LINUX)
|
||||
fixup_silent_linux();
|
||||
#endif
|
||||
ret = bootm_process_cmdline_env(images->os.os == IH_OS_LINUX);
|
||||
if (ret) {
|
||||
printf("Cmdline setup failed (err=%d)\n", ret);
|
||||
ret = CMD_RET_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,13 +60,14 @@ int cli_simple_parse_line(char *line, char *argv[])
|
||||
return nargs;
|
||||
}
|
||||
|
||||
void cli_simple_process_macros(const char *input, char *output)
|
||||
int cli_simple_process_macros(const char *input, char *output, int max_size)
|
||||
{
|
||||
char c, prev;
|
||||
const char *varname_start = NULL;
|
||||
int inputcnt = strlen(input);
|
||||
int outputcnt = CONFIG_SYS_CBSIZE;
|
||||
int outputcnt = max_size;
|
||||
int state = 0; /* 0 = waiting for '$' */
|
||||
int ret;
|
||||
|
||||
/* 1 = waiting for '(' or '{' */
|
||||
/* 2 = waiting for ')' or '}' */
|
||||
@@ -157,13 +158,18 @@ void cli_simple_process_macros(const char *input, char *output)
|
||||
prev = c;
|
||||
}
|
||||
|
||||
if (outputcnt)
|
||||
ret = inputcnt ? -ENOSPC : 0;
|
||||
if (outputcnt) {
|
||||
*output = 0;
|
||||
else
|
||||
} else {
|
||||
*(output - 1) = 0;
|
||||
ret = -ENOSPC;
|
||||
}
|
||||
|
||||
debug_parser("[PROCESS_MACROS] OUTPUT len %zd: \"%s\"\n",
|
||||
strlen(output_start), output_start);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -239,7 +245,8 @@ int cli_simple_run_command(const char *cmd, int flag)
|
||||
debug_parser("token: \"%s\"\n", token);
|
||||
|
||||
/* find macros in this token and replace them */
|
||||
cli_simple_process_macros(token, finaltoken);
|
||||
cli_simple_process_macros(token, finaltoken,
|
||||
sizeof(finaltoken));
|
||||
|
||||
/* Extract arguments */
|
||||
argc = cli_simple_parse_line(finaltoken, argv);
|
||||
|
||||
@@ -1276,6 +1276,15 @@ config SPL_ATF
|
||||
is loaded by SPL (which is considered as BL2 in ATF terminology).
|
||||
More detail at: https://github.com/ARM-software/arm-trusted-firmware
|
||||
|
||||
config SPL_ATF_LOAD_IMAGE_V2
|
||||
bool "Use the new LOAD_IMAGE_V2 parameter passing"
|
||||
depends on SPL_ATF
|
||||
help
|
||||
Some platforms use the newer LOAD_IMAGE_V2 parameter passing.
|
||||
|
||||
If you want to load a bl31 image from the SPL and need the new
|
||||
method, say Y.
|
||||
|
||||
config SPL_ATF_NO_PLATFORM_PARAM
|
||||
bool "Pass no platform parameter"
|
||||
depends on SPL_ATF
|
||||
|
||||
@@ -18,13 +18,36 @@
|
||||
#include <spl.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
static struct bl2_to_bl31_params_mem bl31_params_mem;
|
||||
static struct bl31_params *bl2_to_bl31_params;
|
||||
/* Holds all the structures we need for bl31 parameter passing */
|
||||
struct bl2_to_bl31_params_mem {
|
||||
struct bl31_params bl31_params;
|
||||
struct atf_image_info bl31_image_info;
|
||||
struct atf_image_info bl32_image_info;
|
||||
struct atf_image_info bl33_image_info;
|
||||
struct entry_point_info bl33_ep_info;
|
||||
struct entry_point_info bl32_ep_info;
|
||||
struct entry_point_info bl31_ep_info;
|
||||
};
|
||||
|
||||
__weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr)
|
||||
struct bl2_to_bl31_params_mem_v2 {
|
||||
struct bl_params bl_params;
|
||||
struct bl_params_node bl31_params_node;
|
||||
struct bl_params_node bl32_params_node;
|
||||
struct bl_params_node bl33_params_node;
|
||||
struct atf_image_info bl31_image_info;
|
||||
struct atf_image_info bl32_image_info;
|
||||
struct atf_image_info bl33_image_info;
|
||||
struct entry_point_info bl33_ep_info;
|
||||
struct entry_point_info bl32_ep_info;
|
||||
struct entry_point_info bl31_ep_info;
|
||||
};
|
||||
|
||||
struct bl31_params *bl2_plat_get_bl31_params_default(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr)
|
||||
{
|
||||
static struct bl2_to_bl31_params_mem bl31_params_mem;
|
||||
struct bl31_params *bl2_to_bl31_params;
|
||||
struct entry_point_info *bl32_ep_info;
|
||||
struct entry_point_info *bl33_ep_info;
|
||||
|
||||
@@ -78,6 +101,87 @@ __weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
|
||||
return bl2_to_bl31_params;
|
||||
}
|
||||
|
||||
__weak struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr)
|
||||
{
|
||||
return bl2_plat_get_bl31_params_default(bl32_entry, bl33_entry,
|
||||
fdt_addr);
|
||||
}
|
||||
|
||||
struct bl_params *bl2_plat_get_bl31_params_v2_default(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr)
|
||||
{
|
||||
static struct bl2_to_bl31_params_mem_v2 bl31_params_mem;
|
||||
struct bl_params *bl_params;
|
||||
struct bl_params_node *bl_params_node;
|
||||
|
||||
/*
|
||||
* Initialise the memory for all the arguments that needs to
|
||||
* be passed to BL31
|
||||
*/
|
||||
memset(&bl31_params_mem, 0, sizeof(bl31_params_mem));
|
||||
|
||||
/* Assign memory for TF related information */
|
||||
bl_params = &bl31_params_mem.bl_params;
|
||||
SET_PARAM_HEAD(bl_params, ATF_PARAM_BL_PARAMS, ATF_VERSION_2, 0);
|
||||
bl_params->head = &bl31_params_mem.bl31_params_node;
|
||||
|
||||
/* Fill BL31 related information */
|
||||
bl_params_node = &bl31_params_mem.bl31_params_node;
|
||||
bl_params_node->image_id = ATF_BL31_IMAGE_ID;
|
||||
bl_params_node->image_info = &bl31_params_mem.bl31_image_info;
|
||||
bl_params_node->ep_info = &bl31_params_mem.bl31_ep_info;
|
||||
bl_params_node->next_params_info = &bl31_params_mem.bl32_params_node;
|
||||
SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY,
|
||||
ATF_VERSION_2, 0);
|
||||
|
||||
/* Fill BL32 related information */
|
||||
bl_params_node = &bl31_params_mem.bl32_params_node;
|
||||
bl_params_node->image_id = ATF_BL32_IMAGE_ID;
|
||||
bl_params_node->image_info = &bl31_params_mem.bl32_image_info;
|
||||
bl_params_node->ep_info = &bl31_params_mem.bl32_ep_info;
|
||||
bl_params_node->next_params_info = &bl31_params_mem.bl33_params_node;
|
||||
SET_PARAM_HEAD(bl_params_node->ep_info, ATF_PARAM_EP,
|
||||
ATF_VERSION_2, ATF_EP_SECURE);
|
||||
|
||||
/* secure payload is optional, so set pc to 0 if absent */
|
||||
bl_params_node->ep_info->args.arg3 = fdt_addr;
|
||||
bl_params_node->ep_info->pc = bl32_entry ? bl32_entry : 0;
|
||||
bl_params_node->ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXECPTIONS);
|
||||
SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY,
|
||||
ATF_VERSION_2, 0);
|
||||
|
||||
/* Fill BL33 related information */
|
||||
bl_params_node = &bl31_params_mem.bl33_params_node;
|
||||
bl_params_node->image_id = ATF_BL33_IMAGE_ID;
|
||||
bl_params_node->image_info = &bl31_params_mem.bl33_image_info;
|
||||
bl_params_node->ep_info = &bl31_params_mem.bl33_ep_info;
|
||||
bl_params_node->next_params_info = NULL;
|
||||
SET_PARAM_HEAD(bl_params_node->ep_info, ATF_PARAM_EP,
|
||||
ATF_VERSION_2, ATF_EP_NON_SECURE);
|
||||
|
||||
/* BL33 expects to receive the primary CPU MPID (through x0) */
|
||||
bl_params_node->ep_info->args.arg0 = 0xffff & read_mpidr();
|
||||
bl_params_node->ep_info->pc = bl33_entry;
|
||||
bl_params_node->ep_info->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXECPTIONS);
|
||||
SET_PARAM_HEAD(bl_params_node->image_info, ATF_PARAM_IMAGE_BINARY,
|
||||
ATF_VERSION_2, 0);
|
||||
|
||||
return bl_params;
|
||||
}
|
||||
|
||||
__weak struct bl_params *bl2_plat_get_bl31_params_v2(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr)
|
||||
{
|
||||
return bl2_plat_get_bl31_params_v2_default(bl32_entry, bl33_entry,
|
||||
fdt_addr);
|
||||
}
|
||||
|
||||
static inline void raw_write_daif(unsigned int daif)
|
||||
{
|
||||
__asm__ __volatile__("msr DAIF, %0\n\t" : : "r" (daif) : "memory");
|
||||
@@ -88,16 +192,21 @@ typedef void (*atf_entry_t)(struct bl31_params *params, void *plat_params);
|
||||
static void bl31_entry(uintptr_t bl31_entry, uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry, uintptr_t fdt_addr)
|
||||
{
|
||||
struct bl31_params *bl31_params;
|
||||
atf_entry_t atf_entry = (atf_entry_t)bl31_entry;
|
||||
void *bl31_params;
|
||||
|
||||
bl31_params = bl2_plat_get_bl31_params(bl32_entry, bl33_entry,
|
||||
fdt_addr);
|
||||
if (CONFIG_IS_ENABLED(ATF_LOAD_IMAGE_V2))
|
||||
bl31_params = bl2_plat_get_bl31_params_v2(bl32_entry,
|
||||
bl33_entry,
|
||||
fdt_addr);
|
||||
else
|
||||
bl31_params = bl2_plat_get_bl31_params(bl32_entry, bl33_entry,
|
||||
fdt_addr);
|
||||
|
||||
raw_write_daif(SPSR_EXCEPTION_MASK);
|
||||
dcache_disable();
|
||||
|
||||
atf_entry((void *)bl31_params, (void *)fdt_addr);
|
||||
atf_entry(bl31_params, (void *)fdt_addr);
|
||||
}
|
||||
|
||||
static int spl_fit_images_find(void *blob, int os)
|
||||
|
||||
@@ -14,8 +14,14 @@
|
||||
#define ATF_PARAM_EP 0x01
|
||||
#define ATF_PARAM_IMAGE_BINARY 0x02
|
||||
#define ATF_PARAM_BL31 0x03
|
||||
#define ATF_PARAM_BL_PARAMS 0x05
|
||||
|
||||
#define ATF_VERSION_1 0x01
|
||||
#define ATF_VERSION_2 0x02
|
||||
|
||||
#define ATF_BL31_IMAGE_ID 0x03
|
||||
#define ATF_BL32_IMAGE_ID 0x04
|
||||
#define ATF_BL33_IMAGE_ID 0x05
|
||||
|
||||
#define ATF_EP_SECURE 0x0
|
||||
#define ATF_EP_NON_SECURE 0x1
|
||||
@@ -121,6 +127,9 @@ struct atf_image_info {
|
||||
struct param_header h;
|
||||
uintptr_t image_base; /* physical address of base of image */
|
||||
uint32_t image_size; /* bytes read from image file */
|
||||
#if CONFIG_IS_ENABLED(ATF_LOAD_IMAGE_V2)
|
||||
uint32_t image_max_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -162,21 +171,28 @@ struct bl31_params {
|
||||
struct atf_image_info *bl33_image_info;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* This structure represents the superset of information that is passed to
|
||||
* BL31, e.g. while passing control to it from BL2, bl31_params
|
||||
* and other platform specific params
|
||||
******************************************************************************/
|
||||
struct bl2_to_bl31_params_mem {
|
||||
struct bl31_params bl31_params;
|
||||
struct atf_image_info bl31_image_info;
|
||||
struct atf_image_info bl32_image_info;
|
||||
struct atf_image_info bl33_image_info;
|
||||
struct entry_point_info bl33_ep_info;
|
||||
struct entry_point_info bl32_ep_info;
|
||||
struct entry_point_info bl31_ep_info;
|
||||
/* BL image node in the BL image execution sequence */
|
||||
struct bl_params_node {
|
||||
unsigned int image_id;
|
||||
struct atf_image_info *image_info;
|
||||
struct entry_point_info *ep_info;
|
||||
struct bl_params_node *next_params_info;
|
||||
};
|
||||
|
||||
/*
|
||||
* BL image head node in the BL image execution sequence
|
||||
* It is also used to pass information to next BL image.
|
||||
*/
|
||||
struct bl_params {
|
||||
struct param_header h;
|
||||
struct bl_params_node *head;
|
||||
};
|
||||
|
||||
#define for_each_bl_params_node(bl_params, node) \
|
||||
for ((node) = (bl_params)->head; \
|
||||
(node); \
|
||||
(node) = (node)->next_params_info)
|
||||
|
||||
#endif /*__ASSEMBLY__ */
|
||||
|
||||
#endif /* __BL_COMMON_H__ */
|
||||
|
||||
@@ -75,6 +75,14 @@ void board_quiesce_devices(void);
|
||||
*/
|
||||
void switch_to_non_secure_mode(void);
|
||||
|
||||
/* Flags to control bootm_process_cmdline() */
|
||||
enum bootm_cmdline_t {
|
||||
BOOTM_CL_SILENT = 1 << 0, /* Do silent console processing */
|
||||
BOOTM_CL_SUBST = 1 << 1, /* Do substitution */
|
||||
|
||||
BOOTM_CL_ALL = 3, /* All substitutions */
|
||||
};
|
||||
|
||||
/**
|
||||
* arch_preboot_os() - arch specific configuration before booting
|
||||
*/
|
||||
@@ -85,4 +93,36 @@ void arch_preboot_os(void);
|
||||
*/
|
||||
void board_preboot_os(void);
|
||||
|
||||
/*
|
||||
* bootm_process_cmdline() - Process fix-ups for the command line
|
||||
*
|
||||
* This handles:
|
||||
*
|
||||
* - making Linux boot silently if requested ('silent_linux' envvar)
|
||||
* - performing substitutions in the command line ('bootargs_subst' envvar)
|
||||
*
|
||||
* @maxlen must provide enough space for the string being processed plus the
|
||||
* resulting string
|
||||
*
|
||||
* @buf: buffer holding commandline string to adjust
|
||||
* @maxlen: Maximum length of buffer at @buf (including \0)
|
||||
* @flags: Flags to control what happens (see bootm_cmdline_t)
|
||||
* @return 0 if OK, -ENOMEM if out of memory, -ENOSPC if the commandline is too
|
||||
* long
|
||||
*/
|
||||
int bootm_process_cmdline(char *buf, int maxlen, int flags);
|
||||
|
||||
/**
|
||||
* bootm_process_cmdline_env() - Process fix-ups for the command line
|
||||
*
|
||||
* Updates the 'bootargs' envvar as required. This handles:
|
||||
*
|
||||
* - making Linux boot silently if requested ('silent_linux' envvar)
|
||||
* - performing substitutions in the command line ('bootargs_subst' envvar)
|
||||
*
|
||||
* @flags: Flags to control what happens (see bootm_cmdline_t)
|
||||
* @return 0 if OK, -ENOMEM if out of memory
|
||||
*/
|
||||
int bootm_process_cmdline_env(int flags);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,8 +34,10 @@ int cli_simple_run_command(const char *cmd, int flag);
|
||||
*
|
||||
* @param input Input string possible containing $() / ${} vars
|
||||
* @param output Output string with $() / ${} vars expanded
|
||||
* @param max_size Maximum size of @output (including terminator)
|
||||
* @return 0 if OK, -ENOSPC if we ran out of space in @output
|
||||
*/
|
||||
void cli_simple_process_macros(const char *input, char *output);
|
||||
int cli_simple_process_macros(const char *input, char *output, int max_size);
|
||||
|
||||
/**
|
||||
* cli_simple_run_command_list() - Execute a list of command
|
||||
|
||||
@@ -80,7 +80,16 @@ int hsearch_r(struct env_entry item, enum env_action action,
|
||||
int hmatch_r(const char *match, int last_idx, struct env_entry **retval,
|
||||
struct hsearch_data *htab);
|
||||
|
||||
/* Search and delete entry matching "key" in internal hash table. */
|
||||
/**
|
||||
* hdelete_r() - Search and delete entry in internal hash table
|
||||
*
|
||||
* @key: Name of entry to delete
|
||||
* @htab: Hash table
|
||||
* @flag: Flags to use (H_...)
|
||||
* @return 0 on success, -ENOENT if not found, -EPERM if the hash table callback
|
||||
* rejected changing the variable, -EINVAL if the hash table refused to
|
||||
* delete the variable
|
||||
*/
|
||||
int hdelete_r(const char *key, struct hsearch_data *htab, int flag);
|
||||
|
||||
ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
|
||||
|
||||
@@ -526,25 +526,79 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image,
|
||||
void spl_invoke_atf(struct spl_image_info *spl_image);
|
||||
|
||||
/**
|
||||
* bl2_plat_get_bl31_params() - prepare params for bl31.
|
||||
* @bl32_entry address of BL32 executable (secure)
|
||||
* @bl33_entry address of BL33 executable (non secure)
|
||||
* @fdt_addr address of Flat Device Tree
|
||||
* bl2_plat_get_bl31_params() - return params for bl31.
|
||||
* @bl32_entry: address of BL32 executable (secure)
|
||||
* @bl33_entry: address of BL33 executable (non secure)
|
||||
* @fdt_addr: address of Flat Device Tree
|
||||
*
|
||||
* This function assigns a pointer to the memory that the platform has kept
|
||||
* aside to pass platform specific and trusted firmware related information
|
||||
* to BL31. This memory is allocated by allocating memory to
|
||||
* bl2_to_bl31_params_mem structure which is a superset of all the
|
||||
* structure whose information is passed to BL31
|
||||
* NOTE: This function should be called only once and should be done
|
||||
* before generating params to BL31
|
||||
* This is a weak function which might be overridden by the board code. By
|
||||
* default it will just call bl2_plat_get_bl31_params_default().
|
||||
*
|
||||
* @return bl31 params structure pointer
|
||||
* If you just want to manipulate or add some parameters, you can override
|
||||
* this function, call bl2_plat_get_bl31_params_default and operate on the
|
||||
* returned bl31 params.
|
||||
*
|
||||
* Return: bl31 params structure pointer
|
||||
*/
|
||||
struct bl31_params *bl2_plat_get_bl31_params(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr);
|
||||
|
||||
/**
|
||||
* bl2_plat_get_bl31_params_default() - prepare params for bl31.
|
||||
* @bl32_entry: address of BL32 executable (secure)
|
||||
* @bl33_entry: address of BL33 executable (non secure)
|
||||
* @fdt_addr: address of Flat Device Tree
|
||||
*
|
||||
* This is the default implementation of bl2_plat_get_bl31_params(). It assigns
|
||||
* a pointer to the memory that the platform has kept aside to pass platform
|
||||
* specific and trusted firmware related information to BL31. This memory is
|
||||
* allocated by allocating memory to bl2_to_bl31_params_mem structure which is
|
||||
* a superset of all the structure whose information is passed to BL31
|
||||
*
|
||||
* NOTE: The memory is statically allocated, thus this function should be
|
||||
* called only once. All subsequent calls will overwrite any changes.
|
||||
*
|
||||
* Return: bl31 params structure pointer
|
||||
*/
|
||||
struct bl31_params *bl2_plat_get_bl31_params_default(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr);
|
||||
|
||||
/**
|
||||
* bl2_plat_get_bl31_params_v2() - return params for bl31
|
||||
* @bl32_entry: address of BL32 executable (secure)
|
||||
* @bl33_entry: address of BL33 executable (non secure)
|
||||
* @fdt_addr: address of Flat Device Tree
|
||||
*
|
||||
* This function does the same as bl2_plat_get_bl31_params() except that is is
|
||||
* used for the new LOAD_IMAGE_V2 option, which uses a slightly different
|
||||
* method to pass the parameters.
|
||||
*
|
||||
* Return: bl31 params structure pointer
|
||||
*/
|
||||
struct bl_params *bl2_plat_get_bl31_params_v2(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr);
|
||||
|
||||
/**
|
||||
* bl2_plat_get_bl31_params_v2_default() - prepare params for bl31.
|
||||
* @bl32_entry: address of BL32 executable (secure)
|
||||
* @bl33_entry: address of BL33 executable (non secure)
|
||||
* @fdt_addr: address of Flat Device Tree
|
||||
*
|
||||
* This is the default implementation of bl2_plat_get_bl31_params_v2(). It
|
||||
* prepares the linked list of the bl31 params, populates the image types and
|
||||
* set the entry points for bl32 and bl33 (if available).
|
||||
*
|
||||
* NOTE: The memory is statically allocated, thus this function should be
|
||||
* called only once. All subsequent calls will overwrite any changes.
|
||||
*
|
||||
* Return: bl31 params structure pointer
|
||||
*/
|
||||
struct bl_params *bl2_plat_get_bl31_params_v2_default(uintptr_t bl32_entry,
|
||||
uintptr_t bl33_entry,
|
||||
uintptr_t fdt_addr);
|
||||
/**
|
||||
* spl_optee_entry - entry function for optee
|
||||
*
|
||||
|
||||
@@ -26,6 +26,7 @@ int cmd_ut_category(const char *name, const char *prefix,
|
||||
struct unit_test *tests, int n_ents,
|
||||
int argc, char *const argv[]);
|
||||
|
||||
int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
|
||||
int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[]);
|
||||
int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
|
||||
@@ -472,7 +472,7 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
|
||||
idx = hsearch_r(e, ENV_FIND, &ep, htab, 0);
|
||||
if (idx == 0) {
|
||||
__set_errno(ESRCH);
|
||||
return 0; /* not found */
|
||||
return -ENOENT; /* not found */
|
||||
}
|
||||
|
||||
/* Check for permission */
|
||||
@@ -481,7 +481,7 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
|
||||
debug("change_ok() rejected deleting variable "
|
||||
"%s, skipping it!\n", key);
|
||||
__set_errno(EPERM);
|
||||
return 0;
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/* If there is a callback, call it */
|
||||
@@ -490,12 +490,12 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
|
||||
debug("callback() rejected deleting variable "
|
||||
"%s, skipping it!\n", key);
|
||||
__set_errno(EINVAL);
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
_hdelete(key, htab, ep, idx);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV))
|
||||
@@ -917,7 +917,7 @@ int himport_r(struct hsearch_data *htab,
|
||||
if (!drop_var_from_set(name, nvars, localvars))
|
||||
continue;
|
||||
|
||||
if (hdelete_r(name, htab, flag) == 0)
|
||||
if (hdelete_r(name, htab, flag))
|
||||
debug("DELETE ERROR ##############################\n");
|
||||
|
||||
continue;
|
||||
@@ -979,7 +979,7 @@ int himport_r(struct hsearch_data *htab,
|
||||
* b) if the variable was not present in current env, we notify
|
||||
* it might be a typo
|
||||
*/
|
||||
if (hdelete_r(localvars[i], htab, flag) == 0)
|
||||
if (hdelete_r(localvars[i], htab, flag))
|
||||
printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
|
||||
else
|
||||
printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
ifneq ($(CONFIG_SANDBOX),)
|
||||
obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o
|
||||
endif
|
||||
obj-$(CONFIG_$(SPL_)CMDLINE) += bootm.o
|
||||
obj-$(CONFIG_$(SPL_)CMDLINE) += cmd/
|
||||
obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_ut.o
|
||||
obj-$(CONFIG_$(SPL_)CMDLINE) += command_ut.o
|
||||
|
||||
247
test/bootm.c
Normal file
247
test/bootm.c
Normal file
@@ -0,0 +1,247 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Tests for bootm routines
|
||||
*
|
||||
* Copyright 2020 Google LLC
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <bootm.h>
|
||||
#include <test/suites.h>
|
||||
#include <test/test.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#define BOOTM_TEST(_name, _flags) UNIT_TEST(_name, _flags, bootm_test)
|
||||
|
||||
enum {
|
||||
BUF_SIZE = 1024,
|
||||
};
|
||||
|
||||
#define CONSOLE_STR "console=/dev/ttyS0"
|
||||
|
||||
/* Test cmdline processing where nothing happens */
|
||||
static int bootm_test_nop(struct unit_test_state *uts)
|
||||
{
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
*buf = '\0';
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true));
|
||||
ut_asserteq_str("", buf);
|
||||
|
||||
strcpy(buf, "test");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true));
|
||||
ut_asserteq_str("test", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTM_TEST(bootm_test_nop, 0);
|
||||
|
||||
/* Test cmdline processing when out of space */
|
||||
static int bootm_test_nospace(struct unit_test_state *uts)
|
||||
{
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
/* Zero buffer size */
|
||||
*buf = '\0';
|
||||
ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 0, true));
|
||||
|
||||
/* Buffer string not terminated */
|
||||
memset(buf, 'a', BUF_SIZE);
|
||||
ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, true));
|
||||
|
||||
/* Not enough space to copy string */
|
||||
memset(buf, '\0', BUF_SIZE);
|
||||
memset(buf, 'a', BUF_SIZE / 2);
|
||||
ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, true));
|
||||
|
||||
/* Just enough space */
|
||||
memset(buf, '\0', BUF_SIZE);
|
||||
memset(buf, 'a', BUF_SIZE / 2 - 1);
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true));
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTM_TEST(bootm_test_nospace, 0);
|
||||
|
||||
/* Test silent processing */
|
||||
static int bootm_test_silent(struct unit_test_state *uts)
|
||||
{
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
/* 'silent_linux' not set should do nothing */
|
||||
env_set("silent_linux", NULL);
|
||||
strcpy(buf, CONSOLE_STR);
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
|
||||
ut_asserteq_str(CONSOLE_STR, buf);
|
||||
|
||||
ut_assertok(env_set("silent_linux", "no"));
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
|
||||
ut_asserteq_str(CONSOLE_STR, buf);
|
||||
|
||||
ut_assertok(env_set("silent_linux", "yes"));
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
|
||||
ut_asserteq_str("console=", buf);
|
||||
|
||||
/* Empty buffer should still add the string */
|
||||
*buf = '\0';
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
|
||||
ut_asserteq_str("console=", buf);
|
||||
|
||||
/* Check nothing happens when do_silent is false */
|
||||
*buf = '\0';
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, 0));
|
||||
ut_asserteq_str("", buf);
|
||||
|
||||
/* Not enough space */
|
||||
*buf = '\0';
|
||||
ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 8, BOOTM_CL_SILENT));
|
||||
|
||||
/* Just enough space */
|
||||
*buf = '\0';
|
||||
ut_assertok(bootm_process_cmdline(buf, 9, BOOTM_CL_SILENT));
|
||||
|
||||
/* add at end */
|
||||
strcpy(buf, "something");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
|
||||
ut_asserteq_str("something console=", buf);
|
||||
|
||||
/* change at start */
|
||||
strcpy(buf, CONSOLE_STR " something");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SILENT));
|
||||
ut_asserteq_str("console= something", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTM_TEST(bootm_test_silent, 0);
|
||||
|
||||
/* Test substitution processing */
|
||||
static int bootm_test_subst(struct unit_test_state *uts)
|
||||
{
|
||||
char buf[BUF_SIZE];
|
||||
|
||||
/* try with an unset variable */
|
||||
ut_assertok(env_set("var", NULL));
|
||||
strcpy(buf, "some${var}thing");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("something", buf);
|
||||
|
||||
/* Replace with shorter string */
|
||||
ut_assertok(env_set("var", "bb"));
|
||||
strcpy(buf, "some${var}thing");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("somebbthing", buf);
|
||||
|
||||
/* Replace with same-length string */
|
||||
ut_assertok(env_set("var", "abc"));
|
||||
strcpy(buf, "some${var}thing");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("someabcthing", buf);
|
||||
|
||||
/* Replace with longer string */
|
||||
ut_assertok(env_set("var", "abcde"));
|
||||
strcpy(buf, "some${var}thing");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("someabcdething", buf);
|
||||
|
||||
/* Check it is case sensitive */
|
||||
ut_assertok(env_set("VAR", NULL));
|
||||
strcpy(buf, "some${VAR}thing");
|
||||
ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("something", buf);
|
||||
|
||||
/* Check too long - need 12 bytes for each string */
|
||||
strcpy(buf, "some${var}thing");
|
||||
ut_asserteq(-ENOSPC,
|
||||
bootm_process_cmdline(buf, 12 * 2 - 1, BOOTM_CL_SUBST));
|
||||
|
||||
/* Check just enough space */
|
||||
strcpy(buf, "some${var}thing");
|
||||
ut_assertok(bootm_process_cmdline(buf, 16 * 2, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("someabcdething", buf);
|
||||
|
||||
/*
|
||||
* Check the substition string being too long. This results in a string
|
||||
* of 12 (13 bytes). We need enough space for that plus the original
|
||||
* "a${var}c" string of 9 bytes. So 12 + 9 = 21 bytes.
|
||||
*/
|
||||
ut_assertok(env_set("var", "1234567890"));
|
||||
strcpy(buf, "a${var}c");
|
||||
ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 21, BOOTM_CL_SUBST));
|
||||
|
||||
strcpy(buf, "a${var}c");
|
||||
ut_asserteq(0, bootm_process_cmdline(buf, 22, BOOTM_CL_SUBST));
|
||||
|
||||
/* Check multiple substitutions */
|
||||
ut_assertok(env_set("var", "abc"));
|
||||
strcpy(buf, "some${var}thing${bvar}else");
|
||||
ut_asserteq(0, bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("someabcthingelse", buf);
|
||||
|
||||
/* Check multiple substitutions */
|
||||
ut_assertok(env_set("bvar", "123"));
|
||||
strcpy(buf, "some${var}thing${bvar}else");
|
||||
ut_asserteq(0, bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("someabcthing123else", buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTM_TEST(bootm_test_subst, 0);
|
||||
|
||||
/* Test silent processing in the bootargs variable */
|
||||
static int bootm_test_silent_var(struct unit_test_state *uts)
|
||||
{
|
||||
env_set("bootargs", NULL);
|
||||
ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SUBST));
|
||||
ut_assertnull(env_get("bootargs"));
|
||||
|
||||
ut_assertok(env_set("bootargs", "some${var}thing"));
|
||||
ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SUBST));
|
||||
ut_asserteq_str("something", env_get("bootargs"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTM_TEST(bootm_test_silent_var, 0);
|
||||
|
||||
/* Test substitution processing in the bootargs variable */
|
||||
static int bootm_test_subst_var(struct unit_test_state *uts)
|
||||
{
|
||||
env_set("bootargs", NULL);
|
||||
ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SILENT));
|
||||
ut_asserteq_str("console=", env_get("bootargs"));
|
||||
|
||||
ut_assertok(env_set("var", "abc"));
|
||||
ut_assertok(env_set("bootargs", "some${var}thing"));
|
||||
ut_assertok(bootm_process_cmdline_env(BOOTM_CL_SILENT));
|
||||
ut_asserteq_str("some${var}thing console=", env_get("bootargs"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTM_TEST(bootm_test_subst_var, 0);
|
||||
|
||||
/* Test substitution and silent console processing in the bootargs variable */
|
||||
static int bootm_test_subst_both(struct unit_test_state *uts)
|
||||
{
|
||||
ut_assertok(env_set("silent_linux", "yes"));
|
||||
env_set("bootargs", NULL);
|
||||
ut_assertok(bootm_process_cmdline_env(BOOTM_CL_ALL));
|
||||
ut_asserteq_str("console=", env_get("bootargs"));
|
||||
|
||||
ut_assertok(env_set("bootargs", "some${var}thing " CONSOLE_STR));
|
||||
ut_assertok(env_set("var", "1234567890"));
|
||||
ut_assertok(bootm_process_cmdline_env(BOOTM_CL_ALL));
|
||||
ut_asserteq_str("some1234567890thing console=", env_get("bootargs"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
BOOTM_TEST(bootm_test_subst_both, 0);
|
||||
|
||||
int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
{
|
||||
struct unit_test *tests = ll_entry_start(struct unit_test, bootm_test);
|
||||
const int n_ents = ll_entry_count(struct unit_test, bootm_test);
|
||||
|
||||
return cmd_ut_category("bootm", "bootm_test_", tests, n_ents,
|
||||
argc, argv);
|
||||
}
|
||||
@@ -88,6 +88,7 @@ static struct cmd_tbl cmd_ut_sub[] = {
|
||||
"", ""),
|
||||
U_BOOT_CMD_MKENT(bloblist, CONFIG_SYS_MAXARGS, 1, do_ut_bloblist,
|
||||
"", ""),
|
||||
U_BOOT_CMD_MKENT(bootm, CONFIG_SYS_MAXARGS, 1, do_ut_bootm, "", ""),
|
||||
U_BOOT_CMD_MKENT(str, CONFIG_SYS_MAXARGS, 1, do_ut_str,
|
||||
"", ""),
|
||||
#endif
|
||||
|
||||
2
test/env/hashtable.c
vendored
2
test/env/hashtable.c
vendored
@@ -80,7 +80,7 @@ static int htab_create_delete(struct unit_test_state *uts,
|
||||
ut_asserteq_str(key, ritem->key);
|
||||
ut_asserteq_str(key, ritem->data);
|
||||
|
||||
ut_asserteq(1, hdelete_r(key, htab, 0));
|
||||
ut_asserteq(0, hdelete_r(key, htab, 0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user