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 /* Check for ZIPL magic. Returns 0 if not matched. */ 62 static int zipl_magic(uint8_t *ptr) 63 { 64 uint32_t *p = (void*)ptr; 65 uint32_t *z = (void*)ZIPL_MAGIC; 66 67 if (*p != *z) { 68 debug_print_int("invalid magic", *p); 69 virtio_panic("invalid magic"); 70 } 71 72 return 1; 73 } 74 75 static int zipl_load_segment(struct component_entry *entry) 76 { 77 const int max_entries = (SECTOR_SIZE / sizeof(struct scsi_blockptr)); 78 struct scsi_blockptr *bprs = (void*)sec; 79 uint64_t blockno; 80 long address; 81 int i; 82 83 blockno = entry->data.blockno; 84 address = entry->load_address; 85 86 debug_print_int("loading segment at block", blockno); 87 debug_print_int("addr", address); 88 89 do { 90 if (virtio_read(blockno, (uint8_t *)bprs)) { 91 debug_print_int("failed reading bprs at", blockno); 92 goto fail; 93 } 94 95 for (i = 0;; i++) { 96 u64 *cur_desc = (void*)&bprs[i]; 97 98 blockno = bprs[i].blockno; 99 if (!blockno) 100 break; 101 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)) 105 break; 106 107 address = virtio_load_direct(cur_desc[0], cur_desc[1], 0, 108 (void*)address); 109 if (address == -1) 110 goto fail; 111 } 112 } while (blockno); 113 114 return 0; 115 116 fail: 117 sclp_print("failed loading segment\n"); 118 return -1; 119 } 120 121 /* Run a zipl program */ 122 static int zipl_run(struct scsi_blockptr *pte) 123 { 124 struct component_header *header; 125 struct component_entry *entry; 126 void (*ipl)(void); 127 uint8_t tmp_sec[SECTOR_SIZE]; 128 129 virtio_read(pte->blockno, tmp_sec); 130 header = (struct component_header *)tmp_sec; 131 132 if (!zipl_magic(tmp_sec)) { 133 goto fail; 134 } 135 136 if (header->type != ZIPL_COMP_HEADER_IPL) { 137 goto fail; 138 } 139 140 dputs("start loading images\n"); 141 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) { 146 goto fail; 147 } 148 149 entry++; 150 151 if ((uint8_t*)(&entry[1]) > (tmp_sec + SECTOR_SIZE)) { 152 goto fail; 153 } 154 } 155 156 if (entry->component_type != ZIPL_COMP_ENTRY_EXEC) { 157 goto fail; 158 } 159 160 /* Ensure the guest output starts fresh */ 161 sclp_print("\n"); 162 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 */ 167 ipl(); 168 169 return 0; 170 171 fail: 172 sclp_print("failed running zipl\n"); 173 return -1; 174 } 175 176 int zipl_load(void) 177 { 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 = ""; 184 185 /* Grab the MBR */ 186 virtio_read(0, (void*)mbr); 187 188 dputs("checking magic\n"); 189 190 if (!zipl_magic(mbr->magic)) { 191 error = "zipl_magic 1"; 192 goto fail; 193 } 194 195 debug_print_int("program table", mbr->blockptr.blockno); 196 197 /* Parse the program table */ 198 if (virtio_read(mbr->blockptr.blockno, sec)) { 199 error = "virtio_read"; 200 goto fail; 201 } 202 203 if (!zipl_magic(sec)) { 204 error = "zipl_magic 2"; 205 goto fail; 206 } 207 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) { 212 break; 213 } 214 215 program_table_entries++; 216 } 217 218 debug_print_int("program table entries", program_table_entries); 219 220 if (!program_table_entries) { 221 goto fail; 222 } 223 224 /* Run the default entry */ 225 226 prog_table_entry = (struct scsi_blockptr *)(sec + pte_len); 227 228 return zipl_run(prog_table_entry); 229 230 fail: 231 sclp_print("failed loading zipl: "); 232 sclp_print(error); 233 sclp_print("\n"); 234 return -1; 235 } 236