Compare commits
23 Commits
cli
...
oss-qemu-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6745ec44d9 | ||
|
|
ae65270530 | ||
|
|
4bc5ceac65 | ||
|
|
cc88f32641 | ||
|
|
a97042cdf6 | ||
|
|
5414785620 | ||
|
|
0ed5f6b991 | ||
|
|
f6c413a993 | ||
|
|
bd3ef58432 | ||
|
|
4d8ad27f8e | ||
|
|
5f65048550 | ||
|
|
9fea52af75 | ||
|
|
1aa8ff8220 | ||
|
|
be79f70a11 | ||
|
|
80c56d399c | ||
|
|
c872780ba6 | ||
|
|
21abce189f | ||
|
|
8099cce624 | ||
|
|
793bb912e1 | ||
|
|
403ad10115 | ||
|
|
add868d853 | ||
|
|
057ec035cf | ||
|
|
7665482b11 |
@@ -31,6 +31,7 @@
|
||||
#define POST_DRAM 0x30
|
||||
#define POST_LAPIC 0x31
|
||||
#define POST_OS_RESUME 0x40
|
||||
#define POST_BOOT 0x42
|
||||
|
||||
#define POST_RAM_FAILURE 0xea
|
||||
#define POST_BIST_FAILURE 0xeb
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/post.h>
|
||||
#include <asm/zimage.h>
|
||||
#ifdef CONFIG_SYS_COREBOOT
|
||||
#include <asm/arch/timestamp.h>
|
||||
@@ -201,6 +202,8 @@ int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit)
|
||||
if (IS_ENABLED(CONFIG_EFI_APP))
|
||||
return efi_boot(setup_base, entry, image_64bit);
|
||||
|
||||
post_code(POST_BOOT);
|
||||
|
||||
if (image_64bit) {
|
||||
if (!cpu_has_64bit()) {
|
||||
puts("Cannot boot 64-bit kernel on 32-bit machine\n");
|
||||
|
||||
@@ -17,7 +17,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select X86_RESET_VECTOR
|
||||
select QEMU
|
||||
select QFW_PIO if CMD_QFW
|
||||
select QFW_PIO
|
||||
select BOARD_ROMSIZE_KB_1024 if TARGET_QEMU_X86
|
||||
select BOARD_ROMSIZE_KB_2048 if TARGET_QEMU_X86_64
|
||||
imply VIRTIO_PCI
|
||||
|
||||
@@ -557,7 +557,7 @@ config BOOTSTD_DEFAULTS
|
||||
bool "Select some common defaults for standard boot"
|
||||
depends on BOOTSTD
|
||||
select BOOT_DEFAULTS
|
||||
select BOOTMETH_DISTRO
|
||||
imply BOOTMETH_DISTRO
|
||||
help
|
||||
These are not required but are commonly needed to support a good
|
||||
selection of booting methods. Enable this to improve the capability
|
||||
@@ -731,9 +731,9 @@ config BOOTMETH_VBE
|
||||
config BOOTMETH_DISTRO
|
||||
bool # Options needed to boot any distro
|
||||
select BOOTMETH_SCRIPT if CMDLINE # E.g. Armbian uses scripts
|
||||
select BOOTMETH_EXTLINUX # E.g. Debian uses these
|
||||
imply BOOTMETH_EXTLINUX # E.g. Debian uses these
|
||||
select BOOTMETH_EXTLINUX_PXE if CMD_PXE && CMD_NET && DM_ETH
|
||||
select BOOTMETH_EFILOADER if EFI_BINARY_EXEC # E.g. Ubuntu uses this
|
||||
imply BOOTMETH_EFILOADER if EFI_BINARY_EXEC # E.g. Ubuntu uses this
|
||||
|
||||
config SPL_BOOTMETH_VBE
|
||||
bool "Bootdev support for Verified Boot for Embedded (SPL)"
|
||||
|
||||
@@ -998,10 +998,10 @@ struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const struct bootflow_img *bootflow_img_find(const struct bootflow *bflow,
|
||||
enum bootflow_img_t type)
|
||||
struct bootflow_img *bootflow_img_findw(const struct bootflow *bflow,
|
||||
enum bootflow_img_t type)
|
||||
{
|
||||
const struct bootflow_img *img;
|
||||
struct bootflow_img *img;
|
||||
|
||||
alist_for_each(img, &bflow->images) {
|
||||
if (img->type == type)
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
|
||||
#define LOG_CATEGORY UCLASS_BOOTSTD
|
||||
|
||||
#include <abuf.h>
|
||||
#include <command.h>
|
||||
#include <bootdev.h>
|
||||
#include <bootflow.h>
|
||||
#include <bootm.h>
|
||||
#include <bootmeth.h>
|
||||
#include <env.h>
|
||||
#include <mapmem.h>
|
||||
#include <qfw.h>
|
||||
#include <dm.h>
|
||||
|
||||
@@ -31,26 +34,86 @@ static int qfw_check(struct udevice *dev, struct bootflow_iter *iter)
|
||||
static int qfw_read_bootflow(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
struct udevice *qfw_dev = dev_get_parent(bflow->dev);
|
||||
ulong load, initrd;
|
||||
ulong setup, kern, ramdisk, cmdline_size, setup_addr;
|
||||
struct abuf cmdline;
|
||||
int ret;
|
||||
|
||||
load = env_get_hex("kernel_addr_r", 0);
|
||||
initrd = env_get_hex("ramdisk_addr_r", 0);
|
||||
log_debug("setup kernel %s %lx %lx\n", qfw_dev->name, load, initrd);
|
||||
/* Get the size of each region */
|
||||
ret = qemu_fwcfg_read_info(qfw_dev, &setup, &kern, &ramdisk, &cmdline,
|
||||
&setup_addr);
|
||||
if (ret)
|
||||
return log_msg_ret("qri", ret);
|
||||
bflow->cmdline = abuf_uninit_move(&cmdline, &cmdline_size);
|
||||
|
||||
bflow->name = strdup("qfw");
|
||||
if (!bflow->name)
|
||||
return log_msg_ret("name", -ENOMEM);
|
||||
|
||||
ret = qemu_fwcfg_setup_kernel(qfw_dev, load, initrd);
|
||||
log_debug("setup kernel result %d\n", ret);
|
||||
if (ret)
|
||||
return log_msg_ret("cmd", -EIO);
|
||||
|
||||
/*
|
||||
* create images for each; only cmdline has the actual data; the others
|
||||
* only have a size for now, since the data has yet not been read
|
||||
*/
|
||||
if (!bootflow_img_add(bflow, "setup",
|
||||
(enum bootflow_img_t)IH_TYPE_X86_SETUP,
|
||||
setup_addr, setup))
|
||||
return log_msg_ret("cri", -ENOMEM);
|
||||
if (!bootflow_img_add(bflow, "kernel",
|
||||
(enum bootflow_img_t)IH_TYPE_KERNEL, 0, kern))
|
||||
return log_msg_ret("qrk", -ENOMEM);
|
||||
if (ramdisk && !bootflow_img_add(bflow, "ramdisk",
|
||||
(enum bootflow_img_t)IH_TYPE_RAMDISK,
|
||||
0, ramdisk))
|
||||
return log_msg_ret("qrr", -ENOMEM);
|
||||
if (!bootflow_img_add(bflow, "cmdline", BFI_CMDLINE,
|
||||
map_to_sysmem(bflow->cmdline), cmdline_size))
|
||||
return log_msg_ret("qrc", -ENOMEM);
|
||||
bflow->state = BOOTFLOWST_READY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qfw_read_files(struct udevice *dev, struct bootflow *bflow,
|
||||
bool re_read, const struct bootflow_img **simgp,
|
||||
const struct bootflow_img **kimgp,
|
||||
const struct bootflow_img **rimgp)
|
||||
{
|
||||
struct udevice *qfw_dev = dev_get_parent(bflow->dev);
|
||||
struct bootflow_img *kimg, *rimg;
|
||||
struct abuf setup, kern, ramdisk;
|
||||
const struct bootflow_img *simg;
|
||||
|
||||
simg = bootflow_img_find(bflow,
|
||||
(enum bootflow_img_t)IH_TYPE_X86_SETUP);
|
||||
kimg = bootflow_img_findw(bflow, (enum bootflow_img_t)IH_TYPE_KERNEL);
|
||||
rimg = bootflow_img_findw(bflow, (enum bootflow_img_t)IH_TYPE_RAMDISK);
|
||||
if (!kimg)
|
||||
return log_msg_ret("qfs", -EINVAL);
|
||||
|
||||
/* read files only if not already read */
|
||||
if (re_read || !kimg->addr) {
|
||||
abuf_init_const_addr(&setup, simg ? simg->addr : 0,
|
||||
simg ? simg->size : 0);
|
||||
abuf_init_const_addr(&kern, env_get_hex("kernel_addr_r", 0),
|
||||
kimg->size);
|
||||
abuf_init_const_addr(&ramdisk, env_get_hex("ramdisk_addr_r", 0),
|
||||
rimg ? rimg->size : 0);
|
||||
|
||||
qemu_fwcfg_read_files(qfw_dev, &setup, &kern, &ramdisk);
|
||||
kimg->addr = abuf_addr(&kern);
|
||||
if (rimg)
|
||||
rimg->addr = abuf_addr(&ramdisk);
|
||||
}
|
||||
|
||||
if (simgp)
|
||||
*simgp = simg;
|
||||
if (kimgp)
|
||||
*kimgp = kimg;
|
||||
if (rimgp)
|
||||
*rimgp = rimg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qfw_read_file(struct udevice *dev, struct bootflow *bflow,
|
||||
const char *file_path, ulong addr,
|
||||
enum bootflow_img_t type, ulong *sizep)
|
||||
@@ -58,15 +121,55 @@ static int qfw_read_file(struct udevice *dev, struct bootflow *bflow,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int qfw_boot(struct udevice *dev, struct bootflow *bflow)
|
||||
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
|
||||
static int qfw_read_all(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
struct bootflow_img *kimg;
|
||||
int ret;
|
||||
|
||||
ret = run_command("booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdtcontroladdr}",
|
||||
0);
|
||||
if (ret) {
|
||||
ret = run_command("bootz ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} "
|
||||
"${fdtcontroladdr}", 0);
|
||||
kimg = bootflow_img_findw(bflow, (enum bootflow_img_t)IH_TYPE_KERNEL);
|
||||
if (!kimg)
|
||||
return log_msg_ret("qra", -ENOENT);
|
||||
|
||||
ret = qfw_read_files(dev, bflow, true, NULL, NULL, NULL);
|
||||
if (ret)
|
||||
return log_msg_ret("qrA", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int qfw_boot(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
const struct bootflow_img *simg, *kimg, *rimg;
|
||||
char conf_fdt[20], conf_ramdisk[40], addr_img_str[20];
|
||||
struct bootm_info bmi;
|
||||
int ret;
|
||||
|
||||
/* read the files if not already done */
|
||||
ret = qfw_read_files(dev, bflow, false, &simg, &kimg, &rimg);
|
||||
if (!kimg)
|
||||
return log_msg_ret("qkf", -EINVAL);
|
||||
|
||||
ret = booti_run(&bmi);
|
||||
bootm_init(&bmi);
|
||||
snprintf(conf_fdt, sizeof(conf_fdt), "%lx",
|
||||
(ulong)map_to_sysmem(gd->fdt_blob));
|
||||
snprintf(addr_img_str, sizeof(addr_img_str), "%lx", kimg->addr);
|
||||
bmi.addr_img = addr_img_str;
|
||||
snprintf(conf_ramdisk, sizeof(conf_ramdisk), "%lx:%lx", rimg->addr,
|
||||
rimg->size);
|
||||
bmi.conf_ramdisk = conf_ramdisk;
|
||||
|
||||
ret = -ENOENT;
|
||||
if (IS_ENABLED(CONFIG_CMD_BOOTI))
|
||||
ret = booti_run(&bmi);
|
||||
if (ret && IS_ENABLED(CONFIG_CMD_BOOTZ))
|
||||
ret = bootz_run(&bmi);
|
||||
if (ret && IS_ENABLED(CONFIG_ZBOOT) && simg) {
|
||||
ret = zboot_run_args(kimg->addr, kimg->size,
|
||||
rimg->addr, rimg->size, simg->addr,
|
||||
*bflow->cmdline ? bflow->cmdline : NULL);
|
||||
}
|
||||
|
||||
return ret ? -EIO : 0;
|
||||
@@ -85,6 +188,9 @@ static struct bootmeth_ops qfw_bootmeth_ops = {
|
||||
.check = qfw_check,
|
||||
.read_bootflow = qfw_read_bootflow,
|
||||
.read_file = qfw_read_file,
|
||||
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
|
||||
.read_all = qfw_read_all,
|
||||
#endif
|
||||
.boot = qfw_boot,
|
||||
};
|
||||
|
||||
|
||||
@@ -1413,7 +1413,7 @@ static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long bas
|
||||
err = 0;
|
||||
switch (t.type) {
|
||||
case T_MENU:
|
||||
cfg->prompt = 1;
|
||||
// cfg->prompt = 1;
|
||||
err = parse_menu(ctx, &p, cfg,
|
||||
base + ALIGN(strlen(b) + 1, 4),
|
||||
nest_level);
|
||||
@@ -1460,6 +1460,7 @@ static int parse_pxefile_top(struct pxe_context *ctx, char *p, unsigned long bas
|
||||
|
||||
case T_PROMPT:
|
||||
err = parse_integer(&p, &cfg->prompt);
|
||||
cfg->prompt = 0;
|
||||
// Do not fail if prompt configuration is undefined
|
||||
if (err < 0)
|
||||
eol_or_eof(&p);
|
||||
@@ -1732,6 +1733,7 @@ struct pxe_menu *pxe_prepare(struct pxe_context *ctx, ulong pxefile_addr_r,
|
||||
|
||||
if (prompt)
|
||||
cfg->prompt = prompt;
|
||||
cfg->prompt = 0;
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,10 @@ __weak void board_add_ram_info(int use_default)
|
||||
|
||||
static int init_baud_rate(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL
|
||||
gd->baudrate = env_get_ulong("baudrate", 10, CONFIG_BAUDRATE);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
117
common/qfw.c
117
common/qfw.c
@@ -4,6 +4,7 @@
|
||||
* (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
|
||||
*/
|
||||
|
||||
#include <abuf.h>
|
||||
#include <dm.h>
|
||||
#include <env.h>
|
||||
#include <mapmem.h>
|
||||
@@ -105,62 +106,106 @@ bool qfw_file_iter_end(struct fw_cfg_file_iter *iter)
|
||||
return iter->entry == iter->end;
|
||||
}
|
||||
|
||||
/**
|
||||
* qfw_read_size() - Read the size of an entry
|
||||
*
|
||||
* @sel: Selector value, e.g. FW_CFG_SETUP_SIZE, FW_CFG_CMDLINE_SIZE
|
||||
* Return: Size of the entry
|
||||
*/
|
||||
static ulong qfw_read_size(struct udevice *qfw_dev, enum fw_cfg_selector sel)
|
||||
{
|
||||
u32 size = 0;
|
||||
|
||||
qfw_read_entry(qfw_dev, sel, 4, &size);
|
||||
|
||||
return le32_to_cpu(size);
|
||||
}
|
||||
|
||||
int qemu_fwcfg_read_info(struct udevice *qfw_dev, ulong *setupp, ulong *kernp,
|
||||
ulong *initrdp, struct abuf *cmdline,
|
||||
ulong *setup_addrp)
|
||||
{
|
||||
uint cmdline_size;
|
||||
|
||||
*setupp = qfw_read_size(qfw_dev, FW_CFG_SETUP_SIZE);
|
||||
*kernp = qfw_read_size(qfw_dev, FW_CFG_KERNEL_SIZE);
|
||||
*initrdp = qfw_read_size(qfw_dev, FW_CFG_INITRD_SIZE);
|
||||
cmdline_size = qfw_read_size(qfw_dev, FW_CFG_CMDLINE_SIZE);
|
||||
if (!*kernp)
|
||||
return -ENOENT;
|
||||
|
||||
*setup_addrp = qfw_read_size(qfw_dev, FW_CFG_SETUP_ADDR);
|
||||
|
||||
if (!abuf_init_size(cmdline, cmdline_size))
|
||||
return log_msg_ret("qri", -ENOMEM);
|
||||
qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_DATA, cmdline_size,
|
||||
cmdline->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_fwcfg_read_files(struct udevice *qfw_dev, const struct abuf *setup,
|
||||
const struct abuf *kern, const struct abuf *initrd)
|
||||
{
|
||||
if (setup->size) {
|
||||
qfw_read_entry(qfw_dev, FW_CFG_SETUP_DATA, setup->size,
|
||||
setup->data);
|
||||
}
|
||||
qfw_read_entry(qfw_dev, FW_CFG_KERNEL_DATA, kern->size, kern->data);
|
||||
if (initrd->size) {
|
||||
qfw_read_entry(qfw_dev, FW_CFG_INITRD_DATA, initrd->size,
|
||||
initrd->data);
|
||||
}
|
||||
}
|
||||
|
||||
int qemu_fwcfg_setup_kernel(struct udevice *qfw_dev, ulong load_addr,
|
||||
ulong initrd_addr)
|
||||
{
|
||||
char *data_addr;
|
||||
u32 setup_size, kernel_size, cmdline_size, initrd_size;
|
||||
ulong setup_size, kernel_size, initrd_size, setup_addr;
|
||||
struct abuf cmdline, setup, kern, initrd;
|
||||
int ret;
|
||||
|
||||
qfw_read_entry(qfw_dev, FW_CFG_SETUP_SIZE, 4, &setup_size);
|
||||
qfw_read_entry(qfw_dev, FW_CFG_KERNEL_SIZE, 4, &kernel_size);
|
||||
|
||||
if (!kernel_size) {
|
||||
ret = qemu_fwcfg_read_info(qfw_dev, &setup_size, &initrd_size,
|
||||
&kernel_size, &cmdline, &setup_addr);
|
||||
if (ret) {
|
||||
printf("fatal: no kernel available\n");
|
||||
return -ENOENT;
|
||||
return log_msg_ret("qsk", ret);
|
||||
}
|
||||
|
||||
data_addr = map_sysmem(load_addr, 0);
|
||||
if (setup_size) {
|
||||
qfw_read_entry(qfw_dev, FW_CFG_SETUP_DATA,
|
||||
le32_to_cpu(setup_size), data_addr);
|
||||
data_addr += le32_to_cpu(setup_size);
|
||||
}
|
||||
/*
|
||||
* always put the setup area where QEMU wants it, since it includes
|
||||
* absolute pointers to itself
|
||||
*/
|
||||
abuf_init_const_addr(&setup, setup_addr, 0);
|
||||
abuf_init_const_addr(&kern, load_addr, 0);
|
||||
|
||||
qfw_read_entry(qfw_dev, FW_CFG_KERNEL_DATA,
|
||||
le32_to_cpu(kernel_size), data_addr);
|
||||
data_addr += le32_to_cpu(kernel_size);
|
||||
env_set_hex("filesize", le32_to_cpu(kernel_size));
|
||||
abuf_init_const_addr(&initrd, initrd_addr, 0);
|
||||
qemu_fwcfg_read_files(qfw_dev, &setup, &kern, &initrd);
|
||||
|
||||
data_addr = map_sysmem(initrd_addr, 0);
|
||||
qfw_read_entry(qfw_dev, FW_CFG_INITRD_SIZE, 4, &initrd_size);
|
||||
if (!initrd_size) {
|
||||
env_set_hex("filesize", kern.size);
|
||||
|
||||
if (!initrd_size)
|
||||
printf("warning: no initrd available\n");
|
||||
} else {
|
||||
qfw_read_entry(qfw_dev, FW_CFG_INITRD_DATA,
|
||||
le32_to_cpu(initrd_size), data_addr);
|
||||
data_addr += le32_to_cpu(initrd_size);
|
||||
env_set_hex("filesize", le32_to_cpu(initrd_size));
|
||||
}
|
||||
else
|
||||
env_set_hex("filesize", initrd_size);
|
||||
|
||||
qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_SIZE, 4, &cmdline_size);
|
||||
if (cmdline_size) {
|
||||
qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_DATA,
|
||||
le32_to_cpu(cmdline_size), data_addr);
|
||||
if (cmdline.data) {
|
||||
/*
|
||||
* if kernel cmdline only contains '\0', (e.g. no -append
|
||||
* when invoking qemu), do not update bootargs
|
||||
*/
|
||||
if (*data_addr) {
|
||||
if (env_set("bootargs", data_addr) < 0)
|
||||
if (*(char *)cmdline.data) {
|
||||
if (env_set("bootargs", cmdline.data) < 0)
|
||||
printf("warning: unable to change bootargs\n");
|
||||
}
|
||||
}
|
||||
abuf_uninit(&cmdline);
|
||||
|
||||
printf("loading kernel to address %lx size %x", load_addr,
|
||||
le32_to_cpu(kernel_size));
|
||||
printf("loading kernel to address %lx size %zx", abuf_addr(&kern),
|
||||
kern.size);
|
||||
if (initrd_size)
|
||||
printf(" initrd %lx size %x\n", initrd_addr,
|
||||
le32_to_cpu(initrd_size));
|
||||
printf(" initrd %lx size %lx\n", abuf_addr(&initrd),
|
||||
initrd_size);
|
||||
else
|
||||
printf("\n");
|
||||
|
||||
|
||||
@@ -94,3 +94,34 @@ CONFIG_GENERATE_ACPI_TABLE=y
|
||||
CONFIG_CMD_DHRYSTONE=y
|
||||
# CONFIG_GZIP is not set
|
||||
CONFIG_UNIT_TEST=y
|
||||
CONFIG_BOOTDELAY=-1
|
||||
# CONFIG_DM_ETH is not set
|
||||
# CONFIG_VIRTIO_NET is not set
|
||||
CONFIG_NO_NET=y
|
||||
# CONFIG_VIDEO is not set
|
||||
# CONFIG_SPL_VIDEO is not set
|
||||
# CONFIG_CMDLINE is not set
|
||||
# CONFIG_BOOTMETH_GLOBAL is not set
|
||||
# CONFIG_BOOTMETH_CROS is not set
|
||||
# CONFIG_BOOTMETH_EXTLINUX is not set
|
||||
# CONFIG_BOOTMETH_EFILOADER is not set
|
||||
# CONFIG_BOOTMETH_EFI_BOOTMGR is not set
|
||||
# CONFIG_BOOTMETH_VBE is not set
|
||||
CONFIG_PXE_UTILS=y
|
||||
CONFIG_AUTOBOOT=y
|
||||
CONFIG_PARTITION_TYPE_GUID=y
|
||||
CONFIG_QFW_PIO=y
|
||||
# CONFIG_EFI_LOADER is not set
|
||||
# CONFIG_FIT is not set
|
||||
# CONFIG_USB is not set
|
||||
# CONFIG_SPI is not set
|
||||
# CONFIG_SCSI is not set
|
||||
# CONFIG_FS_FAT is not set
|
||||
CONFIG_ENV_IS_NOWHERE=y
|
||||
# CONFIG_ENV_IS_IN_FAT is not set
|
||||
# CONFIG_DOS_PARTITION is not set
|
||||
# CONFIG_ISO_PARTITION is not set
|
||||
# CONFIG_SPL_PARTITIONS is not set
|
||||
# CONFIG_NVME_PCI is not set
|
||||
# CONFIG_SCSI_AHCI is not set
|
||||
# CONFIG_FS_EXT4 is not set
|
||||
|
||||
15
contrib/README.rst
Normal file
15
contrib/README.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
The `contrib` directory contains software / files which have been contributed
|
||||
to the U-Boot project but are not maintained by the core developers.
|
||||
|
||||
Note to contributors: Each item must have at least an entry in this file. Be
|
||||
sure to add the appropriate GPL-2.0-or-later SPDX tag to files.
|
||||
|
||||
QEMU boot-timer script
|
||||
----------------------
|
||||
|
||||
Runs qboot (or builds and starts U-Boot) and measures how long it takes to
|
||||
start Lunux. Must be run in the U-Boot source directory.
|
||||
|
||||
File: `qemu-boot-timer.sh <../../../../contrib/qemu-boot-timer.sh>`_
|
||||
99
contrib/qemu-boot-timer.sh
Executable file
99
contrib/qemu-boot-timer.sh
Executable file
@@ -0,0 +1,99 @@
|
||||
#/bin/bash
|
||||
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# .. code-block:: bash
|
||||
# qemu-boot-timer.sh
|
||||
#
|
||||
# Runs qboot (or builds and starts U-Boot) and measures how long it takes to
|
||||
# start Linux. Must be run in the U-Boot source directory.
|
||||
|
||||
# You will need to first install tracing tools, e.g.:
|
||||
#
|
||||
# sudo apt install linux-tools-common linux-tools-generic linux-tools-`uname -r`
|
||||
#
|
||||
# and also change files and directories below
|
||||
#
|
||||
# Example usage to test qboot:
|
||||
|
||||
# $ ./contrib/qemu-boot-timer.sh
|
||||
# qemu-system-x86_64: terminating on signal 15 from pid 3548708 (bash)
|
||||
# 1) pid 3548829
|
||||
# qemu_init_end: 48.352996
|
||||
# fw_start: 48.480586 (+0.12759)
|
||||
# linux_start_boot: 66.16271 (+17.682124)
|
||||
# Exit point 0: 66.37544 (+0.21273)
|
||||
#
|
||||
# That shows a time of 17.7 milliseconds for qboot itself
|
||||
|
||||
# Enable this to boot qboot instead of U-Boot
|
||||
#QBOOT=-QB
|
||||
|
||||
# Linux version to boot (read from /boot)
|
||||
version=6.8.0-60-generic
|
||||
|
||||
# UUID of root disk within your disk image, which must be called root.img
|
||||
uuid=bcfdda4a-8249-4f40-9f0f-7c1a76b6cbe8
|
||||
|
||||
# Set up directories to use
|
||||
DIR=/scratch/sglass/qemu-boot-time/
|
||||
PERF_DATA=perf.data
|
||||
export PERF_EXEC_PATH=/scratch/sglass/linux/tools/perf
|
||||
|
||||
# No settings below here:
|
||||
|
||||
# Turn on tracing in Linux
|
||||
sudo bash <<EOF
|
||||
echo 1 > /sys/kernel/debug/tracing/events/kvm/enable
|
||||
echo -1 > /proc/sys/kernel/perf_event_paranoid
|
||||
mount -o remount,mode=755 /sys/kernel/debug
|
||||
mount -o remount,mode=755 /sys/kernel/debug/tracing
|
||||
EOF
|
||||
|
||||
# Start recording
|
||||
echo "starting perf"
|
||||
sleep 1
|
||||
cd $DIR
|
||||
sudo perf record -a -e kvm:kvm_entry -e kvm:kvm_pio -e sched:sched_process_exec \
|
||||
-o $PERF_DATA 2> /tmp/trace.log &
|
||||
PERF_PID=$!
|
||||
|
||||
# Run QEWU with qboot or U-Boot (builds U-Boot automatically)
|
||||
sleep 1
|
||||
cd ~/u
|
||||
echo "building U-Boot"
|
||||
./scripts/build-qemu -a x86 ${QBOOT} -s -v -K /boot/vmlinuz-${version} \
|
||||
-k -d root.img -I /boot/initrd.img-${version} -C -U ${uuid} \
|
||||
2>&1 >/tmp/qemu.log
|
||||
|
||||
echo "running U-Boot in QEMU"
|
||||
./scripts/build-qemu -a x86 ${QBOOT} -rsB -v -K /boot/vmlinuz-${version} \
|
||||
-k -d root.img -I /boot/initrd.img-${version} -C -U ${uuid} \
|
||||
2>&1 >/tmp/qemu.log &
|
||||
|
||||
while [[ -z "$QEMU_PID" ]]; do
|
||||
QEMU_PID=$(pgrep qemu-system-x86)
|
||||
done
|
||||
|
||||
# Wait for it to boot (increase this on slow machines)
|
||||
echo "waiting for a bit"
|
||||
sleep 2
|
||||
|
||||
# Kill QEMU and the perf process
|
||||
kill $QEMU_PID
|
||||
sleep 1
|
||||
|
||||
kill $PERF_PID
|
||||
wait $PERF_PID
|
||||
|
||||
# Adjust permissions on perf data
|
||||
cd $DIR
|
||||
sudo chmod a+r $PERF_DATA
|
||||
|
||||
# Generate the Python script to permit access to the trace
|
||||
perf script -g python 2>/dev/null
|
||||
|
||||
# Run our script which looks for timing points and prints the results
|
||||
echo "parsing perf results"
|
||||
perf script -s ~/perf-script.py -s ${DIR}/perf-script/qemu-perf-script.py \
|
||||
-i $PERF_DATA
|
||||
6
doc/develop/contrib/index.rst
Normal file
6
doc/develop/contrib/index.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Contributions
|
||||
=============
|
||||
|
||||
.. include:: ../../../contrib/README.rst
|
||||
@@ -113,3 +113,11 @@ Historical documentation
|
||||
:maxdepth: 2
|
||||
|
||||
historical/index
|
||||
|
||||
Contributions
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
contrib/index
|
||||
|
||||
@@ -202,6 +202,18 @@ void abuf_init_set(struct abuf *abuf, void *data, size_t size);
|
||||
*/
|
||||
void abuf_init_const(struct abuf *abuf, const void *data, size_t size);
|
||||
|
||||
/**
|
||||
* abuf_init_const_addr() - Set up a new buffer at a given address
|
||||
*
|
||||
* This is similar to abuf_init_const() except that it takes an address instead
|
||||
* of a pointer. Note that the abuf is unallocated.
|
||||
*
|
||||
* @abuf: abuf to set up
|
||||
* @addr: Address to use
|
||||
* @size: Size of buffer
|
||||
*/
|
||||
void abuf_init_const_addr(struct abuf *abuf, ulong addr, size_t size);
|
||||
|
||||
/**
|
||||
* abuf_init_size() - Set up an allocated abuf
|
||||
*
|
||||
|
||||
@@ -648,6 +648,16 @@ struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
|
||||
enum bootflow_img_t type, ulong addr,
|
||||
ulong size);
|
||||
|
||||
/**
|
||||
* bootflow_img_findw() - Find the first image of a given type
|
||||
*
|
||||
* @bflow: Bootflow to search
|
||||
* @type: Image type to search for
|
||||
* Return: Non-const pointer to image, or NULL if not found
|
||||
*/
|
||||
struct bootflow_img *bootflow_img_findw(const struct bootflow *bflow,
|
||||
enum bootflow_img_t type);
|
||||
|
||||
/**
|
||||
* bootflow_img_find() - Find the first image of a given type
|
||||
*
|
||||
@@ -655,8 +665,12 @@ struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
|
||||
* @type: Image type to search for
|
||||
* Return: Pointer to image, or NULL if not found
|
||||
*/
|
||||
const struct bootflow_img *bootflow_img_find(const struct bootflow *bflow,
|
||||
enum bootflow_img_t type);
|
||||
static inline const struct bootflow_img *
|
||||
bootflow_img_find(const struct bootflow *bflow,
|
||||
enum bootflow_img_t type)
|
||||
{
|
||||
return bootflow_img_findw(bflow, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* bootflow_get_seq() - Get the sequence number of a bootflow
|
||||
|
||||
2
include/env/x86.env
vendored
2
include/env/x86.env
vendored
@@ -11,7 +11,7 @@ netdev=eth0
|
||||
consoledev=ttyS0
|
||||
scriptaddr=0x7000000
|
||||
kernel_addr_r=0x1000000
|
||||
ramdisk_addr_r=0x4000000
|
||||
ramdisk_addr_r=0x8000000
|
||||
ramdiskfile=initramfs.gz
|
||||
|
||||
/* common console settings */
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
struct abuf;
|
||||
|
||||
/*
|
||||
* List of firmware configuration item selectors. The official source of truth
|
||||
* for these is the QEMU source itself; see
|
||||
* https://github.com/qemu/qemu/blob/master/hw/nvram/fw_cfg.c
|
||||
*/
|
||||
enum {
|
||||
enum fw_cfg_selector {
|
||||
FW_CFG_SIGNATURE = 0x00,
|
||||
FW_CFG_ID = 0x01,
|
||||
FW_CFG_UUID = 0x02,
|
||||
@@ -316,12 +318,47 @@ bool qfw_file_iter_end(struct fw_cfg_file_iter *iter);
|
||||
*/
|
||||
int qemu_cpu_fixup(void);
|
||||
|
||||
/**
|
||||
* qemu_fwcfg_read_info() - See if QEMU has provided kernel, etc.
|
||||
*
|
||||
* Read info about the kernel and cmdline
|
||||
*
|
||||
* @qfw_dev: UCLASS_QFW device
|
||||
* @setupp: Returns the size of the setup area on succes
|
||||
* @kernp: Returns kernel size on success
|
||||
* @initrd: Returns initrd size on success
|
||||
* @cmdline: Set to the cmdline in the image (allocated by this function, must
|
||||
* be freed by the caller)
|
||||
* @setup_addrp: Address for the setup block, as requested by QEMU
|
||||
*
|
||||
* Return 0 on success, -ENOENT if there is no kernel provided, -ENOMEM if there
|
||||
* was no memory for the cmdline
|
||||
*/
|
||||
int qemu_fwcfg_read_info(struct udevice *qfw_dev, ulong *setupp, ulong *kernp,
|
||||
ulong *initrdp, struct abuf *cmdline,
|
||||
ulong *setup_addrp);
|
||||
|
||||
/**
|
||||
* qemu_fwcfg_read_files() - Read files from a qfw
|
||||
*
|
||||
* Reads kernel and optional setup/initrd images. For each image, the abuf
|
||||
* controls how many bytes are read and the address into which they are read
|
||||
*
|
||||
* @qfw_dev: UCLASS_QFW device
|
||||
* @setup: Buffer into which to read setup (skipped if setup->size is 0)
|
||||
* @kern: Buffer into which to read kernel
|
||||
* @initrd: Buffer into which to read initrd (skipped if initrd->size is 0)
|
||||
*/
|
||||
void qemu_fwcfg_read_files(struct udevice *qfw_dev, const struct abuf *setup,
|
||||
const struct abuf *kern, const struct abuf *initrd);
|
||||
|
||||
/*
|
||||
* qemu_fwcfg_setup_kernel() - Prepare the kernel for zboot
|
||||
*
|
||||
* Loads kernel data to 'load_addr', initrd to 'initrd_addr' and kernel command
|
||||
* line using qemu fw_cfg interface
|
||||
*
|
||||
* @qfw_dev: UCLASS_QFW device
|
||||
* @load_addr: Load address for kernel
|
||||
* @initrd_addr: Load address for ramdisk
|
||||
* @return 0 if OK, -ENOENT if no kernel
|
||||
|
||||
@@ -183,6 +183,13 @@ void abuf_init_const(struct abuf *abuf, const void *data, size_t size)
|
||||
abuf_init_set(abuf, (void *)data, size);
|
||||
}
|
||||
|
||||
#ifndef USE_HOSTCC
|
||||
void abuf_init_const_addr(struct abuf *abuf, ulong addr, size_t size)
|
||||
{
|
||||
return abuf_init_const(abuf, map_sysmem(addr, size), size);
|
||||
}
|
||||
#endif
|
||||
|
||||
void abuf_init_move(struct abuf *abuf, void *data, size_t size)
|
||||
{
|
||||
abuf_init_set(abuf, data, size);
|
||||
|
||||
@@ -44,6 +44,8 @@ def parse_args():
|
||||
help='Select architecture (arm, x86) Default: arm')
|
||||
parser.add_argument('-B', '--no-build', action='store_true',
|
||||
help="Don't build; assume a build exists")
|
||||
parser.add_argument('-C', '--enable-console', action='store_true',
|
||||
help="Enable linux console (x86 only)")
|
||||
parser.add_argument('-d', '--disk',
|
||||
help='Root disk image file to use with QEMU')
|
||||
parser.add_argument('-D', '--share-dir', metavar='DIR',
|
||||
@@ -52,11 +54,17 @@ def parse_args():
|
||||
help='Run UEFI Self-Certification Test (SCT)')
|
||||
parser.add_argument('-E', '--use-tianocore', action='store_true',
|
||||
help='Run Tianocore (OVMF) instead of U-Boot')
|
||||
parser.add_argument('-I', '--initrd',
|
||||
help='Initial ramdisk to run using -initrd')
|
||||
parser.add_argument(
|
||||
'-k', '--kvm', action='store_true',
|
||||
help='Use KVM (Kernel-based Virtual Machine) for acceleration')
|
||||
parser.add_argument('-K', '--kernel',
|
||||
help='Kernel to run using -kernel')
|
||||
parser.add_argument('-o', '--os', metavar='NAME', choices=['ubuntu'],
|
||||
help='Run a specified Operating System')
|
||||
parser.add_argument('-Q', '--use-qboot', action='store_true',
|
||||
help='Run qboot instead of U-Boot')
|
||||
parser.add_argument('-r', '--run', action='store_true',
|
||||
help='Run QEMU with the built/specified image')
|
||||
parser.add_argument('-x', '--xpl', action='store_true',
|
||||
@@ -70,6 +78,12 @@ def parse_args():
|
||||
parser.add_argument(
|
||||
'-S', '--sct-seq',
|
||||
help='SCT sequence-file to be written into the SCT image if -e')
|
||||
parser.add_argument(
|
||||
'-t', '--root',
|
||||
help='Pass the given root device to linux via root=xxx')
|
||||
parser.add_argument(
|
||||
'-U', '--uuid',
|
||||
help='Pass the given root device to linux via root=/dev/disk/by-uuid/')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Show executed commands')
|
||||
parser.add_argument('-w', '--word-32bit', action='store_true',
|
||||
@@ -92,6 +106,7 @@ class BuildQemu:
|
||||
self.sctdir = Path(self.helper.get_setting('sct_dir', '~/dev/efi/sct'))
|
||||
self.tiano = Path(self.helper.get_setting('tianocore_dir',
|
||||
'~/dev/tiano'))
|
||||
self.qboot = Path(self.helper.get_setting('qboot_dir', '~/dev/qboot'))
|
||||
self.mnt = Path(self.helper.get_setting('sct_mnt', '/mnt/sct'))
|
||||
|
||||
self.bitness = 32 if args.word_32bit else 64
|
||||
@@ -138,6 +153,12 @@ class BuildQemu:
|
||||
tout.fatal(
|
||||
'Error: Tianocore BIOS specified (-E) but not found at '
|
||||
f'{bios_override}')
|
||||
elif args.use_qboot:
|
||||
bios_override = Path(self.qboot, 'bios.bin')
|
||||
if not bios_override.exists():
|
||||
tout.fatal(
|
||||
'Error: qboot BIOS specified (-Q) but not found at '
|
||||
f'{bios_override}')
|
||||
|
||||
self.seq_fname = Path(args.sct_seq) if args.sct_seq else None
|
||||
self.img_fname = Path(args.disk) if args.disk else None
|
||||
@@ -281,13 +302,15 @@ class BuildQemu:
|
||||
if not self.bios.exists():
|
||||
tout.fatal(f"Error: BIOS file '{self.bios}' not found")
|
||||
|
||||
cmdline = []
|
||||
|
||||
qemu_cmd = [str(self.qemu)]
|
||||
if self.bios:
|
||||
qemu_cmd.extend(['-bios', str(self.bios)])
|
||||
qemu_cmd.extend(self.kvm_params)
|
||||
qemu_cmd.extend(['-m', self.mem])
|
||||
|
||||
if not self.args.sct_run:
|
||||
if not self.args.sct_run and not self.qboot:
|
||||
qemu_cmd.extend(['-netdev', 'user,id=net0,hostfwd=tcp::2222-:22',
|
||||
'-device', 'virtio-net-pci,netdev=net0'])
|
||||
|
||||
@@ -301,6 +324,21 @@ class BuildQemu:
|
||||
if not any(item.startswith('-serial') for item in self.qemu_extra):
|
||||
qemu_cmd.extend(['-serial', 'mon:stdio'])
|
||||
|
||||
if self.args.kernel:
|
||||
qemu_cmd.extend(['-kernel', self.args.kernel])
|
||||
if self.args.initrd:
|
||||
qemu_cmd.extend(['-initrd', self.args.initrd])
|
||||
|
||||
if self.args.enable_console:
|
||||
cmdline.append('console=ttyS0,115200,8n1')
|
||||
if self.args.root:
|
||||
cmdline.append(f'root={self.args.root}')
|
||||
if self.args.uuid:
|
||||
cmdline.append(f'root=/dev/disk/by-uuid/{self.args.uuid}')
|
||||
|
||||
if cmdline:
|
||||
qemu_cmd.extend(['-append'] + [' '.join(cmdline)])
|
||||
|
||||
# Add other parameters gathered from options
|
||||
qemu_cmd.extend(self.qemu_extra)
|
||||
if self.os_path:
|
||||
|
||||
@@ -34,7 +34,7 @@ class Helper:
|
||||
self.settings = configparser.ConfigParser()
|
||||
fname = f'{os.getenv("HOME")}/.u_boot_qemu'
|
||||
if not os.path.exists(fname):
|
||||
print('No config file found: {fname}\nCreating one...\n')
|
||||
print(f'No config file found: {fname}\nCreating one...\n')
|
||||
tools.write_file(fname, '''# U-Boot QEMU-scripts config
|
||||
|
||||
[DEFAULT]
|
||||
|
||||
@@ -1417,6 +1417,7 @@ static int bootstd_images(struct unit_test_state *uts)
|
||||
const struct legacy_img_hdr *hdr;
|
||||
const struct bootflow_img *img;
|
||||
const struct bootflow *bflow;
|
||||
struct bootflow_img *wimg;
|
||||
struct bootstd_priv *std;
|
||||
const char **old_order;
|
||||
struct udevice *dev;
|
||||
@@ -1504,6 +1505,15 @@ static int bootstd_images(struct unit_test_state *uts)
|
||||
|
||||
ut_assertnull(bootflow_img_find(bflow, BFI_CMDLINE));
|
||||
|
||||
/* check we can update an image size */
|
||||
wimg = bootflow_img_findw(bflow, (enum bootflow_img_t)IH_TYPE_SCRIPT);
|
||||
ut_assertnonnull(wimg);
|
||||
wimg->size = 123;
|
||||
|
||||
img = bootflow_img_find(bflow, (enum bootflow_img_t)IH_TYPE_SCRIPT);
|
||||
ut_assertnonnull(img);
|
||||
ut_asserteq(123, img->size);
|
||||
|
||||
ut_assert_console_end();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -68,6 +68,28 @@ static int lib_test_abuf_init_const(struct unit_test_state *uts)
|
||||
}
|
||||
LIB_TEST(lib_test_abuf_init_const, 0);
|
||||
|
||||
/* Test abuf_init_const_addr() */
|
||||
static int lib_test_abuf_init_const_addr(struct unit_test_state *uts)
|
||||
{
|
||||
struct abuf buf;
|
||||
ulong start;
|
||||
void *ptr;
|
||||
|
||||
start = ut_check_free();
|
||||
|
||||
ptr = map_sysmem(0x100, 0);
|
||||
|
||||
abuf_init_const_addr(&buf, 0x100, 10);
|
||||
ut_asserteq_ptr(ptr, buf.data);
|
||||
ut_asserteq(10, buf.size);
|
||||
|
||||
/* No memory should have been allocated */
|
||||
ut_assertok(ut_check_delta(start));
|
||||
|
||||
return 0;
|
||||
}
|
||||
LIB_TEST(lib_test_abuf_init_const_addr, 0);
|
||||
|
||||
/* Test abuf_map_sysmem() and abuf_addr() */
|
||||
static int lib_test_abuf_map_sysmem(struct unit_test_state *uts)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user