1 /* 2 * QEMU S390 IPL Block 3 * 4 * Copyright 2015 IBM Corp. 5 * Author(s): Alexander Yarygin <yarygin@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 12 #ifndef IPLB_H 13 #define IPLB_H 14 15 #define LOADPARM_LEN 8 16 17 struct IplBlockCcw { 18 uint8_t reserved0[85]; 19 uint8_t ssid; 20 uint16_t devno; 21 uint8_t vm_flags; 22 uint8_t reserved3[3]; 23 uint32_t vm_parm_len; 24 uint8_t nss_name[8]; 25 uint8_t vm_parm[64]; 26 uint8_t reserved4[8]; 27 } __attribute__ ((packed)); 28 typedef struct IplBlockCcw IplBlockCcw; 29 30 struct IplBlockFcp { 31 uint8_t reserved1[305 - 1]; 32 uint8_t opt; 33 uint8_t reserved2[3]; 34 uint16_t reserved3; 35 uint16_t devno; 36 uint8_t reserved4[4]; 37 uint64_t wwpn; 38 uint64_t lun; 39 uint32_t bootprog; 40 uint8_t reserved5[12]; 41 uint64_t br_lba; 42 uint32_t scp_data_len; 43 uint8_t reserved6[260]; 44 uint8_t scp_data[]; 45 } __attribute__ ((packed)); 46 typedef struct IplBlockFcp IplBlockFcp; 47 48 struct IplBlockQemuScsi { 49 uint32_t lun; 50 uint16_t target; 51 uint16_t channel; 52 uint8_t reserved0[77]; 53 uint8_t ssid; 54 uint16_t devno; 55 } __attribute__ ((packed)); 56 typedef struct IplBlockQemuScsi IplBlockQemuScsi; 57 58 struct IplParameterBlock { 59 uint32_t len; 60 uint8_t reserved0[3]; 61 uint8_t version; 62 uint32_t blk0_len; 63 uint8_t pbt; 64 uint8_t flags; 65 uint16_t reserved01; 66 uint8_t loadparm[LOADPARM_LEN]; 67 union { 68 IplBlockCcw ccw; 69 IplBlockFcp fcp; 70 IplBlockQemuScsi scsi; 71 }; 72 } __attribute__ ((packed)); 73 typedef struct IplParameterBlock IplParameterBlock; 74 75 extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); 76 77 #define QIPL_ADDRESS 0xcc 78 79 /* Boot Menu flags */ 80 #define QIPL_FLAG_BM_OPTS_CMD 0x80 81 #define QIPL_FLAG_BM_OPTS_ZIPL 0x40 82 83 /* 84 * This definition must be kept in sync with the defininition 85 * in hw/s390x/ipl.h 86 */ 87 struct QemuIplParameters { 88 uint8_t qipl_flags; 89 uint8_t reserved1[3]; 90 uint64_t netboot_start_addr; 91 uint32_t boot_menu_timeout; 92 uint8_t reserved2[12]; 93 } __attribute__ ((packed)); 94 typedef struct QemuIplParameters QemuIplParameters; 95 96 extern QemuIplParameters qipl; 97 98 #define S390_IPL_TYPE_FCP 0x00 99 #define S390_IPL_TYPE_CCW 0x02 100 #define S390_IPL_TYPE_QEMU_SCSI 0xff 101 102 static inline bool manage_iplb(IplParameterBlock *iplb, bool store) 103 { 104 register unsigned long addr asm("0") = (unsigned long) iplb; 105 register unsigned long rc asm("1") = 0; 106 unsigned long subcode = store ? 6 : 5; 107 108 asm volatile ("diag %0,%2,0x308\n" 109 : "+d" (addr), "+d" (rc) 110 : "d" (subcode) 111 : "memory", "cc"); 112 return rc == 0x01; 113 } 114 115 116 static inline bool store_iplb(IplParameterBlock *iplb) 117 { 118 return manage_iplb(iplb, true); 119 } 120 121 static inline bool set_iplb(IplParameterBlock *iplb) 122 { 123 return manage_iplb(iplb, false); 124 } 125 126 #endif /* IPLB_H */ 127