From 6ec5178c0ef7c336ac41335aedc63f7f080a11a6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:30 -0600 Subject: [PATCH 01/60] test: Skip flat-tree tests if devicetree is not used Many tests don't actually use the devicetree at all so there is no point in running the tests both with livetree and flat tree. Check for this and skip the flat tree test in that case. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- test/test-main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test-main.c b/test/test-main.c index 2a3b2ba364a..778bf0a18a0 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -476,7 +476,8 @@ static int ut_run_test_live_flat(struct unit_test_state *uts, * (for sandbox we handle this by copying the tree, but not for other * boards) */ - if (!(test->flags & UT_TESTF_LIVE_TREE) && + if ((test->flags & UT_TESTF_SCAN_FDT) && + !(test->flags & UT_TESTF_LIVE_TREE) && (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || !(test->flags & UT_TESTF_OTHER_FDT)) && (!runs || ut_test_run_on_flattree(test)) && From 3c2e531cb8f19841cb734c18623832c73d16c26b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:31 -0600 Subject: [PATCH 02/60] bootstd: Correct the name of the QEMU bootmeth This does not relate to sandbox. Correct the name. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/bootmeth_qfw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootmeth_qfw.c b/boot/bootmeth_qfw.c index ecd4b082fd2..8ebbc3ebcd5 100644 --- a/boot/bootmeth_qfw.c +++ b/boot/bootmeth_qfw.c @@ -76,7 +76,7 @@ static int qfw_bootmeth_bind(struct udevice *dev) { struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); - plat->desc = "Sandbox boot for testing"; + plat->desc = "QEMU boot using firmware interface"; return 0; } From 4de979f6646d05d13572ecd2b652f0358dfa5de6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:32 -0600 Subject: [PATCH 03/60] bootstd: Use bootdev instead of bootdevice It seems better to call this a 'bootdev' since this is name used in the documentation. The older 'Bootdevice' name is no-longer used and may cause confusion with the 'bootdevice' environment variable. Update throughout to use bootdev. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/bootflow.c | 4 ++-- drivers/mmc/mmc_bootdev.c | 2 +- drivers/scsi/scsi_bootdev.c | 2 +- drivers/usb/host/usb_bootdev.c | 2 +- fs/sandbox/host_bootdev.c | 2 +- include/bootdev.h | 2 +- include/bootflow.h | 2 +- net/eth_bootdev.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/boot/bootflow.c b/boot/bootflow.c index 8f2cb876bb4..487552fa28c 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -315,14 +315,14 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow) /* If we got a valid bootflow, return it */ if (!ret) { - log_debug("Bootdevice '%s' part %d method '%s': Found bootflow\n", + log_debug("Bootdev '%s' part %d method '%s': Found bootflow\n", dev->name, iter->part, iter->method->name); return 0; } /* Unless there is nothing more to try, move to the next device */ else if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) { - log_debug("Bootdevice '%s' part %d method '%s': Error %d\n", + log_debug("Bootdev '%s' part %d method '%s': Error %d\n", dev->name, iter->part, iter->method->name, ret); /* * For 'all' we return all bootflows, even diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c index b57b8a62276..55ecead2ddf 100644 --- a/drivers/mmc/mmc_bootdev.c +++ b/drivers/mmc/mmc_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for MMC + * Bootdev for MMC * * Copyright 2021 Google LLC * Written by Simon Glass diff --git a/drivers/scsi/scsi_bootdev.c b/drivers/scsi/scsi_bootdev.c index 991013fe1ef..218221fa306 100644 --- a/drivers/scsi/scsi_bootdev.c +++ b/drivers/scsi/scsi_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for USB + * Bootdev for SCSI * * Copyright 2021 Google LLC * Written by Simon Glass diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c index 06e8f61aa1c..7fa1c601dff 100644 --- a/drivers/usb/host/usb_bootdev.c +++ b/drivers/usb/host/usb_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for USB + * Bootdev for USB * * Copyright 2021 Google LLC * Written by Simon Glass diff --git a/fs/sandbox/host_bootdev.c b/fs/sandbox/host_bootdev.c index 0d12ee4ef74..3ef53627608 100644 --- a/fs/sandbox/host_bootdev.c +++ b/fs/sandbox/host_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for MMC + * Bootdev for sandbox host * * Copyright 2021 Google LLC * Written by Simon Glass diff --git a/include/bootdev.h b/include/bootdev.h index e72ef3650f7..1533adfe506 100644 --- a/include/bootdev.h +++ b/include/bootdev.h @@ -200,7 +200,7 @@ void bootdev_clear_bootflows(struct udevice *dev); * All fields in @bflow must be set up. Note that @bflow->dev is used to add the * bootflow to that device. * - * @dev: Bootdevice device to add to + * @dev: Bootdev device to add to * @bflow: Bootflow to add. Note that fields within bflow must be allocated * since this function takes over ownership of these. This functions makes * a copy of @bflow itself (without allocating its fields again), so the diff --git a/include/bootflow.h b/include/bootflow.h index f20f575030f..018d021b810 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -58,7 +58,7 @@ enum bootflow_flags_t { * * @bm_node: Points to siblings in the same bootdev * @glob_node: Points to siblings in the global list (all bootdev) - * @dev: Bootdevice device which produced this bootflow + * @dev: Bootdev device which produced this bootflow * @blk: Block device which contains this bootflow, NULL if this is a network * device or sandbox 'host' device * @part: Partition number (0 for whole device) diff --git a/net/eth_bootdev.c b/net/eth_bootdev.c index f7b4196f78d..869adf8cbbd 100644 --- a/net/eth_bootdev.c +++ b/net/eth_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for ethernet (uses PXE) + * Bootdev for ethernet (uses PXE) * * Copyright 2021 Google LLC * Written by Simon Glass From 2270c3639ae355e298f245ec1c9ba9f560bc7e5c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:33 -0600 Subject: [PATCH 04/60] bootstd: Correct baudrate typo This is a copy error. Fix it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/bootmeth-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 701ee8ad1c8..eeded08dd42 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -395,7 +395,7 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow, /** * on_bootmeths() - Update the bootmeth order * - * This will check for a valid baudrate and only apply it if valid. + * This will check for a valid list of bootmeths and only apply it if valid. */ static int on_bootmeths(const char *name, const char *value, enum env_op op, int flags) From f4a91655c36a1a5fad2ea879ff3ab9217cd21337 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:34 -0600 Subject: [PATCH 05/60] bootstd: Allow storing the OS command line in the bootflow Some operating systems have a command line which can be adjusted before booting. Store this in the bootflow so it can be controlled within U-Boot. Fix up the example output while we are here, since there are a few new items. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- cmd/bootflow.c | 6 ++++++ doc/usage/cmd/bootflow.rst | 5 ++++- include/bootflow.h | 2 ++ test/boot/bootflow.c | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 5c61286a2a7..ddb168c7039 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -324,6 +324,12 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc, printf("Buffer: %lx\n", (ulong)map_to_sysmem(bflow->buf)); printf("Size: %x (%d bytes)\n", bflow->size, bflow->size); printf("OS: %s\n", bflow->os_name ? bflow->os_name : "(none)"); + printf("Cmdline: "); + if (bflow->cmdline) + puts(bflow->cmdline); + else + puts("(none)"); + putc('\n'); printf("Logo: %s\n", bflow->logo ? simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)"); if (bflow->logo) { diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst index 8590efca218..907d44ad9f9 100644 --- a/doc/usage/cmd/bootflow.rst +++ b/doc/usage/cmd/bootflow.rst @@ -258,7 +258,6 @@ displayed and booted:: Name: mmc@7e202000.bootdev.part_2 Device: mmc@7e202000.bootdev Block dev: mmc@7e202000.blk - Sequence: 1 Method: distro State: ready Partition: 2 @@ -266,6 +265,10 @@ displayed and booted:: Filename: extlinux/extlinux.conf Buffer: 3db7ae88 Size: 232 (562 bytes) + OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + Cmdline: (none) + Logo: (none) + FDT: Error: 0 U-Boot> bootflow boot ** Booting bootflow 'smsc95xx_eth.bootdev.0' diff --git a/include/bootflow.h b/include/bootflow.h index 018d021b810..a1c16ab93b7 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -81,6 +81,7 @@ enum bootflow_flags_t { * @fdt_size: Size of FDT file * @fdt_addr: Address of loaded fdt * @flags: Flags for the bootflow (see enum bootflow_flags_t) + * @cmdline: OS command line, or NULL if not known (allocated) */ struct bootflow { struct list_head bm_node; @@ -104,6 +105,7 @@ struct bootflow { int fdt_size; ulong fdt_addr; int flags; + char *cmdline; }; /** diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 2b5f87d7f09..f7ebf9d7f27 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -226,6 +226,7 @@ static int bootflow_cmd_info(struct unit_test_state *uts) ut_assert_nextlinen("Buffer: "); ut_assert_nextline("Size: 253 (595 bytes)"); ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)"); + ut_assert_nextline("Cmdline: (none)"); ut_assert_nextline("Logo: (none)"); ut_assert_nextline("FDT: "); ut_assert_nextline("Error: 0"); From d42243fe21c8847cd5c6db4e11b2aee660448451 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:35 -0600 Subject: [PATCH 06/60] bootstd: Use the bootargs env var for changing the cmdline The "bootargs" environment variable is used to set the command-line arguments to pass to the OS. Use this same mechanism with bootstd as well. When the variable is updated, it is written to the current bootflow. When the current bootflow is updated, the environment variable is updated too. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/bootflow.c | 58 ++++++++++++++++++++++++++++++++++++++++++ cmd/bootflow.c | 6 +++++ include/env_callback.h | 6 +++-- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/boot/bootflow.c b/boot/bootflow.c index 487552fa28c..b820678d41a 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -552,3 +553,60 @@ int bootflow_iter_check_system(const struct bootflow_iter *iter) return -ENOTSUPP; } + +/** + * bootflow_cmdline_set() - Set the command line for a bootflow + * + * @value: New command-line string + * Returns 0 if OK, -ENOENT if no current bootflow, -ENOMEM if out of memory + */ +int bootflow_cmdline_set(struct bootflow *bflow, const char *value) +{ + char *cmdline = NULL; + + if (value) { + cmdline = strdup(value); + if (!cmdline) + return -ENOMEM; + } + + free(bflow->cmdline); + bflow->cmdline = cmdline; + + return 0; +} + +#ifdef CONFIG_BOOTSTD_FULL +/** + * on_bootargs() - Update the cmdline of a bootflow + */ +static int on_bootargs(const char *name, const char *value, enum env_op op, + int flags) +{ + struct bootstd_priv *std; + struct bootflow *bflow; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return 0; + bflow = std->cur_bootflow; + if (!bflow) + return 0; + + switch (op) { + case env_op_create: + case env_op_overwrite: + ret = bootflow_cmdline_set(bflow, value); + if (ret && ret != ENOENT) + return 1; + return 0; + case env_op_delete: + bootflow_cmdline_set(bflow, NULL); + fallthrough; + default: + return 0; + } +} +U_BOOT_ENV_CALLBACK(bootargs, on_bootargs); +#endif diff --git a/cmd/bootflow.c b/cmd/bootflow.c index ddb168c7039..f33db7be5f2 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -288,6 +288,12 @@ static int do_bootflow_select(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_FAILURE; } std->cur_bootflow = found; + if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) { + if (env_set("bootargs", found->cmdline)) { + printf("Cannot set bootargs\n"); + return CMD_RET_FAILURE; + } + } return 0; } diff --git a/include/env_callback.h b/include/env_callback.h index a9a14f2a84a..23bc650c162 100644 --- a/include/env_callback.h +++ b/include/env_callback.h @@ -60,8 +60,10 @@ #define NET6_CALLBACKS #endif -#ifdef CONFIG_BOOTSTD -#define BOOTSTD_CALLBACK "bootmeths:bootmeths," +#ifdef CONFIG_BOOTSTD_FULL +#define BOOTSTD_CALLBACK \ + "bootmeths:bootmeths," \ + "bootargs:bootargs," #else #define BOOTSTD_CALLBACK #endif From 43b6fa9c1464e0918004dc03be03acd3c40bcc25 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:36 -0600 Subject: [PATCH 07/60] bootstd: Allow storing x86 setup information On x86 boards Linux uses a block of binary data to provide information about the command line, memory map, etc. Provide a way to store this in the bootflow so it can be passed on to the OS. No attempt is made to generalise the code, since other archs don't need this information. The field is present always, though, to avoid needing accessors or #ifdefs when building code on other archs. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- cmd/bootflow.c | 2 ++ include/bootflow.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/cmd/bootflow.c b/cmd/bootflow.c index f33db7be5f2..bf30087c7c4 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -336,6 +336,8 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc, else puts("(none)"); putc('\n'); + if (bflow->x86_setup) + printf("X86 setup: %p\n", bflow->x86_setup); printf("Logo: %s\n", bflow->logo ? simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)"); if (bflow->logo) { diff --git a/include/bootflow.h b/include/bootflow.h index a1c16ab93b7..f263173c4da 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -82,6 +82,7 @@ enum bootflow_flags_t { * @fdt_addr: Address of loaded fdt * @flags: Flags for the bootflow (see enum bootflow_flags_t) * @cmdline: OS command line, or NULL if not known (allocated) + * @x86_setup: Pointer to x86 setup block inside @buf, NULL if not present */ struct bootflow { struct list_head bm_node; @@ -106,6 +107,7 @@ struct bootflow { ulong fdt_addr; int flags; char *cmdline; + char *x86_setup; }; /** From 347a845aec18561d36299b0735c47c2b3f45bc71 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:37 -0600 Subject: [PATCH 08/60] bdinfo: Show information about the serial port It is useful to see the detailed setting of the serial port, e.g. to allow setting up earlycon or console for Linux. Add this output to the 'bdinfo' command. Signed-off-by: Simon Glass Reviewed-by: Bin Meng [bmeng: squashed in 20230716033929.253357-2-sjg@chromium.org] Signed-off-by: Bin Meng --- cmd/bdinfo.c | 21 +++++++++++++++++++++ test/cmd/bdinfo.c | 14 ++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 365357ca545..dab73f1d93c 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,25 @@ static void show_video_info(void) } } +static void print_serial(struct udevice *dev) +{ + struct serial_device_info info; + int ret; + + if (!dev || !IS_ENABLED(CONFIG_DM_SERIAL)) + return; + + ret = serial_getinfo(dev, &info); + if (ret) + return; + + bdinfo_print_num_l("serial addr", info.addr); + bdinfo_print_num_l(" width", info.reg_width); + bdinfo_print_num_l(" shift", info.reg_shift); + bdinfo_print_num_l(" offset", info.reg_offset); + bdinfo_print_num_l(" clock", info.clock); +} + int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct bd_info *bd = gd->bd; @@ -151,6 +171,7 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) if (IS_ENABLED(CONFIG_OF_REAL)) printf("devicetree = %s\n", fdtdec_get_srcname()); } + print_serial(gd->cur_serial_dev); arch_print_bdinfo(); diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c index cddf1a46d49..6480393fd5d 100644 --- a/test/cmd/bdinfo.c +++ b/test/cmd/bdinfo.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -191,6 +192,19 @@ static int bdinfo_test_move(struct unit_test_state *uts) ut_assert_nextline("devicetree = %s", fdtdec_get_srcname()); } + if (IS_ENABLED(CONFIG_DM_SERIAL)) { + struct serial_device_info info; + + ut_assertnonnull(gd->cur_serial_dev); + ut_assertok(serial_getinfo(gd->cur_serial_dev, &info)); + + ut_assertok(test_num_l(uts, "serial addr", info.addr)); + ut_assertok(test_num_l(uts, " width", info.reg_width)); + ut_assertok(test_num_l(uts, " shift", info.reg_shift)); + ut_assertok(test_num_l(uts, " offset", info.reg_offset)); + ut_assertok(test_num_l(uts, " clock", info.clock)); + } + ut_assertok(ut_check_console_end(uts)); return 0; From d07861cc7aa605a64c83bc7fbe1340bc31b2c2cf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:38 -0600 Subject: [PATCH 09/60] bootstd: Add a function to update a command line The Linux command line consists of a number of words with optional values. At present U-Boot allows this to be changed using the bootargs environment variable. But this is quite painful, since the command line can be very long. Add a function which can adjust a single field in the command line, so that it is easier to make changes before booting. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/bootflow.c | 191 +++++++++++++++++++++++++++++++++++++++++++ include/bootflow.h | 40 +++++++++ test/boot/bootflow.c | 154 ++++++++++++++++++++++++++++++++++ 3 files changed, 385 insertions(+) diff --git a/boot/bootflow.c b/boot/bootflow.c index b820678d41a..26f26aee38a 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -610,3 +610,194 @@ static int on_bootargs(const char *name, const char *value, enum env_op op, } U_BOOT_ENV_CALLBACK(bootargs, on_bootargs); #endif + +/** + * copy_in() - Copy a string into a cmdline buffer + * + * @buf: Buffer to copy into + * @end: End of buffer (pointer to char after the end) + * @arg: String to copy from + * @len: Number of chars to copy from @arg (note that this is not usually the + * sane as strlen(arg) since the string may contain following arguments) + * @new_val: Value to put after arg, or BOOTFLOWCL_EMPTY to use an empty value + * with no '=' sign + * Returns: Number of chars written to @buf + */ +static int copy_in(char *buf, char *end, const char *arg, int len, + const char *new_val) +{ + char *to = buf; + + /* copy the arg name */ + if (to + len >= end) + return -E2BIG; + memcpy(to, arg, len); + to += len; + + if (new_val == BOOTFLOWCL_EMPTY) { + /* no value */ + } else { + bool need_quote = strchr(new_val, ' '); + len = strlen(new_val); + + /* need space for value, equals sign and maybe two quotes */ + if (to + 1 + (need_quote ? 2 : 0) + len >= end) + return -E2BIG; + *to++ = '='; + if (need_quote) + *to++ = '"'; + memcpy(to, new_val, len); + to += len; + if (need_quote) + *to++ = '"'; + } + + return to - buf; +} + +int cmdline_set_arg(char *buf, int maxlen, const char *cmdline, + const char *set_arg, const char *new_val, int *posp) +{ + bool found_arg = false; + const char *from; + char *to, *end; + int set_arg_len; + char empty = '\0'; + int ret; + + from = cmdline ?: ∅ + + /* check if the value has quotes inside */ + if (new_val && new_val != BOOTFLOWCL_EMPTY && strchr(new_val, '"')) + return -EBADF; + + set_arg_len = strlen(set_arg); + for (to = buf, end = buf + maxlen; *from;) { + const char *val, *arg_end, *val_end, *p; + bool in_quote; + + if (to >= end) + return -E2BIG; + while (*from == ' ') + from++; + if (!*from) + break; + + /* find the end of this arg */ + val = NULL; + arg_end = NULL; + val_end = NULL; + in_quote = false; + for (p = from;; p++) { + if (in_quote) { + if (!*p) + return -EINVAL; + if (*p == '"') + in_quote = false; + continue; + } + if (*p == '=') { + arg_end = p; + val = p + 1; + } else if (*p == '"') { + in_quote = true; + } else if (!*p || *p == ' ') { + val_end = p; + if (!arg_end) + arg_end = p; + break; + } + } + /* + * At this point val_end points to the end of the value, or the + * last char after the arg name, if there is no label. + * arg_end is the char after the arg name + * val points to the value, or NULL if there is none + * char after the value. + * + * fred=1234 + * ^ ^^ ^ + * from || | + * / \ \ + * arg_end val val_end + */ + log_debug("from %s arg_end %ld val %ld val_end %ld\n", from, + (long)(arg_end - from), (long)(val - from), + (long)(val_end - from)); + + if (to != buf) { + if (to >= end) + return -E2BIG; + *to++ = ' '; + } + + /* if this is the target arg, update it */ + if (!strncmp(from, set_arg, arg_end - from)) { + if (!buf) { + bool has_quote = val_end[-1] == '"'; + + /* + * exclude any start/end quotes from + * calculations + */ + if (!val) + val = val_end; + *posp = val - cmdline + has_quote; + return val_end - val - 2 * has_quote; + } + found_arg = true; + if (!new_val) { + /* delete this arg */ + from = val_end + (*val_end == ' '); + log_debug("delete from: %s\n", from); + if (to != buf) + to--; /* drop the space we added */ + continue; + } + + ret = copy_in(to, end, from, arg_end - from, new_val); + if (ret < 0) + return ret; + to += ret; + + /* if not the target arg, copy it unchanged */ + } else if (to) { + int len; + + len = val_end - from; + if (to + len >= end) + return -E2BIG; + memcpy(to, from, len); + to += len; + } + from = val_end; + } + + /* If we didn't find the arg, add it */ + if (!found_arg) { + /* trying to delete something that is not there */ + if (!new_val || !buf) + return -ENOENT; + if (to >= end) + return -E2BIG; + + /* add a space to separate it from the previous arg */ + if (to != buf && to[-1] != ' ') + *to++ = ' '; + ret = copy_in(to, end, set_arg, set_arg_len, new_val); + log_debug("ret=%d, to: %s buf: %s\n", ret, to, buf); + if (ret < 0) + return ret; + to += ret; + } + + /* delete any trailing space */ + if (to > buf && to[-1] == ' ') + to--; + + if (to >= end) + return -E2BIG; + *to++ = '\0'; + + return to - buf; +} diff --git a/include/bootflow.h b/include/bootflow.h index f263173c4da..8db875adf61 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -444,4 +444,44 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node); int bootflow_menu_run(struct bootstd_priv *std, bool text_mode, struct bootflow **bflowp); +#define BOOTFLOWCL_EMPTY ((void *)1) + +/** + * cmdline_set_arg() - Update or read an argument in a cmdline string + * + * Handles updating a single arg in a cmdline string, returning it in a supplied + * buffer; also reading an arg from a cmdline string + * + * When updating, consecutive spaces are squashed as are spaces at the start and + * end. + * + * @buf: Working buffer to use (initial contents are ignored). Use NULL when + * reading + * @maxlen: Length of working buffer. Use 0 when reading + * @cmdline: Command line to update, in the form: + * + * fred mary= jane=123 john="has spaces" + * + * @set_arg: Argument to set or read (may or may not exist) + * @new_val: Value for the new argument. May not include quotes (") but may + * include embedded spaces, in which case it will be quoted when added to the + * command line. Use NULL to delete the argument from @cmdline, BOOTFLOWCL_EMPTY + * to set it to an empty value (no '=' sign after arg), "" to add an '=' sign + * but with an empty value. Use NULL when reading. + * @posp: Ignored when setting an argument; when getting an argument, returns + * the start position of its value in @cmdline, after the first quote, if any + * + * Return: + * For updating: + * length of new buffer (including \0 terminator) on success, -ENOENT if + * @new_val is NULL and @set_arg does not exist in @from, -EINVAL if a + * quoted arg-value in @from is not terminated with a quote, -EBADF if + * @new_val has spaces but does not start and end with quotes (or it has + * quotes in the middle of the string), -E2BIG if @maxlen is too small + * For reading: + * length of arg value (excluding quotes), -ENOENT if not found + */ +int cmdline_set_arg(char *buf, int maxlen, const char *cmdline, + const char *set_arg, const char *new_val, int *posp); + #endif diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index f7ebf9d7f27..ead71172e12 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -683,3 +683,157 @@ static int bootflow_menu_theme(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_menu_theme, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/** + * check_arg() - Check both the normal case and the buffer-overflow case + * + * @uts: Unit-test state + * @expect_ret: Expected return value (i.e. buffer length) + * @expect_str: String expected to be returned + * @buf: Buffer to use + * @from: Original cmdline to update + * @arg: Argument to update (e.g. "console") + * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present, + * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add + * it without any value ("initrd") + */ +static int check_arg(struct unit_test_state *uts, int expect_ret, + const char *expect_str, char *buf, const char *from, + const char *arg, const char *val) +{ + /* check for writing outside the reported bounds */ + buf[expect_ret] = '['; + ut_asserteq(expect_ret, + cmdline_set_arg(buf, expect_ret, from, arg, val, NULL)); + ut_asserteq_str(expect_str, buf); + ut_asserteq('[', buf[expect_ret]); + + /* do the test again but with one less byte in the buffer */ + ut_asserteq(-E2BIG, cmdline_set_arg(buf, expect_ret - 1, from, arg, + val, NULL)); + + return 0; +} + +/* Test of bootflow_cmdline_set_arg() */ +static int test_bootflow_cmdline_set(struct unit_test_state *uts) +{ + char buf[50]; + const int size = sizeof(buf); + + /* + * note that buffer-overflow tests are immediately each test case, just + * top keep the code together + */ + + /* add an arg that doesn't already exist, starting from empty */ + ut_asserteq(-ENOENT, cmdline_set_arg(buf, size, NULL, "me", NULL, + NULL)); + + ut_assertok(check_arg(uts, 3, "me", buf, NULL, "me", BOOTFLOWCL_EMPTY)); + ut_assertok(check_arg(uts, 4, "me=", buf, NULL, "me", "")); + ut_assertok(check_arg(uts, 8, "me=fred", buf, NULL, "me", "fred")); + + /* add an arg that doesn't already exist, starting from non-empty */ + ut_assertok(check_arg(uts, 11, "arg=123 me", buf, "arg=123", "me", + BOOTFLOWCL_EMPTY)); + ut_assertok(check_arg(uts, 12, "arg=123 me=", buf, "arg=123", "me", + "")); + ut_assertok(check_arg(uts, 16, "arg=123 me=fred", buf, "arg=123", "me", + "fred")); + + /* update an arg at the start */ + ut_assertok(check_arg(uts, 1, "", buf, "arg=123", "arg", NULL)); + ut_assertok(check_arg(uts, 4, "arg", buf, "arg=123", "arg", + BOOTFLOWCL_EMPTY)); + ut_assertok(check_arg(uts, 5, "arg=", buf, "arg=123", "arg", "")); + ut_assertok(check_arg(uts, 6, "arg=1", buf, "arg=123", "arg", "1")); + ut_assertok(check_arg(uts, 9, "arg=1234", buf, "arg=123", "arg", + "1234")); + + /* update an arg at the end */ + ut_assertok(check_arg(uts, 5, "mary", buf, "mary arg=123", "arg", + NULL)); + ut_assertok(check_arg(uts, 9, "mary arg", buf, "mary arg=123", "arg", + BOOTFLOWCL_EMPTY)); + ut_assertok(check_arg(uts, 10, "mary arg=", buf, "mary arg=123", "arg", + "")); + ut_assertok(check_arg(uts, 11, "mary arg=1", buf, "mary arg=123", "arg", + "1")); + ut_assertok(check_arg(uts, 14, "mary arg=1234", buf, "mary arg=123", + "arg", "1234")); + + /* update an arg in the middle */ + ut_assertok(check_arg(uts, 16, "mary=abc john=2", buf, + "mary=abc arg=123 john=2", "arg", NULL)); + ut_assertok(check_arg(uts, 20, "mary=abc arg john=2", buf, + "mary=abc arg=123 john=2", "arg", + BOOTFLOWCL_EMPTY)); + ut_assertok(check_arg(uts, 21, "mary=abc arg= john=2", buf, + "mary=abc arg=123 john=2", "arg", "")); + ut_assertok(check_arg(uts, 22, "mary=abc arg=1 john=2", buf, + "mary=abc arg=123 john=2", "arg", "1")); + ut_assertok(check_arg(uts, 25, "mary=abc arg=1234 john=2", buf, + "mary=abc arg=123 john=2", "arg", "1234")); + + /* handle existing args with quotes */ + ut_assertok(check_arg(uts, 16, "mary=\"abc\" john", buf, + "mary=\"abc\" arg=123 john", "arg", NULL)); + + /* handle existing args with quoted spaces */ + ut_assertok(check_arg(uts, 20, "mary=\"abc def\" john", buf, + "mary=\"abc def\" arg=123 john", "arg", NULL)); + + ut_assertok(check_arg(uts, 34, "mary=\"abc def\" arg=123 john def=4", + buf, "mary=\"abc def\" arg=123 john", "def", + "4")); + + /* quote at the start */ + ut_asserteq(-EBADF, cmdline_set_arg(buf, size, + "mary=\"abc def\" arg=\"123 456\"", + "arg", "\"4 5 6", NULL)); + + /* quote at the end */ + ut_asserteq(-EBADF, cmdline_set_arg(buf, size, + "mary=\"abc def\" arg=\"123 456\"", + "arg", "4 5 6\"", NULL)); + + /* quote in the middle */ + ut_asserteq(-EBADF, cmdline_set_arg(buf, size, + "mary=\"abc def\" arg=\"123 456\"", + "arg", "\"4 \"5 6\"", NULL)); + + /* handle updating a quoted arg */ + ut_assertok(check_arg(uts, 27, "mary=\"abc def\" arg=\"4 5 6\"", buf, + "mary=\"abc def\" arg=\"123 456\"", "arg", + "4 5 6")); + + /* changing a quoted arg to a non-quoted arg */ + ut_assertok(check_arg(uts, 23, "mary=\"abc def\" arg=789", buf, + "mary=\"abc def\" arg=\"123 456\"", "arg", + "789")); + + /* changing a non-quoted arg to a quoted arg */ + ut_assertok(check_arg(uts, 29, "mary=\"abc def\" arg=\"456 789\"", buf, + "mary=\"abc def\" arg=123", "arg", "456 789")); + + /* handling of spaces */ + ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123")); + ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123")); + ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john ", "arg", + "123")); + ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john arg=123 ", + "arg", "123")); + ut_assertok(check_arg(uts, 18, "john arg=123 mary", buf, + " john arg=123 mary ", "arg", "123")); + + /* unchanged arg */ + ut_assertok(check_arg(uts, 3, "me", buf, "me", "me", BOOTFLOWCL_EMPTY)); + + /* arg which starts with the same name */ + ut_assertok(check_arg(uts, 28, "mary=abc johnathon=2 john=3", buf, + "mary=abc johnathon=2 john=1", "john", "3")); + + return 0; +} +BOOTSTD_TEST(test_bootflow_cmdline_set, 0); From 82c0938f1d3befdd7dd1a1bda3b0a02b219abb5d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:39 -0600 Subject: [PATCH 10/60] bootstd: Add support for updating elements of the cmdline Add a bootflow command to update the command line more easily. This allows changing a particular parameter rather than editing a very long strings. It is also easier to handle with scripting. The new 'bootflow cmdline' command allows getting and setting single parameters. Fix up the example output while we are here, since there are a few new items. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/bootflow.c | 53 ++++++++++++++++++ cmd/bootflow.c | 70 +++++++++++++++++++++++- doc/usage/cmd/bootflow.rst | 22 +++++++- include/bootflow.h | 42 +++++++++++++++ test/boot/bootflow.c | 108 +++++++++++++++++++++++++++++++++++++ 5 files changed, 293 insertions(+), 2 deletions(-) diff --git a/boot/bootflow.c b/boot/bootflow.c index 26f26aee38a..8c649e8e66c 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -801,3 +801,56 @@ int cmdline_set_arg(char *buf, int maxlen, const char *cmdline, return to - buf; } + +int bootflow_cmdline_set_arg(struct bootflow *bflow, const char *set_arg, + const char *new_val, bool set_env) +{ + char buf[2048]; + char *cmd = NULL; + int ret; + + ret = cmdline_set_arg(buf, sizeof(buf), bflow->cmdline, set_arg, + new_val, NULL); + if (ret < 0) + return ret; + + ret = bootflow_cmdline_set(bflow, buf); + if (*buf) { + cmd = strdup(buf); + if (!cmd) + return -ENOMEM; + } + free(bflow->cmdline); + bflow->cmdline = cmd; + + if (set_env) { + ret = env_set("bootargs", bflow->cmdline); + if (ret) + return ret; + } + + return 0; +} + +int cmdline_get_arg(const char *cmdline, const char *arg, int *posp) +{ + int ret; + + ret = cmdline_set_arg(NULL, 1, cmdline, arg, NULL, posp); + + return ret; +} + +int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg, + const char **val) +{ + int ret; + int pos; + + ret = cmdline_get_arg(bflow->cmdline, arg, &pos); + if (ret < 0) + return ret; + *val = bflow->cmdline + pos; + + return ret; +} diff --git a/cmd/bootflow.c b/cmd/bootflow.c index bf30087c7c4..ab00e4a19e1 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -431,6 +431,72 @@ static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } + +static int do_bootflow_cmdline(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct bootflow *bflow; + const char *op, *arg, *val = NULL; + int ret; + + if (argc < 3) + return CMD_RET_USAGE; + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + + bflow = std->cur_bootflow; + if (!bflow) { + printf("No bootflow selected\n"); + return CMD_RET_FAILURE; + } + + op = argv[1]; + arg = argv[2]; + if (*op == 's') { + if (argc < 4) + return CMD_RET_USAGE; + val = argv[3]; + } + + switch (*op) { + case 'c': /* clear */ + val = ""; + fallthrough; + case 's': /* set */ + case 'd': /* delete */ + ret = bootflow_cmdline_set_arg(bflow, arg, val, true); + break; + case 'g': /* get */ + ret = bootflow_cmdline_get_arg(bflow, arg, &val); + if (ret >= 0) + printf("%.*s\n", ret, val); + break; + } + switch (ret) { + case -E2BIG: + printf("Argument too long\n"); + break; + case -ENOENT: + printf("Argument not found\n"); + break; + case -EINVAL: + printf("Mismatched quotes\n"); + break; + case -EBADF: + printf("Value must be quoted\n"); + break; + default: + if (ret < 0) + printf("Unknown error: %dE\n", ret); + } + if (ret < 0) + return CMD_RET_FAILURE; + + return 0; +} #endif /* CONFIG_CMD_BOOTFLOW_FULL */ #ifdef CONFIG_SYS_LONGHELP @@ -441,7 +507,8 @@ static char bootflow_help_text[] = "bootflow select [|] - select a bootflow\n" "bootflow info [-d] - show info on current bootflow (-d dump bootflow)\n" "bootflow boot - boot current bootflow (or first available if none selected)\n" - "bootflow menu [-t] - show a menu of available bootflows"; + "bootflow menu [-t] - show a menu of available bootflows\n" + "bootflow cmdline [set|get|clear|delete] [] - update cmdline"; #else "scan - boot first available bootflow\n"; #endif @@ -455,5 +522,6 @@ U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text, U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info), U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot), U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu), + U_BOOT_SUBCMD_MKENT(cmdline, 4, 1, do_bootflow_cmdline), #endif ); diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst index 907d44ad9f9..07af789e670 100644 --- a/doc/usage/cmd/bootflow.rst +++ b/doc/usage/cmd/bootflow.rst @@ -13,7 +13,7 @@ Synopis bootflow select [] bootflow info [-d] bootflow boot - + bootflow cmdline [set|get|clear|delete] [] Description ----------- @@ -198,6 +198,26 @@ bootflow boot This boots the current bootflow. +bootflow cmdline +~~~~~~~~~~~~~~~~ + +Some bootmeths can obtain the OS command line since it is stored with the OS. +In that case, you can use `bootflow cmdline` to adjust this. The command line +is assumed to be in the format used by Linux, i.e. a space-separated set of +parameters with optional values, e.g. "noinitrd console=/dev/tty0". + +To change or add a parameter, use:: + + bootflow cmdline set + +To clear a parameter value to empty you can use "" for the value, or use:: + + bootflow cmdline clear + +To delete a parameter entirely, use:: + + bootflow cmdline delete + Example ------- diff --git a/include/bootflow.h b/include/bootflow.h index 8db875adf61..7a8595f3dfc 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -484,4 +484,46 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode, int cmdline_set_arg(char *buf, int maxlen, const char *cmdline, const char *set_arg, const char *new_val, int *posp); +/** + * bootflow_cmdline_set_arg() - Set a single argument for a bootflow + * + * Update the allocated cmdline and set the bootargs variable + * + * @bflow: Bootflow to update + * @arg: Argument to update (e.g. "console") + * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present, + * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add + * it without any value ("initrd") + * @set_env: true to set the "bootargs" environment variable too + * + * Return: 0 if OK, -ENOMEM if out of memory + */ +int bootflow_cmdline_set_arg(struct bootflow *bflow, const char *arg, + const char *val, bool set_env); + +/** + * cmdline_get_arg() - Read an argument from a cmdline + * + * @cmdline: Command line to read, in the form: + * + * fred mary= jane=123 john="has spaces" + * @arg: Argument to read (may or may not exist) + * @posp: Returns position of argument (after any leading quote) if present + * Return: Length of argument value excluding quotes if found, -ENOENT if not + * found + */ +int cmdline_get_arg(const char *cmdline, const char *arg, int *posp); + +/** + * bootflow_cmdline_get_arg() - Read an argument from a cmdline + * + * @bootflow: Bootflow to read from + * @arg: Argument to read (may or may not exist) + * @valp: Returns a pointer to the argument (after any leading quote) if present + * Return: Length of argument value excluding quotes if found, -ENOENT if not + * found + */ +int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg, + const char **val); + #endif diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index ead71172e12..8a4e090e9bc 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -837,3 +837,111 @@ static int test_bootflow_cmdline_set(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(test_bootflow_cmdline_set, 0); + +/* Test of bootflow_cmdline_set_arg() */ +static int bootflow_set_arg(struct unit_test_state *uts) +{ + struct bootflow s_bflow, *bflow = &s_bflow; + ulong mem_start; + + ut_assertok(env_set("bootargs", NULL)); + + mem_start = ut_check_delta(0); + + /* Do a simple sanity check. Rely on bootflow_cmdline() for the rest */ + bflow->cmdline = NULL; + ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", "123", false)); + ut_asserteq_str(bflow->cmdline, "fred=123"); + + ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "and here", false)); + ut_asserteq_str(bflow->cmdline, "fred=123 mary=\"and here\""); + + ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", NULL, false)); + ut_asserteq_str(bflow->cmdline, "fred=123"); + ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", NULL, false)); + ut_asserteq_ptr(bflow->cmdline, NULL); + + ut_asserteq(0, ut_check_delta(mem_start)); + + ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "here", true)); + ut_asserteq_str("mary=here", env_get("bootargs")); + ut_assertok(env_set("bootargs", NULL)); + + return 0; +} +BOOTSTD_TEST(bootflow_set_arg, 0); + +/* Test of bootflow_cmdline_get_arg() */ +static int bootflow_cmdline_get(struct unit_test_state *uts) +{ + int pos; + + /* empty string */ + ut_asserteq(-ENOENT, cmdline_get_arg("", "fred", &pos)); + + /* arg with empty value */ + ut_asserteq(0, cmdline_get_arg("fred= mary", "fred", &pos)); + ut_asserteq(5, pos); + + /* arg with a value */ + ut_asserteq(2, cmdline_get_arg("fred=23", "fred", &pos)); + ut_asserteq(5, pos); + + /* arg with a value */ + ut_asserteq(3, cmdline_get_arg("mary=1 fred=234", "fred", &pos)); + ut_asserteq(12, pos); + + /* arg with a value, after quoted arg */ + ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=234", "fred", &pos)); + ut_asserteq(16, pos); + + /* arg in the middle */ + ut_asserteq(0, cmdline_get_arg("mary=\"1 2\" fred john=23", "fred", + &pos)); + ut_asserteq(15, pos); + + /* quoted arg */ + ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=\"3 4\" john=23", + "fred", &pos)); + ut_asserteq(17, pos); + + /* args starting with the same prefix */ + ut_asserteq(1, cmdline_get_arg("mary=abc johnathon=3 john=1", "john", + &pos)); + ut_asserteq(26, pos); + + return 0; +} +BOOTSTD_TEST(bootflow_cmdline_get, 0); + +static int bootflow_cmdline(struct unit_test_state *uts) +{ + ut_assertok(run_command("bootflow scan mmc", 0)); + ut_assertok(run_command("bootflow sel 0", 0)); + console_record_reset_enable(); + + ut_asserteq(1, run_command("bootflow cmdline get fred", 0)); + ut_assert_nextline("Argument not found"); + ut_assert_console_end(); + + ut_asserteq(0, run_command("bootflow cmdline set fred 123", 0)); + ut_asserteq(0, run_command("bootflow cmdline get fred", 0)); + ut_assert_nextline("123"); + + ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0)); + ut_asserteq(0, run_command("bootflow cmdline get mary", 0)); + ut_assert_nextline("abc"); + + ut_asserteq(0, run_command("bootflow cmdline delete fred", 0)); + ut_asserteq(1, run_command("bootflow cmdline get fred", 0)); + ut_assert_nextline("Argument not found"); + + ut_asserteq(0, run_command("bootflow cmdline clear mary", 0)); + ut_asserteq(0, run_command("bootflow cmdline get mary", 0)); + ut_assert_nextline_empty(); + + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmdline, 0); From 1e5ff886575f5a870cb5f89e6c70b35160479f1f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:40 -0600 Subject: [PATCH 11/60] x86: qemu: Create a little more room for U-Boot We want to enable some of the more interesting bootstd features. Move SPL up to create some room for the larger U-Boot binary. Also disable microcode since this is not needed Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- configs/qemu-x86_64_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 6a539a859e0..7e9f90891a4 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -6,12 +6,13 @@ CONFIG_ENV_SIZE=0x40000 CONFIG_MAX_CPUS=2 CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx" -CONFIG_SPL_TEXT_BASE=0xfffd0000 +CONFIG_SPL_TEXT_BASE=0xfffd8000 CONFIG_DEBUG_UART_BASE=0x3f8 CONFIG_DEBUG_UART_CLOCK=1843200 CONFIG_X86_RUN_64BIT=y CONFIG_TARGET_QEMU_X86_64=y CONFIG_DEBUG_UART=y +# CONFIG_HAVE_MICROCODE is not set CONFIG_SMP=y CONFIG_GENERATE_PIRQ_TABLE=y CONFIG_GENERATE_MP_TABLE=y From 63b7ccbf9ffe9e79a6762a94eec74c8159f11a14 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:41 -0600 Subject: [PATCH 12/60] x86: qemu: Switch to standard boot Drop use of the distro boot script and use standard boot instead. Moving to a text-based environment would be desirable also, but requires additional work. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- configs/qemu-x86_64_defconfig | 2 +- configs/qemu-x86_defconfig | 2 +- include/configs/qemu-x86.h | 8 -------- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 7e9f90891a4..5dfad36ba52 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -20,7 +20,7 @@ CONFIG_X86_OFFSET_U_BOOT=0xfff00000 CONFIG_FIT=y CONFIG_SPL_LOAD_FIT=y CONFIG_SYS_MONITOR_BASE=0x01110000 -CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTSTD_DEFAULTS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_SHOW_BOOT_PROGRESS=y diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index a7c37b8b0e1..56788cd185f 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -9,7 +9,7 @@ CONFIG_SMP=y CONFIG_GENERATE_PIRQ_TABLE=y CONFIG_GENERATE_MP_TABLE=y CONFIG_FIT=y -CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTSTD_DEFAULTS=y CONFIG_BOOTSTAGE=y CONFIG_BOOTSTAGE_REPORT=y CONFIG_SHOW_BOOT_PROGRESS=y diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index 33263a46a40..3e5235291a2 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -12,14 +12,6 @@ #include -#define BOOT_TARGET_DEVICES(func) \ - func(USB, usb, 0) \ - func(SCSI, scsi, 0) \ - func(VIRTIO, virtio, 0) \ - func(IDE, ide, 0) \ - func(DHCP, dhcp, na) - -#include #include #define CFG_STD_DEVICES_SETTINGS "stdin=serial,i8042-kbd\0" \ From 33ebcb468109c40ef0dce262be00a4c161265b90 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:42 -0600 Subject: [PATCH 13/60] bootstd: Support automatically setting Linux parameters Some Linux parameters can be set automatically by U-Boot, if it knows the device being used. For example, since U-Boot knows the serial console being used, it can add parameters for earlycon and console. Add support for this. Note that this is an experimental feature and we will see how useful it turns out to be. It is very handy for ChromeOS, since otherwise it is very difficult to manually determine the UART address or port number, particularly in a script. Provide an example of how this is used with ChromeOS. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/bootflow.c | 33 +++++++++++++++++ cmd/bootflow.c | 5 ++- doc/usage/cmd/bootflow.rst | 75 +++++++++++++++++++++++++++++++++++++- include/bootflow.h | 12 ++++++ 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/boot/bootflow.c b/boot/bootflow.c index 8c649e8e66c..81b5829d5b3 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -854,3 +855,35 @@ int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg, return ret; } + +int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg) +{ + struct serial_device_info info; + char buf[50]; + int ret; + + ret = serial_getinfo(gd->cur_serial_dev, &info); + if (ret) + return ret; + + *buf = '\0'; + if (!strcmp("earlycon", arg)) { + snprintf(buf, sizeof(buf), + "uart8250,mmio32,%#lx,%dn8", info.addr, + info.baudrate); + } else if (!strcmp("console", arg)) { + snprintf(buf, sizeof(buf), + "ttyS0,%dn8", info.baudrate); + } + + if (!*buf) { + printf("Unknown param '%s\n", arg); + return -ENOENT; + } + + ret = bootflow_cmdline_set_arg(bflow, arg, buf, true); + if (ret) + return ret; + + return 0; +} diff --git a/cmd/bootflow.c b/cmd/bootflow.c index ab00e4a19e1..c0aa4f84fe8 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -474,6 +474,9 @@ static int do_bootflow_cmdline(struct cmd_tbl *cmdtp, int flag, int argc, if (ret >= 0) printf("%.*s\n", ret, val); break; + case 'a': /* auto */ + ret = bootflow_cmdline_auto(bflow, arg); + break; } switch (ret) { case -E2BIG: @@ -508,7 +511,7 @@ static char bootflow_help_text[] = "bootflow info [-d] - show info on current bootflow (-d dump bootflow)\n" "bootflow boot - boot current bootflow (or first available if none selected)\n" "bootflow menu [-t] - show a menu of available bootflows\n" - "bootflow cmdline [set|get|clear|delete] [] - update cmdline"; + "bootflow cmdline [set|get|clear|delete|auto] [] - update cmdline"; #else "scan - boot first available bootflow\n"; #endif diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst index 07af789e670..a8af1f8f603 100644 --- a/doc/usage/cmd/bootflow.rst +++ b/doc/usage/cmd/bootflow.rst @@ -13,7 +13,7 @@ Synopis bootflow select [] bootflow info [-d] bootflow boot - bootflow cmdline [set|get|clear|delete] [] + bootflow cmdline [set|get|clear|delete|auto] [] Description ----------- @@ -218,6 +218,16 @@ To delete a parameter entirely, use:: bootflow cmdline delete +Automatic parameters are available in a very few cases. You can use these to +add parmeters where the value is known by U-Boot. For example:: + + bootflow cmdline auto earlycon + bootflow cmdline auto console + +can be used to set the early console (or console) to a suitable value so that +output appears on the serial port. This is only supported by the 16550 serial +driver so far. + Example ------- @@ -450,6 +460,69 @@ Here is am example using the -e flag to see all errors:: (21 bootflows, 2 valid) U-Boot> +Here is an example of booting ChromeOS, adjusting the console beforehand. Note that +the cmdline is word-wrapped here and some parts of the command line are elided:: + + => bootfl list + Showing all bootflows + Seq Method State Uclass Part Name Filename + --- ----------- ------ -------- ---- ------------------------ ---------------- + 0 cros ready nvme 0 5.10.153-20434-g98da1eb2c + 1 efi ready nvme c nvme#0.blk#1.bootdev.part efi/boot/bootia32.efi + 2 efi ready usb_mass_ 2 usb_mass_storage.lun0.boo efi/boot/bootia32.efi + --- ----------- ------ -------- ---- ------------------------ ---------------- + (3 bootflows, 3 valid) + => bootfl sel 0 + => bootfl inf + Name: 5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023 + Device: nvme#0.blk#1.bootdev + Block dev: nvme#0.blk#1 + Method: cros + State: ready + Partition: 0 + Subdir: (none) + Filename: + Buffer: 737a1400 + Size: c47000 (12873728 bytes) + OS: ChromeOS + Cmdline: console= loglevel=7 init=/sbin/init cros_secure drm.trace=0x106 + root=/dev/dm-0 rootwait ro dm_verity.error_behavior=3 + dm_verity.max_bios=-1 dm_verity.dev_wait=1 + dm="1 vroot none ro 1,0 6348800 + verity payload=PARTUUID=799c935b-ae62-d143-8493-816fa936eef7/PARTNROFF=1 + hashtree=PARTUUID=799c935b-ae62-d143-8493-816fa936eef7/PARTNROFF=1 + hashstart=6348800 alg=sha256 + root_hexdigest=78cc462cd45aecbcd49ca476587b4dee59aa1b00ba5ece58e2c29ec9acd914ab + salt=8dec4dc80a75dd834a9b3175c674405e15b16a253fdfe05c79394ae5fd76f66a" + noinitrd vt.global_cursor_default=0 + kern_guid=799c935b-ae62-d143-8493-816fa936eef7 add_efi_memmap boot=local + noresume noswap i915.modeset=1 ramoops.ecc=1 tpm_tis.force=0 + intel_pmc_core.warn_on_s0ix_failures=1 i915.enable_guc=3 i915.enable_dc=4 + xdomain=0 swiotlb=65536 intel_iommu=on i915.enable_psr=1 + usb-storage.quirks=13fe:6500:u + X86 setup: 742e3400 + Logo: (none) + FDT: + Error: 0 + => bootflow cmdline auto earlycon + => bootflow cmd auto console + => print bootargs + bootargs=console=ttyS0,115200n8 loglevel=7 ... + usb-storage.quirks=13fe:6500:u earlycon=uart8250,mmio32,0xfe03e000,115200n8 + => bootflow cmd del console + => print bootargs + bootargs=loglevel=7 ... earlycon=uart8250,mmio32,0xfe03e000,115200n8 + => bootfl boot + ** Booting bootflow '5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023' with cros + Kernel command line: "loglevel=7 ... earlycon=uart8250,mmio32,0xfe03e000,115200n8" + + Starting kernel ... + + [ 0.000000] Linux version 5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) (Chromium OS 15.0_pre465103_p20220825-r4 clang version 15.0.0 (/var/tmp/portage/sys-devel/llvm-15.0_pre465103_p20220825-r4/work/llvm-15.0_pre465103_p20220825/clang db1978b67431ca3462ad8935bf662c15750b8252), LLD 15.0.0) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023 + [ 0.000000] Command line: loglevel=7 ... usb-storage.quirks=13fe:6500:u earlycon=uart8250,mmio32,0xfe03e000,115200n8 + [ 0.000000] x86/split lock detection: warning about user-space split_locks + + Return value ------------ diff --git a/include/bootflow.h b/include/bootflow.h index 7a8595f3dfc..4152577afb7 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -526,4 +526,16 @@ int cmdline_get_arg(const char *cmdline, const char *arg, int *posp); int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg, const char **val); +/** + * bootflow_cmdline_auto() - Automatically set a value for a known argument + * + * This handles a small number of known arguments, for Linux in particular. It + * adds suitable kernel parameters automatically, e.g. to enable the console. + * + * @bflow: Bootflow to update + * @arg: Name of argument to set (e.g. "earlycon" or "console") + * Return: 0 if OK -ve on error + */ +int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg); + #endif From c886557c18956dca5819920fd48d0d250c4b76a1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:43 -0600 Subject: [PATCH 14/60] x86: Add a function to boot a zimage Add a direct interface to booting a zimage, so that bootstd can call it without going through the command-line interface. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/include/asm/zimage.h | 17 ++++++++ arch/x86/lib/zimage.c | 82 ++++++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index 000b38ea899..966d7224eb1 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -72,4 +72,21 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, */ void zimage_dump(struct boot_params *base_ptr); +/** + * zboot_start() - Boot a zimage + * + * Boot a zimage, given the component parts + * + * @addr: Address where the bzImage is moved before booting, either + * BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR + * @base: Pointer to the boot parameters, typically at address + * DEFAULT_SETUP_BASE + * @initrd: Address of the initial ramdisk, or 0 if none + * @initrd_size: Size of the initial ramdisk, or 0 if none + * @cmdline: Command line to use for booting + * Return: -EFAULT on error (normally it does not return) + */ +int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, + ulong base, char *cmdline); + #endif diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index e5ea5129c1e..540d4d888bc 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -442,8 +443,7 @@ static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +static int zboot_load(void) { struct boot_params *base_ptr; @@ -460,31 +460,51 @@ static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, &state.load_address); if (!base_ptr) { puts("## Kernel loading failed ...\n"); - return CMD_RET_FAILURE; + return -EINVAL; } } state.base_ptr = base_ptr; - if (env_set_hex("zbootbase", (ulong)base_ptr) || + + return 0; +} + +static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (zboot_load()) + return CMD_RET_FAILURE; + + if (env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)) || env_set_hex("zbootaddr", state.load_address)) return CMD_RET_FAILURE; return 0; } +static int zboot_setup(void) +{ + struct boot_params *base_ptr = state.base_ptr; + int ret; + + ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, + 0, state.initrd_addr, state.initrd_size, + (ulong)state.cmdline); + if (ret) + return -EINVAL; + + return 0; +} + static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct boot_params *base_ptr = state.base_ptr; - int ret; if (!base_ptr) { printf("base is not set: use 'zboot load' first\n"); return CMD_RET_FAILURE; } - ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, - 0, state.initrd_addr, state.initrd_size, - (ulong)state.cmdline); - if (ret) { + if (zboot_setup()) { puts("Setting up boot parameters failed ...\n"); return CMD_RET_FAILURE; } @@ -501,8 +521,7 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +static int zboot_go(void) { struct boot_params *params = state.base_ptr; struct setup_header *hdr = ¶ms->hdr; @@ -522,11 +541,52 @@ static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, /* we assume that the kernel is in place */ ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit); + + return ret; +} + +static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = zboot_go(); printf("Kernel returned! (err=%d)\n", ret); return CMD_RET_FAILURE; } +int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, + ulong base, char *cmdline) +{ + int ret; + + memset(&state, '\0', sizeof(state)); + + if (base) { + state.base_ptr = map_sysmem(base, 0); + state.load_address = addr; + } else { + state.bzimage_addr = addr; + } + state.bzimage_size = size; + state.initrd_addr = initrd; + state.initrd_size = initrd_size; + state.cmdline = cmdline; + + ret = zboot_load(); + if (ret) + return log_msg_ret("ld", ret); + ret = zboot_setup(); + if (ret) + return log_msg_ret("set", ret); + ret = zboot_go(); + if (ret) + return log_msg_ret("set", ret); + + return -EFAULT; +} + static void print_num(const char *name, ulong value) { printf("%-20s: %lx\n", name, value); From d0dfbf548d0e0f49b33ae22a8fd338231445ecf0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:44 -0600 Subject: [PATCH 15/60] x86: zimage: Export the function to obtain the cmdline Allow reading the command line from a zimage, so that it can be recorded in the bootflow. Reviewed-by: Bin Meng Signed-off-by: Simon Glass --- arch/x86/include/asm/zimage.h | 10 ++++++++++ arch/x86/lib/zimage.c | 11 ++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index 966d7224eb1..9ad74dc0b94 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -89,4 +89,14 @@ void zimage_dump(struct boot_params *base_ptr); int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, ulong base, char *cmdline); +/* + * zimage_get_kernel_version() - Get the version string from a kernel + * + * @params: boot_params pointer + * @kernel_base: base address of kernel + * Return: Kernel version as a NUL-terminated string + */ +const char *zimage_get_kernel_version(struct boot_params *params, + void *kernel_base); + #endif diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 540d4d888bc..062e3d3e315 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -181,7 +181,7 @@ static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob) return 0; } -static const char *get_kernel_version(struct boot_params *params, +const char *zimage_get_kernel_version(struct boot_params *params, void *kernel_base) { struct setup_header *hdr = ¶ms->hdr; @@ -189,10 +189,14 @@ static const char *get_kernel_version(struct boot_params *params, const char *s, *end; bootproto = get_boot_protocol(hdr, false); + log_debug("bootproto %x, hdr->setup_sects %x\n", bootproto, + hdr->setup_sects); if (bootproto < 0x0200 || hdr->setup_sects < 15) return NULL; /* sanity-check the kernel version in case it is missing */ + log_debug("hdr->kernel_version %x, str at %p\n", hdr->kernel_version, + kernel_base + hdr->kernel_version + 0x200); for (s = kernel_base + hdr->kernel_version + 0x200, end = s + 0x100; *s; s++) { if (!isprint(*s)) @@ -239,7 +243,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size, log_debug("Using boot protocol version %x.%02x\n", (bootproto & 0xff00) >> 8, bootproto & 0xff); - version = get_kernel_version(params, image); + version = zimage_get_kernel_version(params, image); if (version) printf("Linux kernel version %s\n", version); else @@ -728,7 +732,8 @@ void zimage_dump(struct boot_params *base_ptr) print_num("Real mode switch", hdr->realmode_swtch); print_num("Start sys seg", hdr->start_sys_seg); print_num("Kernel version", hdr->kernel_version); - version = get_kernel_version(base_ptr, (void *)state.bzimage_addr); + version = zimage_get_kernel_version(base_ptr, + (void *)state.bzimage_addr); if (version) printf(" @%p: %s\n", version, version); print_num("Type of loader", hdr->type_of_loader); From c88d67d0211292dd5f259816b24c65da62ce3e30 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:45 -0600 Subject: [PATCH 16/60] bootstd: Add a simple bootmeth for ChromiumOS It is possible to boot x86-based ChromeOS machines by parsing a table and locating the kernel and command line. Add a bootmeth for this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- boot/Kconfig | 11 ++ boot/Makefile | 1 + boot/bootmeth_cros.c | 212 +++++++++++++++++++++++++++++++++++ configs/tools-only_defconfig | 1 + 4 files changed, 225 insertions(+) create mode 100644 boot/bootmeth_cros.c diff --git a/boot/Kconfig b/boot/Kconfig index c8b8f36d835..b424265df8d 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -463,6 +463,17 @@ config BOOTMETH_GLOBAL EFI bootmgr, since they take full control over which bootdevs are selected to boot. +config BOOTMETH_CROS + bool "Bootdev support for Chromium OS" + depends on X86 || SANDBOX + default y + help + Enables support for booting Chromium OS using bootdevs. This uses the + kernel A slot and obtains the kernel command line from the parameters + provided there. + + Note that only x86 devices are supported at present. + config BOOTMETH_EXTLINUX bool "Bootdev support for extlinux boot" select PXE_UTILS diff --git a/boot/Makefile b/boot/Makefile index f828f870a37..10f01572237 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EXTLINUX) += bootmeth_extlinux.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EXTLINUX_PXE) += bootmeth_pxe.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_CROS) += bootmeth_cros.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c new file mode 100644 index 00000000000..aa19ae097f5 --- /dev/null +++ b/boot/bootmeth_cros.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for ChromiumOS + * + * Copyright 2023 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_X86 +#include +#endif +#include + +enum { + /* Offsets in the kernel-partition header */ + KERN_START = 0x4f0, + KERN_SIZE = 0x518, + + SETUP_OFFSET = 0x1000, /* bytes before base */ + CMDLINE_OFFSET = 0x2000, /* bytes before base */ + OFFSET_BASE = 0x100000, /* assumed kernel load-address */ +}; + +static int cros_check(struct udevice *dev, struct bootflow_iter *iter) +{ + /* This only works on block and network devices */ + if (bootflow_iter_check_blk(iter)) + return log_msg_ret("blk", -ENOTSUPP); + + return 0; +} + +static int copy_cmdline(const char *from, const char *uuid, char **bufp) +{ + const int maxlen = 2048; + char buf[maxlen]; + char *cmd, *to, *end; + int len; + + /* Allow space for cmdline + UUID */ + len = strnlen(from, sizeof(buf)); + if (len >= maxlen) + return -E2BIG; + + log_debug("uuid %d %s\n", uuid ? (int)strlen(uuid) : 0, uuid); + for (to = buf, end = buf + maxlen - UUID_STR_LEN - 1; *from; from++) { + if (to >= end) + return -E2BIG; + if (from[0] == '%' && from[1] == 'U' && uuid && + strlen(uuid) == UUID_STR_LEN) { + strcpy(to, uuid); + to += UUID_STR_LEN; + from++; + } else { + *to++ = *from; + } + } + *to = '\0'; + len = to - buf; + cmd = strdup(buf); + if (!cmd) + return -ENOMEM; + free(*bufp); + *bufp = cmd; + + return 0; +} + +static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + ulong base, start, size, setup, cmdline, num_blks, kern_base; + struct disk_partition info; + const char *uuid = NULL; + void *buf, *hdr; + int ret; + + log_debug("starting, part=%d\n", bflow->part); + + /* We consider the whole disk, not any one partition */ + if (bflow->part) + return log_msg_ret("max", -ENOENT); + + /* Check partition 2 */ + ret = part_get_info(desc, 2, &info); + if (ret) + return log_msg_ret("part", ret); + + /* Make a buffer for the header information */ + num_blks = SZ_4K >> desc->log2blksz; + log_debug("Reading header, blk=%s, start=%lx, blocks=%lx\n", + bflow->blk->name, (ulong)info.start, num_blks); + hdr = memalign(SZ_1K, SZ_4K); + if (!hdr) + return log_msg_ret("hdr", -ENOMEM); + ret = blk_read(bflow->blk, info.start, num_blks, hdr); + if (ret != num_blks) + return log_msg_ret("inf", ret); + + if (memcmp("CHROMEOS", hdr, 8)) + return -ENOENT; + + log_info("Header at %lx\n", (ulong)map_to_sysmem(hdr)); + start = *(u32 *)(hdr + KERN_START); + size = ALIGN(*(u32 *)(hdr + KERN_SIZE), desc->blksz); + log_debug("Reading start %lx size %lx\n", start, size); + bflow->size = size; + + buf = memalign(SZ_1K, size); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + num_blks = size >> desc->log2blksz; + log_debug("Reading data, blk=%s, start=%lx, blocks=%lx\n", + bflow->blk->name, (ulong)info.start, num_blks); + ret = blk_read(bflow->blk, (ulong)info.start + 0x80, num_blks, buf); + if (ret != num_blks) + return log_msg_ret("inf", ret); + base = map_to_sysmem(buf); + + setup = base + start - OFFSET_BASE - SETUP_OFFSET; + cmdline = base + start - OFFSET_BASE - CMDLINE_OFFSET; + kern_base = base + start - OFFSET_BASE + SZ_16K; + log_debug("base %lx setup %lx, cmdline %lx, kern_base %lx\n", base, + setup, cmdline, kern_base); + +#ifdef CONFIG_X86 + const char *version; + + version = zimage_get_kernel_version(map_sysmem(setup, 0), + map_sysmem(kern_base, 0)); + log_debug("version %s\n", version); + if (version) + bflow->name = strdup(version); +#endif + if (!bflow->name) + bflow->name = strdup("ChromeOS"); + if (!bflow->name) + return log_msg_ret("nam", -ENOMEM); + bflow->os_name = strdup("ChromeOS"); + if (!bflow->os_name) + return log_msg_ret("os", -ENOMEM); + +#if CONFIG_IS_ENABLED(PARTITION_UUIDS) + uuid = info.uuid; +#endif + ret = copy_cmdline(map_sysmem(cmdline, 0), uuid, &bflow->cmdline); + if (ret) + return log_msg_ret("cmd", ret); + + bflow->state = BOOTFLOWST_READY; + bflow->buf = buf; + bflow->x86_setup = map_sysmem(setup, 0); + + return 0; +} + +static int cros_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep) +{ + return -ENOSYS; +} + +static int cros_boot(struct udevice *dev, struct bootflow *bflow) +{ +#ifdef CONFIG_X86 + zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0, + map_to_sysmem(bflow->x86_setup), + bflow->cmdline); +#endif + + return log_msg_ret("go", -EFAULT); +} + +static int cros_bootmeth_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = "ChromiumOS boot"; + + return 0; +} + +static struct bootmeth_ops cros_bootmeth_ops = { + .check = cros_check, + .read_bootflow = cros_read_bootflow, + .read_file = cros_read_file, + .boot = cros_boot, +}; + +static const struct udevice_id cros_bootmeth_ids[] = { + { .compatible = "u-boot,cros" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_cros) = { + .name = "bootmeth_cros", + .id = UCLASS_BOOTMETH, + .of_match = cros_bootmeth_ids, + .ops = &cros_bootmeth_ops, + .bind = cros_bootmeth_bind, +}; diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig index 2bc3bd9e912..3f588ea69be 100644 --- a/configs/tools-only_defconfig +++ b/configs/tools-only_defconfig @@ -10,6 +10,7 @@ CONFIG_FIT=y CONFIG_TIMESTAMP=y CONFIG_FIT_SIGNATURE=y # CONFIG_BOOTSTD_FULL is not set +# CONFIG_BOOTMETH_CROS is not set # CONFIG_BOOTMETH_VBE is not set CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="run distro_bootcmd" From 3a01d702f76dbd8a2b6d403d08ab6c26daaa126d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:46 -0600 Subject: [PATCH 17/60] x86: coreboot: Adjust various config options Drop IDE and add NVME since this is more common now. Add ms so it is easier to search for tables in memory. Expand the command-line and print buffers so that we can deal with the very long ChromeOS command lines. (typically 700 characters). Enable BOOTSTD_FULL to get the full set up standard-boot options. Finally, expand the malloc() space so we can read large kernels into a bootflow. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- configs/coreboot_defconfig | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index 0f3512d23c6..fc93561002c 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -1,5 +1,6 @@ CONFIG_X86=y CONFIG_TEXT_BASE=0x1110000 +CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_NR_DRAM_BANKS=8 CONFIG_ENV_SIZE=0x1000 CONFIG_DEFAULT_DEVICE_TREE="coreboot" @@ -8,12 +9,11 @@ CONFIG_VENDOR_COREBOOT=y CONFIG_TARGET_COREBOOT=y CONFIG_FIT=y CONFIG_FIT_SIGNATURE=y +CONFIG_BOOTSTD_FULL=y CONFIG_SYS_MONITOR_BASE=0x01110000 CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" -CONFIG_USE_BOOTCOMMAND=y -CONFIG_BOOTCOMMAND="ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000" CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_LOG=y @@ -23,9 +23,6 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_PCI_INIT_R=y CONFIG_HUSH_PARSER=y -CONFIG_SYS_PBSIZE=532 -CONFIG_CMD_MEM_SEARCH=y -CONFIG_CMD_IDE=y CONFIG_CMD_MMC=y CONFIG_CMD_PART=y CONFIG_CMD_USB=y @@ -52,13 +49,6 @@ CONFIG_USE_ROOTPATH=y CONFIG_REGMAP=y CONFIG_SYSCON=y # CONFIG_ACPIGEN is not set -CONFIG_SYS_IDE_MAXDEVICE=4 -CONFIG_SYS_ATA_DATA_OFFSET=0 -CONFIG_SYS_ATA_REG_OFFSET=0 -CONFIG_SYS_ATA_ALT_OFFSET=0 -CONFIG_ATAPI=y -CONFIG_LBA48=y -CONFIG_SYS_64BIT_LBA=y CONFIG_NVME_PCI=y # CONFIG_PCI_PNP is not set CONFIG_SOUND=y From 3693d348958f2d6339adb20489dd31bc08ddde83 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:47 -0600 Subject: [PATCH 18/60] x86: coral: Adjust various config options Add ms so it is easier to search for tables in memory. Expand the command-line and print buffers so that we can deal with the very long ChromeOS command lines. (typically 700 characters). Enable BOOTSTD_FULL to get the full set of standard-boot options. Replace the existing manual script with 'bootflow scan', since it can find and boot the OS. Finally, expand the malloc() space so we can read large kernels into a bootflow. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- configs/chromebook_coral_defconfig | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig index f5995f22004..fe61153b93d 100644 --- a/configs/chromebook_coral_defconfig +++ b/configs/chromebook_coral_defconfig @@ -1,5 +1,6 @@ CONFIG_X86=y CONFIG_TEXT_BASE=0x1110000 +CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SYS_MALLOC_F_LEN=0x3d00 CONFIG_NR_DRAM_BANKS=8 CONFIG_MAX_CPUS=8 @@ -22,6 +23,7 @@ CONFIG_X86_OFFSET_U_BOOT=0xffd00000 CONFIG_X86_OFFSET_SPL=0xffe80000 CONFIG_INTEL_ACPIGEN=y CONFIG_INTEL_GENERIC_WIFI=y +CONFIG_BOOTSTD_FULL=y CONFIG_SYS_MONITOR_BASE=0x01110000 CONFIG_CHROMEOS=y CONFIG_BOOTSTAGE=y @@ -33,8 +35,10 @@ CONFIG_BOOTSTAGE_STASH=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS_SUBST=y CONFIG_USE_BOOTCOMMAND=y -CONFIG_BOOTCOMMAND="tpm init; tpm startup TPM2_SU_CLEAR; read mmc 0:2 100000 0 80; setexpr loader *001004f0; setexpr size *00100518; setexpr blocks $size / 200; read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; setexpr cmdline_ptr $loader - 2000; setexpr.s cmdline *$cmdline_ptr; setexpr cmdline gsub %U \\\\${uuid}; if part uuid mmc 0:2 uuid; then zboot start 100000 0 0 0 $setup cmdline; zboot load; zboot setup; zboot dump; zboot go;fi" +CONFIG_BOOTCOMMAND="tpm init; tpm startup TPM2_SU_CLEAR; bootflow scan -lb" CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_LOG=y +CONFIG_LOGF_FUNC=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_BLOBLIST=y @@ -52,9 +56,11 @@ CONFIG_SPL_POWER=y CONFIG_TPL_SYS_MALLOC_SIMPLE=y CONFIG_TPL_POWER=y CONFIG_HUSH_PARSER=y -CONFIG_SYS_PBSIZE=532 +CONFIG_SYS_CBSIZE=1024 +CONFIG_SYS_PBSIZE=1024 CONFIG_CMD_CPU=y CONFIG_CMD_PMC=y +CONFIG_CMD_MEM_SEARCH=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_PART=y From 4fb2536e5b17de99cfc44e985a1f617b1dfc0a22 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:36 -0600 Subject: [PATCH 19/60] x86: Allow listing MTRRs in SPL Move MTRR-listing code into a common file so it can be used from SPL. Update the 'mtrr' command to call it. Use this in SPL just before adjusting the MTRRs, so we can see the state set up by the board. Only show it when debug is enabled. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/mtrr.c | 61 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 20 ++++++++++++ arch/x86/lib/spl.c | 7 +++++ cmd/x86/mtrr.c | 60 +++--------------------------------- 4 files changed, 92 insertions(+), 56 deletions(-) diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index e69dfb552b1..d57fcface01 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -30,6 +30,16 @@ DECLARE_GLOBAL_DATA_PTR; +static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = { + "Uncacheable", + "Combine", + "2", + "3", + "Through", + "Protect", + "Back", +}; + /* Prepare to adjust MTRRs */ void mtrr_open(struct mtrr_state *state, bool do_caches) { @@ -320,3 +330,54 @@ int mtrr_set(int cpu_select, int reg, u64 base, u64 mask) return mtrr_start_op(cpu_select, &oper); } + +static void read_mtrrs_(void *arg) +{ + struct mtrr_info *info = arg; + + mtrr_read_all(info); +} + +int mtrr_list(int reg_count, int cpu_select) +{ + struct mtrr_info info; + int ret; + int i; + + printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||", + "Mask ||", "Size ||"); + memset(&info, '\0', sizeof(info)); + ret = mp_run_on_cpus(cpu_select, read_mtrrs_, &info); + if (ret) + return log_msg_ret("run", ret); + for (i = 0; i < reg_count; i++) { + const char *type = "Invalid"; + u64 base, mask, size; + bool valid; + + base = info.mtrr[i].base; + mask = info.mtrr[i].mask; + size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1); + size |= (1 << 12) - 1; + size += 1; + valid = mask & MTRR_PHYS_MASK_VALID; + type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK]; + printf("%d %-5s %-12s %016llx %016llx %016llx\n", i, + valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK, + mask & ~MTRR_PHYS_MASK_VALID, size); + } + + return 0; +} + +int mtrr_get_type_by_name(const char *typename) +{ + int i; + + for (i = 0; i < MTRR_TYPE_COUNT; i++) { + if (*typename == *mtrr_type_name[i]) + return i; + } + + return -EINVAL; +}; diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index ca2edc7878f..2e995f54061 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -190,6 +190,26 @@ int mtrr_set(int cpu_select, int reg, u64 base, u64 mask); */ int mtrr_get_var_count(void); +/** + * mtrr_list() - List the MTRRs + * + * Shows a list of all the MTRRs including their values + * + * @reg_count: Number of registers to show. You can use mtrr_get_var_count() for + * this + * @cpu_select: CPU to use. Use MP_SELECT_BSP for the boot CPU + * Returns: 0 if OK, -ve if the CPU was not found + */ +int mtrr_list(int reg_count, int cpu_select); + +/** + * mtrr_get_type_by_name() - Get the type of an MTRR given its type name + * + * @typename: Name to check + * Returns: MTRR type (MTRR_TYPE_...) or -EINVAL if invalid + */ +int mtrr_get_type_by_name(const char *typename); + #endif #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index ca1645f9d68..b9d23e6bfe1 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -139,6 +140,12 @@ static int x86_spl_init(void) arch_setup_gd(gd->new_gd); gd->start_addr_sp = (ulong)ptr; + if (_LOG_DEBUG) { + ret = mtrr_list(mtrr_get_var_count(), MP_SELECT_BSP); + if (ret) + printf("mtrr_list failed\n"); + } + /* Cache the SPI flash. Otherwise copying the code to RAM takes ages */ ret = mtrr_add_request(MTRR_TYPE_WRBACK, (1ULL << 32) - CONFIG_XIP_ROM_SIZE, diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index b1691d8b65a..6ad7a123a44 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -10,71 +10,19 @@ #include #include -static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = { - "Uncacheable", - "Combine", - "2", - "3", - "Through", - "Protect", - "Back", -}; - -static void read_mtrrs(void *arg) -{ - struct mtrr_info *info = arg; - - mtrr_read_all(info); -} - -static int do_mtrr_list(int reg_count, int cpu_select) -{ - struct mtrr_info info; - int ret; - int i; - - printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||", - "Mask ||", "Size ||"); - memset(&info, '\0', sizeof(info)); - ret = mp_run_on_cpus(cpu_select, read_mtrrs, &info); - if (ret) - return log_msg_ret("run", ret); - for (i = 0; i < reg_count; i++) { - const char *type = "Invalid"; - uint64_t base, mask, size; - bool valid; - - base = info.mtrr[i].base; - mask = info.mtrr[i].mask; - size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1); - size |= (1 << 12) - 1; - size += 1; - valid = mask & MTRR_PHYS_MASK_VALID; - type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK]; - printf("%d %-5s %-12s %016llx %016llx %016llx\n", i, - valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK, - mask & ~MTRR_PHYS_MASK_VALID, size); - } - - return 0; -} - static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[]) { const char *typename = argv[0]; uint32_t start, size; uint64_t base, mask; - int i, type = -1; + int type = -1; bool valid; int ret; if (argc < 3) return CMD_RET_USAGE; - for (i = 0; i < MTRR_TYPE_COUNT; i++) { - if (*typename == *mtrr_type_name[i]) - type = i; - } - if (type == -1) { + type = mtrr_get_type_by_name(typename); + if (type < 0) { printf("Invalid type name %s\n", typename); return CMD_RET_USAGE; } @@ -146,7 +94,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, if (!first) printf("\n"); printf("CPU %d:\n", i); - ret = do_mtrr_list(reg_count, i); + ret = mtrr_list(reg_count, i); if (ret) { printf("Failed to read CPU %s (err=%d)\n", i < MP_SELECT_ALL ? simple_itoa(i) : "", From ef836b9932865c4c244c7532830840560c29c172 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:37 -0600 Subject: [PATCH 20/60] x86: mtrr: Add documentation Add documention for the x86 'mtrr' command. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Suggested-by: Heinrich Schuchardt --- doc/usage/cmd/mtrr.rst | 151 +++++++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + 2 files changed, 152 insertions(+) create mode 100644 doc/usage/cmd/mtrr.rst diff --git a/doc/usage/cmd/mtrr.rst b/doc/usage/cmd/mtrr.rst new file mode 100644 index 00000000000..531153bb3e2 --- /dev/null +++ b/doc/usage/cmd/mtrr.rst @@ -0,0 +1,151 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +mtrr command +============ + +Synopis +------- + + mtrr [list] + mtrr set + mtrr disable + mtrr enable + + +Description +----------- + +The *mtrr* command is used to dump the Memory Type Range Registers (MTRRs) on +an x86 machine. These register control cache behaviour in selected memory +ranges. + +Note that the number of registers can vary between CPUs. + + +mtrr [list] +~~~~~~~~~~~ + +List the MTRRs. The table shows the following information: + +Reg + Register number (the first is register 0) + +Valid + Shows Y if the register is valid (has bit 11 set), N if not + +Write-type + Shows the behaviour when writing to the memory region. The types are + abbreviated to fit a reasonable line length. Valid types shown below. + + ====== ============== ==================================================== + Value Type Meaning + ====== ============== ==================================================== + 0 Uncacheable Skip cache and write directly to memory + 1 Combine Multiple writes can be combined into one transaction + 4 Through Update cache and also write to memory + 5 Protect Writes are prohibited + 6 Back Update cache but don't write to memory + ====== ============== ==================================================== + +Base + Base memory address from which the register controls behaviour + +Mask + Mask value, which also indicates the size + +Size + Length of memory region within which the register controls behaviour + + +mtrr set +~~~~~~~~ + +This sets the value of a particular MTRR. Parameters are: + +reg + Register number to set, with 0 being the first + +type + Access type to set. See Write-type above for valid types. This uses the name + rather than its numeric value. + +start + Base memory address from which the register should control behaviour + +size + Length of memory region within which the register controls behaviour + + +mtrr disable +~~~~~~~~~~~~ + +This disables a particular register, by clearing its `valid` bit (11). + + +mtrr enable +~~~~~~~~~~~ + +This enables a particular register, by setting its `valid` bit (11). + + +Example +------- + +This shows disabling and enabling an MTRR, as well as setting its type:: + + => mtrr + CPU 0: + Reg Valid Write-type Base || Mask || Size || + 0 Y Back 0000000000000000 0000000f80000000 0000000080000000 + 1 Y Back 0000000080000000 0000000fe0000000 0000000020000000 + 2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000 + 3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000 + 4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000 + 5 Y Combine 00000000d0000000 0000000ff0000000 0000000010000000 + 6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + => mtrr d 5 + => mtrr + CPU 0: + Reg Valid Write-type Base || Mask || Size || + 0 Y Back 0000000000000000 0000000f80000000 0000000080000000 + 1 Y Back 0000000080000000 0000000fe0000000 0000000020000000 + 2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000 + 3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000 + 4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000 + 5 N Combine 00000000d0000000 0000000ff0000000 0000000010000000 + 6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + => mtrr e 5 + => mtrr + CPU 0: + Reg Valid Write-type Base || Mask || Size || + 0 Y Back 0000000000000000 0000000f80000000 0000000080000000 + 1 Y Back 0000000080000000 0000000fe0000000 0000000020000000 + 2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000 + 3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000 + 4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000 + 5 Y Combine 00000000d0000000 0000000ff0000000 0000000010000000 + 6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + => mtrr set 5 Uncacheable d0000000 10000000 + => mtrr + CPU 0: + Reg Valid Write-type Base || Mask || Size || + 0 Y Back 0000000000000000 0000000f80000000 0000000080000000 + 1 Y Back 0000000080000000 0000000fe0000000 0000000020000000 + 2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000 + 3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000 + 4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000 + 5 Y Uncacheable 00000000d0000000 0000000ff0000000 0000000010000000 + 6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + 9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000 + => diff --git a/doc/usage/index.rst b/doc/usage/index.rst index f2ffd2787aa..072db53614c 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -76,6 +76,7 @@ Shell commands cmd/md cmd/mmc cmd/mtest + cmd/mtrr cmd/panic cmd/part cmd/pause From 603363927a0da1be12ff7e7b073202861c979693 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:38 -0600 Subject: [PATCH 21/60] bios_emulator: Add Kconfig and adjust Makefile for SPL The Kconfig for this is currently inside a particular board. Move it into the correct place and allow use in SPL, so that video can be used there if needed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- board/google/Kconfig | 7 ------- drivers/Kconfig | 2 ++ drivers/Makefile | 2 +- drivers/bios_emulator/Kconfig | 10 ++++++++++ 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 drivers/bios_emulator/Kconfig diff --git a/board/google/Kconfig b/board/google/Kconfig index a0f1a609764..e4f9b5b68aa 100644 --- a/board/google/Kconfig +++ b/board/google/Kconfig @@ -4,13 +4,6 @@ if VENDOR_GOOGLE -config BIOSEMU - bool - select X86EMU_RAW_IO - -config X86EMU_RAW_IO - bool - choice prompt "Mainboard model" optional diff --git a/drivers/Kconfig b/drivers/Kconfig index 75937fbb6d9..a25f6ae02fd 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -10,6 +10,8 @@ source "drivers/ata/Kconfig" source "drivers/axi/Kconfig" +source "drivers/bios_emulator/Kconfig" + source "drivers/bus/Kconfig" source "drivers/block/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 78dcf62f76a..3bc6d279d7c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+ +obj-$(CONFIG_$(SPL_TPL_)BIOSEMU) += bios_emulator/ obj-$(CONFIG_$(SPL_TPL_)BLK) += block/ obj-$(CONFIG_$(SPL_TPL_)BOOTCOUNT_LIMIT) += bootcount/ obj-$(CONFIG_$(SPL_TPL_)BUTTON) += button/ @@ -80,7 +81,6 @@ ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) obj-y += adc/ obj-y += ata/ obj-$(CONFIG_DM_DEMO) += demo/ -obj-$(CONFIG_BIOSEMU) += bios_emulator/ obj-y += block/ obj-y += cache/ obj-$(CONFIG_CPU) += cpu/ diff --git a/drivers/bios_emulator/Kconfig b/drivers/bios_emulator/Kconfig new file mode 100644 index 00000000000..3660576772d --- /dev/null +++ b/drivers/bios_emulator/Kconfig @@ -0,0 +1,10 @@ +config BIOSEMU + bool + select X86EMU_RAW_IO + +config SPL_BIOSEMU + bool + select X86EMU_RAW_IO + +config X86EMU_RAW_IO + bool From 70f2030f02696ee1820d8df690e878de078b01b3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:39 -0600 Subject: [PATCH 22/60] bios_emulator: Drop VIDEO_IO_OFFSET This is always zero in the source tree, so drop it. While we are here, add a comment to _X86EMU_env since the symbol is actually defined twice, which can cause confusion when building. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/bios_emulator/biosemui.h | 18 +++++++++--------- drivers/bios_emulator/x86emu/sys.c | 1 + include/configs/conga-qeval20-qa3-e3845.h | 2 -- include/configs/dfi-bt700.h | 2 -- include/configs/minnowmax.h | 2 -- include/configs/som-db5800-som-6867.h | 2 -- include/configs/theadorable-x86-common.h | 2 -- include/configs/x86-chromebook.h | 2 -- 8 files changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/bios_emulator/biosemui.h b/drivers/bios_emulator/biosemui.h index 7853015c1e2..954cd883158 100644 --- a/drivers/bios_emulator/biosemui.h +++ b/drivers/bios_emulator/biosemui.h @@ -128,19 +128,19 @@ typedef struct { u32 finalVal; } BE_portInfo; -#define PM_inpb(port) inb(port+VIDEO_IO_OFFSET) -#define PM_inpw(port) inw(port+VIDEO_IO_OFFSET) -#define PM_inpd(port) inl(port+VIDEO_IO_OFFSET) -#define PM_outpb(port,val) outb(val,port+VIDEO_IO_OFFSET) -#define PM_outpw(port,val) outw(val,port+VIDEO_IO_OFFSET) -#define PM_outpd(port,val) outl(val,port+VIDEO_IO_OFFSET) +#define PM_inpb(port) inb(port) +#define PM_inpw(port) inw(port) +#define PM_inpd(port) inl(port) +#define PM_outpb(port, val) outb(val, port) +#define PM_outpw(port, val) outw(val, port) +#define PM_outpd(port, val) outl(val, port) #define LOG_inpb(port) PM_inpb(port) #define LOG_inpw(port) PM_inpw(port) #define LOG_inpd(port) PM_inpd(port) -#define LOG_outpb(port,val) PM_outpb(port,val) -#define LOG_outpw(port,val) PM_outpw(port,val) -#define LOG_outpd(port,val) PM_outpd(port,val) +#define LOG_outpb(port, val) PM_outpb(port, val) +#define LOG_outpw(port, val) PM_outpw(port, val) +#define LOG_outpd(port, val) PM_outpd(port, val) /*-------------------------- Function Prototypes --------------------------*/ diff --git a/drivers/bios_emulator/x86emu/sys.c b/drivers/bios_emulator/x86emu/sys.c index c2db1213fe6..882a8a34cc3 100644 --- a/drivers/bios_emulator/x86emu/sys.c +++ b/drivers/bios_emulator/x86emu/sys.c @@ -44,6 +44,7 @@ /*------------------------- Global Variables ------------------------------*/ +/* Note: bios.c defines this if the emulator is not enabled */ X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */ X86EMU_intrFuncs _X86EMU_intrTab[256]; diff --git a/include/configs/conga-qeval20-qa3-e3845.h b/include/configs/conga-qeval20-qa3-e3845.h index 60617e6fec2..03c364f29fb 100644 --- a/include/configs/conga-qeval20-qa3-e3845.h +++ b/include/configs/conga-qeval20-qa3-e3845.h @@ -16,8 +16,6 @@ "stdout=serial\0" \ "stderr=serial\0" -#define VIDEO_IO_OFFSET 0 - #undef CFG_EXTRA_ENV_SETTINGS #define CFG_EXTRA_ENV_SETTINGS \ "kernel-ver=4.4.0-22\0" \ diff --git a/include/configs/dfi-bt700.h b/include/configs/dfi-bt700.h index 05389a435be..be095e28a1b 100644 --- a/include/configs/dfi-bt700.h +++ b/include/configs/dfi-bt700.h @@ -20,8 +20,6 @@ "stdout=serial\0" \ "stderr=serial\0" -#define VIDEO_IO_OFFSET 0 - #undef CFG_EXTRA_ENV_SETTINGS #define CFG_EXTRA_ENV_SETTINGS \ "kernel-ver=4.4.0-24\0" \ diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 4a12c2f72c6..842672d5575 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -17,6 +17,4 @@ "stderr=vidconsole,serial\0" \ "usb_pgood_delay=40\0" -#define VIDEO_IO_OFFSET 0 - #endif /* __CONFIG_H */ diff --git a/include/configs/som-db5800-som-6867.h b/include/configs/som-db5800-som-6867.h index b2e7aa1514c..5f7eabd3fc6 100644 --- a/include/configs/som-db5800-som-6867.h +++ b/include/configs/som-db5800-som-6867.h @@ -16,6 +16,4 @@ "stdout=serial,vidconsole\0" \ "stderr=serial,vidconsole\0" -#define VIDEO_IO_OFFSET 0 - #endif /* __CONFIG_H */ diff --git a/include/configs/theadorable-x86-common.h b/include/configs/theadorable-x86-common.h index b23b8783076..46aef238213 100644 --- a/include/configs/theadorable-x86-common.h +++ b/include/configs/theadorable-x86-common.h @@ -15,8 +15,6 @@ "stdout=serial\0" \ "stderr=serial\0" -#define VIDEO_IO_OFFSET 0 - /* Environment settings */ #undef CFG_EXTRA_ENV_SETTINGS diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index 98abb00927a..6bf90c7de43 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -10,8 +10,6 @@ #define CFG_X86_REFCODE_ADDR 0xffea0000 #define CFG_X86_REFCODE_RUN_ADDR 0 -#define VIDEO_IO_OFFSET 0 - #define CFG_STD_DEVICES_SETTINGS "stdin=usbkbd,i8042-kbd,serial\0" \ "stdout=vidconsole,serial\0" \ "stderr=vidconsole,serial\0" From b73dba7a83f2071ef97e175be5ee8a2492042e96 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:40 -0600 Subject: [PATCH 23/60] x86: Tidy up EFI code in interrupt_init() The ll_boot_init() check handles the EFI case so we don't need the rest of the code. Drop it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/i386/interrupt.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/arch/x86/cpu/i386/interrupt.c b/arch/x86/cpu/i386/interrupt.c index fae2544c456..f3f3527237f 100644 --- a/arch/x86/cpu/i386/interrupt.c +++ b/arch/x86/cpu/i386/interrupt.c @@ -266,6 +266,10 @@ int interrupt_init(void) struct udevice *dev; int ret; + /* + * When running as an EFI application we are not in control of + * interrupts and should leave them alone. + */ if (!ll_boot_init()) return 0; @@ -274,11 +278,6 @@ int interrupt_init(void) if (ret && ret != -ENODEV) return ret; - /* - * When running as an EFI application we are not in control of - * interrupts and should leave them alone. - */ -#ifndef CONFIG_EFI_APP /* Just in case... */ disable_interrupts(); @@ -294,14 +293,8 @@ int interrupt_init(void) /* Initialize core interrupt and exception functionality of CPU */ cpu_init_interrupts(); - /* - * It is now safe to enable interrupts. - * - * TODO(sjg@chromium.org): But we don't handle these correctly when - * booted from EFI. - */ + /* It is now safe to enable interrupts */ enable_interrupts(); -#endif return 0; } From de94db813272393d136f21b2cb832d8933d2cfb2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:41 -0600 Subject: [PATCH 24/60] x86: Add a comment for board_init_f_r_trampoline() Add a comment for this function in the header. Change the function (and the one after) to use __noreturn to keep checkpatch happy. Add docs to board_init_f_r() while we are here. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/include/asm/u-boot-x86.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 8f38c2d1c60..1d8aa320f53 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -102,8 +102,20 @@ int video_bios_init(void); */ int fsp_save_s3_stack(void); -void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn)); -void board_init_f_r(void) __attribute__ ((noreturn)); +/** + * board_init_f_r_trampoline() - jump to relocated address with new stack + * + * @sp: New stack pointer to use + */ +void __noreturn board_init_f_r_trampoline(ulong sp); + +/** + * board_init_f_r() - jump to relocated U-Boot + * + * This is used to jump from pre-relocation to post-relocation U-Boot. It + * enables the cache and jump to the new location. + */ +void __noreturn board_init_f_r(void); int arch_misc_init(void); From 633af11dd65cde0c198f8548585d6610cf4d0655 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:42 -0600 Subject: [PATCH 25/60] x86: Show the CPU physical address size with bdinfo This is useful information so show it with the bdinfo command. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/bdinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c index 15390070fe8..a20d0954416 100644 --- a/arch/x86/lib/bdinfo.c +++ b/arch/x86/lib/bdinfo.c @@ -22,6 +22,7 @@ void arch_print_bdinfo(void) bdinfo_print_num_l("vendor", gd->arch.x86_vendor); bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor)); bdinfo_print_num_l("model", gd->arch.x86_model); + bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size()); if (IS_ENABLED(CONFIG_EFI_STUB)) efi_show_bdinfo(); From 67884002f48ecf9e39f9402bc3866c8674ada563 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:43 -0600 Subject: [PATCH 26/60] x86: Correct get_sp() implementation for 64-bit Use an assembler implementation as is done for i386, so that the results are equivalent for i386 and x86_64. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/bootm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 61cb7bc6116..3196f9ddc2c 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -258,7 +258,7 @@ static ulong get_sp(void) ulong ret; #if CONFIG_IS_ENABLED(X86_64) - ret = gd->start_addr_sp; + asm("mov %%rsp, %0" : "=r"(ret) : ); #else asm("mov %%esp, %0" : "=r"(ret) : ); #endif From 78f24d8f3415a9ceec993231b81efaa30e2a3cdc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:44 -0600 Subject: [PATCH 27/60] x86: Show an error when a BIOS exception occurs Rather than silently hanging, show an error first. This can happen when there is something wrong with the video BIOS. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/bios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 94349ba8073..8cc686fd146 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -78,7 +78,7 @@ static int int_exception_handler(void) }; struct eregs *regs = ®_info; - debug("Oops, exception %d while executing option rom\n", regs->vector); + log_err("Exception %d while executing option rom\n", regs->vector); cpu_hlt(); return 0; From 297184143ab788b7e591604475760c1794532c99 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:45 -0600 Subject: [PATCH 28/60] acpi: Add a comment to set the acpi tables Sometimes a previous bootloader has written ACPI tables. It is useful to be able to find and list these. Add an 'acpi set' command to set the address for these tables. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- cmd/acpi.c | 24 +++++++++++++++++++++--- doc/usage/cmd/acpi.rst | 29 +++++++++++++++++++++++++++-- test/dm/acpi.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/cmd/acpi.c b/cmd/acpi.c index e70913e40bf..ede9c8c7dcb 100644 --- a/cmd/acpi.c +++ b/cmd/acpi.c @@ -118,6 +118,22 @@ static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } +static int do_acpi_set(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ulong val; + + if (argc < 2) { + printf("ACPI pointer: %lx\n", gd_acpi_start()); + } else { + val = hextoul(argv[1], NULL); + printf("Setting ACPI pointer to %lx\n", val); + gd_set_acpi_start(val); + } + + return 0; +} + static int do_acpi_items(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -157,12 +173,14 @@ static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc, #ifdef CONFIG_SYS_LONGHELP static char acpi_help_text[] = - "list - list ACPI tables\n" - "acpi items [-d] - List/dump each piece of ACPI data from devices\n" - "acpi dump - Dump ACPI table"; + "list - list ACPI tables\n" + "acpi items [-d] - List/dump each piece of ACPI data from devices\n" + "acpi set [] - Set or show address of ACPI tables\n" + "acpi dump - Dump ACPI table"; #endif U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text, U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list), U_BOOT_SUBCMD_MKENT(items, 2, 1, do_acpi_items), + U_BOOT_SUBCMD_MKENT(set, 2, 1, do_acpi_set), U_BOOT_SUBCMD_MKENT(dump, 2, 1, do_acpi_dump)); diff --git a/doc/usage/cmd/acpi.rst b/doc/usage/cmd/acpi.rst index 14bafc8e352..6b9b8949f32 100644 --- a/doc/usage/cmd/acpi.rst +++ b/doc/usage/cmd/acpi.rst @@ -11,12 +11,14 @@ Synopis acpi list acpi items [-d] acpi dump + acpi set
Description ----------- -The *acpi* command is used to dump the ACPI tables generated by U-Boot for passing -to the operating systems. +The *acpi* command is used to dump the ACPI tables generated by U-Boot for +passing to the operating systems. It allows manually setting the address to take +a look at existing ACPI tables. ACPI tables can be generated by various output functions and even devices can output material to include in the Differentiated System Description Table (DSDT) @@ -231,5 +233,28 @@ Example 00000000: 44 53 44 54 ea 32 00 00 02 eb 55 2d 42 4f 4f 54 DSDT.2....U-BOOT 00000010: 55 2d 42 4f 4f 54 42 4c 25 07 11 20 49 4e 54 4c U-BOOTBL%.. INTL +This shows searching for tables in a known area of memory, then setting the +pointer:: + + => acpi list + No ACPI tables present + => ms.s bff00000 80000 "RSD PTR" + bff75000: 52 53 44 20 50 54 52 20 cf 42 4f 43 48 53 20 00 RSD PTR .BOCHS . + 1 match + => acpi set bff75000 + Setting ACPI pointer to bff75000 + => acpi list + Name Base Size Detail + ---- -------- ----- ------ + RSDP bff75000 0 v00 BOCHS + RSDT bff76a63 38 v01 BOCHS BXPC 1 BXPC 1 + FACP bff768ff 74 v01 BOCHS BXPC 1 BXPC 1 + DSDT bff75080 187f v01 BOCHS BXPC 1 BXPC 1 + FACS bff75040 40 + APIC bff76973 90 v01 BOCHS BXPC 1 BXPC 1 + HPET bff76a03 38 v01 BOCHS BXPC 1 BXPC 1 + WAET bff76a3b 28 v01 BOCHS BXPC 1 BXPC 1 + SSDT bff95040 c5 v02 COREv4 COREBOOT 2a CORE 20221020 + .. _`ACPI specification`: https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 818f71572c7..77eb524b59f 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -609,3 +609,41 @@ static int dm_test_acpi_cmd_items(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_cmd_items, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test 'acpi set' command */ +static int dm_test_acpi_cmd_set(struct unit_test_state *uts) +{ + struct acpi_ctx ctx; + ulong addr; + void *buf; + + gd_set_acpi_start(0); + + console_record_reset(); + ut_asserteq(0, gd_acpi_start()); + ut_assertok(run_command("acpi set", 0)); + ut_assert_nextline("ACPI pointer: 0"); + + buf = memalign(16, BUF_SIZE); + ut_assertnonnull(buf); + addr = map_to_sysmem(buf); + ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr)); + + ut_assertok(acpi_write_dev_tables(&ctx)); + + ut_assertok(run_command("acpi set", 0)); + ut_assert_nextline("ACPI pointer: %lx", addr); + + ut_assertok(run_command("acpi set 0", 0)); + ut_assert_nextline("Setting ACPI pointer to 0"); + ut_asserteq(0, gd_acpi_start()); + + ut_assertok(run_commandf("acpi set %lx", addr)); + ut_assert_nextline("Setting ACPI pointer to %lx", addr); + ut_asserteq(addr, gd_acpi_start()); + + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_acpi_cmd_set, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); From b279f5170a807a87a5726bcbeb0bc98937102eee Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:46 -0600 Subject: [PATCH 29/60] bdinfo: Show the RAM top and approximate stack pointer These are useful pieces of information when debugging. The RAM top shows where U-Boot started allocating memory from, before it relocated. The stack pointer can be checked to ensure it is in the correct region. Signed-off-by: Simon Glass Reviewed-by: Nikhil M Jain Reviewed-by: Bin Meng Tested-by: Nikhil M Jain --- cmd/Kconfig | 8 ++++++++ cmd/bdinfo.c | 5 +++++ test/cmd/bdinfo.c | 7 +++++++ 3 files changed, 20 insertions(+) diff --git a/cmd/Kconfig b/cmd/Kconfig index fd76972eaa3..ecfd5752377 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -135,6 +135,14 @@ config CMD_BDI help Print board info +config CMD_BDINFO_EXTRA + bool "bdinfo extra features" + default y if SANDBOX || X86 + help + Show additional information about the board. This uses a little more + code space but provides more options, particularly those useful for + bringup, development and debugging. + config CMD_CONFIG bool "config" default SANDBOX diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index dab73f1d93c..44e6d6a972e 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -173,6 +173,11 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } print_serial(gd->cur_serial_dev); + if (IS_ENABLED(CONFIG_CMD_BDINFO_EXTRA)) { + bdinfo_print_num_ll("stack ptr", (ulong)&bd); + bdinfo_print_num_ll("ram_top ptr", (ulong)gd->ram_top); + } + arch_print_bdinfo(); return 0; diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c index 6480393fd5d..8c09281cac0 100644 --- a/test/cmd/bdinfo.c +++ b/test/cmd/bdinfo.c @@ -205,6 +205,13 @@ static int bdinfo_test_move(struct unit_test_state *uts) ut_assertok(test_num_l(uts, " clock", info.clock)); } + if (IS_ENABLED(CONFIG_CMD_BDINFO_EXTRA)) { + ut_assert_nextlinen("stack ptr"); + ut_assertok(test_num_ll(uts, "ram_top ptr", + (unsigned long long)gd->ram_top)); + ut_assertok(test_num_l(uts, "malloc base", gd_malloc_start())); + } + ut_assertok(ut_check_console_end(uts)); return 0; From 125194e6a136f2a3ef49d443f139b44a04e1bb9e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:47 -0600 Subject: [PATCH 30/60] part: Allow setting the partition-table type Some devices have multiple partition types available on the same media. It is sometimes useful to see these to check that everything is working correctly. Provide a way to manually set the partition-table type, avoiding the auto-detection process. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- cmd/part.c | 34 +++++++++++++++++++ disk/part.c | 16 +++++++++ doc/usage/cmd/part.rst | 74 ++++++++++++++++++++++++++++++++++++++++++ include/part.h | 9 +++++ 4 files changed, 133 insertions(+) diff --git a/cmd/part.c b/cmd/part.c index 28f2b7ff9bb..0ce190005d3 100644 --- a/cmd/part.c +++ b/cmd/part.c @@ -182,6 +182,36 @@ static int do_part_number(int argc, char *const argv[]) return do_part_info(argc, argv, CMD_PART_INFO_NUMBER); } +static int do_part_set(int argc, char *const argv[]) +{ + const char *devname, *partstr, *typestr; + struct blk_desc *desc; + int dev; + + if (argc < 3) + return CMD_RET_USAGE; + + /* Look up the device */ + devname = argv[0]; + partstr = argv[1]; + typestr = argv[2]; + dev = blk_get_device_by_str(devname, partstr, &desc); + if (dev < 0) { + printf("** Bad device specification %s %s **\n", devname, + partstr); + return CMD_RET_FAILURE; + } + + desc->part_type = part_get_type_by_name(typestr); + if (!desc->part_type) { + printf("Unknown partition type '%s'\n", typestr); + return CMD_RET_FAILURE; + } + part_print(desc); + + return 0; +} + #ifdef CONFIG_PARTITION_TYPE_GUID static int do_part_type(int argc, char *const argv[]) { @@ -245,6 +275,8 @@ static int do_part(struct cmd_tbl *cmdtp, int flag, int argc, return do_part_number(argc - 2, argv + 2); else if (!strcmp(argv[1], "types")) return do_part_types(argc - 2, argv + 2); + else if (!strcmp(argv[1], "set")) + return do_part_set(argc - 2, argv + 2); #ifdef CONFIG_PARTITION_TYPE_GUID else if (!strcmp(argv[1], "type")) return do_part_type(argc - 2, argv + 2); @@ -279,6 +311,8 @@ U_BOOT_CMD( #endif "part type : \n" " - set environment variable to partition type\n" + "part set type\n" + " - set partition type for a device\n" "part types\n" " - list supported partition table types" ); diff --git a/disk/part.c b/disk/part.c index 35300df5903..1d2117ab71e 100644 --- a/disk/part.c +++ b/disk/part.c @@ -54,6 +54,22 @@ static struct part_driver *part_driver_lookup_type(struct blk_desc *dev_desc) return NULL; } +int part_get_type_by_name(const char *name) +{ + struct part_driver *drv = + ll_entry_start(struct part_driver, part_driver); + const int n_ents = ll_entry_count(struct part_driver, part_driver); + struct part_driver *entry; + + for (entry = drv; entry != drv + n_ents; entry++) { + if (!strcasecmp(name, entry->name)) + return entry->part_type; + } + + /* Not found */ + return PART_TYPE_UNKNOWN; +} + static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) { struct blk_desc *dev_desc; diff --git a/doc/usage/cmd/part.rst b/doc/usage/cmd/part.rst index 8d2a2803912..8a594aaff27 100644 --- a/doc/usage/cmd/part.rst +++ b/doc/usage/cmd/part.rst @@ -13,6 +13,7 @@ Synopis part start part size part number + part set part type : [varname] part types @@ -82,6 +83,18 @@ part must be specified as partition name. varname a variable to store the current partition number value into +The 'part set' command sets the type of a partition. This is useful when +autodetection fails or does not do the correct thing: + + interface + interface for accessing the block device (mmc, sata, scsi, usb, ....) + dev + device number + part + partition number + type + partition type to use (see 'part types') to check available types + The 'part type' command prints or sets an environment variable to the partition type UUID. interface @@ -147,6 +160,67 @@ Examples => part types Supported partition tables: EFI, AMIGA, DOS, ISO, MAC +This shows looking at a device with multiple partition tables:: + + => virtio scan + => part list virtio 0 + + Partition Map for VirtIO device 0 -- Partition Type: EFI + + Part Start LBA End LBA Name + Attributes + Type GUID + Partition GUID + 1 0x00000040 0x0092b093 "ISO9660" + attrs: 0x1000000000000001 + type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 + guid: a0891d7e-b930-4513-94d8-f629dbd637b2 + 2 0x0092b094 0x0092d7e7 "Appended2" + attrs: 0x0000000000000000 + type: c12a7328-f81f-11d2-ba4b-00a0c93ec93b + guid: a0891d7e-b930-4513-94db-f629dbd637b2 + 3 0x0092d7e8 0x0092da3f "Gap1" + attrs: 0x1000000000000001 + type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 + guid: a0891d7e-b930-4513-94da-f629dbd637b2 + => ls virtio 0:3 + => part types + Supported partition tables: EFI, DOS, ISO + => part set virtio 0 dos + + Partition Map for VirtIO device 0 -- Partition Type: DOS + + Part Start Sector Num Sectors UUID Type + 1 1 9624191 00000000-01 ee + => part set virtio 0 iso + + Partition Map for VirtIO device 0 -- Partition Type: ISO + + Part Start Sect x Size Type + 1 3020 4 512 U-Boot + 2 9613460 10068 512 U-Boot + => part set virtio 0 efi + + Partition Map for VirtIO device 0 -- Partition Type: EFI + + Part Start LBA End LBA Name + Attributes + Type GUID + Partition GUID + 1 0x00000040 0x0092b093 "ISO9660" + attrs: 0x1000000000000001 + type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 + guid: a0891d7e-b930-4513-94d8-f629dbd637b2 + 2 0x0092b094 0x0092d7e7 "Appended2" + attrs: 0x0000000000000000 + type: c12a7328-f81f-11d2-ba4b-00a0c93ec93b + guid: a0891d7e-b930-4513-94db-f629dbd637b2 + 3 0x0092d7e8 0x0092da3f "Gap1" + attrs: 0x1000000000000001 + type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 + guid: a0891d7e-b930-4513-94da-f629dbd637b2 + => + Return value ------------ diff --git a/include/part.h b/include/part.h index be75c735495..3b1b5398699 100644 --- a/include/part.h +++ b/include/part.h @@ -598,6 +598,15 @@ static inline struct part_driver *part_driver_get_first(void) return ll_entry_start(struct part_driver, part_driver); } +/** + * part_get_type_by_name() - Get partition type by name + * + * @name: Name of partition type to look up (not case-sensitive) + * Returns: Corresponding partition type (PART_TYPE_...) or PART_TYPE_UNKNOWN if + * not known + */ +int part_get_type_by_name(const char *name); + #else static inline int part_driver_get_count(void) { return 0; } From d2e7972d7be6dc0078072b01e93c1502c4044e6a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:48 -0600 Subject: [PATCH 31/60] qfw: Show the file address if available Some files have an associated address. Show this with the 'qfw list' command so that it is possible to dump the data. Note that the reference to 'md' is for the md.rst file, not a markdown file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- cmd/qfw.c | 2 +- doc/usage/cmd/qfw.rst | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cmd/qfw.c b/cmd/qfw.c index ae3c6a7a84e..d6ecfa60d5a 100644 --- a/cmd/qfw.c +++ b/cmd/qfw.c @@ -26,7 +26,7 @@ static int qemu_fwcfg_cmd_list_firmware(void) for (file = qfw_file_iter_init(qfw_dev, &iter); !qfw_file_iter_end(&iter); file = qfw_file_iter_next(&iter)) { - printf("%-56s\n", file->cfg.name); + printf("%08lx %-56s\n", file->addr, file->cfg.name); } return 0; diff --git a/doc/usage/cmd/qfw.rst b/doc/usage/cmd/qfw.rst index cc0e27c2779..ec13e0967ae 100644 --- a/doc/usage/cmd/qfw.rst +++ b/doc/usage/cmd/qfw.rst @@ -41,18 +41,21 @@ QEMU firmware files are listed via the *qfw list* command: :: => qfw list - etc/boot-fail-wait - etc/smbios/smbios-tables - etc/smbios/smbios-anchor - etc/e820 - genroms/kvmvapic.bin - genroms/linuxboot.bin - etc/system-states - etc/acpi/tables - etc/table-loader - etc/tpm/log - etc/acpi/rsdp - bootorder + 00000000 bios-geometry + 00000000 bootorder + 000f0060 etc/acpi/rsdp + bed14040 etc/acpi/tables + 00000000 etc/boot-fail-wait + 00000000 etc/e820 + 00000000 etc/smbios/smbios-anchor + 00000000 etc/smbios/smbios-tables + 00000000 etc/system-states + 00000000 etc/table-loader + 00000000 etc/tpm/log + 00000000 genroms/kvmvapic.bin + +Where an address is shown, it indicates where the data is available for +inspection, e.g. using the :doc:`md`. The available CPUs can be shown via the *qfw cpus* command: From f98caa6ae3864451b38c52c6be17e6e53b6685ac Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:49 -0600 Subject: [PATCH 32/60] log: Tidy up an ambiguous comment Add a bit more detail so it is clear that multiple devices are supported, but only one per driver. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- common/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/log.c b/common/log.c index 6f02a25c593..b2de57fcb3b 100644 --- a/common/log.c +++ b/common/log.c @@ -437,7 +437,7 @@ int log_init(void) /* * We cannot add runtime data to the driver since it is likely stored * in rodata. Instead, set up a 'device' corresponding to each driver. - * We only support having a single device. + * We only support having a single device for each driver. */ INIT_LIST_HEAD((struct list_head *)&gd->log_head); while (drv < end) { From 854624c277295fe6c2de66c08750442969b5e584 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:50 -0600 Subject: [PATCH 33/60] qfw: Set the address of the ACPI tables Once the ACPI tables have been set up, record their address so that it is possible to list them with 'acpi list'. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/misc/qfw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 9ef95caa895..0a93feeb4b2 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -18,6 +18,7 @@ #include #include #include +#include #if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_SANDBOX) /* @@ -227,6 +228,9 @@ out: } free(table_loader); + + gd_set_acpi_start(acpi_get_rsdp_addr()); + return addr; } From 3710802ebfc42e24fa6b7f8b78f3d668dac1363e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:51 -0600 Subject: [PATCH 34/60] efi: Show all known UUIDs with CONFIG_CMD_EFIDEBUG The CMD_EFIDEBUG option enables debugging so it is reasonable to assume that all effects should be made to decode the dreaded UUIDs favoured by UEFI. Update the table to show them all when CONFIG_CMD_EFIDEBUG is enabled. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b0..ab30fbf9152 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -255,7 +255,7 @@ static const struct { EFI_CERT_TYPE_PKCS7_GUID, }, #endif -#ifdef CONFIG_EFI +#if defined(CONFIG_CMD_EFIDEBUG) || defined(CONFIG_EFI) { "EFI_LZMA_COMPRESSED", EFI_LZMA_COMPRESSED }, { "EFI_DXE_SERVICES", EFI_DXE_SERVICES }, { "EFI_HOB_LIST", EFI_HOB_LIST }, From 8f015d37813b398c9f2bde9bbf531278a399ad88 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:52 -0600 Subject: [PATCH 35/60] x86: Improve the trampoline in 64-bit mode At present this leaves the stack at the pre-relocation value. This is not ideal since we want to have U-Boot running entirely from the top of memory. In addition, the new global_data pointer is not actually used, since the global_data pointer itself is relocated, then the pre-relocation value is changed, so the effective value (after relocation) does not update. Adjust the implementation to follow the 32-bit code more closely, with a trampoline function which is passed the new stack and global_data pointer. This ensures that the correct values come through even when relocating. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/start64.S | 19 +++++++++++++++++++ arch/x86/include/asm/u-boot-x86.h | 11 +++++++++++ common/board_f.c | 12 +++++++----- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/arch/x86/cpu/start64.S b/arch/x86/cpu/start64.S index 7be834788b9..78e894d2a21 100644 --- a/arch/x86/cpu/start64.S +++ b/arch/x86/cpu/start64.S @@ -26,3 +26,22 @@ _start: /* Should not return here */ jmp . + +.globl board_init_f_r_trampoline64 +.type board_init_f_r_trampoline64, @function +board_init_f_r_trampoline64: + /* + * SDRAM has been initialised, U-Boot code has been copied into + * RAM, BSS has been cleared and relocation adjustments have been + * made. It is now time to jump into the in-RAM copy of U-Boot + * + * %eax = Address of top of new stack + */ + + /* Stack grows down from top of SDRAM */ + movq %rsi, %rsp + + /* New gd is in rdi */ + + /* Re-enter U-Boot by calling board_init_f_r() */ + call board_init_f_r diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 1d8aa320f53..02a8b0f1527 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -117,6 +117,17 @@ void __noreturn board_init_f_r_trampoline(ulong sp); */ void __noreturn board_init_f_r(void); +/* + * board_init_f_r_trampoline64() - jump to relocated address with new stack + * + * This is the 64-bit version + * + * @new_gd: New global_data pointer to use + * @sp: New stack pointer to pass on to board_init_r() + */ +void __noreturn board_init_f_r_trampoline64(struct global_data *new_gd, + ulong sp); + int arch_misc_init(void); /* Read the time stamp counter */ diff --git a/common/board_f.c b/common/board_f.c index 334d04af197..e5969ec9a27 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -729,8 +729,7 @@ static int fix_fdt(void) #endif /* ARM calls relocate_code from its crt0.S */ -#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \ - !CONFIG_IS_ENABLED(X86_64) +#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) static int jump_to_copy(void) { @@ -752,7 +751,11 @@ static int jump_to_copy(void) * (CPU cache) */ arch_setup_gd(gd->new_gd); - board_init_f_r_trampoline(gd->start_addr_sp); +# if CONFIG_IS_ENABLED(X86_64) + board_init_f_r_trampoline64(gd->new_gd, gd->start_addr_sp); +# else + board_init_f_r_trampoline(gd->start_addr_sp); +# endif #else relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr); #endif @@ -967,8 +970,7 @@ static const init_fnc_t init_sequence_f[] = { * watchdog device is not serviced is as small as possible. */ cyclic_unregister_all, -#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \ - !CONFIG_IS_ENABLED(X86_64) +#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) jump_to_copy, #endif NULL, From 0be0f205b974abb7b464e5b2819db47bbc6d5f1f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:53 -0600 Subject: [PATCH 36/60] bdinfo: Show the malloc base with the bdinfo command It is useful to see the base of the malloc region. This is visible when debugging but not in normal usage. Add it to the global data so that it can be shown. Signed-off-by: Simon Glass Reviewed-by: Nikhil M Jain Reviewed-by: Bin Meng Tested-by: Nikhil M Jain --- cmd/bdinfo.c | 1 + common/board_r.c | 7 ++++--- include/asm-generic/global_data.h | 13 +++++++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 44e6d6a972e..1fe13ca13a0 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -176,6 +176,7 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) if (IS_ENABLED(CONFIG_CMD_BDINFO_EXTRA)) { bdinfo_print_num_ll("stack ptr", (ulong)&bd); bdinfo_print_num_ll("ram_top ptr", (ulong)gd->ram_top); + bdinfo_print_num_l("malloc base", gd_malloc_start()); } arch_print_bdinfo(); diff --git a/common/board_r.c b/common/board_r.c index d798c00a80a..4aaa8940311 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -196,7 +196,7 @@ static int initr_barrier(void) static int initr_malloc(void) { - ulong malloc_start; + ulong start; #if CONFIG_VAL(SYS_MALLOC_F_LEN) debug("Pre-reloc malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr, @@ -207,8 +207,9 @@ static int initr_malloc(void) * This value MUST match the value of gd->start_addr_sp in board_f.c: * reserve_noncached(). */ - malloc_start = gd->relocaddr - TOTAL_MALLOC_LEN; - mem_malloc_init((ulong)map_sysmem(malloc_start, TOTAL_MALLOC_LEN), + start = gd->relocaddr - TOTAL_MALLOC_LEN; + gd_set_malloc_start(start); + mem_malloc_init((ulong)map_sysmem(start, TOTAL_MALLOC_LEN), TOTAL_MALLOC_LEN); return 0; } diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index a1e1b9d6400..8fc205ded1a 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -301,6 +301,12 @@ struct global_data { * @timebase_l: low 32 bits of timer */ unsigned int timebase_l; + /** + * @malloc_start: start of malloc() region + */ +#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA) + unsigned long malloc_start; +#endif #if CONFIG_VAL(SYS_MALLOC_F_LEN) /** * @malloc_base: base address of early malloc() @@ -560,6 +566,13 @@ static_assert(sizeof(struct global_data) == GD_SIZE); #define gd_event_state() NULL #endif +#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA) +#define gd_malloc_start() gd->malloc_start +#define gd_set_malloc_start(_val) gd->malloc_start = (_val) +#else +#define gd_malloc_start() 0 +#define gd_set_malloc_start(val) +#endif /** * enum gd_flags - global data flags * From 1dd00b1be82556c35a68c90b187a0f096192fd5f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:54 -0600 Subject: [PATCH 37/60] nvme: Provide more useful debugging messages When scanning fails it is useful to be able to decode what went wrong. Add some debugging for this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/nvme/nvme.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 74e7a5b0110..a7add66ab4d 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -578,17 +578,22 @@ static int nvme_set_queue_count(struct nvme_dev *dev, int count) return min(result & 0xffff, result >> 16) + 1; } -static void nvme_create_io_queues(struct nvme_dev *dev) +static int nvme_create_io_queues(struct nvme_dev *dev) { unsigned int i; + int ret; for (i = dev->queue_count; i <= dev->max_qid; i++) if (!nvme_alloc_queue(dev, i, dev->q_depth)) - break; + return log_msg_ret("all", -ENOMEM); - for (i = dev->online_queues; i <= dev->queue_count - 1; i++) - if (nvme_create_queue(dev->queues[i], i)) - break; + for (i = dev->online_queues; i <= dev->queue_count - 1; i++) { + ret = nvme_create_queue(dev->queues[i], i); + if (ret) + return log_msg_ret("cre", ret); + } + + return 0; } static int nvme_setup_io_queues(struct nvme_dev *dev) @@ -598,14 +603,18 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) nr_io_queues = 1; result = nvme_set_queue_count(dev, nr_io_queues); - if (result <= 0) + if (result <= 0) { + log_debug("Cannot set queue count (err=%dE)\n", result); return result; + } dev->max_qid = nr_io_queues; /* Free previously allocated queues */ nvme_free_queues(dev, nr_io_queues + 1); - nvme_create_io_queues(dev); + result = nvme_create_io_queues(dev); + if (result) + return result; return 0; } @@ -683,8 +692,11 @@ int nvme_scan_namespace(void) uclass_foreach_dev(dev, uc) { ret = device_probe(dev); - if (ret) + if (ret) { + log_err("Failed to probe '%s': err=%dE\n", dev->name, + ret); return ret; + } } return 0; @@ -842,8 +854,10 @@ int nvme_init(struct udevice *udev) ndev->dbs = ((void __iomem *)ndev->bar) + 4096; ret = nvme_configure_admin_queue(ndev); - if (ret) + if (ret) { + log_debug("Unable to configure admin queue (err=%dE)\n", ret); goto free_queue; + } /* Allocate after the page size is known */ ndev->prp_pool = memalign(ndev->page_size, MAX_PRP_POOL); @@ -855,8 +869,10 @@ int nvme_init(struct udevice *udev) ndev->prp_entry_num = MAX_PRP_POOL >> 3; ret = nvme_setup_io_queues(ndev); - if (ret) + if (ret) { + log_debug("Unable to setup I/O queues(err=%dE)\n", ret); goto free_queue; + } nvme_get_info_from_identify(ndev); From db3820a2883ada53ca704fc393148657e44e0706 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:55 -0600 Subject: [PATCH 38/60] pci: Support autoconfig in SPL Allow PCI autoconfig to be handled in SPL, so that we can set it up correctly for boards which need to do this before U-Boot proper. This includes qemu-x64_64 which needs to set up the video device while in 32-bit mode. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/Kconfig | 5 +++++ drivers/pci/pci-uclass.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 84a2ae951f7..aca439d9213 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -44,8 +44,13 @@ config SPL_PCI_PNP bool "Enable Plug & Play support for PCI" help Enable PCI memory and I/O space resource allocation and assignment. + This is required to auto configure the enumerated devices. + This is normally not done in SPL, but can be enabled if devices must + be set up in the SPL phase. Often it is enough to manually configure + one device, so this option can be disabled. + config PCI_REGION_MULTI_ENTRY bool "Enable Multiple entries of region type MEMORY in ranges for PCI" help diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 8d27e40338c..632c1a63cfc 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -722,6 +723,9 @@ static bool pci_need_device_pre_reloc(struct udevice *bus, uint vendor, u32 vendev; int index; + if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(PCI_PNP)) + return true; + for (index = 0; !dev_read_u32_index(bus, "u-boot,pci-pre-reloc", index, &vendev); @@ -793,7 +797,9 @@ static int pci_find_and_bind_driver(struct udevice *parent, * space is pretty limited (ie: using Cache As RAM). */ if (!(gd->flags & GD_FLG_RELOC) && - !(drv->flags & DM_FLAG_PRE_RELOC)) + !(drv->flags & DM_FLAG_PRE_RELOC) && + (!CONFIG_IS_ENABLED(PCI_PNP) || + spl_phase() != PHASE_SPL)) return log_msg_ret("pre", -EPERM); /* @@ -918,6 +924,8 @@ int pci_bind_bus_devices(struct udevice *bus) } ret = pci_find_and_bind_driver(bus, &find_id, bdf, &dev); + } else { + debug("device: %s\n", dev->name); } if (ret == -EPERM) continue; From d424553675e93495f346ea7b24beb8c3dd750c67 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:57 -0600 Subject: [PATCH 39/60] pci: Tidy up logging and reporting for video BIOS When running the ROM the code is not very helpful when something goes wrong. Add a little more debugging and some logging of return values to improve this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index f0dfe631490..51dcdf9749a 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -254,14 +254,16 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), ret = pci_rom_probe(dev, &rom); if (ret) - return ret; + return log_msg_ret("pro", ret); ret = pci_rom_load(rom, &ram, &alloced); - if (ret) + if (ret) { + ret = log_msg_ret("ld", ret); goto err; + } if (!board_should_run_oprom(dev)) { - ret = -ENXIO; + ret = log_msg_ret("run", -ENXIO); goto err; } @@ -299,21 +301,25 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), #ifdef CONFIG_BIOSEMU BE_VGAInfo *info; + log_debug("Running video BIOS with emulator..."); ret = biosemu_setup(dev, &info); if (ret) goto err; biosemu_set_interrupt_handler(0x15, int15_handler); ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, true, vesa_mode, &mode_info); + log_debug("done\n"); if (ret) goto err; #endif } else { #if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL) + log_debug("Running video BIOS..."); bios_set_interrupt_handler(0x15, int15_handler); bios_run_on_x86(dev, (unsigned long)ram, vesa_mode, &mode_info); + log_debug("done\n"); #endif } debug("Final vesa mode %#x\n", mode_info.video_mode); From 5345700d2af425a8c5a36c078db5d71bf31280c7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:58 -0600 Subject: [PATCH 40/60] x86: Allow video-BIOS code to be built for SPL With qemu-x86_64 we need to run the video BIOS while in 32-bit mode, i.e. SPL. Add a Kconfig option for this, adjust the Makefile rules and use CONFIG_IS_ENABLED() where needed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/Makefile | 7 ++++--- arch/x86/lib/bios.c | 2 +- drivers/pci/pci_rom.c | 26 +++++++++++++------------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b0612ae6dd5..90a7618ecfd 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -4,16 +4,17 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y += bdinfo.o -ifndef CONFIG_X86_64 -ifndef CONFIG_TPL_BUILD + +ifndef CONFIG_$(SPL_TPL_)X86_64 obj-y += bios.o obj-y += bios_asm.o obj-y += bios_interrupts.o endif -endif + ifndef CONFIG_SPL_BUILD obj-$(CONFIG_X86_32BIT_INIT) += string.o endif + ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o endif diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 8cc686fd146..e29cae78e50 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -23,7 +23,7 @@ static int (*int_handler[256])(void); /* to have a common register file for interrupt handlers */ -#ifndef CONFIG_BIOSEMU +#if !CONFIG_IS_ENABLED(BIOSEMU) X86EMU_sysEnv _X86EMU_env; #endif diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 51dcdf9749a..228ab7fca72 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -298,20 +298,20 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), } if (emulate) { -#ifdef CONFIG_BIOSEMU - BE_VGAInfo *info; + if (CONFIG_IS_ENABLED(BIOSEMU)) { + BE_VGAInfo *info; - log_debug("Running video BIOS with emulator..."); - ret = biosemu_setup(dev, &info); - if (ret) - goto err; - biosemu_set_interrupt_handler(0x15, int15_handler); - ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, - true, vesa_mode, &mode_info); - log_debug("done\n"); - if (ret) - goto err; -#endif + log_debug("Running video BIOS with emulator..."); + ret = biosemu_setup(dev, &info); + if (ret) + goto err; + biosemu_set_interrupt_handler(0x15, int15_handler); + ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, + true, vesa_mode, &mode_info); + log_debug("done\n"); + if (ret) + goto err; + } } else { #if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL) log_debug("Running video BIOS..."); From 03fe79c091cee0bd591070dd24adfa8f556b50df Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:59 -0600 Subject: [PATCH 41/60] x86: Pass video settings from SPL to U-Boot proper When video is set up in SPL, U-Boot proper needs to use the correct parameters so it can write to the display. Put these in a bloblist so they are available to U-Boot proper. Signed-off-by: Simon Glass Reviewed-by: Nikhil M Jain Reviewed-by: Bin Meng --- common/bloblist.c | 1 + drivers/pci/pci_rom.c | 78 +++++++++++++++++++++++++++++++------------ include/bloblist.h | 1 + include/video.h | 24 +++++++++++++ 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/common/bloblist.c b/common/bloblist.c index 0d63b6e8817..2144b10e1d0 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -51,6 +51,7 @@ static struct tag_name { /* BLOBLISTT_PROJECT_AREA */ { BLOBLISTT_U_BOOT_SPL_HANDOFF, "SPL hand-off" }, + { BLOBLISTT_U_BOOT_VIDEO, "SPL video handoff" }, /* BLOBLISTT_VENDOR_AREA */ }; diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 228ab7fca72..bdfd1f03e79 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -374,34 +376,68 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void)) printf("Not available (previous bootloader prevents it)\n"); return -EPERM; } - bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); - ret = dm_pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE | - PCI_ROM_ALLOW_FALLBACK); - bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); - if (ret) { - debug("failed to run video BIOS: %d\n", ret); - return ret; - } - ret = vesa_setup_video_priv(&mode_info.vesa, - mode_info.vesa.phys_base_ptr, uc_priv, - plat); - if (ret) { - if (ret == -ENFILE) { - /* - * See video-uclass.c for how to set up reserved memory - * in your video driver - */ - log_err("CONFIG_VIDEO_COPY enabled but driver '%s' set up no reserved memory\n", - dev->driver->name); + /* In U-Boot proper, collect the information added by SPL (see below) */ + if (IS_ENABLED(CONFIG_SPL_VIDEO) && spl_phase() > PHASE_SPL && + CONFIG_IS_ENABLED(BLOBLIST)) { + struct video_handoff *ho; + + ho = bloblist_find(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho)); + if (!ho) + return log_msg_ret("blf", -ENOENT); + plat->base = ho->fb; + plat->size = ho->size; + uc_priv->xsize = ho->xsize; + uc_priv->ysize = ho->ysize; + uc_priv->line_length = ho->line_length; + uc_priv->bpix = ho->bpix; + } else { + bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); + ret = dm_pci_run_vga_bios(dev, int15_handler, + PCI_ROM_USE_NATIVE | + PCI_ROM_ALLOW_FALLBACK); + bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); + if (ret) { + debug("failed to run video BIOS: %d\n", ret); + return ret; } - debug("No video mode configured\n"); - return ret; + ret = vesa_setup_video_priv(&mode_info.vesa, + mode_info.vesa.phys_base_ptr, + uc_priv, plat); + if (ret) { + if (ret == -ENFILE) { + /* + * See video-uclass.c for how to set up reserved + * memory in your video driver + */ + log_err("CONFIG_VIDEO_COPY enabled but driver '%s' set up no reserved memory\n", + dev->driver->name); + } + + debug("No video mode configured\n"); + return ret; + } } printf("Video: %dx%dx%d\n", uc_priv->xsize, uc_priv->ysize, mode_info.vesa.bits_per_pixel); + /* In SPL, store the information for use by U-Boot proper */ + if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(BLOBLIST)) { + struct video_handoff *ho; + + ho = bloblist_add(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho), 0); + if (!ho) + return log_msg_ret("blc", -ENOMEM); + + ho->fb = plat->base; + ho->size = plat->size; + ho->xsize = uc_priv->xsize; + ho->ysize = uc_priv->ysize; + ho->line_length = uc_priv->line_length; + ho->bpix = uc_priv->bpix; + } + return 0; } diff --git a/include/bloblist.h b/include/bloblist.h index 2a2f1700eb0..7ea72c6bd46 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -113,6 +113,7 @@ enum bloblist_tag_t { BLOBLISTT_PROJECT_AREA = 0x8000, BLOBLISTT_U_BOOT_SPL_HANDOFF = 0x8000, /* Hand-off info from SPL */ BLOBLISTT_VBE = 0x8001, /* VBE per-phase state */ + BLOBLISTT_U_BOOT_VIDEO = 0x8002, /* Video information from SPL */ /* * Vendor-specific tags are permitted here. Projects can be open source diff --git a/include/video.h b/include/video.h index e98d0f9c895..9729fa348aa 100644 --- a/include/video.h +++ b/include/video.h @@ -134,6 +134,30 @@ struct video_ops { #define video_get_ops(dev) ((struct video_ops *)(dev)->driver->ops) +/** + * struct video_handoff - video information passed from SPL + * + * This is used when video is set up by SPL, to provide the details to U-Boot + * proper. + * + * @fb: Base address of frame buffer, 0 if not yet known + * @size: Frame-buffer size, in bytes + * @xsize: Number of pixel columns (e.g. 1366) + * @ysize: Number of pixels rows (e.g.. 768) + * @line_length: Length of each frame buffer line, in bytes. This can be + * set by the driver, but if not, the uclass will set it after + * probing + * @bpix: Encoded bits per pixel (enum video_log2_bpp) + */ +struct video_handoff { + u64 fb; + u32 size; + u16 xsize; + u16 ysize; + u32 line_length; + u8 bpix; +}; + /** enum colour_idx - the 16 colors supported by consoles */ enum colour_idx { VID_BLACK = 0, From 352525801992799b9bb289e3233a8b17bcf2bc52 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:00 -0600 Subject: [PATCH 42/60] x86: Ensure SPL banner is only shown once Print the banner in SPL init only if the spl_board_init() function isn't enabled. The spl_board_init() function is in the same file, but is called later, by board_init_r(). This avoids printing two banners, which causes tests to fail. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/spl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index b9d23e6bfe1..f27501875ec 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -97,7 +97,13 @@ static int x86_spl_init(void) return ret; } #endif - preloader_console_init(); + /* + * spl_board_init() below sets up the console if enabled. If it isn't, + * do it here. We cannot call this twice since it results in a double + * banner and CI tests fail. + */ + if (!IS_ENABLED(CONFIG_SPL_BOARD_INIT)) + preloader_console_init(); #if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU) ret = print_cpuinfo(); if (ret) { From 7c10e111c18d73e1bb9c64c79e778c9976900d05 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:01 -0600 Subject: [PATCH 43/60] x86: Init video in SPL if enabled When video is required in SPL, set this up ready for use. Ignore any problems since it may be that video is not actually available and we still want to continue on to U-Boot proper in that case. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/spl.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index f27501875ec..039f219f50a 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -263,4 +264,12 @@ void spl_board_init(void) #ifndef CONFIG_TPL preloader_console_init(); #endif + + if (CONFIG_IS_ENABLED(VIDEO)) { + struct udevice *dev; + + /* Set up PCI video in SPL if required */ + uclass_first_device_err(UCLASS_PCI, &dev); + uclass_first_device_err(UCLASS_VIDEO, &dev); + } } From b7d4df5a04733c19747de80b9dfdfdee58c9850d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:02 -0600 Subject: [PATCH 44/60] pci: Adjust video BIOS debugging to be SPL-friendly A hex value is expected for the VGA mode. Add a 0x prefix, since the # construct is not supported in SPL. We don't want to add it, due to code-size constraints. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index bdfd1f03e79..503feb1e6d4 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -273,7 +273,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), defined(CONFIG_FRAMEBUFFER_VESA_MODE) vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE; #endif - debug("Selected vesa mode %#x\n", vesa_mode); + debug("Selected vesa mode 0x%x\n", vesa_mode); if (exec_method & PCI_ROM_USE_NATIVE) { #ifdef CONFIG_X86 @@ -324,7 +324,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), log_debug("done\n"); #endif } - debug("Final vesa mode %#x\n", mode_info.video_mode); + debug("Final vesa mode %x\n", mode_info.video_mode); ret = 0; err: From fa5690c1f53929b78f9d9f4e270bd64befcda755 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:03 -0600 Subject: [PATCH 45/60] pci: Mask the ROM address in case it is already enabled In some cases the video ROM may have been enabled previously, such as by a previous firmware stage. Use the correct address in that case. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 503feb1e6d4..438583aa017 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -93,6 +93,7 @@ static int pci_rom_probe(struct udevice *dev, struct pci_rom_header **hdrp) debug("%s: rom_address=%x\n", __func__, rom_address); return -ENOENT; } + rom_address &= PCI_ROM_ADDRESS_MASK; /* Enable expansion ROM address decoding. */ dm_pci_write_config32(dev, PCI_ROM_ADDRESS, From fa5e2030922b561d5f9ea6c86295f5903e3d878c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:04 -0600 Subject: [PATCH 46/60] x86: Enable display for QEMU 64-bit Enable the various options needed for display to work on the qemu-x86_64 board. This includes expanding the available malloc() memory in SPL, since the PCI bus must be enumerated in order to find the video device. It also includes enabling a bloblist, so that the video parameters can be passed. This is placed at address 10000 but is not needed after U-Boot proper reads the information there. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- configs/qemu-x86_64_defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 5dfad36ba52..70b10c5a80c 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -7,6 +7,7 @@ CONFIG_MAX_CPUS=2 CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx" CONFIG_SPL_TEXT_BASE=0xfffd8000 +CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 CONFIG_DEBUG_UART_BASE=0x3f8 CONFIG_DEBUG_UART_CLOCK=1843200 CONFIG_X86_RUN_64BIT=y @@ -30,7 +31,10 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_PCI_INIT_R=y +CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_ADDR=0x10000 CONFIG_SPL_NO_BSS_LIMIT=y +CONFIG_SPL_BOARD_INIT=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_CPU=y CONFIG_SPL_ENV_SUPPORT=y @@ -69,10 +73,12 @@ CONFIG_LBA48=y CONFIG_SYS_64BIT_LBA=y CONFIG_CPU=y CONFIG_NVME_PCI=y +CONFIG_SPL_PCI_PNP=y CONFIG_SPL_DM_RTC=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y +CONFIG_SPL_VIDEO=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_USER=y CONFIG_FRAMEBUFFER_VESA_MODE=0x144 From e7595aa350ae61e3dfefbde8fe3af01c12b65ccf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:05 -0600 Subject: [PATCH 47/60] x86: Allow logging to be used in SPL reliably When global_data is relocated, log_head moves in memory, meaning that the items in that list point to the wrong place. Disable logging when making the change, then reenable it afterwards, so that logging works normally. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/spl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 039f219f50a..92a5e6aec71 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -144,9 +144,22 @@ static int x86_spl_init(void) */ gd->new_gd = (struct global_data *)ptr; memcpy(gd->new_gd, gd, sizeof(*gd)); + + /* + * Make sure logging is disabled when we switch, since the log system + * list head will move + */ + gd->new_gd->flags &= ~GD_FLG_LOG_READY; arch_setup_gd(gd->new_gd); gd->start_addr_sp = (ulong)ptr; + /* start up logging again, with the new list-head location */ + ret = log_init(); + if (ret) { + log_debug("Log setup failed (err=%d)\n", ret); + return ret; + } + if (_LOG_DEBUG) { ret = mtrr_list(mtrr_get_var_count(), MP_SELECT_BSP); if (ret) From 78211de6002734c6cf7c39c21990f6ba2cc5c965 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:06 -0600 Subject: [PATCH 48/60] fs: fat: Shrink the size of a few strings To save a few bytes, replace Error with ** and try to use the same string for multiple messages where possible. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- fs/fat/fat.c | 20 +++++++++++--------- fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf..d1476aa433d 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -8,6 +8,8 @@ * 2003-03-10 - kharris@nexus-tech.net - ported to uboot */ +#define LOG_CATEGORY LOGC_FS + #include #include #include @@ -97,8 +99,8 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no) /* Read the partition table, if present */ if (part_get_info(dev_desc, part_no, &info)) { if (part_no != 0) { - printf("** Partition %d not valid on device %d **\n", - part_no, dev_desc->devnum); + log_err("Partition %d invalid on device %d\n", part_no, + dev_desc->devnum); return -1; } @@ -168,7 +170,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry) __u32 ret = 0x00; if (CHECK_CLUST(entry, mydata->fatsize)) { - printf("Error: Invalid FAT entry: 0x%08x\n", entry); + log_err("Invalid FAT entry: %#08x\n", entry); return ret; } @@ -586,19 +588,19 @@ static int get_fs_info(fsdata *mydata) mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0]; mydata->clust_size = bs.cluster_size; if (mydata->sect_size != cur_part_info.blksz) { - printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n", - mydata->sect_size, cur_part_info.blksz); + log_err("FAT sector size mismatch (fs=%u, dev=%lu)\n", + mydata->sect_size, cur_part_info.blksz); return -1; } if (mydata->clust_size == 0) { - printf("Error: FAT cluster size not set\n"); + log_err("FAT cluster size not set\n"); return -1; } if ((unsigned int)mydata->clust_size * mydata->sect_size > MAX_CLUSTSIZE) { - printf("Error: FAT cluster size too big (cs=%u, max=%u)\n", - (unsigned int)mydata->clust_size * mydata->sect_size, - MAX_CLUSTSIZE); + log_err("FAT cluster size too big (cs=%u, max=%u)\n", + (uint)mydata->clust_size * mydata->sect_size, + MAX_CLUSTSIZE); return -1; } diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 413fc432ebe..e2a9913f807 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -1571,8 +1571,9 @@ int fat_unlink(const char *filename) char *filename_copy, *dirname, *basename; filename_copy = strdup(filename); - if (!filename_copy) { - printf("Error: allocating memory\n"); + itr = malloc_cache_aligned(sizeof(fat_itr)); + if (!itr || !filename_copy) { + printf("Error: out of memory\n"); ret = -ENOMEM; goto exit; } @@ -1584,13 +1585,6 @@ int fat_unlink(const char *filename) goto exit; } - itr = malloc_cache_aligned(sizeof(fat_itr)); - if (!itr) { - printf("Error: allocating memory\n"); - ret = -ENOMEM; - goto exit; - } - ret = fat_itr_root(itr, &fsdata); if (ret) goto exit; @@ -1605,7 +1599,7 @@ int fat_unlink(const char *filename) } if (!find_directory_entry(itr, basename)) { - printf("%s: doesn't exist\n", basename); + log_err("%s: doesn't exist (%d)\n", basename, -ENOENT); ret = -ENOENT; goto exit; } From 24e7c3e9fcb7cb1987456140fd57ae390be3f645 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:08 -0600 Subject: [PATCH 49/60] x86: Enable useful options for qemu-86_64 This build can be used to boot standard distro builds, since these are mostly 64-bit these days. Enable some more options, so that all possible EFI UUIDs are decoded, we get a proper printf() in SPL, can search memory for tables, support the full set of standard-boot features, have full logging and can boot from CDROM media. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- configs/qemu-x86_64_defconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 70b10c5a80c..b1400876a2f 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -20,6 +20,7 @@ CONFIG_GENERATE_MP_TABLE=y CONFIG_X86_OFFSET_U_BOOT=0xfff00000 CONFIG_FIT=y CONFIG_SPL_LOAD_FIT=y +CONFIG_BOOTSTD_FULL=y CONFIG_SYS_MONITOR_BASE=0x01110000 CONFIG_BOOTSTD_DEFAULTS=y CONFIG_BOOTSTAGE=y @@ -28,6 +29,9 @@ CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" CONFIG_SYS_CONSOLE_INFO_QUIET=y +CONFIG_LOG=y +CONFIG_LOGF_FUNC=y +CONFIG_SPL_LOG=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_PCI_INIT_R=y @@ -47,11 +51,13 @@ CONFIG_SYS_PBSIZE=532 CONFIG_CMD_CPU=y CONFIG_CMD_BOOTEFI_SELFTEST=y CONFIG_CMD_NVEDIT_EFI=y +CONFIG_CMD_MEM_SEARCH=y CONFIG_CMD_IDE=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y # CONFIG_CMD_SETEXPR is not set CONFIG_BOOTP_BOOTFILESIZE=y +CONFIG_CMD_EFIDEBUG=y CONFIG_CMD_TIME=y CONFIG_CMD_QFW=y CONFIG_CMD_BOOTSTAGE=y @@ -83,5 +89,7 @@ CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_USER=y CONFIG_FRAMEBUFFER_VESA_MODE=0x144 CONFIG_CONSOLE_SCROLL_LINES=5 +CONFIG_FAT_BLK_XLATE=y +# CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_GENERATE_ACPI_TABLE=y # CONFIG_GZIP is not set From 8856d613cb79876e1b1e1ef01b7507725810b7c5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:09 -0600 Subject: [PATCH 50/60] x86: Refactor table-writing code a little The implementation of write_tables() is confusing because it uses the rom_table_start variable as the address pointer as it progresses. Rename it to rom_addr to make the code clearer. Move the rom_table_end variable into the block where it is used. Also update logging to use the ACPI category, now that it is available. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/tables.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index ea834a5035f..772c04f1e55 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -3,7 +3,7 @@ * Copyright (C) 2015, Bin Meng */ -#define LOG_CATEGORY LOGC_BOARD +#define LOG_CATEGORY LOGC_ACPI #include #include @@ -78,33 +78,33 @@ void table_fill_string(char *dest, const char *src, size_t n, char pad) int write_tables(void) { - u32 rom_table_start; - u32 rom_table_end; u32 high_table, table_size; struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1]; + u32 rom_addr; int i; - rom_table_start = ROM_TABLE_ADDR; + rom_addr = ROM_TABLE_ADDR; - debug("Writing tables to %x:\n", rom_table_start); + debug("Writing tables to %x:\n", rom_addr); for (i = 0; i < ARRAY_SIZE(table_list); i++) { const struct table_info *table = &table_list[i]; int size = table->size ? : CONFIG_ROM_TABLE_SIZE; + u32 rom_table_end; if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) { - rom_table_start = (ulong)bloblist_add(table->tag, size, - table->align); - if (!rom_table_start) + rom_addr = (ulong)bloblist_add(table->tag, size, + table->align); + if (!rom_addr) return log_msg_ret("bloblist", -ENOBUFS); } - rom_table_end = table->write(rom_table_start); + rom_table_end = table->write(rom_addr); if (!rom_table_end) { log_err("Can't create configuration table %d\n", i); return -EINTR; } if (IS_ENABLED(CONFIG_SEABIOS)) { - table_size = rom_table_end - rom_table_start; + table_size = rom_table_end - rom_addr; high_table = (u32)(ulong)high_table_malloc(table_size); if (high_table) { if (!table->write(high_table)) { @@ -123,13 +123,13 @@ int write_tables(void) } debug("- wrote '%s' to %x, end %x\n", table->name, - rom_table_start, rom_table_end); - if (rom_table_end - rom_table_start > size) { + rom_addr, rom_table_end); + if (rom_table_end - rom_addr > size) { log_err("Out of space for configuration tables: need %x, have %x\n", - rom_table_end - rom_table_start, size); + rom_table_end - rom_addr, size); return log_msg_ret("bloblist", -ENOSPC); } - rom_table_start = rom_table_end; + rom_addr = rom_table_end; } if (IS_ENABLED(CONFIG_SEABIOS)) { From 6a324897825acdd54f31aeebfe0d29b7f6ab4d86 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:10 -0600 Subject: [PATCH 51/60] x86: Record the start and end of the tables The ACPI tables are special in that they are passed to EFI as a separate piece, independent of other tables. Also they can be spread over two areas of memory, e.g. with QEMU we end up with tables kept in high memory as well. Add new global_data fields to hold this information and update the bdinfo command to show the table areas. Move the rom_table_end variable into the loop that uses it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/include/asm/global_data.h | 4 ++++ arch/x86/include/asm/global_data.h | 4 ++++ arch/x86/lib/bdinfo.c | 4 ++++ arch/x86/lib/tables.c | 20 +++++++++++++++++++- drivers/misc/qfw.c | 9 +++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h index f4ce72d5660..f0ab3ba5c14 100644 --- a/arch/sandbox/include/asm/global_data.h +++ b/arch/sandbox/include/asm/global_data.h @@ -13,6 +13,10 @@ struct arch_global_data { uint8_t *ram_buf; /* emulated RAM buffer */ void *text_base; /* pointer to base of text region */ + ulong table_start; /* Start address of x86 tables */ + ulong table_end; /* End address of x86 tables */ + ulong table_start_high; /* Start address of high x86 tables */ + ulong table_end_high; /* End address of high x86 tables */ }; #include diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 22d103df4ee..ea58259ad77 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -123,6 +123,10 @@ struct arch_global_data { #endif void *itss_priv; /* Private ITSS data pointer */ ulong coreboot_table; /* Address of coreboot table */ + ulong table_start; /* Start address of x86 tables */ + ulong table_end; /* End address of x86 tables */ + ulong table_start_high; /* Start address of high x86 tables */ + ulong table_end_high; /* End address of high x86 tables */ }; #endif diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c index a20d0954416..124058442c5 100644 --- a/arch/x86/lib/bdinfo.c +++ b/arch/x86/lib/bdinfo.c @@ -23,6 +23,10 @@ void arch_print_bdinfo(void) bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor)); bdinfo_print_num_l("model", gd->arch.x86_model); bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size()); + bdinfo_print_num_l("table start", gd->arch.table_start); + bdinfo_print_num_l("table end", gd->arch.table_end); + bdinfo_print_num_l(" high start", gd->arch.table_start_high); + bdinfo_print_num_l(" high end", gd->arch.table_end_high); if (IS_ENABLED(CONFIG_EFI_STUB)) efi_show_bdinfo(); diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 772c04f1e55..67bc0a72aeb 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -54,6 +54,10 @@ static struct table_info table_list[] = { #ifdef CONFIG_GENERATE_MP_TABLE { "mp", write_mp_table, }, #endif + /* + * tables which can go in the bloblist must be last in this list, so + * that the calculation of gd->table_end works properly + */ #ifdef CONFIG_GENERATE_ACPI_TABLE { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000}, #endif @@ -80,10 +84,12 @@ int write_tables(void) { u32 high_table, table_size; struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1]; + bool use_high = false; u32 rom_addr; int i; - rom_addr = ROM_TABLE_ADDR; + gd->arch.table_start = ROM_TABLE_ADDR; + rom_addr = gd->arch.table_start; debug("Writing tables to %x:\n", rom_addr); for (i = 0; i < ARRAY_SIZE(table_list); i++) { @@ -92,10 +98,17 @@ int write_tables(void) u32 rom_table_end; if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) { + if (!gd->arch.table_end) + gd->arch.table_end = rom_addr; rom_addr = (ulong)bloblist_add(table->tag, size, table->align); if (!rom_addr) return log_msg_ret("bloblist", -ENOBUFS); + + /* the bloblist is always in high memory */ + use_high = true; + if (!gd->arch.table_start_high) + gd->arch.table_start_high = rom_addr; } rom_table_end = table->write(rom_addr); if (!rom_table_end) { @@ -132,6 +145,11 @@ int write_tables(void) rom_addr = rom_table_end; } + if (use_high) + gd->arch.table_end_high = rom_addr; + else + gd->arch.table_end = rom_addr; + if (IS_ENABLED(CONFIG_SEABIOS)) { /* make sure the last item is zero */ cfg_tables[i].size = 0; diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 0a93feeb4b2..7c01bf23d53 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -65,6 +65,11 @@ static int bios_linker_allocate(struct udevice *dev, printf("error: allocating resource\n"); return -ENOMEM; } + if (aligned_addr < gd->arch.table_start_high) + gd->arch.table_start_high = aligned_addr; + if (aligned_addr + size > gd->arch.table_end_high) + gd->arch.table_end_high = aligned_addr + size; + } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) { aligned_addr = ALIGN(*addr, align); } else { @@ -189,6 +194,10 @@ ulong write_acpi_tables(ulong addr) return addr; } + /* QFW always puts tables at high addresses */ + gd->arch.table_start_high = (ulong)table_loader; + gd->arch.table_end_high = (ulong)table_loader; + qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader); for (i = 0; i < (size / sizeof(*entry)); i++) { From e2e7de874766a1e7b21a7174bf88efa2ef6b6e56 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:11 -0600 Subject: [PATCH 52/60] x86: Convert some debug statements to use logging Move from using debug() to log_debug() so that we don't have to use the __func__ parameter and can access other logging features. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/intel_common/mrc.c | 10 +++++----- arch/x86/cpu/ivybridge/sdram.c | 4 +++- arch/x86/lib/mrccache.c | 6 ++++-- arch/x86/lib/spl.c | 22 ++++++++++++++-------- drivers/gpio/intel_ich6_gpio.c | 5 +++-- drivers/pch/pch9.c | 6 ++++-- 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/arch/x86/cpu/intel_common/mrc.c b/arch/x86/cpu/intel_common/mrc.c index 69405d740b4..56cc253831a 100644 --- a/arch/x86/cpu/intel_common/mrc.c +++ b/arch/x86/cpu/intel_common/mrc.c @@ -3,6 +3,8 @@ * Copyright (c) 2016 Google, Inc */ +#define LOG_CATEGORY UCLASS_RAM + #include #include #include @@ -144,12 +146,10 @@ int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap) ret = gpio_request_list_by_name(dev, "board-id-gpios", desc, ARRAY_SIZE(desc), GPIOD_IS_IN); - if (ret < 0) { - debug("%s: gpio ret=%d\n", __func__, ret); - return ret; - } + if (ret < 0) + return log_msg_ret("gpio", ret); spd_index = dm_gpio_get_values_as_int(desc, ret); - debug("spd index %d\n", spd_index); + log_debug("spd index %d\n", spd_index); node = fdt_first_subnode(blob, dev_of_offset(dev)); if (node < 0) diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 1a0ec433e65..0718aefbb1f 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -9,6 +9,8 @@ * Copyright (C) 2011 Google Inc. */ +#define LOG_CATEGORY UCLASS_RAM + #include #include #include @@ -213,7 +215,7 @@ static int copy_spd(struct udevice *dev, struct pei_data *peid) ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data); if (ret) { - debug("%s: Could not locate SPD (ret=%d)\n", __func__, ret); + log_debug("Could not locate SPD (err=%d)\n", ret); return ret; } diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index 2f6f6880003..6494b8d2634 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -6,6 +6,8 @@ * Copyright (C) 2015 Bin Meng */ +#define LOG_CATEGORY UCLASS_RAM + #include #include #include @@ -197,8 +199,8 @@ static void mrccache_setup(struct mrc_output *mrc, void *data) cache->signature = MRC_DATA_SIGNATURE; cache->data_size = mrc->len; checksum = compute_ip_checksum(mrc->buf, cache->data_size); - debug("Saving %d bytes for MRC output data, checksum %04x\n", - cache->data_size, checksum); + log_debug("Saving %d bytes for MRC output data, checksum %04x\n", + cache->data_size, checksum); cache->checksum = checksum; cache->reserved = 0; memcpy(cache->data, mrc->buf, cache->data_size); diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 92a5e6aec71..ba3434b055c 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -3,6 +3,8 @@ * Copyright (c) 2016 Google, Inc */ +#define LOG_CATEGORY LOGC_BOOT + #include #include #include @@ -76,25 +78,25 @@ static int x86_spl_init(void) #endif int ret; - debug("%s starting\n", __func__); + log_debug("x86 spl starting\n"); if (IS_ENABLED(TPL)) ret = x86_cpu_reinit_f(); else ret = x86_cpu_init_f(); ret = spl_init(); if (ret) { - debug("%s: spl_init() failed\n", __func__); + log_debug("spl_init() failed (err=%d)\n", ret); return ret; } ret = arch_cpu_init(); if (ret) { - debug("%s: arch_cpu_init() failed\n", __func__); + log_debug("arch_cpu_init() failed (err=%d)\n", ret); return ret; } #ifndef CONFIG_TPL ret = fsp_setup_pinctrl(NULL, NULL); if (ret) { - debug("%s: fsp_setup_pinctrl() failed\n", __func__); + log_debug("fsp_setup_pinctrl() failed (err=%d)\n", ret); return ret; } #endif @@ -108,23 +110,25 @@ static int x86_spl_init(void) #if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU) ret = print_cpuinfo(); if (ret) { - debug("%s: print_cpuinfo() failed\n", __func__); + log_debug("print_cpuinfo() failed (err=%d)\n", ret); return ret; } #endif ret = dram_init(); if (ret) { - debug("%s: dram_init() failed\n", __func__); + log_debug("dram_init() failed (err=%d)\n", ret); return ret; } + log_debug("mrc\n"); if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) { ret = mrccache_spl_save(); if (ret) - debug("%s: Failed to write to mrccache (err=%d)\n", - __func__, ret); + log_debug("Failed to write to mrccache (err=%d)\n", + ret); } #ifndef CONFIG_SYS_COREBOOT + log_debug("bss\n"); debug("BSS clear from %lx to %lx len %lx\n", (ulong)&__bss_start, (ulong)&__bss_end, (ulong)&__bss_end - (ulong)&__bss_start); memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start); @@ -145,6 +149,7 @@ static int x86_spl_init(void) gd->new_gd = (struct global_data *)ptr; memcpy(gd->new_gd, gd, sizeof(*gd)); + log_debug("logging\n"); /* * Make sure logging is disabled when we switch, since the log system * list head will move @@ -184,6 +189,7 @@ static int x86_spl_init(void) debug("Failed to set CPU frequency (err=%d)\n", ret); # endif #endif + log_debug("done\n"); return 0; } diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index 63a07b9592a..2ed0d0bea9a 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -26,6 +26,8 @@ * reserved or subject to arcane restrictions. */ +#define LOG_CATEGORY UCLASS_GPIO + #include #include #include @@ -155,8 +157,7 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset, */ tmplong = inl(bank->use_sel); if (!(tmplong & (1UL << offset))) { - debug("%s: gpio %d is reserved for internal use\n", __func__, - offset); + log_debug("gpio %d is reserved for internal use\n", offset); return -EPERM; } diff --git a/drivers/pch/pch9.c b/drivers/pch/pch9.c index 3bd011518b3..3137eb2c28f 100644 --- a/drivers/pch/pch9.c +++ b/drivers/pch/pch9.c @@ -3,6 +3,8 @@ * Copyright (C) 2014 Google, Inc */ +#define LOG_CATEGORY UCLASS_PCH + #include #include #include @@ -38,7 +40,7 @@ static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep) */ dm_pci_read_config32(dev, GPIO_BASE, &base); if (base == 0x00000000 || base == 0xffffffff) { - debug("%s: unexpected BASE value\n", __func__); + log_debug("unexpected BASE value\n"); return -ENODEV; } @@ -59,7 +61,7 @@ static int pch9_get_io_base(struct udevice *dev, u32 *iobasep) dm_pci_read_config32(dev, IO_BASE, &base); if (base == 0x00000000 || base == 0xffffffff) { - debug("%s: unexpected BASE value\n", __func__); + log_debug("unexpected BASE value\n"); return -ENODEV; } From df1bb2cb0b57be734cfc70f5ab7e4712a32ee83f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:12 -0600 Subject: [PATCH 53/60] x86: link: Support Micron memory Add the required tag so that micron memory can be set up correctly. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/dts/chromebook_link.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts index 36956f40bd7..c904b7d0b69 100644 --- a/arch/x86/dts/chromebook_link.dts +++ b/arch/x86/dts/chromebook_link.dts @@ -314,6 +314,7 @@ 00 00 00 00 00 00 00 00]; }; micron_4Gb_1600_1.35v_x16 { + bootph-all; reg = <2>; data = [92 11 0b 03 04 19 02 02 03 11 01 08 0a 00 fe 00 From dac1fa5c197ae30a60b2ce7489051359b9c8ebea Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:13 -0600 Subject: [PATCH 54/60] x86: Make sure that the LPC is active before SDRAM init Some boards need to access GPIOs to determine which SDRAM is fitted to the board, for example chromebook_link. Probe this device (if it exists) to make sure that this works as expected. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/spl.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index ba3434b055c..b6812bb8ca2 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -65,6 +65,8 @@ static int set_max_freq(void) static int x86_spl_init(void) { + struct udevice *dev; + #ifndef CONFIG_TPL /* * TODO(sjg@chromium.org): We use this area of RAM for the stack @@ -114,6 +116,13 @@ static int x86_spl_init(void) return ret; } #endif + /* probe the LPC so we get the GPIO_BASE set up correctly */ + ret = uclass_first_device_err(UCLASS_LPC, &dev); + if (ret && ret != -ENODEV) { + log_debug("lpc probe failed\n"); + return ret; + } + ret = dram_init(); if (ret) { log_debug("dram_init() failed (err=%d)\n", ret); From f9ebfd7c7acebd3d28a3be1d33e30c6f88a05302 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:14 -0600 Subject: [PATCH 55/60] log: Support outputing function names in SPL The output is garbled when tiny printf() is used. Correct this by adding a special case. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- common/log_console.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/log_console.c b/common/log_console.c index f1dcc04b97c..bb091ce21a4 100644 --- a/common/log_console.c +++ b/common/log_console.c @@ -37,8 +37,14 @@ static int log_console_emit(struct log_device *ldev, struct log_rec *rec) printf("%s:", rec->file); if (fmt & BIT(LOGF_LINE)) printf("%d-", rec->line); - if (fmt & BIT(LOGF_FUNC)) - printf("%*s()", CONFIG_LOGF_FUNC_PAD, rec->func); + if (fmt & BIT(LOGF_FUNC)) { + if (CONFIG_IS_ENABLED(USE_TINY_PRINTF)) { + printf("%s()", rec->func); + } else { + printf("%*s()", CONFIG_LOGF_FUNC_PAD, + rec->func); + } + } } if (fmt & BIT(LOGF_MSG)) printf("%s%s", add_space ? " " : "", rec->msg); From f52a7f05371e581d703bba6a724783aeb0ce5ac4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:15 -0600 Subject: [PATCH 56/60] sandbox: Correct header order in board file Fix the header order in this file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- board/sandbox/sandbox.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c index c7b6cb78fff..54c119daeee 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -11,16 +11,16 @@ #include #include #include +#include #include #include +#include #include #include #include #include #include -#include - -#include +#include /* * Pointer to initial global data area From 92ccaf7d97b0fafd3f1b2095ac998c9bd30d8d87 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:16 -0600 Subject: [PATCH 57/60] sandbox: Install ACPI tables on startup With x86 we set up the ACPI tables on startup so they can be examined. Do the same with sandbox, so it is consistent. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- board/sandbox/sandbox.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c index 54c119daeee..9d58860451c 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -15,7 +15,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -154,6 +156,8 @@ int extension_board_scan(struct list_head *extension_list) int board_late_init(void) { struct udevice *dev; + ulong addr, end; + void *ptr; int ret; ret = uclass_first_device_err(UCLASS_CROS_EC, &dev); @@ -166,6 +170,18 @@ int board_late_init(void) panic("Cannot init cros-ec device"); return -1; } + + if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { + /* Reserve 64K for ACPI tables, aligned to a 4K boundary */ + ptr = memalign(SZ_4K, SZ_64K); + addr = map_to_sysmem(ptr); + + /* Generate ACPI tables */ + end = write_acpi_tables(addr); + gd->arch.table_start = addr; + gd->arch.table_end = addr; + } + return 0; } #endif From 085f8db6b98dfdd8c1707797003d677ce654904f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:17 -0600 Subject: [PATCH 58/60] efi: Use the installed ACPI tables U-Boot sets up the ACPI tables during startup. Rather than creating a new set, install the existing ones. Create a memory-map record to cover the tables. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- lib/efi_loader/efi_acpi.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c index 2ddc3502b5d..f755af76f86 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -10,6 +10,9 @@ #include #include #include +#include + +DECLARE_GLOBAL_DATA_PTR; static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID; @@ -20,26 +23,28 @@ static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID; */ efi_status_t efi_acpi_register(void) { - /* Map within the low 32 bits, to allow for 32bit ACPI tables */ - u64 acpi = U32_MAX; + ulong addr, start, end; efi_status_t ret; - ulong addr; - /* Reserve 64kiB page for ACPI */ - ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, - EFI_ACPI_RECLAIM_MEMORY, 16, &acpi); + /* Mark space used for tables */ + start = ALIGN_DOWN(gd->arch.table_start, EFI_PAGE_MASK); + end = ALIGN(gd->arch.table_end, EFI_PAGE_MASK); + ret = efi_add_memory_map(start, end - start, EFI_ACPI_RECLAIM_MEMORY); if (ret != EFI_SUCCESS) return ret; + if (gd->arch.table_start_high) { + start = ALIGN_DOWN(gd->arch.table_start_high, EFI_PAGE_MASK); + end = ALIGN(gd->arch.table_end_high, EFI_PAGE_MASK); + ret = efi_add_memory_map(start, end - start, + EFI_ACPI_RECLAIM_MEMORY); + if (ret != EFI_SUCCESS) + return ret; + } - /* - * Generate ACPI tables - we know that efi_allocate_pages() returns - * a 4k-aligned address, so it is safe to assume that - * write_acpi_tables() will write the table at that address. - */ - addr = map_to_sysmem((void *)(ulong)acpi); - write_acpi_tables(addr); + addr = gd_acpi_start(); + printf("EFI using ACPI tables at %lx\n", addr); /* And expose them to our EFI payload */ return efi_install_configuration_table(&acpi_guid, - (void *)(uintptr_t)acpi); + (void *)(ulong)addr); } From e2d934b4dae97493db2a74211a82b433776e2000 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:18 -0600 Subject: [PATCH 59/60] x86: video: Add a driver for QEMU bochs emulation Bochs is convenient with QEMU on x86 since it does not require a video BIOS. Add a driver for it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/video/Kconfig | 30 ++++++++++ drivers/video/Makefile | 1 + drivers/video/bochs.c | 123 +++++++++++++++++++++++++++++++++++++++++ drivers/video/bochs.h | 36 ++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 drivers/video/bochs.c create mode 100644 drivers/video/bochs.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 49762950719..2ba4f5eac7f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -278,6 +278,36 @@ config VIDCONSOLE_AS_NAME possible to update the environment, the breakage may be confusing for users. This option will be removed around the end of 2020. +config VIDEO_BOCHS + bool "Enable Bochs video emulation for QEMU" + depends on X86 + help + Enable this to use the Bochs video support provided in the QEMU + emulator. This appears as a PCI device which U-Boot can set up to + provide a frame buffer. + +if VIDEO_BOCHS + +config VIDEO_BOCHS_SIZE_X + int "Width of display (X resolution)" + default 1280 + help + Sets the width of the display. + + These two options control the size of the display set up by QEMU. + Typical sizes are 1024 x 768 or 1280 x 1024. + +config VIDEO_BOCHS_SIZE_Y + int "High of display (Y resolution)" + default 1024 + help + Sets the height of the display. + + These two options control the size of the display set up by QEMU. + Typical sizes are 1024 x 768 or 1280 x 1024. + +endif + config VIDEO_COREBOOT bool "Enable coreboot framebuffer driver support" depends on X86 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index f99d7e3c3d9..a9263709084 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_OSD) += video_osd-uclass.o obj-$(CONFIG_SANDBOX_OSD) += sandbox_osd.o obj-$(CONFIG_VIDEO_ARM_MALIDP) += mali_dp.o obj-$(CONFIG_VIDEO_BCM2835) += bcm2835.o +obj-$(CONFIG_VIDEO_BOCHS) += bochs.o obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o diff --git a/drivers/video/bochs.c b/drivers/video/bochs.c new file mode 100644 index 00000000000..2136b511936 --- /dev/null +++ b/drivers/video/bochs.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Modified from coreboot bochs.c + */ + +#define LOG_CATEGORY UCLASS_VIDEO + +#include +#include +#include +#include +#include +#include +#include +#include +#include "bochs.h" + +static int xsize = CONFIG_VIDEO_BOCHS_SIZE_X; +static int ysize = CONFIG_VIDEO_BOCHS_SIZE_Y; + +static void bochs_write(void *mmio, int index, int val) +{ + writew(val, mmio + MMIO_BASE + index * 2); +} + +static int bochs_read(void *mmio, int index) +{ + return readw(mmio + MMIO_BASE + index * 2); +} + +static void bochs_vga_write(int index, uint8_t val) +{ + outb(val, VGA_INDEX); +} + +static int bochs_init_fb(struct udevice *dev) +{ + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + ulong fb; + void *mmio; + int id, mem; + + log_debug("probing %s at PCI %x\n", dev->name, dm_pci_get_bdf(dev)); + fb = dm_pci_read_bar32(dev, 0); + if (!fb) + return log_msg_ret("fb", -EIO); + + /* MMIO bar supported since qemu 3.0+ */ + mmio = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_TYPE, + PCI_REGION_MEM); + + if (!mmio) + return log_msg_ret("map", -EIO); + + /* bochs dispi detection */ + id = bochs_read(mmio, INDEX_ID); + if ((id & 0xfff0) != ID0) { + log_debug("ID mismatch\n"); + return -EPROTONOSUPPORT; + } + mem = bochs_read(mmio, INDEX_VIDEO_MEMORY_64K) * SZ_64K; + log_debug("QEMU VGA: bochs @ %p: %d MiB FB at %lx\n", mmio, mem / SZ_1M, + fb); + + uc_priv->xsize = xsize; + uc_priv->ysize = ysize; + uc_priv->bpix = VIDEO_BPP32; + + /* setup video mode */ + bochs_write(mmio, INDEX_ENABLE, 0); + bochs_write(mmio, INDEX_BANK, 0); + bochs_write(mmio, INDEX_BPP, VNBITS(uc_priv->bpix)); + bochs_write(mmio, INDEX_XRES, xsize); + bochs_write(mmio, INDEX_YRES, ysize); + bochs_write(mmio, INDEX_VIRT_WIDTH, xsize); + bochs_write(mmio, INDEX_VIRT_HEIGHT, ysize); + bochs_write(mmio, INDEX_X_OFFSET, 0); + bochs_write(mmio, INDEX_Y_OFFSET, 0); + bochs_write(mmio, INDEX_ENABLE, ENABLED | LFB_ENABLED); + + bochs_vga_write(0, 0x20); /* disable blanking */ + + plat->base = fb; + + return 0; +} + +static int bochs_video_probe(struct udevice *dev) +{ + int ret; + + ret = bochs_init_fb(dev); + if (ret) + return log_ret(ret); + + return 0; +} + +static int bochs_video_bind(struct udevice *dev) +{ + struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); + + /* Set the maximum supported resolution */ + uc_plat->size = 2560 * 1600 * 4; + log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + + return 0; +} + +U_BOOT_DRIVER(bochs_video) = { + .name = "bochs_video", + .id = UCLASS_VIDEO, + .bind = bochs_video_bind, + .probe = bochs_video_probe, +}; + +static struct pci_device_id bochs_video_supported[] = { + { PCI_DEVICE(0x1234, 0x1111) }, + { }, +}; + +U_BOOT_PCI_DEVICE(bochs_video, bochs_video_supported); diff --git a/drivers/video/bochs.h b/drivers/video/bochs.h new file mode 100644 index 00000000000..4c8ec83a550 --- /dev/null +++ b/drivers/video/bochs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Modified from coreboot bochs.c + */ + +#ifndef __BOCHS_H +#define __BOCHS_H + +#define VGA_INDEX 0x3c0 + +#define IOPORT_INDEX 0x01ce +#define IOPORT_DATA 0x01cf + +enum { + INDEX_ID, + INDEX_XRES, + INDEX_YRES, + INDEX_BPP, + INDEX_ENABLE, + INDEX_BANK, + INDEX_VIRT_WIDTH, + INDEX_VIRT_HEIGHT, + INDEX_X_OFFSET, + INDEX_Y_OFFSET, + INDEX_VIDEO_MEMORY_64K +}; + +#define ID0 0xb0c0 + +#define ENABLED BIT(0) +#define LFB_ENABLED BIT(6) +#define NOCLEARMEM BIT(7) + +#define MMIO_BASE 0x500 + +#endif From b8956425d525c3c25fd218f252f89a5e44df6a9f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:19 -0600 Subject: [PATCH 60/60] x86: Switch QEMU over to use the bochs driver This is more convenient since it does not require a video BIOS. Enable it for QEMU. Also drop use of video in SPL for the 64-bit QEMU, since it not needed now. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/qemu/Kconfig | 2 +- configs/qemu-x86_64_defconfig | 4 ---- configs/qemu-x86_defconfig | 3 --- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/x86/cpu/qemu/Kconfig b/arch/x86/cpu/qemu/Kconfig index f8f2f647308..aa329b0dab2 100644 --- a/arch/x86/cpu/qemu/Kconfig +++ b/arch/x86/cpu/qemu/Kconfig @@ -12,7 +12,7 @@ config QEMU imply SYS_NS16550 imply USB imply USB_EHCI_HCD - imply VIDEO_VESA + imply VIDEO_BOCHS if QEMU diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index b1400876a2f..4a15c516710 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -84,10 +84,6 @@ CONFIG_SPL_DM_RTC=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y -CONFIG_SPL_VIDEO=y -CONFIG_FRAMEBUFFER_SET_VESA_MODE=y -CONFIG_FRAMEBUFFER_VESA_MODE_USER=y -CONFIG_FRAMEBUFFER_VESA_MODE=0x144 CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_FAT_BLK_XLATE=y # CONFIG_SPL_USE_TINY_PRINTF is not set diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index 56788cd185f..95a6ff9ae79 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -53,9 +53,6 @@ CONFIG_NVME_PCI=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y -CONFIG_FRAMEBUFFER_SET_VESA_MODE=y -CONFIG_FRAMEBUFFER_VESA_MODE_USER=y -CONFIG_FRAMEBUFFER_VESA_MODE=0x144 CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_GENERATE_ACPI_TABLE=y # CONFIG_GZIP is not set