zipl: Do not strip kernel image IPL header

The binary Linux kernel image is built to be loaded to memory address
0x0 but the first 64 kbyte contain an IPL header that is not used for
disk IPL. zIPL strips away this IPL header when writing IPL records to
disk, loads the remaining data to memory address 0x10000 and uses the
memory area below that for its own boot loader code.

The Secure Boot firmware feature checks the integrity of an installed
image during IPL using a checksum that was generated for the full image.
Since the checksum becomes invalid if the IPL header is removed, zIPL
must be changed to write the full image to disk.

This patch modifies the zIPL logic to no longer strip away the IPL
header. Instead the full image is loaded to a higher memory address and
relocated by the stage 3 boot loader code to its final location.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Stefan Haberland
2019-04-15 18:08:43 +02:00
committed by Jan Höppner
parent 63089835b0
commit e764f460c4
10 changed files with 70 additions and 9 deletions
+4 -1
View File
@@ -81,7 +81,7 @@ get_stage3_size()
int
boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
address_t initrd_addr, size_t initrd_len, address_t image_addr,
int extra_parm, uint16_t flags)
int extra_parm, uint16_t flags, size_t image_len)
{
struct boot_stage3_params params;
void* data;
@@ -95,6 +95,7 @@ boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
data = misc_malloc(DATA_SIZE(stage3));
if (data == NULL)
return -1;
memset(data, 0, DATA_SIZE(stage3));
/* Prepare params section */
params.parm_addr = (uint64_t) parm_addr;
params.initrd_addr = (uint64_t) initrd_addr;
@@ -102,6 +103,8 @@ boot_get_stage3(void** buffer, size_t* bytecount, address_t parm_addr,
params.load_psw = (uint64_t)(image_addr | PSW_LOAD);
params.extra_parm = (uint64_t) extra_parm;
params.flags = flags;
params.image_len = (uint64_t) image_len;
params.image_addr = (uint64_t) image_addr;
/* Initialize buffer */
memcpy(data, DATA_ADDR(stage3), DATA_SIZE(stage3));
memcpy(data, &params, sizeof(struct boot_stage3_params));