- bootstd: Add a bootmeth for ChromiumOS on x86
- x86: Use qemu-x86_64 to boot EFI installers
This commit is contained in:
Tom Rini 2023-07-17 10:38:28 -04:00
commit 13aa090b87
95 changed files with 2425 additions and 319 deletions

View File

@ -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>

View File

@ -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;
}

View File

@ -3,6 +3,8 @@
* Copyright (c) 2016 Google, Inc
*/
#define LOG_CATEGORY UCLASS_RAM
#include <common.h>
#include <dm.h>
#include <init.h>
@ -144,12 +146,10 @@ int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap)
ret = gpio_request_list_by_name(dev, "board-id-gpios", desc,
ARRAY_SIZE(desc), GPIOD_IS_IN);
if (ret < 0) {
debug("%s: gpio ret=%d\n", __func__, ret);
return ret;
}
if (ret < 0)
return log_msg_ret("gpio", ret);
spd_index = dm_gpio_get_values_as_int(desc, ret);
debug("spd index %d\n", spd_index);
log_debug("spd index %d\n", spd_index);
node = fdt_first_subnode(blob, dev_of_offset(dev));
if (node < 0)

View File

@ -9,6 +9,8 @@
* Copyright (C) 2011 Google Inc.
*/
#define LOG_CATEGORY UCLASS_RAM
#include <common.h>
#include <dm.h>
#include <errno.h>
@ -213,7 +215,7 @@ static int copy_spd(struct udevice *dev, struct pei_data *peid)
ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data);
if (ret) {
debug("%s: Could not locate SPD (ret=%d)\n", __func__, ret);
log_debug("Could not locate SPD (err=%d)\n", ret);
return ret;
}

View File

@ -30,6 +30,16 @@
DECLARE_GLOBAL_DATA_PTR;
static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = {
"Uncacheable",
"Combine",
"2",
"3",
"Through",
"Protect",
"Back",
};
/* Prepare to adjust MTRRs */
void mtrr_open(struct mtrr_state *state, bool do_caches)
{
@ -320,3 +330,54 @@ int mtrr_set(int cpu_select, int reg, u64 base, u64 mask)
return mtrr_start_op(cpu_select, &oper);
}
static void read_mtrrs_(void *arg)
{
struct mtrr_info *info = arg;
mtrr_read_all(info);
}
int mtrr_list(int reg_count, int cpu_select)
{
struct mtrr_info info;
int ret;
int i;
printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||",
"Mask ||", "Size ||");
memset(&info, '\0', sizeof(info));
ret = mp_run_on_cpus(cpu_select, read_mtrrs_, &info);
if (ret)
return log_msg_ret("run", ret);
for (i = 0; i < reg_count; i++) {
const char *type = "Invalid";
u64 base, mask, size;
bool valid;
base = info.mtrr[i].base;
mask = info.mtrr[i].mask;
size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1);
size |= (1 << 12) - 1;
size += 1;
valid = mask & MTRR_PHYS_MASK_VALID;
type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
mask & ~MTRR_PHYS_MASK_VALID, size);
}
return 0;
}
int mtrr_get_type_by_name(const char *typename)
{
int i;
for (i = 0; i < MTRR_TYPE_COUNT; i++) {
if (*typename == *mtrr_type_name[i])
return i;
}
return -EINVAL;
};

View File

@ -12,7 +12,7 @@ config QEMU
imply SYS_NS16550
imply USB
imply USB_EHCI_HCD
imply VIDEO_VESA
imply VIDEO_BOCHS
if QEMU

View File

@ -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

View File

@ -314,6 +314,7 @@
00 00 00 00 00 00 00 00];
};
micron_4Gb_1600_1.35v_x16 {
bootph-all;
reg = <2>;
data = [92 11 0b 03 04 19 02 02
03 11 01 08 0a 00 fe 00

View File

@ -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

View File

@ -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)

View File

@ -102,8 +102,31 @@ int video_bios_init(void);
*/
int fsp_save_s3_stack(void);
void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
void board_init_f_r(void) __attribute__ ((noreturn));
/**
* board_init_f_r_trampoline() - jump to relocated address with new stack
*
* @sp: New stack pointer to use
*/
void __noreturn board_init_f_r_trampoline(ulong sp);
/**
* board_init_f_r() - jump to relocated U-Boot
*
* This is used to jump from pre-relocation to post-relocation U-Boot. It
* enables the cache and jump to the new location.
*/
void __noreturn board_init_f_r(void);
/*
* board_init_f_r_trampoline64() - jump to relocated address with new stack
*
* This is the 64-bit version
*
* @new_gd: New global_data pointer to use
* @sp: New stack pointer to pass on to board_init_r()
*/
void __noreturn board_init_f_r_trampoline64(struct global_data *new_gd,
ulong sp);
int arch_misc_init(void);

View File

@ -72,4 +72,31 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
*/
void zimage_dump(struct boot_params *base_ptr);
/**
* zboot_start() - Boot a zimage
*
* Boot a zimage, given the component parts
*
* @addr: Address where the bzImage is moved before booting, either
* BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
* @base: Pointer to the boot parameters, typically at address
* DEFAULT_SETUP_BASE
* @initrd: Address of the initial ramdisk, or 0 if none
* @initrd_size: Size of the initial ramdisk, or 0 if none
* @cmdline: Command line to use for booting
* Return: -EFAULT on error (normally it does not return)
*/
int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size,
ulong base, char *cmdline);
/*
* zimage_get_kernel_version() - Get the version string from a kernel
*
* @params: boot_params pointer
* @kernel_base: base address of kernel
* Return: Kernel version as a NUL-terminated string
*/
const char *zimage_get_kernel_version(struct boot_params *params,
void *kernel_base);
#endif

View File

@ -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

View File

@ -22,6 +22,11 @@ void arch_print_bdinfo(void)
bdinfo_print_num_l("vendor", gd->arch.x86_vendor);
bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor));
bdinfo_print_num_l("model", gd->arch.x86_model);
bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size());
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();

View File

@ -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
@ -78,7 +78,7 @@ static int int_exception_handler(void)
};
struct eregs *regs = &reg_info;
debug("Oops, exception %d while executing option rom\n", regs->vector);
log_err("Exception %d while executing option rom\n", regs->vector);
cpu_hlt();
return 0;

View File

@ -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

View File

@ -6,6 +6,8 @@
* Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com>
*/
#define LOG_CATEGORY UCLASS_RAM
#include <common.h>
#include <dm.h>
#include <errno.h>
@ -197,8 +199,8 @@ static void mrccache_setup(struct mrc_output *mrc, void *data)
cache->signature = MRC_DATA_SIGNATURE;
cache->data_size = mrc->len;
checksum = compute_ip_checksum(mrc->buf, cache->data_size);
debug("Saving %d bytes for MRC output data, checksum %04x\n",
cache->data_size, checksum);
log_debug("Saving %d bytes for MRC output data, checksum %04x\n",
cache->data_size, checksum);
cache->checksum = checksum;
cache->reserved = 0;
memcpy(cache->data, mrc->buf, cache->data_size);

View File

@ -3,6 +3,8 @@
* Copyright (c) 2016 Google, Inc
*/
#define LOG_CATEGORY LOGC_BOOT
#include <common.h>
#include <cpu_func.h>
#include <debug_uart.h>
@ -15,10 +17,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>
@ -61,6 +65,8 @@ static int set_max_freq(void)
static int x86_spl_init(void)
{
struct udevice *dev;
#ifndef CONFIG_TPL
/*
* TODO(sjg@chromium.org): We use this area of RAM for the stack
@ -74,49 +80,64 @@ static int x86_spl_init(void)
#endif
int ret;
debug("%s starting\n", __func__);
log_debug("x86 spl starting\n");
if (IS_ENABLED(TPL))
ret = x86_cpu_reinit_f();
else
ret = x86_cpu_init_f();
ret = spl_init();
if (ret) {
debug("%s: spl_init() failed\n", __func__);
log_debug("spl_init() failed (err=%d)\n", ret);
return ret;
}
ret = arch_cpu_init();
if (ret) {
debug("%s: arch_cpu_init() failed\n", __func__);
log_debug("arch_cpu_init() failed (err=%d)\n", ret);
return ret;
}
#ifndef CONFIG_TPL
ret = fsp_setup_pinctrl(NULL, NULL);
if (ret) {
debug("%s: fsp_setup_pinctrl() failed\n", __func__);
log_debug("fsp_setup_pinctrl() failed (err=%d)\n", ret);
return ret;
}
#endif
preloader_console_init();
/*
* spl_board_init() below sets up the console if enabled. If it isn't,
* do it here. We cannot call this twice since it results in a double
* banner and CI tests fail.
*/
if (!IS_ENABLED(CONFIG_SPL_BOARD_INIT))
preloader_console_init();
#if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU)
ret = print_cpuinfo();
if (ret) {
debug("%s: print_cpuinfo() failed\n", __func__);
log_debug("print_cpuinfo() failed (err=%d)\n", ret);
return ret;
}
#endif
ret = dram_init();
if (ret) {
debug("%s: dram_init() failed\n", __func__);
/* probe the LPC so we get the GPIO_BASE set up correctly */
ret = uclass_first_device_err(UCLASS_LPC, &dev);
if (ret && ret != -ENODEV) {
log_debug("lpc probe failed\n");
return ret;
}
ret = dram_init();
if (ret) {
log_debug("dram_init() failed (err=%d)\n", ret);
return ret;
}
log_debug("mrc\n");
if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) {
ret = mrccache_spl_save();
if (ret)
debug("%s: Failed to write to mrccache (err=%d)\n",
__func__, ret);
log_debug("Failed to write to mrccache (err=%d)\n",
ret);
}
#ifndef CONFIG_SYS_COREBOOT
log_debug("bss\n");
debug("BSS clear from %lx to %lx len %lx\n", (ulong)&__bss_start,
(ulong)&__bss_end, (ulong)&__bss_end - (ulong)&__bss_start);
memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start);
@ -136,9 +157,29 @@ static int x86_spl_init(void)
*/
gd->new_gd = (struct global_data *)ptr;
memcpy(gd->new_gd, gd, sizeof(*gd));
log_debug("logging\n");
/*
* Make sure logging is disabled when we switch, since the log system
* list head will move
*/
gd->new_gd->flags &= ~GD_FLG_LOG_READY;
arch_setup_gd(gd->new_gd);
gd->start_addr_sp = (ulong)ptr;
/* start up logging again, with the new list-head location */
ret = log_init();
if (ret) {
log_debug("Log setup failed (err=%d)\n", ret);
return ret;
}
if (_LOG_DEBUG) {
ret = mtrr_list(mtrr_get_var_count(), MP_SELECT_BSP);
if (ret)
printf("mtrr_list failed\n");
}
/* Cache the SPI flash. Otherwise copying the code to RAM takes ages */
ret = mtrr_add_request(MTRR_TYPE_WRBACK,
(1ULL << 32) - CONFIG_XIP_ROM_SIZE,
@ -157,6 +198,7 @@ static int x86_spl_init(void)
debug("Failed to set CPU frequency (err=%d)\n", ret);
# endif
#endif
log_debug("done\n");
return 0;
}
@ -250,4 +292,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);
}
}

View File

