2 * QEMU S390 bootmap interpreter
4 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
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
13 // #define DEBUG_FALLBACK
17 do { sclp_print("zipl: " txt); } while (0)
19 #define dputs(fmt, ...) \
23 struct scsi_blockptr
{
28 } __attribute__ ((packed
));
30 struct component_entry
{
31 struct scsi_blockptr data
;
33 uint8_t component_type
;
34 uint64_t load_address
;
35 } __attribute((packed
));
37 struct component_header
{
41 } __attribute((packed
));
47 struct scsi_blockptr blockptr
;
48 } __attribute__ ((packed
));
50 #define ZIPL_MAGIC "zIPL"
52 #define ZIPL_COMP_HEADER_IPL 0x00
53 #define ZIPL_COMP_HEADER_DUMP 0x01
55 #define ZIPL_COMP_ENTRY_LOAD 0x02
56 #define ZIPL_COMP_ENTRY_EXEC 0x01
59 static uint8_t sec
[SECTOR_SIZE
] __attribute__((__aligned__(SECTOR_SIZE
)));
61 typedef struct ResetInfo
{
64 uint32_t ipl_continue
;
69 static void jump_to_IPL_2(void)
71 ResetInfo
*current
= 0;
73 void (*ipl
)(void) = (void *) (uint64_t) current
->ipl_continue
;
74 debug_print_addr("set IPL addr to", ipl
);
76 /* Ensure the guest output starts fresh */
80 ipl(); /* should not return */
83 static void jump_to_IPL_code(uint64_t address
)
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.
90 ResetInfo
*current
= 0;
93 current
->ipl_addr
= (uint32_t) (uint64_t) &jump_to_IPL_2
;
94 current
->ipl_continue
= address
& 0x7fffffff;
98 * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2
99 * can then use r15 as its stack pointer.
101 asm volatile("lghi 1,1\n\t"
103 : : : "1", "memory");
104 virtio_panic("\n! IPL returns !\n");
107 /* Check for ZIPL magic. Returns 0 if not matched. */
108 static int zipl_magic(uint8_t *ptr
)
110 uint32_t *p
= (void*)ptr
;
111 uint32_t *z
= (void*)ZIPL_MAGIC
;
114 debug_print_int("invalid magic", *p
);
115 virtio_panic("invalid magic");
121 static int zipl_load_segment(struct component_entry
*entry
)
123 const int max_entries
= (SECTOR_SIZE
/ sizeof(struct scsi_blockptr
));
124 struct scsi_blockptr
*bprs
= (void*)sec
;
129 blockno
= entry
->data
.blockno
;
130 address
= entry
->load_address
;
132 debug_print_int("loading segment at block", blockno
);
133 debug_print_int("addr", address
);
136 if (virtio_read(blockno
, (uint8_t *)bprs
)) {
137 debug_print_int("failed reading bprs at", blockno
);
142 u64
*cur_desc
= (void*)&bprs
[i
];
144 blockno
= bprs
[i
].blockno
;
148 /* we need the updated blockno for the next indirect entry in the
149 chain, but don't want to advance address */
150 if (i
== (max_entries
- 1))
153 address
= virtio_load_direct(cur_desc
[0], cur_desc
[1], 0,
163 sclp_print("failed loading segment\n");
167 /* Run a zipl program */
168 static int zipl_run(struct scsi_blockptr
*pte
)
170 struct component_header
*header
;
171 struct component_entry
*entry
;
172 uint8_t tmp_sec
[SECTOR_SIZE
];
174 virtio_read(pte
->blockno
, tmp_sec
);
175 header
= (struct component_header
*)tmp_sec
;
177 if (!zipl_magic(tmp_sec
)) {
181 if (header
->type
!= ZIPL_COMP_HEADER_IPL
) {
185 dputs("start loading images\n");
187 /* Load image(s) into RAM */
188 entry
= (struct component_entry
*)(&header
[1]);
189 while (entry
->component_type
== ZIPL_COMP_ENTRY_LOAD
) {
190 if (zipl_load_segment(entry
) < 0) {
196 if ((uint8_t*)(&entry
[1]) > (tmp_sec
+ SECTOR_SIZE
)) {
201 if (entry
->component_type
!= ZIPL_COMP_ENTRY_EXEC
) {
205 /* should not return */
206 jump_to_IPL_code(entry
->load_address
);
211 sclp_print("failed running zipl\n");
217 struct mbr
*mbr
= (void*)sec
;
218 uint8_t *ns
, *ns_end
;
219 int program_table_entries
= 0;
220 int pte_len
= sizeof(struct scsi_blockptr
);
221 struct scsi_blockptr
*prog_table_entry
;
222 const char *error
= "";
225 virtio_read(0, (void*)mbr
);
227 dputs("checking magic\n");
229 if (!zipl_magic(mbr
->magic
)) {
230 error
= "zipl_magic 1";
234 debug_print_int("program table", mbr
->blockptr
.blockno
);
236 /* Parse the program table */
237 if (virtio_read(mbr
->blockptr
.blockno
, sec
)) {
238 error
= "virtio_read";
242 if (!zipl_magic(sec
)) {
243 error
= "zipl_magic 2";
247 ns_end
= sec
+ SECTOR_SIZE
;
248 for (ns
= (sec
+ pte_len
); (ns
+ pte_len
) < ns_end
; ns
++) {
249 prog_table_entry
= (struct scsi_blockptr
*)ns
;
250 if (!prog_table_entry
->blockno
) {
254 program_table_entries
++;
257 debug_print_int("program table entries", program_table_entries
);
259 if (!program_table_entries
) {
263 /* Run the default entry */
265 prog_table_entry
= (struct scsi_blockptr
*)(sec
+ pte_len
);
267 return zipl_run(prog_table_entry
);
270 sclp_print("failed loading zipl: ");