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