2 * QEMU S390 bootmap interpreter
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
15 /* #define DEBUG_FALLBACK */
19 do { sclp_print("zipl: " txt); } while (0)
21 #define dputs(fmt, ...) \
26 static uint8_t sec[MAX_SECTOR_SIZE]
27 __attribute__((__aligned__(MAX_SECTOR_SIZE)));
29 typedef struct ResetInfo {
32 uint32_t ipl_continue;
37 static void jump_to_IPL_2(void)
39 ResetInfo *current = 0;
41 void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue;
42 debug_print_addr("set IPL addr to", ipl);
44 /* Ensure the guest output starts fresh */
48 ipl(); /* should not return */
51 static void jump_to_IPL_code(uint64_t address)
54 * The IPL PSW is at address 0. We also must not overwrite the
55 * content of non-BIOS memory after we loaded the guest, so we
56 * save the original content and restore it in jump_to_IPL_2.
58 ResetInfo *current = 0;
61 current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2;
62 current->ipl_continue = address & 0x7fffffff;
66 * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
67 * can then use r15 as its stack pointer.
69 asm volatile("lghi 1,1\n\t"
72 virtio_panic("\n! IPL returns !\n");
75 /* Check for ZIPL magic. Returns 0 if not matched. */
76 static int zipl_magic(uint8_t *ptr)
78 uint32_t *p = (void *)ptr;
79 uint32_t *z = (void *)ZIPL_MAGIC;
82 debug_print_int("invalid magic", *p);
83 virtio_panic("invalid magic");
89 static int zipl_load_segment(ComponentEntry *entry)
91 const int max_entries = (MAX_SECTOR_SIZE / sizeof(ScsiBlockPtr));
92 ScsiBlockPtr *bprs = (void *)sec;
93 const int bprs_size = sizeof(sec);
94 block_number_t blockno;
98 blockno = entry->data.blockno;
99 address = entry->load_address;
101 debug_print_int("loading segment at block", blockno);
102 debug_print_int("addr", address);
105 memset(bprs, FREE_SPACE_FILLER, bprs_size);
106 if (virtio_read(blockno, (uint8_t *)bprs)) {
107 debug_print_int("failed reading bprs at", blockno);
112 u64 *cur_desc = (void *)&bprs[i];
114 blockno = bprs[i].blockno;
119 /* we need the updated blockno for the next indirect entry in the
120 chain, but don't want to advance address */
121 if (i == (max_entries - 1)) {
125 if (bprs[i].blockct == 0 && unused_space(&bprs[i + 1],
126 sizeof(ScsiBlockPtr))) {
127 /* This is a "continue" pointer.
128 * This ptr is the last one in the current script section.
129 * I.e. the next ptr must point to the unused memory area.
130 * The blockno is not zero, so the upper loop must continue
131 * reading next section of BPRS.
135 address = virtio_load_direct(cur_desc[0], cur_desc[1], 0,
146 sclp_print("failed loading segment\n");
150 /* Run a zipl program */
151 static int zipl_run(ScsiBlockPtr *pte)
153 ComponentHeader *header;
154 ComponentEntry *entry;
155 uint8_t tmp_sec[MAX_SECTOR_SIZE];
157 virtio_read(pte->blockno, tmp_sec);
158 header = (ComponentHeader *)tmp_sec;
160 if (!zipl_magic(tmp_sec)) {
164 if (header->type != ZIPL_COMP_HEADER_IPL) {
168 dputs("start loading images\n");
170 /* Load image(s) into RAM */
171 entry = (ComponentEntry *)(&header[1]);
172 while (entry->component_type == ZIPL_COMP_ENTRY_LOAD) {
173 if (zipl_load_segment(entry) < 0) {
179 if ((uint8_t *)(&entry[1]) > (tmp_sec + MAX_SECTOR_SIZE)) {
184 if (entry->component_type != ZIPL_COMP_ENTRY_EXEC) {
188 /* should not return */
189 jump_to_IPL_code(entry->load_address);
194 sclp_print("failed running zipl\n");
200 ScsiMbr *mbr = (void *)sec;
201 uint8_t *ns, *ns_end;
202 int program_table_entries = 0;
203 const int pte_len = sizeof(ScsiBlockPtr);
204 ScsiBlockPtr *prog_table_entry;
205 const char *error = "";
208 virtio_read(0, (void *)mbr);
210 dputs("checking magic\n");
212 if (!zipl_magic(mbr->magic)) {
213 error = "zipl_magic 1";
217 debug_print_int("program table", mbr->blockptr.blockno);
219 /* Parse the program table */
220 if (virtio_read(mbr->blockptr.blockno, sec)) {
221 error = "virtio_read";
225 if (!zipl_magic(sec)) {
226 error = "zipl_magic 2";
230 ns_end = sec + virtio_get_block_size();
231 for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns++) {
232 prog_table_entry = (ScsiBlockPtr *)ns;
233 if (!prog_table_entry->blockno) {
237 program_table_entries++;
240 debug_print_int("program table entries", program_table_entries);
242 if (!program_table_entries) {
246 /* Run the default entry */
248 prog_table_entry = (ScsiBlockPtr *)(sec + pte_len);
250 return zipl_run(prog_table_entry);
253 sclp_print("failed loading zipl: ");