@ -3,7 +3,7 @@
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*/
#define LOG_CATEGORY LOGC_BOARD
#define LOG_CATEGORY LOGC_ACPI
#include <common.h>
#include <bloblist.h>
@ -54,6 +54,10 @@ static struct table_info table_list[] = {
#ifdef CONFIG_GENERATE_MP_TABLE
{ "mp", write_mp_table, },
#endif
/*
* tables which can go in the bloblist must be last in this list, so
* that the calculation of gd->table_end works properly
*/
#ifdef CONFIG_GENERATE_ACPI_TABLE
{ "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000},
#endif
@ -78,33 +82,42 @@ 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];
bool use_high = false;
u32 rom_addr;
int i;
rom_table_start = ROM_TABLE_ADDR;
gd->arch.table_start = ROM_TABLE_ADDR;
rom_addr = gd->arch.table_start;
debug("Writing tables to %x:\n", rom_table_start);
debug("Writing tables to %x:\n", rom_addr);
for (i = 0; i < ARRAY_SIZE(table_list); i++) {
const struct table_info *table = &table_list[i];
int size = table->size ? : CONFIG_ROM_TABLE_SIZE;
u32 rom_table_end;
if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) {
rom_table_start = (ulong)bloblist_add(table->tag, size,
table->align);
if (!rom_table_start)
if (!gd->arch.table_end)
gd->arch.table_end = rom_addr;
rom_addr = (ulong)bloblist_add(table->tag, size,
table->align);
if (!rom_addr)
return log_msg_ret("bloblist", -ENOBUFS);
/* the bloblist is always in high memory */
use_high = true;
if (!gd->arch.table_start_high)
gd->arch.table_start_high = rom_addr;
}
rom_table_end = table->write(rom_table_start);
rom_table_end = table->write(rom_addr);
if (!rom_table_end) {
log_err("Can't create configuration table %d\n", i);
return -EINTR;
}
if (IS_ENABLED(CONFIG_SEABIOS)) {
table_size = rom_table_end - rom_table_start;
table_size = rom_table_end - rom_addr;
high_table = (u32)(ulong)high_table_malloc(table_size);
if (high_table) {
if (!table->write(high_table)) {
@ -123,15 +136,20 @@ int write_tables(void)
}
debug("- wrote '%s' to %x, end %x\n", table->name,
rom_table_start, rom_table_end);
if (rom_table_end - rom_table_start > size) {
rom_addr, rom_table_end);
if (rom_table_end - rom_addr > size) {
log_err("Out of space for configuration tables: need %x, have %x\n",
rom_table_end - rom_table_start, size);
rom_table_end - rom_addr, size);
return log_msg_ret("bloblist", -ENOSPC);
}
rom_table_start = rom_table_end;
rom_addr = rom_table_end;
}
if (use_high)
gd->arch.table_end_high = rom_addr;
else
gd->arch.table_end = rom_addr;
if (IS_ENABLED(CONFIG_SEABIOS)) {
/* make sure the last item is zero */
cfg_tables[i].size = 0;

View File

@ -22,6 +22,7 @@
#include <irq_func.h>
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
#include <acpi/acpi_table.h>
#include <asm/io.h>
#include <asm/ptrace.h>
@ -180,7 +181,7 @@ static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob)
return 0;
}
static const char *get_kernel_version(struct boot_params *params,
const char *zimage_get_kernel_version(struct boot_params *params,
void *kernel_base)
{
struct setup_header *hdr = &params->hdr;
@ -188,10 +189,14 @@ static const char *get_kernel_version(struct boot_params *params,
const char *s, *end;
bootproto = get_boot_protocol(hdr, false);
log_debug("bootproto %x, hdr->setup_sects %x\n", bootproto,
hdr->setup_sects);
if (bootproto < 0x0200 || hdr->setup_sects < 15)
return NULL;
/* sanity-check the kernel version in case it is missing */
log_debug("hdr->kernel_version %x, str at %p\n", hdr->kernel_version,
kernel_base + hdr->kernel_version + 0x200);
for (s = kernel_base + hdr->kernel_version + 0x200, end = s + 0x100; *s;
s++) {
if (!isprint(*s))
@ -238,7 +243,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
log_debug("Using boot protocol version %x.%02x\n",
(bootproto & 0xff00) >> 8, bootproto & 0xff);
version = get_kernel_version(params, image);
version = zimage_get_kernel_version(params, image);
if (version)
printf("Linux kernel version %s\n", version);
else
@ -442,8 +447,7 @@ static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc,
return 0;
}
static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
static int zboot_load(void)
{
struct boot_params *base_ptr;
@ -460,31 +464,51 @@ static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
&state.load_address);
if (!base_ptr) {
puts("## Kernel loading failed ...\n");
return CMD_RET_FAILURE;
return -EINVAL;
}
}
state.base_ptr = base_ptr;
if (env_set_hex("zbootbase", (ulong)base_ptr) ||
return 0;
}
static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
if (zboot_load())
return CMD_RET_FAILURE;
if (env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)) ||
env_set_hex("zbootaddr", state.load_address))
return CMD_RET_FAILURE;
return 0;
}
static int zboot_setup(void)
{
struct boot_params *base_ptr = state.base_ptr;
int ret;
ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
0, state.initrd_addr, state.initrd_size,
(ulong)state.cmdline);
if (ret)
return -EINVAL;
return 0;
}
static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct boot_params *base_ptr = state.base_ptr;
int ret;
if (!base_ptr) {
printf("base is not set: use 'zboot load' first\n");
return CMD_RET_FAILURE;
}
ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET,
0, state.initrd_addr, state.initrd_size,
(ulong)state.cmdline);
if (ret) {
if (zboot_setup()) {
puts("Setting up boot parameters failed ...\n");
return CMD_RET_FAILURE;
}
@ -501,8 +525,7 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc,
return 0;
}
static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
static int zboot_go(void)
{
struct boot_params *params = state.base_ptr;
struct setup_header *hdr = &params->hdr;
@ -522,11 +545,52 @@ static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
/* we assume that the kernel is in place */
ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit);
return ret;
}
static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
int ret;
ret = zboot_go();
printf("Kernel returned! (err=%d)\n", ret);
return CMD_RET_FAILURE;
}
int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size,
ulong base, char *cmdline)
{
int ret;
memset(&state, '\0', sizeof(state));
if (base) {
state.base_ptr = map_sysmem(base, 0);
state.load_address = addr;
} else {
state.bzimage_addr = addr;
}
state.bzimage_size = size;
state.initrd_addr = initrd;
state.initrd_size = initrd_size;
state.cmdline = cmdline;
ret = zboot_load();
if (ret)
return log_msg_ret("ld", ret);
ret = zboot_setup();
if (ret)
return log_msg_ret("set", ret);
ret = zboot_go();
if (ret)
return log_msg_ret("set", ret);
return -EFAULT;
}
static void print_num(const char *name, ulong value)
{
printf("%-20s: %lx\n", name, value);
@ -668,7 +732,8 @@ void zimage_dump(struct boot_params *base_ptr)
print_num("Real mode switch", hdr->realmode_swtch);
print_num("Start sys seg", hdr->start_sys_seg);
print_num("Kernel version", hdr->kernel_version);
version = get_kernel_version(base_ptr, (void *)state.bzimage_addr);
version = zimage_get_kernel_version(base_ptr,
(void *)state.bzimage_addr);
if (version)
printf(" @%p: %s\n", version, version);
print_num("Type of loader", hdr->type_of_loader);

View File

@ -4,13 +4,6 @@
if VENDOR_GOOGLE
config BIOSEMU
bool
select X86EMU_RAW_IO
config X86EMU_RAW_IO
bool
choice
prompt "Mainboard model"
optional

View File

@ -11,16 +11,18 @@
#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 <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>
#include <linux/kernel.h>
#include <malloc.h>
#include <extension_board.h>
#include <linux/sizes.h>
/*
* Pointer to initial global data area
@ -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

View File

@ -463,6 +463,17 @@ config BOOTMETH_GLOBAL
EFI bootmgr, since they take full control over which bootdevs are
selected to boot.
config BOOTMETH_CROS
bool "Bootdev support for Chromium OS"
depends on X86 || SANDBOX
default y
help
Enables support for booting Chromium OS using bootdevs. This uses the
kernel A slot and obtains the kernel command line from the parameters
provided there.
Note that only x86 devices are supported at present.
config BOOTMETH_EXTLINUX
bool "Bootdev support for extlinux boot"
select PXE_UTILS

View File

@ -27,6 +27,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EXTLINUX) += bootmeth_extlinux.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EXTLINUX_PXE) += bootmeth_pxe.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_CROS) += bootmeth_cros.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o
ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL

View File

@ -12,7 +12,9 @@
#include <bootmeth.h>
#include <bootstd.h>
#include <dm.h>
#include <env_internal.h>
#include <malloc.h>
#include <serial.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
@ -315,14 +317,14 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow)
/* If we got a valid bootflow, return it */
if (!ret) {
log_debug("Bootdevice '%s' part %d method '%s': Found bootflow\n",
log_debug("Bootdev '%s' part %d method '%s': Found bootflow\n",
dev->name, iter->part, iter->method->name);
return 0;
}
/* Unless there is nothing more to try, move to the next device */
else if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
log_debug("Bootdevice '%s' part %d method '%s': Error %d\n",
log_debug("Bootdev '%s' part %d method '%s': Error %d\n",
dev->name, iter->part, iter->method->name, ret);
/*
* For 'all' we return all bootflows, even
@ -552,3 +554,336 @@ int bootflow_iter_check_system(const struct bootflow_iter *iter)
return -ENOTSUPP;
}
/**
* bootflow_cmdline_set() - Set the command line for a bootflow
*
* @value: New command-line string
* Returns 0 if OK, -ENOENT if no current bootflow, -ENOMEM if out of memory
*/
int bootflow_cmdline_set(struct bootflow *bflow, const char *value)
{
char *cmdline = NULL;
if (value) {
cmdline = strdup(value);
if (!cmdline)
return -ENOMEM;
}
free(bflow->cmdline);
bflow->cmdline = cmdline;
return 0;
}
#ifdef CONFIG_BOOTSTD_FULL
/**
* on_bootargs() - Update the cmdline of a bootflow
*/
static int on_bootargs(const char *name, const char *value, enum env_op op,
int flags)
{
struct bootstd_priv *std;
struct bootflow *bflow;
int ret;
ret = bootstd_get_priv(&std);
if (ret)
return 0;
bflow = std->cur_bootflow;
if (!bflow)
return 0;
switch (op) {
case env_op_create:
case env_op_overwrite:
ret = bootflow_cmdline_set(bflow, value);
if (ret && ret != ENOENT)
return 1;
return 0;
case env_op_delete:
bootflow_cmdline_set(bflow, NULL);
fallthrough;
default:
return 0;
}
}
U_BOOT_ENV_CALLBACK(bootargs, on_bootargs);
#endif
/**
* copy_in() - Copy a string into a cmdline buffer
*
* @buf: Buffer to copy into
* @end: End of buffer (pointer to char after the end)
* @arg: String to copy from
* @len: Number of chars to copy from @arg (note that this is not usually the
* sane as strlen(arg) since the string may contain following arguments)
* @new_val: Value to put after arg, or BOOTFLOWCL_EMPTY to use an empty value
* with no '=' sign
* Returns: Number of chars written to @buf
*/
static int copy_in(char *buf, char *end, const char *arg, int len,
const char *new_val)
{
char *to = buf;
/* copy the arg name */
if (to + len >= end)
return -E2BIG;
memcpy(to, arg, len);
to += len;
if (new_val == BOOTFLOWCL_EMPTY) {
/* no value */
} else {
bool need_quote = strchr(new_val, ' ');
len = strlen(new_val);
/* need space for value, equals sign and maybe two quotes */
if (to + 1 + (need_quote ? 2 : 0) + len >= end)
return -E2BIG;
*to++ = '=';
if (need_quote)
*to++ = '"';
memcpy(to, new_val, len);
to += len;
if (need_quote)
*to++ = '"';
}
return to - buf;
}
int cmdline_set_arg(char *buf, int maxlen, const char *cmdline,
const char *set_arg, const char *new_val, int *posp)
{
bool found_arg = false;
const char *from;
char *to, *end;
int set_arg_len;
char empty = '\0';
int ret;
from = cmdline ?: &empty;
/* check if the value has quotes inside */
if (new_val && new_val != BOOTFLOWCL_EMPTY && strchr(new_val, '"'))
return -EBADF;
set_arg_len = strlen(set_arg);
for (to = buf, end = buf + maxlen; *from;) {
const char *val, *arg_end, *val_end, *p;
bool in_quote;
if (to >= end)
return -E2BIG;
while (*from == ' ')
from++;
if (!*from)
break;
/* find the end of this arg */
val = NULL;
arg_end = NULL;
val_end = NULL;
in_quote = false;
for (p = from;; p++) {
if (in_quote) {
if (!*p)
return -EINVAL;
if (*p == '"')
in_quote = false;
continue;
}
if (*p == '=') {
arg_end = p;
val = p + 1;
} else if (*p == '"') {
in_quote = true;
} else if (!*p || *p == ' ') {
val_end = p;
if (!arg_end)
arg_end = p;
break;
}
}
/*
* At this point val_end points to the end of the value, or the
* last char after the arg name, if there is no label.
* arg_end is the char after the arg name
* val points to the value, or NULL if there is none
* char after the value.
*
* fred=1234
* ^ ^^ ^
* from || |
* / \ \
* arg_end val val_end
*/
log_debug("from %s arg_end %ld val %ld val_end %ld\n", from,
(long)(arg_end - from), (long)(val - from),
(long)(val_end - from));
if (to != buf) {
if (to >= end)
return -E2BIG;
*to++ = ' ';
}
/* if this is the target arg, update it */
if (!strncmp(from, set_arg, arg_end - from)) {
if (!buf) {
bool has_quote = val_end[-1] == '"';
/*
* exclude any start/end quotes from
* calculations
*/
if (!val)
val = val_end;
*posp = val - cmdline + has_quote;
return val_end - val - 2 * has_quote;
}
found_arg = true;
if (!new_val) {
/* delete this arg */
from = val_end + (*val_end == ' ');
log_debug("delete from: %s\n", from);
if (to != buf)
to--; /* drop the space we added */
continue;
}
ret = copy_in(to, end, from, arg_end - from, new_val);
if (ret < 0)
return ret;
to += ret;
/* if not the target arg, copy it unchanged */
} else if (to) {
int len;
len = val_end - from;
if (to + len >= end)
return -E2BIG;
memcpy(to, from, len);
to += len;
}
from = val_end;
}
/* If we didn't find the arg, add it */
if (!found_arg) {
/* trying to delete something that is not there */
if (!new_val || !buf)
return -ENOENT;
if (to >= end)
return -E2BIG;
/* add a space to separate it from the previous arg */
if (to != buf && to[-1] != ' ')
*to++ = ' ';
ret = copy_in(to, end, set_arg, set_arg_len, new_val);
log_debug("ret=%d, to: %s buf: %s\n", ret, to, buf);
if (ret < 0)
return ret;
to += ret;
}
/* delete any trailing space */
if (to > buf && to[-1] == ' ')
to--;
if (to >= end)
return -E2BIG;
*to++ = '\0';
return to - buf;
}
int bootflow_cmdline_set_arg(struct bootflow *bflow, const char *set_arg,
const char *new_val, bool set_env)
{
char buf[2048];
char *cmd = NULL;
int ret;
ret = cmdline_set_arg(buf, sizeof(buf), bflow->cmdline, set_arg,
new_val, NULL);
if (ret < 0)
return ret;
ret = bootflow_cmdline_set(bflow, buf);
if (*buf) {
cmd = strdup(buf);
if (!cmd)
return -ENOMEM;
}
free(bflow->cmdline);
bflow->cmdline = cmd;
if (set_env) {
ret = env_set("bootargs", bflow->cmdline);
if (ret)
return ret;
}
return 0;
}
int cmdline_get_arg(const char *cmdline, const char *arg, int *posp)
{
int ret;
ret = cmdline_set_arg(NULL, 1, cmdline, arg, NULL, posp);
return ret;
}
int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg,
const char **val)
{
int ret;
int pos;
ret = cmdline_get_arg(bflow->cmdline, arg, &pos);
if (ret < 0)
return ret;
*val = bflow->cmdline + pos;
return ret;
}
int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg)
{
struct serial_device_info info;
char buf[50];
int ret;
ret = serial_getinfo(gd->cur_serial_dev, &info);
if (ret)
return ret;
*buf = '\0';
if (!strcmp("earlycon", arg)) {
snprintf(buf, sizeof(buf),
"uart8250,mmio32,%#lx,%dn8", info.addr,
info.baudrate);
} else if (!strcmp("console", arg)) {
snprintf(buf, sizeof(buf),
"ttyS0,%dn8", info.baudrate);
}
if (!*buf) {
printf("Unknown param '%s\n", arg);
return -ENOENT;
}
ret = bootflow_cmdline_set_arg(bflow, arg, buf, true);
if (ret)
return ret;
return 0;
}

View File

@ -395,7 +395,7 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
/**
* on_bootmeths() - Update the bootmeth order
*
* This will check for a valid baudrate and only apply it if valid.
* This will check for a valid list of bootmeths and only apply it if valid.
*/
static int on_bootmeths(const char *name, const char *value, enum env_op op,
int flags)

212
boot/bootmeth_cros.c Normal file
View File

@ -0,0 +1,212 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Bootmethod for ChromiumOS
*
* Copyright 2023 Google LLC
* Written by Simon Glass <sjg@chromium.org>
*/
#define LOG_CATEGORY UCLASS_BOOTSTD
#include <common.h>
#include <blk.h>
#include <bootdev.h>
#include <bootflow.h>
#include <bootmeth.h>
#include <dm.h>
#include <malloc.h>
#include <mapmem.h>
#include <part.h>
#ifdef CONFIG_X86
#include <asm/zimage.h>
#endif
#include <linux/sizes.h>
enum {
/* Offsets in the kernel-partition header */
KERN_START = 0x4f0,
KERN_SIZE = 0x518,
SETUP_OFFSET = 0x1000, /* bytes before base */
CMDLINE_OFFSET = 0x2000, /* bytes before base */
OFFSET_BASE = 0x100000, /* assumed kernel load-address */
};
static int cros_check(struct udevice *dev, struct bootflow_iter *iter)
{
/* This only works on block and network devices */
if (bootflow_iter_check_blk(iter))
return log_msg_ret("blk", -ENOTSUPP);
return 0;
}
static int copy_cmdline(const char *from, const char *uuid, char **bufp)
{
const int maxlen = 2048;
char buf[maxlen];
char *cmd, *to, *end;
int len;
/* Allow space for cmdline + UUID */
len = strnlen(from, sizeof(buf));
if (len >= maxlen)
return -E2BIG;
log_debug("uuid %d %s\n", uuid ? (int)strlen(uuid) : 0, uuid);
for (to = buf, end = buf + maxlen - UUID_STR_LEN - 1; *from; from++) {
if (to >= end)
return -E2BIG;
if (from[0] == '%' && from[1] == 'U' && uuid &&
strlen(uuid) == UUID_STR_LEN) {
strcpy(to, uuid);
to += UUID_STR_LEN;
from++;
} else {
*to++ = *from;
}
}
*to = '\0';
len = to - buf;
cmd = strdup(buf);
if (!cmd)
return -ENOMEM;
free(*bufp);
*bufp = cmd;
return 0;
}
static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
{
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
ulong base, start, size, setup, cmdline, num_blks, kern_base;
struct disk_partition info;
const char *uuid = NULL;
void *buf, *hdr;
int ret;
log_debug("starting, part=%d\n", bflow->part);
/* We consider the whole disk, not any one partition */
if (bflow->part)
return log_msg_ret("max", -ENOENT);
/* Check partition 2 */
ret = part_get_info(desc, 2, &info);
if (ret)
return log_msg_ret("part", ret);
/* Make a buffer for the header information */
num_blks = SZ_4K >> desc->log2blksz;
log_debug("Reading header, blk=%s, start=%lx, blocks=%lx\n",
bflow->blk->name, (ulong)info.start, num_blks);
hdr = memalign(SZ_1K, SZ_4K);
if (!hdr)
return log_msg_ret("hdr", -ENOMEM);
ret = blk_read(bflow->blk, info.start, num_blks, hdr);
if (ret != num_blks)
return log_msg_ret("inf", ret);
if (memcmp("CHROMEOS", hdr, 8))
return -ENOENT;
log_info("Header at %lx\n", (ulong)map_to_sysmem(hdr));
start = *(u32 *)(hdr + KERN_START);
size = ALIGN(*(u32 *)(hdr + KERN_SIZE), desc->blksz);
log_debug("Reading start %lx size %lx\n", start, size);
bflow->size = size;
buf = memalign(SZ_1K, size);
if (!buf)
return log_msg_ret("buf", -ENOMEM);
num_blks = size >> desc->log2blksz;
log_debug("Reading data, blk=%s, start=%lx, blocks=%lx\n",
bflow->blk->name, (ulong)info.start, num_blks);
ret = blk_read(bflow->blk, (ulong)info.start + 0x80, num_blks, buf);
if (ret != num_blks)
return log_msg_ret("inf", ret);
base = map_to_sysmem(buf);
setup = base + start - OFFSET_BASE - SETUP_OFFSET;
cmdline = base + start - OFFSET_BASE - CMDLINE_OFFSET;
kern_base = base + start - OFFSET_BASE + SZ_16K;
log_debug("base %lx setup %lx, cmdline %lx, kern_base %lx\n", base,
setup, cmdline, kern_base);
#ifdef CONFIG_X86
const char *version;
version = zimage_get_kernel_version(map_sysmem(setup, 0),
map_sysmem(kern_base, 0));
log_debug("version %s\n", version);
if (version)
bflow->name = strdup(version);
#endif
if (!bflow->name)
bflow->name = strdup("ChromeOS");
if (!bflow->name)
return log_msg_ret("nam", -ENOMEM);
bflow->os_name = strdup("ChromeOS");
if (!bflow->os_name)
return log_msg_ret("os", -ENOMEM);
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
uuid = info.uuid;
#endif
ret = copy_cmdline(map_sysmem(cmdline, 0), uuid, &bflow->cmdline);
if (ret)
return log_msg_ret("cmd", ret);
bflow->state = BOOTFLOWST_READY;
bflow->buf = buf;
bflow->x86_setup = map_sysmem(setup, 0);
return 0;
}
static int cros_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr, ulong *sizep)
{
return -ENOSYS;
}
static int cros_boot(struct udevice *dev, struct bootflow *bflow)
{
#ifdef CONFIG_X86
zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0,
map_to_sysmem(bflow->x86_setup),
bflow->cmdline);
#endif
return log_msg_ret("go", -EFAULT);
}
static int cros_bootmeth_bind(struct udevice *dev)
{
struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
plat->desc = "ChromiumOS boot";
return 0;
}
static struct bootmeth_ops cros_bootmeth_ops = {
.check = cros_check,
.read_bootflow = cros_read_bootflow,
.read_file = cros_read_file,
.boot = cros_boot,
};
static const struct udevice_id cros_bootmeth_ids[] = {
{ .compatible = "u-boot,cros" },
{ }
};
U_BOOT_DRIVER(bootmeth_cros) = {
.name = "bootmeth_cros",
.id = UCLASS_BOOTMETH,
.of_match = cros_bootmeth_ids,
.ops = &cros_bootmeth_ops,
.bind = cros_bootmeth_bind,
};

