xref: /openbmc/qemu/pc-bios/s390-ccw/iplb.h (revision f697bed2)
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 
manage_iplb(IplParameterBlock * iplb,bool store)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 
store_iplb(IplParameterBlock * iplb)44 static inline bool store_iplb(IplParameterBlock *iplb)
45 {
46     return manage_iplb(iplb, true);
47 }
48 
set_iplb(IplParameterBlock * iplb)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  */
load_next_iplb(void)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