]> Git Repo - qemu.git/blame - pc-bios/s390-ccw/main.c
s390-bios: Decouple channel i/o logic from virtio
[qemu.git] / pc-bios / s390-ccw / main.c
CommitLineData
92f2ca38
AG
1/*
2 * S390 virtio-ccw loading program
3 *
4 * Copyright (c) 2013 Alexander Graf <[email protected]>
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
90806fec 11#include "libc.h"
92f2ca38 12#include "s390-ccw.h"
120d0410 13#include "cio.h"
60612d5c 14#include "virtio.h"
92f2ca38 15
92f2ca38 16char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
b88d7fa5 17static SubChannelId blk_schid = { .one = 1 };
a0e11b61 18static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
118ee80f 19QemuIplParameters qipl;
a5f6e097
JH
20IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
21static bool have_iplb;
f2879a5c 22
9eaa654a 23#define LOADPARM_PROMPT "PROMPT "
074afe60 24#define LOADPARM_EMPTY " "
53b310ce 25#define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL)
9eaa654a 26
f2879a5c 27/*
a5f6e097 28 * Principles of Operations (SA22-7832-09) chapter 17 requires that
f2879a5c
CB
29 * a subsystem-identification is at 184-187 and bytes 188-191 are zero
30 * after list-directed-IPL and ccw-IPL.
31 */
32void write_subsystem_identification(void)
33{
b88d7fa5 34 SubChannelId *schid = (SubChannelId *) 184;
f2879a5c
CB
35 uint32_t *zeroes = (uint32_t *) 188;
36
37 *schid = blk_schid;
38 *zeroes = 0;
39}
40
c9262e8a 41void panic(const char *string)
92f2ca38
AG
42{
43 sclp_print(string);
7f61cbc1 44 disabled_wait();
92f2ca38
AG
45 while (1) { }
46}
47
95fa1af8
FA
48unsigned int get_loadparm_index(void)
49{
074afe60 50 return atoui(loadparm_str);
95fa1af8
FA
51}
52
b88d7fa5 53static bool find_dev(Schib *schib, int dev_no)
0f79b89b
AY
54{
55 int i, r;
56
57 for (i = 0; i < 0x10000; i++) {
58 blk_schid.sch_no = i;
59 r = stsch_err(blk_schid, schib);
60 if ((r == 3) || (r == -EIO)) {
61 break;
62 }
63 if (!schib->pmcw.dnv) {
64 continue;
65 }
a1102ceb 66 if (!virtio_is_supported(blk_schid)) {
0f79b89b
AY
67 continue;
68 }
99b72e0f
FA
69 /* Skip net devices since no IPLB is created and therefore no
70 * no network bootloader has been loaded
71 */
72 if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
73 continue;
74 }
0f79b89b
AY
75 if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
76 return true;
77 }
78 }
79
80 return false;
81}
82
9eaa654a
CW
83static void menu_setup(void)
84{
a0e11b61 85 if (memcmp(loadparm_str, LOADPARM_PROMPT, LOADPARM_LEN) == 0) {
9eaa654a
CW
86 menu_set_parms(QIPL_FLAG_BM_OPTS_CMD, 0);
87 return;
88 }
89
90 /* If loadparm was set to any other value, then do not enable menu */
a0e11b61 91 if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) {
9eaa654a
CW
92 return;
93 }
94
95 switch (iplb.pbt) {
96 case S390_IPL_TYPE_CCW:
ffb4a1c8 97 case S390_IPL_TYPE_QEMU_SCSI:
53b310ce 98 menu_set_parms(qipl.qipl_flags & BOOT_MENU_FLAG_MASK,
9eaa654a
CW
99 qipl.boot_menu_timeout);
100 return;
101 }
102}
103
87f910c1
JH
104/*
105 * Initialize the channel I/O subsystem so we can talk to our ipl/boot device.
106 */
107static void css_setup(void)
108{
109 /*
110 * Unconditionally enable mss support. In every sane configuration this
111 * will succeed; and even if it doesn't, stsch_err() can handle it.
112 */
113 enable_mss_facility();
114}
115
a5f6e097
JH
116/*
117 * Collect various pieces of information from the hypervisor/hardware that
118 * we'll use to determine exactly how we'll boot.
119 */
120static void boot_setup(void)
121{
122 char lpmsg[] = "LOADPARM=[________]\n";
123
124 sclp_get_loadparm_ascii(loadparm_str);
125 memcpy(lpmsg + 10, loadparm_str, 8);
126 sclp_print(lpmsg);
127
128 have_iplb = store_iplb(&iplb);
129}
130
d046c51d 131static void virtio_setup(void)
92f2ca38 132{
b88d7fa5 133 Schib schib;
0f79b89b 134 int ssid;
92f2ca38 135 bool found = false;
0f79b89b 136 uint16_t dev_no;
99b72e0f 137 VDev *vdev = virtio_get_device();
118ee80f 138 QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
0f79b89b 139
118ee80f
CW
140 memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
141
a5f6e097 142 if (have_iplb) {
d046c51d
AY
143 switch (iplb.pbt) {
144 case S390_IPL_TYPE_CCW:
145 dev_no = iplb.ccw.devno;
146 debug_print_int("device no. ", dev_no);
147 blk_schid.ssid = iplb.ccw.ssid & 0x3;
148 debug_print_int("ssid ", blk_schid.ssid);
149 found = find_dev(&schib, dev_no);
150 break;
b39b7718 151 case S390_IPL_TYPE_QEMU_SCSI:
b39b7718
ED
152 vdev->scsi_device_selected = true;
153 vdev->selected_scsi_device.channel = iplb.scsi.channel;
154 vdev->selected_scsi_device.target = iplb.scsi.target;
155 vdev->selected_scsi_device.lun = iplb.scsi.lun;
156 blk_schid.ssid = iplb.scsi.ssid & 0x3;
157 found = find_dev(&schib, iplb.scsi.devno);
158 break;
d046c51d
AY
159 default:
160 panic("List-directed IPL not supported yet!\n");
161 }
9eaa654a 162 menu_setup();
0f79b89b
AY
163 } else {
164 for (ssid = 0; ssid < 0x3; ssid++) {
165 blk_schid.ssid = ssid;
166 found = find_dev(&schib, -1);
167 if (found) {
168 break;
92f2ca38
AG
169 }
170 }
171 }
172
80ba3e24 173 IPL_assert(found, "No virtio device found");
92f2ca38 174
99b72e0f
FA
175 if (virtio_get_device_type() == VIRTIO_ID_NET) {
176 sclp_print("Network boot device detected\n");
118ee80f 177 vdev->netboot_start_addr = qipl.netboot_start_addr;
99b72e0f 178 } else {
867e039a 179 virtio_blk_setup_device(blk_schid);
60612d5c 180
99b72e0f
FA
181 IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected");
182 }
92f2ca38
AG
183}
184
185int main(void)
186{
187 sclp_setup();
87f910c1 188 css_setup();
a5f6e097 189 boot_setup();
d046c51d 190 virtio_setup();
ff151f4e 191
60612d5c
ED
192 zipl_load(); /* no return */
193
c9262e8a 194 panic("Failed to load OS from hard disk\n");
60612d5c 195 return 0; /* make compiler happy */
92f2ca38 196}
This page took 0.24851 seconds and 4 git commands to generate.