summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml8
-rw-r--r--arch/x86/cpu/cpu.c24
-rw-r--r--arch/x86/cpu/i386/call64.S35
-rw-r--r--arch/x86/cpu/i386/cpu.c41
-rw-r--r--arch/x86/cpu/mtrr.c115
-rw-r--r--arch/x86/cpu/qemu/dram.c18
-rw-r--r--arch/x86/cpu/qemu/e820.c62
-rw-r--r--arch/x86/cpu/qemu/qemu.c20
-rw-r--r--arch/x86/cpu/start.S4
-rw-r--r--arch/x86/cpu/start16.S3
-rw-r--r--arch/x86/cpu/x86_64/cpu.c5
-rw-r--r--arch/x86/include/asm/bootparam.h15
-rw-r--r--arch/x86/include/asm/cpu.h91
-rw-r--r--arch/x86/include/asm/e820.h95
-rw-r--r--arch/x86/include/asm/interrupt.h1
-rw-r--r--arch/x86/include/asm/msr.h9
-rw-r--r--arch/x86/include/asm/mtrr.h16
-rw-r--r--arch/x86/include/asm/processor.h5
-rw-r--r--arch/x86/lib/Makefile2
-rw-r--r--arch/x86/lib/bios.c27
-rw-r--r--arch/x86/lib/bios_interrupts.c8
-rw-r--r--arch/x86/lib/e820.c70
-rw-r--r--arch/x86/lib/i8259.c2
-rw-r--r--arch/x86/lib/spl.c4
-rw-r--r--arch/x86/lib/tables.c9
-rw-r--r--arch/x86/lib/zimage.c34
-rw-r--r--boot/bootdev-uclass.c7
-rw-r--r--boot/bootflow.c7
-rw-r--r--cmd/acpi.c59
-rw-r--r--cmd/bootflow.c2
-rw-r--r--cmd/x86/mtrr.c11
-rw-r--r--configs/qemu-x86_64_defconfig18
-rw-r--r--configs/qemu-x86_defconfig12
-rw-r--r--doc/develop/bootstd/overview.rst5
-rw-r--r--doc/usage/cmd/acpi.rst20
-rw-r--r--drivers/misc/qfw_acpi.c32
-rw-r--r--include/acpi/acpi_table.h2
-rw-r--r--include/bootflow.h2
-rw-r--r--include/bootstd.h3
-rw-r--r--include/mapmem.h2
-rw-r--r--lib/acpi/acpi_table.c5
-rw-r--r--test/boot/bootdev.c1
-rw-r--r--test/boot/bootflow.c5
-rw-r--r--test/dm/acpi.c59
-rw-r--r--test/py/conftest.py22
-rw-r--r--test/py/console_base.py25
-rw-r--r--test/py/pytest.ini1
-rw-r--r--test/py/tests/test_distro.py61
-rw-r--r--test/py/tests/test_ut.py17
49 files changed, 803 insertions, 298 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2dbe6325f33..0f27e67abb9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -565,7 +565,7 @@ coreboot test.py:
- export USE_LABGRID_SJG=1
# export verbose="-v"
- ${SRC}/test/py/test.py --role ${ROLE} --build-dir "${OUT}"
- --capture=tee-sys -k "not bootstd" || ret=$?
+ --capture=tee-sys -k "not bootstd ${TEST_PY_TEST_SPEC}" || ret=$?
- U_BOOT_BOARD_IDENTITY="${ROLE}" u-boot-test-release || true
- if [[ $ret -ne 0 ]]; then
exit $ret;
@@ -702,3 +702,9 @@ vf2:
variables:
ROLE: vf2
<<: *lab_dfn
+
+qemu-x86_64:
+ variables:
+ ROLE: qemu-x86_64
+ TEST_PY_TEST_SPEC: "and not sleep"
+ <<: *lab_dfn
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index a8b21406ac0..c373b14df30 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -364,3 +364,27 @@ long locate_coreboot_table(void)
return addr;
}
+
+static bool has_cpuid(void)
+{
+ return flag_is_changeable_p(X86_EFLAGS_ID);
+}
+
+static uint cpu_cpuid_extended_level(void)
+{
+ return cpuid_eax(0x80000000);
+}
+
+int cpu_phys_address_size(void)
+{
+ if (!has_cpuid())
+ return 32;
+
+ if (cpu_cpuid_extended_level() >= 0x80000008)
+ return cpuid_eax(0x80000008) & 0xff;
+
+ if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36))
+ return 36;
+
+ return 32;
+}
diff --git a/arch/x86/cpu/i386/call64.S b/arch/x86/cpu/i386/call64.S
index 424732fa3fa..a9d3f16a6ad 100644
--- a/arch/x86/cpu/i386/call64.S
+++ b/arch/x86/cpu/i386/call64.S
@@ -7,6 +7,7 @@
*/
#include <asm/msr-index.h>
+#include <asm/processor.h>
#include <asm/processor-flags.h>
.code32
@@ -21,17 +22,19 @@ cpu_call64:
* ecx - target
*/
cli
+ pushl $0 /* top 64-bits of target */
push %ecx /* arg2 = target */
push %edx /* arg1 = setup_base */
mov %eax, %ebx
- /* Load new GDT with the 64bit segments using 32bit descriptor */
- leal gdt, %eax
- movl %eax, gdt+2
- lgdt gdt
+ # disable paging
+ movl %cr0, %eax
+ andl $~X86_CR0_PG, %eax
+ movl %eax, %cr0
/* Enable PAE mode */
- movl $(X86_CR4_PAE), %eax
+ movl %cr4, %eax
+ orl $X86_CR4_PAE, %eax
movl %eax, %cr4
/* Enable the boot page tables */
@@ -44,12 +47,6 @@ cpu_call64:
btsl $_EFER_LME, %eax
wrmsr
- /* After gdt is loaded */
- xorl %eax, %eax
- lldt %ax
- movl $0x20, %eax
- ltr %ax
-
/*
* Setup for the jump to 64bit mode
*
@@ -62,22 +59,18 @@ cpu_call64:
*/
pop %esi /* setup_base */
- pushl $0x10
- leal lret_target, %eax
- pushl %eax
-
/* Enter paged protected Mode, activating Long Mode */
- movl $(X86_CR0_PG | X86_CR0_PE), %eax
+ movl %cr0, %eax
+ orl $X86_CR0_PG, %eax
movl %eax, %cr0
/* Jump from 32bit compatibility mode into 64bit mode. */
- lret
+ ljmp $(X86_GDT_ENTRY_64BIT_CS * X86_GDT_ENTRY_SIZE), $lret_target
-code64:
+.code64
lret_target:
- pop %eax /* target */
- mov %eax, %eax /* Clear bits 63:32 */
- jmp *%eax /* Jump to the 64-bit target */
+ pop %rax /* target */
+ jmp *%rax /* Jump to the 64-bit target */
.globl call64_stub_size
call64_stub_size:
diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c
index a51a24498a7..ee6dbeb5c48 100644
--- a/arch/x86/cpu/i386/cpu.c
+++ b/arch/x86/cpu/i386/cpu.c
@@ -35,10 +35,6 @@
DECLARE_GLOBAL_DATA_PTR;
-#define CPUID_FEATURE_PAE BIT(6)
-#define CPUID_FEATURE_PSE36 BIT(17)
-#define CPUID_FEAURE_HTT BIT(28)
-
/*
* Constructor for a conventional segment GDT (or LDT) entry
* This is a macro so it can be used in initialisers
@@ -160,6 +156,9 @@ void arch_setup_gd(gd_t *new_gd)
gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_CS] = GDT_ENTRY(0x809b, 0, 0xfffff);
gdt_addr[X86_GDT_ENTRY_16BIT_FLAT_DS] = GDT_ENTRY(0x8093, 0, 0xfffff);
+ gdt_addr[X86_GDT_ENTRY_64BIT_CS] = GDT_ENTRY(0xaf9b, 0, 0xfffff);
+ gdt_addr[X86_GDT_ENTRY_64BIT_TS1] = GDT_ENTRY(0x8980, 0, 0xfffff);
+ gdt_addr[X86_GDT_ENTRY_64BIT_TS2] = 0;
load_gdt(gdt_addr, X86_GDT_NUM_ENTRIES);
load_ds(X86_GDT_ENTRY_32BIT_DS);
@@ -409,25 +408,6 @@ static void setup_identity(void)
}
}
-static uint cpu_cpuid_extended_level(void)
-{
- return cpuid_eax(0x80000000);
-}
-
-int cpu_phys_address_size(void)
-{
- if (!has_cpuid())
- return 32;
-
- if (cpu_cpuid_extended_level() >= 0x80000008)
- return cpuid_eax(0x80000008) & 0xff;
-
- if (cpuid_edx(1) & (CPUID_FEATURE_PAE | CPUID_FEATURE_PSE36))
- return 36;
-
- return 32;
-}
-
static void setup_mtrr(void)
{
u64 mtrr_cap;
@@ -589,6 +569,13 @@ int cpu_has_64bit(void)
#define PAGETABLE_BASE 0x80000
#define PAGETABLE_SIZE (6 * 4096)
+#define _PRES BIT(0) /* present */
+#define _RW BIT(1) /* write allowed */
+#define _US BIT(2) /* user-access allowed */
+#define _A BIT(5) /* has been accessed */
+#define _DT BIT(6) /* has been written to */
+#define _PS BIT(7) /* indicates 2MB page size here */
+
/**
* build_pagetable() - build a flat 4GiB page table structure for 64-bti mode
*
@@ -601,15 +588,17 @@ static void build_pagetable(uint32_t *pgtable)
memset(pgtable, '\0', PAGETABLE_SIZE);
/* Level 4 needs a single entry */
- pgtable[0] = (ulong)&pgtable[1024] + 7;
+ pgtable[0] = (ulong)&pgtable[1024] + _PRES + _RW + _US + _A;
/* Level 3 has one 64-bit entry for each GiB of memory */
for (i = 0; i < 4; i++)
- pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i + 7;
+ pgtable[1024 + i * 2] = (ulong)&pgtable[2048] + 0x1000 * i +
+ _PRES + _RW + _US + _A;
/* Level 2 has 2048 64-bit entries, each repesenting 2MiB */
for (i = 0; i < 2048; i++)
- pgtable[2048 + i * 2] = 0x183 + (i << 21UL);
+ pgtable[2048 + i * 2] = _PRES + _RW + _US + _PS + _A + _DT +
+ (i << 21UL);
}
int cpu_jump_to_64bit(ulong setup_base, ulong target)
diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c
index 07ea89162de..7a0f00b9b8f 100644
--- a/arch/x86/cpu/mtrr.c
+++ b/arch/x86/cpu/mtrr.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2014 Google, Inc
+ * Portions added from coreboot
*
* Memory Type Range Regsters - these are used to tell the CPU whether
* memory is cacheable and if so the cache write mode to use.
@@ -16,6 +17,7 @@
* since the MTRR registers are sometimes in flux.
*/
+#include <cpu.h>
#include <cpu_func.h>
#include <log.h>
#include <sort.h>
@@ -39,6 +41,27 @@ static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
"Back",
};
+u64 mtrr_to_size(u64 mask)
+{
+ u64 size;
+
+ size = ~mask & ((1ULL << cpu_phys_address_size()) - 1);
+ size |= (1 << 12) - 1;
+ size += 1;
+
+ return size;
+}
+
+u64 mtrr_to_mask(u64 size)
+{
+ u64 mask;
+
+ mask = ~(size - 1);
+ mask &= (1ull << cpu_phys_address_size()) - 1;
+
+ return mask;
+}
+
/* Prepare to adjust MTRRs */
void mtrr_open(struct mtrr_state *state, bool do_caches)
{
@@ -68,11 +91,9 @@ void mtrr_close(struct mtrr_state *state, bool do_caches)
static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size)
{
- u64 mask;
+ u64 mask = mtrr_to_mask(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);
}
@@ -184,30 +205,80 @@ int mtrr_commit(bool do_caches)
return 0;
}
-int mtrr_add_request(int type, uint64_t start, uint64_t size)
+/* fms: find most significant bit set (from Linux) */
+static inline uint fms(uint val)
+{
+ uint ret;
+
+ __asm__("bsrl %1,%0\n\t"
+ "jnz 1f\n\t"
+ "movl $0,%0\n"
+ "1:" : "=r" (ret) : "mr" (val));
+
+ return ret;
+}
+
+/*
+ * fms64: find most significant bit set in a 64-bit word
+ * As samples, fms64(0x0) = 0; fms64(0x4400) = 14;
+ * fms64(0x40400000000) = 42.
+ */
+static uint fms64(uint64_t val)
+{
+ u32 hi = (u32)(val >> 32);
+
+ if (!hi)
+ return fms((u32)val);
+
+ return fms(hi) + 32;
+}
+
+int mtrr_add_request(int type, u64 base, uint64_t size)
{
struct mtrr_request *req;
- uint64_t mask;
+ u64 mask;
debug("%s: count=%d\n", __func__, gd->arch.mtrr_req_count);
if (!gd->arch.has_mtrr)
return -ENOSYS;
- if (!is_power_of_2(size))
- return -EINVAL;
-
- if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
- return -ENOSPC;
- req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
- req->type = type;
- req->start = start;
- req->size = size;
- debug("%d: type=%d, %08llx %08llx\n", gd->arch.mtrr_req_count - 1,
- req->type, req->start, req->size);
- mask = ~(req->size - 1);
- mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
- mask |= MTRR_PHYS_MASK_VALID;
- debug(" %016llx %016llx\n", req->start | req->type, mask);
+ while (size) {
+ uint addr_lsb;
+ uint size_msb;
+ u64 mtrr_size;
+
+ addr_lsb = fls64(base);
+ size_msb = fms64(size);
+
+ /*
+ * All MTRR entries need to have their base aligned to the
+ * mask size. The maximum size is calculated by a function of
+ * the min base bit set and maximum size bit set.
+ * Algorithm is from coreboot
+ */
+ if (!addr_lsb || addr_lsb > size_msb)
+ mtrr_size = 1ull << size_msb;
+ else
+ mtrr_size = 1ull << addr_lsb;
+ log_debug("addr_lsb %x size_msb %x mtrr_size %llx\n",
+ addr_lsb, size_msb, mtrr_size);
+
+ if (gd->arch.mtrr_req_count == MAX_MTRR_REQUESTS)
+ return -ENOSPC;
+ req = &gd->arch.mtrr_req[gd->arch.mtrr_req_count++];
+ req->type = type;
+ req->start = base;
+ req->size = mtrr_size;
+ log_debug("%d: type=%d, %08llx %08llx ",
+ gd->arch.mtrr_req_count - 1, req->type, req->start,
+ req->size);
+ mask = mtrr_to_mask(req->size);
+ mask |= MTRR_PHYS_MASK_VALID;
+ log_debug(" %016llx %016llx\n", req->start | req->type, mask);
+
+ size -= mtrr_size;
+ base += mtrr_size;
+ }
return 0;
}
@@ -360,9 +431,7 @@ int mtrr_list(int reg_count, int cpu_select)
base = info.mtrr[i].base;
mask = info.mtrr[i].mask;
- size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
- size |= (1 << 12) - 1;
- size += 1;
+ size = mtrr_to_size(mask);
valid = mask & MTRR_PHYS_MASK_VALID;
type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
diff --git a/arch/x86/cpu/qemu/dram.c b/arch/x86/cpu/qemu/dram.c
index 62a301c0fd3..ba3638e6acc 100644
--- a/arch/x86/cpu/qemu/dram.c
+++ b/arch/x86/cpu/qemu/dram.c
@@ -4,7 +4,9 @@
*/
#include <init.h>
+#include <spl.h>
#include <asm/global_data.h>
+#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/arch/qemu.h>
#include <linux/sizes.h>
@@ -44,6 +46,22 @@ int dram_init(void)
gd->ram_size += qemu_get_high_memory_size();
post_code(POST_DRAM);
+ if (xpl_phase() == PHASE_BOARD_F) {
+ u64 total = gd->ram_size;
+ int ret;
+
+ if (total > SZ_2G + SZ_1G)
+ total += SZ_1G;
+ ret = mtrr_add_request(MTRR_TYPE_WRBACK, 0, total);
+ if (ret != -ENOSYS) {
+ if (ret)
+ return log_msg_ret("mta", ret);
+ ret = mtrr_commit(false);
+ if (ret)
+ return log_msg_ret("mtc", ret);
+ }
+ }
+
return 0;
}
diff --git a/arch/x86/cpu/qemu/e820.c b/arch/x86/cpu/qemu/e820.c
index 17a04f86479..078d1d86b02 100644
--- a/arch/x86/cpu/qemu/e820.c
+++ b/arch/x86/cpu/qemu/e820.c
@@ -6,6 +6,7 @@
* (C) Copyright 2019 Bin Meng <bmeng.cn@gmail.com>
*/
+#include <bloblist.h>
#include <env_internal.h>
#include <malloc.h>
#include <asm/e820.h>
@@ -19,51 +20,34 @@ unsigned int install_e820_map(unsigned int max_entries,
struct e820_entry *entries)
{
u64 high_mem_size;
- int n = 0;
+ struct e820_ctx ctx;
- entries[n].addr = 0;
- entries[n].size = ISA_START_ADDRESS;
- entries[n].type = E820_RAM;
- n++;
+ e820_init(&ctx, entries, max_entries);
- entries[n].addr = ISA_START_ADDRESS;
- entries[n].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
- entries[n].type = E820_RESERVED;
- n++;
+ e820_next(&ctx, E820_RAM, ISA_START_ADDRESS);
+ e820_next(&ctx, E820_RESERVED, ISA_END_ADDRESS);
/*
- * since we use memalign(malloc) to allocate high memory for
- * storing ACPI tables, we need to reserve them in e820 tables,
- * otherwise kernel will reclaim them and data will be corrupted
+ * if we use bloblist to allocate high memory for storing ACPI tables,
+ * we need to reserve that region in e820 tables, otherwise the kernel
+ * will reclaim them and data will be corrupted. The ACPI tables may not
+ * have been written yet, so use the whole bloblist size
*/
- entries[n].addr = ISA_END_ADDRESS;
- entries[n].size = gd->relocaddr - TOTAL_MALLOC_LEN - ISA_END_ADDRESS;
- entries[n].type = E820_RAM;
- n++;
-
- /* for simplicity, reserve entire malloc space */
- entries[n].addr = gd->relocaddr - TOTAL_MALLOC_LEN;
- entries[n].size = TOTAL_MALLOC_LEN;
- entries[n].type = E820_RESERVED;
- n++;
-
- entries[n].addr = gd->relocaddr;
- entries[n].size = qemu_get_low_memory_size() - gd->relocaddr;
- entries[n].type = E820_RESERVED;
- n++;
-
- entries[n].addr = CONFIG_PCIE_ECAM_BASE;
- entries[n].size = CONFIG_PCIE_ECAM_SIZE;
- entries[n].type = E820_RESERVED;
- n++;
+ if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
+ e820_to_addr(&ctx, E820_RAM, (ulong)gd->bloblist);
+ e820_next(&ctx, E820_ACPI, bloblist_get_total_size());
+ } else {
+ /* If using memalign() reserve that whole region instead */
+ e820_to_addr(&ctx, E820_RAM, gd->relocaddr - TOTAL_MALLOC_LEN);
+ e820_next(&ctx, E820_ACPI, TOTAL_MALLOC_LEN);
+ }
+ e820_to_addr(&ctx, E820_RAM, qemu_get_low_memory_size());
+ e820_add(&ctx, E820_RESERVED, CONFIG_PCIE_ECAM_BASE,
+ CONFIG_PCIE_ECAM_SIZE);
high_mem_size = qemu_get_high_memory_size();
- if (high_mem_size) {
- entries[n].addr = SZ_4G;
- entries[n].size = high_mem_size;
- entries[n].type = E820_RAM;
- n++;
- }
+ if (high_mem_size)
+ e820_add(&ctx, E820_RAM, SZ_4G, high_mem_size);
- return n;
+ return e820_finish(&ctx);
}
diff --git a/arch/x86/cpu/qemu/qemu.c b/arch/x86/cpu/qemu/qemu.c
index 563f63e2bc8..e846ccd44aa 100644
--- a/arch/x86/cpu/qemu/qemu.c
+++ b/arch/x86/cpu/qemu/qemu.c
@@ -15,14 +15,21 @@
#include <asm/arch/qemu.h>
#include <asm/u-boot-x86.h>
-static bool i440fx;
-
#if CONFIG_IS_ENABLED(QFW_PIO)
U_BOOT_DRVINFO(x86_qfw_pio) = {
.name = "qfw_pio",
};
#endif
+static bool is_i440fx(void)
+{
+ u16 device;
+
+ pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device);
+
+ return device == PCI_DEVICE_ID_INTEL_82441;
+}
+
static void enable_pm_piix(void)
{
u8 en;
@@ -50,16 +57,17 @@ static void enable_pm_ich9(void)
void qemu_chipset_init(void)
{
- u16 device, xbcs;
+ bool i440fx;
+ u16 xbcs;
int pam, i;
+ i440fx = is_i440fx();
+
/*
* i440FX and Q35 chipset have different PAM register offset, but with
* the same bitfield layout. Here we determine the offset based on its
* PCI device ID.
*/
- pci_read_config16(PCI_BDF(0, 0, 0), PCI_DEVICE_ID, &device);
- i440fx = (device == PCI_DEVICE_ID_INTEL_82441);
pam = i440fx ? I440FX_PAM : Q35_PAM;
/*
@@ -123,7 +131,7 @@ int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq)
{
u8 irq;
- if (i440fx) {
+ if (is_i440fx()) {
/*
* Not like most x86 platforms, the PIRQ[A-D] on PIIX3 are not
* connected to I/O APIC INTPIN#16-19. Instead they are routed
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
index 0ef27cc5a00..385a691265e 100644
--- a/arch/x86/cpu/start.S
+++ b/arch/x86/cpu/start.S
@@ -254,7 +254,7 @@ multiboot_header:
* GDT is setup in a safe location in RAM
*/
gdt_ptr2:
- .word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
+ .word gdt2_end - gdt_ptr2 - 1
.long gdt_rom2 /* base */
/* Some CPUs are picky about GDT alignment... */
@@ -313,4 +313,6 @@ gdt_rom2:
.byte 0x93 /* access */
.byte 0xcf /* flags + limit_high */
.byte 0x00 /* base_high */
+gdt2_end:
+
#endif
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S
index 865a49731e5..8d9acb193e0 100644
--- a/arch/x86/cpu/start16.S
+++ b/arch/x86/cpu/start16.S
@@ -61,7 +61,7 @@ idt_ptr:
* GDT is setup in a safe location in RAM
*/
gdt_ptr:
- .word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
+ .word gdt_end - gdt_rom - 1
.long BOOT_SEG + gdt_rom /* base */
/* Some CPUs are picky about GDT alignment... */
@@ -120,3 +120,4 @@ gdt_rom:
.byte 0x93 /* access */
.byte 0xcf /* flags + limit_high */
.byte 0x00 /* base_high */
+gdt_end:
diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c
index 71bc07f872a..25ae92c702f 100644
--- a/arch/x86/cpu/x86_64/cpu.c
+++ b/arch/x86/cpu/x86_64/cpu.c
@@ -59,11 +59,6 @@ int x86_cpu_reinit_f(void)
return 0;
}
-int cpu_phys_address_size(void)
-{
- return CONFIG_CPU_ADDR_BITS;
-}
-
int x86_cpu_init_f(void)
{
return 0;
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index ac4865300f1..657d920b14f 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -122,6 +122,14 @@ struct efi_info {
__u32 efi_memmap_hi;
};
+/* Gleaned from OFW's set-parameters in cpu/x86/pc/linux.fth */
+struct olpc_ofw_header {
+ __u32 ofw_magic; /* OFW signature */
+ __u32 ofw_version;
+ __u32 cif_handler; /* callback into OFW */
+ __u32 irq_desc_table;
+} __attribute__((packed));
+
/* The so-called "zeropage" */
struct boot_params {
struct screen_info screen_info; /* 0x000 */
@@ -134,7 +142,12 @@ struct boot_params {
__u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
__u8 hd1_info[16]; /* obsolete! */ /* 0x090 */
struct sys_desc_table sys_desc_table; /* 0x0a0 */
- __u8 _pad4[144]; /* 0x0b0 */
+ struct olpc_ofw_header olpc_ofw_header; /* 0x0b0 */
+ __u32 ext_ramdisk_image; /* 0x0c0 */
+ __u32 ext_ramdisk_size; /* 0x0c4 */
+ __u32 ext_cmd_line_ptr; /* 0x0c8 */
+ __u8 _pad4[112]; /* 0x0cc */
+ __u32 cc_blob_address; /* 0x13c */
struct edid_info edid_info; /* 0x140 */
struct efi_info efi_info; /* 0x1c0 */
__u32 alt_mem_k; /* 0x1e0 */
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index fd389d4024c..5d24c17f8a3 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -58,6 +58,10 @@ enum {
X86_SYSCON_PUNIT, /* Power unit */
};
+#define CPUID_FEATURE_PAE BIT(6)
+#define CPUID_FEATURE_PSE36 BIT(17)
+#define CPUID_FEAURE_HTT BIT(28)
+
struct cpuid_result {
uint32_t eax;
uint32_t ebx;
@@ -105,68 +109,47 @@ static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
return result;
}
-/*
- * CPUID functions returning a single datum
- */
-static inline unsigned int cpuid_eax(unsigned int op)
+static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
{
- unsigned int eax;
-
- __asm__("mov %%ebx, %%edi;"
- "cpuid;"
- "mov %%edi, %%ebx;"
- : "=a" (eax)
- : "0" (op)
- : "ecx", "edx", "edi");
- return eax;
+ /* ecx is often an input as well as an output. */
+ asm volatile("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (*eax), "2" (*ecx)
+ : "memory");
}
-static inline unsigned int cpuid_ebx(unsigned int op)
-{
- unsigned int eax, ebx;
-
- __asm__("mov %%ebx, %%edi;"
- "cpuid;"
- "mov %%ebx, %%esi;"
- "mov %%edi, %%ebx;"
- : "=a" (eax), "=S" (ebx)
- : "0" (op)
- : "ecx", "edx", "edi");
- return ebx;
+#define native_cpuid_reg(reg) \
+static inline unsigned int cpuid_##reg(unsigned int op) \
+{ \
+ unsigned int eax = op, ebx, ecx = 0, edx; \
+ \
+ native_cpuid(&eax, &ebx, &ecx, &edx); \
+ \
+ return reg; \
}
-static inline unsigned int cpuid_ecx(unsigned int op)
-{
- unsigned int eax, ecx;
-
- __asm__("mov %%ebx, %%edi;"
- "cpuid;"
- "mov %%edi, %%ebx;"
- : "=a" (eax), "=c" (ecx)
- : "0" (op)
- : "edx", "edi");
- return ecx;
-}
+/*
+ * Native CPUID functions returning a single datum.
+ */
+native_cpuid_reg(eax)
+native_cpuid_reg(ebx)
+native_cpuid_reg(ecx)
+native_cpuid_reg(edx)
-static inline unsigned int cpuid_edx(unsigned int op)
+#if CONFIG_IS_ENABLED(X86_64)
+static inline int flag_is_changeable_p(u32 flag)
{
- unsigned int eax, edx;
-
- __asm__("mov %%ebx, %%edi;"
- "cpuid;"
- "mov %%edi, %%ebx;"
- : "=a" (eax), "=d" (edx)
- : "0" (op)
- : "ecx", "edi");
- return edx;
+ return 1;
}
-
-#if !CONFIG_IS_ENABLED(X86_64)
-
+#else
/* Standard macro to see if a specific flag is changeable */
-static inline int flag_is_changeable_p(uint32_t flag)
+static inline int flag_is_changeable_p(u32 flag)
{
- uint32_t f1, f2;
+ u32 f1, f2;
asm(
"pushfl\n\t"
@@ -181,9 +164,9 @@ static inline int flag_is_changeable_p(uint32_t flag)
"popfl\n\t"
: "=&r" (f1), "=&r" (f2)
: "ir" (flag));
- return ((f1^f2) & flag) != 0;
+ return ((f1 ^ f2) & flag) != 0;
}
-#endif
+#endif /* X86_64 */
/**
* cpu_enable_paging_pae() - Enable PAE-paging
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 1ab709abfc8..a535818b2d5 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -3,6 +3,8 @@
#define E820MAX 128 /* number of entries in E820MAP */
+#ifdef __ASSEMBLY__
+
#define E820_RAM 1
#define E820_RESERVED 2
#define E820_ACPI 3
@@ -10,9 +12,21 @@
#define E820_UNUSABLE 5
#define E820_COUNT 6 /* Number of types */
-#ifndef __ASSEMBLY__
+#else
+
#include <linux/types.h>
+/* Available e820 memory-region types */
+enum e820_type {
+ E820_RAM = 1,
+ E820_RESERVED,
+ E820_ACPI,
+ E820_NVS,
+ E820_UNUSABLE,
+
+ E820_COUNT,
+};
+
struct e820_entry {
__u64 addr; /* start of memory segment */
__u64 size; /* size of memory segment */
@@ -22,11 +36,82 @@ struct e820_entry {
#define ISA_START_ADDRESS 0xa0000
#define ISA_END_ADDRESS 0x100000
+/**
+ * Context to use for e820_add()
+ *
+ * @entries: Table being filled in
+ * @addr: Current address we are up to
+ * @count: Number of entries added to @entries so far
+ * @max_entries: Maximum number of entries allowed
+ */
+struct e820_ctx {
+ struct e820_entry *entries;
+ u64 addr;
+ int count;
+ int max_entries;
+};
+
+/**
+ * e820_init() - Start setting up an e820 table
+ *
+ * @ctx: Context to set up
+ * @entries: Place to put entries
+ * @max_entries: Maximum size of @entries
+ */
+void e820_init(struct e820_ctx *ctx, struct e820_entry *entries,
+ int max_entries);
+
+/**
+ * e820_add() - Add an entry to the table
+ *
+ * @ctx: Context
+ * @type: Type of entry
+ * @addr: Start address of entry
+ * @size Size of entry
+ */
+void e820_add(struct e820_ctx *ctx, enum e820_type type, u64 addr, u64 size);
+
+/**
+ * e820_to_addr() - Add an entry that covers the space up to a given address
+ *
+ * @ctx: Context
+ * @type: Type of entry
+ * @end_addr: Address where the entry should finish
+ */
+void e820_to_addr(struct e820_ctx *ctx, enum e820_type type, u64 end_addr);
+
+/**
+ * e820_next() - Add an entry that carries on from the last one
+ *
+ * @ctx: Context
+ * @type: Type of entry
+ * @size Size of entry
+ */
+void e820_next(struct e820_ctx *ctx, enum e820_type type, u64 size);
+
+/**
+ * e820_finish() - Finish the table
+ *
+ * Checks the table is not too large, panics if so
+ *
+ * @ctx: Context
+ * Returns: Number of entries
+ */
+int e820_finish(struct e820_ctx *ctx);
+
/* Implementation-defined function to install an e820 map */
unsigned int install_e820_map(unsigned int max_entries,
struct e820_entry *);
/**
+ * e820_dump() - Dump the e820 table
+ *
+ * @entries: Pointer to start of table
+ * @count: Number of entries in the table
+ */
+void e820_dump(struct e820_entry *entries, uint count);
+
+/**
* cb_install_e820_map() - Install e820 map provided by coreboot sysinfo
*
* This should be used when booting from coreboot, since in that case the
@@ -39,6 +124,14 @@ unsigned int install_e820_map(unsigned int max_entries,
unsigned int cb_install_e820_map(unsigned int max_entries,
struct e820_entry *entries);
+/**
+ * e820_dump() - Dump an e820 table
+ *
+ * @entries: Pointer to first entry
+ * @count: Number of entries in the table
+ */
+void e820_dump(struct e820_entry *entries, uint count);
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_E820_H */
diff --git a/arch/x86/include/asm/interrupt.h b/arch/x86/include/asm/interrupt.h
index e23fb2c8e72..c689fc23d08 100644
--- a/arch/x86/include/asm/interrupt.h
+++ b/arch/x86/include/asm/interrupt.h
@@ -10,6 +10,7 @@
#ifndef __ASM_INTERRUPT_H_
#define __ASM_INTERRUPT_H_ 1
+#include <stdbool.h>
#include <asm/types.h>
#define SYS_NUM_IRQS 16
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index af5f9a11980..39dc7b33aa0 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -59,15 +59,14 @@ static inline unsigned long long native_read_tscp(unsigned int *aux)
* edx:eax, while for x86_64 it doesn't mean rdx:rax or edx:eax. Instead,
* it means rax *or* rdx.
*/
-#ifdef CONFIG_X86_64
-#define DECLARE_ARGS(val, low, high) unsigned low, high
-#define EAX_EDX_VAL(val, low, high) ((low) | ((u64)(high) << 32))
-#define EAX_EDX_ARGS(val, low, high) "a" (low), "d" (high)
+#if CONFIG_IS_ENABLED(X86_64)
+/* Using 64-bit values saves one instruction clearing the high half of low */
+#define DECLARE_ARGS(val, low, high) unsigned long low, high
+#define EAX_EDX_VAL(val, low, high) ((low) | (high) << 32)
#define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high)
#else
#define DECLARE_ARGS(val, low, high) unsigned long long val
#define EAX_EDX_VAL(val, low, high) (val)
-#define EAX_EDX_ARGS(val, low, high) "A" (val)
#define EAX_EDX_RET(val, low, high) "=A" (val)
#endif
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 2e995f54061..67e897daa25 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -91,6 +91,22 @@ struct mtrr_info {
};
/**
+ * mtrr_to_size() - Convert a mask to a size value
+ *
+ * @mask: Value of the mask register
+ * Return: associated size
+ */
+u64 mtrr_to_size(u64 mask);
+
+/**
+ * mtrr_to_mask() - Convert a size to a mask value
+ *
+ * @size: Value of the size register
+ * Return: associated mask, without MTRR_PHYS_MASK_VALID
+ */
+u64 mtrr_to_mask(u64 size);
+
+/**
* mtrr_open() - Prepare to adjust MTRRs
*
* Use mtrr_open() passing in a structure - this function will init it. Then
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index d7b68367861..ad8240be387 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -18,7 +18,10 @@
#define X86_GDT_ENTRY_16BIT_DS 6
#define X86_GDT_ENTRY_16BIT_FLAT_CS 7
#define X86_GDT_ENTRY_16BIT_FLAT_DS 8
-#define X86_GDT_NUM_ENTRIES 9
+#define X86_GDT_ENTRY_64BIT_CS 9
+#define X86_GDT_ENTRY_64BIT_TS1 10
+#define X86_GDT_ENTRY_64BIT_TS2 11
+#define X86_GDT_NUM_ENTRIES 12
#define X86_GDT_SIZE (X86_GDT_NUM_ENTRIES * X86_GDT_ENTRY_SIZE)
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 43e6a1de77d..a908356e8a6 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -26,7 +26,9 @@ obj-y += e820.o
obj-y += init_helpers.o
obj-y += interrupts.o
obj-y += lpc-uclass.o
+ifndef CONFIG_XPL_BUILD
obj-y += mpspec.o
+endif
obj-$(CONFIG_$(PHASE_)ACPIGEN) += acpi_nhlt.o
obj-y += northbridge-uclass.o
obj-$(CONFIG_I8259_PIC) += i8259.o
diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c
index 03f7360032c..de4578666fb 100644
--- a/arch/x86/lib/bios.c
+++ b/arch/x86/lib/bios.c
@@ -5,6 +5,9 @@
* Copyright (C) 2007 Advanced Micro Devices, Inc.
* Copyright (C) 2009-2010 coresystems GmbH
*/
+
+#define LOG_CATEGRORY LOGC_ARCH
+
#include <compiler.h>
#include <bios_emul.h>
#include <irq_func.h>
@@ -228,7 +231,11 @@ static void vbe_set_graphics(int vesa_mode, struct vesa_state *mode_info)
{
unsigned char *framebuffer;
- mode_info->video_mode = (1 << 14) | vesa_mode;
+ /*
+ * bit 14 is linear-framebuffer mode
+ * bit 15 means don't clear the display
+ */
+ mode_info->video_mode = (1 << 14) | (1 << 15) | vesa_mode;
vbe_get_mode_info(mode_info);
framebuffer = (unsigned char *)(ulong)mode_info->vesa.phys_base_ptr;
@@ -298,16 +305,14 @@ asmlinkage int interrupt_handler(u32 intnumber, u32 gsfs, u32 dses,
cs = cs_ip >> 16;
flags = stackflags;
-#ifdef CONFIG_REALMODE_DEBUG
- debug("oprom: INT# 0x%x\n", intnumber);
- debug("oprom: eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
- eax, ebx, ecx, edx);
- debug("oprom: ebp: %08x esp: %08x edi: %08x esi: %08x\n",
- ebp, esp, edi, esi);
- debug("oprom: ip: %04x cs: %04x flags: %08x\n",
- ip, cs, flags);
- debug("oprom: stackflags = %04x\n", stackflags);
-#endif
+ log_debug("oprom: INT# 0x%x\n", intnumber);
+ log_debug("oprom: eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
+ eax, ebx, ecx, edx);
+ log_debug("oprom: ebp: %08x esp: %08x edi: %08x esi: %08x\n",
+ ebp, esp, edi, esi);
+ log_debug("oprom: ip: %04x cs: %04x flags: %08x\n",
+ ip, cs, flags);
+ log_debug("oprom: stackflags = %04x\n", stackflags);
/*
* Fetch arguments from the stack and put them to a place
diff --git a/arch/x86/lib/bios_interrupts.c b/arch/x86/lib/bios_interrupts.c
index b2cf1527b1c..e0c2284a901 100644
--- a/arch/x86/lib/bios_interrupts.c
+++ b/arch/x86/lib/bios_interrupts.c
@@ -7,6 +7,8 @@
* Copyright (C) 2007-2009 coresystems GmbH
*/
+#define LOG_CATEGRORY LOGC_ARCH
+
#include <log.h>
#include <asm/pci.h>
#include "bios_emul.h"
@@ -198,10 +200,8 @@ int int1a_handler(void)
dm_pci_write_config32(dev, reg, dword);
break;
}
-#ifdef CONFIG_REALMODE_DEBUG
- debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n", func,
- bus, devfn, reg, M.x86.R_ECX);
-#endif
+ log_debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%x\n", func,
+ bus, devfn, reg, M.x86.R_ECX);
M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
M.x86.R_EAX |= PCIBIOS_SUCCESSFUL;
retval = 1;
diff --git a/arch/x86/lib/e820.c b/arch/x86/lib/e820.c
index d478b7486e3..bcc5f6f3044 100644
--- a/arch/x86/lib/e820.c
+++ b/arch/x86/lib/e820.c
@@ -3,13 +3,39 @@
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*/
+#define LOG_CATEGORY LOGC_ARCH
+
#include <efi_loader.h>
#include <lmb.h>
+#include <log.h>
#include <asm/e820.h>
#include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR;
+static const char *const e820_type_name[E820_COUNT] = {
+ [E820_RAM] = "RAM",
+ [E820_RESERVED] = "Reserved",
+ [E820_ACPI] = "ACPI",
+ [E820_NVS] = "ACPI NVS",
+ [E820_UNUSABLE] = "Unusable",
+};
+
+void e820_dump(struct e820_entry *entries, uint count)
+{
+ int i;
+
+ printf("%12s %10s %s\n", "Addr", "Size", "Type");
+ for (i = 0; i < count; i++) {
+ struct e820_entry *entry = &entries[i];
+
+ printf("%12llx %10llx %s\n", entry->addr, entry->size,
+ entry->type < E820_COUNT ?
+ e820_type_name[entry->type] :
+ simple_itoa(entry->type));
+ }
+}
+
/*
* Install a default e820 table with 4 entries as follows:
*
@@ -37,6 +63,50 @@ __weak unsigned int install_e820_map(unsigned int max_entries,
return 4;
}
+void e820_init(struct e820_ctx *ctx, struct e820_entry *entries,
+ int max_entries)
+{
+ memset(ctx, '\0', sizeof(*ctx));
+ ctx->entries = entries;
+ ctx->max_entries = max_entries;
+}
+
+void e820_add(struct e820_ctx *ctx, enum e820_type type, u64 addr, u64 size)
+{
+ struct e820_entry *entry = &ctx->entries[ctx->count++];
+
+ if (ctx->count <= ctx->max_entries) {
+ entry->addr = addr;
+ entry->size = size;
+ entry->type = type;
+ }
+ ctx->addr = addr + size;
+}
+
+void e820_next(struct e820_ctx *ctx, enum e820_type type, u64 size)
+{
+ e820_add(ctx, type, ctx->addr, size);
+}
+
+void e820_to_addr(struct e820_ctx *ctx, enum e820_type type, u64 addr)
+{
+ e820_next(ctx, type, addr - ctx->addr);
+}
+
+int e820_finish(struct e820_ctx *ctx)
+{
+ if (ctx->count > ctx->max_entries) {
+ printf("e820 has %d entries but room for only %d\n", ctx->count,
+ ctx->max_entries);
+ panic("e820 table too large");
+ }
+ log_debug("e820 map installed, n=%d\n", ctx->count);
+ if (_DEBUG)
+ e820_dump(ctx->entries, ctx->count);
+
+ return ctx->count;
+}
+
#if CONFIG_IS_ENABLED(EFI_LOADER)
void efi_add_known_memory(void)
{
diff --git a/arch/x86/lib/i8259.c b/arch/x86/lib/i8259.c
index 465ff70146f..088f78f4661 100644
--- a/arch/x86/lib/i8259.c
+++ b/arch/x86/lib/i8259.c
@@ -13,6 +13,8 @@
* Programmable Interrupt Controllers.
*/
+#define LOG_CATEGORY UCLASS_IRQ
+
#include <log.h>
#include <asm/io.h>
#include <asm/i8259.h>
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 7a033505101..0a6a761987e 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -84,8 +84,6 @@ static int x86_spl_init(void)
log_debug("x86 spl starting\n");
if (IS_ENABLED(TPL))
ret = x86_cpu_reinit_f();
- else
- ret = x86_cpu_init_f();
ret = spl_init();
if (ret) {
log_debug("spl_init() failed (err=%d)\n", ret);
@@ -283,7 +281,7 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
{
int ret;
- printf("Jumping to 64-bit U-Boot: Note many features are missing\n");
+ log_debug("Jumping to 64-bit U-Boot\n");
ret = cpu_jump_to_64bit_uboot(spl_image->entry_point);
debug("ret=%d\n", ret);
hang();
diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c
index 44fe80c5224..ec52992209f 100644
--- a/arch/x86/lib/tables.c
+++ b/arch/x86/lib/tables.c
@@ -45,6 +45,13 @@ struct table_info {
int align;
};
+/* QEMU's tables include quite a bit of empty space */
+#ifdef CONFIG_QEMU
+#define ACPI_SIZE (192 << 10)
+#else
+#define ACPI_SIZE SZ_64K
+#endif
+
static struct table_info table_list[] = {
#ifdef CONFIG_GENERATE_PIRQ_TABLE
{ "pirq", write_pirq_routing_table },
@@ -60,7 +67,7 @@ static struct table_info table_list[] = {
* that the calculation of gd->table_end works properly
*/
#ifdef CONFIG_GENERATE_ACPI_TABLE
- { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, SZ_64K, SZ_4K},
+ { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, ACPI_SIZE, SZ_4K},
#endif
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
/*
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
index ba7a008fec7..65bccdae9b2 100644
--- a/arch/x86/lib/zimage.c
+++ b/arch/x86/lib/zimage.c
@@ -222,7 +222,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
else
*load_addressp = ZIMAGE_LOAD_ADDR;
- printf("Building boot_params at 0x%8.8lx\n", (ulong)setup_base);
+ printf("Building boot_params at %lx\n", (ulong)setup_base);
memset(setup_base, 0, sizeof(*setup_base));
setup_base->hdr = params->hdr;
@@ -298,10 +298,13 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
hdr->type_of_loader = 0x80; /* U-Boot version 0 */
if (initrd_addr) {
printf("Initial RAM disk at linear address "
- "0x%08lx, size %ld bytes\n",
- initrd_addr, initrd_size);
+ "%lx, size %lx (%ld bytes)\n",
+ initrd_addr, initrd_size, initrd_size);
hdr->ramdisk_image = initrd_addr;
+ setup_base->ext_ramdisk_image = 0;
+ setup_base->ext_ramdisk_size = 0;
+ setup_base->ext_cmd_line_ptr = 0;
hdr->ramdisk_size = initrd_size;
}
}
@@ -372,8 +375,7 @@ int zboot_load(struct bootm_info *bmi)
struct boot_params *from = (struct boot_params *)bmi->base_ptr;
base_ptr = (struct boot_params *)DEFAULT_SETUP_BASE;
- log_debug("Building boot_params at 0x%8.8lx\n",
- (ulong)base_ptr);
+ log_debug("Building boot_params at %lx\n", (ulong)base_ptr);
memset(base_ptr, '\0', sizeof(*base_ptr));
base_ptr->hdr = from->hdr;
} else {
@@ -474,14 +476,6 @@ static void print_num64(const char *name, u64 value)
printf("%-20s: %llx\n", name, value);
}
-static const char *const e820_type_name[E820_COUNT] = {
- [E820_RAM] = "RAM",
- [E820_RESERVED] = "Reserved",
- [E820_ACPI] = "ACPI",
- [E820_NVS] = "ACPI NVS",
- [E820_UNUSABLE] = "Unusable",
-};
-
static const char *const bootloader_id[] = {
"LILO",
"Loadlin",
@@ -569,24 +563,14 @@ void zimage_dump(struct bootm_info *bmi, bool show_cmdline)
{
struct boot_params *base_ptr;
struct setup_header *hdr;
- int i;
base_ptr = bmi->base_ptr;
printf("Setup located at %p:\n\n", base_ptr);
print_num64("ACPI RSDP addr", base_ptr->acpi_rsdp_addr);
printf("E820: %d entries\n", base_ptr->e820_entries);
- if (base_ptr->e820_entries) {
- printf("%12s %10s %s\n", "Addr", "Size", "Type");
- for (i = 0; i < base_ptr->e820_entries; i++) {
- struct e820_entry *entry = &base_ptr->e820_map[i];
-
- printf("%12llx %10llx %s\n", entry->addr, entry->size,
- entry->type < E820_COUNT ?
- e820_type_name[entry->type] :
- simple_itoa(entry->type));
- }
- }
+ if (base_ptr->e820_entries)
+ e820_dump(base_ptr->e820_map, base_ptr->e820_entries);
hdr = &base_ptr->hdr;
print_num("Setup sectors", hdr->setup_sects);
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index c39147940b6..3791ebfcb42 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -168,8 +168,10 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
*/
/* if there are bootable partitions, scan only those */
- } else if (iter->first_bootable >= 0 &&
+ } else if ((iter->flags & BOOTFLOWIF_ONLY_BOOTABLE) &&
+ iter->first_bootable >= 0 &&
(iter->first_bootable ? !info.bootable : iter->part != 1)) {
+ log_debug("Skipping non-bootable partition %d\n", iter->part);
return log_msg_ret("boot", -EINVAL);
} else {
ret = fs_set_blk_dev_with_part(desc, bflow->part);
@@ -577,6 +579,9 @@ int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
struct udevice *dev;
log_debug("next\n");
+ if (iter->cur_label >= 0 && !iter->labels[iter->cur_label])
+ return log_msg_ret("fil", -ENODEV);
+
for (dev = NULL; !dev && iter->labels[++iter->cur_label];) {
const char *label = iter->labels[iter->cur_label];
int ret;
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 58a1afa7a75..4054a966af8 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -942,8 +942,9 @@ int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg)
*buf = '\0';
if (!strcmp("earlycon", arg) && info.type == SERIAL_CHIP_16550_COMPATIBLE) {
snprintf(buf, sizeof(buf),
- "uart8250,mmio32,%#lx,%dn8", info.addr,
- info.baudrate);
+ "uart8250,%s,%#lx,%dn8",
+ info.addr_space == SERIAL_ADDRESS_SPACE_IO ? "io" :
+ "mmio", info.addr, info.baudrate);
} else if (!strcmp("earlycon", arg) && info.type == SERIAL_CHIP_PL01X) {
snprintf(buf, sizeof(buf),
"pl011,mmio32,%#lx,%dn8", info.addr,
@@ -954,7 +955,7 @@ int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg)
}
if (!*buf) {
- printf("Unknown param '%s\n", arg);
+ printf("Unknown param '%s'\n", arg);
return -ENOENT;
}
diff --git a/cmd/acpi.c b/cmd/acpi.c
index 094d9d4e858..bb243202009 100644
--- a/cmd/acpi.c
+++ b/cmd/acpi.c
@@ -7,6 +7,7 @@
#include <display_options.h>
#include <log.h>
#include <mapmem.h>
+#include <tables_csum.h>
#include <acpi/acpi_table.h>
#include <asm/acpi_table.h>
#include <asm/global_data.h>
@@ -15,6 +16,17 @@
DECLARE_GLOBAL_DATA_PTR;
+static const char *show_checksum(void *ptr, uint size, bool chksums)
+{
+ uint checksum;
+
+ if (!chksums)
+ return "";
+ checksum = table_compute_checksum(ptr, size);
+
+ return checksum ? " bad" : " OK";
+}
+
/**
* dump_hdr() - Dump an ACPI header
*
@@ -23,16 +35,17 @@ DECLARE_GLOBAL_DATA_PTR;
*
* @hdr: ACPI header to dump
*/
-static void dump_hdr(struct acpi_table_header *hdr)
+static void dump_hdr(struct acpi_table_header *hdr, bool chksums)
{
bool has_hdr = memcmp(hdr->signature, "FACS", ACPI_NAME_LEN);
printf("%.*s %16lx %5x", ACPI_NAME_LEN, hdr->signature,
(ulong)map_to_sysmem(hdr), hdr->length);
if (has_hdr) {
- printf(" v%02d %.6s %.8s %x %.4s %x\n", hdr->revision,
+ printf(" v%02d %.6s %.8s %x %.4s %x%s\n", hdr->revision,
hdr->oem_id, hdr->oem_table_id, hdr->oem_revision,
- hdr->creator_id, hdr->creator_revision);
+ hdr->creator_id, hdr->creator_revision,
+ show_checksum(hdr, hdr->length, chksums));
} else {
printf("\n");
}
@@ -52,22 +65,22 @@ static int dump_table_name(const char *sig)
return 0;
}
-static void list_fadt(struct acpi_fadt *fadt)
+static void list_fadt(struct acpi_fadt *fadt, bool chksums)
{
if (fadt->header.revision >= 3 && fadt->x_dsdt)
- dump_hdr(nomap_sysmem(fadt->x_dsdt, 0));
+ dump_hdr(nomap_sysmem(fadt->x_dsdt, 0), chksums);
else if (fadt->dsdt)
- dump_hdr(nomap_sysmem(fadt->dsdt, 0));
- if (!IS_ENABLED(CONFIG_X86) &&
+ dump_hdr(nomap_sysmem(fadt->dsdt, 0), chksums);
+ if (!IS_ENABLED(CONFIG_X86) && !IS_ENABLED(CONFIG_SANDBOX) &&
!(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI))
log_err("FADT not ACPI-hardware-reduced-compliant\n");
if (fadt->header.revision >= 3 && fadt->x_firmware_ctrl)
- dump_hdr(nomap_sysmem(fadt->x_firmware_ctrl, 0));
+ dump_hdr(nomap_sysmem(fadt->x_firmware_ctrl, 0), chksums);
else if (fadt->firmware_ctrl)
- dump_hdr(nomap_sysmem(fadt->firmware_ctrl, 0));
+ dump_hdr(nomap_sysmem(fadt->firmware_ctrl, 0), chksums);
}
-static void list_rsdt(struct acpi_rsdp *rsdp)
+static void list_rsdt(struct acpi_rsdp *rsdp, bool chksums)
{
int len, i, count;
struct acpi_rsdt *rsdt;
@@ -75,11 +88,11 @@ static void list_rsdt(struct acpi_rsdp *rsdp)
if (rsdp->rsdt_address) {
rsdt = nomap_sysmem(rsdp->rsdt_address, 0);
- dump_hdr(&rsdt->header);
+ dump_hdr(&rsdt->header, chksums);
}
if (rsdp->xsdt_address) {
xsdt = nomap_sysmem(rsdp->xsdt_address, 0);
- dump_hdr(&xsdt->header);
+ dump_hdr(&xsdt->header, chksums);
len = xsdt->header.length - sizeof(xsdt->header);
count = len / sizeof(u64);
} else if (rsdp->rsdt_address) {
@@ -100,24 +113,28 @@ static void list_rsdt(struct acpi_rsdp *rsdp)
if (!entry)
break;
hdr = nomap_sysmem(entry, 0);
- dump_hdr(hdr);
+ dump_hdr(hdr, chksums);
if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN))
- list_fadt((struct acpi_fadt *)hdr);
+ list_fadt((struct acpi_fadt *)hdr, chksums);
}
}
-static void list_rsdp(struct acpi_rsdp *rsdp)
+static void list_rsdp(struct acpi_rsdp *rsdp, bool chksums)
{
- printf("RSDP %16lx %5x v%02d %.6s\n", (ulong)map_to_sysmem(rsdp),
- rsdp->length, rsdp->revision, rsdp->oem_id);
- list_rsdt(rsdp);
+ printf("RSDP %16lx %5x v%02d %.6s%s%s\n",
+ (ulong)map_to_sysmem(rsdp), rsdp->length, rsdp->revision,
+ rsdp->oem_id, show_checksum(rsdp, 0x14, chksums),
+ show_checksum(rsdp, rsdp->length, chksums));
+ list_rsdt(rsdp, chksums);
}
static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct acpi_rsdp *rsdp;
+ bool chksums;
+ chksums = argc >= 2 && !strcmp("-c", argv[1]);
rsdp = map_sysmem(gd_acpi_start(), 0);
if (!rsdp) {
printf("No ACPI tables present\n");
@@ -125,7 +142,7 @@ static int do_acpi_list(struct cmd_tbl *cmdtp, int flag, int argc,
}
printf("Name Base Size Detail\n"
"---- ---------------- ----- ----------------------------\n");
- list_rsdp(rsdp);
+ list_rsdp(rsdp, chksums);
return 0;
}
@@ -187,13 +204,13 @@ static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc,
}
U_BOOT_LONGHELP(acpi,
- "list - list ACPI tables\n"
+ "list [-c] - list ACPI tables [check checksums]\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");
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(list, 2, 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/cmd/bootflow.c b/cmd/bootflow.c
index 6d0be320bdb..5349abe49b5 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -173,7 +173,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
std->cur_bootflow = NULL;
- flags = 0;
+ flags = BOOTFLOWIF_ONLY_BOOTABLE;
if (list)
flags |= BOOTFLOWIF_SHOW;
if (all)
diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c
index b2afb598c73..289865515ef 100644
--- a/cmd/x86/mtrr.c
+++ b/cmd/x86/mtrr.c
@@ -13,8 +13,8 @@
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;
+ u64 start, size;
+ u64 base, mask;
int type = -1;
bool valid;
int ret;
@@ -26,13 +26,12 @@ static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[])
printf("Invalid type name %s\n", typename);
return CMD_RET_USAGE;
}
- start = hextoul(argv[1], NULL);
- size = hextoul(argv[2], NULL);
+ start = hextoull(argv[1], NULL);
+ size = hextoull(argv[2], NULL);
base = start | type;
valid = native_read_msr(MTRR_PHYS_MASK_MSR(reg)) & MTRR_PHYS_MASK_VALID;
- mask = ~((uint64_t)size - 1);
- mask &= (1ULL << CONFIG_CPU_ADDR_BITS) - 1;
+ mask = mtrr_to_mask(size);
if (valid)
mask |= MTRR_PHYS_MASK_VALID;
diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig
index 792ba06c2b8..58b1fbf132d 100644
--- a/configs/qemu-x86_64_defconfig
+++ b/configs/qemu-x86_64_defconfig
@@ -1,13 +1,13 @@
CONFIG_X86=y
CONFIG_TEXT_BASE=0x1110000
-CONFIG_SYS_MALLOC_F_LEN=0x1000
-CONFIG_BLOBLIST_SIZE_RELOC=0x20000
+CONFIG_SYS_MALLOC_F_LEN=0x1800
+CONFIG_BLOBLIST_SIZE_RELOC=0x40000
CONFIG_NR_DRAM_BANKS=8
CONFIG_ENV_SIZE=0x40000
CONFIG_MAX_CPUS=2
CONFIG_SPL_DM_SPI=y
CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx"
-CONFIG_SPL_SYS_MALLOC_F_LEN=0x3000
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x4800
CONFIG_SPL_TEXT_BASE=0xfffd0000
CONFIG_DEBUG_UART_BASE=0x3f8
CONFIG_DEBUG_UART_CLOCK=1843200
@@ -41,9 +41,7 @@ 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
CONFIG_SPL_DM_SPI_FLASH=y
-CONFIG_SPL_NET=y
CONFIG_SPL_PCI=y
CONFIG_SPL_PCH=y
CONFIG_SPL_RTC=y
@@ -54,6 +52,7 @@ CONFIG_CMD_MEM_SEARCH=y
CONFIG_CMD_IDE=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
+CONFIG_CMD_CAT=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_BOOTFILESIZE=y
CONFIG_CMD_EFIDEBUG=y
@@ -61,6 +60,9 @@ CONFIG_CMD_TIME=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_FAT=y
+CONFIG_ENV_FAT_INTERFACE="virtio"
+CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_USE_BOOTFILE=y
CONFIG_BOOTFILE="bzImage"
@@ -83,11 +85,11 @@ CONFIG_SYS_NS16550_PORT_MAPPED=y
CONFIG_SPI=y
CONFIG_USB_KEYBOARD=y
CONFIG_CONSOLE_TRUETYPE=y
-CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
-CONFIG_FRAMEBUFFER_VESA_MODE_USER=y
-CONFIG_FRAMEBUFFER_VESA_MODE=0x144
+CONFIG_VIDEO_BOCHS=y
+# CONFIG_VIDEO_VESA is not set
CONFIG_CONSOLE_SCROLL_LINES=5
CONFIG_SPL_VIDEO=y
# CONFIG_SPL_USE_TINY_PRINTF is not set
CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_CMD_DHRYSTONE=y
# CONFIG_GZIP is not set
diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig
index 0b0e10c795f..099d3f32d1b 100644
--- a/configs/qemu-x86_defconfig
+++ b/configs/qemu-x86_defconfig
@@ -1,7 +1,7 @@
CONFIG_X86=y
CONFIG_TEXT_BASE=0xFFF00000
CONFIG_SYS_MALLOC_F_LEN=0x1000
-CONFIG_BLOBLIST_SIZE_RELOC=0x20000
+CONFIG_BLOBLIST_SIZE_RELOC=0x40000
CONFIG_NR_DRAM_BANKS=8
CONFIG_ENV_SIZE=0x40000
CONFIG_MAX_CPUS=2
@@ -34,6 +34,7 @@ CONFIG_CMD_MEM_SEARCH=y
CONFIG_CMD_IDE=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
+CONFIG_CMD_CAT=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_BOOTFILESIZE=y
CONFIG_CMD_EFIDEBUG=y
@@ -42,6 +43,9 @@ CONFIG_CMD_BOOTSTAGE=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_MAC_PARTITION=y
CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_FAT=y
+CONFIG_ENV_FAT_INTERFACE="virtio"
+CONFIG_ENV_FAT_DEVICE_AND_PART="0:1"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_USE_BOOTFILE=y
CONFIG_BOOTFILE="bzImage"
@@ -62,9 +66,9 @@ CONFIG_SYS_NS16550_PORT_MAPPED=y
CONFIG_SPI=y
CONFIG_USB_KEYBOARD=y
CONFIG_CONSOLE_TRUETYPE=y
-CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
-CONFIG_FRAMEBUFFER_VESA_MODE_USER=y
-CONFIG_FRAMEBUFFER_VESA_MODE=0x144
+CONFIG_VIDEO_BOCHS=y
+# CONFIG_VIDEO_VESA is not set
CONFIG_CONSOLE_SCROLL_LINES=5
CONFIG_GENERATE_ACPI_TABLE=y
+CONFIG_CMD_DHRYSTONE=y
# CONFIG_GZIP is not set
diff --git a/doc/develop/bootstd/overview.rst b/doc/develop/bootstd/overview.rst
index e3ce97cc4f5..9fe5630ab16 100644
--- a/doc/develop/bootstd/overview.rst
+++ b/doc/develop/bootstd/overview.rst
@@ -235,8 +235,9 @@ means that `default_get_bootflow()` is used. This simply obtains the
block device and calls a bootdev helper function to do the rest. The
implementation of `bootdev_find_in_blk()` checks the partition table, and
attempts to read a file from a filesystem on the partition number given by the
-`@iter->part` parameter. If there are any bootable partitions in the table,
-then only bootable partitions are considered.
+`@iter->part` parameter. If there are any bootable partitions in the table and
+the BOOTFLOWIF_ONLY_BOOTABLE flag is set in `@iter->flags`, then only bootable
+partitions are considered.
Each bootdev has a priority, which indicates the order in which it is used,
if `boot_targets` is not used. Faster bootdevs are used first, since they are
diff --git a/doc/usage/cmd/acpi.rst b/doc/usage/cmd/acpi.rst
index 9f30972fe53..e652968d584 100644
--- a/doc/usage/cmd/acpi.rst
+++ b/doc/usage/cmd/acpi.rst
@@ -11,7 +11,7 @@ Synopsis
::
- acpi list
+ acpi list [-c]
acpi items [-d]
acpi dump <name>
acpi set <address>
@@ -38,6 +38,9 @@ List the ACPI tables that have been generated. Each table has a 4-character
table name (e.g. SSDT, FACS) and has a format defined by the
`ACPI specification`_.
+The `-c` flag tells U-Boot to verify the checksums and print 'OK' or 'BAD' next
+to each table.
+
U-Boot does not currently support decoding the tables. Unlike devicetree, ACPI
tables have no regular schema and also some include bytecode, so decoding the
tables requires a lot of code.
@@ -259,5 +262,20 @@ pointer::
WAET bff76a3b 28 v01 BOCHS BXPC 1 BXPC 1
SSDT bff95040 c5 v02 COREv4 COREBOOT 2a CORE 20221020
+This shows checking that the checksums are correct for each table::
+
+ => acpi list -c
+ Name Base Size Detail
+ ---- ---------------- ----- ----------------------------
+ RSDP bec9a000 24 v00 BOCHS OK OK
+ RSDT bec9bd4a 38 v01 BOCHS BXPC 1 BXPC 1 OK
+ FACP bec9bb46 74 v01 BOCHS BXPC 1 BXPC 1 OK
+ DSDT bec9a080 1ac6 v01 BOCHS BXPC 1 BXPC 1 OK
+ FACS bec9a040 40
+ APIC bec9bbba 78 v03 BOCHS BXPC 1 BXPC 1 OK
+ HPET bec9bc32 38 v01 BOCHS BXPC 1 BXPC 1 OK
+ SRAT bec9bc6a b8 v01 BOCHS BXPC 1 BXPC 1 OK
+ WAET bec9bd22 28 v01 BOCHS BXPC 1 BXPC 1 OK
+
.. _`ACPI specification`: https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
diff --git a/drivers/misc/qfw_acpi.c b/drivers/misc/qfw_acpi.c
index 0d0cf764689..ec00ba65ade 100644
--- a/drivers/misc/qfw_acpi.c
+++ b/drivers/misc/qfw_acpi.c
@@ -25,17 +25,18 @@ DECLARE_GLOBAL_DATA_PTR;
*
* @entry : BIOS linker command entry which tells where to allocate memory
* (either high memory or low memory)
- * @addr : The address that should be used for low memory allcation. If the
+ * @addr : The address that should be used for low memory allocation. If the
* memory allocation request is 'ZONE_HIGH' then this parameter will
* be ignored.
* @return: 0 on success, or negative value on failure
*/
-static int bios_linker_allocate(struct udevice *dev,
+static int bios_linker_allocate(struct acpi_ctx *ctx, struct udevice *dev,
struct bios_linker_entry *entry, ulong *addr)
{
uint32_t size, align;
struct fw_file *file;
unsigned long aligned_addr;
+ struct acpi_rsdp *rsdp;
align = le32_to_cpu(entry->alloc.align);
/* align must be power of 2 */
@@ -58,7 +59,9 @@ static int bios_linker_allocate(struct udevice *dev,
* If allocation zone is ZONE_FSEG, then we use the 'addr' passed
* in which is low memory
*/
- if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
+ if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) {
+ aligned_addr = ALIGN(*addr, align);
+ } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH) {
aligned_addr = (unsigned long)memalign(align, size);
if (!aligned_addr) {
printf("error: allocating resource\n");
@@ -83,8 +86,13 @@ static int bios_linker_allocate(struct udevice *dev,
(void *)aligned_addr);
file->addr = aligned_addr;
+ rsdp = (void *)aligned_addr;
+ if (!strncmp(rsdp->signature, RSDP_SIG, sizeof(rsdp->signature)))
+ ctx->rsdp = rsdp;
+
/* adjust address for low memory allocation */
- if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
+ if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) ||
+ entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG)
*addr = (aligned_addr + size);
return 0;
@@ -209,19 +217,23 @@ ulong write_acpi_tables(ulong addr)
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
for (i = 0; i < (size / sizeof(*entry)); i++) {
+ log_content("entry %d: addr %lx\n", i, addr);
entry = table_loader + i;
switch (le32_to_cpu(entry->command)) {
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
- ret = bios_linker_allocate(dev, entry, &addr);
+ log_content(" - %s\n", entry->alloc.file);
+ ret = bios_linker_allocate(ctx, dev, entry, &addr);
if (ret)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
+ log_content(" - %s\n", entry->pointer.src_file);
ret = bios_linker_add_pointer(dev, entry);
if (ret)
goto out;
break;
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
+ log_content(" - %s\n", entry->cksum.file);
ret = bios_linker_add_checksum(dev, entry);
if (ret)
goto out;
@@ -246,6 +258,16 @@ out:
free(table_loader);
+ if (!ctx->rsdp) {
+ printf("error: no RSDP found\n");
+ return addr;
+ }
+ struct acpi_rsdp *rsdp = ctx->rsdp;
+
+ rsdp->length = sizeof(*rsdp);
+ rsdp->xsdt_address = 0;
+ rsdp->ext_checksum = table_compute_checksum((u8 *)rsdp, sizeof(*rsdp));
+
gd_set_acpi_start(acpi_get_rsdp_addr());
return addr;
diff --git a/include/acpi/acpi_table.h b/include/acpi/acpi_table.h
index b8b1f1338c6..8ef19adc990 100644
--- a/include/acpi/acpi_table.h
+++ b/include/acpi/acpi_table.h
@@ -36,7 +36,7 @@ struct acpi_ctx;
* RSDP (Root System Description Pointer)
* Note: ACPI 1.0 didn't have length, xsdt_address, and ext_checksum
*/
-struct acpi_rsdp {
+struct __packed acpi_rsdp {
char signature[8]; /* RSDP signature */
u8 checksum; /* Checksum of the first 20 bytes */
char oem_id[6]; /* OEM ID */
diff --git a/include/bootflow.h b/include/bootflow.h
index 480cf8a5af1..d408b8c85bd 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -160,6 +160,7 @@ struct bootflow_img {
* before using it
* @BOOTFLOWIF_ALL: Return bootflows with errors as well
* @BOOTFLOWIF_HUNT: Hunt for new bootdevs using the bootdrv hunters
+ * @BOOTFLOWIF_ONLY_BOOTABLE: Only consider partitions marked 'bootable'
*
* Internal flags:
* @BOOTFLOWIF_SINGLE_DEV: (internal) Just scan one bootdev
@@ -176,6 +177,7 @@ enum bootflow_iter_flags_t {
BOOTFLOWIF_SHOW = 1 << 1,
BOOTFLOWIF_ALL = 1 << 2,
BOOTFLOWIF_HUNT = 1 << 3,
+ BOOTFLOWIF_ONLY_BOOTABLE = BIT(4),
/*
* flags used internally by standard boot - do not set these when
diff --git a/include/bootstd.h b/include/bootstd.h
index 3398e48e88b..2bc464756dd 100644
--- a/include/bootstd.h
+++ b/include/bootstd.h
@@ -22,6 +22,9 @@ struct udevice;
* This is attached to the (only) bootstd device, so there is only one instance
* of this struct. It provides overall information about bootdevs and bootflows.
*
+ * TODO(sjg@chromium.org): Convert prefixes, bootdev_order and env_order to use
+ * alist
+ *
* @prefixes: NULL-terminated list of prefixes to use for bootflow filenames,
* e.g. "/", "/boot/"; NULL if none
* @bootdev_order: Order to use for bootdevs (or NULL if none), with each item
diff --git a/include/mapmem.h b/include/mapmem.h
index f496c96d16c..8ec03d59f0b 100644
--- a/include/mapmem.h
+++ b/include/mapmem.h
@@ -33,7 +33,7 @@ static inline phys_addr_t map_to_sysmem(const void *ptr)
* nomap_sysmem() - pass through an address unchanged
*
* This is used to indicate an address which should NOT be mapped, e.g. in
- * SMBIOS tables. Using this function instead of a case shows that the sandbox
+ * SMBIOS tables. Using this function instead of a cast shows that the sandbox
* conversion has been done
*/
static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len)
diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c
index 4ad1f56e961..12215f5d90a 100644
--- a/lib/acpi/acpi_table.c
+++ b/lib/acpi/acpi_table.c
@@ -66,6 +66,7 @@ int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags)
dmar->host_address_width = info.address_width - 1;
dmar->flags = flags;
+ header->checksum = table_compute_checksum(dmar, header->length);
return 0;
}
@@ -255,8 +256,8 @@ int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry)
header->creator_revision = 1;
fadt->minor_revision = 2;
- fadt->x_firmware_ctrl = map_to_sysmem(ctx->facs);
- fadt->x_dsdt = map_to_sysmem(ctx->dsdt);
+ fadt->x_firmware_ctrl = nomap_to_sysmem(ctx->facs);
+ fadt->x_dsdt = nomap_to_sysmem(ctx->dsdt);
if (fadt->x_firmware_ctrl < 0x100000000ULL)
fadt->firmware_ctrl = fadt->x_firmware_ctrl;
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 5f07430714e..d5499918249 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -509,6 +509,7 @@ static int bootdev_test_bootable(struct unit_test_state *uts)
iter.part = 0;
ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk));
iter.dev = blk;
+ iter.flags = BOOTFLOWIF_ONLY_BOOTABLE;
ut_assertok(device_find_next_child(&iter.dev));
uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index eb7f00af39a..5f9c037ff53 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -297,8 +297,9 @@ static int bootflow_iter(struct unit_test_state *uts)
/* The first device is mmc2.bootdev which has no media */
ut_asserteq(-EPROTONOSUPPORT,
- bootflow_scan_first(NULL, NULL, &iter,
- BOOTFLOWIF_ALL | BOOTFLOWIF_SKIP_GLOBAL, &bflow));
+ bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_ALL |
+ BOOTFLOWIF_SKIP_GLOBAL |
+ BOOTFLOWIF_ONLY_BOOTABLE, &bflow));
ut_asserteq(2, iter.num_methods);
ut_asserteq(0, iter.cur_method);
ut_asserteq(0, iter.part);
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index 39a26bbb492..db012b6d2f1 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -309,6 +309,8 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)
}
ut_asserteq(0, ctx.rsdt->entry[3]);
ut_asserteq(0, ctx.xsdt->entry[3]);
+ unmap_sysmem(buf);
+ free(buf);
return 0;
}
@@ -386,6 +388,8 @@ static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts)
ut_asserteq(nomap_to_sysmem(rsdt), rsdp->rsdt_address);
ut_asserteq(nomap_to_sysmem(xsdt), rsdp->xsdt_address);
+ unmap_sysmem(buf);
+ free(buf);
return 0;
}
@@ -428,11 +432,59 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts)
ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
addr, sizeof(struct acpi_dmar), OEM_REVISION);
ut_assert_console_end();
+ unmap_sysmem(buf);
+ free(buf);
return 0;
}
DM_TEST(dm_test_acpi_cmd_list, UTF_SCAN_PDATA | UTF_SCAN_FDT | UTF_CONSOLE);
+/* Test 'acpi list -c' command */
+static int dm_test_acpi_cmd_list_chksum(struct unit_test_state *uts)
+{
+ struct acpi_ctx ctx;
+ ulong addr;
+ void *buf;
+
+ 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));
+
+ run_command("acpi list -c", 0);
+ ut_assert_nextline("Name Base Size Detail");
+ ut_assert_nextline("---- ---------------- ----- ----------------------------");
+ ut_assert_nextline("RSDP %16lx %5zx v02 U-BOOT OK OK", addr,
+ sizeof(struct acpi_rsdp));
+ addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
+ ut_assert_nextline("RSDT %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0 OK",
+ addr, sizeof(struct acpi_table_header) +
+ 3 * sizeof(u32), OEM_REVISION);
+ addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
+ ut_assert_nextline("XSDT %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0 OK",
+ addr, sizeof(struct acpi_table_header) +
+ 3 * sizeof(u64), OEM_REVISION);
+ addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
+ ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0 OK",
+ addr, sizeof(struct acpi_dmar), OEM_REVISION);
+ addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
+ ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0 OK",
+ addr, sizeof(struct acpi_dmar), OEM_REVISION);
+ addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
+ ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0 OK",
+ addr, sizeof(struct acpi_dmar), OEM_REVISION);
+ ut_assert_console_end();
+ ut_assert_console_end();
+ unmap_sysmem(buf);
+ free(buf);
+
+ return 0;
+}
+DM_TEST(dm_test_acpi_cmd_list_chksum,
+ UTF_SCAN_PDATA | UTF_SCAN_FDT | UTF_CONSOLE);
+
/* Test 'acpi dump' command */
static int dm_test_acpi_cmd_dump(struct unit_test_state *uts)
{
@@ -458,6 +510,8 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts)
ut_assert_nextline("DMAR @ %16lx", addr);
ut_assert_nextlines_are_dump(0x30);
ut_assert_console_end();
+ unmap_sysmem(buf);
+ free(buf);
return 0;
}
@@ -642,6 +696,8 @@ static int dm_test_acpi_cmd_items(struct unit_test_state *uts)
ut_assert_nextlines_are_dump(2);
ut_assert_nextline("%s", "");
ut_assert_console_end();
+ unmap_sysmem(buf);
+ free(buf);
return 0;
}
@@ -679,6 +735,8 @@ static int dm_test_acpi_cmd_set(struct unit_test_state *uts)
ut_asserteq(addr, gd_acpi_start());
ut_assert_console_end();
+ unmap_sysmem(buf);
+ free(buf);
return 0;
}
@@ -774,6 +832,7 @@ static int dm_test_acpi_find_table(struct unit_test_state *uts)
/* Restore previous ACPI tables */
gd_set_acpi_start(acpi_start);
+ unmap_sysmem(buf);
free(buf);
return 0;
diff --git a/test/py/conftest.py b/test/py/conftest.py
index e59897c1f78..5aea85647af 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -334,6 +334,7 @@ def pytest_configure(config):
ubconfig.dtb = build_dir + '/arch/sandbox/dts/test.dtb'
ubconfig.connection_ok = True
ubconfig.timing = config.getoption('timing')
+ ubconfig.role = config.getoption('role')
env_vars = (
'board_type',
@@ -760,6 +761,26 @@ def setup_singlethread(item):
if worker_id and worker_id != 'master':
pytest.skip('must run single-threaded')
+def setup_role(item):
+ """Process any 'role' marker for a test.
+
+ Skip this test if the role does not match.
+
+ Args:
+ item (pytest.Item): The pytest test item
+ """
+ required_roles = []
+ for roles in item.iter_markers('role'):
+ role = roles.args[0]
+ if role.startswith('!'):
+ if ubconfig.role == role[1:]:
+ pytest.skip(f'role "{ubconfig.role}" not supported')
+ return
+ else:
+ required_roles.append(role)
+ if required_roles and ubconfig.role not in required_roles:
+ pytest.skip(f'board "{ubconfig.role}" not supported')
+
def start_test_section(item):
anchors[item.name] = log.start_section(item.name)
@@ -781,6 +802,7 @@ def pytest_runtest_setup(item):
setup_buildconfigspec(item)
setup_requiredtool(item)
setup_singlethread(item)
+ setup_role(item)
def pytest_runtest_protocol(item, nextitem):
"""pytest hook: Called to execute a test.
diff --git a/test/py/console_base.py b/test/py/console_base.py
index 260df773bac..88d444b44b8 100644
--- a/test/py/console_base.py
+++ b/test/py/console_base.py
@@ -370,21 +370,30 @@ class ConsoleBase(object):
output.append(self.run_command(cmd))
return output
- def ctrlc(self):
- """Send a CTRL-C character to U-Boot.
+ def send(self, msg):
+ """Send characters without waiting for echo, etc."""
+ self.run_command(msg, wait_for_prompt=False, wait_for_echo=False,
+ send_nl=False)
+
+ def ctrl(self, char):
+ """Send a CTRL- character to U-Boot.
This is useful in order to stop execution of long-running synchronous
commands such as "ums".
Args:
- None.
-
- Returns:
- Nothing.
+ char (str): Character to send, e.g. 'C' to send Ctrl-C
"""
+ self.log.action(f'Sending Ctrl-{char}')
+ self.send(chr(ord(char) - ord('@')))
- self.log.action('Sending Ctrl-C')
- self.run_command(chr(3), wait_for_echo=False, send_nl=False)
+ def ctrlc(self):
+ """Send a CTRL-C character to U-Boot.
+
+ This is useful in order to stop execution of long-running synchronous
+ commands such as "ums".
+ """
+ self.ctrl('C')
def wait_for(self, text):
"""Wait for a pattern to be emitted by U-Boot.
diff --git a/test/py/pytest.ini b/test/py/pytest.ini
index 26d83f83e00..361be0178ee 100644
--- a/test/py/pytest.ini
+++ b/test/py/pytest.ini
@@ -12,3 +12,4 @@ markers =
requiredtool: U-Boot: Required host tools for a test.
slow: U-Boot: Specific test will run slowly.
singlethread: Cannot run in parallel
+ role: U-Boot: Indicates the lab 'role' which can execute this test
diff --git a/test/py/tests/test_distro.py b/test/py/tests/test_distro.py
new file mode 100644
index 00000000000..bdf4ab657d1
--- /dev/null
+++ b/test/py/tests/test_distro.py
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2025 Canonical Ltd.
+# Written by Simon Glass <simon.glass@canonical.com>
+
+import pytest
+
+# Enable early console so that the test can see if something goes wrong
+CONSOLE = 'earlycon=uart8250,io,0x3f8 console=uart8250,io,0x3f8'
+
+@pytest.mark.boardspec('qemu-x86_64')
+@pytest.mark.role('qemu-x86_64')
+def test_distro(ubman):
+ """Test that of-platdata can be generated and used in sandbox"""
+ with ubman.log.section('boot'):
+ ubman.run_command('boot', wait_for_prompt=False)
+
+ with ubman.log.section('Grub'):
+ # Wait for grub to come up and offset a menu
+ ubman.p.expect(['Try or Install Ubuntu'])
+
+ # Press 'e' to edit the command line
+ ubman.log.info("Pressing 'e'")
+ ubman.run_command('e', wait_for_prompt=False, send_nl=False)
+
+ # Wait until we see the editor appear
+ ubman.p.expect(['/casper/initrd'])
+
+ # Go down to the 'linux' line. Avoid using down-arrow as that includes
+ # an Escape character, which may be parsed by Grub as such, causing it
+ # to return to the top menu
+ ubman.log.info("Going DOWN")
+ ubman.ctrl('N')
+ ubman.ctrl('N')
+ ubman.ctrl('N')
+
+ # Go to end of line
+ ubman.log.info("Going to EOL")
+ ubman.ctrl('E')
+
+ # Backspace to remove 'quiet splash'
+ ubman.log.info("Erasing quiet and splash")
+ ubman.send('\b' * len('quiet splash'))
+
+ # Send our noisy console
+ ubman.log.info("Noisy console")
+ ubman.send(CONSOLE)
+
+ # Tell grub to boot
+ ubman.log.info("boot")
+ ubman.ctrl('X')
+ ubman.p.expect(['Booting a command list'])
+
+ with ubman.log.section('Linux'):
+ # Linux should start immediately
+ ubman.p.expect(['Linux version'])
+
+ with ubman.log.section('Ubuntu'):
+ # Shortly later, we should see this banner
+ ubman.p.expect(['Welcome to .*Ubuntu 24.04.1 LTS.*!'])
+
+ ubman.restart_uboot()
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index ea0c43cd4fc..b8adb597e11 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -57,6 +57,17 @@ def setup_image(ubman, devnum, part_type, img_size=20, second_part=False,
stdin=spec.encode('utf-8'))
return fname, mnt
+def copy_partition(ubman, fsfile, outname):
+ """Copy a partition into a disk iamge
+
+ Args:
+ ubman (ConsoleBase): U-Boot fixture
+ fsfile (str): Name of partition file
+ outname (str): Name of full-disk file to update
+ """
+ utils.run_and_log(ubman,
+ f'dd if={fsfile} of={outname} bs=1M seek=1 conv=notrunc')
+
def setup_bootmenu_image(ubman):
"""Create a 20MB disk image with a single ext4 partition
@@ -172,7 +183,7 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
fsfile = 'ext18M.img'
utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}')
utils.run_and_log(ubman, f'mkfs.ext4 {fsfile} -d {mnt}')
- utils.run_and_log(ubman, f'dd if={fsfile} of={fname} bs=1M seek=1')
+ copy_partition(ubman, fsfile, fname)
utils.run_and_log(ubman, f'rm -rf {mnt}')
utils.run_and_log(ubman, f'rm -f {fsfile}')
@@ -224,7 +235,7 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}')
utils.run_and_log(ubman, f'mkfs.vfat {fsfile}')
utils.run_and_log(ubman, ['sh', '-c', f'mcopy -i {fsfile} {mnt}/* ::/'])
- utils.run_and_log(ubman, f'dd if={fsfile} of={fname} bs=1M seek=1')
+ copy_partition(ubman, fsfile, fname)
utils.run_and_log(ubman, f'rm -rf {mnt}')
utils.run_and_log(ubman, f'rm -f {fsfile}')
@@ -562,7 +573,7 @@ def setup_efi_image(ubman):
utils.run_and_log(ubman, f'fallocate -l 18M {fsfile}')
utils.run_and_log(ubman, f'mkfs.vfat {fsfile}')
utils.run_and_log(ubman, ['sh', '-c', f'mcopy -vs -i {fsfile} {mnt}/* ::/'])
- utils.run_and_log(ubman, f'dd if={fsfile} of={fname} bs=1M seek=1')
+ copy_partition(ubman, fsfile, fname)
utils.run_and_log(ubman, f'rm -rf {mnt}')
utils.run_and_log(ubman, f'rm -f {fsfile}')