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>
This commit is contained in:
Eduard Shishkin
2022-11-22 13:31:40 +01:00
committed by Jan Höppner
parent cf5f373142
commit f7d2339c6a
14 changed files with 1100 additions and 637 deletions

View File

@@ -57,11 +57,41 @@ struct linear_blockptr {
uint8_t reserved[4];
} __packed;
/*
* Format of a boot record on ECKD DASD for List-Directed IPL
*/
struct eckd_boot_record {
uint8_t magic[4];
uint32_t version_id;
uint8_t unused[8];
uint8_t program_table_pointer[16];
uint8_t reserved[478];
uint16_t os_id;
} __packed;
/*
* Layout of block pointer for cylinder/head/sector devices
* e.g. ECKD
*/
struct eckd_blockptr {
enum blkptr_format_id {
/*
* this is the old format which serves only CCW-type IPL,
* and doesn't fit List-Directed IPL. Still supported for
* compatibility reasons.
*/
LEGACY_BLKPTR_FORMAT_ID,
/*
* this is the "new" format which serves only List-Directed IPL,
* but is also suitable for CCW-type IPL.
*/
BLKPTR_FORMAT_ID
};
/*
* Block pointers format identified as LEGACY_BLKPTR_FORMAT_ID.
*/
struct eckd_blockptr_legacy {
uint16_t cyl;
uint16_t head;
uint8_t sec;
@@ -70,6 +100,18 @@ struct eckd_blockptr {
uint8_t reserved[8];
} __packed;
/*
* Block pointers format identified as BLKPTR_FORMAT_ID.
*/
struct eckd_blockptr {
uint32_t cyl;
uint8_t head;
uint8_t sec;
uint8_t reserved1[4];
uint16_t blockct;
uint8_t reserved2[4];
} __packed;
typedef enum {
COMPONENT_TYPE_EXECUTE = 0x01,
COMPONENT_TYPE_LOAD = 0x02,
@@ -153,6 +195,7 @@ struct boot_info_bp_dump {
struct boot_info_bp_ipl {
union {
struct eckd_blockptr_legacy eckd_legacy;
struct eckd_blockptr eckd;
struct linear_blockptr lin;
} bm_ptr;

View File

@@ -97,6 +97,17 @@ typedef struct volume_label
unsigned long long formatted_blocks; /* valid when ldl_version >= f2 */
} __attribute__ ((packed)) volume_label_t;
/**
* This represents a volume label specific for OS/390 compatible disk layout
*/
struct vol_label_cdl {
char volkey[4];
char vollbl[4];
char opaq[70];
cchhb_t br; /* boot record address */
char stdv[1]; /* standard version ID */
} __attribute__ ((packed));
static inline int is_vol1(char *this)
{
char vol1[] = {0xe5, 0xd6, 0xd3, 0xf1, 0x00} /* "VOL1" in EBCDIC */;

View File

@@ -15,14 +15,16 @@
int extract_length(void *data)
{
struct eckd_blockptr *blockptr = (struct eckd_blockptr *)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 *blockptr = (struct eckd_blockptr *)data;
struct eckd_blockptr_legacy *blockptr =
(struct eckd_blockptr_legacy *)data;
return blockptr->cyl || blockptr->head || blockptr->sec;
}
@@ -30,7 +32,7 @@ int is_zero_block(void *data)
void * load_direct(disk_blockptr_t *data, struct subchannel_id subchannel_id,
void *load_addr)
{
struct eckd_blockptr *blockptr = &data->eckd;
struct eckd_blockptr_legacy *blockptr = &data->eckd;
struct ccw1 *ccws;
unsigned long record_size;
struct seek_arg seek_addr;

View File

@@ -27,7 +27,7 @@
#include "error.h"
typedef union {
struct eckd_blockptr eckd;
struct eckd_blockptr_legacy eckd;
struct linear_blockptr linear;
} disk_blockptr_t;

View File

@@ -158,8 +158,8 @@ struct mvdump_parm_table {
void boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type,
void *param);
void boot_get_ipl_info(struct boot_info *boot_info, uint8_t dev_type,
disk_blockptr_t *bm_ptr, struct disk_info *info);
void boot_get_ipl_info_ccw(struct boot_info *boot_info, uint8_t dev_type,
disk_blockptr_t *bm_ptr, struct disk_info *info);
int boot_check_data(void);
int boot_init_fba_stage0(struct boot_fba_stage0* stage0,
@@ -187,6 +187,8 @@ int boot_get_tape_ipl(void** data, size_t* size, address_t parm_addr,
address_t initrd_addr, address_t image_addr);
int boot_get_tape_dump(void** data, size_t* size, uint64_t mem);
int boot_get_eckd_dump_stage2(void** data, size_t* size, uint64_t mem);
int boot_get_eckd_ld_ipl_br(void **br_ptr, size_t *size_ptr,
disk_blockptr_t *table, struct disk_info *info);
int boot_get_eckd_mvdump_stage2(void** data, size_t* size, uint64_t mem,
uint8_t force, struct mvdump_parm_table);
int boot_get_fba_dump_stage2(void** data, size_t* size, uint64_t mem);

View File

@@ -51,11 +51,7 @@ struct file_signature {
int bootmap_header_init(int fd);
int bootmap_header_read(int fd, struct bootmap_header *bh);
int bootmap_header_write(int fd, struct bootmap_header *bh);
int bootmap_create(struct job_data* job, disk_blockptr_t* program_table,
disk_blockptr_t *scsi_dump_sb_blockptr,
disk_blockptr_t** stage2_list, blocknum_t* stage2_count,
char** device, struct disk_info** new_info);
void bootmap_store_blockptr(void* buffer, disk_blockptr_t* ptr,
struct disk_info* info);
void bootmap_store_blockptr(void *buffer, disk_blockptr_t *ptr,
struct disk_info *info, int fid);
#endif /* if not BOOTMAP_H */

View File

@@ -16,6 +16,7 @@
#include <sys/types.h>
#include "zipl.h"
#include "lib/vtoc.h"
/* Type for representing disk block numbers */
@@ -23,7 +24,7 @@ typedef uint64_t blocknum_t;
/* Pointer to block on a disk with cyl/head/sec layout */
struct disk_blockptr_chs {
int cyl;
unsigned int cyl;
int head;
int sec;
int size;
@@ -52,14 +53,6 @@ typedef enum {
disk_type_eckd_cdl,
} disk_type_t;
/* from linux/hdregs.h */
struct hd_geometry {
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
/* Disk information source */
typedef enum {
source_auto,
@@ -108,6 +101,7 @@ int disk_get_info_from_file(const char* filename,
struct disk_info** info);
void disk_free_info(struct disk_info* info);
char* disk_get_type_name(disk_type_t type);
char *disk_get_ipl_type(disk_type_t type);
int disk_is_large_volume(struct disk_info* info);
int disk_cyl_from_blocknum(blocknum_t blocknum, struct disk_info* info);
int disk_head_from_blocknum(blocknum_t blocknum, struct disk_info* info);

View File

@@ -15,12 +15,90 @@
#include "disk.h"
#include "job.h"
#include "zipl.h"
#include "boot/boot_defs.h"
/*
* For compatibility reasons zIPL can build multiple "similar"
* program tables, which differ only in block pointers format
*/
enum program_table_id {
PROGRAM_TABLE_0,
PROGRAM_TABLE_1,
NR_PROGRAM_TABLES
};
int install_bootloader(const char* device, disk_blockptr_t* program_table,
disk_blockptr_t* scsi_dump_sb_blockptr,
disk_blockptr_t* stage2_data, blocknum_t stage2_count,
struct disk_info* info, struct job_data* job);
enum program_component_id {
COMPONENT_ID_HEAP_AREA,
COMPONENT_ID_STACK_AREA,
COMPONENT_ID_LOADER_SIGNATURE,
COMPONENT_ID_LOADER,
COMPONENT_ID_PARAMETERS,
COMPONENT_ID_IMAGE_SIGNATURE,
COMPONENT_ID_KERNEL_IMAGE,
COMPONENT_ID_PARMLINE,
COMPONENT_ID_RAMDISK_SIGNATURE,
COMPONENT_ID_RAMDISK,
COMPONENT_ID_ENVBLK,
COMPONENT_ID_SEGMENT_FILE,
NR_PROGRAM_COMPONENTS
};
struct component_loc {
address_t addr;
size_t size;
};
struct component_footer {
component_type type;
const char *desc;
};
struct program_component {
struct component_loc loc;
disk_blockptr_t *list;
blocknum_t count;
};
struct program_table {
disk_blockptr_t table;
disk_blockptr_t *stage1b_list;
blocknum_t stage1b_count;
};
/* Bootloader Installation Set */
struct install_set {
struct program_table tables[NR_PROGRAM_TABLES];
struct program_component *components[NR_PROGRAM_COMPONENTS];
int nr_tables; /* number of "similar" program tables to be installed */
int nr_menu_entries;
int fd;
char *device;
char *filename;
struct disk_info *info;
disk_blockptr_t scsi_dump_sb_blockptr;
};
extern struct component_footer component_footers[NR_PROGRAM_COMPONENTS];
static inline component_type component_type_by_id(enum program_component_id id)
{
return component_footers[id].type;
}
static inline const char *component_desc_by_id(enum program_component_id id)
{
return component_footers[id].desc;
}
static inline struct program_component *get_component(struct install_set *bis,
int i, int j)
{
return bis->components[i] + j;
}
int prepare_bootloader(struct job_data *job, struct install_set *bis);
int install_bootloader(struct job_data *job, struct install_set *bis);
void free_bootloader(struct install_set *bis);
int install_tapeloader(const char* device, const char* image,
const char* parmline, const char* ramdisk,
address_t image_addr, address_t parm_addr,

View File

@@ -7,7 +7,8 @@ ALL_CPPFLAGS += -I../include -I../boot \
-D_FILE_OFFSET_BITS=64 $(NO_PIE_CFLAGS)
ALL_LDFLAGS += -Wl,-z,noexecstack $(NO_PIE_LDFLAGS)
libs = $(rootdir)/libutil/libutil.a
libs = $(rootdir)/libutil/libutil.a \
$(rootdir)/libvtoc/libvtoc.a \
objects = misc.o error.o scan.o job.o boot.o bootmap.o fs-map.o disk.o \
bootmap_header.o envblk.o install.o zipl.o $(rootdir)/zipl/boot/data.o

View File

@@ -16,6 +16,7 @@
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "lib/util_libc.h"
#include "stage3.h"
@@ -560,9 +561,12 @@ boot_get_dump_info(struct boot_info *boot_info, uint8_t dev_type, void *param)
sizeof(boot_info->bp.dump.param));
}
/*
* Helper function to install a boot record for CCW-type IPL from DASD
*/
void
boot_get_ipl_info(struct boot_info *boot_info, uint8_t dev_type,
disk_blockptr_t *bm_ptr, struct disk_info *info)
boot_get_ipl_info_ccw(struct boot_info *boot_info, uint8_t dev_type,
disk_blockptr_t *bm_ptr, struct disk_info *info)
{
memset(boot_info, 0, sizeof(*boot_info));
memcpy(&boot_info->magic, BOOT_INFO_MAGIC, sizeof(boot_info->magic));
@@ -570,6 +574,30 @@ boot_get_ipl_info(struct boot_info *boot_info, uint8_t dev_type,
boot_info->dev_type = dev_type;
boot_info->bp_type = BOOT_INFO_BP_TYPE_IPL;
boot_info->version = BOOT_INFO_VERSION;
bootmap_store_blockptr(&boot_info->bp, bm_ptr, info);
bootmap_store_blockptr(&boot_info->bp, bm_ptr, info,
LEGACY_BLKPTR_FORMAT_ID);
}
/**
* Allocate and initialize a boot record for List-Directed IPL from DASD
*
* TABLE: address of an actual program table
*/
int boot_get_eckd_ld_ipl_br(void **br_ptr, size_t *size_ptr,
disk_blockptr_t *table, struct disk_info *info)
{
struct eckd_boot_record *br;
br = util_zalloc(info->phy_block_size);
if (!br)
return -1;
memcpy(&br->magic, ZIPL_MAGIC, ZIPL_MAGIC_SIZE);
br->version_id = DISK_LAYOUT_ID;
bootmap_store_blockptr(&br->program_table_pointer, table, info,
BLKPTR_FORMAT_ID);
br->os_id = 0x55aa; /* LINUX */
*br_ptr = br;
*size_ptr = info->phy_block_size;
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -28,6 +28,7 @@
#include "lib/util_proc.h"
#include "lib/util_sys.h"
#include "lib/util_libc.h"
#include "disk.h"
#include "error.h"
#include "install.h"
@@ -755,7 +756,6 @@ disk_write_block_buffer_align(int fd, int fd_is_basedisk, const void *buffer,
size_t bytecount, disk_blockptr_t **blocklist,
struct disk_info *info, int align, off_t *offset)
{
disk_blockptr_t* list;
blocknum_t count;
blocknum_t i;
size_t written;
@@ -764,13 +764,12 @@ disk_write_block_buffer_align(int fd, int fd_is_basedisk, const void *buffer,
int rc;
count = (bytecount + info->phy_block_size - 1) / info->phy_block_size;
list = (disk_blockptr_t *) misc_malloc(sizeof(disk_blockptr_t) *
count);
if (list == NULL) {
*blocklist = (disk_blockptr_t *)util_zalloc(sizeof(disk_blockptr_t) *
count);
if (*blocklist == NULL) {
close(fd);
return 0;
}
memset((void *) list, 0, sizeof(disk_blockptr_t) * count);
/* Build list */
for (i=0, written=0; i < count; i++, written += chunk_size) {
chunk_size = bytecount - written;
@@ -778,17 +777,15 @@ disk_write_block_buffer_align(int fd, int fd_is_basedisk, const void *buffer,
chunk_size = info->phy_block_size;
rc = disk_write_block_aligned_base(fd, fd_is_basedisk,
VOID_ADD(buffer, written),
chunk_size, &list[i], info,
chunk_size, &(*blocklist)[i],
info,
i == 0 ? align : info->phy_block_size,
&pos);
if (rc) {
free(list);
if (rc)
return 0;
}
if (offset != NULL && i == 0)
*offset = pos;
}
*blocklist = list;
return count;
}
@@ -830,6 +827,21 @@ disk_get_type_name(disk_type_t type)
}
}
/* Return IPL types supported for a given disk TYPE */
char *disk_get_ipl_type(disk_type_t type)
{
switch (type) {
case disk_type_scsi:
return "LD-";
case disk_type_fba:
case disk_type_eckd_ldl:
return "CCW-";
case disk_type_eckd_cdl:
return "CCW- and LD-";
default:
return "";
}
}
/* Return non-zero for ECKD large volumes. */
int
@@ -1050,7 +1062,6 @@ disk_get_blocklist_from_file(const char *filename, struct file_range *reg,
disk_blockptr_t **blocklist,
struct disk_info* info)
{
disk_blockptr_t* list;
struct stat stats;
int fd;
off_t off;
@@ -1094,24 +1105,21 @@ disk_get_blocklist_from_file(const char *filename, struct file_range *reg,
blk_count = ((blocknum_t) count +
info->phy_block_size - 1) / info->phy_block_size;
list = (disk_blockptr_t *) misc_malloc(sizeof(disk_blockptr_t) *
blk_count);
if (list == NULL) {
*blocklist = (disk_blockptr_t *)util_zalloc(sizeof(disk_blockptr_t) *
blk_count);
if (*blocklist == NULL) {
close(fd);
return 0;
}
memset((void *) list, 0, sizeof(disk_blockptr_t) * blk_count);
/* Build list */
for (i = 0; i < blk_count; i++) {
if (disk_get_blocknum(fd, 0, blk_off + i, &blocknum, info)) {
free(list);
close(fd);
return 0;
}
disk_blockptr_from_blocknum(&list[i], blocknum, info);
disk_blockptr_from_blocknum(&(*blocklist)[i], blocknum, info);
}
close(fd);
*blocklist = list;
return blk_count;
}

View File

@@ -25,6 +25,7 @@
#include "lib/zt_common.h"
#include "lib/util_sys.h"
#include "lib/vtoc.h"
#include "boot.h"
#include "bootmap.h"
@@ -109,7 +110,8 @@ update_scsi_mbr(void* bootblock, disk_blockptr_t* table,
memset(buffer, 0, sizeof(struct scsi_mbr));
memcpy(&mbr->magic, ZIPL_MAGIC, ZIPL_MAGIC_SIZE);
mbr->version_id = DISK_LAYOUT_ID;
bootmap_store_blockptr(&mbr->program_table_pointer, table, info);
bootmap_store_blockptr(&mbr->program_table_pointer, table, info,
0 /* this argument is ignored for scsi */);
if (scsi_dump_sb_blockptr->linear.block != 0) {
/* Write dump boot_info */
param.block = scsi_dump_sb_blockptr->linear.block *
@@ -168,11 +170,11 @@ install_scsi(int fd, disk_blockptr_t* program_table, struct disk_info* info,
}
/* Install bootloader for initial program load from an FBA type disk. */
/* Install bootloader for CCW-type IPL from a FBA type disk */
static int
install_fba(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info)
install_fba_ccw(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info)
{
struct boot_fba_stage0 stage0;
@@ -180,8 +182,8 @@ install_fba(int fd, disk_blockptr_t *program_table,
if (boot_init_fba_stage0(&stage0, stage1b_list, stage1b_count))
return -1;
boot_get_ipl_info(&stage0.boot_info, BOOT_INFO_DEV_TYPE_FBA,
program_table, info);
boot_get_ipl_info_ccw(&stage0.boot_info, BOOT_INFO_DEV_TYPE_FBA,
program_table, info);
if (DRY_RUN_FUNC(misc_pwrite(fd, &stage0, sizeof(stage0), 0)))
return -1;
@@ -218,12 +220,14 @@ out:
return rc;
}
/* Install bootloader for initial program load from an ECKD type disk with
* Linux Disk Layout. */
/*
* Install bootloader for CCW-type IPL from ECKD type disk with
* Linux Disk Layout
*/
static int
install_eckd_ldl(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info)
install_eckd_ldl_ccw(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info)
{
struct boot_eckd_ldl_stage0 stage0;
struct boot_eckd_stage1 stage1;
@@ -236,8 +240,8 @@ install_eckd_ldl(int fd, disk_blockptr_t *program_table,
if (boot_init_eckd_stage1(&stage1, stage1b_list, stage1b_count))
return -1;
boot_get_ipl_info(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD,
program_table, info);
boot_get_ipl_info_ccw(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD,
program_table, info);
if (DRY_RUN_FUNC(misc_pwrite(fd, &stage1, sizeof(stage1),
sizeof(stage0))))
@@ -246,12 +250,14 @@ install_eckd_ldl(int fd, disk_blockptr_t *program_table,
return 0;
}
/* Install bootloader for initial program load from an ECKD type disk with
* OS/390 compatible disk layout. */
static int
install_eckd_cdl(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info)
/**
* Install bootloader for CCW-type IPL from ECKD type disk with
* OS/390 compatible disk layout
*/
static int install_eckd_cdl_ccw(int fd, disk_blockptr_t *program_table,
disk_blockptr_t *stage1b_list,
blocknum_t stage1b_count,
struct disk_info *info)
{
struct boot_eckd_cdl_stage0 stage0;
struct boot_eckd_stage1 stage1;
@@ -264,8 +270,8 @@ install_eckd_cdl(int fd, disk_blockptr_t *program_table,
if (boot_init_eckd_stage1(&stage1, stage1b_list, stage1b_count))
return -1;
boot_get_ipl_info(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD,
program_table, info);
boot_get_ipl_info_ccw(&stage1.boot_info, BOOT_INFO_DEV_TYPE_ECKD,
program_table, info);
if (DRY_RUN_FUNC(misc_pwrite(fd, &stage1, sizeof(stage1),
4 + info->phy_block_size)))
@@ -273,16 +279,74 @@ install_eckd_cdl(int fd, disk_blockptr_t *program_table,
return 0;
}
int
install_bootloader(const char *device, disk_blockptr_t *program_table,
disk_blockptr_t *scsi_dump_sb_blockptr,
disk_blockptr_t *stage1b_list, blocknum_t stage1b_count,
struct disk_info *info, struct job_data *job)
/**
* Install a program table for List-Directed IPL on a CDL-formatted DASD.
*
* The installation means storing an actual boot record address in the
* volume label.
*
* BR: represents an actual boot record address.
*/
static int install_eckd_cdl_ld(int fd, disk_blockptr_t *br,
struct disk_info *info)
{
struct vol_label_cdl vl;
int rc;
/* Read a volume label from CDL-formatted DASD */
if (misc_seek(fd, 2 * info->phy_block_size))
return -1;
rc = misc_read(fd, &vl, sizeof(vl));
if (rc) {
error_text("Could not read volume label");
return rc;
}
/* Verify that we have a VOL1 label */
if (!is_vol1(vl.vollbl)) {
error_text("Volume label 'vol1' not initialized");
return -1;
}
/* Pack the actual boot record address */
vtoc_set_cchhb(&vl.br, br->chs.cyl, br->chs.head, br->chs.sec);
/* Write out the updated volume label */
if (misc_seek(fd, 2 * info->phy_block_size))
return -1;
rc = DRY_RUN_FUNC(misc_write(fd, &vl, sizeof(vl)));
if (rc)
error_text("Could not update volume lablel 'vol1'");
return 0;
}
/**
* Install a "compatible" boot record referring one, or two "similar"
* program tables.
*
* The picture below shows which program table is used for IPL
* of specified type from disk of specified type.
* 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
*/
int install_bootloader(struct job_data *job, struct install_set *bis)
{
disk_blockptr_t *scsi_dump_sb_blockptr = &bis->scsi_dump_sb_blockptr;
struct program_table *pt0 = &bis->tables[PROGRAM_TABLE_0];
struct program_table *pt1 = &bis->tables[PROGRAM_TABLE_1];
struct disk_info *info = bis->info;
char *device = bis->device;
int fd, rc;
/* Inform user about what we're up to */
printf("Preparing boot device: ");
printf("Preparing boot device for %sIPL: ",
disk_get_ipl_type(info->type));
if (info->name) {
printf("%s", info->name);
if (info->devno >= 0)
@@ -310,27 +374,40 @@ install_bootloader(const char *device, disk_blockptr_t *program_table,
"caches.\n");
}
}
/* Call disk specific install functions */
/*
* Depending on disk type, install one or two program tables
* for CCW-type IPL and (or) for List-Directed IPL (see the
* picture in comments above)
*/
rc = -1;
switch (info->type) {
case disk_type_scsi:
rc = install_scsi(fd, program_table, info,
rc = install_scsi(fd, &pt0->table, info,
scsi_dump_sb_blockptr);
if (rc == 0 && job->id == job_dump_partition &&
!is_ngdump_enabled(device, &job->target))
rc = overwrite_partition_start(fd, info, 0);
break;
case disk_type_fba:
rc = install_fba(fd, program_table, stage1b_list,
stage1b_count, info);
rc = install_fba_ccw(fd,
&pt0->table,
pt0->stage1b_list,
pt0->stage1b_count, info);
break;
case disk_type_eckd_ldl:
rc = install_eckd_ldl(fd, program_table, stage1b_list,
stage1b_count, info);
rc = install_eckd_ldl_ccw(fd,
&pt0->table,
pt0->stage1b_list,
pt0->stage1b_count, info);
break;
case disk_type_eckd_cdl:
rc = install_eckd_cdl(fd, program_table, stage1b_list,
stage1b_count, info);
rc = install_eckd_cdl_ccw(fd,
&pt0->table,
pt0->stage1b_list,
pt0->stage1b_count, info);
if (rc)
break;
rc = install_eckd_cdl_ld(fd, pt1->stage1b_list, info);
break;
case disk_type_diag:
/* Should not happen */

View File

@@ -126,11 +126,8 @@ check_for_root(void)
int
main(int argc, char* argv[])
{
struct disk_info* info;
disk_blockptr_t program_table, scsi_dump_sb_blockptr, *stage1b_list;
blocknum_t stage1b_count;
struct install_set bis;
struct job_data* job;
char* device;
int rc;
/* Check internals */
@@ -197,21 +194,11 @@ main(int argc, char* argv[])
case job_ipl:
case job_segment:
case job_menu:
/* Create bootmap */
stage1b_list = NULL;
rc = bootmap_create(job, &program_table, &scsi_dump_sb_blockptr,
&stage1b_list, &stage1b_count, &device,
&info);
rc = prepare_bootloader(job, &bis);
if (rc)
break;
/* Install boot loader */
rc = install_bootloader(device, &program_table,
&scsi_dump_sb_blockptr, stage1b_list,
stage1b_count, info, job);
if (stage1b_list != NULL)
free(stage1b_list);
misc_free_temp_dev(device);
disk_free_info(info);
rc = install_bootloader(job, &bis);
free_bootloader(&bis);
break;
case job_ipl_tape:
rc = install_tapeloader(job->data.ipl_tape.device,
@@ -251,3 +238,57 @@ main(int argc, char* argv[])
job_free(job);
return abs(rc);
}
/**
* Program Component Footers
*/
struct component_footer component_footers[NR_PROGRAM_COMPONENTS] = {
[COMPONENT_ID_HEAP_AREA] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "heap area"
},
[COMPONENT_ID_STACK_AREA] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "stack area"
},
[COMPONENT_ID_LOADER_SIGNATURE] = {
.type = COMPONENT_TYPE_SIGNATURE,
.desc = "loader signature"
},
[COMPONENT_ID_LOADER] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "internal loader"
},
[COMPONENT_ID_PARAMETERS] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "parameters"
},
[COMPONENT_ID_IMAGE_SIGNATURE] = {
.type = COMPONENT_TYPE_SIGNATURE,
.desc = "image signature"
},
[COMPONENT_ID_KERNEL_IMAGE] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "kernel image"
},
[COMPONENT_ID_PARMLINE] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "parmline"
},
[COMPONENT_ID_RAMDISK_SIGNATURE] = {
.type = COMPONENT_TYPE_SIGNATURE,
.desc = "ramdisk signature"
},
[COMPONENT_ID_RAMDISK] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "initial ramdisk"
},
[COMPONENT_ID_ENVBLK] = {
.type = COMPONENT_TYPE_LOAD,
.desc = "environment blk"
},
[COMPONENT_ID_SEGMENT_FILE] = {
.type = COMPONENT_TYPE_EXECUTE,
.desc = "segment file"
}
};