Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 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 | |
Thomas Huth | 90806fe | 2017-07-12 14:49:43 +0200 | [diff] [blame] | 11 | #include "libc.h" |
Jason J. Herne | c95df3d | 2019-04-04 10:34:25 -0400 | [diff] [blame^] | 12 | #include "s390-arch.h" |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 13 | #include "s390-ccw.h" |
Jason J. Herne | 120d041 | 2019-04-04 10:34:24 -0400 | [diff] [blame] | 14 | #include "cio.h" |
Eugene (jno) Dvurechenski | 60612d5 | 2014-05-19 20:11:07 +0200 | [diff] [blame] | 15 | #include "virtio.h" |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 16 | |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 17 | char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); |
Eugene (jno) Dvurechenski | b88d7fa | 2015-11-10 14:10:20 +0100 | [diff] [blame] | 18 | static SubChannelId blk_schid = { .one = 1 }; |
Collin Walling | a0e11b6 | 2018-05-29 00:40:09 -0400 | [diff] [blame] | 19 | static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; |
Collin L. Walling | 118ee80 | 2018-02-23 10:43:11 -0500 | [diff] [blame] | 20 | QemuIplParameters qipl; |
Jason J. Herne | a5f6e09 | 2019-04-04 10:34:22 -0400 | [diff] [blame] | 21 | IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); |
| 22 | static bool have_iplb; |
Jason J. Herne | c95df3d | 2019-04-04 10:34:25 -0400 | [diff] [blame^] | 23 | LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */ |
Christian Borntraeger | f2879a5 | 2014-07-01 12:17:41 +0200 | [diff] [blame] | 24 | |
Collin L. Walling | 9eaa654 | 2018-02-23 10:43:13 -0500 | [diff] [blame] | 25 | #define LOADPARM_PROMPT "PROMPT " |
Collin Walling | 074afe6 | 2018-04-16 12:56:08 -0400 | [diff] [blame] | 26 | #define LOADPARM_EMPTY " " |
Collin L. Walling | 53b310c | 2018-02-23 10:43:18 -0500 | [diff] [blame] | 27 | #define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL) |
Collin L. Walling | 9eaa654 | 2018-02-23 10:43:13 -0500 | [diff] [blame] | 28 | |
Christian Borntraeger | f2879a5 | 2014-07-01 12:17:41 +0200 | [diff] [blame] | 29 | /* |
Jason J. Herne | a5f6e09 | 2019-04-04 10:34:22 -0400 | [diff] [blame] | 30 | * Principles of Operations (SA22-7832-09) chapter 17 requires that |
Christian Borntraeger | f2879a5 | 2014-07-01 12:17:41 +0200 | [diff] [blame] | 31 | * a subsystem-identification is at 184-187 and bytes 188-191 are zero |
| 32 | * after list-directed-IPL and ccw-IPL. |
| 33 | */ |
| 34 | void write_subsystem_identification(void) |
| 35 | { |
Eugene (jno) Dvurechenski | b88d7fa | 2015-11-10 14:10:20 +0100 | [diff] [blame] | 36 | SubChannelId *schid = (SubChannelId *) 184; |
Christian Borntraeger | f2879a5 | 2014-07-01 12:17:41 +0200 | [diff] [blame] | 37 | uint32_t *zeroes = (uint32_t *) 188; |
| 38 | |
| 39 | *schid = blk_schid; |
| 40 | *zeroes = 0; |
| 41 | } |
| 42 | |
Eugene (jno) Dvurechenski | c9262e8 | 2015-09-17 12:47:27 +0200 | [diff] [blame] | 43 | void panic(const char *string) |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 44 | { |
| 45 | sclp_print(string); |
Christian Borntraeger | 7f61cbc | 2013-04-23 01:23:02 +0000 | [diff] [blame] | 46 | disabled_wait(); |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 47 | while (1) { } |
| 48 | } |
| 49 | |
Farhan Ali | 95fa1af | 2017-01-16 10:45:49 -0500 | [diff] [blame] | 50 | unsigned int get_loadparm_index(void) |
| 51 | { |
Collin Walling | 074afe6 | 2018-04-16 12:56:08 -0400 | [diff] [blame] | 52 | return atoui(loadparm_str); |
Farhan Ali | 95fa1af | 2017-01-16 10:45:49 -0500 | [diff] [blame] | 53 | } |
| 54 | |
Eugene (jno) Dvurechenski | b88d7fa | 2015-11-10 14:10:20 +0100 | [diff] [blame] | 55 | static bool find_dev(Schib *schib, int dev_no) |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 56 | { |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 57 | int i, r; |
Dominik Dingel | ff151f4 | 2013-04-30 07:15:58 +0000 | [diff] [blame] | 58 | |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 59 | for (i = 0; i < 0x10000; i++) { |
| 60 | blk_schid.sch_no = i; |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 61 | r = stsch_err(blk_schid, schib); |
| 62 | if ((r == 3) || (r == -EIO)) { |
Cornelia Huck | 22d67ab | 2013-04-26 02:12:52 +0000 | [diff] [blame] | 63 | break; |
| 64 | } |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 65 | if (!schib->pmcw.dnv) { |
| 66 | continue; |
| 67 | } |
Eugene (jno) Dvurechenski | a1102ce | 2015-10-26 16:55:16 +0100 | [diff] [blame] | 68 | if (!virtio_is_supported(blk_schid)) { |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 69 | continue; |
| 70 | } |
Farhan Ali | 99b72e0 | 2016-11-01 17:34:00 -0400 | [diff] [blame] | 71 | /* Skip net devices since no IPLB is created and therefore no |
| 72 | * no network bootloader has been loaded |
| 73 | */ |
| 74 | if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { |
| 75 | continue; |
| 76 | } |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 77 | if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) { |
| 78 | return true; |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | return false; |
| 83 | } |
| 84 | |
Collin L. Walling | 9eaa654 | 2018-02-23 10:43:13 -0500 | [diff] [blame] | 85 | static void menu_setup(void) |
| 86 | { |
Collin Walling | a0e11b6 | 2018-05-29 00:40:09 -0400 | [diff] [blame] | 87 | if (memcmp(loadparm_str, LOADPARM_PROMPT, LOADPARM_LEN) == 0) { |
Collin L. Walling | 9eaa654 | 2018-02-23 10:43:13 -0500 | [diff] [blame] | 88 | menu_set_parms(QIPL_FLAG_BM_OPTS_CMD, 0); |
| 89 | return; |
| 90 | } |
| 91 | |
| 92 | /* If loadparm was set to any other value, then do not enable menu */ |
Collin Walling | a0e11b6 | 2018-05-29 00:40:09 -0400 | [diff] [blame] | 93 | if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { |
Collin L. Walling | 9eaa654 | 2018-02-23 10:43:13 -0500 | [diff] [blame] | 94 | return; |
| 95 | } |
| 96 | |
| 97 | switch (iplb.pbt) { |
| 98 | case S390_IPL_TYPE_CCW: |
Collin L. Walling | ffb4a1c | 2018-02-23 10:43:19 -0500 | [diff] [blame] | 99 | case S390_IPL_TYPE_QEMU_SCSI: |
Collin L. Walling | 53b310c | 2018-02-23 10:43:18 -0500 | [diff] [blame] | 100 | menu_set_parms(qipl.qipl_flags & BOOT_MENU_FLAG_MASK, |
Collin L. Walling | 9eaa654 | 2018-02-23 10:43:13 -0500 | [diff] [blame] | 101 | qipl.boot_menu_timeout); |
| 102 | return; |
| 103 | } |
| 104 | } |
| 105 | |
Jason J. Herne | 87f910c | 2019-04-04 10:34:21 -0400 | [diff] [blame] | 106 | /* |
| 107 | * Initialize the channel I/O subsystem so we can talk to our ipl/boot device. |
| 108 | */ |
| 109 | static void css_setup(void) |
| 110 | { |
| 111 | /* |
| 112 | * Unconditionally enable mss support. In every sane configuration this |
| 113 | * will succeed; and even if it doesn't, stsch_err() can handle it. |
| 114 | */ |
| 115 | enable_mss_facility(); |
| 116 | } |
| 117 | |
Jason J. Herne | a5f6e09 | 2019-04-04 10:34:22 -0400 | [diff] [blame] | 118 | /* |
| 119 | * Collect various pieces of information from the hypervisor/hardware that |
| 120 | * we'll use to determine exactly how we'll boot. |
| 121 | */ |
| 122 | static void boot_setup(void) |
| 123 | { |
| 124 | char lpmsg[] = "LOADPARM=[________]\n"; |
| 125 | |
| 126 | sclp_get_loadparm_ascii(loadparm_str); |
| 127 | memcpy(lpmsg + 10, loadparm_str, 8); |
| 128 | sclp_print(lpmsg); |
| 129 | |
| 130 | have_iplb = store_iplb(&iplb); |
| 131 | } |
| 132 | |
Alexander Yarygin | d046c51 | 2015-07-31 17:04:51 +0300 | [diff] [blame] | 133 | static void virtio_setup(void) |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 134 | { |
Eugene (jno) Dvurechenski | b88d7fa | 2015-11-10 14:10:20 +0100 | [diff] [blame] | 135 | Schib schib; |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 136 | int ssid; |
| 137 | bool found = false; |
| 138 | uint16_t dev_no; |
Farhan Ali | 99b72e0 | 2016-11-01 17:34:00 -0400 | [diff] [blame] | 139 | VDev *vdev = virtio_get_device(); |
Collin L. Walling | 118ee80 | 2018-02-23 10:43:11 -0500 | [diff] [blame] | 140 | QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 141 | |
Collin L. Walling | 118ee80 | 2018-02-23 10:43:11 -0500 | [diff] [blame] | 142 | memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); |
| 143 | |
Jason J. Herne | a5f6e09 | 2019-04-04 10:34:22 -0400 | [diff] [blame] | 144 | if (have_iplb) { |
Alexander Yarygin | d046c51 | 2015-07-31 17:04:51 +0300 | [diff] [blame] | 145 | switch (iplb.pbt) { |
| 146 | case S390_IPL_TYPE_CCW: |
| 147 | dev_no = iplb.ccw.devno; |
| 148 | debug_print_int("device no. ", dev_no); |
| 149 | blk_schid.ssid = iplb.ccw.ssid & 0x3; |
| 150 | debug_print_int("ssid ", blk_schid.ssid); |
| 151 | found = find_dev(&schib, dev_no); |
| 152 | break; |
Eugene (jno) Dvurechenski | b39b771 | 2016-06-01 15:25:51 +0200 | [diff] [blame] | 153 | case S390_IPL_TYPE_QEMU_SCSI: |
Eugene (jno) Dvurechenski | b39b771 | 2016-06-01 15:25:51 +0200 | [diff] [blame] | 154 | vdev->scsi_device_selected = true; |
| 155 | vdev->selected_scsi_device.channel = iplb.scsi.channel; |
| 156 | vdev->selected_scsi_device.target = iplb.scsi.target; |
| 157 | vdev->selected_scsi_device.lun = iplb.scsi.lun; |
| 158 | blk_schid.ssid = iplb.scsi.ssid & 0x3; |
| 159 | found = find_dev(&schib, iplb.scsi.devno); |
| 160 | break; |
Alexander Yarygin | d046c51 | 2015-07-31 17:04:51 +0300 | [diff] [blame] | 161 | default: |
| 162 | panic("List-directed IPL not supported yet!\n"); |
| 163 | } |
Collin L. Walling | 9eaa654 | 2018-02-23 10:43:13 -0500 | [diff] [blame] | 164 | menu_setup(); |
Alexander Yarygin | 0f79b89 | 2015-06-25 18:35:58 +0300 | [diff] [blame] | 165 | } else { |
| 166 | for (ssid = 0; ssid < 0x3; ssid++) { |
| 167 | blk_schid.ssid = ssid; |
| 168 | found = find_dev(&schib, -1); |
| 169 | if (found) { |
| 170 | break; |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 171 | } |
| 172 | } |
| 173 | } |
| 174 | |
Eugene (jno) Dvurechenski | 80ba3e2 | 2015-11-10 15:37:22 +0100 | [diff] [blame] | 175 | IPL_assert(found, "No virtio device found"); |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 176 | |
Farhan Ali | 99b72e0 | 2016-11-01 17:34:00 -0400 | [diff] [blame] | 177 | if (virtio_get_device_type() == VIRTIO_ID_NET) { |
| 178 | sclp_print("Network boot device detected\n"); |
Collin L. Walling | 118ee80 | 2018-02-23 10:43:11 -0500 | [diff] [blame] | 179 | vdev->netboot_start_addr = qipl.netboot_start_addr; |
Farhan Ali | 99b72e0 | 2016-11-01 17:34:00 -0400 | [diff] [blame] | 180 | } else { |
Thomas Huth | 867e039 | 2017-07-12 14:49:45 +0200 | [diff] [blame] | 181 | virtio_blk_setup_device(blk_schid); |
Eugene (jno) Dvurechenski | 60612d5 | 2014-05-19 20:11:07 +0200 | [diff] [blame] | 182 | |
Farhan Ali | 99b72e0 | 2016-11-01 17:34:00 -0400 | [diff] [blame] | 183 | IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); |
| 184 | } |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 185 | } |
| 186 | |
| 187 | int main(void) |
| 188 | { |
| 189 | sclp_setup(); |
Jason J. Herne | 87f910c | 2019-04-04 10:34:21 -0400 | [diff] [blame] | 190 | css_setup(); |
Jason J. Herne | a5f6e09 | 2019-04-04 10:34:22 -0400 | [diff] [blame] | 191 | boot_setup(); |
Alexander Yarygin | d046c51 | 2015-07-31 17:04:51 +0300 | [diff] [blame] | 192 | virtio_setup(); |
Dominik Dingel | ff151f4 | 2013-04-30 07:15:58 +0000 | [diff] [blame] | 193 | |
Eugene (jno) Dvurechenski | 60612d5 | 2014-05-19 20:11:07 +0200 | [diff] [blame] | 194 | zipl_load(); /* no return */ |
| 195 | |
Eugene (jno) Dvurechenski | c9262e8 | 2015-09-17 12:47:27 +0200 | [diff] [blame] | 196 | panic("Failed to load OS from hard disk\n"); |
Eugene (jno) Dvurechenski | 60612d5 | 2014-05-19 20:11:07 +0200 | [diff] [blame] | 197 | return 0; /* make compiler happy */ |
Alexander Graf | 92f2ca3 | 2013-04-22 20:57:58 +0200 | [diff] [blame] | 198 | } |