cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

bootmap.h (14326B)


      1/*
      2 * QEMU S390 bootmap interpreter -- declarations
      3 *
      4 * Copyright 2014 IBM Corp.
      5 * Author(s): Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com>
      6 *
      7 * This work is licensed under the terms of the GNU GPL, version 2 or (at
      8 * your option) any later version. See the COPYING file in the top-level
      9 * directory.
     10 */
     11#ifndef _PC_BIOS_S390_CCW_BOOTMAP_H
     12#define _PC_BIOS_S390_CCW_BOOTMAP_H
     13
     14#include "s390-ccw.h"
     15#include "virtio.h"
     16
     17typedef uint64_t block_number_t;
     18#define NULL_BLOCK_NR 0xffffffffffffffffULL
     19
     20#define FREE_SPACE_FILLER '\xAA'
     21
     22typedef struct ScsiBlockPtr {
     23    uint64_t blockno;
     24    uint16_t size;
     25    uint16_t blockct;
     26    uint8_t reserved[4];
     27} __attribute__ ((packed)) ScsiBlockPtr;
     28
     29typedef struct FbaBlockPtr {
     30    uint32_t blockno;
     31    uint16_t size;
     32    uint16_t blockct;
     33} __attribute__ ((packed)) FbaBlockPtr;
     34
     35typedef struct EckdCHS {
     36    uint16_t cylinder;
     37    uint16_t head;
     38    uint8_t sector;
     39} __attribute__ ((packed)) EckdCHS;
     40
     41typedef struct EckdBlockPtr {
     42    EckdCHS chs; /* cylinder/head/sector is an address of the block */
     43    uint16_t size;
     44    uint8_t count; /* (size_in_blocks-1);
     45                    * it's 0 for TablePtr, ScriptPtr, and SectionPtr */
     46} __attribute__ ((packed)) EckdBlockPtr;
     47
     48typedef struct ExtEckdBlockPtr {
     49    EckdBlockPtr bptr;
     50    uint8_t reserved[8];
     51} __attribute__ ((packed)) ExtEckdBlockPtr;
     52
     53typedef union BootMapPointer {
     54    ScsiBlockPtr scsi;
     55    FbaBlockPtr fba;
     56    EckdBlockPtr eckd;
     57    ExtEckdBlockPtr xeckd;
     58} __attribute__ ((packed)) BootMapPointer;
     59
     60/* aka Program Table */
     61typedef struct BootMapTable {
     62    uint8_t magic[4];
     63    uint8_t reserved[12];
     64    BootMapPointer entry[];
     65} __attribute__ ((packed)) BootMapTable;
     66
     67typedef union ComponentEntryData {
     68    uint64_t load_psw;
     69    uint64_t load_addr;
     70} ComponentEntryData;
     71
     72typedef struct ComponentEntry {
     73    ScsiBlockPtr data;
     74    uint8_t pad[7];
     75    uint8_t component_type;
     76    ComponentEntryData compdat;
     77} __attribute((packed)) ComponentEntry;
     78
     79typedef struct ComponentHeader {
     80    uint8_t magic[4];   /* == "zIPL"                    */
     81    uint8_t type;       /* == ZIPL_COMP_HEADER_*        */
     82    uint8_t reserved[27];
     83} __attribute((packed)) ComponentHeader;
     84
     85typedef struct ScsiMbr {
     86    uint8_t magic[4];
     87    uint32_t version_id;
     88    uint8_t reserved[8];
     89    ScsiBlockPtr pt;   /* block pointer to program table */
     90} __attribute__ ((packed)) ScsiMbr;
     91
     92#define ZIPL_MAGIC              "zIPL"
     93#define ZIPL_MAGIC_EBCDIC       "\xa9\xc9\xd7\xd3"
     94#define IPL1_MAGIC "\xc9\xd7\xd3\xf1" /* == "IPL1" in EBCDIC */
     95#define IPL2_MAGIC "\xc9\xd7\xd3\xf2" /* == "IPL2" in EBCDIC */
     96#define VOL1_MAGIC "\xe5\xd6\xd3\xf1" /* == "VOL1" in EBCDIC */
     97#define LNX1_MAGIC "\xd3\xd5\xe7\xf1" /* == "LNX1" in EBCDIC */
     98#define CMS1_MAGIC "\xc3\xd4\xe2\xf1" /* == "CMS1" in EBCDIC */
     99
    100#define LDL1_VERSION '\x40' /* == ' ' in EBCDIC */
    101#define LDL2_VERSION '\xf2' /* == '2' in EBCDIC */
    102
    103#define ZIPL_COMP_HEADER_IPL    0x00
    104#define ZIPL_COMP_HEADER_DUMP   0x01
    105
    106#define ZIPL_COMP_ENTRY_EXEC      0x01
    107#define ZIPL_COMP_ENTRY_LOAD      0x02
    108#define ZIPL_COMP_ENTRY_SIGNATURE 0x03
    109
    110typedef struct XEckdMbr {
    111    uint8_t magic[4];   /* == "xIPL"        */
    112    uint8_t version;
    113    uint8_t bp_type;
    114    uint8_t dev_type;   /* == DEV_TYPE_*    */
    115#define DEV_TYPE_ECKD 0x00
    116#define DEV_TYPE_FBA  0x01
    117    uint8_t flags;
    118    BootMapPointer blockptr;
    119    uint8_t reserved[8];
    120} __attribute__ ((packed)) XEckdMbr; /* see also BootInfo */
    121
    122typedef struct BootMapScriptEntry {
    123    BootMapPointer blkptr;
    124    uint8_t pad[7];
    125    uint8_t type;   /* == BOOT_SCRIPT_* */
    126#define BOOT_SCRIPT_EXEC      0x01
    127#define BOOT_SCRIPT_LOAD      0x02
    128#define BOOT_SCRIPT_SIGNATURE 0x03
    129    union {
    130        uint64_t load_address;
    131        uint64_t load_psw;
    132    } address;
    133} __attribute__ ((packed)) BootMapScriptEntry;
    134
    135typedef struct BootMapScriptHeader {
    136    uint32_t magic;
    137    uint8_t type;
    138#define BOOT_SCRIPT_HDR_IPL 0x00
    139    uint8_t reserved[27];
    140} __attribute__ ((packed)) BootMapScriptHeader;
    141
    142typedef struct BootMapScript {
    143    BootMapScriptHeader header;
    144    BootMapScriptEntry  entry[];
    145} __attribute__ ((packed)) BootMapScript;
    146
    147/*
    148 * These aren't real VTOCs, but referred to this way in some docs.
    149 * They are "volume labels" actually.
    150 *
    151 * Some structures looks similar to described above, but left
    152 * separate as there is no indication that they are the same.
    153 * So, the value definitions are left separate too.
    154 */
    155typedef struct LDL_VTOC {       /* @ rec.3 cyl.0 trk.0 for ECKD */
    156    char magic[4];              /* "LNX1", EBCDIC               */
    157    char volser[6];             /* volser, EBCDIC               */
    158    uint8_t reserved[69];       /* reserved, 0x40               */
    159    uint8_t LDL_version;        /* 0x40 or 0xF2                 */
    160    uint64_t formatted_blocks;  /* if LDL_version >= 0xF2       */
    161} __attribute__ ((packed)) LDL_VTOC;
    162
    163typedef struct format_date {
    164    uint8_t YY;
    165    uint8_t MM;
    166    uint8_t DD;
    167    uint8_t hh;
    168    uint8_t mm;
    169    uint8_t ss;
    170} __attribute__ ((packed)) format_date_t;
    171
    172typedef struct CMS_VTOC {       /* @ rec.3 cyl.0 trk.0 for ECKD */
    173                                /* @ blk.1 (zero based) for FBA */
    174    char magic[4];              /* 'CMS1', EBCDIC               */
    175    char volser[6];             /* volser, EBCDIC               */
    176    uint16_t version;           /* = 0                          */
    177    uint32_t block_size;        /* = 512, 1024, 2048, or 4096   */
    178    uint32_t disk_origin;       /* = 4 or 5                     */
    179    uint32_t blocks;            /* Number of usable cyls/blocks */
    180    uint32_t formatted;         /* Max number of fmtd cyls/blks */
    181    uint32_t CMS_blocks;        /* disk size in CMS blocks      */
    182    uint32_t CMS_used;          /* Number of CMS blocks in use  */
    183    uint32_t FST_size;          /* = 64, bytes                  */
    184    uint32_t FST_per_CMS_blk;   /*                              */
    185    format_date_t format_date;  /* YYMMDDhhmmss as 6 bytes      */
    186    uint8_t reserved1[2];       /* = 0                          */
    187    uint32_t offset;            /* disk offset when reserved    */
    188    uint32_t next_hole;         /* block nr                     */
    189    uint32_t HBLK_hole_offset;  /* >> HBLK data of next hole    */
    190    uint32_t alloc_map_usr_off; /* >> user part of Alloc map    */
    191    uint8_t reserved2[4];       /* = 0                          */
    192    char shared_seg_name[8];    /*                              */
    193} __attribute__ ((packed)) CMS_VTOC;
    194
    195/* from zipl/include/boot.h */
    196typedef struct BootInfoBpIpl {
    197    union {
    198        ExtEckdBlockPtr eckd;
    199        ScsiBlockPtr linr;
    200    } bm_ptr;
    201    uint8_t unused[16];
    202} __attribute__ ((packed)) BootInfoBpIpl;
    203
    204typedef struct EckdDumpParam {
    205    uint32_t        start_blk;
    206    uint32_t        end_blk;
    207    uint16_t        blocksize;
    208    uint8_t         num_heads;
    209    uint8_t         bpt;
    210    char            reserved[4];
    211} __attribute((packed, may_alias)) EckdDumpParam;
    212
    213typedef struct FbaDumpParam {
    214    uint64_t        start_blk;
    215    uint64_t        blockct;
    216} __attribute((packed)) FbaDumpParam;
    217
    218typedef struct BootInfoBpDump {
    219    union {
    220        EckdDumpParam eckd;
    221        FbaDumpParam fba;
    222    } param;
    223    uint8_t         unused[16];
    224} __attribute__ ((packed)) BootInfoBpDump;
    225
    226typedef struct BootInfo {          /* @ 0x70, record #0    */
    227    unsigned char magic[4]; /* = 'zIPL', ASCII      */
    228    uint8_t version;        /* = 1                  */
    229#define BOOT_INFO_VERSION               1
    230    uint8_t bp_type;        /* = 0                  */
    231#define BOOT_INFO_BP_TYPE_IPL           0x00
    232#define BOOT_INFO_BP_TYPE_DUMP          0x01
    233    uint8_t dev_type;       /* = 0                  */
    234#define BOOT_INFO_DEV_TYPE_ECKD         0x00
    235#define BOOT_INFO_DEV_TYPE_FBA          0x01
    236    uint8_t flags;          /* = 1                  */
    237#ifdef __s390x__
    238#define BOOT_INFO_FLAGS_ARCH            0x01
    239#else
    240#define BOOT_INFO_FLAGS_ARCH            0x00
    241#endif
    242    union {
    243        BootInfoBpDump dump;
    244        BootInfoBpIpl ipl;
    245    } bp;
    246} __attribute__ ((packed)) BootInfo; /* see also XEckdMbr   */
    247
    248/*
    249 * Structs for IPL
    250 */
    251#define STAGE2_BLK_CNT_MAX  24 /* Stage 1b can load up to 24 blocks */
    252
    253typedef struct EckdCdlIpl1 {
    254    uint8_t key[4]; /* == "IPL1" */
    255    uint8_t data[24];
    256} __attribute__((packed)) EckdCdlIpl1;
    257
    258typedef struct EckdSeekArg {
    259    uint16_t pad;
    260    EckdCHS chs;
    261    uint8_t pad2;
    262} __attribute__ ((packed)) EckdSeekArg;
    263
    264typedef struct EckdStage1b {
    265    uint8_t reserved[32 * STAGE2_BLK_CNT_MAX];
    266    struct EckdSeekArg seek[STAGE2_BLK_CNT_MAX];
    267    uint8_t unused[64];
    268} __attribute__ ((packed)) EckdStage1b;
    269
    270typedef struct EckdStage1 {
    271    uint8_t reserved[72];
    272    struct EckdSeekArg seek[2];
    273} __attribute__ ((packed)) EckdStage1;
    274
    275typedef struct EckdCdlIpl2 {
    276    uint8_t key[4]; /* == "IPL2" */
    277    struct EckdStage1 stage1;
    278    XEckdMbr mbr;
    279    uint8_t reserved[24];
    280} __attribute__((packed)) EckdCdlIpl2;
    281
    282typedef struct EckdLdlIpl1 {
    283    uint8_t reserved[24];
    284    struct EckdStage1 stage1;
    285    BootInfo bip; /* BootInfo is MBR for LDL */
    286} __attribute__((packed)) EckdLdlIpl1;
    287
    288typedef struct IplVolumeLabel {
    289    unsigned char key[4]; /* == "VOL1" */
    290    union {
    291        unsigned char data[80];
    292        struct {
    293            unsigned char key[4]; /* == "VOL1" */
    294            unsigned char volser[6];
    295            unsigned char reserved[6];
    296        } f;
    297    };
    298} __attribute__((packed)) IplVolumeLabel;
    299
    300typedef enum {
    301    ECKD_NO_IPL,
    302    ECKD_CMS,
    303    ECKD_LDL,
    304    ECKD_LDL_UNLABELED,
    305} ECKD_IPL_mode_t;
    306
    307/* utility code below */
    308
    309static inline void print_volser(const void *volser)
    310{
    311    char ascii[8];
    312
    313    ebcdic_to_ascii((char *)volser, ascii, 6);
    314    ascii[6] = '\0';
    315    sclp_print("VOLSER=[");
    316    sclp_print(ascii);
    317    sclp_print("]\n");
    318}
    319
    320static inline bool unused_space(const void *p, size_t size)
    321{
    322    size_t i;
    323    const unsigned char *m = p;
    324
    325    for (i = 0; i < size; i++) {
    326        if (m[i] != FREE_SPACE_FILLER) {
    327            return false;
    328        }
    329    }
    330    return true;
    331}
    332
    333static inline bool is_null_block_number(block_number_t x)
    334{
    335    return x == NULL_BLOCK_NR;
    336}
    337
    338static inline void read_block(block_number_t blockno,
    339                              void *buffer,
    340                              const char *errmsg)
    341{
    342    IPL_assert(virtio_read(blockno, buffer) == 0, errmsg);
    343}
    344
    345static inline bool block_size_ok(uint32_t block_size)
    346{
    347    return block_size == virtio_get_block_size();
    348}
    349
    350static inline bool magic_match(const void *data, const void *magic)
    351{
    352    return *((uint32_t *)data) == *((uint32_t *)magic);
    353}
    354
    355static inline uint32_t iso_733_to_u32(uint64_t x)
    356{
    357    return (uint32_t)x;
    358}
    359
    360#define ISO_SECTOR_SIZE 2048
    361/* El Torito specifies boot image size in 512 byte blocks */
    362#define ET_SECTOR_SHIFT 2
    363
    364#define ISO_PRIMARY_VD_SECTOR 16
    365
    366static inline void read_iso_sector(uint32_t block_offset, void *buf,
    367                                   const char *errmsg)
    368{
    369    IPL_assert(virtio_read_many(block_offset, buf, 1) == 0, errmsg);
    370}
    371
    372static inline void read_iso_boot_image(uint32_t block_offset, void *load_addr,
    373                                       uint32_t blks_to_load)
    374{
    375    IPL_assert(virtio_read_many(block_offset, load_addr, blks_to_load) == 0,
    376               "Failed to read boot image!");
    377}
    378
    379#define ISO9660_MAX_DIR_DEPTH 8
    380
    381typedef struct IsoDirHdr {
    382    uint8_t dr_len;
    383    uint8_t ear_len;
    384    uint64_t ext_loc;
    385    uint64_t data_len;
    386    uint8_t recording_datetime[7];
    387    uint8_t file_flags;
    388    uint8_t file_unit_size;
    389    uint8_t gap_size;
    390    uint32_t vol_seqnum;
    391    uint8_t fileid_len;
    392} __attribute__((packed)) IsoDirHdr;
    393
    394typedef struct IsoVdElTorito {
    395    uint8_t el_torito[32]; /* must contain el_torito_magic value */
    396    uint8_t unused0[32];
    397    uint32_t bc_offset;
    398    uint8_t unused1[1974];
    399} __attribute__((packed)) IsoVdElTorito;
    400
    401typedef struct IsoVdPrimary {
    402    uint8_t unused1;
    403    uint8_t sys_id[32];
    404    uint8_t vol_id[32];
    405    uint8_t unused2[8];
    406    uint64_t vol_space_size;
    407    uint8_t unused3[32];
    408    uint32_t vol_set_size;
    409    uint32_t vol_seqnum;
    410    uint32_t log_block_size;
    411    uint64_t path_table_size;
    412    uint32_t l_path_table;
    413    uint32_t opt_l_path_table;
    414    uint32_t m_path_table;
    415    uint32_t opt_m_path_table;
    416    IsoDirHdr rootdir;
    417    uint8_t root_null;
    418    uint8_t reserved2[1858];
    419} __attribute__((packed)) IsoVdPrimary;
    420
    421typedef struct IsoVolDesc {
    422    uint8_t type;
    423    uint8_t ident[5];
    424    uint8_t version;
    425    union {
    426        IsoVdElTorito boot;
    427        IsoVdPrimary primary;
    428    } vd;
    429} __attribute__((packed)) IsoVolDesc;
    430
    431#define VOL_DESC_TYPE_BOOT 0
    432#define VOL_DESC_TYPE_PRIMARY 1
    433#define VOL_DESC_TYPE_SUPPLEMENT 2
    434#define VOL_DESC_TYPE_PARTITION 3
    435#define VOL_DESC_TERMINATOR 255
    436
    437typedef struct IsoBcValid {
    438    uint8_t platform_id;
    439    uint16_t reserved;
    440    uint8_t id[24];
    441    uint16_t checksum;
    442    uint8_t key[2];
    443} __attribute__((packed)) IsoBcValid;
    444
    445typedef struct IsoBcSection {
    446    uint8_t boot_type;
    447    uint16_t load_segment;
    448    uint8_t sys_type;
    449    uint8_t unused;
    450    uint16_t sector_count;
    451    uint32_t load_rba;
    452    uint8_t selection[20];
    453} __attribute__((packed)) IsoBcSection;
    454
    455typedef struct IsoBcHdr {
    456    uint8_t platform_id;
    457    uint16_t sect_num;
    458    uint8_t id[28];
    459} __attribute__((packed)) IsoBcHdr;
    460
    461typedef struct IsoBcEntry {
    462    uint8_t id;
    463    union {
    464        IsoBcValid valid; /* id == 0x01 */
    465        IsoBcSection sect; /* id == 0x88 || id == 0x0 */
    466        IsoBcHdr hdr; /* id == 0x90 || id == 0x91 */
    467    } body;
    468} __attribute__((packed)) IsoBcEntry;
    469
    470#define ISO_BC_ENTRY_PER_SECTOR (ISO_SECTOR_SIZE / sizeof(IsoBcEntry))
    471#define ISO_BC_HDR_VALIDATION 0x01
    472#define ISO_BC_BOOTABLE_SECTION 0x88
    473#define ISO_BC_MAGIC_55 0x55
    474#define ISO_BC_MAGIC_AA 0xaa
    475#define ISO_BC_PLATFORM_X86 0x0
    476#define ISO_BC_PLATFORM_PPC 0x1
    477#define ISO_BC_PLATFORM_MAC 0x2
    478
    479static inline bool is_iso_bc_valid(IsoBcEntry *e)
    480{
    481    IsoBcValid *v = &e->body.valid;
    482
    483    if (e->id != ISO_BC_HDR_VALIDATION) {
    484        return false;
    485    }
    486
    487    if (v->platform_id != ISO_BC_PLATFORM_X86 &&
    488        v->platform_id != ISO_BC_PLATFORM_PPC &&
    489        v->platform_id != ISO_BC_PLATFORM_MAC) {
    490        return false;
    491    }
    492
    493    return v->key[0] == ISO_BC_MAGIC_55 &&
    494           v->key[1] == ISO_BC_MAGIC_AA &&
    495           v->reserved == 0x0;
    496}
    497
    498#endif /* _PC_BIOS_S390_CCW_BOOTMAP_H */