aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2022-09-16 14:36:03 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2022-09-19 15:35:50 +0200
commit8ca302e86d685fa05b16e2b208888243da319941 (patch)
tree042c4f9c557dc21cd33a2cb434f4cb617d214bea
parenta5300c4949b8d4de2d34bedfaed66793f48ec948 (diff)
downloadqboot-8ca302e86d685fa05b16e2b208888243da319941.zip
qboot-8ca302e86d685fa05b16e2b208888243da319941.tar.gz
qboot-8ca302e86d685fa05b16e2b208888243da319941.tar.bz2
Place setup_data at location specified by hostHEADmaster
QEMU places setup_data at a particular location, which cannot be relocated due to it containing self references in absolute address terms. For this reason, it supplies the intended location in FW_CFG_SETUP_ADDR. That is what is used in the option ROMs provided by QEMU, use this too in qboot. This also has the effect of removing the 8k limit on the copied size, since the header is copied to the right location from the beginning. Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> Message-Id: <20220916133603.693135-1-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--fw_cfg.c13
-rw-r--r--include/linuxboot.h1
-rw-r--r--linuxboot.c4
3 files changed, 9 insertions, 9 deletions
diff --git a/fw_cfg.c b/fw_cfg.c
index 4b920cf..f3d9605 100644
--- a/fw_cfg.c
+++ b/fw_cfg.c
@@ -269,6 +269,7 @@ void boot_from_fwcfg(void)
{
struct linuxboot_args args;
uint32_t kernel_size;
+ enum { HEADER_PEEK_SIZE = 8192 };
fw_cfg_select(FW_CFG_CMDLINE_SIZE);
args.cmdline_size = fw_cfg_readl_le();
@@ -282,15 +283,17 @@ void boot_from_fwcfg(void)
kernel_size = fw_cfg_readl_le();
fw_cfg_select(FW_CFG_SETUP_SIZE);
args.vmlinuz_size = kernel_size + fw_cfg_readl_le();
+ fw_cfg_select(FW_CFG_SETUP_ADDR);
+ args.setup_addr = (void *)fw_cfg_readl_le();
if (!args.vmlinuz_size)
return;
fw_cfg_select(FW_CFG_SETUP_DATA);
- fw_cfg_read(args.header, sizeof(args.header));
+ fw_cfg_read(args.setup_addr, HEADER_PEEK_SIZE);
if (!parse_bzimage(&args)) {
- uint8_t *header = args.header;
+ uint8_t *header = args.setup_addr;
if (ldl_p(header) == 0x464c457f) /* ELF magic */
boot_pvh_from_fw_cfg();
@@ -298,9 +301,9 @@ void boot_from_fwcfg(void)
}
/* SETUP_DATA already selected */
- if (args.setup_size > sizeof(args.header))
- fw_cfg_read(args.setup_addr + sizeof(args.header),
- args.setup_size - sizeof(args.header));
+ if (args.setup_size > HEADER_PEEK_SIZE)
+ fw_cfg_read(args.setup_addr + HEADER_PEEK_SIZE,
+ args.setup_size - HEADER_PEEK_SIZE);
fw_cfg_select(FW_CFG_KERNEL_DATA);
fw_cfg_read_entry(FW_CFG_KERNEL_DATA, args.kernel_addr, kernel_size);
diff --git a/include/linuxboot.h b/include/linuxboot.h
index 6e865f0..e04c234 100644
--- a/include/linuxboot.h
+++ b/include/linuxboot.h
@@ -10,7 +10,6 @@ struct linuxboot_args {
/* Input */
uint32_t cmdline_size, vmlinuz_size, initrd_size;
- uint8_t header[8192];
};
bool parse_bzimage(struct linuxboot_args *args);
diff --git a/linuxboot.c b/linuxboot.c
index 251bcb6..bdb01ee 100644
--- a/linuxboot.c
+++ b/linuxboot.c
@@ -11,7 +11,7 @@ struct hvm_start_info start_info = {0};
bool parse_bzimage(struct linuxboot_args *args)
{
- uint8_t *header = args->header;
+ uint8_t *header = args->setup_addr;
uint32_t real_addr, cmdline_addr, prot_addr, initrd_addr;
uint32_t setup_size;
@@ -84,7 +84,6 @@ bool parse_bzimage(struct linuxboot_args *args)
args->setup_size = (setup_size+1)*512;
args->kernel_size = args->vmlinuz_size - setup_size;
args->initrd_addr = (void *)initrd_addr;
- args->setup_addr = (void *)real_addr;
args->kernel_addr = (void *)prot_addr;
args->cmdline_addr = (void *)cmdline_addr;
return true;
@@ -92,7 +91,6 @@ bool parse_bzimage(struct linuxboot_args *args)
void boot_bzimage(struct linuxboot_args *args)
{
- memcpy(args->setup_addr, args->header, sizeof(args->header));
#ifdef BENCHMARK_HACK
/* Exit just before getting to vmlinuz, so that it is easy
* to time/profile the firmware.