[PATCH 00/38] x86: Use qemu-x86_64 to boot EFI installers

This series adds various minor features so that qemu-x86_64 can boot the Ubuntu 2022.04 installer using a virtio device:
qemu-system-x86_64 -M pc -drive format=raw,file=root.img -bios /tmp/b/qemu-x86_64/u-boot.rom -drive if=virtio,file=ubuntu-22.04.2-desktop-amd64.iso -smp 4 -m 4G -serial mon:stdio
The main changes include: - Enable video in SPL while running in 32-bit mode - Drop the duplicate ACPI tables with EFI - Support PCI autoconfig in SPL - Support FAT on a CDROM filesystem - Improved bootstd rules around device tree and efi_set_bootdev()
There are also quite a number of minor tweaks and fixes to make things easier to use.
This series is based on an older version of the SPL-video series from Nikhil M Jain. It is available at u-boot-dm/bryc-working
Simon Glass (38): x86: Tidy up availability of string functions x86: Allow listing MTRRs in SPL bios_emulator: Add Kconfig and adjust Makefile for SPL bios_emulator: Drop VIDEO_IO_OFFSET x86: Tidy up EFI code in interrupt_init() x86: Set high bits of the mtrr base registrer x86: Add a comment for board_init_f_r_trampoline() x86: Show the CPU physical address size with bdinfo x86: Correct get_sp() implementation for 64-bit x86: Show an error when a BINS exception occurs acpi: Add a comment to set the acpi tables bdinfo: Show the RAM top and approximate stack pointer part: Allow setting the partition-table type qfw: Show the file address if available log: Tidy up an ambiguous comment. video: Allow building video drivers for SPL qfw: Set the address of the ACPI tables efi: Show all known UUIDs with CONFIG_CMD_EFIDEBUG x86: Improve the trampoline in 64-bit mode Show the malloc base with the bdinfo command nvme: Provide more useful debugging messages pci: Support autoconfig in SPL pci: Allow the video BIOS to work in SPL with QEMU pci: Tidy up logging and reporting for video BIOS x86: Allow video-BIOS code to be built for SPL x86: Pass video settings from SPL to U-Boot proper x86: Init video in SPL if enabled pci: Adjust video BIOS debugging to be SPL-friendly pci: Mask the ROM address in case it is already enabled x86: Enable display for QEMU 64-bit x86: Allow logging to be used in SPL reliably fs: fat: Shrink the size of a few strings fs: fat: Support reading from a larger block size x86: Enable useful options for qemu-86_64 x86: Record the start and end of the tables sandbox: Correct header order in board file sandbox: Install ACPI tables on startup efi: Use the installed ACPI tables
arch/sandbox/include/asm/global_data.h | 4 + arch/x86/cpu/i386/interrupt.c | 17 +-- arch/x86/cpu/mtrr.c | 62 +++++++- arch/x86/cpu/start64.S | 19 +++ arch/x86/include/asm/global_data.h | 4 + arch/x86/include/asm/mtrr.h | 20 +++ arch/x86/include/asm/string.h | 6 +- arch/x86/include/asm/u-boot-x86.h | 21 ++- arch/x86/lib/Makefile | 9 +- arch/x86/lib/bdinfo.c | 5 + arch/x86/lib/bios.c | 5 +- arch/x86/lib/bootm.c | 2 +- arch/x86/lib/spl.c | 26 +++- arch/x86/lib/tables.c | 4 +- board/google/Kconfig | 7 - board/sandbox/sandbox.c | 22 ++- cmd/Kconfig | 8 ++ cmd/acpi.c | 24 +++- cmd/bdinfo.c | 6 + cmd/part.c | 34 +++++ cmd/qfw.c | 2 +- cmd/x86/mtrr.c | 60 +------- common/board_f.c | 12 +- common/board_r.c | 7 +- common/log.c | 2 +- configs/qemu-x86_64_defconfig | 14 ++ disk/part.c | 16 +++ doc/usage/cmd/acpi.rst | 29 +++- doc/usage/cmd/part.rst | 74 ++++++++++ doc/usage/cmd/qfw.rst | 28 ++-- drivers/Kconfig | 2 + drivers/Makefile | 5 +- drivers/bios_emulator/Kconfig | 10 ++ drivers/bios_emulator/biosemui.h | 18 +-- drivers/bios_emulator/x86emu/sys.c | 1 + drivers/misc/qfw.c | 12 ++ drivers/nvme/nvme.c | 36 +++-- drivers/pci/Kconfig | 8 ++ drivers/pci/pci-uclass.c | 10 +- drivers/pci/pci_rom.c | 165 +++++++++++++++++----- fs/fat/Kconfig | 13 ++ fs/fat/fat.c | 117 ++++++++++++--- fs/fat/fat_write.c | 22 ++- include/asm-generic/global_data.h | 11 ++ include/bloblist.h | 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 - include/part.h | 9 ++ include/pci_ids.h | 1 + include/video.h | 24 ++++ lib/efi_loader/efi_acpi.c | 33 +++-- lib/uuid.c | 2 +- test/dm/acpi.c | 38 +++++ 57 files changed, 866 insertions(+), 233 deletions(-) create mode 100644 drivers/bios_emulator/Kconfig

For now, just enable the fast-but-large string functions in 32-boot U-Boot proper only. Avoid using them in SPL. We cannot use then in 64-bit builds since we only have 32-bit assembly.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/string.h | 6 +++++- arch/x86/lib/Makefile | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h index c15b264a5c08..5c49b0f009b7 100644 --- a/arch/x86/include/asm/string.h +++ b/arch/x86/include/asm/string.h @@ -14,7 +14,11 @@ extern char *strrchr(const char *s, int c); #undef __HAVE_ARCH_STRCHR extern char *strchr(const char *s, int c);
-#ifdef CONFIG_X86_64 +/* + * Our assembly routines do not work on in 64-bit mode and we don't do a lot of + * copying in SPL, so code size is more important there. + */ +#if defined(CONFIG_SPL_BUILD) || !IS_ENABLED(CONFIG_X86_32BIT_INIT)
#undef __HAVE_ARCH_MEMCPY extern void *memcpy(void *, const void *, __kernel_size_t); diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index a6f22441474b..b0612ae6dd5f 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -10,7 +10,9 @@ obj-y += bios.o obj-y += bios_asm.o obj-y += bios_interrupts.o endif -obj-y += string.o +endif +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_X86_32BIT_INIT) += string.o endif ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o

When using video in SPL it is useful to see the values of the MTRR registers. Move this code into a shared file, so it can be called from SPL easily.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/mtrr.c | 61 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 20 ++++++++++++ cmd/x86/mtrr.c | 60 +++--------------------------------- 3 files changed, 85 insertions(+), 56 deletions(-)
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index e69dfb552b16..1b5f24aab317 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -30,6 +30,16 @@
DECLARE_GLOBAL_DATA_PTR;
+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 ca2edc7878f7..2e995f540616 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/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index ff4be6b7bf5b..fd0e67e46eb3 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -10,71 +10,19 @@ #include <asm/mp.h> #include <asm/mtrr.h>
-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; } @@ -147,7 +95,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, printf("\n"); if (i < MP_SELECT_ALL) 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) : "",

Am 30. März 2023 23:31:51 MESZ schrieb Simon Glass sjg@chromium.org:
When using video in SPL it is useful to see the values of the MTRR registers. Move this code into a shared file, so it can be called from SPL easily.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/mtrr.c | 61 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 20 ++++++++++++ cmd/x86/mtrr.c | 60 +++--------------------------------- 3 files changed, 85 insertions(+), 56 deletions(-)
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index e69dfb552b16..1b5f24aab317 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -30,6 +30,16 @@
DECLARE_GLOBAL_DATA_PTR;
+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 ca2edc7878f7..2e995f540616 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/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index ff4be6b7bf5b..fd0e67e46eb3 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -10,71 +10,19 @@ #include <asm/mp.h> #include <asm/mtrr.h>
-static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
- "Uncacheable",
- "Combine",
- "2",
- "3",
- "Through",
- "Protect",
- "Back",
-};
Adding a "write-" prefix would make the meaning clearer
{ "uncachable", /* 0 */ "write-combining", /* 1 */ "2", /* 2 */ "3", /* 3 */ "write-through", /* 4 */ "write-protect", /* 5 */ "write-back", /* 6 */ };
Please, provide /doc/usage/cmd/mtrr.rst.
Best regards
Heinrich
-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; }
@@ -147,7 +95,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, printf("\n"); if (i < MP_SELECT_ALL) 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) : "",

Hi Heinrich,
On Thu, 30 Mar 2023 at 16:10, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:31:51 MESZ schrieb Simon Glass sjg@chromium.org:
When using video in SPL it is useful to see the values of the MTRR registers. Move this code into a shared file, so it can be called from SPL easily.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/cpu/mtrr.c | 61 +++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/mtrr.h | 20 ++++++++++++ cmd/x86/mtrr.c | 60 +++--------------------------------- 3 files changed, 85 insertions(+), 56 deletions(-)
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index e69dfb552b16..1b5f24aab317 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",
-};
Adding a "write-" prefix would make the meaning clearer
I decided against that since it makes the strings repetitive and long. The only one that wouldn't have 'write' is 'uncacheable'.
{ "uncachable", /* 0 */ "write-combining", /* 1 */ "2", /* 2 */ "3", /* 3 */ "write-through", /* 4 */ "write-protect", /* 5 */ "write-back", /* 6 */ };
Please, provide /doc/usage/cmd/mtrr.rst.
Added in a separate patch.
Regards, Simon

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 sjg@chromium.org ---
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 a0f1a6097641..e4f9b5b68aab 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 9101e538b097..b5d21e8e6c90 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 58be410135dd..f9822bea266e 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/ @@ -77,7 +78,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 000000000000..3660576772d1 --- /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

This is always zero in the source tree, so drop it.
While we are here, add a comment to _X86EMU_env since it the symbol is actually defined twice, which can cause confusion when building.
Signed-off-by: Simon Glass sjg@chromium.org ---
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 7853015c1e2e..954cd883158c 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 c2db1213fe66..882a8a34cc3e 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 60617e6fec25..03c364f29fb3 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 05389a435bee..be095e28a1b4 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 4a12c2f72c62..842672d55751 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 b2e7aa1514c0..5f7eabd3fc64 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 b23b8783076b..46aef238213a 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 98abb00927ad..6bf90c7de432 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"

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 sjg@chromium.org ---
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 fae2544c456f..f3f3527237f2 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; }

Linux expects all the high bits to be set, not just those needed for the CPU. Ignore the number of CPU bits and set them all.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/mtrr.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index 1b5f24aab317..bde8481a41c8 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -73,7 +73,6 @@ static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size)
wrmsrl(MTRR_PHYS_BASE_MSR(reg), start | type); mask = ~(size - 1); - mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1; wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask | MTRR_PHYS_MASK_VALID); }

