*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
+#include "qemu/datadir.h"
#include "qapi/error.h"
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
-#include "sysemu/sysemu.h"
#include "sysemu/tcg.h"
-#include "cpu.h"
#include "elf.h"
#include "hw/loader.h"
#include "hw/qdev-properties.h"
#define KERN_IMAGE_START 0x010000UL
#define LINUX_MAGIC_ADDR 0x010008UL
+#define KERN_PARM_AREA_SIZE_ADDR 0x010430UL
#define KERN_PARM_AREA 0x010480UL
+#define LEGACY_KERN_PARM_AREA_SIZE 0x000380UL
#define INITRD_START 0x800000UL
#define INITRD_PARM_START 0x010408UL
#define PARMFILE_START 0x001000UL
return srcaddr + dstaddr;
}
+static uint64_t get_max_kernel_cmdline_size(void)
+{
+ uint64_t *size_ptr = rom_ptr(KERN_PARM_AREA_SIZE_ADDR, sizeof(*size_ptr));
+
+ if (size_ptr) {
+ uint64_t size;
+
+ size = be64_to_cpu(*size_ptr);
+ if (size) {
+ return size;
+ }
+ }
+ return LEGACY_KERN_PARM_AREA_SIZE;
+}
+
static void s390_ipl_realize(DeviceState *dev, Error **errp)
{
+ MachineState *ms = MACHINE(qdev_get_machine());
S390IPLState *ipl = S390_IPL(dev);
uint32_t *ipl_psw;
uint64_t pentry;
char *magic;
int kernel_size;
- Error *err = NULL;
int bios_size;
char *bios_filename;
* even if an external kernel has been defined.
*/
if (!ipl->kernel || ipl->enforce_bios) {
- uint64_t fwbase = (MIN(ram_size, 0x80000000U) - 0x200000) & ~0xffffUL;
+ uint64_t fwbase = (MIN(ms->ram_size, 0x80000000U) - 0x200000) & ~0xffffUL;
- if (bios_name == NULL) {
- bios_name = ipl->firmware;
- }
-
- bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+ bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware);
if (bios_filename == NULL) {
- error_setg(&err, "could not find stage1 bootloader");
- goto error;
+ error_setg(errp, "could not find stage1 bootloader");
+ return;
}
bios_size = load_elf(bios_filename, NULL,
g_free(bios_filename);
if (bios_size == -1) {
- error_setg(&err, "could not load bootloader '%s'", bios_name);
- goto error;
+ error_setg(errp, "could not load bootloader '%s'", ipl->firmware);
+ return;
}
/* default boot target is the bios */
&pentry, NULL,
NULL, NULL, 1, EM_S390, 0, 0);
if (kernel_size < 0) {
- kernel_size = load_image_targphys(ipl->kernel, 0, ram_size);
+ kernel_size = load_image_targphys(ipl->kernel, 0, ms->ram_size);
if (kernel_size < 0) {
- error_setg(&err, "could not load kernel '%s'", ipl->kernel);
- goto error;
+ error_setg(errp, "could not load kernel '%s'", ipl->kernel);
+ return;
}
/* if this is Linux use KERN_IMAGE_START */
magic = rom_ptr(LINUX_MAGIC_ADDR, 6);
if (ipl_psw) {
pentry = be32_to_cpu(*ipl_psw) & PSW_MASK_SHORT_ADDR;
} else {
- error_setg(&err, "Could not get IPL PSW");
- goto error;
+ error_setg(errp, "Could not get IPL PSW");
+ return;
}
}
}
* loader) and it won't work. For this case we force it to 0x10000, too.
*/
if (pentry == KERN_IMAGE_START || pentry == 0x800) {
- char *parm_area = rom_ptr(KERN_PARM_AREA, strlen(ipl->cmdline) + 1);
+ size_t cmdline_size = strlen(ipl->cmdline) + 1;
+ char *parm_area = rom_ptr(KERN_PARM_AREA, cmdline_size);
+
ipl->start_addr = KERN_IMAGE_START;
/* Overwrite parameters in the kernel image, which are "rom" */
if (parm_area) {
+ uint64_t max_cmdline_size = get_max_kernel_cmdline_size();
+
+ if (cmdline_size > max_cmdline_size) {
+ error_setg(errp,
+ "kernel command line exceeds maximum size:"
+ " %zu > %" PRIu64,
+ cmdline_size, max_cmdline_size);
+ return;
+ }
+
strcpy(parm_area, ipl->cmdline);
}
} else {
initrd_offset += 0x100000;
}
initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
- ram_size - initrd_offset);
+ ms->ram_size - initrd_offset);
if (initrd_size == -1) {
- error_setg(&err, "could not load initrd '%s'", ipl->initrd);
- goto error;
+ error_setg(errp, "could not load initrd '%s'", ipl->initrd);
+ return;
}
/*
* TODO: there should be a better way to do this.
*/
qemu_register_reset(resettable_cold_reset_fn, dev);
-error:
- error_propagate(errp, err);
}
static Property s390_ipl_properties[] = {
static int load_netboot_image(Error **errp)
{
+ MachineState *ms = MACHINE(qdev_get_machine());
S390IPLState *ipl = get_ipl_device();
char *netboot_filename;
MemoryRegion *sysmem = get_system_memory();
false);
if (img_size < 0) {
- img_size = load_image_size(netboot_filename, ram_ptr, ram_size);
+ img_size = load_image_size(netboot_filename, ram_ptr, ms->ram_size);
ipl->start_addr = KERN_IMAGE_START;
}
}
}
if (reset_type == S390_RESET_MODIFIED_CLEAR ||
- reset_type == S390_RESET_LOAD_NORMAL) {
+ reset_type == S390_RESET_LOAD_NORMAL ||
+ reset_type == S390_RESET_PV) {
/* ignore -no-reboot, send no event */
qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET);
} else {
void s390_ipl_prepare_cpu(S390CPU *cpu)
{
S390IPLState *ipl = get_ipl_device();
- Error *err = NULL;
cpu->env.psw.addr = ipl->start_addr;
cpu->env.psw.mask = IPL_PSW_MASK;
}
}
if (ipl->netboot) {
- if (load_netboot_image(&err) < 0) {
- error_report_err(err);
- exit(1);
- }
+ load_netboot_image(&error_fatal);
ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr);
}
s390_ipl_set_boot_menu(ipl);