aboutsummaryrefslogtreecommitdiff
path: root/fw_cfg.c
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2015-05-21 10:00:47 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2015-05-21 11:44:57 +0200
commit3d284aa77f35b743679cd2be9b78b592b36c425f (patch)
tree81d141f2a5a2765fb6b3c74c0d9834cae08ddc2f /fw_cfg.c
parentb39bb6c7a55584e7e13e1f855b684ddad7975e63 (diff)
downloadqboot-3d284aa77f35b743679cd2be9b78b592b36c425f.zip
qboot-3d284aa77f35b743679cd2be9b78b592b36c425f.tar.gz
qboot-3d284aa77f35b743679cd2be9b78b592b36c425f.tar.bz2
parse vmlinuz inside firmware
This will make it possible to load the vmlinuz from CBFS. We need some contortions because QEMU splits the real mode and protected mode parts of vmlinuz in different fw_cfg files. The parsing code is lifted from QEMU. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'fw_cfg.c')
-rw-r--r--fw_cfg.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/fw_cfg.c b/fw_cfg.c
index 293e4be..c1b354e 100644
--- a/fw_cfg.c
+++ b/fw_cfg.c
@@ -1,7 +1,9 @@
#include "bios.h"
+#include "stdio.h"
#include "ioport.h"
#include "string.h"
#include "fw_cfg.h"
+#include "linuxboot.h"
struct fw_cfg_file {
uint32_t size;
@@ -48,3 +50,46 @@ void fw_cfg_file_select(int id)
{
fw_cfg_select(files[id].select);
}
+
+void boot_from_fwcfg(void)
+{
+ struct linuxboot_args args;
+ uint32_t kernel_size;
+
+ fw_cfg_select(FW_CFG_CMDLINE_SIZE);
+ args.cmdline_size = fw_cfg_readl_le();
+ fw_cfg_select(FW_CFG_INITRD_SIZE);
+ args.initrd_size = fw_cfg_readl_le();
+
+ /* QEMU has already split the real mode and protected mode
+ * parts. Recombine them in args.vmlinuz_size.
+ */
+ fw_cfg_select(FW_CFG_KERNEL_SIZE);
+ 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_DATA);
+ fw_cfg_read(args.header, sizeof(args.header));
+
+ if (!parse_bzimage(&args))
+ return;
+
+ /* 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));
+
+ fw_cfg_select(FW_CFG_KERNEL_DATA);
+ fw_cfg_read(args.kernel_addr, kernel_size);
+
+ fw_cfg_select(FW_CFG_CMDLINE_DATA);
+ fw_cfg_read(args.cmdline_addr, args.cmdline_size);
+
+ if (args.initrd_size) {
+ fw_cfg_select(FW_CFG_INITRD_DATA);
+ fw_cfg_read(args.initrd_addr, args.initrd_size);
+ }
+
+ boot_bzimage(&args);
+}