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