Add a comment for this function in the header.
Change the function (and the one after) to use __noreturn to keep checkpatch happy.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/u-boot-x86.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 8f38c2d1c601..1610d7237bcd 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -102,8 +102,14 @@ 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); + +void __noreturn board_init_f_r(void);
int arch_misc_init(void);

Am 30. März 2023 23:31:56 MESZ schrieb Simon Glass sjg@chromium.org:
Add a comment for this function in the header.
Change the function (and the one after) to use __noreturn to keep checkpatch happy.
Signed-off-by: Simon Glass sjg@chromium.org
arch/x86/include/asm/u-boot-x86.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 8f38c2d1c601..1610d7237bcd 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -102,8 +102,14 @@ 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);
missing function description
+void __noreturn board_init_f_r(void);
ditto
int arch_misc_init(void);

This is useful information so show it with the bdinfo command.
Signed-off-by: Simon Glass sjg@chromium.org ---
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 15390070fe85..0970efa4726f 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", cpu_phys_address_size());
if (IS_ENABLED(CONFIG_EFI_STUB)) efi_show_bdinfo();

Use an assembler implementation as is done for i386, so that the results are equivalent.
Signed-off-by: Simon Glass sjg@chromium.org ---
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 61cb7bc61168..3196f9ddc2c8 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

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 sjg@chromium.org ---
arch/x86/lib/bios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 94349ba8073d..b28db31308f0 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -78,7 +78,8 @@ static int int_exception_handler(void) }; struct eregs *regs = ®_info;
- debug("Oops, exception %d while executing option rom\n", regs->vector); + log_err("Oops, exception %d while executing option rom\n", + regs->vector); cpu_hlt();
return 0;

Am 30. März 2023 23:31:59 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
arch/x86/lib/bios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 94349ba8073d..b28db31308f0 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -78,7 +78,8 @@ static int int_exception_handler(void) }; struct eregs *regs = ®_info;
- debug("Oops, exception %d while executing option rom\n", regs->vector);
- log_err("Oops, exception %d while executing option rom\n",
Please, drop "Oops, " which does not add information. Do we have a function to convert the exception number to a string?
%s/rom/ROM/
Regards
Heinrich
regs->vector);
cpu_hlt();
return 0;

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 sjg@chromium.org ---
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 e70913e40bfe..ede9c8c7dcb4 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 <name> - Dump ACPI table"; + "list - list ACPI tables\n" + "acpi items [-d] - List/dump each piece of ACPI data from devices\n" + "acpi set [<addr>] - Set or show address of ACPI tables\n" + "acpi dump <name> - 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 14bafc8e3524..5aeb4f4b77bf 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 <name> + acpi set <address>
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 allow 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 9634fc2e9002..1511336a5ebc 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -611,3 +611,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);

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 sjg@chromium.org ---
cmd/Kconfig | 8 ++++++++ cmd/bdinfo.c | 5 +++++ 2 files changed, 13 insertions(+)
diff --git a/cmd/Kconfig b/cmd/Kconfig index 6ab05ea52aa2..cd47d7b9ef45 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 f709904c5167..4e0c763a7096 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -145,6 +145,11 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) printf("devicetree = %s\n", fdtdec_get_srcname()); }
+ 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;

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 sjg@chromium.org ---
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 28f2b7ff9bbe..0ce190005d32 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 <interface> <dev>:<part> <varname>\n" " - set environment variable to partition type\n" + "part set <interface> <dev> 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 d449635254e1..5274baaac208 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 8d2a2803912d..8a594aaff27e 100644 --- a/doc/usage/cmd/part.rst +++ b/doc/usage/cmd/part.rst @@ -13,6 +13,7 @@ Synopis part start <interface> <dev> <part> <varname> part size <interface> <dev> <part> <varname> part number <interface> <dev> <part> <varname> + part set <interface> <dev> <part> <type> part type <interface> <dev>:<part> [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 be75c7354955..3b1b5398699c 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; }

Am 30. März 2023 23:32:02 MESZ schrieb Simon Glass sjg@chromium.org:
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.
Do you have an example image where we get it wrong?
Linux does not need that. What is different in our table type priorities to Linux?
I am not yet convinced we need to set this manually.
Best regards
Heinrich
Signed-off-by: Simon Glass sjg@chromium.org
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 28f2b7ff9bbe..0ce190005d32 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 <interface> <dev>:<part> <varname>\n" " - set environment variable to partition type\n"
- "part set <interface> <dev> 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 d449635254e1..5274baaac208 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 8d2a2803912d..8a594aaff27e 100644 --- a/doc/usage/cmd/part.rst +++ b/doc/usage/cmd/part.rst @@ -13,6 +13,7 @@ Synopis part start <interface> <dev> <part> <varname> part size <interface> <dev> <part> <varname> part number <interface> <dev> <part> <varname>
- part set <interface> <dev> <part> <type> part type <interface> <dev>:<part> [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 be75c7354955..3b1b5398699c 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; }

Hi Heinrich,
On Fri, 31 Mar 2023 at 11:33, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:02 MESZ schrieb Simon Glass sjg@chromium.org:
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.
Do you have an example image where we get it wrong?
Linux does not need that. What is different in our table type priorities to Linux?
I am not yet convinced we need to set this manually.
There is an example in the documentation I added. That is using the Ubuntu 22.04 ISO. Can you give it a try?
You can also try it with a CDROM drive, something like:
qemu-system-x86_64 -drive format=raw,file=root.img -bios /tmp/b/qemu-x86_64/u-boot.rom -cdrom ubuntu-22.04.2-desktop-amd64.iso -hdb fat:rw:/home/sglass/cosarm/win/seabios -nographic -m 4096
Regards, Simon
Signed-off-by: Simon Glass sjg@chromium.org
cmd/part.c | 34 +++++++++++++++++++ disk/part.c | 16 +++++++++ doc/usage/cmd/part.rst | 74 ++++++++++++++++++++++++++++++++++++++++++ include/part.h | 9 +++++ 4 files changed, 133 insertions(+)
[..]

Am 31. März 2023 01:49:05 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:33, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:02 MESZ schrieb Simon Glass sjg@chromium.org:
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.
Do you have an example image where we get it wrong?
Linux does not need that. What is different in our table type priorities to Linux?
I am not yet convinced we need to set this manually.
There is an example in the documentation I added. That is using the Ubuntu 22.04 ISO. Can you give it a try?
Linux would mount this as iso9660.
U-Boot lacks a driver for this file system.
There is no need to mount the file as CD-ROM drive. You could mount it as virtio drive instead or as USB. Then U-Boot can read the EFI partition with sector size 512.
Computers nowadays are installed from USB. Most workstation cases don't foresee optical drives anymore.
Best regards
Heinrich
You can also try it with a CDROM drive, something like:
qemu-system-x86_64 -drive format=raw,file=root.img -bios /tmp/b/qemu-x86_64/u-boot.rom -cdrom ubuntu-22.04.2-desktop-amd64.iso -hdb fat:rw:/home/sglass/cosarm/win/seabios -nographic -m 4096
Regards, Simon
Signed-off-by: Simon Glass sjg@chromium.org
cmd/part.c | 34 +++++++++++++++++++ disk/part.c | 16 +++++++++ doc/usage/cmd/part.rst | 74 ++++++++++++++++++++++++++++++++++++++++++ include/part.h | 9 +++++ 4 files changed, 133 insertions(+)
[..]

Hi Heinrich,
On Fri, 31 Mar 2023 at 13:17, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:49:05 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:33, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:02 MESZ schrieb Simon Glass sjg@chromium.org:
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.
Do you have an example image where we get it wrong?
Linux does not need that. What is different in our table type priorities to Linux?
I am not yet convinced we need to set this manually.
There is an example in the documentation I added. That is using the Ubuntu 22.04 ISO. Can you give it a try?
Linux would mount this as iso9660.
U-Boot lacks a driver for this file system.
There is no need to mount the file as CD-ROM drive. You could mount it as virtio drive instead or as USB. Then U-Boot can read the EFI partition with sector size 512.
Computers nowadays are installed from USB. Most workstation cases don't foresee optical drives anymore.
Yes, the example I have shown is for virtio and you can see the different filesystems present there.
Regards, Simon
Best regards
Heinrich
You can also try it with a CDROM drive, something like:
qemu-system-x86_64 -drive format=raw,file=root.img -bios /tmp/b/qemu-x86_64/u-boot.rom -cdrom ubuntu-22.04.2-desktop-amd64.iso -hdb fat:rw:/home/sglass/cosarm/win/seabios -nographic -m 4096
Regards, Simon
Signed-off-by: Simon Glass sjg@chromium.org
cmd/part.c | 34 +++++++++++++++++++ disk/part.c | 16 +++++++++ doc/usage/cmd/part.rst | 74 ++++++++++++++++++++++++++++++++++++++++++ include/part.h | 9 +++++ 4 files changed, 133 insertions(+)
[..]

Some files have an associated address. Show this with the 'qfw list' command so that it is possible to dump the data.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/qfw.c | 2 +- doc/usage/cmd/qfw.rst | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/cmd/qfw.c b/cmd/qfw.c index ae3c6a7a84e9..d6ecfa60d5a7 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 cc0e27c27790..76d74278a213 100644 --- a/doc/usage/cmd/qfw.rst +++ b/doc/usage/cmd/qfw.rst @@ -11,6 +11,7 @@ Synopsis qfw list qfw cpus qfw load [kernel_addr [initrd_addr]] + qfw list
Description ----------- @@ -41,18 +42,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:

Am 30. März 2023 23:32:03 MESZ schrieb Simon Glass sjg@chromium.org:
Some files have an associated address. Show this with the 'qfw list' command so that it is possible to dump the data.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/qfw.c | 2 +- doc/usage/cmd/qfw.rst | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/cmd/qfw.c b/cmd/qfw.c index ae3c6a7a84e9..d6ecfa60d5a7 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);
Are the tables always in the lower 4GiB on all architectures (riscv64, arm64, x86)?
}
return 0; diff --git a/doc/usage/cmd/qfw.rst b/doc/usage/cmd/qfw.rst index cc0e27c27790..76d74278a213 100644 --- a/doc/usage/cmd/qfw.rst +++ b/doc/usage/cmd/qfw.rst @@ -11,6 +11,7 @@ Synopsis qfw list qfw cpus qfw load [kernel_addr [initrd_addr]]
- qfw list
Description
@@ -41,18 +42,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:

Hi Heinrich,
On Fri, 31 Mar 2023 at 11:31, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:03 MESZ schrieb Simon Glass sjg@chromium.org:
Some files have an associated address. Show this with the 'qfw list' command so that it is possible to dump the data.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/qfw.c | 2 +- doc/usage/cmd/qfw.rst | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/cmd/qfw.c b/cmd/qfw.c index ae3c6a7a84e9..d6ecfa60d5a7 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);
Are the tables always in the lower 4GiB on all architectures (riscv64, arm64, x86)?
Yes, so far as I have seen on x86. We don't generate them for ARM or RISC-V. I do want to make sure the addresses are readable.
[..]
Regards, Simon