View File

@ -76,7 +76,7 @@ static int qfw_bootmeth_bind(struct udevice *dev)
{
struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
plat->desc = "Sandbox boot for testing";
plat->desc = "QEMU boot using firmware interface";
return 0;
}

View File

@ -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

View File

@ -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));

View File

@ -13,6 +13,7 @@
#include <lmb.h>
#include <mapmem.h>
#include <net.h>
#include <serial.h>
#include <video.h>
#include <vsprintf.h>
#include <asm/cache.h>
@ -113,6 +114,25 @@ static void show_video_info(void)
}
}
static void print_serial(struct udevice *dev)
{
struct serial_device_info info;
int ret;
if (!dev || !IS_ENABLED(CONFIG_DM_SERIAL))
return;
ret = serial_getinfo(dev, &info);
if (ret)
return;
bdinfo_print_num_l("serial addr", info.addr);
bdinfo_print_num_l(" width", info.reg_width);
bdinfo_print_num_l(" shift", info.reg_shift);
bdinfo_print_num_l(" offset", info.reg_offset);
bdinfo_print_num_l(" clock", info.clock);
}
int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct bd_info *bd = gd->bd;
@ -151,6 +171,13 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
if (IS_ENABLED(CONFIG_OF_REAL))
printf("devicetree = %s\n", fdtdec_get_srcname());
}
print_serial(gd->cur_serial_dev);
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();

View File

