diff options
author | Fan Zhang <zhangfan@linux.vnet.ibm.com> | 2015-02-12 18:02:13 +0100 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2015-02-13 16:14:09 +0100 |
commit | f0180f913e3bcd04cb132f5f6036e823a78e0673 (patch) | |
tree | 47a31ccd3dbf847c4104d0e159809c8c72142665 /hw/s390x/ipl.c | |
parent | cd2d5541271f1934345d8ca42f5fafff1744eee7 (diff) |
s390x/ipl: always load the bios for ccw machine
We will need bios support in order to be able to support selecting a
different boot device via diagnose 308 in the ccw machine, so let's
make the bios mandatory for the ccw machine.
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: Fan Zhang <zhangfan@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'hw/s390x/ipl.c')
-rw-r--r-- | hw/s390x/ipl.c | 105 |
1 files changed, 59 insertions, 46 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 4ba8409668..4014a6a229 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(), }; |