From patchwork Tue Dec 11 02:40:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Mendoza-Jonas X-Patchwork-Id: 1010818 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43DPMc5g0fz9s3q for ; Tue, 11 Dec 2018 13:41:16 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="u85NZXzb"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="dHVewxj3"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 43DPMc478kzDqvy for ; Tue, 11 Dec 2018 13:41:16 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="u85NZXzb"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="dHVewxj3"; dkim-atps=neutral X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=mendozajonas.com (client-ip=66.111.4.25; helo=out1-smtp.messagingengine.com; envelope-from=sam@mendozajonas.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="u85NZXzb"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="dHVewxj3"; dkim-atps=neutral Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 43DPMJ26kJzDqsD for ; Tue, 11 Dec 2018 13:41:00 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id A49B5217DD; Mon, 10 Dec 2018 21:40:57 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Mon, 10 Dec 2018 21:40:57 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= mendozajonas.com; h=from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; s=fm1; bh=Ytxt29I9bJN2SMjmuz8fYzKL7YIsnYjMion2bGcvOeQ=; b=u85NZ XzbvGhpG+zoXbLoU2nx+87A1Cej5kd30YyUXoUkvLN6crNlRr0qn/jGWYnjrhnB3 Tsnq01iJF9A/s4RVZMC2wGXzWPqi/gGz4jDmDw3GhwNYQvdSFtBY/cj17RX8EFmm lMwSx2kab/7QXCNlkzHThBltP/3fcKcLlws0qi5K9PPkUpxAwtnFNr6Qv2ocWeND KZo/RD6hY9hBhdRfqPkRrNPrml9qw+C3uGQCVvd7vGEBXC1bUpGtBD8eRDPN5stv WzebCgLvUHJxUIICYhL1jIKtOhMeKcfJhXNAnQ4KAVW7WUJnG3APE5NHVioxbm/y no7zgOxCMOBEx16aQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=Ytxt29I9bJN2SMjmuz8fYzKL7YIsnYjMion2bGcvOeQ=; b=dHVewxj3 Ah1VsleT6sTBAweJCtWZY5XsXaom/lof4usHAVc4X/Ha7UzbJvpf9ZKAr2laxXpc AnPTlzmGUwQYLCHDW0PhNXIg8MNCaTQSQnP955wia/rrcM27rSqVnhl1aDGaR5Uu ucIHP7VgZ3lqXgtXVfcOjRBP3OIAfZicX1ihfMuHPgzTMUz319FrDh+QmoPad7vs b551DJ6rpzpv8qRywDDDq7YF3weINcdKreGiGjuu/ed5T7VhkFs4wMG61GyaYWqK Fv51TlKju97lI/K5oTwCG3HUcaa+0vFgHGA0zBzFN6Whous2YUtNB1B3EqbuhE3Q Kvlx0HTqokgaag== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudegiedggeelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfquhhtnecuuegrihhlohhuthemucef tddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpe furghmuhgvlhcuofgvnhguohiirgdqlfhonhgrshcuoehsrghmsehmvghnughoiigrjhho nhgrshdrtghomheqnecukfhppeduvddvrdelledrkedvrddutdenucfrrghrrghmpehmrg hilhhfrhhomhepshgrmhesmhgvnhguohiirghjohhnrghsrdgtohhmnecuvehluhhsthgv rhfuihiivgeptd X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id 057EBE4675; Mon, 10 Dec 2018 21:40:55 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH v2 1/3] discover/platform-powerpc: read bootdev config from IPMI boot mailbox Date: Tue, 11 Dec 2018 13:40:44 +1100 Message-Id: <20181211024046.17067-2-sam@mendozajonas.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181211024046.17067-1-sam@mendozajonas.com> References: <20181211024046.17067-1-sam@mendozajonas.com> MIME-Version: 1.0 X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Mendoza-Jonas Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" The IPMI Get System Boot Options commands includes parameter 7, the "boot initiator mailbox". This can be used to hold arbitrary data to influence the boot order. Use this to provide an alternate bootdev configuration to Petitboot that will override the one saved to NVRAM. This provides more fine grained override options than the existing device-type based overrides. Signed-off-by: Samuel Mendoza-Jonas --- discover/platform-powerpc.c | 256 ++++++++++++++++++++++++++++++++++++ discover/platform.c | 2 +- discover/platform.h | 2 + 3 files changed, 259 insertions(+), 1 deletion(-) diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c index a43dd676..3e700983 100644 --- a/discover/platform-powerpc.c +++ b/discover/platform-powerpc.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -28,12 +29,18 @@ static const char *devtree_dir = "/proc/device-tree/"; struct platform_powerpc { struct param_list *params; struct ipmi *ipmi; + char *ipmi_mailbox_original_config; int (*get_ipmi_bootdev)( struct platform_powerpc *platform, uint8_t *bootdev, bool *persistent); int (*clear_ipmi_bootdev)( struct platform_powerpc *platform, bool persistent); + int (*get_ipmi_boot_mailbox)( + struct platform_powerpc *platform, + char **buf); + int (*clear_ipmi_boot_mailbox)( + struct platform_powerpc *platform); int (*set_os_boot_sensor)( struct platform_powerpc *platform); void (*get_platform_versions)(struct system_info *info); @@ -429,6 +436,210 @@ static int get_ipmi_bootdev_ipmi(struct platform_powerpc *platform, return 0; } +static int get_ipmi_boot_mailbox_block(struct platform_powerpc *platform, + char *buf, uint8_t block) +{ + size_t blocksize = 16; + uint8_t resp[3 + 16]; + uint16_t resp_len; + char *debug_buf; + int rc; + uint8_t req[] = { + 0x07, /* parameter selector: boot initiator mailbox */ + block, /* set selector */ + 0x00, /* no block selector */ + }; + + resp_len = sizeof(resp); + rc = ipmi_transaction(platform->ipmi, IPMI_NETFN_CHASSIS, + IPMI_CMD_CHASSIS_GET_SYSTEM_BOOT_OPTIONS, + req, sizeof(req), + resp, &resp_len, + ipmi_timeout); + if (rc) { + pb_log("platform: error reading IPMI boot options\n"); + return -1; + } + + if (resp_len < sizeof(resp)) { + if (resp_len < 3) { + pb_log("platform: unexpected length (%d) in " + "boot options mailbox response\n", + resp_len); + return -1; + } + + if (resp_len == 4) { + pb_debug_fn("block %hu empty\n", block); + return 0; + } + + blocksize = sizeof(resp) - 3; + pb_debug_fn("Mailbox block %hu returns only %zu bytes in block\n", + block, blocksize); + } + + debug_buf = format_buffer(platform, resp, resp_len); + pb_debug_fn("IPMI bootdev mailbox block %hu:\n%s\n", block, debug_buf); + talloc_free(debug_buf); + + if (resp[0] != 0) { + pb_log("platform: non-zero completion code %d from IPMI req\n", + resp[0]); + return -1; + } + + /* check for correct parameter version */ + if ((resp[1] & 0xf) != 0x1) { + pb_log("platform: unexpected version (0x%x) in " + "boot mailbox response\n", resp[0]); + return -1; + } + + /* check for valid paramters */ + if (resp[2] & 0x80) { + pb_debug("platform: boot mailbox parameters are invalid/locked\n"); + return -1; + } + + memcpy(buf, &resp[3], blocksize); + + return blocksize; +} + +static int get_ipmi_boot_mailbox(struct platform_powerpc *platform, + char **buf) +{ + char *mailbox_buffer, *prefix; + const size_t blocksize = 16; + char block_buffer[blocksize]; + size_t mailbox_size; + int content_size; + uint8_t i; + int rc; + + mailbox_buffer = NULL; + mailbox_size = 0; + + /* + * The BMC may hold up to 255 blocks of data but more likely the number + * will be closer to the minimum of 5 set by the specification and error + * on higher numbers. + */ + for (i = 0; i < UCHAR_MAX; i++) { + rc = get_ipmi_boot_mailbox_block(platform, block_buffer, i); + if (rc < 3 && i == 0) { + /* + * Immediate failure, no blocks read or missing IANA + * number. + */ + return -1; + } + if (rc < 1) { + /* Error or no bytes read */ + break; + } + + if (i == 0) { + /* + * The first three bytes of block zero are an IANA + * Enterprise ID number. Check it matches the IBM + * number, '2'. + */ + if (block_buffer[0] != 0x02 || + block_buffer[1] != 0x00 || + block_buffer[2] != 0x00) { + pb_log_fn("IANA number unrecognised: 0x%x:0x%x:0x%x\n", + block_buffer[0], + block_buffer[1], + block_buffer[2]); + return -1; + } + } + + mailbox_buffer = talloc_realloc(platform, mailbox_buffer, + char, mailbox_size + rc); + if (!mailbox_buffer) { + pb_log_fn("Failed to allocate mailbox buffer\n"); + return -1; + } + memcpy(mailbox_buffer + mailbox_size, block_buffer, rc); + mailbox_size += rc; + } + + if (i < 5) + pb_log_fn("Only %hu blocks read, spec requires at least 5.\n" + "Send a bug report to your preferred BMC vendor!\n", + i); + else + pb_debug_fn("%hu blocks read (%zu bytes)\n", i, mailbox_size); + + if (mailbox_size < 3 + strlen("petitboot,bootdevs=")) + return -1; + + prefix = talloc_strndup(mailbox_buffer, mailbox_buffer + 3, + strlen("petitboot,bootdevs=")); + if (!prefix) { + pb_log_fn("Couldn't check prefix\n"); + talloc_free(mailbox_buffer); + return -1; + } + + if (strncmp(prefix, "petitboot,bootdevs=", + strlen("petitboot,bootdevs=")) != 0 ) { + /* Empty or garbage */ + pb_debug_fn("Buffer looks unconfigured\n"); + talloc_free(mailbox_buffer); + *buf = NULL; + return 0; + } + + /* Don't include IANA number in buffer */ + content_size = mailbox_size - 3 - strlen("petitboot,bootdevs="); + *buf = talloc_memdup(platform, + mailbox_buffer + 3 + strlen("petitboot,bootdevs="), + content_size + 1); + (*buf)[content_size] = '\0'; + + talloc_free(mailbox_buffer); + return 0; +} + +static int clear_ipmi_boot_mailbox(struct platform_powerpc *platform) +{ + uint8_t req[18] = {0}; /* req (2) + blocksize (16) */ + uint16_t resp_len; + uint8_t resp[1]; + uint8_t i; + int rc; + + req[0] = 0x07; /* parameter selector: boot initiator mailbox */ + + resp_len = sizeof(resp); + + for (i = 0; i < 16; i++) { + req[1] = i; /* set selector */ + rc = ipmi_transaction(platform->ipmi, IPMI_NETFN_CHASSIS, + IPMI_CMD_CHASSIS_SET_SYSTEM_BOOT_OPTIONS, + req, sizeof(req), + resp, &resp_len, + ipmi_timeout); + + if (rc || resp[0]) { + if (i == 0) { + pb_log("platform: error clearing IPMI boot mailbox, rc %d resp[0] %hu\n", + rc, resp[0]); + return -1; + } else + break; + } + } + + pb_debug_fn("Cleared %hu blocks\n", i); + + return 0; +} + static int set_ipmi_os_boot_sensor(struct platform_powerpc *platform) { int sensor_number; @@ -606,6 +817,31 @@ static int load_config(struct platform *p, struct config *config) if (rc) pb_log_fn("Failed to parse nvram\n"); + /* + * If we have an IPMI mailbox configuration available use it instead of + * the boot order found in NVRAM. + */ + if (platform->get_ipmi_boot_mailbox) { + char *mailbox; + struct param *param; + rc = platform->get_ipmi_boot_mailbox(platform, &mailbox); + if (!rc && mailbox) { + platform->ipmi_mailbox_original_config = + talloc_strdup( + platform, + param_list_get_value( + platform->params, "petitboot,bootdevs")); + param_list_set(platform->params, "petitboot,bootdevs", + mailbox, false); + param = param_list_get_param(platform->params, + "petitboot,bootdevs"); + /* Avoid writing this to NVRAM */ + param->modified = false; + config->ipmi_bootdev_mailbox = true; + talloc_free(mailbox); + } + } + config_populate_all(config, platform->params); if (platform->get_ipmi_bootdev) { @@ -639,6 +875,7 @@ static int save_config(struct platform *p, struct config *config) { struct platform_powerpc *platform = to_platform_powerpc(p); struct config *defaults; + struct param *param; if (config->ipmi_bootdev == IPMI_BOOTDEV_INVALID && platform->clear_ipmi_bootdev) { @@ -648,6 +885,23 @@ static int save_config(struct platform *p, struct config *config) config->ipmi_bootdev_persistent = false; } + if (!config->ipmi_bootdev_mailbox && + platform->ipmi_mailbox_original_config) { + param = param_list_get_param(platform->params, + "petitboot,bootdevs"); + /* Restore old boot order if unmodified */ + if (!param->modified) { + param_list_set(platform->params, "petitboot,bootdevs", + platform->ipmi_mailbox_original_config, + false); + param->modified = false; + config_populate_bootdev(config, platform->params); + } + platform->clear_ipmi_boot_mailbox(platform); + talloc_free(platform->ipmi_mailbox_original_config); + platform->ipmi_mailbox_original_config = NULL; + } + defaults = talloc_zero(platform, struct config); config_set_defaults(defaults); @@ -744,6 +998,8 @@ static bool probe(struct platform *p, void *ctx) platform->ipmi = ipmi_open(platform); platform->get_ipmi_bootdev = get_ipmi_bootdev_ipmi; platform->clear_ipmi_bootdev = clear_ipmi_bootdev_ipmi; + platform->get_ipmi_boot_mailbox = get_ipmi_boot_mailbox; + platform->clear_ipmi_boot_mailbox = clear_ipmi_boot_mailbox; platform->set_os_boot_sensor = set_ipmi_os_boot_sensor; } else if (!stat(sysparams_dir, &statbuf)) { pb_debug("platform: using sysparams for IPMI paramters\n"); diff --git a/discover/platform.c b/discover/platform.c index 7712ef14..8ce52fc8 100644 --- a/discover/platform.c +++ b/discover/platform.c @@ -468,7 +468,7 @@ static int read_bootdev(void *ctx, char **pos, struct autoboot_option *opt) return rc; } -static void config_populate_bootdev(struct config *config, +void config_populate_bootdev(struct config *config, const struct param_list *pl) { struct autoboot_option *opt, *new = NULL; diff --git a/discover/platform.h b/discover/platform.h index f7d3d1c4..5a5c9907 100644 --- a/discover/platform.h +++ b/discover/platform.h @@ -31,6 +31,8 @@ const struct config *config_get(void); int config_set(struct config *config); void config_set_defaults(struct config *config); void config_set_autoboot(bool autoboot_enabled); +void config_populate_bootdev(struct config *config, + const struct param_list *pl); void config_populate_all(struct config *config, const struct param_list *pl); void params_update_network_values(struct param_list *pl, From patchwork Tue Dec 11 02:40:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Mendoza-Jonas X-Patchwork-Id: 1010819 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43DPMp6SRjz9s47 for ; Tue, 11 Dec 2018 13:41:26 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="XBwu1PoM"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="ugZZUYK6"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 43DPMp4ckRzDqxH for ; Tue, 11 Dec 2018 13:41:26 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="XBwu1PoM"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="ugZZUYK6"; dkim-atps=neutral X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=mendozajonas.com (client-ip=66.111.4.25; helo=out1-smtp.messagingengine.com; envelope-from=sam@mendozajonas.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="XBwu1PoM"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="ugZZUYK6"; dkim-atps=neutral Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 43DPMK605RzDqrn for ; Tue, 11 Dec 2018 13:41:01 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id 5B8E521921; Mon, 10 Dec 2018 21:40:59 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Mon, 10 Dec 2018 21:40:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= mendozajonas.com; h=from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; s=fm1; bh=EmfHopKffR54VAMpxppgoqDdYHtnTkWHz17wUGn8udY=; b=XBwu1 PoM0fRiuNUxziL9EXxc+vTdGlik6i3b5WgvKxmls8GKT47kJ9xSX456In332tRoB dnie/akMDyi0hsVt4mPi+oaGs3EzNlNDWI+oDpJ4Car9aiVrHF2+RsleB5vVuR8J EGomolTK1vROm9mbKL7lPHehKssfO++WdfbiWoLcOgOjviDEItmB3gFUYHPvteJr vUr8IJSOWJwKDtpHNex80vKar9ey9V7DmTpee0+jVLNv7ajAYOtoYSfqhtKN6wKI oB1QlvikLW6xgkS4HKzvIVpIIV8IMMvLK5WRi3TDzNgnzIALyhxglLBgUfKX01PB XvwqtWxWtABDSsTGQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=EmfHopKffR54VAMpxppgoqDdYHtnTkWHz17wUGn8udY=; b=ugZZUYK6 uxibjQG5WysQXwtNHjvFIcNlG+Zi4hYWMylPnIK49mUUs765wp29UxUrsXKKVShJ vaPhhF/RyDv4FKLVxpRwBdtyXHvj841H5Tj27los/anqlNIA5pHk1azsuCJTxc0z 0gim6xYtPsuZqJjJaDr2p21XZnmEDEb+dHGL/qVPzNbXWugw8XSeVp6O3CCh9x2T zMRMsR7oGIm5yJTlduOrE5AB8HWefzaXyvt+i+jW86tY2FsAwoUfE6mKm+/LSKoN zo2P6J4fS3594P8Fbw+s/hEPz63YjncFbSNTzTNgVyZbI698u4/y6XPJH5KcfMT7 yjUuRNDU3BLp+g== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudegiedggeelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfquhhtnecuuegrihhlohhuthemucef tddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpe furghmuhgvlhcuofgvnhguohiirgdqlfhonhgrshcuoehsrghmsehmvghnughoiigrjhho nhgrshdrtghomheqnecukfhppeduvddvrdelledrkedvrddutdenucfrrghrrghmpehmrg hilhhfrhhomhepshgrmhesmhgvnhguohiirghjohhnrghsrdgtohhmnecuvehluhhsthgv rhfuihiivgeptd X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id D6E70E4675; Mon, 10 Dec 2018 21:40:57 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH v2 2/3] utils: Add helper to send mailbox request Date: Tue, 11 Dec 2018 13:40:45 +1100 Message-Id: <20181211024046.17067-3-sam@mendozajonas.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181211024046.17067-1-sam@mendozajonas.com> References: <20181211024046.17067-1-sam@mendozajonas.com> MIME-Version: 1.0 X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Mendoza-Jonas Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" A simple script to set, display, and clear a BMC's boot initiator mailbox. Signed-off-by: Samuel Mendoza-Jonas --- utils/ipmi-mailbox-config.py | 166 +++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100755 utils/ipmi-mailbox-config.py diff --git a/utils/ipmi-mailbox-config.py b/utils/ipmi-mailbox-config.py new file mode 100755 index 00000000..1b57ebb9 --- /dev/null +++ b/utils/ipmi-mailbox-config.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 + +import argparse +import subprocess + +def send_block_read_command(hostname, username, password, index, dry_run): + + if hostname is None and dry_run: + hostname = "" + + cmd = "ipmitool -I lanplus -H " + hostname + if username is not None: + cmd = cmd + " -U " + username + if password is not None: + cmd = cmd + " -P " + password + + # chassis netfn, get-sys-boot-options, parameter 7, set-sel, block-sel + cmd = cmd + " raw 0x00 0x09 0x07 " + hex(index) + " 0x00 " + + print(cmd) + if not dry_run: + rc = subprocess.call(cmd, shell=True) + if rc != 0: + print("Command returned error: {}".format(rc)) + +def send_block_command(hostname, username, password, block, index, dry_run): + + if hostname is None and dry_run: + hostname = "" + + cmd = "ipmitool -I lanplus -H " + hostname + if username is not None: + cmd = cmd + " -U " + username + if password is not None: + cmd = cmd + " -P " + password + + # chassis netfn, set-sys-boot-options, parameter 7, set-sel, block-sel + cmd = cmd + " raw 0x00 0x08 0x07 " + hex(index) + " " + block + + print(cmd) + if not dry_run: + rc = subprocess.call(cmd, shell=True) + if rc != 0: + print("Command returned error: {}".format(rc)) + +def construct_buffer(config, max_blocks): + + # Add IBM's IANA prefix + raw = bytes([0x02, 0x00, 0x00]) + config.encode('ascii') + + n_blocks = int(len(raw) / 16) + if len(raw) % 16 != 0: + n_blocks += 1 + + if n_blocks > 255: + print("ERROR: buffer would require {} blocks".format(n_blocks) + + " which is more than hypothetically possible (255)") + return None + + if n_blocks > max_blocks: + print("ERROR: buffer would require {} blocks".format(n_blocks) + + " which is more than max_blocks ({})".format(max_blocks)) + return None + + if n_blocks > 5: + print("Warning: buffer would require {} blocks".format(n_blocks) + + "which is more than some BMCs support") + + blocks = [] + rem = len(raw) + for i in range(n_blocks): + block = "" + if rem >= 16: + last = 16 + else: + last = rem + + for j in range(16): + if j < last: + block += "{:#02x} ".format(raw[i * 16 + j]) + else: + # Pad out to 16 bytes + block += "0x00 " + + + blocks.append(block) + rem -= last + + if n_blocks < max_blocks: + for i in range(max_blocks - n_blocks): + blocks.append("0x00 0x00 0x00 0x00 " + + "0x00 0x00 0x00 0x00 " + + "0x00 0x00 0x00 0x00 " + + "0x00 0x00 0x00 0x00") + + return blocks + +def construct_empty_buffer(max_blocks): + + blocks = [] + for i in range(max_blocks): + blocks.append("0x00 0x00 0x00 0x00 " + + "0x00 0x00 0x00 0x00 " + + "0x00 0x00 0x00 0x00 " + + "0x00 0x00 0x00 0x00") + + return blocks + +def main(): + + parser = argparse.ArgumentParser() + parser.add_argument("-b", "--bmc-hostname") + parser.add_argument("-u", "--username") + parser.add_argument("-p", "--password") + parser.add_argument("-n", "--dry-run", action="store_true") + parser.add_argument("-c", "--config") + parser.add_argument("-x", "--clear", action="store_true") + parser.add_argument("-d", "--dump", action="store_true") + parser.add_argument("-m", "--max-blocks") + + args = parser.parse_args() + + if not args.dry_run and args.bmc_hostname is None: + print("No hostname specified!") + return -1 + + if args.config and args.clear: + print("Can't specify --config and --clear together") + return -1 + + if args.max_blocks: + n_blocks = int(args.max_blocks) + else: + n_blocks = 16 + + + if args.config or args.clear: + if args.config: + blocks = construct_buffer(args.config, int(args.max_blocks)) + if args.clear: + blocks = construct_empty_buffer(int(args.max_blocks)) + if blocks is None: + print("Failed to construct buffer") + return -1 + + print("{} blocks to send".format(len(blocks))) + print("---------------------------------------") + for i in range(len(blocks)): + try: + send_block_command(args.bmc_hostname, args.username, args.password, + blocks[i], i, args.dry_run) + except Exception as e: + print(e) + print("Error sending block {}".format(i)) + return -1 + i += 1 + + if args.dump: + print("\nReading {} blocks".format(n_blocks)) + print("---------------------------------------") + for i in range(n_blocks): + send_block_read_command(args.bmc_hostname, args.username, + args.password, i, args.dry_run) + +if __name__ == "__main__": + main() From patchwork Tue Dec 11 02:40:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Mendoza-Jonas X-Patchwork-Id: 1010820 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43DPN11Bjbz9s3q for ; Tue, 11 Dec 2018 13:41:37 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="b1fgOHBi"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="e0ig41Gb"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 43DPN0649VzDqwC for ; Tue, 11 Dec 2018 13:41:36 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="b1fgOHBi"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="e0ig41Gb"; dkim-atps=neutral X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=mendozajonas.com (client-ip=66.111.4.25; helo=out1-smtp.messagingengine.com; envelope-from=sam@mendozajonas.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=mendozajonas.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="b1fgOHBi"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="e0ig41Gb"; dkim-atps=neutral Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 43DPMM3qXrzDqrn for ; Tue, 11 Dec 2018 13:41:03 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id 0C6EE21EDD; Mon, 10 Dec 2018 21:41:01 -0500 (EST) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Mon, 10 Dec 2018 21:41:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= mendozajonas.com; h=from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; s=fm1; bh=dPJcrjVdVkDBvgds7iwWXSWe+5ERWHkhsDW4bcHWlEI=; b=b1fgO HBicVs8//RbkelxDCMoI0vS6CCtkY6R9wYRGQL33s8tUP6yHzzPQGArw/nmnWILP 6Zkoe4+Xvr9rvGveFee0YycX514VtA5GXDf+y21CK6wepewzgG3m4mqPjawqgTXr ufJJjHC9y/z8Hwhprtezp7KdO5wSDVJMNkTg+34BQ9vGokafyyydJ4fIyAZWwJg/ rAFqbt5SAKAhVgap4hRsu8p/CrWIuDKlqj6tQiV+VNJwf4lQpPceh0A6NtqluvZo wZzagSYlEhsZyWnpeb+IpLNJ45CezeF76CLBuJfs2r8Y0I+YAfGB9OUYcsXjpBn5 8+ebZ6mNA+UEZ7g8w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=dPJcrjVdVkDBvgds7iwWXSWe+5ERWHkhsDW4bcHWlEI=; b=e0ig41Gb telhkJQAezkyt5EfsBNZqBNMH0xYMklvJiPw4AUjSM+C/Y+KnblRs6Pu1LaVp7s4 mdRwawKLmbsScq8wkBFysoRzFnD6s5pyi4bD7zozBI2dRm3X5NZbyFU5ZPObGB0r PzkhgOBtaUt0fbHud1+J8da97iJG5CCNMvP5wmVfTFONEukM8/kQsml5iuygVSZs AMCMOsMsEkM7+wXAQxvHOZxhSmETCmnB/z4ZWJfacEQzKepfSJwoWueNrKnUt/3w U/vuHxulTEIut7mK8AGSGQlKq8QbB11qQ/n2I6LArQoNpwQb2I5rNAL7/zyYlT9e 0zy55VcaUzdP2A== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudegiedggeelucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfquhhtnecuuegrihhlohhuthemucef tddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpe furghmuhgvlhcuofgvnhguohiirgdqlfhonhgrshcuoehsrghmsehmvghnughoiigrjhho nhgrshdrtghomheqnecukfhppeduvddvrdelledrkedvrddutdenucfrrghrrghmpehmrg hilhhfrhhomhepshgrmhesmhgvnhguohiirghjohhnrghsrdgtohhmnecuvehluhhsthgv rhfuihiivgepvd X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id 760BFE4675; Mon, 10 Dec 2018 21:40:59 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH v2 3/3] ui/ncurses: Add option to clear IPMI boot mailbox Date: Tue, 11 Dec 2018 13:40:46 +1100 Message-Id: <20181211024046.17067-4-sam@mendozajonas.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181211024046.17067-1-sam@mendozajonas.com> References: <20181211024046.17067-1-sam@mendozajonas.com> MIME-Version: 1.0 X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Mendoza-Jonas Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" If there is an IPMI boot mailbox configuration present display a message in the System Configuration screen and provide the option to clear the mailbox. Signed-off-by: Samuel Mendoza-Jonas --- discover/platform-powerpc.c | 9 ++++--- lib/pb-config/pb-config.c | 1 + lib/pb-protocol/pb-protocol.c | 6 +++++ lib/types/types.h | 1 + ui/ncurses/nc-config.c | 49 ++++++++++++++++++++++++++++++++++- 5 files changed, 61 insertions(+), 5 deletions(-) diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c index 3e700983..5d7cc597 100644 --- a/discover/platform-powerpc.c +++ b/discover/platform-powerpc.c @@ -617,7 +617,7 @@ static int clear_ipmi_boot_mailbox(struct platform_powerpc *platform) resp_len = sizeof(resp); - for (i = 0; i < 16; i++) { + for (i = 0; i < UCHAR_MAX; i++) { req[1] = i; /* set selector */ rc = ipmi_transaction(platform->ipmi, IPMI_NETFN_CHASSIS, IPMI_CMD_CHASSIS_SET_SYSTEM_BOOT_OPTIONS, @@ -627,11 +627,12 @@ static int clear_ipmi_boot_mailbox(struct platform_powerpc *platform) if (rc || resp[0]) { if (i == 0) { - pb_log("platform: error clearing IPMI boot mailbox, rc %d resp[0] %hu\n", + pb_log_fn("error clearing IPMI boot mailbox, " + "rc %d resp[0] %hu\n", rc, resp[0]); return -1; - } else - break; + } + break; } } diff --git a/lib/pb-config/pb-config.c b/lib/pb-config/pb-config.c index 7fa925c2..a802c92f 100644 --- a/lib/pb-config/pb-config.c +++ b/lib/pb-config/pb-config.c @@ -83,6 +83,7 @@ struct config *config_copy(void *ctx, const struct config *src) dest->ipmi_bootdev = src->ipmi_bootdev; dest->ipmi_bootdev_persistent = src->ipmi_bootdev_persistent; + dest->ipmi_bootdev_mailbox = src->ipmi_bootdev_mailbox; dest->allow_writes = src->allow_writes; diff --git a/lib/pb-protocol/pb-protocol.c b/lib/pb-protocol/pb-protocol.c index d8771fcb..b4138bbf 100644 --- a/lib/pb-protocol/pb-protocol.c +++ b/lib/pb-protocol/pb-protocol.c @@ -324,6 +324,7 @@ int pb_protocol_config_len(const struct config *config) } len += 4 + 4; /* ipmi_bootdev, ipmi_bootdev_persistent */ + len += 4; /* ipmi_bootdev_mailbox */ len += 4; /* allow_writes */ @@ -646,6 +647,8 @@ int pb_protocol_serialise_config(const struct config *config, pos += 4; *(uint32_t *)pos = config->ipmi_bootdev_persistent; pos += 4; + *(uint32_t *)pos = config->ipmi_bootdev_mailbox; + pos += 4; *(uint32_t *)pos = config->allow_writes; pos += 4; @@ -1277,6 +1280,9 @@ int pb_protocol_deserialise_config(struct config *config, if (read_u32(&pos, &len, &tmp)) goto out; config->ipmi_bootdev_persistent = !!tmp; + if (read_u32(&pos, &len, &tmp)) + goto out; + config->ipmi_bootdev_mailbox = !!tmp; if (read_u32(&pos, &len, &tmp)) goto out; diff --git a/lib/types/types.h b/lib/types/types.h index 39760d91..9d83d87d 100644 --- a/lib/types/types.h +++ b/lib/types/types.h @@ -188,6 +188,7 @@ struct config { unsigned int ipmi_bootdev; bool ipmi_bootdev_persistent; + bool ipmi_bootdev_mailbox; char *http_proxy; char *https_proxy; diff --git a/ui/ncurses/nc-config.c b/ui/ncurses/nc-config.c index 4685fa5d..943ee8a8 100644 --- a/ui/ncurses/nc-config.c +++ b/ui/ncurses/nc-config.c @@ -34,7 +34,7 @@ #include "nc-config.h" #include "nc-widgets.h" -#define N_FIELDS 49 +#define N_FIELDS 51 extern struct help_text config_help_text; @@ -67,6 +67,7 @@ struct config_screen { bool autoboot_enabled; bool ipmi_override; + bool ipmi_mailbox; bool net_override; struct { @@ -86,6 +87,9 @@ struct config_screen { struct nc_widget_label *ipmi_clear_l; struct nc_widget_button *ipmi_clear_b; + struct nc_widget_label *ipmi_mailbox_l; + struct nc_widget_button *ipmi_mailbox_b; + struct nc_widget_label *network_l; struct nc_widget_select *network_f; @@ -439,6 +443,27 @@ static void ipmi_clear_click(void *arg) screen->exit = true; } +static void ipmi_clear_mailbox_click(void *arg) +{ + struct config_screen *screen = arg; + struct config *config; + int rc; + + config = config_copy(screen, screen->cui->config); + config->ipmi_bootdev_mailbox = false; + config->safe_mode = false; + + rc = cui_send_config(screen->cui, config); + talloc_free(config); + + if (rc) + pb_log("cui_send_config failed!\n"); + else + pb_debug("config sent!\n"); + screen->exit = true; +} + + static int layout_pair(struct config_screen *screen, int y, struct nc_widget_label *label, struct nc_widget *field) @@ -546,6 +571,18 @@ static void config_screen_layout_widgets(struct config_screen *screen) y += 1; } + if (screen->ipmi_mailbox) { + wl = widget_label_base(screen->widgets.ipmi_mailbox_l); + widget_set_visible(wl, true); + widget_move(wl, y, screen->label_x); + y += 1; + + wf = widget_button_base(screen->widgets.ipmi_mailbox_b); + widget_set_visible(wf, true); + widget_move(wf, y, screen->field_x); + y += 1; + } + y += 1; y += layout_pair(screen, y, screen->widgets.network_l, @@ -990,6 +1027,16 @@ static void config_screen_setup_widgets(struct config_screen *screen, screen->ipmi_override = true; } + if (config->ipmi_bootdev_mailbox) { + screen->widgets.ipmi_mailbox_l = widget_new_label(set, 0, 0, + _("IPMI boot order mailbox config present")); + screen->widgets.ipmi_mailbox_b = widget_new_button(set, 0, 0, + strncols(_("Clear IPMI boot order mailbox now")) + 10, + _("Clear IPMI boot order mailbox now"), + ipmi_clear_mailbox_click, screen); + screen->ipmi_mailbox = true; + } + screen->widgets.network_l = widget_new_label(set, 0, 0, _("Network:")); screen->widgets.network_f = widget_new_select(set, 0, 0, COLS - screen->field_x - 1);