Files
s390-tools/zipl/boot/eckd2.c
Eduard Shishkin f7d2339c6a zipl: List-Directed IPL from ECKD DASD
Make zipl tool prepare ECKD DASD for booting by different IPL
programs (with the same boot record installed).

Besides standard CCW-type IPL, user gets an ability to trigger
(with the same boot record installed!) List-Directed IPL. This
allows to use the feature of secure boot from ECKD DASD (which
is not available for CCW-type IPL).

When using the old boot interfaces, the usual CCW-type IPL is
triggered for DASD. Also for compatibility reasons zipl(8) tool
is modified to create and install one, or two "similar" program
tables per boot partition, depending on job and disk type. The
"similar" program tables differ only in block pointers format.
The old IPL programs (CCW-type IPL) use program table based on the
old format.

All program tables are packed to the same bootmap file. Their
order and logical offsets in the file are not significant (not
used by anyone).

The picture below shows which program table is used for IPL of
specified type from disk of specified type. Here "0" and "1" are
identifiers of program tables based on the old and new block
pointers format respectively. E.g. program table "0" is used for
CCW-type IPL from ECKD DASD. LD-IPL from DASD FBA is unsupported
(respectively, only one program table "0" is used), etc.

                            CCW-IPL   LD-IPL

 SCSI                          X        0
 DASD FBA                      0        X
 ECKD DASD LDL                 0        X
 ECKD DASD CDL                 0        1

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00

102 lines
2.4 KiB
C

/*
* zipl - zSeries Initial Program Loader tool
*
* Subroutines for ECKD disks
*
* Copyright IBM Corp. 2013, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "eckd.h"
#include "boot/s390.h"
#include "stage2.h"
int extract_length(void *data)
{
struct eckd_blockptr_legacy *blockptr =
(struct eckd_blockptr_legacy *)data;
return blockptr->size * (blockptr->blockct + 1);
}
int is_zero_block(void *data)
{
struct eckd_blockptr_legacy *blockptr =
(struct eckd_blockptr_legacy *)data;
return blockptr->cyl || blockptr->head || blockptr->sec;
}
void * load_direct(disk_blockptr_t *data, struct subchannel_id subchannel_id,
void *load_addr)
{
struct eckd_blockptr_legacy *blockptr = &data->eckd;
struct ccw1 *ccws;
unsigned long record_size;
struct seek_arg seek_addr;
struct chr_t search_arg;
int record_number;
struct irb *irb;
struct orb orb;
int i = 3;
irb = (struct irb *)&S390_lowcore.irb;
memset(irb, 0, sizeof(struct irb));
memset(&orb, 0, sizeof(struct orb));
memset(&seek_addr, 0, sizeof(struct ch_t));
memset(&search_arg, 0, sizeof(struct chr_t));
ccws = (struct ccw1 *)get_zeroed_page();
/* initialise SEEK, SEARCH and TIC CCW*/
ccws[0].cmd_code = DASD_ECKD_CCW_SEEK;
ccws[0].flags = CCW_FLAG_CC | CCW_FLAG_SLI;
ccws[0].count = 6;
seek_addr.ch.cyl = blockptr->cyl;
seek_addr.ch.head = blockptr->head;
ccws[0].cda = (uint32_t) (unsigned long) &seek_addr;
record_number = blockptr->blockct;
record_size = blockptr->size;
ccws[1].cmd_code = DASD_ECKD_CCW_SEARCH;
ccws[1].flags = CCW_FLAG_CC | CCW_FLAG_SLI;
ccws[1].count = 5;
search_arg.cyl = blockptr->cyl;
search_arg.head = blockptr->head;
search_arg.record = blockptr->sec;
ccws[1].cda = (uint32_t) (unsigned long) &search_arg;
ccws[2].cmd_code = DASD_ECKD_CCW_TIC;
ccws[2].flags = 0;
ccws[2].count = 0;
ccws[2].cda = (uint32_t) (unsigned long) &ccws[1];
/* initialise READ CCWs */
while (1) {
ccws[i].cmd_code = DASD_ECKD_CCW_READ_MT;
ccws[i].flags = CCW_FLAG_SLI;
ccws[i].count = record_size;
ccws[i].cda = (uint32_t) (unsigned long) load_addr;
record_number--;
load_addr += record_size;
i++;
if (record_number >= 0)
ccws[i-1].flags |= CCW_FLAG_CC;
else
break;
}
orb.fmt = 1;
orb.cpa = (uint32_t) (unsigned long) ccws;
start_io(subchannel_id, irb, &orb, 1);
free_page((unsigned long)ccws);
return load_addr;
}