Date: Fri, 31 Mar 2023 00:31:17 +0200 From: Heinrich Schuchardt xypron.glpk@gmx.de
Am 30. März 2023 23:32:03 MESZ schrieb Simon Glass sjg@chromium.org:
Some files have an associated address. Show this with the 'qfw list' command so that it is possible to dump the data.
Signed-off-by: Simon Glass sjg@chromium.org
cmd/qfw.c | 2 +- doc/usage/cmd/qfw.rst | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/cmd/qfw.c b/cmd/qfw.c index ae3c6a7a84e9..d6ecfa60d5a7 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);
Are the tables always in the lower 4GiB on all architectures (riscv64, arm64, x86)?
Some arm64 doesn't even have memory in the lower 4GiB of memory. Not sure if qemu emulates such hardware though.
}
return 0; diff --git a/doc/usage/cmd/qfw.rst b/doc/usage/cmd/qfw.rst index cc0e27c27790..76d74278a213 100644 --- a/doc/usage/cmd/qfw.rst +++ b/doc/usage/cmd/qfw.rst @@ -11,6 +11,7 @@ Synopsis qfw list qfw cpus qfw load [kernel_addr [initrd_addr]]
- qfw list
Description
@@ -41,18 +42,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:

Add a a bit more detail so it is clear that multiple devices are supported, but only one per driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
common/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/log.c b/common/log.c index 7cfc49bc28a5..ec33b62e8a6f 100644 --- a/common/log.c +++ b/common/log.c @@ -436,7 +436,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) {

Update the Makefile rules to allow video drivers in SPL. This is useful for 64-bit QEMU on x86, since the video BIOS can only be run from 32-bit mode (i.e. in SPL).
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/Makefile b/drivers/Makefile index f9822bea266e..eb8e2b5ee805 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -37,6 +37,8 @@ obj-$(CONFIG_$(SPL_)SYSINFO) += sysinfo/ obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm/ obj-$(CONFIG_XEN) += xen/ obj-$(CONFIG_$(SPL_)FPGA) += fpga/ +obj-$(CONFIG_$(SPL_TPL_)VIDEO) += video/ + obj-y += bus/
ifndef CONFIG_TPL_BUILD @@ -96,7 +98,6 @@ obj-y += rtc/ obj-y += scsi/ obj-y += sound/ obj-y += spmi/ -obj-y += video/ obj-y += watchdog/ obj-$(CONFIG_QE) += qe/ obj-$(CONFIG_U_QE) += qe/

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 sjg@chromium.org ---
drivers/misc/qfw.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 9ef95caa8956..0a93feeb4b2e 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -18,6 +18,7 @@ #include <dm.h> #include <misc.h> #include <tables_csum.h> +#include <asm/acpi_table.h>
#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; }

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 sjg@chromium.org ---
lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b00..ab30fbf9152f 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 },

Am 30. März 2023 23:32:07 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b00..ab30fbf9152f 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 },
None of these are used when not building the EFI app.
Best regards
Heinrich

Hi Heinrich,
On Fri, 31 Mar 2023 at 11:38, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:07 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b00..ab30fbf9152f 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 },
None of these are used when not building the EFI app.
So you think we should disable them? As I said above, enabling debugging seems like a good reason to allow decoding of all of them.
Regards, SImon

Am 31. März 2023 01:48:57 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:38, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:07 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b00..ab30fbf9152f 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 },
None of these are used when not building the EFI app.
So you think we should disable them? As I said above, enabling debugging seems like a good reason to allow decoding of all of them.
Regards, SImon
U-Boot, Shim, GRUB will not use any of these. The EFI app sees them if shared by the preceding UEFI firmware.
There are zillions other GUIDs that a vendor UEFI might use. But why should we care?
I would rather drop these strings from the code base.
Best regards
Heinrich

Hi Heinrich,
On Fri, 31 Mar 2023 at 13:27, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:48:57 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:38, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:07 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b00..ab30fbf9152f 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 },
None of these are used when not building the EFI app.
So you think we should disable them? As I said above, enabling debugging seems like a good reason to allow decoding of all of them.
Regards, SImon
U-Boot, Shim, GRUB will not use any of these. The EFI app sees them if shared by the preceding UEFI firmware.
There are zillions other GUIDs that a vendor UEFI might use. But why should we care?
I would rather drop these strings from the code base.
I would far rather drop the UUIDs from the code base. Is that possible? We should use a simple numeric tag, like 0, 1, 2, 3, 4 with an associated descriptive string. Even using a 16-byte string would be better than a UUID.
While we have to put up with UUIDs, we need a way to make them intelligible for us poor sods who need to decode boot-time traces[1] and the like.
Regards, Simon
[1] EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed33da0, 5b1b31a1-9562-11d2-8e3f-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed238b0, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_locate_handle_ext(2, a19832b9-ac25-11d3-9a2d-0090273fc14d, 0000000000000000, 000000007ecf4948, 000000007d6f3ba0) EFI: Exit: efi_locate_handle_ext: 0 EFI: Entry efi_open_protocol(000000007ed25040, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed25040, a19832b9-ac25-11d3-9a2d-0090273fc14d, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed33da0, 5b1b31a1-9562-11d2-8e3f-00a0c969723b, 000000007ecf49b8, 00000 0007ed33da0, 0000000000000000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed238b0, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4958, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_locate_protocol(96751a3d-72f4-41a6-a794-ed5d0e67ae6b, 0000000000000000, 000000007ecf4668) EFI: Exit: efi_locate_protocol: 14 EFI: Entry efi_locate_handle_ext(2, f541796d-a62e-4954-a775-9584f61b9cdd, 0000000000000000, 000000007ecf4638, 000000007d40be00) EFI: Exit: efi_locate_handle_ext: 14 EFI: Entry efi_locate_handle_ext(2, 607f766c-7455-42be-930b-e4d76db2720f, 0000000000000000, 000000007ecf4638, 000000007d40be00) EFI: Exit: efi_locate_handle_ext: 14 EFI: Entry efi_locate_protocol(f42f7782-012e-4c12-9956-49f94304f721, 0000000000000000, 000000007ecf43e8) EFI: Exit: efi_locate_protocol: 14

Am 31. März 2023 03:16:06 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 13:27, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:48:57 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:38, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:07 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b00..ab30fbf9152f 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 },
None of these are used when not building the EFI app.
So you think we should disable them? As I said above, enabling debugging seems like a good reason to allow decoding of all of them.
Regards, SImon
U-Boot, Shim, GRUB will not use any of these. The EFI app sees them if shared by the preceding UEFI firmware.
There are zillions other GUIDs that a vendor UEFI might use. But why should we care?
I would rather drop these strings from the code base.
I would far rather drop the UUIDs from the code base. Is that possible? We should use a simple numeric tag, like 0, 1, 2, 3, 4 with an associated descriptive string. Even using a 16-byte string would be better than a UUID.
While we have to put up with UUIDs, we need a way to make them intelligible for us poor sods who need to decode boot-time traces[1] and the like.
The EFI spec uses GUIDs and these are strings you will find with Google. Natural numbers that have bo significance won't serve anybody. GUIDs not used inside U-Boot we should not care to translate as there are too many.
Regards, Simon
[1] EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed33da0, 5b1b31a1-9562-11d2-8e3f-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed238b0, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_locate_handle_ext(2, a19832b9-ac25-11d3-9a2d-0090273fc14d, 0000000000000000, 000000007ecf4948, 000000007d6f3ba0) EFI: Exit: efi_locate_handle_ext: 0 EFI: Entry efi_open_protocol(000000007ed25040, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed25040, a19832b9-ac25-11d3-9a2d-0090273fc14d, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed33da0, 5b1b31a1-9562-11d2-8e3f-00a0c969723b, 000000007ecf49b8, 00000 0007ed33da0, 0000000000000000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed238b0, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4958, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_locate_protocol(96751a3d-72f4-41a6-a794-ed5d0e67ae6b, 0000000000000000, 000000007ecf4668) EFI: Exit: efi_locate_protocol: 14 EFI: Entry efi_locate_handle_ext(2, f541796d-a62e-4954-a775-9584f61b9cdd, 0000000000000000, 000000007ecf4638, 000000007d40be00) EFI: Exit: efi_locate_handle_ext: 14 EFI: Entry efi_locate_handle_ext(2, 607f766c-7455-42be-930b-e4d76db2720f, 0000000000000000, 000000007ecf4638, 000000007d40be00) EFI: Exit: efi_locate_handle_ext: 14 EFI: Entry efi_locate_protocol(f42f7782-012e-4c12-9956-49f94304f721, 0000000000000000, 000000007ecf43e8) EFI: Exit: efi_locate_protocol: 14

Hi Heinrich,
On Fri, 31 Mar 2023 at 19:46, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 03:16:06 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 13:27, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:48:57 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:38, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:07 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/uuid.c b/lib/uuid.c index 96e1af3c8b00..ab30fbf9152f 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 },
None of these are used when not building the EFI app.
So you think we should disable them? As I said above, enabling debugging seems like a good reason to allow decoding of all of them.
Regards, SImon
U-Boot, Shim, GRUB will not use any of these. The EFI app sees them if shared by the preceding UEFI firmware.
There are zillions other GUIDs that a vendor UEFI might use. But why should we care?
I would rather drop these strings from the code base.
I would far rather drop the UUIDs from the code base. Is that possible? We should use a simple numeric tag, like 0, 1, 2, 3, 4 with an associated descriptive string. Even using a 16-byte string would be better than a UUID.
While we have to put up with UUIDs, we need a way to make them intelligible for us poor sods who need to decode boot-time traces[1] and the like.
The EFI spec uses GUIDs and these are strings you will find with Google. Natural numbers that have bo significance won't serve anybody. GUIDs not used inside U-Boot we should not care to translate as there are too many.
I think it is an interesting idea though, to have an internal register of these things with an enum. Then U-Boot can just use that everywhere and it is clear what it is, at least within the U-Boot code base. Things that are not understood don't matter anyway, since we don't have code for them.
Anyway, back to the original topic, as you can see from the trace below, it is far too tedious for a human to decode the UUIDs. That is what the computer is for.
But if this patch has no value, because the UUIDs I mention are never shown, we can drop it.
Regards, Simon
Regards, Simon
[1] EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed33da0, 5b1b31a1-9562-11d2-8e3f-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed238b0, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_locate_handle_ext(2, a19832b9-ac25-11d3-9a2d-0090273fc14d, 0000000000000000, 000000007ecf4948, 000000007d6f3ba0) EFI: Exit: efi_locate_handle_ext: 0 EFI: Entry efi_open_protocol(000000007ed25040, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed25040, a19832b9-ac25-11d3-9a2d-0090273fc14d, 000000007ecf4978, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed33da0, 5b1b31a1-9562-11d2-8e3f-00a0c969723b, 000000007ecf49b8, 00000 0007ed33da0, 0000000000000000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_open_protocol(000000007ed238b0, 09576e91-6d3f-11d2-8e39-00a0c969723b, 000000007ecf4958, 000000007ed33da0, 00000000000 00000, 0x2) EFI: Exit: efi_open_protocol: 0 EFI: Entry efi_locate_protocol(96751a3d-72f4-41a6-a794-ed5d0e67ae6b, 0000000000000000, 000000007ecf4668) EFI: Exit: efi_locate_protocol: 14 EFI: Entry efi_locate_handle_ext(2, f541796d-a62e-4954-a775-9584f61b9cdd, 0000000000000000, 000000007ecf4638, 000000007d40be00) EFI: Exit: efi_locate_handle_ext: 14 EFI: Entry efi_locate_handle_ext(2, 607f766c-7455-42be-930b-e4d76db2720f, 0000000000000000, 000000007ecf4638, 000000007d40be00) EFI: Exit: efi_locate_handle_ext: 14 EFI: Entry efi_locate_protocol(f42f7782-012e-4c12-9956-49f94304f721, 0000000000000000, 000000007ecf43e8) EFI: Exit: efi_locate_protocol: 14

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 sjg@chromium.org ---
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 7be834788b9f..78e894d2a21a 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 1610d7237bcd..3703094027d5 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -109,6 +109,17 @@ int fsp_save_s3_stack(void); */ void __noreturn board_init_f_r_trampoline(ulong sp);
+/** + * 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); + void __noreturn board_init_f_r(void);
int arch_misc_init(void); diff --git a/common/board_f.c b/common/board_f.c index f3c1ab53b1c6..f252a8eed5fd 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -731,8 +731,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) { @@ -754,7 +753,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 @@ -969,8 +972,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,

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 sjg@chromium.org ---
cmd/bdinfo.c | 1 + common/board_r.c | 7 ++++--- include/asm-generic/global_data.h | 11 +++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c index 4e0c763a7096..f1f8d59673fb 100644 --- a/cmd/bdinfo.c +++ b/cmd/bdinfo.c @@ -148,6 +148,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 d798c00a80a5..4aaa89403117 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 422e0cf4720f..3ccd66fdeb7a 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -301,6 +301,10 @@ struct global_data { * @timebase_l: low 32 bits of timer */ unsigned int timebase_l; + /** + * @malloc_start: start of malloc() region + */ + CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA, (ulong malloc_start;)) #if CONFIG_VAL(SYS_MALLOC_F_LEN) /** * @malloc_base: base address of early malloc() @@ -560,6 +564,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 *