@ -288,6 +288,12 @@ static int do_bootflow_select(struct cmd_tbl *cmdtp, int flag, int argc,
return CMD_RET_FAILURE;
}
std->cur_bootflow = found;
if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
if (env_set("bootargs", found->cmdline)) {
printf("Cannot set bootargs\n");
return CMD_RET_FAILURE;
}
}
return 0;
}
@ -324,6 +330,14 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
printf("Buffer: %lx\n", (ulong)map_to_sysmem(bflow->buf));
printf("Size: %x (%d bytes)\n", bflow->size, bflow->size);
printf("OS: %s\n", bflow->os_name ? bflow->os_name : "(none)");
printf("Cmdline: ");
if (bflow->cmdline)
puts(bflow->cmdline);
else
puts("(none)");
putc('\n');
if (bflow->x86_setup)
printf("X86 setup: %p\n", bflow->x86_setup);
printf("Logo: %s\n", bflow->logo ?
simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)");
if (bflow->logo) {
@ -417,6 +431,75 @@ static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc,
return 0;
}
static int do_bootflow_cmdline(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
struct bootstd_priv *std;
struct bootflow *bflow;
const char *op, *arg, *val = NULL;
int ret;
if (argc < 3)
return CMD_RET_USAGE;
ret = bootstd_get_priv(&std);
if (ret)
return CMD_RET_FAILURE;
bflow = std->cur_bootflow;
if (!bflow) {
printf("No bootflow selected\n");
return CMD_RET_FAILURE;
}
op = argv[1];
arg = argv[2];
if (*op == 's') {
if (argc < 4)
return CMD_RET_USAGE;
val = argv[3];
}
switch (*op) {
case 'c': /* clear */
val = "";
fallthrough;
case 's': /* set */
case 'd': /* delete */
ret = bootflow_cmdline_set_arg(bflow, arg, val, true);
break;
case 'g': /* get */
ret = bootflow_cmdline_get_arg(bflow, arg, &val);
if (ret >= 0)
printf("%.*s\n", ret, val);
break;
case 'a': /* auto */
ret = bootflow_cmdline_auto(bflow, arg);
break;
}
switch (ret) {
case -E2BIG:
printf("Argument too long\n");
break;
case -ENOENT:
printf("Argument not found\n");
break;
case -EINVAL:
printf("Mismatched quotes\n");
break;
case -EBADF:
printf("Value must be quoted\n");
break;
default:
if (ret < 0)
printf("Unknown error: %dE\n", ret);
}
if (ret < 0)
return CMD_RET_FAILURE;
return 0;
}
#endif /* CONFIG_CMD_BOOTFLOW_FULL */
#ifdef CONFIG_SYS_LONGHELP
@ -427,7 +510,8 @@ static char bootflow_help_text[] =
"bootflow select [<num>|<name>] - select a bootflow\n"
"bootflow info [-d] - show info on current bootflow (-d dump bootflow)\n"
"bootflow boot - boot current bootflow (or first available if none selected)\n"
"bootflow menu [-t] - show a menu of available bootflows";
"bootflow menu [-t] - show a menu of available bootflows\n"
"bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] - update cmdline";
#else
"scan - boot first available bootflow\n";
#endif
@ -441,5 +525,6 @@ U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text,
U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info),
U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot),
U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu),
U_BOOT_SUBCMD_MKENT(cmdline, 4, 1, do_bootflow_cmdline),
#endif
);

View File

@ -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"
);

View File

@ -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;

View File

