xref: /openbmc/qemu/pc-bios/s390-ccw/bootmap.c (revision 10358b6a)
1 /*
2  * QEMU S390 bootmap interpreter
3  *
4  * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or (at
7  * your option) any later version. See the COPYING file in the top-level
8  * directory.
9  */
10 
11 #include "s390-ccw.h"
12 
13 // #define DEBUG_FALLBACK
14 
15 #ifdef DEBUG_FALLBACK
16 #define dputs(txt) \
17     do { sclp_print("zipl: " txt); } while (0)
18 #else
19 #define dputs(fmt, ...) \
20     do { } while (0)
21 #endif
22 
23 struct scsi_blockptr {
24     uint64_t blockno;
25     uint16_t size;
26     uint16_t blockct;
27     uint8_t reserved[4];
28 } __attribute__ ((packed));
29 
30 struct component_entry {
31     struct scsi_blockptr data;
32     uint8_t pad[7];
33     uint8_t component_type;
34     uint64_t load_address;
35 } __attribute((packed));
36 
37 struct component_header {
38     uint8_t magic[4];
39     uint8_t type;
40     uint8_t reserved[27];
41 } __attribute((packed));
42 
43 struct mbr {
44     uint8_t magic[4];
45     uint32_t version_id;
46     uint8_t reserved[8];
47     struct scsi_blockptr blockptr;
48 } __attribute__ ((packed));
49 
50 #define ZIPL_MAGIC			"zIPL"
51 
52 #define ZIPL_COMP_HEADER_IPL		0x00
53 #define ZIPL_COMP_HEADER_DUMP		0x01
54 
55 #define ZIPL_COMP_ENTRY_LOAD		0x02
56 #define ZIPL_COMP_ENTRY_EXEC		0x01
57 
58 /* Scratch space */
59 static uint8_t sec[SECTOR_SIZE] __attribute__((__aligned__(SECTOR_SIZE)));
60 
61 typedef struct ResetInfo {
62     uint32_t ipl_mask;
63     uint32_t ipl_addr;
64     uint32_t ipl_continue;
65 } ResetInfo;
66 
67 ResetInfo save;
68 
69 static void jump_to_IPL_2(void)
70 {
71     ResetInfo *current = 0;
72 
73     void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
74     debug_print_addr("set IPL addr to", ipl);
75 
76     /* Ensure the guest output starts fresh */
77     sclp_print("\n");
78 
79     *current = save;
80     ipl(); /* should not return */
81 }
82 
83 static void jump_to_IPL_code(uint64_t address)
84 {
85     /*
86      * The IPL PSW is at address 0. We also must not overwrite the
87      * content of non-BIOS memory after we loaded the guest, so we
88      * save the original content and restore it in jump_to_IPL_2.
89      */
90     ResetInfo *current = 0;
91 
92     save = *current;
93     current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
94     current->ipl_continue = address & 0x7fffffff;
95 
96     /*
97      * HACK ALERT.
98      * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
99      * can then use r15 as its stack pointer.
100      */
101     asm volatile("lghi 1,1\n\t"
102                  "diag 1,1,0x308\n\t"
103                  : : : "1", "memory");
104     virtio_panic("\n! IPL returns !\n");
105 }
106 
107 /* Check for ZIPL magic. Returns 0 if not matched. */
108 static int zipl_magic(uint8_t *ptr)
109 {
110     uint32_t *p = (void*)ptr;
111     uint32_t *z = (void*)ZIPL_MAGIC;
112 
113     if (*p != *z) {
114         debug_print_int("invalid magic", *p);
115         virtio_panic("invalid magic");
116     }
117 
118     return 1;
119 }
120 
121 #define FREE_SPACE_FILLER '\xAA'
122 
123 static inline bool unused_space(const void *p, unsigned int size)
124 {
125     int i;
126     const unsigned char *m = p;
127 
128     for (i = 0; i < size; i++) {
129         if (m[i] != FREE_SPACE_FILLER) {
130             return false;
131         }
132     }
133     return true;
134 }
135 
136 static int zipl_load_segment(struct component_entry *entry)
137 {
138     const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr));
139     struct scsi_blockptr *bprs = (void*)sec;
140     const int bprs_size = sizeof(sec);
141     uint64_t blockno;
142     long address;
143     int i;
144 
145     blockno = entry->data.blockno;
146     address = entry->load_address;
147 
148     debug_print_int("loading segment at block", blockno);
149     debug_print_int("addr", address);
150 
151     do {
152         memset(bprs, FREE_SPACE_FILLER, bprs_size);
153         if (virtio_read(blockno, (uint8_t *)bprs)) {
154             debug_print_int("failed reading bprs at", blockno);
155             goto fail;
156         }
157 
158         for (i = 0;; i++) {
159             u64 *cur_desc = (void*)&bprs[i];
160 
161             blockno = bprs[i].blockno;
162             if (!blockno)
163                 break;
164 
165             /* we need the updated blockno for the next indirect entry in the
166                chain, but don't want to advance address */
167             if (i == (max_entries - 1))
168                 break;
169 
170             if (bprs[i].blockct == 0 && unused_space(&bprs[i + 1],
171                 sizeof(struct scsi_blockptr))) {
172                 /* This is a "continue" pointer.
173                  * This ptr is the last one in the current script section.
174                  * I.e. the next ptr must point to the unused memory area.
175                  * The blockno is not zero, so the upper loop must continue
176                  * reading next section of BPRS.
177                  */
178                 break;
179             }
180             address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
181                                          (void*)address);
182             if (address == -1)
183                 goto fail;
184         }
185     } while (blockno);
186 
187     return 0;
188 
189 fail:
190     sclp_print("failed loading segment\n");
191     return -1;
192 }
193 
194 /* Run a zipl program */
195 static int zipl_run(struct scsi_blockptr *pte)
196 {
197     struct component_header *header;
198     struct component_entry *entry;
199     uint8_t tmp_sec[SECTOR_SIZE];
200 
201     virtio_read(pte->blockno, tmp_sec);
202     header = (struct component_header *)tmp_sec;
203 
204     if (!zipl_magic(tmp_sec)) {
205         goto fail;
206     }
207 
208     if (header->type != ZIPL_COMP_HEADER_IPL) {
209         goto fail;
210     }
211 
212     dputs("start loading images\n");
213 
214     /* Load image(s) into RAM */
215     entry = (struct component_entry *)(&header[1]);
216     while (entry->component_type == ZIPL_COMP_ENTRY_LOAD) {
217         if (zipl_load_segment(entry) < 0) {
218             goto fail;
219         }
220 
221         entry++;
222 
223         if ((uint8_t*)(&entry[1]) > (tmp_sec + SECTOR_SIZE)) {
224             goto fail;
225         }
226     }
227 
228     if (entry->component_type != ZIPL_COMP_ENTRY_EXEC) {
229         goto fail;
230     }
231 
232     /* should not return */
233     jump_to_IPL_code(entry->load_address);
234 
235     return 0;
236 
237 fail:
238     sclp_print("failed running zipl\n");
239     return -1;
240 }
241 
242 int zipl_load(void)
243 {
244     struct mbr *mbr = (void*)sec;
245     uint8_t *ns, *ns_end;
246     int program_table_entries = 0;
247     int pte_len = sizeof(struct scsi_blockptr);
248     struct scsi_blockptr *prog_table_entry;
249     const char *error = "";
250 
251     /* Grab the MBR */
252     virtio_read(0, (void*)mbr);
253 
254     dputs("checking magic\n");
255 
256     if (!zipl_magic(mbr->magic)) {
257         error = "zipl_magic 1";
258         goto fail;
259     }
260 
261     debug_print_int("program table", mbr->blockptr.blockno);
262 
263     /* Parse the program table */
264     if (virtio_read(mbr->blockptr.blockno, sec)) {
265         error = "virtio_read";
266         goto fail;
267     }
268 
269     if (!zipl_magic(sec)) {
270         error = "zipl_magic 2";
271         goto fail;
272     }
273 
274     ns_end = sec + SECTOR_SIZE;
275     for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns++) {
276         prog_table_entry = (struct scsi_blockptr *)ns;
277         if (!prog_table_entry->blockno) {
278             break;
279         }
280 
281         program_table_entries++;
282     }
283 
284     debug_print_int("program table entries", program_table_entries);
285 
286     if (!program_table_entries) {
287         goto fail;
288     }
289 
290     /* Run the default entry */
291 
292     prog_table_entry = (struct scsi_blockptr *)(sec + pte_len);
293 
294     return zipl_run(prog_table_entry);
295 
296 fail:
297     sclp_print("failed loading zipl: ");
298     sclp_print(error);
299     sclp_print("\n");
300     return -1;
301 }
302