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 /* Check for ZIPL magic. Returns 0 if not matched. */
62 static int zipl_magic(uint8_t *ptr
)
64 uint32_t *p
= (void*)ptr
;
65 uint32_t *z
= (void*)ZIPL_MAGIC
;
68 debug_print_int("invalid magic", *p
);
69 virtio_panic("invalid magic");
75 static int zipl_load_segment(struct component_entry
*entry
)
77 const int max_entries
= (SECTOR_SIZE
/ sizeof(struct scsi_blockptr
));
78 struct scsi_blockptr
*bprs
= (void*)sec
;
83 blockno
= entry
->data
.blockno
;
84 address
= entry
->load_address
;
86 debug_print_int("loading segment at block", blockno
);
87 debug_print_int("addr", address
);
90 if (virtio_read(blockno
, (uint8_t *)bprs
)) {
91 debug_print_int("failed reading bprs at", blockno
);
96 u64
*cur_desc
= (void*)&bprs
[i
];
98 blockno
= bprs
[i
].blockno
;
102 /* we need the updated blockno for the next indirect entry in the
103 chain, but don't want to advance address */
104 if (i
== (max_entries
- 1))
107 address
= virtio_load_direct(cur_desc
[0], cur_desc
[1], 0,
117 sclp_print("failed loading segment\n");
121 /* Run a zipl program */
122 static int zipl_run(struct scsi_blockptr
*pte
)
124 struct component_header
*header
;
125 struct component_entry
*entry
;
127 uint8_t tmp_sec
[SECTOR_SIZE
];
129 virtio_read(pte
->blockno
, tmp_sec
);
130 header
= (struct component_header
*)tmp_sec
;
132 if (!zipl_magic(tmp_sec
)) {
136 if (header
->type
!= ZIPL_COMP_HEADER_IPL
) {
140 dputs("start loading images\n");
142 /* Load image(s) into RAM */
143 entry
= (struct component_entry
*)(&header
[1]);
144 while (entry
->component_type
== ZIPL_COMP_ENTRY_LOAD
) {
145 if (zipl_load_segment(entry
) < 0) {
151 if ((uint8_t*)(&entry
[1]) > (tmp_sec
+ SECTOR_SIZE
)) {
156 if (entry
->component_type
!= ZIPL_COMP_ENTRY_EXEC
) {
160 /* Ensure the guest output starts fresh */
163 /* And run the OS! */
164 ipl
= (void*)(entry
->load_address
& 0x7fffffff);
165 debug_print_addr("set IPL addr to", ipl
);
166 /* should not return */
172 sclp_print("failed running zipl\n");
178 struct mbr
*mbr
= (void*)sec
;
179 uint8_t *ns
, *ns_end
;
180 int program_table_entries
= 0;
181 int pte_len
= sizeof(struct scsi_blockptr
);
182 struct scsi_blockptr
*prog_table_entry
;
183 const char *error
= "";
186 virtio_read(0, (void*)mbr
);
188 dputs("checking magic\n");
190 if (!zipl_magic(mbr
->magic
)) {
191 error
= "zipl_magic 1";
195 debug_print_int("program table", mbr
->blockptr
.blockno
);
197 /* Parse the program table */
198 if (virtio_read(mbr
->blockptr
.blockno
, sec
)) {
199 error
= "virtio_read";
203 if (!zipl_magic(sec
)) {
204 error
= "zipl_magic 2";
208 ns_end
= sec
+ SECTOR_SIZE
;
209 for (ns
= (sec
+ pte_len
); (ns
+ pte_len
) < ns_end
; ns
++) {
210 prog_table_entry
= (struct scsi_blockptr
*)ns
;
211 if (!prog_table_entry
->blockno
) {
215 program_table_entries
++;
218 debug_print_int("program table entries", program_table_entries
);
220 if (!program_table_entries
) {
224 /* Run the default entry */
226 prog_table_entry
= (struct scsi_blockptr
*)(sec
+ pte_len
);
228 return zipl_run(prog_table_entry
);
231 sclp_print("failed loading zipl: ");