Message ID | 20240927005117.1679506-18-jrossi@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390x: Add Full Boot Order Support | expand |
On 27/09/2024 02.51, jrossi@linux.ibm.com wrote: > From: Jared Rossi <jrossi@linux.ibm.com> > > Allow attempts to boot from multiple IPL devices. If the first device fails to > IPL, select the pre-built IPLB for the next device in the boot order and attempt > to IPL from it. Continue this process until IPL is successful or there are no > devices left to try. > > Signed-off-by: Jared Rossi <jrossi@linux.ibm.com> > > --- ... > diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c > index d7c457e0ed..e38eedd83a 100644 > --- a/pc-bios/s390-ccw/main.c > +++ b/pc-bios/s390-ccw/main.c > @@ -23,7 +23,7 @@ static SubChannelId blk_schid = { .one = 1 }; > static char loadparm_str[LOADPARM_LEN + 1]; > QemuIplParameters qipl; > IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); > -static bool have_iplb; > +bool have_iplb; > static uint16_t cutype; > LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ > > @@ -55,6 +55,12 @@ void write_iplb_location(void) > } > } > > +static void copy_qipl(void) > +{ > + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; > + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); > +} > + > unsigned int get_loadparm_index(void) > { > return atoi(loadparm_str); > @@ -152,6 +158,7 @@ static void menu_setup(void) > > /* If loadparm was set to any other value, then do not enable menu */ > if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { > + menu_set_parms(qipl.qipl_flags && ~BOOT_MENU_FLAG_MASK, 0); > return; > } > > @@ -183,7 +190,10 @@ static void css_setup(void) > static void boot_setup(void) > { > char lpmsg[] = "LOADPARM=[________]\n"; > - have_iplb = store_iplb(&iplb); > + > + if (!have_iplb) { > + have_iplb = store_iplb(&iplb); > + } > > if (memcmp(iplb.loadparm, "@@@@@@@@", LOADPARM_LEN) != 0) { > ebcdic_to_ascii((char *) iplb.loadparm, loadparm_str, LOADPARM_LEN); > @@ -191,6 +201,10 @@ static void boot_setup(void) > sclp_get_loadparm_ascii(loadparm_str); > } > > + if (have_iplb) { > + menu_setup(); > + } > + > memcpy(lpmsg + 10, loadparm_str, 8); > puts(lpmsg); > > @@ -208,6 +222,7 @@ static bool find_boot_device(void) > > switch (iplb.pbt) { > case S390_IPL_TYPE_CCW: > + vdev->scsi_device_selected = false; > debug_print_int("device no. ", iplb.ccw.devno); > blk_schid.ssid = iplb.ccw.ssid & 0x3; > debug_print_int("ssid ", blk_schid.ssid); > @@ -231,15 +246,8 @@ static bool find_boot_device(void) > static int virtio_setup(void) > { > VDev *vdev = virtio_get_device(); > - QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; > int ret; > > - memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); > - > - if (have_iplb) { > - menu_setup(); > - } > - > switch (vdev->senseid.cu_model) { > case VIRTIO_ID_NET: > puts("Network boot device detected"); > @@ -281,41 +289,19 @@ static void ipl_boot_device(void) > } > } > > -/* > - * No boot device has been specified, so we have to scan through the > - * channels to find one. > - */ > -static void probe_boot_device(void) > -{ > - int ssid, sch_no, ret; > - > - for (ssid = 0; ssid < 0x3; ssid++) { > - blk_schid.ssid = ssid; > - for (sch_no = 0; sch_no < 0x10000; sch_no++) { > - ret = is_dev_possibly_bootable(-1, sch_no); > - if (ret < 0) { > - break; > - } > - if (ret == true) { > - ipl_boot_device(); /* Only returns if unsuccessful */ > - return; > - } > - } > - } > - > - puts("Could not find a suitable boot device (none specified)"); > -} > - > void main(void) > { > + copy_qipl(); > sclp_setup(); > css_setup(); > - boot_setup(); > - if (have_iplb && find_boot_device()) { > - ipl_boot_device(); > - } else { > - probe_boot_device(); > - } > + do { > + boot_setup(); > + if (have_iplb && find_boot_device()) { > + ipl_boot_device(); > + } > + have_iplb = load_next_iplb(); > + } while (have_iplb); > + > + panic("No suitable device for IPL. Halting..."); > > - panic("Failed to IPL. Halting..."); > } Can we please keep the possibility to boot from any device (i.e. the probe_boot_device() stuff), in case the user did not specify any boot index property at all? Thanks, Thomas
On 27/09/2024 02.51, jrossi@linux.ibm.com wrote: > From: Jared Rossi <jrossi@linux.ibm.com> > > Allow attempts to boot from multiple IPL devices. If the first device fails to > IPL, select the pre-built IPLB for the next device in the boot order and attempt > to IPL from it. Continue this process until IPL is successful or there are no > devices left to try. > > Signed-off-by: Jared Rossi <jrossi@linux.ibm.com> > > --- ... > diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c > index d7c457e0ed..e38eedd83a 100644 > --- a/pc-bios/s390-ccw/main.c > +++ b/pc-bios/s390-ccw/main.c > @@ -23,7 +23,7 @@ static SubChannelId blk_schid = { .one = 1 }; > static char loadparm_str[LOADPARM_LEN + 1]; > QemuIplParameters qipl; > IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); > -static bool have_iplb; > +bool have_iplb; > static uint16_t cutype; > LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ > > @@ -55,6 +55,12 @@ void write_iplb_location(void) > } > } > > +static void copy_qipl(void) > +{ > + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; > + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); > +} > + > unsigned int get_loadparm_index(void) > { > return atoi(loadparm_str); > @@ -152,6 +158,7 @@ static void menu_setup(void) > > /* If loadparm was set to any other value, then do not enable menu */ > if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { > + menu_set_parms(qipl.qipl_flags && ~BOOT_MENU_FLAG_MASK, 0); That looks supsicious ... did you mean just one "&" instead of "&&" here? > return; > } Thomas
On 9/30/24 8:32 AM, Thomas Huth wrote: > On 27/09/2024 02.51, jrossi@linux.ibm.com wrote: >> From: Jared Rossi <jrossi@linux.ibm.com> >> >> -/* >> - * No boot device has been specified, so we have to scan through the >> - * channels to find one. >> - */ >> -static void probe_boot_device(void) >> -{ >> - int ssid, sch_no, ret; >> - >> - for (ssid = 0; ssid < 0x3; ssid++) { >> - blk_schid.ssid = ssid; >> - for (sch_no = 0; sch_no < 0x10000; sch_no++) { >> - ret = is_dev_possibly_bootable(-1, sch_no); >> - if (ret < 0) { >> - break; >> - } >> - if (ret == true) { >> - ipl_boot_device(); /* Only returns if unsuccessful */ >> - return; >> - } >> - } >> - } >> - >> - puts("Could not find a suitable boot device (none specified)"); >> -} >> - >> > ... > > Can we please keep the possibility to boot from any device (i.e. the > probe_boot_device() stuff), in case the user did not specify any boot > index property at all? > > Thanks, > Thomas > Yes, I’ll restore it. Jared Rossi
On 9/30/24 9:08 AM, Thomas Huth wrote: > On 27/09/2024 02.51, jrossi@linux.ibm.com wrote: >> From: Jared Rossi <jrossi@linux.ibm.com> >> >> Allow attempts to boot from multiple IPL devices. If the first device >> fails to >> IPL, select the pre-built IPLB for the next device in the boot order >> and attempt >> to IPL from it. Continue this process until IPL is successful or >> there are no >> devices left to try. >> >> Signed-off-by: Jared Rossi <jrossi@linux.ibm.com> >> >> --- > ... >> diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c >> index d7c457e0ed..e38eedd83a 100644 >> --- a/pc-bios/s390-ccw/main.c >> +++ b/pc-bios/s390-ccw/main.c >> @@ -23,7 +23,7 @@ static SubChannelId blk_schid = { .one = 1 }; >> static char loadparm_str[LOADPARM_LEN + 1]; >> QemuIplParameters qipl; >> IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); >> -static bool have_iplb; >> +bool have_iplb; >> static uint16_t cutype; >> LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ >> @@ -55,6 +55,12 @@ void write_iplb_location(void) >> } >> } >> +static void copy_qipl(void) >> +{ >> + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; >> + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); >> +} >> + >> unsigned int get_loadparm_index(void) >> { >> return atoi(loadparm_str); >> @@ -152,6 +158,7 @@ static void menu_setup(void) >> /* If loadparm was set to any other value, then do not enable >> menu */ >> if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { >> + menu_set_parms(qipl.qipl_flags && ~BOOT_MENU_FLAG_MASK, 0); > > That looks supsicious ... did you mean just one "&" instead of "&&" here? > Good catch, yes it should be a single “&”. Jared Rossi
diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h index 16643f5879..d58fe71974 100644 --- a/pc-bios/s390-ccw/iplb.h +++ b/pc-bios/s390-ccw/iplb.h @@ -17,6 +17,7 @@ #endif #include <qipl.h> +#include <string.h> extern QemuIplParameters qipl; extern IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); @@ -49,4 +50,26 @@ static inline bool set_iplb(IplParameterBlock *iplb) return manage_iplb(iplb, false); } +/* + * The IPL started on the device, but failed in some way. If the IPLB chain + * still has more devices left to try, use the next device in order. + */ +static inline bool load_next_iplb(void) +{ + IplParameterBlock *next_iplb; + + if (qipl.chain_len < 1) { + return false; + } + + qipl.index++; + next_iplb = (IplParameterBlock *) qipl.next_iplb; + memcpy(&iplb, next_iplb, sizeof(IplParameterBlock)); + + qipl.chain_len--; + qipl.next_iplb = qipl.next_iplb + sizeof(IplParameterBlock); + + return true; +} + #endif /* IPLB_H */ diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c index bcf0e12f02..afe1888511 100644 --- a/pc-bios/s390-ccw/jump2ipl.c +++ b/pc-bios/s390-ccw/jump2ipl.c @@ -45,9 +45,10 @@ int jump_to_IPL_code(uint64_t address) */ if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { iplb.devno = qipl.index; - if (!set_iplb(&iplb)) { - panic("Failed to set IPLB"); - } + } + + if (!set_iplb(&iplb)) { + panic("Failed to set IPLB"); } /* diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index d7c457e0ed..e38eedd83a 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -23,7 +23,7 @@ static SubChannelId blk_schid = { .one = 1 }; static char loadparm_str[LOADPARM_LEN + 1]; QemuIplParameters qipl; IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); -static bool have_iplb; +bool have_iplb; static uint16_t cutype; LowCore *lowcore; /* Yes, this *is* a pointer to address 0 */ @@ -55,6 +55,12 @@ void write_iplb_location(void) } } +static void copy_qipl(void) +{ + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); +} + unsigned int get_loadparm_index(void) { return atoi(loadparm_str); @@ -152,6 +158,7 @@ static void menu_setup(void) /* If loadparm was set to any other value, then do not enable menu */ if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { + menu_set_parms(qipl.qipl_flags && ~BOOT_MENU_FLAG_MASK, 0); return; } @@ -183,7 +190,10 @@ static void css_setup(void) static void boot_setup(void) { char lpmsg[] = "LOADPARM=[________]\n"; - have_iplb = store_iplb(&iplb); + + if (!have_iplb) { + have_iplb = store_iplb(&iplb); + } if (memcmp(iplb.loadparm, "@@@@@@@@", LOADPARM_LEN) != 0) { ebcdic_to_ascii((char *) iplb.loadparm, loadparm_str, LOADPARM_LEN); @@ -191,6 +201,10 @@ static void boot_setup(void) sclp_get_loadparm_ascii(loadparm_str); } + if (have_iplb) { + menu_setup(); + } + memcpy(lpmsg + 10, loadparm_str, 8); puts(lpmsg); @@ -208,6 +222,7 @@ static bool find_boot_device(void) switch (iplb.pbt) { case S390_IPL_TYPE_CCW: + vdev->scsi_device_selected = false; debug_print_int("device no. ", iplb.ccw.devno); blk_schid.ssid = iplb.ccw.ssid & 0x3; debug_print_int("ssid ", blk_schid.ssid); @@ -231,15 +246,8 @@ static bool find_boot_device(void) static int virtio_setup(void) { VDev *vdev = virtio_get_device(); - QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; int ret; - memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); - - if (have_iplb) { - menu_setup(); - } - switch (vdev->senseid.cu_model) { case VIRTIO_ID_NET: puts("Network boot device detected"); @@ -281,41 +289,19 @@ static void ipl_boot_device(void) } } -/* - * No boot device has been specified, so we have to scan through the - * channels to find one. - */ -static void probe_boot_device(void) -{ - int ssid, sch_no, ret; - - for (ssid = 0; ssid < 0x3; ssid++) { - blk_schid.ssid = ssid; - for (sch_no = 0; sch_no < 0x10000; sch_no++) { - ret = is_dev_possibly_bootable(-1, sch_no); - if (ret < 0) { - break; - } - if (ret == true) { - ipl_boot_device(); /* Only returns if unsuccessful */ - return; - } - } - } - - puts("Could not find a suitable boot device (none specified)"); -} - void main(void) { + copy_qipl(); sclp_setup(); css_setup(); - boot_setup(); - if (have_iplb && find_boot_device()) { - ipl_boot_device(); - } else { - probe_boot_device(); - } + do { + boot_setup(); + if (have_iplb && find_boot_device()) { + ipl_boot_device(); + } + have_iplb = load_next_iplb(); + } while (have_iplb); + + panic("No suitable device for IPL. Halting..."); - panic("Failed to IPL. Halting..."); } diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c index 013f94d932..734e980c6b 100644 --- a/pc-bios/s390-ccw/netmain.c +++ b/pc-bios/s390-ccw/netmain.c @@ -41,6 +41,7 @@ #define DEFAULT_TFTP_RETRIES 20 extern char _start[]; +extern bool have_iplb; #define KERNEL_ADDR ((void *)0L) #define KERNEL_MAX_SIZE ((long)_start) @@ -478,7 +479,7 @@ static int virtio_setup(void) */ enable_mss_facility(); - if (store_iplb(&iplb)) { + if (have_iplb || store_iplb(&iplb)) { if (iplb.pbt != S390_IPL_TYPE_CCW) { puts("IPL_TYPE_CCW expected"); }