From 8ca302e86d685fa05b16e2b208888243da319941 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 16 Sep 2022 14:36:03 +0100 Subject: Place setup_data at location specified by host 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 Cc: Ard Biesheuvel Signed-off-by: Jason A. Donenfeld Message-Id: <20220916133603.693135-1-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini --- fw_cfg.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'fw_cfg.c') 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); -- cgit v1.1