@ -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;
}
@ -146,7 +94,7 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc,
if (!first)
printf("\n");
printf("CPU %d:\n", i);
ret = do_mtrr_list(reg_count, i);
ret = mtrr_list(reg_count, i);
if (ret) {
printf("Failed to read CPU %s (err=%d)\n",
i < MP_SELECT_ALL ? simple_itoa(i) : "",

View File

@ -51,6 +51,7 @@ static struct tag_name {
/* BLOBLISTT_PROJECT_AREA */
{ BLOBLISTT_U_BOOT_SPL_HANDOFF, "SPL hand-off" },
{ BLOBLISTT_U_BOOT_VIDEO, "SPL video handoff" },
/* BLOBLISTT_VENDOR_AREA */
};

View File

@ -729,8 +729,7 @@ static int fix_fdt(void)
#endif
/* ARM calls relocate_code from its crt0.S */
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!CONFIG_IS_ENABLED(X86_64)
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
static int jump_to_copy(void)
{
@ -752,7 +751,11 @@ static int jump_to_copy(void)
* (CPU cache)
*/
arch_setup_gd(gd->new_gd);
board_init_f_r_trampoline(gd->start_addr_sp);
# if CONFIG_IS_ENABLED(X86_64)
board_init_f_r_trampoline64(gd->new_gd, gd->start_addr_sp);
# else
board_init_f_r_trampoline(gd->start_addr_sp);
# endif
#else
relocate_code(gd->start_addr_sp, gd->new_gd, gd->relocaddr);
#endif
@ -967,8 +970,7 @@ static const init_fnc_t init_sequence_f[] = {
* watchdog device is not serviced is as small as possible.
*/
cyclic_unregister_all,
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!CONFIG_IS_ENABLED(X86_64)
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
jump_to_copy,
#endif
NULL,

View File

@ -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;
}

View File

@ -437,7 +437,7 @@ int log_init(void)
/*
* We cannot add runtime data to the driver since it is likely stored
* in rodata. Instead, set up a 'device' corresponding to each driver.
* We only support having a single device.
* We only support having a single device for each driver.
*/
INIT_LIST_HEAD((struct list_head *)&gd->log_head);
while (drv < end) {

View File

@ -37,8 +37,14 @@ static int log_console_emit(struct log_device *ldev, struct log_rec *rec)
printf("%s:", rec->file);
if (fmt & BIT(LOGF_LINE))
printf("%d-", rec->line);
if (fmt & BIT(LOGF_FUNC))
printf("%*s()", CONFIG_LOGF_FUNC_PAD, rec->func);
if (fmt & BIT(LOGF_FUNC)) {
if (CONFIG_IS_ENABLED(USE_TINY_PRINTF)) {
printf("%s()", rec->func);
} else {
printf("%*s()", CONFIG_LOGF_FUNC_PAD,
rec->func);
}
}
}
if (fmt & BIT(LOGF_MSG))
printf("%s%s", add_space ? " " : "", rec->msg);

View File

@ -1,5 +1,6 @@
CONFIG_X86=y
CONFIG_TEXT_BASE=0x1110000
CONFIG_SYS_MALLOC_LEN=0x2000000
CONFIG_SYS_MALLOC_F_LEN=0x3d00
CONFIG_NR_DRAM_BANKS=8
CONFIG_MAX_CPUS=8
@ -22,6 +23,7 @@ CONFIG_X86_OFFSET_U_BOOT=0xffd00000
CONFIG_X86_OFFSET_SPL=0xffe80000
CONFIG_INTEL_ACPIGEN=y
CONFIG_INTEL_GENERIC_WIFI=y
CONFIG_BOOTSTD_FULL=y
CONFIG_SYS_MONITOR_BASE=0x01110000
CONFIG_CHROMEOS=y
CONFIG_BOOTSTAGE=y
@ -33,8 +35,10 @@ CONFIG_BOOTSTAGE_STASH=y
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS_SUBST=y
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="tpm init; tpm startup TPM2_SU_CLEAR; read mmc 0:2 100000 0 80; setexpr loader *001004f0; setexpr size *00100518; setexpr blocks $size / 200; read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; setexpr cmdline_ptr $loader - 2000; setexpr.s cmdline *$cmdline_ptr; setexpr cmdline gsub %U \\\\${uuid}; if part uuid mmc 0:2 uuid; then zboot start 100000 0 0 0 $setup cmdline; zboot load; zboot setup; zboot dump; zboot go;fi"
CONFIG_BOOTCOMMAND="tpm init; tpm startup TPM2_SU_CLEAR; bootflow scan -lb"
CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_LOG=y
CONFIG_LOGF_FUNC=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_BLOBLIST=y
@ -52,9 +56,11 @@ CONFIG_SPL_POWER=y
CONFIG_TPL_SYS_MALLOC_SIMPLE=y
CONFIG_TPL_POWER=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=532
CONFIG_SYS_CBSIZE=1024
CONFIG_SYS_PBSIZE=1024
CONFIG_CMD_CPU=y
CONFIG_CMD_PMC=y
CONFIG_CMD_MEM_SEARCH=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_PART=y

View File

@ -1,5 +1,6 @@
CONFIG_X86=y
CONFIG_TEXT_BASE=0x1110000
CONFIG_SYS_MALLOC_LEN=0x2000000
CONFIG_NR_DRAM_BANKS=8
CONFIG_ENV_SIZE=0x1000
CONFIG_DEFAULT_DEVICE_TREE="coreboot"
@ -8,12 +9,11 @@ CONFIG_VENDOR_COREBOOT=y
CONFIG_TARGET_COREBOOT=y
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_BOOTSTD_FULL=y
CONFIG_SYS_MONITOR_BASE=0x01110000
CONFIG_SHOW_BOOT_PROGRESS=y
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro"
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000"
CONFIG_PRE_CONSOLE_BUFFER=y
CONFIG_SYS_CONSOLE_INFO_QUIET=y
CONFIG_LOG=y
@ -23,9 +23,6 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_LAST_STAGE_INIT=y
CONFIG_PCI_INIT_R=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=532
CONFIG_CMD_MEM_SEARCH=y
CONFIG_CMD_IDE=y
CONFIG_CMD_MMC=y
CONFIG_CMD_PART=y
CONFIG_CMD_USB=y
@ -52,13 +49,6 @@ CONFIG_USE_ROOTPATH=y
CONFIG_REGMAP=y
CONFIG_SYSCON=y
# CONFIG_ACPIGEN is not set
CONFIG_SYS_IDE_MAXDEVICE=4
CONFIG_SYS_ATA_DATA_OFFSET=0
CONFIG_SYS_ATA_REG_OFFSET=0
CONFIG_SYS_ATA_ALT_OFFSET=0
CONFIG_ATAPI=y
CONFIG_LBA48=y
CONFIG_SYS_64BIT_LBA=y
CONFIG_NVME_PCI=y
# CONFIG_PCI_PNP is not set
CONFIG_SOUND=y

View File

@ -6,30 +6,39 @@ CONFIG_ENV_SIZE=0x40000
CONFIG_MAX_CPUS=2
CONFIG_SPL_DM_SPI=y
CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx"
CONFIG_SPL_TEXT_BASE=0xfffd0000
CONFIG_SPL_TEXT_BASE=0xfffd8000
CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000
CONFIG_DEBUG_UART_BASE=0x3f8
CONFIG_DEBUG_UART_CLOCK=1843200
CONFIG_X86_RUN_64BIT=y
CONFIG_TARGET_QEMU_X86_64=y
CONFIG_DEBUG_UART=y
# CONFIG_HAVE_MICROCODE is not set
CONFIG_SMP=y
CONFIG_GENERATE_PIRQ_TABLE=y
CONFIG_GENERATE_MP_TABLE=y
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_BOOTSTD_DEFAULTS=y
CONFIG_BOOTSTAGE=y
CONFIG_BOOTSTAGE_REPORT=y
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
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
@ -42,11 +51,13 @@ CONFIG_SYS_PBSIZE=532
CONFIG_CMD_CPU=y
CONFIG_CMD_BOOTEFI_SELFTEST=y
CONFIG_CMD_NVEDIT_EFI=y
CONFIG_CMD_MEM_SEARCH=y
CONFIG_CMD_IDE=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_BOOTFILESIZE=y
CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_TIME=y
CONFIG_CMD_QFW=y
CONFIG_CMD_BOOTSTAGE=y
@ -68,13 +79,13 @@ 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_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

View File

@ -9,7 +9,7 @@ CONFIG_SMP=y
CONFIG_GENERATE_PIRQ_TABLE=y
CONFIG_GENERATE_MP_TABLE=y
CONFIG_FIT=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_BOOTSTD_DEFAULTS=y
CONFIG_BOOTSTAGE=y
CONFIG_BOOTSTAGE_REPORT=y
CONFIG_SHOW_BOOT_PROGRESS=y
@ -53,9 +53,6 @@ CONFIG_NVME_PCI=y
CONFIG_SYS_NS16550_PORT_MAPPED=y
CONFIG_SPI=y
CONFIG_USB_KEYBOARD=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_FRAMEBUFFER_VESA_MODE_USER=y
CONFIG_FRAMEBUFFER_VESA_MODE=0x144
CONFIG_CONSOLE_SCROLL_LINES=5
CONFIG_GENERATE_ACPI_TABLE=y
# CONFIG_GZIP is not set

View File

@ -10,6 +10,7 @@ CONFIG_FIT=y
CONFIG_TIMESTAMP=y
CONFIG_FIT_SIGNATURE=y
# CONFIG_BOOTSTD_FULL is not set
# CONFIG_BOOTMETH_CROS is not set
# CONFIG_BOOTMETH_VBE is not set
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="run distro_bootcmd"

View File

@ -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;

View File

@ -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 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

View File

@ -13,7 +13,7 @@ Synopis
bootflow select [<num|name>]
bootflow info [-d]
bootflow boot
bootflow cmdline [set|get|clear|delete|auto] <param> [<value>]
Description
-----------
@ -198,6 +198,36 @@ bootflow boot
This boots the current bootflow.
bootflow cmdline
~~~~~~~~~~~~~~~~
Some bootmeths can obtain the OS command line since it is stored with the OS.
In that case, you can use `bootflow cmdline` to adjust this. The command line
is assumed to be in the format used by Linux, i.e. a space-separated set of
parameters with optional values, e.g. "noinitrd console=/dev/tty0".
To change or add a parameter, use::
bootflow cmdline set <param> <value>
To clear a parameter value to empty you can use "" for the value, or use::
bootflow cmdline clear <param>
To delete a parameter entirely, use::
bootflow cmdline delete <param>
Automatic parameters are available in a very few cases. You can use these to
add parmeters where the value is known by U-Boot. For example::
bootflow cmdline auto earlycon
bootflow cmdline auto console
can be used to set the early console (or console) to a suitable value so that
output appears on the serial port. This is only supported by the 16550 serial
driver so far.
Example
-------
@ -258,7 +288,6 @@ displayed and booted::
Name: mmc@7e202000.bootdev.part_2
Device: mmc@7e202000.bootdev
Block dev: mmc@7e202000.blk
Sequence: 1
Method: distro
State: ready
Partition: 2
@ -266,6 +295,10 @@ displayed and booted::
Filename: extlinux/extlinux.conf
Buffer: 3db7ae88
Size: 232 (562 bytes)
OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
Cmdline: (none)
Logo: (none)
FDT: <NULL>
Error: 0
U-Boot> bootflow boot
** Booting bootflow 'smsc95xx_eth.bootdev.0'
@ -427,6 +460,69 @@ Here is am example using the -e flag to see all errors::
(21 bootflows, 2 valid)
U-Boot>
Here is an example of booting ChromeOS, adjusting the console beforehand. Note that
the cmdline is word-wrapped here and some parts of the command line are elided::
=> bootfl list
Showing all bootflows
Seq Method State Uclass Part Name Filename
--- ----------- ------ -------- ---- ------------------------ ----------------
0 cros ready nvme 0 5.10.153-20434-g98da1eb2c <NULL>
1 efi ready nvme c nvme#0.blk#1.bootdev.part efi/boot/bootia32.efi
2 efi ready usb_mass_ 2 usb_mass_storage.lun0.boo efi/boot/bootia32.efi
--- ----------- ------ -------- ---- ------------------------ ----------------
(3 bootflows, 3 valid)
=> bootfl sel 0
=> bootfl inf
Name: 5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023
Device: nvme#0.blk#1.bootdev
Block dev: nvme#0.blk#1
Method: cros
State: ready
Partition: 0
Subdir: (none)
Filename: <NULL>
Buffer: 737a1400
Size: c47000 (12873728 bytes)
OS: ChromeOS
Cmdline: console= loglevel=7 init=/sbin/init cros_secure drm.trace=0x106
root=/dev/dm-0 rootwait ro dm_verity.error_behavior=3
dm_verity.max_bios=-1 dm_verity.dev_wait=1
dm="1 vroot none ro 1,0 6348800
verity payload=PARTUUID=799c935b-ae62-d143-8493-816fa936eef7/PARTNROFF=1
hashtree=PARTUUID=799c935b-ae62-d143-8493-816fa936eef7/PARTNROFF=1
hashstart=6348800 alg=sha256
root_hexdigest=78cc462cd45aecbcd49ca476587b4dee59aa1b00ba5ece58e2c29ec9acd914ab
salt=8dec4dc80a75dd834a9b3175c674405e15b16a253fdfe05c79394ae5fd76f66a"
noinitrd vt.global_cursor_default=0
kern_guid=799c935b-ae62-d143-8493-816fa936eef7 add_efi_memmap boot=local
noresume noswap i915.modeset=1 ramoops.ecc=1 tpm_tis.force=0
intel_pmc_core.warn_on_s0ix_failures=1 i915.enable_guc=3 i915.enable_dc=4
xdomain=0 swiotlb=65536 intel_iommu=on i915.enable_psr=1
usb-storage.quirks=13fe:6500:u
X86 setup: 742e3400
Logo: (none)
FDT: <NULL>
Error: 0
=> bootflow cmdline auto earlycon
=> bootflow cmd auto console
=> print bootargs
bootargs=console=ttyS0,115200n8 loglevel=7 ...
usb-storage.quirks=13fe:6500:u earlycon=uart8250,mmio32,0xfe03e000,115200n8
=> bootflow cmd del console
=> print bootargs
bootargs=loglevel=7 ... earlycon=uart8250,mmio32,0xfe03e000,115200n8
=> bootfl boot
** Booting bootflow '5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023' with cros
Kernel command line: "loglevel=7 ... earlycon=uart8250,mmio32,0xfe03e000,115200n8"
Starting kernel ...
[ 0.000000] Linux version 5.10.153-20434-g98da1eb2cf9d (chrome-bot@chromeos-release-builder-us-central1-b-x32-12-xijx) (Chromium OS 15.0_pre465103_p20220825-r4 clang version 15.0.0 (/var/tmp/portage/sys-devel/llvm-15.0_pre465103_p20220825-r4/work/llvm-15.0_pre465103_p20220825/clang db1978b67431ca3462ad8935bf662c15750b8252), LLD 15.0.0) #1 SMP PREEMPT Tue Jan 24 19:38:23 PST 2023
[ 0.000000] Command line: loglevel=7 ... usb-storage.quirks=13fe:6500:u earlycon=uart8250,mmio32,0xfe03e000,115200n8
[ 0.000000] x86/split lock detection: warning about user-space split_locks
Return value
------------

151
doc/usage/cmd/mtrr.rst Normal file
View File

@ -0,0 +1,151 @@
.. SPDX-License-Identifier: GPL-2.0+:
mtrr command
============
Synopis
-------
mtrr [list]
mtrr set <reg> <type> <start> <size>
mtrr disable <reg>
mtrr enable
Description
-----------
The *mtrr* command is used to dump the Memory Type Range Registers (MTRRs) on
an x86 machine. These register control cache behaviour in selected memory
ranges.
Note that the number of registers can vary between CPUs.
mtrr [list]
~~~~~~~~~~~
List the MTRRs. The table shows the following information:
Reg
Register number (the first is register 0)
Valid
Shows Y if the register is valid (has bit 11 set), N if not
Write-type
Shows the behaviour when writing to the memory region. The types are
abbreviated to fit a reasonable line length. Valid types shown below.
====== ============== ====================================================
Value Type Meaning
====== ============== ====================================================
0 Uncacheable Skip cache and write directly to memory
1 Combine Multiple writes can be combined into one transaction
4 Through Update cache and also write to memory
5 Protect Writes are prohibited
6 Back Update cache but don't write to memory
====== ============== ====================================================
Base
Base memory address from which the register controls behaviour
Mask
Mask value, which also indicates the size
Size
Length of memory region within which the register controls behaviour
mtrr set
~~~~~~~~
This sets the value of a particular MTRR. Parameters are:
reg
Register number to set, with 0 being the first
type
Access type to set. See Write-type above for valid types. This uses the name
rather than its numeric value.
start
Base memory address from which the register should control behaviour
size
Length of memory region within which the register controls behaviour
mtrr disable
~~~~~~~~~~~~
This disables a particular register, by clearing its `valid` bit (11).
mtrr enable
~~~~~~~~~~~
This enables a particular register, by setting its `valid` bit (11).
Example
-------
This shows disabling and enabling an MTRR, as well as setting its type::
=> mtrr
CPU 0:
Reg Valid Write-type Base || Mask || Size ||
0 Y Back 0000000000000000 0000000f80000000 0000000080000000
1 Y Back 0000000080000000 0000000fe0000000 0000000020000000
2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000
3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000
4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000
5 Y Combine 00000000d0000000 0000000ff0000000 0000000010000000
6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
=> mtrr d 5
=> mtrr
CPU 0:
Reg Valid Write-type Base || Mask || Size ||
0 Y Back 0000000000000000 0000000f80000000 0000000080000000
1 Y Back 0000000080000000 0000000fe0000000 0000000020000000
2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000
3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000
4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000
5 N Combine 00000000d0000000 0000000ff0000000 0000000010000000
6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
=> mtrr e 5
=> mtrr
CPU 0:
Reg Valid Write-type Base || Mask || Size ||
0 Y Back 0000000000000000 0000000f80000000 0000000080000000
1 Y Back 0000000080000000 0000000fe0000000 0000000020000000
2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000
3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000
4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000
5 Y Combine 00000000d0000000 0000000ff0000000 0000000010000000
6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
=> mtrr set 5 Uncacheable d0000000 10000000
=> mtrr
CPU 0:
Reg Valid Write-type Base || Mask || Size ||
0 Y Back 0000000000000000 0000000f80000000 0000000080000000
1 Y Back 0000000080000000 0000000fe0000000 0000000020000000
2 Y Back 00000000a0000000 0000000ff0000000 0000000010000000
3 Y Uncacheable 00000000ad000000 0000000fff000000 0000000001000000
4 Y Uncacheable 00000000ae000000 0000000ffe000000 0000000002000000
5 Y Uncacheable 00000000d0000000 0000000ff0000000 0000000010000000
6 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
7 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
8 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
9 N Uncacheable 0000000000000000 0000000000000000 0000001000000000
=>

View File

@ -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
------------

View File

@ -41,18 +41,21 @@ QEMU firmware files are listed via the *qfw list* command:
::
=> qfw list
etc/boot-fail-wait
etc/smbios/smbios-tables
etc/smbios/smbios-anchor
etc/e820
genroms/kvmvapic.bin
genroms/linuxboot.bin
etc/system-states
etc/acpi/tables
etc/table-loader
etc/tpm/log
etc/acpi/rsdp
bootorder
00000000 bios-geometry
00000000 bootorder
000f0060 etc/acpi/rsdp
bed14040 etc/acpi/tables
00000000 etc/boot-fail-wait
00000000 etc/e820
00000000 etc/smbios/smbios-anchor
00000000 etc/smbios/smbios-tables
00000000 etc/system-states
00000000 etc/table-loader
00000000 etc/tpm/log
00000000 genroms/kvmvapic.bin
Where an address is shown, it indicates where the data is available for
inspection, e.g. using the :doc:`md`.
The available CPUs can be shown via the *qfw cpus* command:

View File

@ -76,6 +76,7 @@ Shell commands
cmd/md
cmd/mmc
cmd/mtest
cmd/mtrr
cmd/panic
cmd/part
cmd/pause

View File

@ -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"

View File

@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0+
obj-$(CONFIG_$(SPL_TPL_)BIOSEMU) += bios_emulator/
obj-$(CONFIG_$(SPL_TPL_)BLK) += block/
obj-$(CONFIG_$(SPL_TPL_)BOOTCOUNT_LIMIT) += bootcount/
obj-$(CONFIG_$(SPL_TPL_)BUTTON) += button/
@ -80,7 +81,6 @@ ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
obj-y += adc/
obj-y += ata/
obj-$(CONFIG_DM_DEMO) += demo/
obj-$(CONFIG_BIOSEMU) += bios_emulator/
obj-y += block/
obj-y += cache/
obj-$(CONFIG_CPU) += cpu/

View File

@ -0,0 +1,10 @@
config BIOSEMU
bool
select X86EMU_RAW_IO
config SPL_BIOSEMU
bool
select X86EMU_RAW_IO
config X86EMU_RAW_IO
bool

View File

@ -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 --------------------------*/

View File

@ -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];

View File

@ -26,6 +26,8 @@
* reserved or subject to arcane restrictions.
*/
#define LOG_CATEGORY UCLASS_GPIO
#include <common.h>
#include <dm.h>
#include <errno.h>
@ -155,8 +157,7 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset,
*/
tmplong = inl(bank->use_sel);
if (!(tmplong & (1UL << offset))) {
debug("%s: gpio %d is reserved for internal use\n", __func__,
offset);
log_debug("gpio %d is reserved for internal use\n", offset);
return -EPERM;
}

View File

@ -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)
/*
@ -64,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 {
@ -188,6 +194,10 @@ ulong write_acpi_tables(ulong addr)
return addr;
}
/* QFW always puts tables at high addresses */
gd->arch.table_start_high = (ulong)table_loader;
gd->arch.table_end_high = (ulong)table_loader;
qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
for (i = 0; i < (size / sizeof(*entry)); i++) {
@ -227,6 +237,9 @@ out:
}
free(table_loader);
gd_set_acpi_start(acpi_get_rsdp_addr());
return addr;
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Bootdevice for MMC
* Bootdev for MMC
*
* Copyright 2021 Google LLC
* Written by Simon Glass <sjg@chromium.org>

View File

@ -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);