When scanning fails it is useful to be able to decode what went wrong. Add some debugging for this.
Signed-off-by: Simon Glass sjg@chromium.org ---
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 74e7a5b01109..a7add66ab4d1 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);

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 sjg@chromium.org ---
drivers/pci/Kconfig | 8 ++++++++ drivers/pci/pci-uclass.c | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index ef328d26525b..165f111a4f5b 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -40,6 +40,14 @@ config PCI_PNP help Enable PCI memory and I/O space resource allocation and assignment.
+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 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 8d27e40338cf..632c1a63cfce 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -13,6 +13,7 @@ #include <log.h> #include <malloc.h> #include <pci.h> +#include <spl.h> #include <asm/global_data.h> #include <asm/io.h> #include <dm/device-internal.h> @@ -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;

QEMU emulates two common machines (Q35 and i440fx) which use mapping to determine whether RAM is present below 1MB. In order to copy the video BIOS to c0000 we need to flip this mapping over to RAM. This does not happen automatically until SPL has finished running.
Switch in RAM at these address so that the video BIOS can be loaded and run. This fix was found in the seabios code base.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci_rom.c | 46 +++++++++++++++++++++++++++++++++++++++++++ include/pci_ids.h | 1 + 2 files changed, 47 insertions(+)
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index f0dfe6314907..0f44238bbbc8 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -141,6 +141,49 @@ static int pci_rom_probe(struct udevice *dev, struct pci_rom_header **hdrp) return 0; }
+#define Q35_HOST_BRIDGE_PAM0 0x90 +#define I440FX_PAM0 0x59 + +/** + * intel_set_writable_ram() - Set RAM to be writable + * + * This is needed for QEMU when using Q35 or I440FX emulation, since otherwise + * there is no RAM available at c0000 + * + * See Intel 82945G/82945G/82945GC GMCH and 82945P/82945PL MCH Datasheet for + * information about the PAM0-PAM6 registers + */ +static void intel_set_writable_ram(void) +{ + struct udevice *dev; + int pam0 = -1; + int i; + + for (pci_find_first_device(&dev); dev; pci_find_next_device(&dev)) { + const struct pci_child_plat *pdata = dev_get_parent_plat(dev); + + if (pdata->vendor == PCI_VENDOR_ID_INTEL) { + if (pdata->device == PCI_DEVICE_ID_INTEL_Q35_MCH) { + pam0 = Q35_HOST_BRIDGE_PAM0; + break; + } else if (pdata->device == PCI_DEVICE_ID_INTEL_82441) { + pam0 = I440FX_PAM0; + break; + } + } + } + + if (!dev) + return; + + // Adjust RAM to be writable from c0000 to f0000 + for (i = 1; i <= 6; i++) + dm_pci_write_config8(dev, pam0 + i, 0x33); + + // Also f0000-100000 + dm_pci_write_config8(dev, pam0, 0x30); +} + /** * pci_rom_load() - Load a ROM image and return a pointer to it * @@ -185,6 +228,9 @@ static int pci_rom_load(struct pci_rom_header *rom_header, return -ENOMEM; *allocedp = true; #endif + /* QEMU hacks */ + intel_set_writable_ram(); + if (target != rom_header) { ulong start = get_timer(0);
diff --git a/include/pci_ids.h b/include/pci_ids.h index 5ae1b9b7fb6e..33e90c8d2769 100644 --- a/include/pci_ids.h +++ b/include/pci_ids.h @@ -2870,6 +2870,7 @@ #define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916 #define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918 #define PCI_DEVICE_ID_INTEL_ICH9_AHCI 0x2922 +#define PCI_DEVICE_ID_INTEL_Q35_MCH 0x29c0 #define PCI_DEVICE_ID_INTEL_I7_MCR 0x2c18 #define PCI_DEVICE_ID_INTEL_I7_MC_TAD 0x2c19 #define PCI_DEVICE_ID_INTEL_I7_MC_RAS 0x2c1a

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 sjg@chromium.org ---
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 0f44238bbbc8..dab0f1979068 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -300,14 +300,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; }
@@ -345,21 +347,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);

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 sjg@chromium.org ---
arch/x86/lib/Makefile | 7 ++++--- arch/x86/lib/bios.c | 2 +- drivers/pci/pci_rom.c | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b0612ae6dd5f..90a7618ecfde 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 b28db31308f0..e2b422bec1ed 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 dab0f1979068..2d9a2a899ef7 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -344,20 +344,20 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), }
if (emulate) { -#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 + 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; + } } else { #if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL) log_debug("Running video BIOS...");

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 sjg@chromium.org ---
drivers/pci/pci_rom.c | 78 +++++++++++++++++++++++++++++++------------ include/bloblist.h | 1 + include/video.h | 24 +++++++++++++ 3 files changed, 82 insertions(+), 21 deletions(-)
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 2d9a2a899ef7..ecb6da64c5c9 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -26,6 +26,7 @@
#include <common.h> #include <bios_emul.h> +#include <bloblist.h> #include <bootstage.h> #include <dm.h> #include <errno.h> @@ -34,6 +35,7 @@ #include <malloc.h> #include <pci.h> #include <pci_rom.h> +#include <spl.h> #include <vesa.h> #include <video.h> #include <acpi/acpi_s3.h> @@ -420,34 +422,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 2a2f1700eb09..7ea72c6bd46d 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 4d99e5dc27f6..795a7378535e 100644 --- a/include/video.h +++ b/include/video.h @@ -133,6 +133,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; + ushort xsize; + ushort ysize; + u32 line_length; + u8 bpix; +}; + /** enum colour_idx - the 16 colors supported by consoles */ enum colour_idx { VID_BLACK = 0,

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.
Make sure that the SPL banner is only shown once.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/spl.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index bdf57ef7b5bd..0e1a18b251d7 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -15,10 +15,12 @@ #include <malloc.h> #include <spl.h> #include <syscon.h> +#include <vesa.h> #include <asm/cpu.h> #include <asm/cpu_common.h> #include <asm/fsp2/fsp_api.h> #include <asm/global_data.h> +#include <asm/mp.h> #include <asm/mrccache.h> #include <asm/mtrr.h> #include <asm/pci.h> @@ -96,7 +98,8 @@ static int x86_spl_init(void) return ret; } #endif - preloader_console_init(); + if (!IS_ENABLED(CONFIG_SPL_BOARD_INIT)) + preloader_console_init(); #if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU) ret = print_cpuinfo(); if (ret) { @@ -255,4 +258,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); + } }

A hex value is expected for the VGA mode. Drop the 0x prefix, which is not supported in SPL.
Signed-off-by: Simon Glass sjg@chromium.org ---
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 ecb6da64c5c9..62cfe60c0fb2 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -319,7 +319,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 %x\n", vesa_mode);
if (exec_method & PCI_ROM_USE_NATIVE) { #ifdef CONFIG_X86 @@ -370,7 +370,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:

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 sjg@chromium.org ---
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 62cfe60c0fb2..ba2cf18d53eb 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,

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 sjg@chromium.org ---
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 f29a5aa0f813..371ca9de8429 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=0xfffd0000 +CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 CONFIG_DEBUG_UART_BASE=0x3f8 CONFIG_DEBUG_UART_CLOCK=1843200 CONFIG_X86_RUN_64BIT=y @@ -29,7 +30,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

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 sjg@chromium.org ---
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 0e1a18b251d7..3253b0a26062 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -137,9 +137,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; + } + /* 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,

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 sjg@chromium.org ---
fs/fat/fat.c | 12 ++++++------ fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf3..f0df7988e172 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -97,8 +97,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); + printf("** Partition %d invalid on device %d **\n", + part_no, dev_desc->devnum); return -1; }
@@ -168,7 +168,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); + printf("** Invalid FAT entry: %#08x\n", entry); return ret; }
@@ -586,17 +586,17 @@ 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", + printf("** FAT sector size mismatch (fs=%hu, 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"); + printf("** 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", + printf("** FAT cluster size too big (cs=%u, max=%u)\n", (unsigned int)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 00541ebc3a4a..4d2d4db07fa6 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -1568,8 +1568,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; } @@ -1581,13 +1582,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; @@ -1602,7 +1596,7 @@ int fat_unlink(const char *filename) }
if (!find_directory_entry(itr, basename)) { - printf("%s: doesn't exist\n", basename); + printf("%s: doesn't exist (%d)\n", basename, -ENOENT); ret = -ENOENT; goto exit; }

Am 30. März 2023 23:32:21 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
fs/fat/fat.c | 12 ++++++------ fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf3..f0df7988e172 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -97,8 +97,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);
printf("** Partition %d invalid on device %d **\n",
}part_no, dev_desc->devnum); return -1;
@@ -168,7 +168,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);
printf("** Invalid FAT entry: %#08x\n", entry);
The ** is superfluous. The text makes it clear that an error occured
return ret;
}
@@ -586,17 +586,17 @@ 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",
printf("** FAT sector size mismatch (fs=%hu, dev=%lu)\n",
ditto
mydata->sect_size, cur_part_info.blksz); return -1;
} if (mydata->clust_size == 0) {
printf("Error: FAT cluster size not set\n");
printf("** FAT cluster size not set\n");
ditto
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",
printf("** FAT cluster size too big
ditto
(cs=%u, max=%u)\n",
(unsigned int)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 00541ebc3a4a..4d2d4db07fa6 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -1568,8 +1568,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");
remove 'Error: '
Best regards
Heinrich
ret = -ENOMEM; goto exit;
} @@ -1581,13 +1582,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;
@@ -1602,7 +1596,7 @@ int fat_unlink(const char *filename) }
if (!find_directory_entry(itr, basename)) {
printf("%s: doesn't exist\n", basename);
ret = -ENOENT; goto exit; }printf("%s: doesn't exist (%d)\n", basename, -ENOENT);

Hi Heinrich,
On Fri, 31 Mar 2023 at 11:48, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:21 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
fs/fat/fat.c | 12 ++++++------ fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf3..f0df7988e172 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -97,8 +97,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);
printf("** Partition %d invalid on device %d **\n",
part_no, dev_desc->devnum); return -1; }
@@ -168,7 +168,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);
printf("** Invalid FAT entry: %#08x\n", entry);
The ** is superfluous. The text makes it clear that an error occured
So should I drop the other ** strings in these files too? Please take a look and see what you think.
[..]
Regards, Simon

Am 31. März 2023 01:49:35 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:48, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:21 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
fs/fat/fat.c | 12 ++++++------ fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf3..f0df7988e172 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -97,8 +97,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);
printf("** Partition %d invalid on device %d **\n",
part_no, dev_desc->devnum); return -1; }
@@ -168,7 +168,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);
printf("** Invalid FAT entry: %#08x\n", entry);
The ** is superfluous. The text makes it clear that an error occured
So should I drop the other ** strings in these files too? Please take a look and see what you think.
I suggest to avoid prefixes like 'Error:' and '**' in all our code if the message text already indicates an error.
Best regards
Heinrich
[..]
Regards, Simon

Hi Heinrich,
On Fri, 31 Mar 2023 at 13:05, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:49:35 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:48, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:21 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
fs/fat/fat.c | 12 ++++++------ fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf3..f0df7988e172 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -97,8 +97,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);
printf("** Partition %d invalid on device %d **\n",
part_no, dev_desc->devnum); return -1; }
@@ -168,7 +168,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);
printf("** Invalid FAT entry: %#08x\n", entry);
The ** is superfluous. The text makes it clear that an error occured
So should I drop the other ** strings in these files too? Please take a look and see what you think.
I suggest to avoid prefixes like 'Error:' and '**' in all our code if the message text already indicates an error.
That makes sense to me. It is sometimes hard to know whether something indicates an error, though. If you look through fat.c you'll see what I mean.
Regards, Simon

Am 31. März 2023 03:16:13 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 13:05, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:49:35 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:48, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:21 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
fs/fat/fat.c | 12 ++++++------ fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf3..f0df7988e172 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -97,8 +97,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);
printf("** Partition %d invalid on device %d **\n",
part_no, dev_desc->devnum); return -1; }
@@ -168,7 +168,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);
printf("** Invalid FAT entry: %#08x\n", entry);
The ** is superfluous. The text makes it clear that an error occured
So should I drop the other ** strings in these files too? Please take a look and see what you think.
I suggest to avoid prefixes like 'Error:' and '**' in all our code if the message text already indicates an error.
That makes sense to me. It is sometimes hard to know whether something indicates an error, though. If you look through fat.c you'll see what I mean.
Users might prefer log_err writing messages in red on the console.
Regards, Simon

On Fri, 31 Mar 2023 at 09:51, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 03:16:13 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 13:05, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:49:35 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:48, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:21 MESZ schrieb Simon Glass sjg@chromium.org:
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 sjg@chromium.org
fs/fat/fat.c | 12 ++++++------ fs/fat/fat_write.c | 14 ++++---------- 2 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 2da93dae3cf3..f0df7988e172 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -97,8 +97,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);
printf("** Partition %d invalid on device %d **\n",
part_no, dev_desc->devnum); return -1; }
@@ -168,7 +168,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);
printf("** Invalid FAT entry: %#08x\n", entry);
The ** is superfluous. The text makes it clear that an error occured
So should I drop the other ** strings in these files too? Please take a look and see what you think.
I suggest to avoid prefixes like 'Error:' and '**' in all our code if the message text already indicates an error.
That makes sense to me. It is sometimes hard to know whether something indicates an error, though. If you look through fat.c you'll see what I mean.
Users might prefer log_err writing messages in red on the console.
FWIW I agree with Heinrich here. We got 'Error: XXXXX' sprinkled around from older code, but it makes sense to convert them to log_err where possible
Regards /Ilias
Regards, Simon

On 3/31/23 09:33, Ilias Apalodimas wrote:
On Fri, 31 Mar 2023 at 09:51, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 03:16:13 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 13:05, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 31. März 2023 01:49:35 MESZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Fri, 31 Mar 2023 at 11:48, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:21 MESZ schrieb Simon Glass sjg@chromium.org: > 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 sjg@chromium.org > --- > > fs/fat/fat.c | 12 ++++++------ > fs/fat/fat_write.c | 14 ++++---------- > 2 files changed, 10 insertions(+), 16 deletions(-) > > diff --git a/fs/fat/fat.c b/fs/fat/fat.c > index 2da93dae3cf3..f0df7988e172 100644 > --- a/fs/fat/fat.c > +++ b/fs/fat/fat.c > @@ -97,8 +97,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); > + printf("** Partition %d invalid on device %d **\n", > + part_no, dev_desc->devnum); > return -1; > } > > @@ -168,7 +168,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); > + printf("** Invalid FAT entry: %#08x\n", entry);
The ** is superfluous. The text makes it clear that an error occured
So should I drop the other ** strings in these files too? Please take a look and see what you think.
I suggest to avoid prefixes like 'Error:' and '**' in all our code if the message text already indicates an error.
That makes sense to me. It is sometimes hard to know whether something indicates an error, though. If you look through fat.c you'll see what I mean.
Users might prefer log_err writing messages in red on the console.
FWIW I agree with Heinrich here. We got 'Error: XXXXX' sprinkled around from older code, but it makes sense to convert them to log_err where possible
We should move all error output to log_err() and then can later add decoration (color or prefix) in log_err().
Best regards
Heinrich
Regards /Ilias
Regards, Simon

At present it is not possible to read from some CDROM drives since the FAT sector size does not match the media's block size. Add a conversion option for this, so that reading is possible.
This does increase SPL size for read-only FAT support by 25 bytes but all but 6 are covered by the previous patch. We could reduce the overhead of this feature to 0 bytes by making the code uglier (using a static variable).
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/fat/Kconfig | 13 ++++++ fs/fat/fat.c | 107 ++++++++++++++++++++++++++++++++++++++++----- fs/fat/fat_write.c | 8 ++-- 3 files changed, 114 insertions(+), 14 deletions(-)
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig index 9bb11eac9f7a..b0aa888c6cc4 100644 --- a/fs/fat/Kconfig +++ b/fs/fat/Kconfig @@ -22,3 +22,16 @@ config FS_FAT_MAX_CLUSTSIZE is the smallest amount of disk space that can be used to hold a file. Unless you have an extremely tight memory memory constraints, leave the default. + +config FAT_BLK_XLATE + bool "Enable FAT filesystem on a device with a larger block size" + depends on FS_FAT + help + This provides a simple translation mechanism for reading FAT + filesystems which don't use the same sector size as the underlying + media. For example, the FAT filesystem may use 512 bytes but the + media uses 2048, e.g. on a CDROM drive. + + This only supports the case where the FAT filesystem's sector size is + smaller than the media's block size. It does not support creating or + writing files. diff --git a/fs/fat/fat.c b/fs/fat/fat.c index f0df7988e172..02c6d55a99b3 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -43,13 +43,93 @@ static struct disk_partition cur_part_info; #define DOS_FS_TYPE_OFFSET 0x36 #define DOS_FS32_TYPE_OFFSET 0x52
-static int disk_read(__u32 block, __u32 nr_blocks, void *buf) +/** + * disk_read_conv() - Read blocks and break them into smaller ones + * + * This is used when the FAT filesystem is hosted on a block device with a + * block size greated than 512 bytes, e.g. the 2048 bytes of a CDROM drive. It + * reads the blocks into a buffer and pulls out what is requested by the calling + * function. + * + * It uses an internal 2KB buffer on the stack. + * + * @mydata: Filesystem information + * @block: Block number to read, in terms of mydata->sect_size + * @nr_blocks: Number of blocks to read, in terms of mydata->sect_size + * @buf: Buffer for data + */ +static int disk_read_conv(fsdata *mydata, __u32 block, __u32 nr_blocks, + void *buf) +{ + uint factor, whole, remain, upto; + ulong base, index; + uint to_copy; + u8 tbuf[2048]; + int ret; + + log_debug("mydata %x, cur_dev %lx, block %x, nr_block %x\n", + mydata->sect_size, cur_dev->blksz, block, nr_blocks); + if (mydata->sect_size > cur_dev->blksz || + cur_dev->blksz > sizeof(tbuf)) { + log_err("Block size %lx not supported\n", cur_dev->blksz); + return -EIO; + } + factor = cur_dev->blksz / mydata->sect_size; + + /* get the first partial block */ + base = cur_part_info.start + block / factor; + index = block % factor; + log_debug("cur_part_info.start %llx, block %x, base %lx, index %lx\n", + (unsigned long long)cur_part_info.start, block, base, index); + ret = blk_dread(cur_dev, base, 1, tbuf); + if (ret != 1) + return -EIO; + + to_copy = min((ulong)nr_blocks, factor - index); + log_debug("to_copy %x\n", to_copy); + memcpy(buf, tbuf + index * mydata->sect_size, + to_copy * mydata->sect_size); + upto = to_copy; + + /* load any whole blocks */ + remain = nr_blocks - upto; + whole = remain / factor; + log_debug("factor %x, whole %x, remain %x\n", factor, whole, remain); + if (whole) { + ret = blk_dread(cur_dev, base + 1, whole, + buf + upto * mydata->sect_size); + if (ret != whole) + return -EIO; + upto += whole * factor; + remain = nr_blocks - upto; + } + + /* load any blocks at the end */ + log_debug("end: remain %x\n", remain); + if (remain) { + ret = blk_dread(cur_dev, base + 1 + whole, 1, tbuf); + if (ret != 1) + return -EIO; + memcpy(buf + upto * mydata->sect_size, tbuf, + remain * mydata->sect_size); + upto += remain; + } + + return upto; +} + +static int disk_read(fsdata *mydata, __u32 block, __u32 nr_blocks, void *buf) { ulong ret;
if (!cur_dev) return -1;
+ /* support converting from a larger block size */ + if (IS_ENABLED(CONFIG_FAT_BLK_XLATE) && mydata && + mydata->sect_size != cur_dev->blksz) + return disk_read_conv(mydata, block, nr_blocks, buf); + ret = blk_dread(cur_dev, cur_part_info.start + block, nr_blocks, buf);
if (ret != nr_blocks) @@ -66,7 +146,7 @@ int fat_set_blk_dev(struct blk_desc *dev_desc, struct disk_partition *info) cur_part_info = *info;
/* Make sure it has a valid FAT header */ - if (disk_read(0, 1, buffer) != 1) { + if (disk_read(NULL, 0, 1, buffer) != 1) { cur_dev = NULL; return -1; } @@ -211,7 +291,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry) if (flush_dirty_fat_buffer(mydata) < 0) return -1;
- if (disk_read(startblock, getsize, bufptr) < 0) { + if (disk_read(mydata, startblock, getsize, bufptr) < 0) { debug("Error reading FAT blocks\n"); return ret; } @@ -265,7 +345,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) debug("FAT: Misaligned buffer address (%p)\n", buffer);
while (size >= mydata->sect_size) { - ret = disk_read(startsect++, 1, tmpbuf); + ret = disk_read(mydata, startsect++, 1, tmpbuf); if (ret != 1) { debug("Error reading data (got %d)\n", ret); return -1; @@ -279,7 +359,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) __u32 bytes_read; __u32 sect_count = size / mydata->sect_size;
- ret = disk_read(startsect, sect_count, buffer); + ret = disk_read(mydata, startsect, sect_count, buffer); if (ret != sect_count) { debug("Error reading data (got %d)\n", ret); return -1; @@ -292,7 +372,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) if (size) { ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
- ret = disk_read(startsect, 1, tmpbuf); + ret = disk_read(mydata, startsect, 1, tmpbuf); if (ret != 1) { debug("Error reading data (got %d)\n", ret); return -1; @@ -504,7 +584,7 @@ read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize) return -1; }
- if (disk_read(0, 1, block) < 0) { + if (disk_read(NULL, 0, 1, block) < 0) { debug("Error: reading block\n"); goto fail; } @@ -586,9 +666,14 @@ 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("** FAT sector size mismatch (fs=%hu, dev=%lu)\n", - mydata->sect_size, cur_part_info.blksz); - return -1; + if (IS_ENABLED(CONFIG_FAT_BLK_XLATE)) { + printf("Warning: FAT sector size mismatch (fs=%u, dev=%lu): translating for read-only\n", + mydata->sect_size, cur_part_info.blksz); + } else { + printf("** FAT sector size mismatch (fs=%u, dev=%lu), see CONFIG_FAT_BLK_XLATE\n", + mydata->sect_size, cur_part_info.blksz); + return -1; + } } if (mydata->clust_size == 0) { printf("** FAT cluster size not set\n"); @@ -846,7 +931,7 @@ void *fat_next_cluster(fat_itr *itr, unsigned int *nbytes) * dent at a time and iteratively constructing the vfat long * name. */ - ret = disk_read(sect, read_size, itr->block); + ret = disk_read(itr->fsdata, sect, read_size, itr->block); if (ret < 0) { debug("Error: reading block\n"); return NULL; diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 4d2d4db07fa6..baef52af6363 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -474,7 +474,7 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
startblock += mydata->fat_sect;
- if (disk_read(startblock, getsize, bufptr) < 0) { + if (disk_read(NULL, startblock, getsize, bufptr) < 0) { debug("Error reading FAT blocks\n"); return -1; } @@ -709,7 +709,8 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer, /* partial write at beginning */ if (pos) { wsize = min(bytesperclust - pos, size); - ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster); + ret = disk_read(NULL, startsect, mydata->clust_size, + tmpbuf_cluster); if (ret != mydata->clust_size) { debug("Error reading data (got %d)\n", ret); return -1; @@ -775,7 +776,8 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer, /* partial write at end */ if (size) { wsize = size; - ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster); + ret = disk_read(NULL, startsect, mydata->clust_size, + tmpbuf_cluster); if (ret != mydata->clust_size) { debug("Error reading data (got %d)\n", ret); return -1;

Am 30. März 2023 23:32:22 MESZ schrieb Simon Glass sjg@chromium.org:
At present it is not possible to read from some CDROM drives since the FAT sector size does not match the media's block size. Add a conversion option for this, so that reading is possible.
This does increase SPL size for read-only FAT support by 25 bytes but all but 6 are covered by the previous patch. We could reduce the overhead of this feature to 0 bytes by making the code uglier (using a static variable).
512 and 2048 are not the only physical sector sizes. Some hard drives use 4096.
This change deserves a test case.
Best regards
Heinrich
Signed-off-by: Simon Glass sjg@chromium.org
fs/fat/Kconfig | 13 ++++++ fs/fat/fat.c | 107 ++++++++++++++++++++++++++++++++++++++++----- fs/fat/fat_write.c | 8 ++-- 3 files changed, 114 insertions(+), 14 deletions(-)
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig index 9bb11eac9f7a..b0aa888c6cc4 100644 --- a/fs/fat/Kconfig +++ b/fs/fat/Kconfig @@ -22,3 +22,16 @@ config FS_FAT_MAX_CLUSTSIZE is the smallest amount of disk space that can be used to hold a file. Unless you have an extremely tight memory memory constraints, leave the default.
+config FAT_BLK_XLATE
- bool "Enable FAT filesystem on a device with a larger block size"
- depends on FS_FAT
- help
This provides a simple translation mechanism for reading FAT
filesystems which don't use the same sector size as the underlying
media. For example, the FAT filesystem may use 512 bytes but the
media uses 2048, e.g. on a CDROM drive.
This only supports the case where the FAT filesystem's sector size is
smaller than the media's block size. It does not support creating or
writing files.
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index f0df7988e172..02c6d55a99b3 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -43,13 +43,93 @@ static struct disk_partition cur_part_info; #define DOS_FS_TYPE_OFFSET 0x36 #define DOS_FS32_TYPE_OFFSET 0x52
-static int disk_read(__u32 block, __u32 nr_blocks, void *buf) +/**
- disk_read_conv() - Read blocks and break them into smaller ones
- This is used when the FAT filesystem is hosted on a block device with a
- block size greated than 512 bytes, e.g. the 2048 bytes of a CDROM drive. It
- reads the blocks into a buffer and pulls out what is requested by the calling
- function.
- It uses an internal 2KB buffer on the stack.
- @mydata: Filesystem information
- @block: Block number to read, in terms of mydata->sect_size
- @nr_blocks: Number of blocks to read, in terms of mydata->sect_size
- @buf: Buffer for data
- */
+static int disk_read_conv(fsdata *mydata, __u32 block, __u32 nr_blocks,
void *buf)
+{
- uint factor, whole, remain, upto;
- ulong base, index;
- uint to_copy;
- u8 tbuf[2048];
- int ret;
- log_debug("mydata %x, cur_dev %lx, block %x, nr_block %x\n",
mydata->sect_size, cur_dev->blksz, block, nr_blocks);
- if (mydata->sect_size > cur_dev->blksz ||
cur_dev->blksz > sizeof(tbuf)) {
log_err("Block size %lx not supported\n", cur_dev->blksz);
return -EIO;
- }
- factor = cur_dev->blksz / mydata->sect_size;
- /* get the first partial block */
- base = cur_part_info.start + block / factor;
- index = block % factor;
- log_debug("cur_part_info.start %llx, block %x, base %lx, index %lx\n",
(unsigned long long)cur_part_info.start, block, base, index);
- ret = blk_dread(cur_dev, base, 1, tbuf);
- if (ret != 1)
return -EIO;
- to_copy = min((ulong)nr_blocks, factor - index);
- log_debug("to_copy %x\n", to_copy);
- memcpy(buf, tbuf + index * mydata->sect_size,
to_copy * mydata->sect_size);
- upto = to_copy;
- /* load any whole blocks */
- remain = nr_blocks - upto;
- whole = remain / factor;
- log_debug("factor %x, whole %x, remain %x\n", factor, whole, remain);
- if (whole) {
ret = blk_dread(cur_dev, base + 1, whole,
buf + upto * mydata->sect_size);
if (ret != whole)
return -EIO;
upto += whole * factor;
remain = nr_blocks - upto;
- }
- /* load any blocks at the end */
- log_debug("end: remain %x\n", remain);
- if (remain) {
ret = blk_dread(cur_dev, base + 1 + whole, 1, tbuf);
if (ret != 1)
return -EIO;
memcpy(buf + upto * mydata->sect_size, tbuf,
remain * mydata->sect_size);
upto += remain;
- }
- return upto;
+}
+static int disk_read(fsdata *mydata, __u32 block, __u32 nr_blocks, void *buf) { ulong ret;
if (!cur_dev) return -1;
/* support converting from a larger block size */
if (IS_ENABLED(CONFIG_FAT_BLK_XLATE) && mydata &&
mydata->sect_size != cur_dev->blksz)
return disk_read_conv(mydata, block, nr_blocks, buf);
ret = blk_dread(cur_dev, cur_part_info.start + block, nr_blocks, buf);
if (ret != nr_blocks)
@@ -66,7 +146,7 @@ int fat_set_blk_dev(struct blk_desc *dev_desc, struct disk_partition *info) cur_part_info = *info;
/* Make sure it has a valid FAT header */
- if (disk_read(0, 1, buffer) != 1) {
- if (disk_read(NULL, 0, 1, buffer) != 1) { cur_dev = NULL; return -1; }
@@ -211,7 +291,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry) if (flush_dirty_fat_buffer(mydata) < 0) return -1;
if (disk_read(startblock, getsize, bufptr) < 0) {
}if (disk_read(mydata, startblock, getsize, bufptr) < 0) { debug("Error reading FAT blocks\n"); return ret;
@@ -265,7 +345,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) debug("FAT: Misaligned buffer address (%p)\n", buffer);
while (size >= mydata->sect_size) {
ret = disk_read(startsect++, 1, tmpbuf);
ret = disk_read(mydata, startsect++, 1, tmpbuf); if (ret != 1) { debug("Error reading data (got %d)\n", ret); return -1;
@@ -279,7 +359,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) __u32 bytes_read; __u32 sect_count = size / mydata->sect_size;
ret = disk_read(startsect, sect_count, buffer);
if (ret != sect_count) { debug("Error reading data (got %d)\n", ret); return -1;ret = disk_read(mydata, startsect, sect_count, buffer);
@@ -292,7 +372,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) if (size) { ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
ret = disk_read(startsect, 1, tmpbuf);
if (ret != 1) { debug("Error reading data (got %d)\n", ret); return -1;ret = disk_read(mydata, startsect, 1, tmpbuf);
@@ -504,7 +584,7 @@ read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize) return -1; }
- if (disk_read(0, 1, block) < 0) {
- if (disk_read(NULL, 0, 1, block) < 0) { debug("Error: reading block\n"); goto fail; }
@@ -586,9 +666,14 @@ 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("** FAT sector size mismatch (fs=%hu, dev=%lu)\n",
mydata->sect_size, cur_part_info.blksz);
return -1;
if (IS_ENABLED(CONFIG_FAT_BLK_XLATE)) {
printf("Warning: FAT sector size mismatch (fs=%u, dev=%lu): translating for read-only\n",
mydata->sect_size, cur_part_info.blksz);
} else {
printf("** FAT sector size mismatch (fs=%u, dev=%lu), see CONFIG_FAT_BLK_XLATE\n",
mydata->sect_size, cur_part_info.blksz);
return -1;
} if (mydata->clust_size == 0) { printf("** FAT cluster size not set\n");}
@@ -846,7 +931,7 @@ void *fat_next_cluster(fat_itr *itr, unsigned int *nbytes) * dent at a time and iteratively constructing the vfat long * name. */
- ret = disk_read(sect, read_size, itr->block);
- ret = disk_read(itr->fsdata, sect, read_size, itr->block); if (ret < 0) { debug("Error: reading block\n"); return NULL;
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 4d2d4db07fa6..baef52af6363 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -474,7 +474,7 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
startblock += mydata->fat_sect;
if (disk_read(startblock, getsize, bufptr) < 0) {
}if (disk_read(NULL, startblock, getsize, bufptr) < 0) { debug("Error reading FAT blocks\n"); return -1;
@@ -709,7 +709,8 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer, /* partial write at beginning */ if (pos) { wsize = min(bytesperclust - pos, size);
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
ret = disk_read(NULL, startsect, mydata->clust_size,
if (ret != mydata->clust_size) { debug("Error reading data (got %d)\n", ret); return -1;tmpbuf_cluster);
@@ -775,7 +776,8 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer, /* partial write at end */ if (size) { wsize = size;
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
ret = disk_read(NULL, startsect, mydata->clust_size,
if (ret != mydata->clust_size) { debug("Error reading data (got %d)\n", ret); return -1;tmpbuf_cluster);

On 3/31/23 00:55, Heinrich Schuchardt wrote:
Am 30. März 2023 23:32:22 MESZ schrieb Simon Glass sjg@chromium.org:
At present it is not possible to read from some CDROM drives since the FAT sector size does not match the media's block size. Add a conversion option for this, so that reading is possible.
This does increase SPL size for read-only FAT support by 25 bytes but all but 6 are covered by the previous patch. We could reduce the overhead of this feature to 0 bytes by making the code uglier (using a static variable).
512 and 2048 are not the only physical sector sizes. Some hard drives use 4096.
To complete the logic you have first to take into account the size of a FAT sector (BPB_BytsPerSec) defined in the FAT boot sector which can take values 512, 1024, 2048, or 4096.
Cf. https://academy.cba.mit.edu/classes/networking_communications/SD/FAT.pdf
Best regards
Heinrich
This change deserves a test case.
Best regards
Heinrich
Signed-off-by: Simon Glass sjg@chromium.org
fs/fat/Kconfig | 13 ++++++ fs/fat/fat.c | 107 ++++++++++++++++++++++++++++++++++++++++----- fs/fat/fat_write.c | 8 ++-- 3 files changed, 114 insertions(+), 14 deletions(-)
diff --git a/fs/fat/Kconfig b/fs/fat/Kconfig index 9bb11eac9f7a..b0aa888c6cc4 100644 --- a/fs/fat/Kconfig +++ b/fs/fat/Kconfig @@ -22,3 +22,16 @@ config FS_FAT_MAX_CLUSTSIZE is the smallest amount of disk space that can be used to hold a file. Unless you have an extremely tight memory memory constraints, leave the default.
+config FAT_BLK_XLATE
- bool "Enable FAT filesystem on a device with a larger block size"
- depends on FS_FAT
- help
This provides a simple translation mechanism for reading FAT
filesystems which don't use the same sector size as the underlying
media. For example, the FAT filesystem may use 512 bytes but the
media uses 2048, e.g. on a CDROM drive.
This only supports the case where the FAT filesystem's sector size is
smaller than the media's block size. It does not support creating or
writing files.
diff --git a/fs/fat/fat.c b/fs/fat/fat.c index f0df7988e172..02c6d55a99b3 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -43,13 +43,93 @@ static struct disk_partition cur_part_info; #define DOS_FS_TYPE_OFFSET 0x36 #define DOS_FS32_TYPE_OFFSET 0x52
-static int disk_read(__u32 block, __u32 nr_blocks, void *buf) +/**
- disk_read_conv() - Read blocks and break them into smaller ones
- This is used when the FAT filesystem is hosted on a block device with a
- block size greated than 512 bytes, e.g. the 2048 bytes of a CDROM drive. It
- reads the blocks into a buffer and pulls out what is requested by the calling
- function.
- It uses an internal 2KB buffer on the stack.
- @mydata: Filesystem information
- @block: Block number to read, in terms of mydata->sect_size
- @nr_blocks: Number of blocks to read, in terms of mydata->sect_size
- @buf: Buffer for data
- */
+static int disk_read_conv(fsdata *mydata, __u32 block, __u32 nr_blocks,
void *buf)
+{
- uint factor, whole, remain, upto;
- ulong base, index;
- uint to_copy;
- u8 tbuf[2048];
- int ret;
- log_debug("mydata %x, cur_dev %lx, block %x, nr_block %x\n",
mydata->sect_size, cur_dev->blksz, block, nr_blocks);
- if (mydata->sect_size > cur_dev->blksz ||
cur_dev->blksz > sizeof(tbuf)) {
log_err("Block size %lx not supported\n", cur_dev->blksz);
return -EIO;
- }
- factor = cur_dev->blksz / mydata->sect_size;
- /* get the first partial block */
- base = cur_part_info.start + block / factor;
- index = block % factor;
- log_debug("cur_part_info.start %llx, block %x, base %lx, index %lx\n",
(unsigned long long)cur_part_info.start, block, base, index);
- ret = blk_dread(cur_dev, base, 1, tbuf);
- if (ret != 1)
return -EIO;
- to_copy = min((ulong)nr_blocks, factor - index);
- log_debug("to_copy %x\n", to_copy);
- memcpy(buf, tbuf + index * mydata->sect_size,
to_copy * mydata->sect_size);
- upto = to_copy;
- /* load any whole blocks */
- remain = nr_blocks - upto;
- whole = remain / factor;
- log_debug("factor %x, whole %x, remain %x\n", factor, whole, remain);
- if (whole) {
ret = blk_dread(cur_dev, base + 1, whole,
buf + upto * mydata->sect_size);
if (ret != whole)
return -EIO;
upto += whole * factor;
remain = nr_blocks - upto;
- }
- /* load any blocks at the end */
- log_debug("end: remain %x\n", remain);
- if (remain) {
ret = blk_dread(cur_dev, base + 1 + whole, 1, tbuf);
if (ret != 1)
return -EIO;
memcpy(buf + upto * mydata->sect_size, tbuf,
remain * mydata->sect_size);
upto += remain;
- }
- return upto;
+}
+static int disk_read(fsdata *mydata, __u32 block, __u32 nr_blocks, void *buf) { ulong ret;
if (!cur_dev) return -1;
/* support converting from a larger block size */
if (IS_ENABLED(CONFIG_FAT_BLK_XLATE) && mydata &&
mydata->sect_size != cur_dev->blksz)
return disk_read_conv(mydata, block, nr_blocks, buf);
ret = blk_dread(cur_dev, cur_part_info.start + block, nr_blocks, buf);
if (ret != nr_blocks)
@@ -66,7 +146,7 @@ int fat_set_blk_dev(struct blk_desc *dev_desc, struct disk_partition *info) cur_part_info = *info;
/* Make sure it has a valid FAT header */
- if (disk_read(0, 1, buffer) != 1) {
- if (disk_read(NULL, 0, 1, buffer) != 1) { cur_dev = NULL; return -1; }
@@ -211,7 +291,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry) if (flush_dirty_fat_buffer(mydata) < 0) return -1;
if (disk_read(startblock, getsize, bufptr) < 0) {
}if (disk_read(mydata, startblock, getsize, bufptr) < 0) { debug("Error reading FAT blocks\n"); return ret;
@@ -265,7 +345,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) debug("FAT: Misaligned buffer address (%p)\n", buffer);
while (size >= mydata->sect_size) {
ret = disk_read(startsect++, 1, tmpbuf);
ret = disk_read(mydata, startsect++, 1, tmpbuf); if (ret != 1) { debug("Error reading data (got %d)\n", ret); return -1;
@@ -279,7 +359,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) __u32 bytes_read; __u32 sect_count = size / mydata->sect_size;
ret = disk_read(startsect, sect_count, buffer);
if (ret != sect_count) { debug("Error reading data (got %d)\n", ret); return -1;ret = disk_read(mydata, startsect, sect_count, buffer);
@@ -292,7 +372,7 @@ get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) if (size) { ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
ret = disk_read(startsect, 1, tmpbuf);
if (ret != 1) { debug("Error reading data (got %d)\n", ret); return -1;ret = disk_read(mydata, startsect, 1, tmpbuf);
@@ -504,7 +584,7 @@ read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize) return -1; }
- if (disk_read(0, 1, block) < 0) {
- if (disk_read(NULL, 0, 1, block) < 0) { debug("Error: reading block\n"); goto fail; }
@@ -586,9 +666,14 @@ 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("** FAT sector size mismatch (fs=%hu, dev=%lu)\n",
mydata->sect_size, cur_part_info.blksz);
return -1;
if (IS_ENABLED(CONFIG_FAT_BLK_XLATE)) {
printf("Warning: FAT sector size mismatch (fs=%u, dev=%lu): translating for read-only\n",
mydata->sect_size, cur_part_info.blksz);
} else {
printf("** FAT sector size mismatch (fs=%u, dev=%lu), see CONFIG_FAT_BLK_XLATE\n",
mydata->sect_size, cur_part_info.blksz);
return -1;
} if (mydata->clust_size == 0) { printf("** FAT cluster size not set\n");}
@@ -846,7 +931,7 @@ void *fat_next_cluster(fat_itr *itr, unsigned int *nbytes) * dent at a time and iteratively constructing the vfat long * name. */
- ret = disk_read(sect, read_size, itr->block);
- ret = disk_read(itr->fsdata, sect, read_size, itr->block); if (ret < 0) { debug("Error: reading block\n"); return NULL;
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 4d2d4db07fa6..baef52af6363 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -474,7 +474,7 @@ static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
startblock += mydata->fat_sect;
if (disk_read(startblock, getsize, bufptr) < 0) {
}if (disk_read(NULL, startblock, getsize, bufptr) < 0) { debug("Error reading FAT blocks\n"); return -1;
@@ -709,7 +709,8 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer, /* partial write at beginning */ if (pos) { wsize = min(bytesperclust - pos, size);
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
ret = disk_read(NULL, startsect, mydata->clust_size,
if (ret != mydata->clust_size) { debug("Error reading data (got %d)\n", ret); return -1;tmpbuf_cluster);
@@ -775,7 +776,8 @@ get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer, /* partial write at end */ if (size) { wsize = size;
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
ret = disk_read(NULL, startsect, mydata->clust_size,
if (ret != mydata->clust_size) { debug("Error reading data (got %d)\n", ret); return -1;tmpbuf_cluster);

Hi Heinrich,
On Fri, 31 Mar 2023 at 04:28, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 3/31/23 00:55, Heinrich Schuchardt wrote:
Am 30. März 2023 23:32:22 MESZ schrieb Simon Glass sjg@chromium.org:
At present it is not possible to read from some CDROM drives since the FAT sector size does not match the media's block size. Add a conversion option for this, so that reading is possible.
This does increase SPL size for read-only FAT support by 25 bytes but all but 6 are covered by the previous patch. We could reduce the overhead of this feature to 0 bytes by making the code uglier (using a static variable).
512 and 2048 are not the only physical sector sizes. Some hard drives use 4096.
To complete the logic you have first to take into account the size of a FAT sector (BPB_BytsPerSec) defined in the FAT boot sector which can take values 512, 1024, 2048, or 4096.
Cf. https://academy.cba.mit.edu/classes/networking_communications/SD/FAT.pdf
Best regards
Heinrich
This change deserves a test case.
If we keep this I should be able to add something simple.
Regards, Simon

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 sjg@chromium.org ---
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 371ca9de8429..79ea35918575 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -19,6 +19,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_DISTRO_DEFAULTS=y CONFIG_BOOTSTAGE=y @@ -27,6 +28,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 @@ -46,12 +50,14 @@ 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_NFS is not set +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

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 sjg@chromium.org ---
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 | 4 +++- drivers/misc/qfw.c | 8 ++++++++ 5 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h index f4ce72d56602..f0ab3ba5c146 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 <asm-generic/global_data.h> diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 22d103df4ee8..ea58259ad774 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 0970efa4726f..9504e7fc293e 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", 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 ea834a5035f5..66b1700adc62 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -79,17 +79,18 @@ 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]; int i;
rom_table_start = ROM_TABLE_ADDR; + gd->arch.table_start = rom_table_start;
debug("Writing tables to %x:\n", rom_table_start); 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, @@ -131,6 +132,7 @@ int write_tables(void) } rom_table_start = rom_table_end; } + gd->arch.table_end = rom_table_start;
if (IS_ENABLED(CONFIG_SEABIOS)) { /* make sure the last item is zero */ diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 0a93feeb4b2e..c0da4bd7359e 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,9 @@ ulong write_acpi_tables(ulong addr) return addr; }
+ 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++) {

Fix the header order in this file.
Signed-off-by: Simon Glass sjg@chromium.org ---
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 2e44bdf0df3e..e72d8164ebf6 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -11,16 +11,16 @@ #include <efi.h> #include <efi_loader.h> #include <env_internal.h> +#include <extension_board.h> #include <init.h> #include <led.h> +#include <malloc.h> #include <os.h> #include <asm/global_data.h> #include <asm/test.h> #include <asm/u-boot-sandbox.h> #include <linux/kernel.h> -#include <malloc.h> - -#include <extension_board.h> +#include <linux/sizes.h>
/* * Pointer to initial global data area

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 sjg@chromium.org ---
board/sandbox/sandbox.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c index e72d8164ebf6..2083eaa2dc55 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -15,7 +15,9 @@ #include <init.h> #include <led.h> #include <malloc.h> +#include <mapmem.h> #include <os.h> +#include <acpi/acpi_table.h> #include <asm/global_data.h> #include <asm/test.h> #include <asm/u-boot-sandbox.h> @@ -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

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 sjg@chromium.org ---
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 2ddc3502b5df..f755af76f866 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -10,6 +10,9 @@ #include <log.h> #include <mapmem.h> #include <acpi/acpi_table.h> +#include <asm/global_data.h> + +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); }

Am 30. März 2023 23:32:27 MESZ schrieb Simon Glass sjg@chromium.org:
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.
I understand that this works on QEMU which provides ACPI tables. But on all other systems that use ACPI you will still have to generate ACPI tables.
So you cannot simply drop the table generation.
If you have moved the generation step somewhere else, this patch should mention the new location.
Best regards
Heinrich
Signed-off-by: Simon Glass sjg@chromium.org
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 2ddc3502b5df..f755af76f866 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -10,6 +10,9 @@ #include <log.h> #include <mapmem.h> #include <acpi/acpi_table.h> +#include <asm/global_data.h>
+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);
}

Hi Heinrich,
On Fri, 31 Mar 2023 at 10:53, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 30. März 2023 23:32:27 MESZ schrieb Simon Glass sjg@chromium.org:
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.
I understand that this works on QEMU which provides ACPI tables. But on all other systems that use ACPI you will still have to generate ACPI tables.
So you cannot simply drop the table generation.
If you have moved the generation step somewhere else, this patch should mention the new location.
This only applies to x86 as we don't have ACPI tables for other archs. The generation step has not moved, it's just that they have always been generated before start-up. I think this might have been overlooked when writing the UEFI code? I'm actually not sure how this worked before on any x86 board.
See last_stage_init() which calls write_tables().
Regards, Simon
Signed-off-by: Simon Glass sjg@chromium.org
lib/efi_loader/efi_acpi.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-)
[..]

Hi Bin,
On Thu, 30 Mar 2023 at 15:32, Simon Glass sjg@chromium.org wrote:
This series adds various minor features so that qemu-x86_64 can boot the Ubuntu 2022.04 installer using a virtio device:
qemu-system-x86_64 -M pc -drive format=raw,file=root.img -bios /tmp/b/qemu-x86_64/u-boot.rom -drive if=virtio,file=ubuntu-22.04.2-desktop-amd64.iso -smp 4 -m 4G -serial mon:stdio
The main changes include:
- Enable video in SPL while running in 32-bit mode
- Drop the duplicate ACPI tables with EFI
- Support PCI autoconfig in SPL
- Support FAT on a CDROM filesystem
- Improved bootstd rules around device tree and efi_set_bootdev()
There are also quite a number of minor tweaks and fixes to make things easier to use.
This series is based on an older version of the SPL-video series from Nikhil M Jain. It is available at u-boot-dm/bryc-working
Simon Glass (38): x86: Tidy up availability of string functions x86: Allow listing MTRRs in SPL bios_emulator: Add Kconfig and adjust Makefile for SPL bios_emulator: Drop VIDEO_IO_OFFSET x86: Tidy up EFI code in interrupt_init() x86: Set high bits of the mtrr base registrer x86: Add a comment for board_init_f_r_trampoline() x86: Show the CPU physical address size with bdinfo x86: Correct get_sp() implementation for 64-bit x86: Show an error when a BINS exception occurs acpi: Add a comment to set the acpi tables bdinfo: Show the RAM top and approximate stack pointer part: Allow setting the partition-table type qfw: Show the file address if available log: Tidy up an ambiguous comment. video: Allow building video drivers for SPL qfw: Set the address of the ACPI tables efi: Show all known UUIDs with CONFIG_CMD_EFIDEBUG x86: Improve the trampoline in 64-bit mode Show the malloc base with the bdinfo command nvme: Provide more useful debugging messages pci: Support autoconfig in SPL pci: Allow the video BIOS to work in SPL with QEMU pci: Tidy up logging and reporting for video BIOS x86: Allow video-BIOS code to be built for SPL x86: Pass video settings from SPL to U-Boot proper x86: Init video in SPL if enabled pci: Adjust video BIOS debugging to be SPL-friendly pci: Mask the ROM address in case it is already enabled x86: Enable display for QEMU 64-bit x86: Allow logging to be used in SPL reliably fs: fat: Shrink the size of a few strings fs: fat: Support reading from a larger block size x86: Enable useful options for qemu-86_64 x86: Record the start and end of the tables sandbox: Correct header order in board file sandbox: Install ACPI tables on startup efi: Use the installed ACPI tables
arch/sandbox/include/asm/global_data.h | 4 + arch/x86/cpu/i386/interrupt.c | 17 +-- arch/x86/cpu/mtrr.c | 62 +++++++- arch/x86/cpu/start64.S | 19 +++ arch/x86/include/asm/global_data.h | 4 + arch/x86/include/asm/mtrr.h | 20 +++ arch/x86/include/asm/string.h | 6 +- arch/x86/include/asm/u-boot-x86.h | 21 ++- arch/x86/lib/Makefile | 9 +- arch/x86/lib/bdinfo.c | 5 + arch/x86/lib/bios.c | 5 +- arch/x86/lib/bootm.c | 2 +- arch/x86/lib/spl.c | 26 +++- arch/x86/lib/tables.c | 4 +- board/google/Kconfig | 7 - board/sandbox/sandbox.c | 22 ++- cmd/Kconfig | 8 ++ cmd/acpi.c | 24 +++- cmd/bdinfo.c | 6 + cmd/part.c | 34 +++++ cmd/qfw.c | 2 +- cmd/x86/mtrr.c | 60 +------- common/board_f.c | 12 +- common/board_r.c | 7 +- common/log.c | 2 +- configs/qemu-x86_64_defconfig | 14 ++ disk/part.c | 16 +++ doc/usage/cmd/acpi.rst | 29 +++- doc/usage/cmd/part.rst | 74 ++++++++++ doc/usage/cmd/qfw.rst | 28 ++-- drivers/Kconfig | 2 + drivers/Makefile | 5 +- drivers/bios_emulator/Kconfig | 10 ++ drivers/bios_emulator/biosemui.h | 18 +-- drivers/bios_emulator/x86emu/sys.c | 1 + drivers/misc/qfw.c | 12 ++ drivers/nvme/nvme.c | 36 +++-- drivers/pci/Kconfig | 8 ++ drivers/pci/pci-uclass.c | 10 +- drivers/pci/pci_rom.c | 165 +++++++++++++++++----- fs/fat/Kconfig | 13 ++ fs/fat/fat.c | 117 ++++++++++++--- fs/fat/fat_write.c | 22 ++- include/asm-generic/global_data.h | 11 ++ include/bloblist.h | 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 - include/part.h | 9 ++ include/pci_ids.h | 1 + include/video.h | 24 ++++ lib/efi_loader/efi_acpi.c | 33 +++-- lib/uuid.c | 2 +- test/dm/acpi.c | 38 +++++ 57 files changed, 866 insertions(+), 233 deletions(-) create mode 100644 drivers/bios_emulator/Kconfig
-- 2.40.0.348.gf938b09366-goog
Any thoughts on this series, please? I have some comments from Heinrich so will respin this, but would like to check first if there is anything else?
Regards, Simon
participants (4)
-
Heinrich Schuchardt
-
Ilias Apalodimas
-
Mark Kettenis
-
Simon Glass