Files
s390-tools/include/boot/ipl.h
Marc Hartmayer 3356d6f4fa genprotimg: boot: initial bootloader support
Add a boot loader for protected virtualization (PV) that can be
combined with a kernel/initrd/parmfile to form a single bootable file.
This file must be constructed in a way that it can be used (1) for a
QEMU direct kernel boot and (2) it can be zipl'ed by the normal,
unmodified zipl program.

This new boot loader consists of two parts:

1. stage3a boot loader (cleartext), this loader is responsible for
   the transition into the protected mode by doing diag308 subcode 8
   and 10 calls.

2. stage3b boot loader (encrypted), this loader is very similar to the
   normal zipl stage3 boot loader. It will be loaded by the Ultravisor
   after the successful transition into protected mode. Like the zipl
   stage3 boot loader it moves the kernel and patches in the values
   for initrd and parmline.

The requirements for (1) and (2) result in the following constraints:

1. It must be possible to place stage3a and stage3b at a location >=
   0x10000 because the zipl stage3 loader zeroes out everything at
   addresses lower than 0x10000 of the image.

2. As the stage3 loader of zipl assumes that the passed kernel image
   looks like a normal kernel image, the zipl stage3 loader modifies the
   content at the memory area 0x10400 - 0x10800, therefore we leave this
   area unused in our stage3a loader.

3. The default entry address used by the zipl stage3 loader is 0x10000
   so we add a simple branch to 0x11000 at 0x10000 so the zipl stage3
   loader can modify the area 0x10400 - 0x10800 without affecting the
   stage3a loader.

The stage3b loader is linked at address 0x9000, therefore it will not
work at another address. The relocation support for the stage3b
loader, so that it can be placed at addresses != 0x9000, is added in
the next patch. This loader with relocation support has the name
'stage3b_reloc'.

The memory layout of the single bootable file looks like:

+-----------------------+-----------+------------------------+
|Start                  |End        |Use                     |
+=======================+===========+========================+
|0                      |0x7        |Short PSW, starting     |
|                       |           |instruction at 0x11000  |
+-----------------------+-----------+------------------------+
|0x10000                |0x10012    |Branch to 0x11000       |
+-----------------------+-----------+------------------------+
|0x10013                |0x10fff    |Left intentionally      |
|                       |           |unused                  |
+-----------------------+-----------+------------------------+
|0x11000                |0x12fff    |Stage3a                 |
+-----------------------+-----------+------------------------+
|0x13000                |0x13fff    |IPIB used as argument   |
|                       |           |for the diag308 call    |
+-----------------------+-----------+------------------------+
|0x14000                |0x1[45]fff |UV header used for the  |
|                       |           |diag308 call (size can  |
|                       |           |be either 1 or 2 pages) |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Kernel        |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Cmdline       |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Initrd        |
+-----------------------+-----------+------------------------+
|NEXT_PAGE_ALIGNED_ADDR |           |Encrypted Stage3b_reloc |
+-----------------------+-----------+------------------------+

Reviewed-by: Philipp Rudo <prudo@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2020-03-16 13:39:10 +01:00

186 lines
3.7 KiB
C

