| 1 | /* |
| 2 | * bootloader support |
| 3 | * |
| 4 | * Copyright IBM, Corp. 2012, 2020 |
| 5 | * |
| 6 | * Authors: |
| 7 | * Christian Borntraeger <borntraeger@de.ibm.com> |
| 8 | * Janosch Frank <frankja@linux.ibm.com> |
| 9 | * |
| 10 | * This work is licensed under the terms of the GNU GPL, version 2 or (at your |
| 11 | * option) any later version. See the COPYING file in the top-level directory. |
| 12 | * |
| 13 | */ |
| 14 | |
| 15 | #include "qemu/osdep.h" |
| 16 | #include "qemu/datadir.h" |
| 17 | #include "qapi/error.h" |
| 18 | #include "system/physmem.h" |
| 19 | #include "system/reset.h" |
| 20 | #include "system/runstate.h" |
| 21 | #include "elf.h" |
| 22 | #include "hw/core/loader.h" |
| 23 | #include "hw/core/qdev-properties.h" |
| 24 | #include "hw/core/boards.h" |
| 25 | #include "hw/s390x/virtio-ccw.h" |
| 26 | #include "hw/s390x/vfio-ccw.h" |
| 27 | #include "hw/s390x/css.h" |
| 28 | #include "hw/s390x/ebcdic.h" |
| 29 | #include "hw/scsi/scsi.h" |
| 30 | #include "hw/virtio/virtio-net.h" |
| 31 | #include "hw/virtio/virtio-pci.h" |
| 32 | #include "hw/s390x/s390-pci-bus.h" |
| 33 | #include "exec/cpu-common.h" |
| 34 | #include "ipl.h" |
| 35 | #include "qemu/error-report.h" |
| 36 | #include "qemu/config-file.h" |
| 37 | #include "qemu/cutils.h" |
| 38 | #include "qemu/option.h" |
| 39 | #include "qemu/ctype.h" |
| 40 | #include "standard-headers/linux/virtio_ids.h" |
| 41 | #include "cert-store.h" |
| 42 | |
| 43 | #define KERN_IMAGE_START 0x010000UL |
| 44 | #define LINUX_MAGIC_ADDR 0x010008UL |
| 45 | #define KERN_PARM_AREA_SIZE_ADDR 0x010430UL |
| 46 | #define KERN_PARM_AREA 0x010480UL |
| 47 | #define LEGACY_KERN_PARM_AREA_SIZE 0x000380UL |
| 48 | #define INITRD_START 0x800000UL |
| 49 | #define INITRD_PARM_START 0x010408UL |
| 50 | #define PARMFILE_START 0x001000UL |
| 51 | #define ZIPL_IMAGE_START 0x009000UL |
| 52 | #define BIOS_MAX_SIZE 0x300000UL |
| 53 | #define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) |
| 54 | |
| 55 | /* Place the IPLB chain immediately before the BIOS in memory */ |
| 56 | static uint64_t find_iplb_chain_addr(uint64_t bios_addr, uint16_t count) |
| 57 | { |
| 58 | return (bios_addr & TARGET_PAGE_MASK) |
| 59 | - (count * sizeof(IplParameterBlock)); |
| 60 | } |
| 61 | |
| 62 | static const VMStateDescription vmstate_iplb_extended = { |
| 63 | .name = "ipl/iplb_extended", |
| 64 | .version_id = 0, |
| 65 | .minimum_version_id = 0, |
| 66 | .fields = (const VMStateField[]) { |
| 67 | VMSTATE_UINT8_ARRAY(reserved_ext, IplParameterBlock, 4096 - 200), |
| 68 | VMSTATE_END_OF_LIST() |
| 69 | } |
| 70 | }; |
| 71 | |
| 72 | static const VMStateDescription vmstate_iplb = { |
| 73 | .name = "ipl/iplb", |
| 74 | .version_id = 0, |
| 75 | .minimum_version_id = 0, |
| 76 | .fields = (const VMStateField[]) { |
| 77 | VMSTATE_UINT8_ARRAY(reserved1, IplParameterBlock, 110), |
| 78 | VMSTATE_UINT16(devno, IplParameterBlock), |
| 79 | VMSTATE_UINT8_ARRAY(reserved2, IplParameterBlock, 88), |
| 80 | VMSTATE_END_OF_LIST() |
| 81 | }, |
| 82 | .subsections = (const VMStateDescription * const []) { |
| 83 | &vmstate_iplb_extended, |
| 84 | NULL |
| 85 | } |
| 86 | }; |
| 87 | |
| 88 | static const VMStateDescription vmstate_ipl = { |
| 89 | .name = "ipl", |
| 90 | .version_id = 0, |
| 91 | .minimum_version_id = 0, |
| 92 | .fields = (const VMStateField[]) { |
| 93 | VMSTATE_UINT64(compat_start_addr, S390IPLState), |
| 94 | VMSTATE_UINT64(compat_bios_start_addr, S390IPLState), |
| 95 | VMSTATE_STRUCT(iplb, S390IPLState, 0, vmstate_iplb, IplParameterBlock), |
| 96 | VMSTATE_BOOL(iplb_valid, S390IPLState), |
| 97 | VMSTATE_UINT8(cssid, S390IPLState), |
| 98 | VMSTATE_UINT8(ssid, S390IPLState), |
| 99 | VMSTATE_UINT16(devno, S390IPLState), |
| 100 | VMSTATE_END_OF_LIST() |
| 101 | } |
| 102 | }; |
| 103 | |
| 104 | static S390IPLState *get_ipl_device(void) |
| 105 | { |
| 106 | return S390_IPL(object_resolve_path_type("", TYPE_S390_IPL, NULL)); |
| 107 | } |
| 108 | |
| 109 | static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr) |
| 110 | { |
| 111 | uint64_t dstaddr = *(uint64_t *) opaque; |
| 112 | /* |
| 113 | * Assuming that our s390-ccw.img was linked for starting at address 0, |
| 114 | * we can simply add the destination address for the final location |
| 115 | */ |
| 116 | return srcaddr + dstaddr; |
| 117 | } |
| 118 | |
| 119 | static uint64_t get_max_kernel_cmdline_size(void) |
| 120 | { |
| 121 | uint64_t *size_ptr = rom_ptr(KERN_PARM_AREA_SIZE_ADDR, sizeof(*size_ptr)); |
| 122 | |
| 123 | if (size_ptr) { |
| 124 | uint64_t size; |
| 125 | |
| 126 | size = be64_to_cpu(*size_ptr); |
| 127 | if (size) { |
| 128 | return size; |
| 129 | } |
| 130 | } |
| 131 | return LEGACY_KERN_PARM_AREA_SIZE; |
| 132 | } |
| 133 | |
| 134 | static void s390_ipl_realize(DeviceState *dev, Error **errp) |
| 135 | { |
| 136 | MachineState *ms = MACHINE(qdev_get_machine()); |
| 137 | S390IPLState *ipl = S390_IPL(dev); |
| 138 | uint32_t *ipl_psw; |
| 139 | uint64_t pentry; |
| 140 | char *magic; |
| 141 | int kernel_size; |
| 142 | |
| 143 | int bios_size; |
| 144 | char *bios_filename; |
| 145 | |
| 146 | /* |
| 147 | * Always load the bios if it was enforced, |
| 148 | * even if an external kernel has been defined. |
| 149 | */ |
| 150 | if (!ipl->kernel || ipl->enforce_bios) { |
| 151 | uint64_t fwbase; |
| 152 | |
| 153 | if (ms->ram_size < BIOS_MAX_SIZE) { |
| 154 | error_setg(errp, "not enough RAM to load the BIOS file"); |
| 155 | return; |
| 156 | } |
| 157 | |
| 158 | fwbase = (MIN(ms->ram_size, 0x80000000U) - BIOS_MAX_SIZE) & ~0xffffUL; |
| 159 | |
| 160 | bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware); |
| 161 | if (bios_filename == NULL) { |
| 162 | error_setg(errp, "could not find stage1 bootloader"); |
| 163 | return; |
| 164 | } |
| 165 | |
| 166 | bios_size = load_elf(bios_filename, NULL, |
| 167 | bios_translate_addr, &fwbase, |
| 168 | &ipl->bios_start_addr, NULL, NULL, NULL, |
| 169 | ELFDATA2MSB, EM_S390, 0, 0); |
| 170 | if (bios_size > 0) { |
| 171 | /* Adjust ELF start address to final location */ |
| 172 | ipl->bios_start_addr += fwbase; |
| 173 | } else { |
| 174 | /* Try to load non-ELF file */ |
| 175 | bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START, |
| 176 | 4096, NULL); |
| 177 | ipl->bios_start_addr = ZIPL_IMAGE_START; |
| 178 | } |
| 179 | g_free(bios_filename); |
| 180 | |
| 181 | if (bios_size == -1) { |
| 182 | error_setg(errp, "could not load bootloader '%s'", ipl->firmware); |
| 183 | return; |
| 184 | } |
| 185 | |
| 186 | /* default boot target is the bios */ |
| 187 | ipl->start_addr = ipl->bios_start_addr; |
| 188 | } |
| 189 | |
| 190 | if (ipl->kernel) { |
| 191 | kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL, |
| 192 | &pentry, NULL, |
| 193 | NULL, NULL, ELFDATA2MSB, EM_S390, 0, 0); |
| 194 | if (kernel_size < 0) { |
| 195 | kernel_size = load_image_targphys(ipl->kernel, 0, ms->ram_size, |
| 196 | NULL); |
| 197 | if (kernel_size < 0) { |
| 198 | error_setg(errp, "could not load kernel '%s'", ipl->kernel); |
| 199 | return; |
| 200 | } |
| 201 | /* if this is Linux use KERN_IMAGE_START */ |
| 202 | magic = rom_ptr(LINUX_MAGIC_ADDR, 6); |
| 203 | if (magic && !memcmp(magic, "S390EP", 6)) { |
| 204 | pentry = KERN_IMAGE_START; |
| 205 | } else { |
| 206 | /* if not Linux load the address of the (short) IPL PSW */ |
| 207 | ipl_psw = rom_ptr(4, 4); |
| 208 | if (ipl_psw) { |
| 209 | pentry = be32_to_cpu(*ipl_psw) & PSW_MASK_SHORT_ADDR; |
| 210 | } else { |
| 211 | error_setg(errp, "Could not get IPL PSW"); |
| 212 | return; |
| 213 | } |
| 214 | } |
| 215 | } |
| 216 | /* |
| 217 | * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the |
| 218 | * kernel parameters here as well. Note: For old kernels (up to 3.2) |
| 219 | * we can not rely on the ELF entry point - it was 0x800 (the SALIPL |
| 220 | * loader) and it won't work. For this case we force it to 0x10000, too. |
| 221 | */ |
| 222 | if (pentry == KERN_IMAGE_START || pentry == 0x800) { |
| 223 | size_t cmdline_size = strlen(ipl->cmdline) + 1; |
| 224 | char *parm_area = rom_ptr(KERN_PARM_AREA, cmdline_size); |
| 225 | |
| 226 | ipl->start_addr = KERN_IMAGE_START; |
| 227 | /* Overwrite parameters in the kernel image, which are "rom" */ |
| 228 | if (parm_area) { |
| 229 | uint64_t max_cmdline_size = get_max_kernel_cmdline_size(); |
| 230 | |
| 231 | if (cmdline_size > max_cmdline_size) { |
| 232 | error_setg(errp, |
| 233 | "kernel command line exceeds maximum size:" |
| 234 | " %zu > %" PRIu64, |
| 235 | cmdline_size, max_cmdline_size); |
| 236 | return; |
| 237 | } |
| 238 | |
| 239 | strcpy(parm_area, ipl->cmdline); |
| 240 | } |
| 241 | } else { |
| 242 | ipl->start_addr = pentry; |
| 243 | } |
| 244 | |
| 245 | if (ipl->initrd) { |
| 246 | ram_addr_t initrd_offset; |
| 247 | int initrd_size; |
| 248 | uint64_t *romptr; |
| 249 | |
| 250 | initrd_offset = INITRD_START; |
| 251 | while (kernel_size + 0x100000 > initrd_offset) { |
| 252 | initrd_offset += 0x100000; |
| 253 | } |
| 254 | initrd_size = load_image_targphys(ipl->initrd, initrd_offset, |
| 255 | ms->ram_size - initrd_offset, |
| 256 | NULL); |
| 257 | if (initrd_size == -1) { |
| 258 | error_setg(errp, "could not load initrd '%s'", ipl->initrd); |
| 259 | return; |
| 260 | } |
| 261 | |
| 262 | /* |
| 263 | * we have to overwrite values in the kernel image, |
| 264 | * which are "rom" |
| 265 | */ |
| 266 | romptr = rom_ptr(INITRD_PARM_START, 16); |
| 267 | if (romptr) { |
| 268 | stq_be_p(romptr, initrd_offset); |
| 269 | stq_be_p(romptr + 1, initrd_size); |
| 270 | } |
| 271 | } |
| 272 | } |
| 273 | /* |
| 274 | * Don't ever use the migrated values, they could come from a different |
| 275 | * BIOS and therefore don't work. But still migrate the values, so |
| 276 | * QEMUs relying on it don't break. |
| 277 | */ |
| 278 | ipl->compat_start_addr = ipl->start_addr; |
| 279 | ipl->compat_bios_start_addr = ipl->bios_start_addr; |
| 280 | /* |
| 281 | * Because this Device is not on any bus in the qbus tree (it is |
| 282 | * not a sysbus device and it's not on some other bus like a PCI |
| 283 | * bus) it will not be automatically reset by the 'reset the |
| 284 | * sysbus' hook registered by vl.c like most devices. So we must |
| 285 | * manually register a reset hook for it. |
| 286 | * TODO: there should be a better way to do this. |
| 287 | */ |
| 288 | qemu_register_reset(resettable_cold_reset_fn, dev); |
| 289 | } |
| 290 | |
| 291 | static const Property s390_ipl_properties[] = { |
| 292 | DEFINE_PROP_STRING("kernel", S390IPLState, kernel), |
| 293 | DEFINE_PROP_STRING("initrd", S390IPLState, initrd), |
| 294 | DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline), |
| 295 | DEFINE_PROP_STRING("firmware", S390IPLState, firmware), |
| 296 | DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false), |
| 297 | }; |
| 298 | |
| 299 | static void s390_ipl_set_boot_menu(S390IPLState *ipl) |
| 300 | { |
| 301 | unsigned long splash_time = 0; |
| 302 | |
| 303 | if (!get_boot_device(0)) { |
| 304 | if (current_machine->boot_config.has_menu && current_machine->boot_config.menu) { |
| 305 | error_report("boot menu requires a bootindex to be specified for " |
| 306 | "the IPL device"); |
| 307 | } |
| 308 | return; |
| 309 | } |
| 310 | |
| 311 | switch (ipl->iplb.pbt) { |
| 312 | case S390_IPL_TYPE_CCW: |
| 313 | /* In the absence of -boot menu, use zipl parameters */ |
| 314 | if (!current_machine->boot_config.has_menu) { |
| 315 | ipl->qipl.qipl_flags |= QIPL_FLAG_BM_OPTS_ZIPL; |
| 316 | return; |
| 317 | } |
| 318 | break; |
| 319 | case S390_IPL_TYPE_PCI: |
| 320 | case S390_IPL_TYPE_QEMU_SCSI: |
| 321 | break; |
| 322 | default: |
| 323 | if (current_machine->boot_config.has_menu && current_machine->boot_config.menu) { |
| 324 | error_report("boot menu is not supported for this device type"); |
| 325 | } |
| 326 | return; |
| 327 | } |
| 328 | |
| 329 | if (!current_machine->boot_config.has_menu || !current_machine->boot_config.menu) { |
| 330 | return; |
| 331 | } |
| 332 | |
| 333 | ipl->qipl.qipl_flags |= QIPL_FLAG_BM_OPTS_CMD; |
| 334 | |
| 335 | if (current_machine->boot_config.has_splash_time) { |
| 336 | splash_time = current_machine->boot_config.splash_time; |
| 337 | } |
| 338 | if (splash_time > 0xffffffff) { |
| 339 | error_report("splash-time is too large, forcing it to max value"); |
| 340 | ipl->qipl.boot_menu_timeout = 0xffffffff; |
| 341 | return; |
| 342 | } |
| 343 | |
| 344 | ipl->qipl.boot_menu_timeout = cpu_to_be32(splash_time); |
| 345 | } |
| 346 | |
| 347 | #define S390_DEVTYPE_NONE 0x00 |
| 348 | |
| 349 | #define CCW_DEVTYPE_VIRTIO 0x01 |
| 350 | #define CCW_DEVTYPE_VIRTIO_NET 0x02 |
| 351 | #define CCW_DEVTYPE_SCSI 0x03 |
| 352 | #define CCW_DEVTYPE_VFIO 0x04 |
| 353 | |
| 354 | static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype) |
| 355 | { |
| 356 | CcwDevice *ccw_dev = NULL; |
| 357 | int tmp_dt = S390_DEVTYPE_NONE; |
| 358 | |
| 359 | if (dev_st) { |
| 360 | VirtIONet *virtio_net_dev = (VirtIONet *) |
| 361 | object_dynamic_cast(OBJECT(dev_st), TYPE_VIRTIO_NET); |
| 362 | VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *) |
| 363 | object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), |
| 364 | TYPE_VIRTIO_CCW_DEVICE); |
| 365 | VFIOCCWDevice *vfio_ccw_dev = (VFIOCCWDevice *) |
| 366 | object_dynamic_cast(OBJECT(dev_st), TYPE_VFIO_CCW); |
| 367 | |
| 368 | if (virtio_ccw_dev) { |
| 369 | ccw_dev = CCW_DEVICE(virtio_ccw_dev); |
| 370 | if (virtio_net_dev) { |
| 371 | tmp_dt = CCW_DEVTYPE_VIRTIO_NET; |
| 372 | } else { |
| 373 | tmp_dt = CCW_DEVTYPE_VIRTIO; |
| 374 | } |
| 375 | } else if (vfio_ccw_dev) { |
| 376 | ccw_dev = CCW_DEVICE(vfio_ccw_dev); |
| 377 | tmp_dt = CCW_DEVTYPE_VFIO; |
| 378 | } else { |
| 379 | SCSIDevice *sd = (SCSIDevice *) |
| 380 | object_dynamic_cast(OBJECT(dev_st), |
| 381 | TYPE_SCSI_DEVICE); |
| 382 | if (sd) { |
| 383 | SCSIBus *sbus = scsi_bus_from_device(sd); |
| 384 | VirtIODevice *vdev = (VirtIODevice *) |
| 385 | object_dynamic_cast(OBJECT(sbus->qbus.parent), |
| 386 | TYPE_VIRTIO_DEVICE); |
| 387 | if (vdev) { |
| 388 | ccw_dev = (CcwDevice *) |
| 389 | object_dynamic_cast(OBJECT(qdev_get_parent_bus(DEVICE(vdev))->parent), |
| 390 | TYPE_CCW_DEVICE); |
| 391 | if (ccw_dev) { |
| 392 | tmp_dt = CCW_DEVTYPE_SCSI; |
| 393 | } |
| 394 | } |
| 395 | } |
| 396 | } |
| 397 | } |
| 398 | if (devtype) { |
| 399 | *devtype = tmp_dt; |
| 400 | } |
| 401 | return ccw_dev; |
| 402 | } |
| 403 | |
| 404 | #define PCI_DEVTYPE_VIRTIO 0x05 |
| 405 | |
| 406 | static S390PCIBusDevice *s390_get_pci_device(DeviceState *dev_st, int *devtype) |
| 407 | { |
| 408 | S390PCIBusDevice *pbdev = NULL; |
| 409 | int tmp_dt = S390_DEVTYPE_NONE; |
| 410 | |
| 411 | if (dev_st) { |
| 412 | PCIDevice *pci_dev = (PCIDevice *) |
| 413 | object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), |
| 414 | TYPE_VIRTIO_PCI); |
| 415 | if (pci_dev) { |
| 416 | pbdev = s390_pci_find_dev_by_pci(s390_get_phb(), pci_dev); |
| 417 | if (pbdev) { |
| 418 | tmp_dt = PCI_DEVTYPE_VIRTIO; |
| 419 | } |
| 420 | } |
| 421 | } |
| 422 | if (devtype) { |
| 423 | *devtype = tmp_dt; |
| 424 | } |
| 425 | |
| 426 | return pbdev; |
| 427 | } |
| 428 | |
| 429 | static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain, uint16_t count) |
| 430 | { |
| 431 | S390IPLState *ipl = get_ipl_device(); |
| 432 | uint64_t len = sizeof(IplParameterBlock) * count; |
| 433 | uint64_t chain_addr = find_iplb_chain_addr(ipl->bios_start_addr, count); |
| 434 | |
| 435 | physical_memory_write(chain_addr, iplb_chain, len); |
| 436 | return chain_addr; |
| 437 | } |
| 438 | |
| 439 | void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp) |
| 440 | { |
| 441 | /* Initialize the loadparm with spaces */ |
| 442 | memset(loadparm, ' ', LOADPARM_LEN); |
| 443 | qdev_prop_sanitize_s390x_loadparm(loadparm, str, errp); |
| 444 | } |
| 445 | |
| 446 | void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp) |
| 447 | { |
| 448 | int i; |
| 449 | |
| 450 | /* Initialize the loadparm with EBCDIC spaces (0x40) */ |
| 451 | memset(ebcdic_lp, '@', LOADPARM_LEN); |
| 452 | for (i = 0; i < LOADPARM_LEN && ascii_lp[i]; i++) { |
| 453 | ebcdic_lp[i] = ascii2ebcdic[(uint8_t) ascii_lp[i]]; |
| 454 | } |
| 455 | } |
| 456 | |
| 457 | S390IPLCertificateStore *s390_ipl_get_certificate_store(void) |
| 458 | { |
| 459 | S390IPLState *ipl = get_ipl_device(); |
| 460 | |
| 461 | return &ipl->cert_store; |
| 462 | } |
| 463 | |
| 464 | static bool s390_has_certificate(void) |
| 465 | { |
| 466 | S390IPLState *ipl = get_ipl_device(); |
| 467 | |
| 468 | return ipl->cert_store.count > 0; |
| 469 | } |
| 470 | |
| 471 | static bool s390_secure_boot_enabled(void) |
| 472 | { |
| 473 | return S390_CCW_MACHINE(qdev_get_machine())->secure_boot; |
| 474 | } |
| 475 | |
| 476 | static void s390_set_secure_boot_flags(IplParameterBlock *iplb, |
| 477 | bool secure_boot, bool audit_mode) |
| 478 | { |
| 479 | if (!secure_boot && !audit_mode) { |
| 480 | return; |
| 481 | } |
| 482 | |
| 483 | /* |
| 484 | * If secure-boot is enabled, then toggle the secure IPL flags (SIPL) to |
| 485 | * trigger secure boot in the s390 BIOS. |
| 486 | * |
| 487 | * Boot process will terminate if any error occurs during secure boot. |
| 488 | */ |
| 489 | if (secure_boot) { |
| 490 | iplb->hdr_flags |= DIAG308_IPIB_FLAGS_SIPL; |
| 491 | } |
| 492 | |
| 493 | /* |
| 494 | * For both secure boot and audit mode, enable the IPL Information |
| 495 | * Report (IPLIR) flag so that the firmware generates an IPL |
| 496 | * Information Report Block (IIRB). |
| 497 | * |
| 498 | * Results of secure boot will be stored in IIRB. |
| 499 | * |
| 500 | * Extend the IPL parameter block to its maximum length to ensure |
| 501 | * sufficient space for the BIOS to populate the IIRB. |
| 502 | */ |
| 503 | iplb->hdr_flags |= DIAG308_IPIB_FLAGS_IPLIR; |
| 504 | iplb->len = cpu_to_be32(S390_IPLB_MAX_LEN); |
| 505 | } |
| 506 | |
| 507 | static bool s390_validate_secure_boot_device(int devtype, Error **errp) |
| 508 | { |
| 509 | switch (devtype) { |
| 510 | case CCW_DEVTYPE_VFIO: |
| 511 | error_setg(errp, "Passthrough (vfio) CCW device does not support secure boot!"); |
| 512 | return false; |
| 513 | case CCW_DEVTYPE_VIRTIO_NET: |
| 514 | error_setg(errp, "Virtio net boot device does not support secure boot!"); |
| 515 | return false; |
| 516 | default: |
| 517 | return true; |
| 518 | } |
| 519 | } |
| 520 | |
| 521 | static void s390_apply_secure_boot(IplParameterBlock *iplb, int devtype, |
| 522 | bool secure_boot, bool audit_mode) |
| 523 | { |
| 524 | Error *local_error = NULL; |
| 525 | |
| 526 | if (!secure_boot && !audit_mode) { |
| 527 | return; |
| 528 | } |
| 529 | |
| 530 | if (!s390_validate_secure_boot_device(devtype, &local_error)) { |
| 531 | error_report_err(local_error); |
| 532 | exit(1); |
| 533 | } |
| 534 | |
| 535 | s390_set_secure_boot_flags(iplb, secure_boot, audit_mode); |
| 536 | } |
| 537 | |
| 538 | static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb) |
| 539 | { |
| 540 | CcwDevice *ccw_dev = NULL; |
| 541 | S390PCIBusDevice *pbdev = NULL; |
| 542 | SCSIDevice *sd; |
| 543 | int devtype; |
| 544 | uint8_t *lp; |
| 545 | g_autofree void *scsi_lp = NULL; |
| 546 | g_autofree void *pci_lp = NULL; |
| 547 | |
| 548 | ccw_dev = s390_get_ccw_device(dev_st, &devtype); |
| 549 | if (ccw_dev) { |
| 550 | lp = ccw_dev->loadparm; |
| 551 | |
| 552 | switch (devtype) { |
| 553 | case CCW_DEVTYPE_SCSI: |
| 554 | sd = SCSI_DEVICE(dev_st); |
| 555 | scsi_lp = object_property_get_str(OBJECT(sd), "loadparm", NULL); |
| 556 | if (scsi_lp && strlen(scsi_lp) > 0) { |
| 557 | lp = scsi_lp; |
| 558 | } |
| 559 | iplb->len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN); |
| 560 | iplb->blk0_len = |
| 561 | cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN); |
| 562 | iplb->pbt = S390_IPL_TYPE_QEMU_SCSI; |
| 563 | iplb->scsi.lun = cpu_to_be32(sd->lun); |
| 564 | iplb->scsi.target = cpu_to_be16(sd->id); |
| 565 | iplb->scsi.channel = cpu_to_be16(sd->channel); |
| 566 | iplb->scsi.devno = cpu_to_be16(ccw_dev->sch->devno); |
| 567 | iplb->scsi.ssid = ccw_dev->sch->ssid & 3; |
| 568 | break; |
| 569 | case CCW_DEVTYPE_VFIO: |
| 570 | iplb->len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); |
| 571 | iplb->pbt = S390_IPL_TYPE_CCW; |
| 572 | iplb->ccw.devno = cpu_to_be16(ccw_dev->sch->devno); |
| 573 | iplb->ccw.ssid = ccw_dev->sch->ssid & 3; |
| 574 | break; |
| 575 | case CCW_DEVTYPE_VIRTIO_NET: |
| 576 | case CCW_DEVTYPE_VIRTIO: |
| 577 | iplb->len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); |
| 578 | iplb->blk0_len = |
| 579 | cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); |
| 580 | iplb->pbt = S390_IPL_TYPE_CCW; |
| 581 | iplb->ccw.devno = cpu_to_be16(ccw_dev->sch->devno); |
| 582 | iplb->ccw.ssid = ccw_dev->sch->ssid & 3; |
| 583 | break; |
| 584 | } |
| 585 | |
| 586 | /* If the device loadparm is empty use the global machine loadparm */ |
| 587 | if (memcmp(lp, NO_LOADPARM, 8) == 0) { |
| 588 | lp = S390_CCW_MACHINE(qdev_get_machine())->loadparm; |
| 589 | } |
| 590 | |
| 591 | s390_ipl_convert_loadparm((char *)lp, iplb->loadparm); |
| 592 | iplb->flags |= DIAG308_FLAGS_LP_VALID; |
| 593 | |
| 594 | s390_apply_secure_boot(iplb, devtype, s390_secure_boot_enabled(), |
| 595 | s390_has_certificate()); |
| 596 | |
| 597 | return true; |
| 598 | } |
| 599 | |
| 600 | pbdev = s390_get_pci_device(dev_st, &devtype); |
| 601 | if (pbdev) { |
| 602 | if (s390_secure_boot_enabled() || s390_has_certificate()) { |
| 603 | error_report("Virtio pci boot device does not support secure boot!"); |
| 604 | exit(1); |
| 605 | } |
| 606 | |
| 607 | pci_lp = object_property_get_str(OBJECT(pbdev->pdev), "loadparm", NULL); |
| 608 | if (pci_lp && strlen(pci_lp) > 0) { |
| 609 | lp = pci_lp; |
| 610 | } else { |
| 611 | /* Use machine loadparm as a place holder if PCI LP is unset */ |
| 612 | lp = S390_CCW_MACHINE(qdev_get_machine())->loadparm; |
| 613 | } |
| 614 | |
| 615 | switch (devtype) { |
| 616 | case PCI_DEVTYPE_VIRTIO: |
| 617 | iplb->len = cpu_to_be32(S390_IPLB_MIN_PCI_LEN); |
| 618 | iplb->pbt = S390_IPL_TYPE_PCI; |
| 619 | iplb->pci.fid = cpu_to_be32(pbdev->fid); |
| 620 | break; |
| 621 | default: |
| 622 | return false; |
| 623 | } |
| 624 | |
| 625 | s390_ipl_convert_loadparm((char *)lp, iplb->loadparm); |
| 626 | iplb->flags |= DIAG308_FLAGS_LP_VALID; |
| 627 | |
| 628 | return true; |
| 629 | } |
| 630 | |
| 631 | return false; |
| 632 | } |
| 633 | |
| 634 | void s390_rebuild_iplb(uint16_t dev_index, IplParameterBlock *iplb) |
| 635 | { |
| 636 | S390IPLState *ipl = get_ipl_device(); |
| 637 | uint16_t index; |
| 638 | index = ipl->rebuilt_iplb ? ipl->iplb_index : dev_index; |
| 639 | |
| 640 | ipl->rebuilt_iplb = s390_build_iplb(get_boot_device(index), iplb); |
| 641 | ipl->iplb_index = index; |
| 642 | } |
| 643 | |
| 644 | static bool s390_init_all_iplbs(S390IPLState *ipl) |
| 645 | { |
| 646 | int iplb_num = 0; |
| 647 | IplParameterBlock iplb_chain[MAX_BOOT_DEVS - 1] = { 0 }; |
| 648 | DeviceState *dev_st = get_boot_device(0); |
| 649 | Object *machine = qdev_get_machine(); |
| 650 | |
| 651 | /* |
| 652 | * Parse the boot devices. Generate an IPLB for only the first boot device |
| 653 | * which will later be set with DIAG308. |
| 654 | */ |
| 655 | if (!dev_st) { |
| 656 | ipl->qipl.chain_len = 0; |
| 657 | return false; |
| 658 | } |
| 659 | |
| 660 | /* If no machine loadparm was defined fill it with spaces */ |
| 661 | if (memcmp(S390_CCW_MACHINE(machine)->loadparm, NO_LOADPARM, 8) == 0) { |
| 662 | object_property_set_str(machine, "loadparm", " ", NULL); |
| 663 | } |
| 664 | |
| 665 | iplb_num = 1; |
| 666 | s390_build_iplb(dev_st, &ipl->iplb); |
| 667 | |
| 668 | /* Index any fallback boot devices */ |
| 669 | while (get_boot_device(iplb_num)) { |
| 670 | iplb_num++; |
| 671 | } |
| 672 | |
| 673 | if (iplb_num > MAX_BOOT_DEVS) { |
| 674 | warn_report("Excess boot devices defined! %d boot devices found, " |
| 675 | "but only the first %d will be considered.", |
| 676 | iplb_num, MAX_BOOT_DEVS); |
| 677 | |
| 678 | iplb_num = MAX_BOOT_DEVS; |
| 679 | } |
| 680 | |
| 681 | ipl->qipl.chain_len = cpu_to_be16(iplb_num - 1); |
| 682 | |
| 683 | /* |
| 684 | * Build fallback IPLBs for any boot devices above index 0, up to a |
| 685 | * maximum amount as defined in ipl.h |
| 686 | */ |
| 687 | if (iplb_num > 1) { |
| 688 | /* Start at 1 because the IPLB for boot index 0 is not chained */ |
| 689 | for (int i = 1; i < iplb_num; i++) { |
| 690 | dev_st = get_boot_device(i); |
| 691 | s390_build_iplb(dev_st, &iplb_chain[i - 1]); |
| 692 | } |
| 693 | } |
| 694 | |
| 695 | /* |
| 696 | * Allocate maximum space for IPLB chain and/or certificate storage. |
| 697 | * Once a valid boot device is found, this space will be used to store |
| 698 | * certificates if secure boot is enabled. |
| 699 | */ |
| 700 | if (iplb_num > 1 || s390_has_certificate()) { |
| 701 | ipl->qipl.ipl_data = cpu_to_be64(s390_ipl_map_iplb_chain(iplb_chain, |
| 702 | MAX_BOOT_DEVS - 1)); |
| 703 | } |
| 704 | |
| 705 | return iplb_num; |
| 706 | } |
| 707 | |
| 708 | QEMU_BUILD_BUG_MSG(sizeof(IplParameterBlock) * (MAX_BOOT_DEVS - 1) != CERT_BUF_SIZE, |
| 709 | "certificate buffer size is wrong"); |
| 710 | |
| 711 | static void update_machine_ipl_properties(IplParameterBlock *iplb) |
| 712 | { |
| 713 | Object *machine = qdev_get_machine(); |
| 714 | Error *err = NULL; |
| 715 | |
| 716 | /* Sync loadparm */ |
| 717 | if (iplb->flags & DIAG308_FLAGS_LP_VALID) { |
| 718 | uint8_t *ebcdic_loadparm = iplb->loadparm; |
| 719 | char ascii_loadparm[9]; |
| 720 | int i; |
| 721 | |
| 722 | for (i = 0; i < 8 && ebcdic_loadparm[i]; i++) { |
| 723 | ascii_loadparm[i] = ebcdic2ascii[(uint8_t) ebcdic_loadparm[i]]; |
| 724 | } |
| 725 | ascii_loadparm[i] = 0; |
| 726 | object_property_set_str(machine, "loadparm", ascii_loadparm, &err); |
| 727 | } else { |
| 728 | object_property_set_str(machine, "loadparm", " ", &err); |
| 729 | } |
| 730 | if (err) { |
| 731 | warn_report_err(err); |
| 732 | } |
| 733 | } |
| 734 | |
| 735 | void s390_ipl_update_diag308(IplParameterBlock *iplb) |
| 736 | { |
| 737 | S390IPLState *ipl = get_ipl_device(); |
| 738 | |
| 739 | /* |
| 740 | * The IPLB set and retrieved by subcodes 8/9 is completely |
| 741 | * separate from the one managed via subcodes 5/6. |
| 742 | */ |
| 743 | if (iplb->pbt == S390_IPL_TYPE_PV) { |
| 744 | ipl->iplb_pv = *iplb; |
| 745 | ipl->iplb_valid_pv = true; |
| 746 | } else { |
| 747 | ipl->iplb = *iplb; |
| 748 | ipl->iplb_valid = true; |
| 749 | |
| 750 | /* |
| 751 | * The kernel does not preserve secure boot flags across a reboot. |
| 752 | * Re-apply them here based on the current machine configuration. |
| 753 | */ |
| 754 | s390_set_secure_boot_flags(&ipl->iplb, |
| 755 | s390_secure_boot_enabled(), |
| 756 | s390_has_certificate()); |
| 757 | } |
| 758 | |
| 759 | update_machine_ipl_properties(iplb); |
| 760 | } |
| 761 | |
| 762 | IplParameterBlock *s390_ipl_get_iplb_pv(void) |
| 763 | { |
| 764 | S390IPLState *ipl = get_ipl_device(); |
| 765 | |
| 766 | if (!ipl->iplb_valid_pv) { |
| 767 | return NULL; |
| 768 | } |
| 769 | return &ipl->iplb_pv; |
| 770 | } |
| 771 | |
| 772 | IplParameterBlock *s390_ipl_get_iplb(void) |
| 773 | { |
| 774 | S390IPLState *ipl = get_ipl_device(); |
| 775 | |
| 776 | if (!ipl->iplb_valid) { |
| 777 | return NULL; |
| 778 | } |
| 779 | return &ipl->iplb; |
| 780 | } |
| 781 | |
| 782 | void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type) |
| 783 | { |
| 784 | S390IPLState *ipl = get_ipl_device(); |
| 785 | if (reset_type == S390_RESET_EXTERNAL || reset_type == S390_RESET_REIPL) { |
| 786 | /* use CPU 0 for full resets */ |
| 787 | ipl->reset_cpu_index = 0; |
| 788 | } else { |
| 789 | ipl->reset_cpu_index = cs->cpu_index; |
| 790 | } |
| 791 | |
| 792 | ipl->reset_type = reset_type; |
| 793 | if (reset_type == S390_RESET_MODIFIED_CLEAR || |
| 794 | reset_type == S390_RESET_LOAD_NORMAL || |
| 795 | reset_type == S390_RESET_PV) { |
| 796 | /* ignore -no-reboot, send no event */ |
| 797 | qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET); |
| 798 | } else { |
| 799 | qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); |
| 800 | } |
| 801 | } |
| 802 | |
| 803 | void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type) |
| 804 | { |
| 805 | S390IPLState *ipl = get_ipl_device(); |
| 806 | |
| 807 | *cs = qemu_get_cpu(ipl->reset_cpu_index); |
| 808 | if (!*cs) { |
| 809 | /* use any CPU */ |
| 810 | *cs = first_cpu; |
| 811 | } |
| 812 | *reset_type = ipl->reset_type; |
| 813 | } |
| 814 | |
| 815 | void s390_ipl_clear_reset_request(void) |
| 816 | { |
| 817 | S390IPLState *ipl = get_ipl_device(); |
| 818 | |
| 819 | ipl->reset_type = S390_RESET_EXTERNAL; |
| 820 | /* use CPU 0 for full resets */ |
| 821 | ipl->reset_cpu_index = 0; |
| 822 | } |
| 823 | |
| 824 | static void s390_ipl_prepare_qipl(S390CPU *cpu) |
| 825 | { |
| 826 | S390IPLState *ipl = get_ipl_device(); |
| 827 | uint8_t *addr; |
| 828 | uint64_t len = 4096; |
| 829 | |
| 830 | addr = physical_memory_map(cpu->env.psa, &len, true); |
| 831 | if (!addr || len < QIPL_ADDRESS + sizeof(QemuIplParameters)) { |
| 832 | error_report("Cannot set QEMU IPL parameters"); |
| 833 | return; |
| 834 | } |
| 835 | memcpy(addr + QIPL_ADDRESS, &ipl->qipl, sizeof(QemuIplParameters)); |
| 836 | physical_memory_unmap(addr, len, 1, len); |
| 837 | } |
| 838 | |
| 839 | int s390_ipl_prepare_pv_header(struct S390PVResponse *pv_resp, Error **errp) |
| 840 | { |
| 841 | IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); |
| 842 | IPLBlockPV *ipib_pv = &ipib->pv; |
| 843 | void *hdr = g_malloc(ipib_pv->pv_header_len); |
| 844 | int rc; |
| 845 | |
| 846 | physical_memory_read(ipib_pv->pv_header_addr, hdr, |
| 847 | ipib_pv->pv_header_len); |
| 848 | rc = s390_pv_set_sec_parms((uintptr_t)hdr, ipib_pv->pv_header_len, |
| 849 | pv_resp, errp); |
| 850 | g_free(hdr); |
| 851 | return rc; |
| 852 | } |
| 853 | |
| 854 | int s390_ipl_pv_unpack(struct S390PVResponse *pv_resp) |
| 855 | { |
| 856 | IplParameterBlock *ipib = s390_ipl_get_iplb_pv(); |
| 857 | IPLBlockPV *ipib_pv = &ipib->pv; |
| 858 | int i, rc = 0; |
| 859 | |
| 860 | for (i = 0; i < ipib_pv->num_comp; i++) { |
| 861 | rc = s390_pv_unpack(ipib_pv->components[i].addr, |
| 862 | TARGET_PAGE_ALIGN(ipib_pv->components[i].size), |
| 863 | ipib_pv->components[i].tweak_pref, |
| 864 | pv_resp); |
| 865 | if (rc) { |
| 866 | break; |
| 867 | } |
| 868 | } |
| 869 | return rc; |
| 870 | } |
| 871 | |
| 872 | void s390_ipl_prepare_cpu(S390CPU *cpu) |
| 873 | { |
| 874 | S390IPLState *ipl = get_ipl_device(); |
| 875 | |
| 876 | cpu->env.psw.addr = ipl->start_addr; |
| 877 | cpu->env.psw.mask = IPL_PSW_MASK; |
| 878 | |
| 879 | s390_ipl_create_cert_store(&ipl->cert_store); |
| 880 | |
| 881 | if (!ipl->kernel || ipl->iplb_valid) { |
| 882 | cpu->env.psw.addr = ipl->bios_start_addr; |
| 883 | if (!ipl->iplb_valid) { |
| 884 | ipl->iplb_valid = s390_init_all_iplbs(ipl); |
| 885 | |
| 886 | /* |
| 887 | * Secure IPL without specifying a boot device. |
| 888 | * IPLB is not generated if no boot device is defined. |
| 889 | */ |
| 890 | if ((s390_has_certificate() || s390_secure_boot_enabled()) && |
| 891 | !ipl->iplb_valid) { |
| 892 | error_report("No boot device defined for Secure IPL"); |
| 893 | exit(1); |
| 894 | } |
| 895 | } else { |
| 896 | ipl->qipl.chain_len = 0; |
| 897 | } |
| 898 | } |
| 899 | s390_ipl_set_boot_menu(ipl); |
| 900 | s390_ipl_prepare_qipl(cpu); |
| 901 | } |
| 902 | |
| 903 | static void s390_ipl_reset(DeviceState *dev) |
| 904 | { |
| 905 | S390IPLState *ipl = S390_IPL(dev); |
| 906 | |
| 907 | if (ipl->reset_type != S390_RESET_REIPL) { |
| 908 | ipl->iplb_valid = false; |
| 909 | memset(&ipl->iplb, 0, sizeof(IplParameterBlock)); |
| 910 | } |
| 911 | } |
| 912 | |
| 913 | static void s390_ipl_class_init(ObjectClass *klass, const void *data) |
| 914 | { |
| 915 | DeviceClass *dc = DEVICE_CLASS(klass); |
| 916 | |
| 917 | dc->realize = s390_ipl_realize; |
| 918 | device_class_set_props(dc, s390_ipl_properties); |
| 919 | device_class_set_legacy_reset(dc, s390_ipl_reset); |
| 920 | dc->vmsd = &vmstate_ipl; |
| 921 | set_bit(DEVICE_CATEGORY_MISC, dc->categories); |
| 922 | /* Reason: Loads the ROMs and thus can only be used one time - internally */ |
| 923 | dc->user_creatable = false; |
| 924 | } |
| 925 | |
| 926 | static const TypeInfo s390_ipl_info = { |
| 927 | .class_init = s390_ipl_class_init, |
| 928 | .parent = TYPE_DEVICE, |
| 929 | .name = TYPE_S390_IPL, |
| 930 | .instance_size = sizeof(S390IPLState), |
| 931 | }; |
| 932 | |
| 933 | static void s390_ipl_register_types(void) |
| 934 | { |
| 935 | type_register_static(&s390_ipl_info); |
| 936 | } |
| 937 | |
| 938 | type_init(s390_ipl_register_types) |