1 /* 2 * S390 virtio-ccw loading program 3 * 4 * Copyright (c) 2013 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 "libc.h" 12 #include "helper.h" 13 #include "s390-arch.h" 14 #include "s390-ccw.h" 15 #include "cio.h" 16 #include "virtio.h" 17 #include "virtio-scsi.h" 18 #include "dasd-ipl.h" 19 20 char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); 21 static SubChannelId blk_schid = { .one = 1 }; 22 static char loadparm_str[LOADPARM_LEN + 1]; 23 QemuIplParameters qipl; 24 IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); 25 static bool have_iplb; 26 static uint16_t cutype; 27 LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ 28 29 #define LOADPARM_PROMPT "PROMPT " 30 #define LOADPARM_EMPTY " " 31 #define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL) 32 33 /* 34 * Principles of Operations (SA22-7832-09) chapter 17 requires that 35 * a subsystem-identification is at 184-187 and bytes 188-191 are zero 36 * after list-directed-IPL and ccw-IPL. 37 */ 38 void write_subsystem_identification(void) 39 { 40 lowcore->subchannel_id = blk_schid.sch_id; 41 lowcore->subchannel_nr = blk_schid.sch_no; 42 lowcore->io_int_parm = 0; 43 } 44 45 void write_iplb_location(void) 46 { 47 if (cutype == CU_TYPE_VIRTIO && virtio_get_device_type() != VIRTIO_ID_NET) { 48 lowcore->ptr_iplb = ptr2u32(&iplb); 49 } 50 } 51 52 unsigned int get_loadparm_index(void) 53 { 54 return atoui(loadparm_str); 55 } 56 57 static int is_dev_possibly_bootable(int dev_no, int sch_no) 58 { 59 bool is_virtio; 60 Schib schib; 61 int r; 62 63 blk_schid.sch_no = sch_no; 64 r = stsch_err(blk_schid, &schib); 65 if (r == 3 || r == -EIO) { 66 return -ENODEV; 67 } 68 if (!schib.pmcw.dnv) { 69 return false; 70 } 71 72 enable_subchannel(blk_schid); 73 cutype = cu_type(blk_schid); 74 75 /* 76 * Note: we always have to run virtio_is_supported() here to make 77 * sure that the vdev.senseid data gets pre-initialized correctly 78 */ 79 is_virtio = virtio_is_supported(blk_schid); 80 81 /* No specific devno given, just return whether the device is possibly bootable */ 82 if (dev_no < 0) { 83 switch (cutype) { 84 case CU_TYPE_VIRTIO: 85 if (is_virtio) { 86 /* 87 * Skip net devices since no IPLB is created and therefore 88 * no network bootloader has been loaded 89 */ 90 if (virtio_get_device_type() != VIRTIO_ID_NET) { 91 return true; 92 } 93 } 94 return false; 95 case CU_TYPE_DASD_3990: 96 case CU_TYPE_DASD_2107: 97 return true; 98 default: 99 return false; 100 } 101 } 102 103 /* Caller asked for a specific devno */ 104 if (schib.pmcw.dev == dev_no) { 105 return true; 106 } 107 108 return false; 109 } 110 111 /* 112 * Find the subchannel connected to the given device (dev_no) and fill in the 113 * subchannel information block (schib) with the connected subchannel's info. 114 * NOTE: The global variable blk_schid is updated to contain the subchannel 115 * information. 116 * 117 * If the caller gives dev_no=-1 then the user did not specify a boot device. 118 * In this case we'll just use the first potentially bootable device we find. 119 */ 120 static bool find_subch(int dev_no) 121 { 122 int i, r; 123 124 for (i = 0; i < 0x10000; i++) { 125 r = is_dev_possibly_bootable(dev_no, i); 126 if (r < 0) { 127 break; 128 } 129 if (r == true) { 130 return true; 131 } 132 } 133 134 return false; 135 } 136 137 static void menu_setup(void) 138 { 139 if (memcmp(loadparm_str, LOADPARM_PROMPT, LOADPARM_LEN) == 0) { 140 menu_set_parms(QIPL_FLAG_BM_OPTS_CMD, 0); 141 return; 142 } 143 144 /* If loadparm was set to any other value, then do not enable menu */ 145 if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { 146 return; 147 } 148 149 switch (iplb.pbt) { 150 case S390_IPL_TYPE_CCW: 151 case S390_IPL_TYPE_QEMU_SCSI: 152 menu_set_parms(qipl.qipl_flags & BOOT_MENU_FLAG_MASK, 153 qipl.boot_menu_timeout); 154 return; 155 } 156 } 157 158 /* 159 * Initialize the channel I/O subsystem so we can talk to our ipl/boot device. 160 */ 161 static void css_setup(void) 162 { 163 /* 164 * Unconditionally enable mss support. In every sane configuration this 165 * will succeed; and even if it doesn't, stsch_err() can handle it. 166 */ 167 enable_mss_facility(); 168 } 169 170 /* 171 * Collect various pieces of information from the hypervisor/hardware that 172 * we'll use to determine exactly how we'll boot. 173 */ 174 static void boot_setup(void) 175 { 176 char lpmsg[] = "LOADPARM=[________]\n"; 177 178 sclp_get_loadparm_ascii(loadparm_str); 179 memcpy(lpmsg + 10, loadparm_str, 8); 180 sclp_print(lpmsg); 181 182 /* 183 * Clear out any potential S390EP magic (see jump_to_low_kernel()), 184 * so we don't taint our decision-making process during a reboot. 185 */ 186 memset((char *)S390EP, 0, 6); 187 188 have_iplb = store_iplb(&iplb); 189 } 190 191 static void find_boot_device(void) 192 { 193 VDev *vdev = virtio_get_device(); 194 bool found; 195 196 switch (iplb.pbt) { 197 case S390_IPL_TYPE_CCW: 198 debug_print_int("device no. ", iplb.ccw.devno); 199 blk_schid.ssid = iplb.ccw.ssid & 0x3; 200 debug_print_int("ssid ", blk_schid.ssid); 201 found = find_subch(iplb.ccw.devno); 202 break; 203 case S390_IPL_TYPE_QEMU_SCSI: 204 vdev->scsi_device_selected = true; 205 vdev->selected_scsi_device.channel = iplb.scsi.channel; 206 vdev->selected_scsi_device.target = iplb.scsi.target; 207 vdev->selected_scsi_device.lun = iplb.scsi.lun; 208 blk_schid.ssid = iplb.scsi.ssid & 0x3; 209 found = find_subch(iplb.scsi.devno); 210 break; 211 default: 212 panic("List-directed IPL not supported yet!\n"); 213 } 214 215 IPL_assert(found, "Boot device not found\n"); 216 } 217 218 static int virtio_setup(void) 219 { 220 VDev *vdev = virtio_get_device(); 221 QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; 222 int ret; 223 224 memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); 225 226 if (have_iplb) { 227 menu_setup(); 228 } 229 230 switch (vdev->senseid.cu_model) { 231 case VIRTIO_ID_NET: 232 sclp_print("Network boot device detected\n"); 233 vdev->netboot_start_addr = qipl.netboot_start_addr; 234 return 0; 235 case VIRTIO_ID_BLOCK: 236 ret = virtio_blk_setup_device(blk_schid); 237 break; 238 case VIRTIO_ID_SCSI: 239 ret = virtio_scsi_setup_device(blk_schid); 240 break; 241 default: 242 panic("\n! No IPL device available !\n"); 243 } 244 245 if (!ret) { 246 IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); 247 } 248 249 return ret; 250 } 251 252 static void ipl_boot_device(void) 253 { 254 switch (cutype) { 255 case CU_TYPE_DASD_3990: 256 case CU_TYPE_DASD_2107: 257 dasd_ipl(blk_schid, cutype); /* no return */ 258 break; 259 case CU_TYPE_VIRTIO: 260 if (virtio_setup() == 0) { 261 zipl_load(); /* Only returns in case of errors */ 262 } 263 break; 264 default: 265 print_int("Attempting to boot from unexpected device type", cutype); 266 panic("\nBoot failed.\n"); 267 } 268 } 269 270 /* 271 * No boot device has been specified, so we have to scan through the 272 * channels to find one. 273 */ 274 static void probe_boot_device(void) 275 { 276 int ssid, sch_no, ret; 277 278 for (ssid = 0; ssid < 0x3; ssid++) { 279 blk_schid.ssid = ssid; 280 for (sch_no = 0; sch_no < 0x10000; sch_no++) { 281 ret = is_dev_possibly_bootable(-1, sch_no); 282 if (ret < 0) { 283 break; 284 } 285 if (ret == true) { 286 ipl_boot_device(); /* Only returns if unsuccessful */ 287 } 288 } 289 } 290 291 sclp_print("Could not find a suitable boot device (none specified)\n"); 292 } 293 294 void main(void) 295 { 296 sclp_setup(); 297 css_setup(); 298 boot_setup(); 299 if (have_iplb) { 300 find_boot_device(); 301 ipl_boot_device(); 302 } else { 303 probe_boot_device(); 304 } 305 306 panic("Failed to load OS from hard disk\n"); 307 } 308