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 #ifndef QEMU_PACKED 16 #define QEMU_PACKED __attribute__((packed)) 17 #endif 18 19 #include <qipl.h> 20 #include <string.h> 21 22 extern QemuIplParameters qipl; 23 extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); 24 extern bool have_iplb; 25 26 #define S390_IPL_TYPE_FCP 0x00 27 #define S390_IPL_TYPE_CCW 0x02 28 #define S390_IPL_TYPE_QEMU_SCSI 0xff 29 30 static inline bool manage_iplb(IplParameterBlock *iplb, bool store) 31 { 32 register unsigned long addr asm("0") = (unsigned long) iplb; 33 register unsigned long rc asm("1") = 0; 34 unsigned long subcode = store ? 6 : 5; 35 36 asm volatile ("diag %0,%2,0x308\n" 37 : "+d" (addr), "+d" (rc) 38 : "d" (subcode) 39 : "memory", "cc"); 40 return rc == 0x01; 41 } 42 43 44 static inline bool store_iplb(IplParameterBlock *iplb) 45 { 46 return manage_iplb(iplb, true); 47 } 48 49 static inline bool set_iplb(IplParameterBlock *iplb) 50 { 51 return manage_iplb(iplb, false); 52 } 53 54 /* 55 * The IPL started on the device, but failed in some way. If the IPLB chain 56 * still has more devices left to try, use the next device in order. 57 */ 58 static inline bool load_next_iplb(void) 59 { 60 IplParameterBlock *next_iplb; 61 62 if (qipl.chain_len < 1) { 63 return false; 64 } 65 66 qipl.index++; 67 next_iplb = (IplParameterBlock *) qipl.next_iplb; 68 memcpy(&iplb, next_iplb, sizeof(IplParameterBlock)); 69 70 qipl.chain_len--; 71 qipl.next_iplb = qipl.next_iplb + sizeof(IplParameterBlock); 72 73 return true; 74 } 75 76 #endif /* IPLB_H */ 77