View File

@ -3,6 +3,8 @@
* Copyright (C) 2014 Google, Inc
*/
#define LOG_CATEGORY UCLASS_PCH
#include <common.h>
#include <dm.h>
#include <log.h>
@ -38,7 +40,7 @@ static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep)
*/
dm_pci_read_config32(dev, GPIO_BASE, &base);
if (base == 0x00000000 || base == 0xffffffff) {
debug("%s: unexpected BASE value\n", __func__);
log_debug("unexpected BASE value\n");
return -ENODEV;
}
@ -59,7 +61,7 @@ static int pch9_get_io_base(struct udevice *dev, u32 *iobasep)
dm_pci_read_config32(dev, IO_BASE, &base);
if (base == 0x00000000 || base == 0xffffffff) {
debug("%s: unexpected BASE value\n", __func__);
log_debug("unexpected BASE value\n");
return -ENODEV;
}

View File

@ -44,8 +44,13 @@ config SPL_PCI_PNP
bool "Enable Plug & Play support for PCI"
help
Enable PCI memory and I/O space resource allocation and assignment.
This is required to auto configure the enumerated devices.
This is normally not done in SPL, but can be enabled if devices must
be set up in the SPL phase. Often it is enough to manually configure
one device, so this option can be disabled.
config PCI_REGION_MULTI_ENTRY
bool "Enable Multiple entries of region type MEMORY in ranges for PCI"
help

View File

@ -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;

View File

@ -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>
@ -91,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,
@ -254,14 +257,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;
}
@ -269,7 +274,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
defined(CONFIG_FRAMEBUFFER_VESA_MODE)
vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE;
#endif
debug("Selected vesa mode %#x\n", vesa_mode);
debug("Selected vesa mode 0x%x\n", vesa_mode);
if (exec_method & PCI_ROM_USE_NATIVE) {
#ifdef CONFIG_X86
@ -296,27 +301,31 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void),
}
if (emulate) {
#ifdef CONFIG_BIOSEMU
BE_VGAInfo *info;
if (CONFIG_IS_ENABLED(BIOSEMU)) {
BE_VGAInfo *info;
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);
if (ret)
goto err;
#endif
log_debug("Running video BIOS with emulator...");
ret = biosemu_setup(dev, &info);
if (ret)
goto err;
biosemu_set_interrupt_handler(0x15, int15_handler);
ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info,
true, vesa_mode, &mode_info);
log_debug("done\n");
if (ret)
goto err;
}
} else {
#if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL)
log_debug("Running video BIOS...");
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);
debug("Final vesa mode %x\n", mode_info.video_mode);
ret = 0;
err:
@ -368,34 +377,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;
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Bootdevice for USB
* Bootdev for SCSI
*
* Copyright 2021 Google LLC
* Written by Simon Glass <sjg@chromium.org>

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Bootdevice for USB
* Bootdev for USB
*
* Copyright 2021 Google LLC
* Written by Simon Glass <sjg@chromium.org>

View File

@ -278,6 +278,36 @@ config VIDCONSOLE_AS_NAME
possible to update the environment, the breakage may be confusing for
users. This option will be removed around the end of 2020.
config VIDEO_BOCHS
bool "Enable Bochs video emulation for QEMU"
depends on X86
help
Enable this to use the Bochs video support provided in the QEMU
emulator. This appears as a PCI device which U-Boot can set up to
provide a frame buffer.
if VIDEO_BOCHS
config VIDEO_BOCHS_SIZE_X
int "Width of display (X resolution)"
default 1280
help
Sets the width of the display.
These two options control the size of the display set up by QEMU.
Typical sizes are 1024 x 768 or 1280 x 1024.
config VIDEO_BOCHS_SIZE_Y
int "High of display (Y resolution)"
default 1024
help
Sets the height of the display.
These two options control the size of the display set up by QEMU.
Typical sizes are 1024 x 768 or 1280 x 1024.
endif
config VIDEO_COREBOOT
bool "Enable coreboot framebuffer driver support"
depends on X86

View File

@ -45,6 +45,7 @@ obj-$(CONFIG_OSD) += video_osd-uclass.o
obj-$(CONFIG_SANDBOX_OSD) += sandbox_osd.o
obj-$(CONFIG_VIDEO_ARM_MALIDP) += mali_dp.o
obj-$(CONFIG_VIDEO_BCM2835) += bcm2835.o
obj-$(CONFIG_VIDEO_BOCHS) += bochs.o
obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o
obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o
obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o

123
drivers/video/bochs.c Normal file
View File

@ -0,0 +1,123 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Modified from coreboot bochs.c
*/
#define LOG_CATEGORY UCLASS_VIDEO
#include <common.h>
#include <dm.h>
#include <log.h>
#include <pci.h>
#include <video.h>
#include <asm/io.h>
#include <asm/mtrr.h>
#include <linux/sizes.h>
#include "bochs.h"
static int xsize = CONFIG_VIDEO_BOCHS_SIZE_X;
static int ysize = CONFIG_VIDEO_BOCHS_SIZE_Y;
static void bochs_write(void *mmio, int index, int val)
{
writew(val, mmio + MMIO_BASE + index * 2);
}
static int bochs_read(void *mmio, int index)
{
return readw(mmio + MMIO_BASE + index * 2);
}
static void bochs_vga_write(int index, uint8_t val)
{
outb(val, VGA_INDEX);
}
static int bochs_init_fb(struct udevice *dev)
{
struct video_uc_plat *plat = dev_get_uclass_plat(dev);
struct video_priv *uc_priv = dev_get_uclass_priv(dev);
ulong fb;
void *mmio;
int id, mem;
log_debug("probing %s at PCI %x\n", dev->name, dm_pci_get_bdf(dev));
fb = dm_pci_read_bar32(dev, 0);
if (!fb)
return log_msg_ret("fb", -EIO);
/* MMIO bar supported since qemu 3.0+ */
mmio = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_TYPE,
PCI_REGION_MEM);
if (!mmio)
return log_msg_ret("map", -EIO);
/* bochs dispi detection */
id = bochs_read(mmio, INDEX_ID);
if ((id & 0xfff0) != ID0) {
log_debug("ID mismatch\n");
return -EPROTONOSUPPORT;
}
mem = bochs_read(mmio, INDEX_VIDEO_MEMORY_64K) * SZ_64K;
log_debug("QEMU VGA: bochs @ %p: %d MiB FB at %lx\n", mmio, mem / SZ_1M,
fb);
uc_priv->xsize = xsize;
uc_priv->ysize = ysize;
uc_priv->bpix = VIDEO_BPP32;
/* setup video mode */
bochs_write(mmio, INDEX_ENABLE, 0);
bochs_write(mmio, INDEX_BANK, 0);
bochs_write(mmio, INDEX_BPP, VNBITS(uc_priv->bpix));
bochs_write(mmio, INDEX_XRES, xsize);
bochs_write(mmio, INDEX_YRES, ysize);
bochs_write(mmio, INDEX_VIRT_WIDTH, xsize);
bochs_write(mmio, INDEX_VIRT_HEIGHT, ysize);
bochs_write(mmio, INDEX_X_OFFSET, 0);
bochs_write(mmio, INDEX_Y_OFFSET, 0);
bochs_write(mmio, INDEX_ENABLE, ENABLED | LFB_ENABLED);
bochs_vga_write(0, 0x20); /* disable blanking */
plat->base = fb;
return 0;
}
static int bochs_video_probe(struct udevice *dev)
{
int ret;
ret = bochs_init_fb(dev);
if (ret)
return log_ret(ret);
return 0;
}
static int bochs_video_bind(struct udevice *dev)
{
struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev);
/* Set the maximum supported resolution */
uc_plat->size = 2560 * 1600 * 4;
log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size);
return 0;
}
U_BOOT_DRIVER(bochs_video) = {
.name = "bochs_video",
.id = UCLASS_VIDEO,
.bind = bochs_video_bind,
.probe = bochs_video_probe,
};
static struct pci_device_id bochs_video_supported[] = {
{ PCI_DEVICE(0x1234, 0x1111) },
{ },
};
U_BOOT_PCI_DEVICE(bochs_video, bochs_video_supported);

36
drivers/video/bochs.h Normal file
View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Modified from coreboot bochs.c
*/
#ifndef __BOCHS_H
#define __BOCHS_H
#define VGA_INDEX 0x3c0
#define IOPORT_INDEX 0x01ce
#define IOPORT_DATA 0x01cf
enum {
INDEX_ID,
INDEX_XRES,
INDEX_YRES,
INDEX_BPP,
INDEX_ENABLE,
INDEX_BANK,
INDEX_VIRT_WIDTH,
INDEX_VIRT_HEIGHT,
INDEX_X_OFFSET,
INDEX_Y_OFFSET,
INDEX_VIDEO_MEMORY_64K
};
#define ID0 0xb0c0
#define ENABLED BIT(0)
#define LFB_ENABLED BIT(6)
#define NOCLEARMEM BIT(7)
#define MMIO_BASE 0x500
#endif

View File

@ -8,6 +8,8 @@
* 2003-03-10 - kharris@nexus-tech.net - ported to uboot
*/
#define LOG_CATEGORY LOGC_FS
#include <common.h>
#include <blk.h>
#include <config.h>
@ -97,8 +99,8 @@ int fat_register_device(struct blk_desc *dev_desc, int part_no)
/* Read the partition table, if present */
if (part_get_info(dev_desc, part_no, &info)) {
if (part_no != 0) {
printf("** Partition %d not valid on device %d **\n",
part_no, dev_desc->devnum);
log_err("Partition %d invalid on device %d\n", part_no,
dev_desc->devnum);
return -1;
}
@ -168,7 +170,7 @@ static __u32 get_fatent(fsdata *mydata, __u32 entry)
__u32 ret = 0x00;
if (CHECK_CLUST(entry, mydata->fatsize)) {
printf("Error: Invalid FAT entry: 0x%08x\n", entry);
log_err("Invalid FAT entry: %#08x\n", entry);
return ret;
}
@ -586,19 +588,19 @@ static int get_fs_info(fsdata *mydata)
mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
mydata->clust_size = bs.cluster_size;
if (mydata->sect_size != cur_part_info.blksz) {
printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n",
mydata->sect_size, cur_part_info.blksz);
log_err("FAT sector size mismatch (fs=%u, dev=%lu)\n",
mydata->sect_size, cur_part_info.blksz);
return -1;
}
if (mydata->clust_size == 0) {
printf("Error: FAT cluster size not set\n");
log_err("FAT cluster size not set\n");
return -1;
}
if ((unsigned int)mydata->clust_size * mydata->sect_size >
MAX_CLUSTSIZE) {
printf("Error: FAT cluster size too big (cs=%u, max=%u)\n",
(unsigned int)mydata->clust_size * mydata->sect_size,
MAX_CLUSTSIZE);
log_err("FAT cluster size too big (cs=%u, max=%u)\n",
(uint)mydata->clust_size * mydata->sect_size,
MAX_CLUSTSIZE);
return -1;
}

