1 | /* |
2 | * s390 IPL device |
3 | * |
4 | * Copyright 2015 IBM Corp. |
5 | * Author(s): Zhang Fan <bjfanzh@cn.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 HW_S390_IPL_H |
13 | #define HW_S390_IPL_H |
14 | |
15 | #include "cpu.h" |
16 | #include "hw/qdev-core.h" |
17 | |
18 | struct IplBlockCcw { |
19 | uint8_t reserved0[85]; |
20 | uint8_t ssid; |
21 | uint16_t devno; |
22 | uint8_t vm_flags; |
23 | uint8_t reserved3[3]; |
24 | uint32_t vm_parm_len; |
25 | uint8_t nss_name[8]; |
26 | uint8_t vm_parm[64]; |
27 | uint8_t reserved4[8]; |
28 | } QEMU_PACKED; |
29 | typedef struct IplBlockCcw IplBlockCcw; |
30 | |
31 | struct IplBlockFcp { |
32 | uint8_t reserved1[305 - 1]; |
33 | uint8_t opt; |
34 | uint8_t reserved2[3]; |
35 | uint16_t reserved3; |
36 | uint16_t devno; |
37 | uint8_t reserved4[4]; |
38 | uint64_t wwpn; |
39 | uint64_t lun; |
40 | uint32_t bootprog; |
41 | uint8_t reserved5[12]; |
42 | uint64_t br_lba; |
43 | uint32_t scp_data_len; |
44 | uint8_t reserved6[260]; |
45 | uint8_t scp_data[]; |
46 | } QEMU_PACKED; |
47 | typedef struct IplBlockFcp IplBlockFcp; |
48 | |
49 | struct IplBlockQemuScsi { |
50 | uint32_t lun; |
51 | uint16_t target; |
52 | uint16_t channel; |
53 | uint8_t reserved0[77]; |
54 | uint8_t ssid; |
55 | uint16_t devno; |
56 | } QEMU_PACKED; |
57 | typedef struct IplBlockQemuScsi IplBlockQemuScsi; |
58 | |
59 | #define DIAG308_FLAGS_LP_VALID 0x80 |
60 | |
61 | union IplParameterBlock { |
62 | struct { |
63 | uint32_t len; |
64 | uint8_t reserved0[3]; |
65 | uint8_t version; |
66 | uint32_t blk0_len; |
67 | uint8_t pbt; |
68 | uint8_t flags; |
69 | uint16_t reserved01; |
70 | uint8_t loadparm[8]; |
71 | union { |
72 | IplBlockCcw ccw; |
73 | IplBlockFcp fcp; |
74 | IplBlockQemuScsi scsi; |
75 | }; |
76 | } QEMU_PACKED; |
77 | struct { |
78 | uint8_t reserved1[110]; |
79 | uint16_t devno; |
80 | uint8_t reserved2[88]; |
81 | uint8_t reserved_ext[4096 - 200]; |
82 | } QEMU_PACKED; |
83 | } QEMU_PACKED; |
84 | typedef union IplParameterBlock IplParameterBlock; |
85 | |
86 | int s390_ipl_set_loadparm(uint8_t *loadparm); |
87 | void s390_ipl_update_diag308(IplParameterBlock *iplb); |
88 | void s390_ipl_prepare_cpu(S390CPU *cpu); |
89 | IplParameterBlock *s390_ipl_get_iplb(void); |
90 | |
91 | enum s390_reset { |
92 | /* default is a reset not triggered by a CPU e.g. issued by QMP */ |
93 | S390_RESET_EXTERNAL = 0, |
94 | S390_RESET_REIPL, |
95 | S390_RESET_MODIFIED_CLEAR, |
96 | S390_RESET_LOAD_NORMAL, |
97 | }; |
98 | void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type); |
99 | void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type); |
100 | void s390_ipl_clear_reset_request(void); |
101 | |
102 | #define QIPL_ADDRESS 0xcc |
103 | |
104 | /* Boot Menu flags */ |
105 | #define QIPL_FLAG_BM_OPTS_CMD 0x80 |
106 | #define QIPL_FLAG_BM_OPTS_ZIPL 0x40 |
107 | |
108 | /* |
109 | * The QEMU IPL Parameters will be stored at absolute address |
110 | * 204 (0xcc) which means it is 32-bit word aligned but not |
111 | * double-word aligned. |
112 | * Placement of data fields in this area must account for |
113 | * their alignment needs. E.g., netboot_start_address must |
114 | * have an offset of 4 + n * 8 bytes within the struct in order |
115 | * to keep it double-word aligned. |
116 | * The total size of the struct must never exceed 28 bytes. |
117 | * This definition must be kept in sync with the defininition |
118 | * in pc-bios/s390-ccw/iplb.h. |
119 | */ |
120 | struct QemuIplParameters { |
121 | uint8_t qipl_flags; |
122 | uint8_t reserved1[3]; |
123 | uint64_t netboot_start_addr; |
124 | uint32_t ; |
125 | uint8_t reserved2[12]; |
126 | } QEMU_PACKED; |
127 | typedef struct QemuIplParameters QemuIplParameters; |
128 | |
129 | #define TYPE_S390_IPL "s390-ipl" |
130 | #define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL) |
131 | |
132 | struct S390IPLState { |
133 | /*< private >*/ |
134 | DeviceState parent_obj; |
135 | IplParameterBlock iplb; |
136 | QemuIplParameters qipl; |
137 | uint64_t start_addr; |
138 | uint64_t compat_start_addr; |
139 | uint64_t bios_start_addr; |
140 | uint64_t compat_bios_start_addr; |
141 | bool enforce_bios; |
142 | bool iplb_valid; |
143 | bool netboot; |
144 | /* reset related properties don't have to be migrated or reset */ |
145 | enum s390_reset reset_type; |
146 | int reset_cpu_index; |
147 | |
148 | /*< public >*/ |
149 | char *kernel; |
150 | char *initrd; |
151 | char *cmdline; |
152 | char *firmware; |
153 | char *netboot_fw; |
154 | uint8_t cssid; |
155 | uint8_t ssid; |
156 | uint16_t devno; |
157 | bool iplbext_migration; |
158 | }; |
159 | typedef struct S390IPLState S390IPLState; |
160 | QEMU_BUILD_BUG_MSG(offsetof(S390IPLState, iplb) & 3, "alignment of iplb wrong" ); |
161 | |
162 | #define S390_IPL_TYPE_FCP 0x00 |
163 | #define S390_IPL_TYPE_CCW 0x02 |
164 | #define S390_IPL_TYPE_QEMU_SCSI 0xff |
165 | |
166 | #define 8 |
167 | #define S390_IPLB_MIN_CCW_LEN 200 |
168 | #define S390_IPLB_MIN_FCP_LEN 384 |
169 | #define S390_IPLB_MIN_QEMU_SCSI_LEN 200 |
170 | |
171 | static inline bool iplb_valid_len(IplParameterBlock *iplb) |
172 | { |
173 | return be32_to_cpu(iplb->len) <= sizeof(IplParameterBlock); |
174 | } |
175 | |
176 | static inline bool iplb_valid_ccw(IplParameterBlock *iplb) |
177 | { |
178 | return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_CCW_LEN && |
179 | iplb->pbt == S390_IPL_TYPE_CCW; |
180 | } |
181 | |
182 | static inline bool iplb_valid_fcp(IplParameterBlock *iplb) |
183 | { |
184 | return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_FCP_LEN && |
185 | iplb->pbt == S390_IPL_TYPE_FCP; |
186 | } |
187 | |
188 | #endif |
189 | |