qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Collin L. Walling" <walling@linux.vnet.ibm.com>
To: qemu-s390x@nongnu.org, qemu-devel@nongnu.org
Cc: borntraeger@de.ibm.com, frankja@linux.vnet.ibm.com,
	cohuck@redhat.com, thuth@redhat.com, david@redhat.com,
	alifm@linux.vnet.ibm.com
Subject: [Qemu-devel] [PATCH v4 07/10] s390-ccw: read stage2 boot loader data to find menu
Date: Tue, 23 Jan 2018 13:26:50 -0500	[thread overview]
Message-ID: <1516732013-18272-8-git-send-email-walling@linux.vnet.ibm.com> (raw)
In-Reply-To: <1516732013-18272-1-git-send-email-walling@linux.vnet.ibm.com>

Read the stage2 boot loader data block-by-block. We scan the
current block for the string "zIPL" to detect the start of the
boot menu banner. We then load the adjacent blocks (previous
block and next block) to account for the possibility of menu
data spanning multiple blocks.

Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com>
---
 pc-bios/s390-ccw/bootmap.c | 94 +++++++++++++++++++++++++++++++++++++++++++---
 pc-bios/s390-ccw/bootmap.h |  1 +
 pc-bios/s390-ccw/menu.c    |  5 +++
 pc-bios/s390-ccw/menu.h    |  1 +
 4 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 0da4c7f..7d7e0c5 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -13,6 +13,7 @@
 #include "bootmap.h"
 #include "virtio.h"
 #include "bswap.h"
+#include "menu.h"
 
 #ifdef DEBUG
 /* #define DEBUG_FALLBACK */
@@ -83,6 +84,10 @@ static void jump_to_IPL_code(uint64_t address)
 
 static unsigned char _bprs[8*1024]; /* guessed "max" ECKD sector size */
 static const int max_bprs_entries = sizeof(_bprs) / sizeof(ExtEckdBlockPtr);
+static uint8_t _s2[MAX_SECTOR_SIZE * 3] __attribute__((__aligned__(PAGE_SIZE)));
+static void *s2_prev_blk = _s2;
+static void *s2_cur_blk = _s2 + MAX_SECTOR_SIZE;
+static void *s2_next_blk = _s2 + MAX_SECTOR_SIZE * 2;
 
 static inline void verify_boot_info(BootInfo *bip)
 {
@@ -182,7 +187,76 @@ static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
     return block_nr;
 }
 
