126f2bbd6SEugene (jno) Dvurechenski /*
226f2bbd6SEugene (jno) Dvurechenski * QEMU S390 bootmap interpreter -- declarations
326f2bbd6SEugene (jno) Dvurechenski *
426f2bbd6SEugene (jno) Dvurechenski * Copyright 2014 IBM Corp.
526f2bbd6SEugene (jno) Dvurechenski * Author(s): Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com>
626f2bbd6SEugene (jno) Dvurechenski *
726f2bbd6SEugene (jno) Dvurechenski * This work is licensed under the terms of the GNU GPL, version 2 or (at
826f2bbd6SEugene (jno) Dvurechenski * your option) any later version. See the COPYING file in the top-level
926f2bbd6SEugene (jno) Dvurechenski * directory.
1026f2bbd6SEugene (jno) Dvurechenski */
1126f2bbd6SEugene (jno) Dvurechenski #ifndef _PC_BIOS_S390_CCW_BOOTMAP_H
1226f2bbd6SEugene (jno) Dvurechenski #define _PC_BIOS_S390_CCW_BOOTMAP_H
1326f2bbd6SEugene (jno) Dvurechenski
1426f2bbd6SEugene (jno) Dvurechenski #include "s390-ccw.h"
15a94b485eSEugene (jno) Dvurechenski #include "virtio.h"
16a94b485eSEugene (jno) Dvurechenski
17a94b485eSEugene (jno) Dvurechenski typedef uint64_t block_number_t;
18f17a8430SChristian Borntraeger #define NULL_BLOCK_NR 0xffffffffffffffffULL
19*80631527SJared Rossi #define ERROR_BLOCK_NR 0xfffffffffffffffeULL
2026f2bbd6SEugene (jno) Dvurechenski
2126f2bbd6SEugene (jno) Dvurechenski #define FREE_SPACE_FILLER '\xAA'
2226f2bbd6SEugene (jno) Dvurechenski
2326f2bbd6SEugene (jno) Dvurechenski typedef struct ScsiBlockPtr {
2426f2bbd6SEugene (jno) Dvurechenski uint64_t blockno;
2526f2bbd6SEugene (jno) Dvurechenski uint16_t size;
2626f2bbd6SEugene (jno) Dvurechenski uint16_t blockct;
2726f2bbd6SEugene (jno) Dvurechenski uint8_t reserved[4];
2826f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) ScsiBlockPtr;
2926f2bbd6SEugene (jno) Dvurechenski
3026f2bbd6SEugene (jno) Dvurechenski typedef struct FbaBlockPtr {
3126f2bbd6SEugene (jno) Dvurechenski uint32_t blockno;
3226f2bbd6SEugene (jno) Dvurechenski uint16_t size;
3326f2bbd6SEugene (jno) Dvurechenski uint16_t blockct;
3426f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) FbaBlockPtr;
3526f2bbd6SEugene (jno) Dvurechenski
3680beedccSCollin L. Walling typedef struct EckdCHS {
3780beedccSCollin L. Walling uint16_t cylinder;
3826f2bbd6SEugene (jno) Dvurechenski uint16_t head;
3926f2bbd6SEugene (jno) Dvurechenski uint8_t sector;
4080beedccSCollin L. Walling } __attribute__ ((packed)) EckdCHS;
4180beedccSCollin L. Walling
4280beedccSCollin L. Walling typedef struct EckdBlockPtr {
4380beedccSCollin L. Walling EckdCHS chs; /* cylinder/head/sector is an address of the block */
4426f2bbd6SEugene (jno) Dvurechenski uint16_t size;
4526f2bbd6SEugene (jno) Dvurechenski uint8_t count; /* (size_in_blocks-1);
4626f2bbd6SEugene (jno) Dvurechenski * it's 0 for TablePtr, ScriptPtr, and SectionPtr */
4726f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) EckdBlockPtr;
4826f2bbd6SEugene (jno) Dvurechenski
498af5d141SJared Rossi typedef struct LdEckdCHS {
508af5d141SJared Rossi uint32_t cylinder;
518af5d141SJared Rossi uint8_t head;
528af5d141SJared Rossi uint8_t sector;
538af5d141SJared Rossi } __attribute__ ((packed)) LdEckdCHS;
548af5d141SJared Rossi
558af5d141SJared Rossi typedef struct LdEckdBlockPtr {
568af5d141SJared Rossi LdEckdCHS chs; /* cylinder/head/sector is an address of the block */
578af5d141SJared Rossi uint8_t reserved[4];
588af5d141SJared Rossi uint16_t count;
598af5d141SJared Rossi uint32_t pad;
608af5d141SJared Rossi } __attribute__ ((packed)) LdEckdBlockPtr;
618af5d141SJared Rossi
628af5d141SJared Rossi /* bptr is used for CCW type IPL, while ldptr is for list-directed IPL */
638af5d141SJared Rossi typedef union ExtEckdBlockPtr {
6426f2bbd6SEugene (jno) Dvurechenski EckdBlockPtr bptr;
658af5d141SJared Rossi LdEckdBlockPtr ldptr;
6626f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) ExtEckdBlockPtr;
6726f2bbd6SEugene (jno) Dvurechenski
6826f2bbd6SEugene (jno) Dvurechenski typedef union BootMapPointer {
6926f2bbd6SEugene (jno) Dvurechenski ScsiBlockPtr scsi;
7026f2bbd6SEugene (jno) Dvurechenski FbaBlockPtr fba;
7126f2bbd6SEugene (jno) Dvurechenski EckdBlockPtr eckd;
7226f2bbd6SEugene (jno) Dvurechenski ExtEckdBlockPtr xeckd;
7326f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) BootMapPointer;
7426f2bbd6SEugene (jno) Dvurechenski
758af5d141SJared Rossi typedef struct BootRecord {
768af5d141SJared Rossi uint8_t magic[4];
778af5d141SJared Rossi uint32_t version;
788af5d141SJared Rossi uint64_t res1;
798af5d141SJared Rossi BootMapPointer pgt;
808af5d141SJared Rossi uint8_t reserved[510 - 32];
818af5d141SJared Rossi uint16_t os_id;
828af5d141SJared Rossi } __attribute__ ((packed)) BootRecord;
838af5d141SJared Rossi
845340eb07SCollin L. Walling /* aka Program Table */
855340eb07SCollin L. Walling typedef struct BootMapTable {
865340eb07SCollin L. Walling uint8_t magic[4];
875340eb07SCollin L. Walling uint8_t reserved[12];
885340eb07SCollin L. Walling BootMapPointer entry[];
895340eb07SCollin L. Walling } __attribute__ ((packed)) BootMapTable;
905340eb07SCollin L. Walling
914906a4e4SJanosch Frank typedef union ComponentEntryData {
924906a4e4SJanosch Frank uint64_t load_psw;
934906a4e4SJanosch Frank uint64_t load_addr;
944906a4e4SJanosch Frank } ComponentEntryData;
954906a4e4SJanosch Frank
9626f2bbd6SEugene (jno) Dvurechenski typedef struct ComponentEntry {
9726f2bbd6SEugene (jno) Dvurechenski ScsiBlockPtr data;
9826f2bbd6SEugene (jno) Dvurechenski uint8_t pad[7];
9926f2bbd6SEugene (jno) Dvurechenski uint8_t component_type;
1004906a4e4SJanosch Frank ComponentEntryData compdat;
10126f2bbd6SEugene (jno) Dvurechenski } __attribute((packed)) ComponentEntry;
10226f2bbd6SEugene (jno) Dvurechenski
10326f2bbd6SEugene (jno) Dvurechenski typedef struct ComponentHeader {
10426f2bbd6SEugene (jno) Dvurechenski uint8_t magic[4]; /* == "zIPL" */
10526f2bbd6SEugene (jno) Dvurechenski uint8_t type; /* == ZIPL_COMP_HEADER_* */
10626f2bbd6SEugene (jno) Dvurechenski uint8_t reserved[27];
10726f2bbd6SEugene (jno) Dvurechenski } __attribute((packed)) ComponentHeader;
10826f2bbd6SEugene (jno) Dvurechenski
10926f2bbd6SEugene (jno) Dvurechenski typedef struct ScsiMbr {
11026f2bbd6SEugene (jno) Dvurechenski uint8_t magic[4];
11126f2bbd6SEugene (jno) Dvurechenski uint32_t version_id;
11226f2bbd6SEugene (jno) Dvurechenski uint8_t reserved[8];
1135340eb07SCollin L. Walling ScsiBlockPtr pt; /* block pointer to program table */
11426f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) ScsiMbr;
11526f2bbd6SEugene (jno) Dvurechenski
11626f2bbd6SEugene (jno) Dvurechenski #define ZIPL_MAGIC "zIPL"
117ba831b25SCollin L. Walling #define ZIPL_MAGIC_EBCDIC "\xa9\xc9\xd7\xd3"
11826f2bbd6SEugene (jno) Dvurechenski #define IPL1_MAGIC "\xc9\xd7\xd3\xf1" /* == "IPL1" in EBCDIC */
11926f2bbd6SEugene (jno) Dvurechenski #define IPL2_MAGIC "\xc9\xd7\xd3\xf2" /* == "IPL2" in EBCDIC */
12026f2bbd6SEugene (jno) Dvurechenski #define VOL1_MAGIC "\xe5\xd6\xd3\xf1" /* == "VOL1" in EBCDIC */
12126f2bbd6SEugene (jno) Dvurechenski #define LNX1_MAGIC "\xd3\xd5\xe7\xf1" /* == "LNX1" in EBCDIC */
12226f2bbd6SEugene (jno) Dvurechenski #define CMS1_MAGIC "\xc3\xd4\xe2\xf1" /* == "CMS1" in EBCDIC */
12326f2bbd6SEugene (jno) Dvurechenski
12426f2bbd6SEugene (jno) Dvurechenski #define LDL1_VERSION '\x40' /* == ' ' in EBCDIC */
12526f2bbd6SEugene (jno) Dvurechenski #define LDL2_VERSION '\xf2' /* == '2' in EBCDIC */
12626f2bbd6SEugene (jno) Dvurechenski
12726f2bbd6SEugene (jno) Dvurechenski #define ZIPL_COMP_HEADER_IPL 0x00
12826f2bbd6SEugene (jno) Dvurechenski #define ZIPL_COMP_HEADER_DUMP 0x01
12926f2bbd6SEugene (jno) Dvurechenski
13026f2bbd6SEugene (jno) Dvurechenski #define ZIPL_COMP_ENTRY_EXEC 0x01
1312497b4a3SJason J. Herne #define ZIPL_COMP_ENTRY_LOAD 0x02
1322497b4a3SJason J. Herne #define ZIPL_COMP_ENTRY_SIGNATURE 0x03
13326f2bbd6SEugene (jno) Dvurechenski
13426f2bbd6SEugene (jno) Dvurechenski typedef struct XEckdMbr {
13526f2bbd6SEugene (jno) Dvurechenski uint8_t magic[4]; /* == "xIPL" */
13626f2bbd6SEugene (jno) Dvurechenski uint8_t version;
13726f2bbd6SEugene (jno) Dvurechenski uint8_t bp_type;
13826f2bbd6SEugene (jno) Dvurechenski uint8_t dev_type; /* == DEV_TYPE_* */
13926f2bbd6SEugene (jno) Dvurechenski #define DEV_TYPE_ECKD 0x00
14026f2bbd6SEugene (jno) Dvurechenski #define DEV_TYPE_FBA 0x01
14126f2bbd6SEugene (jno) Dvurechenski uint8_t flags;
14226f2bbd6SEugene (jno) Dvurechenski BootMapPointer blockptr;
14326f2bbd6SEugene (jno) Dvurechenski uint8_t reserved[8];
14426f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) XEckdMbr; /* see also BootInfo */
14526f2bbd6SEugene (jno) Dvurechenski
14626f2bbd6SEugene (jno) Dvurechenski typedef struct BootMapScriptEntry {
14726f2bbd6SEugene (jno) Dvurechenski BootMapPointer blkptr;
14826f2bbd6SEugene (jno) Dvurechenski uint8_t pad[7];
14926f2bbd6SEugene (jno) Dvurechenski uint8_t type; /* == BOOT_SCRIPT_* */
15026f2bbd6SEugene (jno) Dvurechenski #define BOOT_SCRIPT_EXEC 0x01
15126f2bbd6SEugene (jno) Dvurechenski #define BOOT_SCRIPT_LOAD 0x02
1522497b4a3SJason J. Herne #define BOOT_SCRIPT_SIGNATURE 0x03
15326f2bbd6SEugene (jno) Dvurechenski union {
15426f2bbd6SEugene (jno) Dvurechenski uint64_t load_address;
15526f2bbd6SEugene (jno) Dvurechenski uint64_t load_psw;
15626f2bbd6SEugene (jno) Dvurechenski } address;
15726f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) BootMapScriptEntry;
15826f2bbd6SEugene (jno) Dvurechenski
15926f2bbd6SEugene (jno) Dvurechenski typedef struct BootMapScriptHeader {
16026f2bbd6SEugene (jno) Dvurechenski uint32_t magic;
16126f2bbd6SEugene (jno) Dvurechenski uint8_t type;
16226f2bbd6SEugene (jno) Dvurechenski #define BOOT_SCRIPT_HDR_IPL 0x00
16326f2bbd6SEugene (jno) Dvurechenski uint8_t reserved[27];
16426f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) BootMapScriptHeader;
16526f2bbd6SEugene (jno) Dvurechenski
16626f2bbd6SEugene (jno) Dvurechenski typedef struct BootMapScript {
16726f2bbd6SEugene (jno) Dvurechenski BootMapScriptHeader header;
168f7795e40SPhilippe Mathieu-Daudé BootMapScriptEntry entry[];
16926f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) BootMapScript;
17026f2bbd6SEugene (jno) Dvurechenski
17126f2bbd6SEugene (jno) Dvurechenski /*
17226f2bbd6SEugene (jno) Dvurechenski * These aren't real VTOCs, but referred to this way in some docs.
17326f2bbd6SEugene (jno) Dvurechenski * They are "volume labels" actually.
17426f2bbd6SEugene (jno) Dvurechenski *
17526f2bbd6SEugene (jno) Dvurechenski * Some structures looks similar to described above, but left
17626f2bbd6SEugene (jno) Dvurechenski * separate as there is no indication that they are the same.
17726f2bbd6SEugene (jno) Dvurechenski * So, the value definitions are left separate too.
17826f2bbd6SEugene (jno) Dvurechenski */
17926f2bbd6SEugene (jno) Dvurechenski typedef struct LDL_VTOC { /* @ rec.3 cyl.0 trk.0 for ECKD */
18026f2bbd6SEugene (jno) Dvurechenski char magic[4]; /* "LNX1", EBCDIC */
18126f2bbd6SEugene (jno) Dvurechenski char volser[6]; /* volser, EBCDIC */
18226f2bbd6SEugene (jno) Dvurechenski uint8_t reserved[69]; /* reserved, 0x40 */
18326f2bbd6SEugene (jno) Dvurechenski uint8_t LDL_version; /* 0x40 or 0xF2 */
18426f2bbd6SEugene (jno) Dvurechenski uint64_t formatted_blocks; /* if LDL_version >= 0xF2 */
18526f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) LDL_VTOC;
18626f2bbd6SEugene (jno) Dvurechenski
18726f2bbd6SEugene (jno) Dvurechenski typedef struct format_date {
18826f2bbd6SEugene (jno) Dvurechenski uint8_t YY;
18926f2bbd6SEugene (jno) Dvurechenski uint8_t MM;
19026f2bbd6SEugene (jno) Dvurechenski uint8_t DD;
19126f2bbd6SEugene (jno) Dvurechenski uint8_t hh;
19226f2bbd6SEugene (jno) Dvurechenski uint8_t mm;
19326f2bbd6SEugene (jno) Dvurechenski uint8_t ss;
19426f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) format_date_t;
19526f2bbd6SEugene (jno) Dvurechenski
19626f2bbd6SEugene (jno) Dvurechenski typedef struct CMS_VTOC { /* @ rec.3 cyl.0 trk.0 for ECKD */
19726f2bbd6SEugene (jno) Dvurechenski /* @ blk.1 (zero based) for FBA */
19826f2bbd6SEugene (jno) Dvurechenski char magic[4]; /* 'CMS1', EBCDIC */
19926f2bbd6SEugene (jno) Dvurechenski char volser[6]; /* volser, EBCDIC */
20026f2bbd6SEugene (jno) Dvurechenski uint16_t version; /* = 0 */
20126f2bbd6SEugene (jno) Dvurechenski uint32_t block_size; /* = 512, 1024, 2048, or 4096 */
20226f2bbd6SEugene (jno) Dvurechenski uint32_t disk_origin; /* = 4 or 5 */
20326f2bbd6SEugene (jno) Dvurechenski uint32_t blocks; /* Number of usable cyls/blocks */
20426f2bbd6SEugene (jno) Dvurechenski uint32_t formatted; /* Max number of fmtd cyls/blks */
20526f2bbd6SEugene (jno) Dvurechenski uint32_t CMS_blocks; /* disk size in CMS blocks */
20626f2bbd6SEugene (jno) Dvurechenski uint32_t CMS_used; /* Number of CMS blocks in use */
20726f2bbd6SEugene (jno) Dvurechenski uint32_t FST_size; /* = 64, bytes */
20826f2bbd6SEugene (jno) Dvurechenski uint32_t FST_per_CMS_blk; /* */
20926f2bbd6SEugene (jno) Dvurechenski format_date_t format_date; /* YYMMDDhhmmss as 6 bytes */
21026f2bbd6SEugene (jno) Dvurechenski uint8_t reserved1[2]; /* = 0 */
21126f2bbd6SEugene (jno) Dvurechenski uint32_t offset; /* disk offset when reserved */
21226f2bbd6SEugene (jno) Dvurechenski uint32_t next_hole; /* block nr */
21326f2bbd6SEugene (jno) Dvurechenski uint32_t HBLK_hole_offset; /* >> HBLK data of next hole */
21426f2bbd6SEugene (jno) Dvurechenski uint32_t alloc_map_usr_off; /* >> user part of Alloc map */
21526f2bbd6SEugene (jno) Dvurechenski uint8_t reserved2[4]; /* = 0 */
21626f2bbd6SEugene (jno) Dvurechenski char shared_seg_name[8]; /* */
21726f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) CMS_VTOC;
21826f2bbd6SEugene (jno) Dvurechenski
21926f2bbd6SEugene (jno) Dvurechenski /* from zipl/include/boot.h */
22026f2bbd6SEugene (jno) Dvurechenski typedef struct BootInfoBpIpl {
22126f2bbd6SEugene (jno) Dvurechenski union {
22226f2bbd6SEugene (jno) Dvurechenski ExtEckdBlockPtr eckd;
22326f2bbd6SEugene (jno) Dvurechenski ScsiBlockPtr linr;
22426f2bbd6SEugene (jno) Dvurechenski } bm_ptr;
22526f2bbd6SEugene (jno) Dvurechenski uint8_t unused[16];
22626f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) BootInfoBpIpl;
22726f2bbd6SEugene (jno) Dvurechenski
22826f2bbd6SEugene (jno) Dvurechenski typedef struct EckdDumpParam {
22926f2bbd6SEugene (jno) Dvurechenski uint32_t start_blk;
23026f2bbd6SEugene (jno) Dvurechenski uint32_t end_blk;
23126f2bbd6SEugene (jno) Dvurechenski uint16_t blocksize;
23226f2bbd6SEugene (jno) Dvurechenski uint8_t num_heads;
23326f2bbd6SEugene (jno) Dvurechenski uint8_t bpt;
23426f2bbd6SEugene (jno) Dvurechenski char reserved[4];
23526f2bbd6SEugene (jno) Dvurechenski } __attribute((packed, may_alias)) EckdDumpParam;
23626f2bbd6SEugene (jno) Dvurechenski
23726f2bbd6SEugene (jno) Dvurechenski typedef struct FbaDumpParam {
23826f2bbd6SEugene (jno) Dvurechenski uint64_t start_blk;
23926f2bbd6SEugene (jno) Dvurechenski uint64_t blockct;
24026f2bbd6SEugene (jno) Dvurechenski } __attribute((packed)) FbaDumpParam;
24126f2bbd6SEugene (jno) Dvurechenski
24226f2bbd6SEugene (jno) Dvurechenski typedef struct BootInfoBpDump {
24326f2bbd6SEugene (jno) Dvurechenski union {
24426f2bbd6SEugene (jno) Dvurechenski EckdDumpParam eckd;
24526f2bbd6SEugene (jno) Dvurechenski FbaDumpParam fba;
24626f2bbd6SEugene (jno) Dvurechenski } param;
24726f2bbd6SEugene (jno) Dvurechenski uint8_t unused[16];
24826f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) BootInfoBpDump;
24926f2bbd6SEugene (jno) Dvurechenski
25026f2bbd6SEugene (jno) Dvurechenski typedef struct BootInfo { /* @ 0x70, record #0 */
25126f2bbd6SEugene (jno) Dvurechenski unsigned char magic[4]; /* = 'zIPL', ASCII */
25226f2bbd6SEugene (jno) Dvurechenski uint8_t version; /* = 1 */
25326f2bbd6SEugene (jno) Dvurechenski #define BOOT_INFO_VERSION 1
25426f2bbd6SEugene (jno) Dvurechenski uint8_t bp_type; /* = 0 */
25526f2bbd6SEugene (jno) Dvurechenski #define BOOT_INFO_BP_TYPE_IPL 0x00
25626f2bbd6SEugene (jno) Dvurechenski #define BOOT_INFO_BP_TYPE_DUMP 0x01
25726f2bbd6SEugene (jno) Dvurechenski uint8_t dev_type; /* = 0 */
25826f2bbd6SEugene (jno) Dvurechenski #define BOOT_INFO_DEV_TYPE_ECKD 0x00
25926f2bbd6SEugene (jno) Dvurechenski #define BOOT_INFO_DEV_TYPE_FBA 0x01
26026f2bbd6SEugene (jno) Dvurechenski uint8_t flags; /* = 1 */
26126f2bbd6SEugene (jno) Dvurechenski #ifdef __s390x__
26226f2bbd6SEugene (jno) Dvurechenski #define BOOT_INFO_FLAGS_ARCH 0x01
26326f2bbd6SEugene (jno) Dvurechenski #else
26426f2bbd6SEugene (jno) Dvurechenski #define BOOT_INFO_FLAGS_ARCH 0x00
26526f2bbd6SEugene (jno) Dvurechenski #endif
26626f2bbd6SEugene (jno) Dvurechenski union {
26726f2bbd6SEugene (jno) Dvurechenski BootInfoBpDump dump;
26826f2bbd6SEugene (jno) Dvurechenski BootInfoBpIpl ipl;
26926f2bbd6SEugene (jno) Dvurechenski } bp;
27026f2bbd6SEugene (jno) Dvurechenski } __attribute__ ((packed)) BootInfo; /* see also XEckdMbr */
27126f2bbd6SEugene (jno) Dvurechenski
272ac4c5958SCollin L. Walling /*
273ac4c5958SCollin L. Walling * Structs for IPL
274ac4c5958SCollin L. Walling */
275ac4c5958SCollin L. Walling #define STAGE2_BLK_CNT_MAX 24 /* Stage 1b can load up to 24 blocks */
27626f2bbd6SEugene (jno) Dvurechenski
277ac4c5958SCollin L. Walling typedef struct EckdCdlIpl1 {
278ac4c5958SCollin L. Walling uint8_t key[4]; /* == "IPL1" */
279ac4c5958SCollin L. Walling uint8_t data[24];
280ac4c5958SCollin L. Walling } __attribute__((packed)) EckdCdlIpl1;
281ac4c5958SCollin L. Walling
282ba831b25SCollin L. Walling typedef struct EckdSeekArg {
283ba831b25SCollin L. Walling uint16_t pad;
284ba831b25SCollin L. Walling EckdCHS chs;
285ba831b25SCollin L. Walling uint8_t pad2;
286ba831b25SCollin L. Walling } __attribute__ ((packed)) EckdSeekArg;
287ba831b25SCollin L. Walling
288ba831b25SCollin L. Walling typedef struct EckdStage1b {
289ba831b25SCollin L. Walling uint8_t reserved[32 * STAGE2_BLK_CNT_MAX];
290ba831b25SCollin L. Walling struct EckdSeekArg seek[STAGE2_BLK_CNT_MAX];
291ba831b25SCollin L. Walling uint8_t unused[64];
292ba831b25SCollin L. Walling } __attribute__ ((packed)) EckdStage1b;
293ba831b25SCollin L. Walling
294ba831b25SCollin L. Walling typedef struct EckdStage1 {
295ba831b25SCollin L. Walling uint8_t reserved[72];
296ba831b25SCollin L. Walling struct EckdSeekArg seek[2];
297ba831b25SCollin L. Walling } __attribute__ ((packed)) EckdStage1;
298ba831b25SCollin L. Walling
299ac4c5958SCollin L. Walling typedef struct EckdCdlIpl2 {
300ac4c5958SCollin L. Walling uint8_t key[4]; /* == "IPL2" */
301ba831b25SCollin L. Walling struct EckdStage1 stage1;
30226f2bbd6SEugene (jno) Dvurechenski XEckdMbr mbr;
303ac4c5958SCollin L. Walling uint8_t reserved[24];
304ac4c5958SCollin L. Walling } __attribute__((packed)) EckdCdlIpl2;
305ac4c5958SCollin L. Walling
306ac4c5958SCollin L. Walling typedef struct EckdLdlIpl1 {
307ba831b25SCollin L. Walling uint8_t reserved[24];
308ba831b25SCollin L. Walling struct EckdStage1 stage1;
309ac4c5958SCollin L. Walling BootInfo bip; /* BootInfo is MBR for LDL */
310ac4c5958SCollin L. Walling } __attribute__((packed)) EckdLdlIpl1;
31126f2bbd6SEugene (jno) Dvurechenski
31226f2bbd6SEugene (jno) Dvurechenski typedef struct IplVolumeLabel {
31326f2bbd6SEugene (jno) Dvurechenski unsigned char key[4]; /* == "VOL1" */
31426f2bbd6SEugene (jno) Dvurechenski union {
31526f2bbd6SEugene (jno) Dvurechenski unsigned char data[80];
31626f2bbd6SEugene (jno) Dvurechenski struct {
31726f2bbd6SEugene (jno) Dvurechenski unsigned char key[4]; /* == "VOL1" */
31826f2bbd6SEugene (jno) Dvurechenski unsigned char volser[6];
3198af5d141SJared Rossi unsigned char reserved[64];
3208af5d141SJared Rossi EckdCHS br; /* Location of Boot Record for list-directed IPL */
32126f2bbd6SEugene (jno) Dvurechenski } f;
32226f2bbd6SEugene (jno) Dvurechenski };
32326f2bbd6SEugene (jno) Dvurechenski } __attribute__((packed)) IplVolumeLabel;
32426f2bbd6SEugene (jno) Dvurechenski
325564e52b9SEugene (jno) Dvurechenski typedef enum {
326564e52b9SEugene (jno) Dvurechenski ECKD_NO_IPL,
327564e52b9SEugene (jno) Dvurechenski ECKD_CMS,
328564e52b9SEugene (jno) Dvurechenski ECKD_LDL,
32914f56a2eSEugene (jno) Dvurechenski ECKD_LDL_UNLABELED,
330564e52b9SEugene (jno) Dvurechenski } ECKD_IPL_mode_t;
331564e52b9SEugene (jno) Dvurechenski
332a94b485eSEugene (jno) Dvurechenski /* utility code below */
333a94b485eSEugene (jno) Dvurechenski
print_volser(const void * volser)334a94b485eSEugene (jno) Dvurechenski static inline void print_volser(const void *volser)
335a94b485eSEugene (jno) Dvurechenski {
336a94b485eSEugene (jno) Dvurechenski char ascii[8];
337a94b485eSEugene (jno) Dvurechenski
338a94b485eSEugene (jno) Dvurechenski ebcdic_to_ascii((char *)volser, ascii, 6);
339a94b485eSEugene (jno) Dvurechenski ascii[6] = '\0';
3409f427883SJared Rossi printf("VOLSER=[%s]\n", ascii);
341a94b485eSEugene (jno) Dvurechenski }
342a94b485eSEugene (jno) Dvurechenski
unused_space(const void * p,size_t size)343a94b485eSEugene (jno) Dvurechenski static inline bool unused_space(const void *p, size_t size)
344a94b485eSEugene (jno) Dvurechenski {
345a94b485eSEugene (jno) Dvurechenski size_t i;
346a94b485eSEugene (jno) Dvurechenski const unsigned char *m = p;
347a94b485eSEugene (jno) Dvurechenski
348a94b485eSEugene (jno) Dvurechenski for (i = 0; i < size; i++) {
349a94b485eSEugene (jno) Dvurechenski if (m[i] != FREE_SPACE_FILLER) {
350a94b485eSEugene (jno) Dvurechenski return false;
351a94b485eSEugene (jno) Dvurechenski }
352a94b485eSEugene (jno) Dvurechenski }
353a94b485eSEugene (jno) Dvurechenski return true;
354a94b485eSEugene (jno) Dvurechenski }
355a94b485eSEugene (jno) Dvurechenski
is_null_block_number(block_number_t x)356a94b485eSEugene (jno) Dvurechenski static inline bool is_null_block_number(block_number_t x)
357a94b485eSEugene (jno) Dvurechenski {
358a94b485eSEugene (jno) Dvurechenski return x == NULL_BLOCK_NR;
359a94b485eSEugene (jno) Dvurechenski }
360a94b485eSEugene (jno) Dvurechenski
read_block(block_number_t blockno,void * buffer,const char * errmsg)361a94b485eSEugene (jno) Dvurechenski static inline void read_block(block_number_t blockno,
362a94b485eSEugene (jno) Dvurechenski void *buffer,
363a94b485eSEugene (jno) Dvurechenski const char *errmsg)
364a94b485eSEugene (jno) Dvurechenski {
365a94b485eSEugene (jno) Dvurechenski IPL_assert(virtio_read(blockno, buffer) == 0, errmsg);
366a94b485eSEugene (jno) Dvurechenski }
367a94b485eSEugene (jno) Dvurechenski
block_size_ok(uint32_t block_size)368a94b485eSEugene (jno) Dvurechenski static inline bool block_size_ok(uint32_t block_size)
369a94b485eSEugene (jno) Dvurechenski {
370a94b485eSEugene (jno) Dvurechenski return block_size == virtio_get_block_size();
371a94b485eSEugene (jno) Dvurechenski }
372a94b485eSEugene (jno) Dvurechenski
magic_match(const void * data,const void * magic)373a94b485eSEugene (jno) Dvurechenski static inline bool magic_match(const void *data, const void *magic)
374a94b485eSEugene (jno) Dvurechenski {
375a94b485eSEugene (jno) Dvurechenski return *((uint32_t *)data) == *((uint32_t *)magic);
376a94b485eSEugene (jno) Dvurechenski }
377a94b485eSEugene (jno) Dvurechenski
iso_733_to_u32(uint64_t x)378869648e8SMaxim Samoylov static inline uint32_t iso_733_to_u32(uint64_t x)
379869648e8SMaxim Samoylov {
380869648e8SMaxim Samoylov return (uint32_t)x;
381869648e8SMaxim Samoylov }
382869648e8SMaxim Samoylov
383866cac91SMaxim Samoylov #define ISO_SECTOR_SIZE 2048
384866cac91SMaxim Samoylov /* El Torito specifies boot image size in 512 byte blocks */
385866cac91SMaxim Samoylov #define ET_SECTOR_SHIFT 2
386866cac91SMaxim Samoylov
387866cac91SMaxim Samoylov #define ISO_PRIMARY_VD_SECTOR 16
388866cac91SMaxim Samoylov
read_iso_boot_image(uint32_t block_offset,void * load_addr,uint32_t blks_to_load)389bef2b8ddSJared Rossi static inline int read_iso_boot_image(uint32_t block_offset, void *load_addr,
390866cac91SMaxim Samoylov uint32_t blks_to_load)
391866cac91SMaxim Samoylov {
392bef2b8ddSJared Rossi if (virtio_read_many(block_offset, load_addr, blks_to_load)) {
393bef2b8ddSJared Rossi puts("Failed to read boot image!");
394bef2b8ddSJared Rossi return -1;
395bef2b8ddSJared Rossi }
396bef2b8ddSJared Rossi return 0;
397866cac91SMaxim Samoylov }
398866cac91SMaxim Samoylov
399869648e8SMaxim Samoylov #define ISO9660_MAX_DIR_DEPTH 8
400869648e8SMaxim Samoylov
401866cac91SMaxim Samoylov typedef struct IsoDirHdr {
402866cac91SMaxim Samoylov uint8_t dr_len;
403866cac91SMaxim Samoylov uint8_t ear_len;
404866cac91SMaxim Samoylov uint64_t ext_loc;
405866cac91SMaxim Samoylov uint64_t data_len;
406866cac91SMaxim Samoylov uint8_t recording_datetime[7];
407866cac91SMaxim Samoylov uint8_t file_flags;
408866cac91SMaxim Samoylov uint8_t file_unit_size;
409866cac91SMaxim Samoylov uint8_t gap_size;
410866cac91SMaxim Samoylov uint32_t vol_seqnum;
411866cac91SMaxim Samoylov uint8_t fileid_len;
412866cac91SMaxim Samoylov } __attribute__((packed)) IsoDirHdr;
413866cac91SMaxim Samoylov
414866cac91SMaxim Samoylov typedef struct IsoVdElTorito {
415866cac91SMaxim Samoylov uint8_t el_torito[32]; /* must contain el_torito_magic value */
416866cac91SMaxim Samoylov uint8_t unused0[32];
417866cac91SMaxim Samoylov uint32_t bc_offset;
418866cac91SMaxim Samoylov uint8_t unused1[1974];
419866cac91SMaxim Samoylov } __attribute__((packed)) IsoVdElTorito;
420866cac91SMaxim Samoylov
421866cac91SMaxim Samoylov typedef struct IsoVdPrimary {
422866cac91SMaxim Samoylov uint8_t unused1;
423866cac91SMaxim Samoylov uint8_t sys_id[32];
424866cac91SMaxim Samoylov uint8_t vol_id[32];
425866cac91SMaxim Samoylov uint8_t unused2[8];
426866cac91SMaxim Samoylov uint64_t vol_space_size;
427866cac91SMaxim Samoylov uint8_t unused3[32];
428866cac91SMaxim Samoylov uint32_t vol_set_size;
429866cac91SMaxim Samoylov uint32_t vol_seqnum;
430866cac91SMaxim Samoylov uint32_t log_block_size;
431866cac91SMaxim Samoylov uint64_t path_table_size;
432866cac91SMaxim Samoylov uint32_t l_path_table;
433866cac91SMaxim Samoylov uint32_t opt_l_path_table;
434866cac91SMaxim Samoylov uint32_t m_path_table;
435866cac91SMaxim Samoylov uint32_t opt_m_path_table;
436866cac91SMaxim Samoylov IsoDirHdr rootdir;
437866cac91SMaxim Samoylov uint8_t root_null;
438866cac91SMaxim Samoylov uint8_t reserved2[1858];
439866cac91SMaxim Samoylov } __attribute__((packed)) IsoVdPrimary;
440866cac91SMaxim Samoylov
441866cac91SMaxim Samoylov typedef struct IsoVolDesc {
442866cac91SMaxim Samoylov uint8_t type;
443866cac91SMaxim Samoylov uint8_t ident[5];
444866cac91SMaxim Samoylov uint8_t version;
445866cac91SMaxim Samoylov union {
446866cac91SMaxim Samoylov IsoVdElTorito boot;
447866cac91SMaxim Samoylov IsoVdPrimary primary;
448866cac91SMaxim Samoylov } vd;
449866cac91SMaxim Samoylov } __attribute__((packed)) IsoVolDesc;
450866cac91SMaxim Samoylov
451866cac91SMaxim Samoylov #define VOL_DESC_TYPE_BOOT 0
452866cac91SMaxim Samoylov #define VOL_DESC_TYPE_PRIMARY 1
453866cac91SMaxim Samoylov #define VOL_DESC_TYPE_SUPPLEMENT 2
454866cac91SMaxim Samoylov #define VOL_DESC_TYPE_PARTITION 3
455866cac91SMaxim Samoylov #define VOL_DESC_TERMINATOR 255
456866cac91SMaxim Samoylov
457866cac91SMaxim Samoylov typedef struct IsoBcValid {
458866cac91SMaxim Samoylov uint8_t platform_id;
459866cac91SMaxim Samoylov uint16_t reserved;
460866cac91SMaxim Samoylov uint8_t id[24];
461866cac91SMaxim Samoylov uint16_t checksum;
462866cac91SMaxim Samoylov uint8_t key[2];
463866cac91SMaxim Samoylov } __attribute__((packed)) IsoBcValid;
464866cac91SMaxim Samoylov
465866cac91SMaxim Samoylov typedef struct IsoBcSection {
466866cac91SMaxim Samoylov uint8_t boot_type;
467866cac91SMaxim Samoylov uint16_t load_segment;
468866cac91SMaxim Samoylov uint8_t sys_type;
469866cac91SMaxim Samoylov uint8_t unused;
470866cac91SMaxim Samoylov uint16_t sector_count;
471866cac91SMaxim Samoylov uint32_t load_rba;
472866cac91SMaxim Samoylov uint8_t selection[20];
473866cac91SMaxim Samoylov } __attribute__((packed)) IsoBcSection;
474866cac91SMaxim Samoylov
475866cac91SMaxim Samoylov typedef struct IsoBcHdr {
476866cac91SMaxim Samoylov uint8_t platform_id;
477866cac91SMaxim Samoylov uint16_t sect_num;
478866cac91SMaxim Samoylov uint8_t id[28];
479866cac91SMaxim Samoylov } __attribute__((packed)) IsoBcHdr;
480866cac91SMaxim Samoylov
481866cac91SMaxim Samoylov typedef struct IsoBcEntry {
482866cac91SMaxim Samoylov uint8_t id;
483866cac91SMaxim Samoylov union {
484866cac91SMaxim Samoylov IsoBcValid valid; /* id == 0x01 */
485866cac91SMaxim Samoylov IsoBcSection sect; /* id == 0x88 || id == 0x0 */
486866cac91SMaxim Samoylov IsoBcHdr hdr; /* id == 0x90 || id == 0x91 */
487866cac91SMaxim Samoylov } body;
488866cac91SMaxim Samoylov } __attribute__((packed)) IsoBcEntry;
489866cac91SMaxim Samoylov
490866cac91SMaxim Samoylov #define ISO_BC_ENTRY_PER_SECTOR (ISO_SECTOR_SIZE / sizeof(IsoBcEntry))
491866cac91SMaxim Samoylov #define ISO_BC_HDR_VALIDATION 0x01
492866cac91SMaxim Samoylov #define ISO_BC_BOOTABLE_SECTION 0x88
493866cac91SMaxim Samoylov #define ISO_BC_MAGIC_55 0x55
494866cac91SMaxim Samoylov #define ISO_BC_MAGIC_AA 0xaa
495866cac91SMaxim Samoylov #define ISO_BC_PLATFORM_X86 0x0
496866cac91SMaxim Samoylov #define ISO_BC_PLATFORM_PPC 0x1
497866cac91SMaxim Samoylov #define ISO_BC_PLATFORM_MAC 0x2
498866cac91SMaxim Samoylov
is_iso_bc_valid(IsoBcEntry * e)499866cac91SMaxim Samoylov static inline bool is_iso_bc_valid(IsoBcEntry *e)
500866cac91SMaxim Samoylov {
501866cac91SMaxim Samoylov IsoBcValid *v = &e->body.valid;
502866cac91SMaxim Samoylov
503866cac91SMaxim Samoylov if (e->id != ISO_BC_HDR_VALIDATION) {
504866cac91SMaxim Samoylov return false;
505866cac91SMaxim Samoylov }
506866cac91SMaxim Samoylov
507866cac91SMaxim Samoylov if (v->platform_id != ISO_BC_PLATFORM_X86 &&
508866cac91SMaxim Samoylov v->platform_id != ISO_BC_PLATFORM_PPC &&
509866cac91SMaxim Samoylov v->platform_id != ISO_BC_PLATFORM_MAC) {
510866cac91SMaxim Samoylov return false;
511866cac91SMaxim Samoylov }
512866cac91SMaxim Samoylov
513866cac91SMaxim Samoylov return v->key[0] == ISO_BC_MAGIC_55 &&
514866cac91SMaxim Samoylov v->key[1] == ISO_BC_MAGIC_AA &&
515866cac91SMaxim Samoylov v->reserved == 0x0;
516866cac91SMaxim Samoylov }
517866cac91SMaxim Samoylov
51826f2bbd6SEugene (jno) Dvurechenski #endif /* _PC_BIOS_S390_CCW_BOOTMAP_H */
519