From patchwork Mon Jan 15 16:44:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Collin L. Walling" X-Patchwork-Id: 10164817 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B413F601C0 for ; Mon, 15 Jan 2018 16:51:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9DD47201B0 for ; Mon, 15 Jan 2018 16:51:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9222D201CB; Mon, 15 Jan 2018 16:51:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E514B201B0 for ; Mon, 15 Jan 2018 16:51:29 +0000 (UTC) Received: from localhost ([::1]:47162 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eb7yq-0001Db-Ul for patchwork-qemu-devel@patchwork.kernel.org; Mon, 15 Jan 2018 11:51:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57424) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eb7su-00052g-Bg for qemu-devel@nongnu.org; Mon, 15 Jan 2018 11:45:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eb7sp-000294-UJ for qemu-devel@nongnu.org; Mon, 15 Jan 2018 11:45:20 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:40236) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eb7sp-00027P-Jz for qemu-devel@nongnu.org; Mon, 15 Jan 2018 11:45:15 -0500 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0FGgT6N146179 for ; Mon, 15 Jan 2018 11:45:14 -0500 Received: from e36.co.us.ibm.com (e36.co.us.ibm.com [32.97.110.154]) by mx0a-001b2d01.pphosted.com with ESMTP id 2fgucuw7bn-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 15 Jan 2018 11:45:14 -0500 Received: from localhost by e36.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 15 Jan 2018 09:45:13 -0700 Received: from b03cxnp07028.gho.boulder.ibm.com (9.17.130.15) by e36.co.us.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 15 Jan 2018 09:45:10 -0700 Received: from b03ledav001.gho.boulder.ibm.com (b03ledav001.gho.boulder.ibm.com [9.17.130.232]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0FGjAHc14090640; Mon, 15 Jan 2018 09:45:10 -0700 Received: from b03ledav001.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 38B826E035; Mon, 15 Jan 2018 09:45:10 -0700 (MST) Received: from collin-ThinkPad-W541.pok.ibm.com (unknown [9.56.58.154]) by b03ledav001.gho.boulder.ibm.com (Postfix) with ESMTP id 820A26E038; Mon, 15 Jan 2018 09:45:09 -0700 (MST) From: "Collin L. Walling" To: qemu-s390x@nongnu.org, qemu-devel@nongnu.org Date: Mon, 15 Jan 2018 11:44:22 -0500 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1516034665-27606-1-git-send-email-walling@linux.vnet.ibm.com> References: <1516034665-27606-1-git-send-email-walling@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18011516-0020-0000-0000-00000D4E1DB3 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008383; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000245; SDB=6.00975440; UDB=6.00494388; IPR=6.00755367; BA=6.00005778; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019046; XFM=3.00000015; UTC=2018-01-15 16:45:12 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18011516-0021-0000-0000-00005FB3CECA Message-Id: <1516034665-27606-6-git-send-email-walling@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-15_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=2 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801150238 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PATCH v3 5/8] s390-ccw: interactive boot menu for eckd dasd (read stage2 data) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: frankja@linux.vnet.ibm.com, thuth@redhat.com, cohuck@redhat.com, david@redhat.com, alifm@linux.vnet.ibm.com, borntraeger@de.ibm.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- pc-bios/s390-ccw/bootmap.c | 112 +++++++++++++++++++++++++++++++++++++++++++-- pc-bios/s390-ccw/bootmap.h | 1 + pc-bios/s390-ccw/menu.h | 10 ++++ 3 files changed, 118 insertions(+), 5 deletions(-) diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index 29915e4..fb8ff80 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 * 4] __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,94 @@ 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 mbr_block_nr) +static ZiplParms get_zipl_parms(int offset) +{ + ZiplParms zipl_parms = { + .flag = *(uint16_t *)(s2_cur_blk + offset - ZIPL_FLAG_OFFSET), + .timeout = *(uint16_t *)(s2_cur_blk + offset - ZIPL_TIMEOUT_OFFSET), + .menu_start = offset, + }; + + return zipl_parms; +} + +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, prev_block_nr, next_block_nr; + EckdStage1b *s1b = (void *)sec; + ZiplParms zipl_parms; + bool found = false; + 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((void *)&s1b->seek[i].cyl); + + 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((void *)&s1b->seek[i + 1].cyl); + } + + if (next_block_nr) { + read_block(next_block_nr, s2_next_blk, + "Cannot read stage2 boot loader"); + } + + zipl_parms = get_zipl_parms(offset); + found = true; + break; + } + + prev_block_nr = cur_block_nr; + } + + if (!found) { + sclp_print("No zipl boot menu data found. Booting default entry."); + return 0; + } + + zipl_parms.menu_start++; /* make compiler happy -- does nothing vital */ + return 0; /* implemented next patch */ +} + +static void run_eckd_boot_script(block_number_t mbr_block_nr, + block_number_t s1b_block_nr) { int i; unsigned int loadparm = get_loadparm_index(); @@ -191,6 +283,10 @@ static void run_eckd_boot_script(block_number_t mbr_block_nr) ScsiMbr *bte = (void *)sec; /* Eckd bootmap table entry */ 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 +319,7 @@ static void ipl_eckd_cdl(void) XEckdMbr *mbr; EckdCdlIpl2 *ipl2 = (void *)sec; IplVolumeLabel *vlbl = (void *)sec; - block_number_t mbr_block_nr; + block_number_t mbr_block_nr, s1b_block_nr; /* we have just read the block #0 and recognized it as "IPL1" */ sclp_print("CDL\n"); @@ -249,7 +345,10 @@ static void ipl_eckd_cdl(void) /* save pointer to Boot Script */ mbr_block_nr = eckd_block_num((void *)&mbr->blockptr); - run_eckd_boot_script(mbr_block_nr); + /* save pointer to Stage1b Data */ + s1b_block_nr = eckd_block_num((void *)&ipl2->stage1.seek[0].cyl); + + run_eckd_boot_script(mbr_block_nr, s1b_block_nr); /* no return */ } @@ -280,7 +379,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 mbr_block_nr; + block_number_t mbr_block_nr, s1b_block_nr; EckdLdlIpl1 *ipl1 = (void *)sec; if (mode != ECKD_LDL_UNLABELED) { @@ -303,7 +402,10 @@ static void ipl_eckd_ldl(ECKD_IPL_mode_t mode) mbr_block_nr = eckd_block_num((void *)&ipl1->boot_info.bp.ipl.bm_ptr.eckd.bptr); - run_eckd_boot_script(mbr_block_nr); + /* save pointer to Stage1b Data */ + s1b_block_nr = eckd_block_num((void *)&ipl1->stage1.seek[0].cyl); + + run_eckd_boot_script(mbr_block_nr, s1b_block_nr); /* no return */ } diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h index df956f2..56445f2 100644 --- a/pc-bios/s390-ccw/bootmap.h +++ b/pc-bios/s390-ccw/bootmap.h @@ -74,6 +74,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.h b/pc-bios/s390-ccw/menu.h index 04b1db1..3a8a487 100644 --- a/pc-bios/s390-ccw/menu.h +++ b/pc-bios/s390-ccw/menu.h @@ -17,6 +17,16 @@ #define BOOT_MENU_FLAG_BOOT_OPTS 0x80 #define BOOT_MENU_FLAG_ZIPL_OPTS 0x40 +/* Offsets from zipl fields to zipl banner start */ +#define ZIPL_TIMEOUT_OFFSET 138 +#define ZIPL_FLAG_OFFSET 140 + +typedef struct ZiplParms { + uint16_t flag; + uint16_t timeout; + uint64_t menu_start; +} ZiplParms; + void menu_set_parms(uint8_t boot_menu_flags, uint16_t boot_menu_timeout); bool menu_check_flags(uint8_t check_flags);