/*
* IPL related definitions
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef IPL_H
#define IPL_H
#include "lib/zt_common.h"
#include "s390.h"
#define IPL_FLAG_SECURE 0x40
#define IPL_RB_COMPONENT_FLAG_SIGNED 0x80
#define IPL_RB_COMPONENT_FLAG_VERIFIED 0x40
#ifndef __ASSEMBLER__
#include <stdint.h>
/* IPL Parameter List header */
struct ipl_pl_hdr {
uint32_t len;
uint8_t flags;
uint8_t reserved1[2];
uint8_t version;
} __packed;
/* IPL Parameter Block header */
struct ipl_pb_hdr {
uint32_t len;
uint8_t pbt;
} __packed;
/* IPL Parameter Block 0 with common fields */
struct ipl_pb0_common {
uint32_t len;
uint8_t pbt;
uint8_t flags;
uint8_t reserved1[2];
uint8_t loadparm[8];
uint8_t reserved2[84];
} __packed;
/* IPL Parameter Block 0 for FCP */
struct ipl_pb0_fcp {
uint32_t len;
uint8_t pbt;
uint8_t reserved1[3];
uint8_t loadparm[8];
uint8_t reserved2[304];
uint8_t opt;
uint8_t reserved3[3];
uint8_t cssid;
uint8_t reserved4[1];
uint8_t devno;
uint8_t reserved5[4];
uint64_t wwpn;
uint64_t lun;
uint32_t bootprog;
uint8_t reserved6[12];
uint64_t br_lba;
uint32_t scp_data_len;
uint8_t reserved7[260];
uint8_t scp_data[];
} __packed;
/* IPL Parameter Block 0 for CCW */
struct ipl_pb0_ccw {
uint32_t len;
uint8_t pbt;
uint8_t flags;
uint8_t reserved1[2];
uint8_t loadparm[8];
uint8_t reserved2[84];
uint16_t reserved3 : 13;
uint8_t ssid : 3;
uint16_t devno;
uint8_t vm_flags;
uint8_t reserved4[3];
uint32_t vm_parm_len;
uint8_t nss_name[8];
uint8_t vm_parm[64];
uint8_t reserved5[8];
} __packed;
/* Structure must not have any padding */
struct ipl_pb0_pv_comp {
uint64_t tweak_pref;
uint64_t addr;
uint64_t len;
};
STATIC_ASSERT(sizeof(struct ipl_pb0_pv_comp) == 3 * 8)
/* IPL Parameter Block 0 for PV */
struct ipl_pb0_pv {
uint32_t len;
uint8_t pbt;
uint8_t reserved1[3];
uint8_t loadparm[8];
uint8_t reserved2[84];
uint8_t reserved3[3];
uint8_t version;
uint8_t reserved4[4];
uint32_t num_comp;
uint64_t pv_hdr_addr;
uint64_t pv_hdr_size;
struct ipl_pb0_pv_comp components[];
} __packed;
struct ipl_parameter_block {
struct ipl_pl_hdr hdr;
union {
struct ipl_pb_hdr pb0_hdr;
struct ipl_pb0_common common;
struct ipl_pb0_fcp fcp;
struct ipl_pb0_ccw ccw;
struct ipl_pb0_pv pv;
char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
};
} __packed __aligned(PAGE_SIZE);
/* IPL Report List header */
struct ipl_rl_hdr {
uint32_t len;
uint8_t flags;
uint8_t reserved1[2];
uint8_t version;
uint8_t reserved2[8];
} __packed;
/* IPL Report Block header */
/* Structure must not have any padding */
struct ipl_rb_hdr {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
};
STATIC_ASSERT(sizeof(struct ipl_rb_hdr) == 4 + 1 + 11)
/* IPL Report Block types */
enum ipl_rbt {
IPL_RBT_CERTIFICATES = 1,
IPL_RBT_COMPONENTS = 2,
};
/* IPL Report Block for the certificate list */
struct ipl_rb_certificate_entry {
uint64_t addr;
uint64_t len;
} __packed;
struct ipl_rb_certificates {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
struct ipl_rb_certificate_entry entries[];
} __packed;
/* IPL Report Block for the component list */
struct ipl_rb_component_entry {
uint64_t addr;
uint64_t len;
uint8_t flags;
uint8_t reserved1[5];
uint16_t certificate_index;
uint8_t reserved2[8];
};
/* Structure must not have any padding */
struct ipl_rb_components {
uint32_t len;
uint8_t rbt;
uint8_t reserved1[11];
struct ipl_rb_component_entry entries[];
};
STATIC_ASSERT(sizeof(struct ipl_rb_components) == 4 + 1 + 11)
#endif /* __ASSEMBLER__ */
#endif /* IPL_H */