-static void run_eckd_boot_script(block_number_t bmt_block_nr)
+static bool find_zipl_boot_menu_banner(int *offset)
+{
+    int i;
+
+    /* Menu banner starts with "zIPL" */
+    for (i = 0; i < virtio_get_block_size() - 4; i++) {
+        if (magic_match(s2_cur_blk + i, ZIPL_MAGIC_EBCDIC)) {
+            *offset = i;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static int eckd_get_boot_menu_index(block_number_t s1b_block_nr)
+{
+    block_number_t cur_block_nr;
+    block_number_t prev_block_nr = 0;
+    block_number_t next_block_nr = 0;
+    EckdStage1b *s1b = (void *)sec;
+    int offset;
+    int i;
+
+    /* Get Stage1b data */
+    memset(sec, FREE_SPACE_FILLER, sizeof(sec));
+    read_block(s1b_block_nr, s1b, "Cannot read stage1b boot loader");
+
+    memset(_s2, FREE_SPACE_FILLER, sizeof(_s2));
+
+    /* Get Stage2 data */
+    for (i = 0; i < STAGE2_BLK_CNT_MAX; i++) {
+        cur_block_nr = eckd_block_num(s1b->seek[i].chs);
+
+        if (!cur_block_nr) {
+            break;
+        }
+
+        read_block(cur_block_nr, s2_cur_blk, "Cannot read stage2 boot loader");
+
+        if (find_zipl_boot_menu_banner(&offset)) {
+            /* Load the adjacent blocks to account for the
+             * possibility of menu data spanning multiple blocks.
+             */
+            if (prev_block_nr) {
+                read_block(prev_block_nr, s2_prev_blk,
+                           "Cannot read stage2 boot loader");
+            }
+
+            if (i + 1 < STAGE2_BLK_CNT_MAX) {
+                next_block_nr = eckd_block_num(s1b->seek[i + 1].chs);
+            }
+
+            if (next_block_nr) {
+                read_block(next_block_nr, s2_next_blk,
+                           "Cannot read stage2 boot loader");
+            }
+
+            return menu_get_zipl_boot_index(s2_cur_blk, offset);
+        }
+
+        prev_block_nr = cur_block_nr;
+    }
+
+    sclp_print("No zipl boot menu data found. Booting default entry.");
+    return 0;
+}
+
+static void run_eckd_boot_script(block_number_t bmt_block_nr,
+                                 block_number_t s1b_block_nr)
 {
     int i;
     unsigned int loadparm = get_loadparm_index();
@@ -191,6 +265,10 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr)
     BootMapTable *bmt = (void *)sec;
     BootMapScript *bms = (void *)sec;
 
+    if (menu_check_flags(BOOT_MENU_FLAG_BOOT_OPTS | BOOT_MENU_FLAG_ZIPL_OPTS)) {
+        loadparm = eckd_get_boot_menu_index(s1b_block_nr);
+    }
+
     debug_print_int("loadparm", loadparm);
     IPL_assert(loadparm < 31, "loadparm value greater than"
                " maximum number of boot entries allowed");
@@ -223,7 +301,7 @@ static void ipl_eckd_cdl(void)
     XEckdMbr *mbr;
     EckdCdlIpl2 *ipl2 = (void *)sec;
     IplVolumeLabel *vlbl = (void *)sec;
-    block_number_t bmt_block_nr;
+    block_number_t bmt_block_nr, s1b_block_nr;
 
     /* we have just read the block #0 and recognized it as "IPL1" */
     sclp_print("CDL\n");
@@ -241,6 +319,9 @@ static void ipl_eckd_cdl(void)
     /* save pointer to Boot Map Table */
     bmt_block_nr = eckd_block_num(mbr->blockptr.xeckd.bptr.chs);
 
+    /* save pointer to Stage1b Data */
+    s1b_block_nr = eckd_block_num(ipl2->stage1.seek[0].chs);
+
     memset(sec, FREE_SPACE_FILLER, sizeof(sec));
     read_block(2, vlbl, "Cannot read Volume Label at block 2");
     IPL_assert(magic_match(vlbl->key, VOL1_MAGIC),
@@ -249,7 +330,7 @@ static void ipl_eckd_cdl(void)
                "Invalid magic of volser block");
     print_volser(vlbl->f.volser);
 
-    run_eckd_boot_script(bmt_block_nr);
+    run_eckd_boot_script(bmt_block_nr, s1b_block_nr);
     /* no return */
 }
 
@@ -280,7 +361,7 @@ static void print_eckd_ldl_msg(ECKD_IPL_mode_t mode)
 
 static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
 {
-    block_number_t bmt_block_nr;
+    block_number_t bmt_block_nr, s1b_block_nr;
     EckdLdlIpl1 *ipl1 = (void *)sec;
 
     if (mode != ECKD_LDL_UNLABELED) {
@@ -302,7 +383,10 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode)
     /* save pointer to Boot Map Table */
     bmt_block_nr = eckd_block_num(ipl1->bip.bp.ipl.bm_ptr.eckd.bptr.chs);
 
-    run_eckd_boot_script(bmt_block_nr);
+    /* save pointer to Stage1b Data */
+    s1b_block_nr = eckd_block_num(ipl1->stage1.seek[0].chs);
+
+    run_eckd_boot_script(bmt_block_nr, s1b_block_nr);
     /* no return */
 }
 
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index a3a58f4..8fa6a7b 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -85,6 +85,7 @@ typedef struct ScsiMbr {
 } __attribute__ ((packed)) ScsiMbr;
 
 #define ZIPL_MAGIC              "zIPL"
+#define ZIPL_MAGIC_EBCDIC       "\xa9\xc9\xd7\xd3"
 #define IPL1_MAGIC "\xc9\xd7\xd3\xf1" /* == "IPL1" in EBCDIC */
 #define IPL2_MAGIC "\xc9\xd7\xd3\xf2" /* == "IPL2" in EBCDIC */
 #define VOL1_MAGIC "\xe5\xd6\xd3\xf1" /* == "VOL1" in EBCDIC */
diff --git a/pc-bios/s390-ccw/menu.c b/pc-bios/s390-ccw/menu.c
index e15a7f2..de12c73 100644
--- a/pc-bios/s390-ccw/menu.c
+++ b/pc-bios/s390-ccw/menu.c
@@ -14,6 +14,11 @@
 static uint8_t flags;
 static uint64_t timeout;
 
+int menu_get_zipl_boot_index(const void *stage2, int offset)
+{
+    return 0; /* implemented next patch */
+}
+
 void menu_set_parms(uint8_t boot_menu_flag, uint16_t boot_menu_timeout)
 {
     flags = boot_menu_flag;
diff --git a/pc-bios/s390-ccw/menu.h b/pc-bios/s390-ccw/menu.h
index 04b1db1..f4a1068 100644
--- a/pc-bios/s390-ccw/menu.h
+++ b/pc-bios/s390-ccw/menu.h
@@ -17,6 +17,7 @@
 #define BOOT_MENU_FLAG_BOOT_OPTS 0x80
 #define BOOT_MENU_FLAG_ZIPL_OPTS 0x40
 
+int menu_get_zipl_boot_index(const void *stage2, int offset);
 void menu_set_parms(uint8_t boot_menu_flags, uint16_t boot_menu_timeout);
 bool menu_check_flags(uint8_t check_flags);
 
-- 
2.7.4

  parent reply	other threads:[~2018-01-23 18:27 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-23 18:26 [Qemu-devel] [PATCH v4 00/10] Interactive Boot Menu for DASD and SCSI Guests on s390x Collin L. Walling
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 01/10] s390-ccw: refactor boot map table code Collin L. Walling
2018-01-25 10:07   ` Thomas Huth
2018-01-25 14:54     ` [Qemu-devel] [qemu-s390x] " Collin L. Walling
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 02/10] s390-ccw: refactor eckd_block_num to use CHS Collin L. Walling
2018-01-25 11:06   ` Thomas Huth
2018-01-25 11:17     ` Cornelia Huck
2018-01-25 14:55       ` [Qemu-devel] [qemu-s390x] " Collin L. Walling
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 03/10] s390-ccw: refactor IPL structs Collin L. Walling
2018-01-25 11:39   ` Thomas Huth
2018-01-25 15:13     ` [Qemu-devel] [qemu-s390x] " Collin L. Walling
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 04/10] s390-ccw: update libc Collin L. Walling
2018-01-23 19:23   ` Eric Blake
2018-01-23 22:33     ` [Qemu-devel] [qemu-s390x] " Collin L. Walling
2018-01-25 12:06       ` Thomas Huth
2018-01-25 15:08         ` Eric Blake
2018-01-25 15:19           ` Collin L. Walling
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 05/10] s390-ccw: parse and set boot menu options Collin L. Walling
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 06/10] s390-ccw: set up interactive boot menu parameters Collin L. Walling
2018-01-25 13:12   ` Thomas Huth
2018-01-23 18:26 ` Collin L. Walling [this message]
2018-01-25 15:25   ` [Qemu-devel] [PATCH v4 07/10] s390-ccw: read stage2 boot loader data to find menu Thomas Huth
2018-01-25 15:49     ` [Qemu-devel] [qemu-s390x] " Collin L. Walling
2018-01-26  9:50       ` Thomas Huth
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 08/10] s390-ccw: print zipl boot menu Collin L. Walling
2018-01-25 15:46   ` Thomas Huth
2018-01-29 10:15   ` [Qemu-devel] [qemu-s390x] " David Hildenbrand
2018-01-29 14:27     ` Collin L. Walling
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 09/10] s390-ccw: read user input for boot index via the SCLP console Collin L. Walling
2018-01-26 10:44   ` Thomas Huth
2018-01-29 10:07   ` [Qemu-devel] [qemu-s390x] " David Hildenbrand
2018-01-29 10:11     ` David Hildenbrand
2018-01-29 15:16     ` Collin L. Walling
2018-01-29 13:08   ` David Hildenbrand
2018-01-29 14:38     ` Collin L. Walling
2018-01-29 15:17       ` David Hildenbrand
2018-01-23 18:26 ` [Qemu-devel] [PATCH v4 10/10] s390-ccw: interactive boot menu for scsi Collin L. Walling
2018-01-23 19:18 ` [Qemu-devel] [PATCH v4 00/10] Interactive Boot Menu for DASD and SCSI Guests on s390x Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1516732013-18272-8-git-send-email-walling@linux.vnet.ibm.com \
    --to=walling@linux.vnet.ibm.com \
    --cc=alifm@linux.vnet.ibm.com \
    --cc=borntraeger@de.ibm.com \
    --cc=cohuck@redhat.com \
    --cc=david@redhat.com \
    --cc=frankja@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-s390x@nongnu.org \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).