mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
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:
committed by
Jan Höppner
parent
63089835b0
commit
e764f460c4
+4
-1
@@ -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, ¶ms, sizeof(struct boot_stage3_params));
|
||||
|
||||
+15
-4
@@ -409,7 +409,6 @@ print_components(const char *name[], struct component_loc *loc, int num)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
int verbose, int add_files, component_header_type type,
|
||||
@@ -424,6 +423,7 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
struct component_loc comp_loc[4];
|
||||
int rc;
|
||||
int offset, flags = 0;
|
||||
size_t ramdisk_size, image_size;
|
||||
|
||||
memset(comp_loc, 0, sizeof(comp_loc));
|
||||
table = misc_malloc(info->phy_block_size);
|
||||
@@ -456,18 +456,29 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ramdisk_size = stats.st_size;
|
||||
if (info->type == disk_type_scsi)
|
||||
flags |= STAGE3_FLAG_SCSI;
|
||||
if (ipl->is_kdump)
|
||||
flags |= STAGE3_FLAG_KDUMP;
|
||||
|
||||
/* Get kernel file size */
|
||||
if (stat(ipl->image, &stats)) {
|
||||
error_reason(strerror(errno));
|
||||
error_text("Could not get information for file '%s'",
|
||||
ipl->image);
|
||||
free(table);
|
||||
return -1;
|
||||
}
|
||||
image_size = stats.st_size;
|
||||
|
||||
/* Add stage 3 loader to bootmap */
|
||||
rc = boot_get_stage3(&stage3, &stage3_size, ipl->parm_addr,
|
||||
ipl->ramdisk_addr, (size_t) stats.st_size,
|
||||
ipl->ramdisk_addr, ramdisk_size,
|
||||
ipl->is_kdump ? ipl->image_addr + 0x10 :
|
||||
ipl->image_addr,
|
||||
(info->type == disk_type_scsi) ? 0 : 1,
|
||||
flags);
|
||||
flags, image_size);
|
||||
if (rc) {
|
||||
free(table);
|
||||
return rc;
|
||||
@@ -487,7 +498,7 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
||||
printf(" kernel image......: %s\n", ipl->image);
|
||||
}
|
||||
rc = add_component_file(fd, ipl->image, ipl->image_addr,
|
||||
KERNEL_HEADER_SIZE, VOID_ADD(table, offset),
|
||||
0, VOID_ADD(table, offset),
|
||||
add_files, info, target, &comp_loc[0]);
|
||||
if (rc) {
|
||||
error_text("Could not add image file '%s'", ipl->image);
|
||||
|
||||
+1
-1
@@ -511,7 +511,7 @@ get_ipl_components(struct job_ipl_data *ipl, struct component_loc **clp,
|
||||
/* Fill in component data */
|
||||
num = 0;
|
||||
rc = set_cl_element(&cl[num++], "kernel image", ipl->image,
|
||||
&ipl->image_addr, 0, 0x10000,
|
||||
&ipl->image_addr, 0, 0,
|
||||
MAXIMUM_PHYSICAL_BLOCKSIZE);
|
||||
if (rc)
|
||||
goto error;
|
||||
|
||||
Reference in New Issue
Block a user