summaryrefslogtreecommitdiffstats
path: root/hw/s390x/ipl.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x/ipl.c')
-rw-r--r--hw/s390x/ipl.c105
1 files changed, 59 insertions, 46 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 4ba8409..4014a6a 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -50,6 +50,8 @@ typedef struct S390IPLState {
/*< private >*/
SysBusDevice parent_obj;
uint64_t start_addr;
+ uint64_t bios_start_addr;
+ bool enforce_bios;
/*< public >*/
char *kernel;
@@ -65,11 +67,14 @@ static int s390_ipl_init(SysBusDevice *dev)
uint64_t pentry = KERN_IMAGE_START;
int kernel_size;
- if (!ipl->kernel) {
- int bios_size;
- char *bios_filename;
+ int bios_size;
+ char *bios_filename;
- /* Load zipl bootloader */
+ /*
+ * Always load the bios if it was enforced,
+ * even if an external kernel has been defined.
+ */
+ if (!ipl->kernel || ipl->enforce_bios) {
if (bios_name == NULL) {
bios_name = ipl->firmware;
}
@@ -79,12 +84,12 @@ static int s390_ipl_init(SysBusDevice *dev)
hw_error("could not find stage1 bootloader\n");
}
- bios_size = load_elf(bios_filename, NULL, NULL, &ipl->start_addr, NULL,
- NULL, 1, ELF_MACHINE, 0);
+ bios_size = load_elf(bios_filename, NULL, NULL, &ipl->bios_start_addr,
+ NULL, NULL, 1, ELF_MACHINE, 0);
if (bios_size < 0) {
bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
4096);
- ipl->start_addr = ZIPL_IMAGE_START;
+ ipl->bios_start_addr = ZIPL_IMAGE_START;
if (bios_size > 4096) {
hw_error("stage1 bootloader is > 4k\n");
}
@@ -94,52 +99,59 @@ static int s390_ipl_init(SysBusDevice *dev)
if (bios_size == -1) {
hw_error("could not load bootloader '%s'\n", bios_name);
}
- return 0;
- }
- kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
- NULL, 1, ELF_MACHINE, 0);
- if (kernel_size < 0) {
- kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
- }
- if (kernel_size < 0) {
- fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
- return -1;
- }
- /*
- * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
- * kernel parameters here as well. Note: For old kernels (up to 3.2)
- * we can not rely on the ELF entry point - it was 0x800 (the SALIPL
- * loader) and it won't work. For this case we force it to 0x10000, too.
- */
- if (pentry == KERN_IMAGE_START || pentry == 0x800) {
- ipl->start_addr = KERN_IMAGE_START;
- /* Overwrite parameters in the kernel image, which are "rom" */
- strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
- } else {
- ipl->start_addr = pentry;
+ /* default boot target is the bios */
+ ipl->start_addr = ipl->bios_start_addr;
}
- if (ipl->initrd) {
- ram_addr_t initrd_offset;
- int initrd_size;
-
- initrd_offset = INITRD_START;
- while (kernel_size + 0x100000 > initrd_offset) {
- initrd_offset += 0x100000;
+ if (ipl->kernel) {
+ kernel_size = load_elf(ipl->kernel, NULL, NULL, &pentry, NULL,
+ NULL, 1, ELF_MACHINE, 0);
+ if (kernel_size < 0) {
+ kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
+ }
+ if (kernel_size < 0) {
+ fprintf(stderr, "could not load kernel '%s'\n", ipl->kernel);
+ return -1;
}
- initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
- ram_size - initrd_offset);
- if (initrd_size == -1) {
- fprintf(stderr, "qemu: could not load initrd '%s'\n", ipl->initrd);
- exit(1);
+ /*
+ * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
+ * kernel parameters here as well. Note: For old kernels (up to 3.2)
+ * we can not rely on the ELF entry point - it was 0x800 (the SALIPL
+ * loader) and it won't work. For this case we force it to 0x10000, too.
+ */
+ if (pentry == KERN_IMAGE_START || pentry == 0x800) {
+ ipl->start_addr = KERN_IMAGE_START;
+ /* Overwrite parameters in the kernel image, which are "rom" */
+ strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline);
+ } else {
+ ipl->start_addr = pentry;
}
- /* we have to overwrite values in the kernel image, which are "rom" */
- stq_p(rom_ptr(INITRD_PARM_START), initrd_offset);
- stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
- }
+ if (ipl->initrd) {
+ ram_addr_t initrd_offset;
+ int initrd_size;
+
+ initrd_offset = INITRD_START;
+ while (kernel_size + 0x100000 > initrd_offset) {
+ initrd_offset += 0x100000;
+ }
+ initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
+ ram_size - initrd_offset);
+ if (initrd_size == -1) {
+ fprintf(stderr, "qemu: could not load initrd '%s'\n",
+ ipl->initrd);
+ exit(1);
+ }
+ /*
+ * we have to overwrite values in the kernel image,
+ * which are "rom"
+ */
+ stq_p(rom_ptr(INITRD_PARM_START), initrd_offset);
+ stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size);
+ }
+ }
return 0;
}
@@ -148,6 +160,7 @@ static Property s390_ipl_properties[] = {
DEFINE_PROP_STRING("initrd", S390IPLState, initrd),
DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
+ DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false),
DEFINE_PROP_END_OF_LIST(),
};
OpenPOWER on IntegriCloud