View File

@ -1571,8 +1571,9 @@ int fat_unlink(const char *filename)
char *filename_copy, *dirname, *basename;
filename_copy = strdup(filename);
if (!filename_copy) {
printf("Error: allocating memory\n");
itr = malloc_cache_aligned(sizeof(fat_itr));
if (!itr || !filename_copy) {
printf("Error: out of memory\n");
ret = -ENOMEM;
goto exit;
}
@ -1584,13 +1585,6 @@ int fat_unlink(const char *filename)
goto exit;
}
itr = malloc_cache_aligned(sizeof(fat_itr));
if (!itr) {
printf("Error: allocating memory\n");
ret = -ENOMEM;
goto exit;
}
ret = fat_itr_root(itr, &fsdata);
if (ret)
goto exit;
@ -1605,7 +1599,7 @@ int fat_unlink(const char *filename)
}
if (!find_directory_entry(itr, basename)) {
printf("%s: doesn't exist\n", basename);
log_err("%s: doesn't exist (%d)\n", basename, -ENOENT);
ret = -ENOENT;
goto exit;
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Bootdevice for MMC
* Bootdev for sandbox host
*
* Copyright 2021 Google LLC
* Written by Simon Glass <sjg@chromium.org>

View File

@ -301,6 +301,12 @@ struct global_data {
* @timebase_l: low 32 bits of timer
*/
unsigned int timebase_l;
/**
* @malloc_start: start of malloc() region
*/
#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA)
unsigned long malloc_start;
#endif
#if CONFIG_VAL(SYS_MALLOC_F_LEN)
/**
* @malloc_base: base address of early malloc()
@ -560,6 +566,13 @@ static_assert(sizeof(struct global_data) == GD_SIZE);
#define gd_event_state() NULL
#endif
#if CONFIG_IS_ENABLED(CMD_BDINFO_EXTRA)
#define gd_malloc_start() gd->malloc_start
#define gd_set_malloc_start(_val) gd->malloc_start = (_val)
#else
#define gd_malloc_start() 0
#define gd_set_malloc_start(val)
#endif
/**
* enum gd_flags - global data flags
*

View File

@ -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

View File

@ -200,7 +200,7 @@ void bootdev_clear_bootflows(struct udevice *dev);
* All fields in @bflow must be set up. Note that @bflow->dev is used to add the
* bootflow to that device.
*
* @dev: Bootdevice device to add to
* @dev: Bootdev device to add to
* @bflow: Bootflow to add. Note that fields within bflow must be allocated
* since this function takes over ownership of these. This functions makes
* a copy of @bflow itself (without allocating its fields again), so the

View File

@ -58,7 +58,7 @@ enum bootflow_flags_t {
*
* @bm_node: Points to siblings in the same bootdev
* @glob_node: Points to siblings in the global list (all bootdev)
* @dev: Bootdevice device which produced this bootflow
* @dev: Bootdev device which produced this bootflow
* @blk: Block device which contains this bootflow, NULL if this is a network
* device or sandbox 'host' device
* @part: Partition number (0 for whole device)
@ -81,6 +81,8 @@ enum bootflow_flags_t {
* @fdt_size: Size of FDT file
* @fdt_addr: Address of loaded fdt
* @flags: Flags for the bootflow (see enum bootflow_flags_t)
* @cmdline: OS command line, or NULL if not known (allocated)
* @x86_setup: Pointer to x86 setup block inside @buf, NULL if not present
*/
struct bootflow {
struct list_head bm_node;
@ -104,6 +106,8 @@ struct bootflow {
int fdt_size;
ulong fdt_addr;
int flags;
char *cmdline;
char *x86_setup;
};
/**
@ -440,4 +444,98 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node);
int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
struct bootflow **bflowp);
#define BOOTFLOWCL_EMPTY ((void *)1)
/**
* cmdline_set_arg() - Update or read an argument in a cmdline string
*
* Handles updating a single arg in a cmdline string, returning it in a supplied
* buffer; also reading an arg from a cmdline string
*
* When updating, consecutive spaces are squashed as are spaces at the start and
* end.
*
* @buf: Working buffer to use (initial contents are ignored). Use NULL when
* reading
* @maxlen: Length of working buffer. Use 0 when reading
* @cmdline: Command line to update, in the form:
*
* fred mary= jane=123 john="has spaces"
*
* @set_arg: Argument to set or read (may or may not exist)
* @new_val: Value for the new argument. May not include quotes (") but may
* include embedded spaces, in which case it will be quoted when added to the
* command line. Use NULL to delete the argument from @cmdline, BOOTFLOWCL_EMPTY
* to set it to an empty value (no '=' sign after arg), "" to add an '=' sign
* but with an empty value. Use NULL when reading.
* @posp: Ignored when setting an argument; when getting an argument, returns
* the start position of its value in @cmdline, after the first quote, if any
*
* Return:
* For updating:
* length of new buffer (including \0 terminator) on success, -ENOENT if
* @new_val is NULL and @set_arg does not exist in @from, -EINVAL if a
* quoted arg-value in @from is not terminated with a quote, -EBADF if
* @new_val has spaces but does not start and end with quotes (or it has
* quotes in the middle of the string), -E2BIG if @maxlen is too small
* For reading:
* length of arg value (excluding quotes), -ENOENT if not found
*/
int cmdline_set_arg(char *buf, int maxlen, const char *cmdline,
const char *set_arg, const char *new_val, int *posp);
/**
* bootflow_cmdline_set_arg() - Set a single argument for a bootflow
*
* Update the allocated cmdline and set the bootargs variable
*
* @bflow: Bootflow to update
* @arg: Argument to update (e.g. "console")
* @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present,
* "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add
* it without any value ("initrd")
* @set_env: true to set the "bootargs" environment variable too
*
* Return: 0 if OK, -ENOMEM if out of memory
*/
int bootflow_cmdline_set_arg(struct bootflow *bflow, const char *arg,
const char *val, bool set_env);
/**
* cmdline_get_arg() - Read an argument from a cmdline
*
* @cmdline: Command line to read, in the form:
*
* fred mary= jane=123 john="has spaces"
* @arg: Argument to read (may or may not exist)
* @posp: Returns position of argument (after any leading quote) if present
* Return: Length of argument value excluding quotes if found, -ENOENT if not
* found
*/
int cmdline_get_arg(const char *cmdline, const char *arg, int *posp);
/**
* bootflow_cmdline_get_arg() - Read an argument from a cmdline
*
* @bootflow: Bootflow to read from
* @arg: Argument to read (may or may not exist)
* @valp: Returns a pointer to the argument (after any leading quote) if present
* Return: Length of argument value excluding quotes if found, -ENOENT if not
* found
*/
int bootflow_cmdline_get_arg(struct bootflow *bflow, const char *arg,
const char **val);
/**
* bootflow_cmdline_auto() - Automatically set a value for a known argument
*
* This handles a small number of known arguments, for Linux in particular. It
* adds suitable kernel parameters automatically, e.g. to enable the console.
*
* @bflow: Bootflow to update
* @arg: Name of argument to set (e.g. "earlycon" or "console")
* Return: 0 if OK -ve on error
*/
int bootflow_cmdline_auto(struct bootflow *bflow, const char *arg);
#endif

View File

@ -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" \

View File

@ -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" \

View File

@ -17,6 +17,4 @@
"stderr=vidconsole,serial\0" \
"usb_pgood_delay=40\0"
#define VIDEO_IO_OFFSET 0
#endif /* __CONFIG_H */

View File

@ -12,14 +12,6 @@
#include <linux/sizes.h>
#define BOOT_TARGET_DEVICES(func) \
func(USB, usb, 0) \
func(SCSI, scsi, 0) \
func(VIRTIO, virtio, 0) \
func(IDE, ide, 0) \
func(DHCP, dhcp, na)
#include <config_distro_bootcmd.h>
#include <configs/x86-common.h>
#define CFG_STD_DEVICES_SETTINGS "stdin=serial,i8042-kbd\0" \

View File

@ -16,6 +16,4 @@
"stdout=serial,vidconsole\0" \
"stderr=serial,vidconsole\0"
#define VIDEO_IO_OFFSET 0
#endif /* __CONFIG_H */

View File

@ -15,8 +15,6 @@
"stdout=serial\0" \
"stderr=serial\0"
#define VIDEO_IO_OFFSET 0
/* Environment settings */
#undef CFG_EXTRA_ENV_SETTINGS

View File

@ -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"

View File

@ -60,8 +60,10 @@
#define NET6_CALLBACKS
#endif
#ifdef CONFIG_BOOTSTD
#define BOOTSTD_CALLBACK "bootmeths:bootmeths,"
#ifdef CONFIG_BOOTSTD_FULL
#define BOOTSTD_CALLBACK \
"bootmeths:bootmeths," \
"bootargs:bootargs,"
#else
#define BOOTSTD_CALLBACK
#endif

View File

@ -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; }

View File

@ -134,6 +134,30 @@ struct video_ops {
#define video_get_ops(dev) ((struct video_ops *)(dev)->driver->ops)
/**
* struct video_handoff - video information passed from SPL
*
* This is used when video is set up by SPL, to provide the details to U-Boot
* proper.
*
* @fb: Base address of frame buffer, 0 if not yet known
* @size: Frame-buffer size, in bytes
* @xsize: Number of pixel columns (e.g. 1366)
* @ysize: Number of pixels rows (e.g.. 768)
* @line_length: Length of each frame buffer line, in bytes. This can be
* set by the driver, but if not, the uclass will set it after
* probing
* @bpix: Encoded bits per pixel (enum video_log2_bpp)
*/
struct video_handoff {
u64 fb;
u32 size;
u16 xsize;
u16 ysize;
u32 line_length;
u8 bpix;
};
/** enum colour_idx - the 16 colors supported by consoles */
enum colour_idx {
VID_BLACK = 0,

View File

@ -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);
}

View File

@ -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 },

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Bootdevice for ethernet (uses PXE)
* Bootdev for ethernet (uses PXE)
*
* Copyright 2021 Google LLC
* Written by Simon Glass <sjg@chromium.org>

View File

@ -226,6 +226,7 @@ static int bootflow_cmd_info(struct unit_test_state *uts)
ut_assert_nextlinen("Buffer: ");
ut_assert_nextline("Size: 253 (595 bytes)");
ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)");
ut_assert_nextline("Cmdline: (none)");
ut_assert_nextline("Logo: (none)");
ut_assert_nextline("FDT: <NULL>");
ut_assert_nextline("Error: 0");
@ -682,3 +683,265 @@ static int bootflow_menu_theme(struct unit_test_state *uts)
return 0;
}
BOOTSTD_TEST(bootflow_menu_theme, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
/**
* check_arg() - Check both the normal case and the buffer-overflow case
*
* @uts: Unit-test state
* @expect_ret: Expected return value (i.e. buffer length)
* @expect_str: String expected to be returned
* @buf: Buffer to use
* @from: Original cmdline to update
* @arg: Argument to update (e.g. "console")
* @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present,
* "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add
* it without any value ("initrd")
*/
static int check_arg(struct unit_test_state *uts, int expect_ret,
const char *expect_str, char *buf, const char *from,
const char *arg, const char *val)
{
/* check for writing outside the reported bounds */
buf[expect_ret] = '[';
ut_asserteq(expect_ret,
cmdline_set_arg(buf, expect_ret, from, arg, val, NULL));
ut_asserteq_str(expect_str, buf);
ut_asserteq('[', buf[expect_ret]);
/* do the test again but with one less byte in the buffer */
ut_asserteq(-E2BIG, cmdline_set_arg(buf, expect_ret - 1, from, arg,
val, NULL));
return 0;
}
/* Test of bootflow_cmdline_set_arg() */
static int test_bootflow_cmdline_set(struct unit_test_state *uts)
{
char buf[50];
const int size = sizeof(buf);
/*
* note that buffer-overflow tests are immediately each test case, just
* top keep the code together
*/
/* add an arg that doesn't already exist, starting from empty */
ut_asserteq(-ENOENT, cmdline_set_arg(buf, size, NULL, "me", NULL,
NULL));
ut_assertok(check_arg(uts, 3, "me", buf, NULL, "me", BOOTFLOWCL_EMPTY));
ut_assertok(check_arg(uts, 4, "me=", buf, NULL, "me", ""));
ut_assertok(check_arg(uts, 8, "me=fred", buf, NULL, "me", "fred"));
/* add an arg that doesn't already exist, starting from non-empty */
ut_assertok(check_arg(uts, 11, "arg=123 me", buf, "arg=123", "me",
BOOTFLOWCL_EMPTY));
ut_assertok(check_arg(uts, 12, "arg=123 me=", buf, "arg=123", "me",
""));
ut_assertok(check_arg(uts, 16, "arg=123 me=fred", buf, "arg=123", "me",
"fred"));
/* update an arg at the start */
ut_assertok(check_arg(uts, 1, "", buf, "arg=123", "arg", NULL));
ut_assertok(check_arg(uts, 4, "arg", buf, "arg=123", "arg",
BOOTFLOWCL_EMPTY));
ut_assertok(check_arg(uts, 5, "arg=", buf, "arg=123", "arg", ""));
ut_assertok(check_arg(uts, 6, "arg=1", buf, "arg=123", "arg", "1"));
ut_assertok(check_arg(uts, 9, "arg=1234", buf, "arg=123", "arg",
"1234"));
/* update an arg at the end */
ut_assertok(check_arg(uts, 5, "mary", buf, "mary arg=123", "arg",
NULL));
ut_assertok(check_arg(uts, 9, "mary arg", buf, "mary arg=123", "arg",
BOOTFLOWCL_EMPTY));
ut_assertok(check_arg(uts, 10, "mary arg=", buf, "mary arg=123", "arg",
""));
ut_assertok(check_arg(uts, 11, "mary arg=1", buf, "mary arg=123", "arg",
"1"));
ut_assertok(check_arg(uts, 14, "mary arg=1234", buf, "mary arg=123",
"arg", "1234"));
/* update an arg in the middle */
ut_assertok(check_arg(uts, 16, "mary=abc john=2", buf,
"mary=abc arg=123 john=2", "arg", NULL));
ut_assertok(check_arg(uts, 20, "mary=abc arg john=2", buf,
"mary=abc arg=123 john=2", "arg",
BOOTFLOWCL_EMPTY));
ut_assertok(check_arg(uts, 21, "mary=abc arg= john=2", buf,
"mary=abc arg=123 john=2", "arg", ""));
ut_assertok(check_arg(uts, 22, "mary=abc arg=1 john=2", buf,
"mary=abc arg=123 john=2", "arg", "1"));
ut_assertok(check_arg(uts, 25, "mary=abc arg=1234 john=2", buf,
"mary=abc arg=123 john=2", "arg", "1234"));
/* handle existing args with quotes */
ut_assertok(check_arg(uts, 16, "mary=\"abc\" john", buf,
"mary=\"abc\" arg=123 john", "arg", NULL));
/* handle existing args with quoted spaces */
ut_assertok(check_arg(uts, 20, "mary=\"abc def\" john", buf,
"mary=\"abc def\" arg=123 john", "arg", NULL));
ut_assertok(check_arg(uts, 34, "mary=\"abc def\" arg=123 john def=4",
buf, "mary=\"abc def\" arg=123 john", "def",
"4"));
/* quote at the start */
ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
"mary=\"abc def\" arg=\"123 456\"",
"arg", "\"4 5 6", NULL));
/* quote at the end */
ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
"mary=\"abc def\" arg=\"123 456\"",
"arg", "4 5 6\"", NULL));
/* quote in the middle */
ut_asserteq(-EBADF, cmdline_set_arg(buf, size,
"mary=\"abc def\" arg=\"123 456\"",
"arg", "\"4 \"5 6\"", NULL));
/* handle updating a quoted arg */
ut_assertok(check_arg(uts, 27, "mary=\"abc def\" arg=\"4 5 6\"", buf,
"mary=\"abc def\" arg=\"123 456\"", "arg",
"4 5 6"));
/* changing a quoted arg to a non-quoted arg */
ut_assertok(check_arg(uts, 23, "mary=\"abc def\" arg=789", buf,
"mary=\"abc def\" arg=\"123 456\"", "arg",
"789"));
/* changing a non-quoted arg to a quoted arg */
ut_assertok(check_arg(uts, 29, "mary=\"abc def\" arg=\"456 789\"", buf,
"mary=\"abc def\" arg=123", "arg", "456 789"));
/* handling of spaces */
ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123"));
ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john ", "arg",
"123"));
ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john arg=123 ",
"arg", "123"));
ut_assertok(check_arg(uts, 18, "john arg=123 mary", buf,
" john arg=123 mary ", "arg", "123"));
/* unchanged arg */
ut_assertok(check_arg(uts, 3, "me", buf, "me", "me", BOOTFLOWCL_EMPTY));
/* arg which starts with the same name */
ut_assertok(check_arg(uts, 28, "mary=abc johnathon=2 john=3", buf,
"mary=abc johnathon=2 john=1", "john", "3"));
return 0;
}
BOOTSTD_TEST(test_bootflow_cmdline_set, 0);
/* Test of bootflow_cmdline_set_arg() */
static int bootflow_set_arg(struct unit_test_state *uts)
{
struct bootflow s_bflow, *bflow = &s_bflow;
ulong mem_start;
ut_assertok(env_set("bootargs", NULL));
mem_start = ut_check_delta(0);
/* Do a simple sanity check. Rely on bootflow_cmdline() for the rest */
bflow->cmdline = NULL;
ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", "123", false));
ut_asserteq_str(bflow->cmdline, "fred=123");
ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "and here", false));
ut_asserteq_str(bflow->cmdline, "fred=123 mary=\"and here\"");
ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", NULL, false));
ut_asserteq_str(bflow->cmdline, "fred=123");
ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", NULL, false));
ut_asserteq_ptr(bflow->cmdline, NULL);
ut_asserteq(0, ut_check_delta(mem_start));
ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "here", true));
ut_asserteq_str("mary=here", env_get("bootargs"));
ut_assertok(env_set("bootargs", NULL));
return 0;
}
BOOTSTD_TEST(bootflow_set_arg, 0);
/* Test of bootflow_cmdline_get_arg() */
static int bootflow_cmdline_get(struct unit_test_state *uts)
{
int pos;
/* empty string */
ut_asserteq(-ENOENT, cmdline_get_arg("", "fred", &pos));
/* arg with empty value */
ut_asserteq(0, cmdline_get_arg("fred= mary", "fred", &pos));
ut_asserteq(5, pos);
/* arg with a value */
ut_asserteq(2, cmdline_get_arg("fred=23", "fred", &pos));
ut_asserteq(5, pos);
/* arg with a value */
ut_asserteq(3, cmdline_get_arg("mary=1 fred=234", "fred", &pos));
ut_asserteq(12, pos);
/* arg with a value, after quoted arg */
ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=234", "fred", &pos));
ut_asserteq(16, pos);
/* arg in the middle */
ut_asserteq(0, cmdline_get_arg("mary=\"1 2\" fred john=23", "fred",
&pos));
ut_asserteq(15, pos);
/* quoted arg */
ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=\"3 4\" john=23",
"fred", &pos));
ut_asserteq(17, pos);
/* args starting with the same prefix */
ut_asserteq(1, cmdline_get_arg("mary=abc johnathon=3 john=1", "john",
&pos));
ut_asserteq(26, pos);
return 0;
}
BOOTSTD_TEST(bootflow_cmdline_get, 0);
static int bootflow_cmdline(struct unit_test_state *uts)
{
ut_assertok(run_command("bootflow scan mmc", 0));
ut_assertok(run_command("bootflow sel 0", 0));
console_record_reset_enable();
ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
ut_assert_nextline("Argument not found");
ut_assert_console_end();
ut_asserteq(0, run_command("bootflow cmdline set fred 123", 0));
ut_asserteq(0, run_command("bootflow cmdline get fred", 0));
ut_assert_nextline("123");
ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
ut_assert_nextline("abc");
ut_asserteq(0, run_command("bootflow cmdline delete fred", 0));
ut_asserteq(1, run_command("bootflow cmdline get fred", 0));
ut_assert_nextline("Argument not found");
ut_asserteq(0, run_command("bootflow cmdline clear mary", 0));
ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
ut_assert_nextline_empty();
ut_assert_console_end();
return 0;
}
BOOTSTD_TEST(bootflow_cmdline, 0);

View File

@ -16,6 +16,7 @@
#include <env.h>
#include <lmb.h>
#include <net.h>
#include <serial.h>
#include <video.h>
#include <vsprintf.h>
#include <asm/cache.h>
@ -191,6 +192,26 @@ static int bdinfo_test_move(struct unit_test_state *uts)
ut_assert_nextline("devicetree = %s", fdtdec_get_srcname());
}
if (IS_ENABLED(CONFIG_DM_SERIAL)) {
struct serial_device_info info;
ut_assertnonnull(gd->cur_serial_dev);
ut_assertok(serial_getinfo(gd->cur_serial_dev, &info));
ut_assertok(test_num_l(uts, "serial addr", info.addr));
ut_assertok(test_num_l(uts, " width", info.reg_width));
ut_assertok(test_num_l(uts, " shift", info.reg_shift));
ut_assertok(test_num_l(uts, " offset", info.reg_offset));
ut_assertok(test_num_l(uts, " clock", info.clock));
}
if (IS_ENABLED(CONFIG_CMD_BDINFO_EXTRA)) {
ut_assert_nextlinen("stack ptr");
ut_assertok(test_num_ll(uts, "ram_top ptr",
(unsigned long long)gd->ram_top));
ut_assertok(test_num_l(uts, "malloc base", gd_malloc_start()));
}
ut_assertok(ut_check_console_end(uts));
return 0;

View File

@ -609,3 +609,41 @@ static int dm_test_acpi_cmd_items(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_acpi_cmd_items, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test 'acpi set' command */
static int dm_test_acpi_cmd_set(struct unit_test_state *uts)
{
struct acpi_ctx ctx;
ulong addr;
void *buf;
gd_set_acpi_start(0);
console_record_reset();
ut_asserteq(0, gd_acpi_start());
ut_assertok(run_command("acpi set", 0));
ut_assert_nextline("ACPI pointer: 0");
buf = memalign(16, BUF_SIZE);
ut_assertnonnull(buf);
addr = map_to_sysmem(buf);
ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr));
ut_assertok(acpi_write_dev_tables(&ctx));
ut_assertok(run_command("acpi set", 0));
ut_assert_nextline("ACPI pointer: %lx", addr);
ut_assertok(run_command("acpi set 0", 0));
ut_assert_nextline("Setting ACPI pointer to 0");
ut_asserteq(0, gd_acpi_start());
ut_assertok(run_commandf("acpi set %lx", addr));
ut_assert_nextline("Setting ACPI pointer to %lx", addr);
ut_asserteq(addr, gd_acpi_start());
ut_assert_console_end();
return 0;
}
DM_TEST(dm_test_acpi_cmd_set, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);

View File

@ -476,7 +476,8 @@ static int ut_run_test_live_flat(struct unit_test_state *uts,
* (for sandbox we handle this by copying the tree, but not for other
* boards)
*/
if (!(test->flags & UT_TESTF_LIVE_TREE) &&
if ((test->flags & UT_TESTF_SCAN_FDT) &&
!(test->flags & UT_TESTF_LIVE_TREE) &&
(CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) ||
!(test->flags & UT_TESTF_OTHER_FDT)) &&
(!runs || ut_test_run_on_flattree(test)) &&