From patchwork Mon Dec 3 03:00:33 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: 1006632 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 437VBH4lmKz9s55 for ; Mon, 3 Dec 2018 14:01:11 +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="i8XGAQGD"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="o5YQAwxr"; 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 437VBH1YLmzDqYV for ; Mon, 3 Dec 2018 14:01:11 +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="i8XGAQGD"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="o5YQAwxr"; 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.28; helo=out4-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="i8XGAQGD"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="o5YQAwxr"; dkim-atps=neutral Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 437VB1759QzDqXm for ; Mon, 3 Dec 2018 14:00:57 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id 39D2C21FC2; Sun, 2 Dec 2018 22:00:50 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sun, 02 Dec 2018 22:00:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= mendozajonas.com; h=from:to:cc:subject:date:message-id :mime-version:content-transfer-encoding; s=fm1; bh=et24I+jwgkwlb 9YkHkIpDngXNcdawOT52fyqDaI9jUE=; b=i8XGAQGD7PncHXgfR27C3ohbP+MAV 3OCffDUgdNUVJB0pyllpMQX8smS8MT8jPpAY87OFbHhod1HuP5+Cwlkdv3++pyG/ OyZfEW0xaWRXiMJnfPG5jHCe+doQEsowsxEq41XHGBdmDX0kPpG/aAkX9KRYsFu5 clZ+cAfkSvUJSJVF69lVASwEi7fbEfOMen+2VjpqzGOtUHUWjetW2OC9atxmLhVv V7OBAs32YBZwSYyRaT4hNKamrRVwa4B+7PFqPCU8iysiAABOWPnDLyDDEl/yVFdy 0VPCLbKFaqWuearRGJ7dTUJfEOVc/u2zCOr/Wy7bv0FJLvrhF4XJEe3gA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :message-id:mime-version:subject:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=et24I+jwgkwlb9YkH kIpDngXNcdawOT52fyqDaI9jUE=; b=o5YQAwxr7Fj/uwnrQBQMOUoYxN8HpfomC TpDqEgi4s0NRkCswweWWfEPDKFexcurEajB4gtcZ+kgS3+S0+vKIC1ab7gRS609+ plwVELVkxve9JbIzsUN/+7hG5h8ZJATSZFpLPY1mwH2eMQ994aCzw0vo0tEFA9qO IiwCeZYcifpFPNQLPE7OpWsLUy5yKT8c4UYTtuglGEQJT3iqGYDXqBzCfj0FLXKi hnRWOXt1R57zuCa46Pl9MKLScRR/ARxJTeRPx0tTbsfBji05PMP8eLlh6Bk0ihyr oxoOq0Us9dobL7Gij/AnoWnpLfPtZnATdtC5c8mDokgmcEw2MvPtw== X-ME-Sender: X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id 1D0401039D; Sun, 2 Dec 2018 22:00:47 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH 1/3] discover/platform-powerpc: read bootdev config from IPMI boot mailbox Date: Mon, 3 Dec 2018 14:00:33 +1100 Message-Id: <20181203030035.26487-1-sam@mendozajonas.com> X-Mailer: git-send-email 2.19.2 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 | 230 +++++++++++++++++++++++++++++++++++- discover/platform.c | 2 +- discover/platform.h | 2 + 3 files changed, 232 insertions(+), 2 deletions(-) diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c index f8f33054..c674e17c 100644 --- a/discover/platform-powerpc.c +++ b/discover/platform-powerpc.c @@ -27,13 +27,18 @@ static const char *devtree_dir = "/proc/device-tree/"; struct platform_powerpc { struct param_list *params; struct ipmi *ipmi; - bool ipmi_bootdev_persistent; + 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 +434,184 @@ 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) +{ + const size_t blocksize = 16; + uint8_t resp[3 + blocksize]; + 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)) { + pb_log("platform: unexpected length (%d) in " + "boot options mailbox response\n", resp_len); + return -1; + } + + 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 0; +} + +static int get_ipmi_boot_mailbox(struct platform_powerpc *platform, + char **buf) +{ + const size_t blocksize = 16; + char *mailbox_buffer, *prefix; + int content_size; + uint8_t i; + int rc; + + mailbox_buffer = talloc_array(platform, char, blocksize * 16); + if (!mailbox_buffer) { + pb_log_fn("Failed to allocate mailbox buffer\n"); + return -1; + } + + /* + * The mailbox can hold up to 16 16-byte blocks which we must request + * individually. The mininum number required by the spec is 5 blocks, + * but work with what we've got if we get less. + */ + for (i = 0; i < 16; i++) { + rc = get_ipmi_boot_mailbox_block(platform, + mailbox_buffer + (i * 16), i); + if (rc && i == 0) { + /* Immediate failure, no blocks read */ + return -1; + } + if (rc) + 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 (mailbox_buffer[0] != 0x02 || + mailbox_buffer[1] != 0x00 || + mailbox_buffer[2] != 0x00) { + pb_log_fn("IANA number unrecognised: 0x%x:0x%x:0x%x\n", + mailbox_buffer[0], + mailbox_buffer[1], + mailbox_buffer[2]); + return -1; + } + } + } + + 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\n", i); + + 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 = (i + 1) * blocksize - 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; @@ -605,6 +788,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) { @@ -630,6 +838,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) { @@ -639,6 +848,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); @@ -718,6 +944,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 237da3a9..8a23afd3 100644 --- a/discover/platform.c +++ b/discover/platform.c @@ -455,7 +455,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 29405626..1ac905af 100644 --- a/discover/platform.h +++ b/discover/platform.h @@ -27,6 +27,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 Mon Dec 3 03:00:34 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: 1006633 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 437VBS19myz9s9G for ; Mon, 3 Dec 2018 14:01:20 +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="Q1i/aXGZ"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="D/vHvC5P"; 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 437VBR5lXKzDqYP for ; Mon, 3 Dec 2018 14:01:19 +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="Q1i/aXGZ"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="D/vHvC5P"; 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.28; helo=out4-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="Q1i/aXGZ"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="D/vHvC5P"; dkim-atps=neutral Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 437VB201fFzDqXq for ; Mon, 3 Dec 2018 14:00:57 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id 213BD21FC1; Sun, 2 Dec 2018 22:00:52 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sun, 02 Dec 2018 22:00:52 -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=cDgdhIf4kte2vZxfaop3tIOemcZQl4+FIf39qgTvKSU=; b=Q1i/a XGZgG187iTv3PXDmMGuC9SfXETBfvtnGgc0gyo5h4cpzNO5MemdmeezF0DUzfSyU 6nSwrdVQ7Y4wbilT/82ByYZ+2EFZiKvxDchJj7bP3PiUrbTvh4OkPjQ8XJYbaOjh OdL6NL7lyXoUYOl4hPCgIFKawXyIlHxMznMlH+SpfIK1oj515CLkxb3Vaz8Byorb J5X3e+O8pfbp13V7+to8ROj9WidjmbAmE3UNEX43achcD1ioieqaPs6xl6gDNL8z fj7qNso2yRUi71sAQ1nQf9KmPofFlUZrV+fZ9ByYRJsSWbqNhRWQKAMoILD5joLb GSdD2PMOjmu2YJbAQ== 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=cDgdhIf4kte2vZxfaop3tIOemcZQl4+FIf39qgTvKSU=; b=D/vHvC5P wIf2Uck2DHoExj52Zv2toB8yb+aN87KUz7Du94T/uh9CC5A5aGuf6hH+SliLkvRS qXWaCOqMwAIB5n48CLl+kFDbUp8piIODidnzET0d1BL6i8lH49mZbQtMADeElE6X sKUdZDTP+yLUZZZ66yI3S0FsxWJry1KzNA9lex24vjysD2aYvWt2Ozt7fprXMrSk wx5RWiTKiDQfiF6zOBeutLrIWPsBPu8fpCvuEm/D74g19Q5iLGzwBYpaV4nzjSBN A+8YZmVKd92lTxrHTtYDbDFZxM2qQIQmiurEOlQMdpeQylMpyCrL0+Bckrdd7UB/ eoCXzAIHAWl3yw== X-ME-Sender: X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id F035B1039F; Sun, 2 Dec 2018 22:00:49 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH 2/3] utils: Add helper to send mailbox request Date: Mon, 3 Dec 2018 14:00:34 +1100 Message-Id: <20181203030035.26487-2-sam@mendozajonas.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181203030035.26487-1-sam@mendozajonas.com> References: <20181203030035.26487-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 | 167 +++++++++++++++++++++++++++++++++++ 1 file changed, 167 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..b1060797 --- /dev/null +++ b/utils/ipmi-mailbox-config.py @@ -0,0 +1,167 @@ +#!/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 > 16: + print("ERROR: buffer would require {} blocks" + + "which is more than allowed (16)".format(n_blocks)) + return None + + if n_blocks > max_blocks: + print("ERROR: buffer would require {} blocks" + + "which is more than max_blocks ({})".format(n_blocks, max_blocks)) + return None + + if n_blocks > 5: + print("Warning: buffer would require {} blocks" + + "which is more than some BMCs support".format(n_blocks)) + + + 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 Mon Dec 3 03:00:35 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: 1006634 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 437VBf2vT1z9s55 for ; Mon, 3 Dec 2018 14:01:30 +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="X3VnDzjY"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="GylRJ0/P"; 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 437VBf1KvvzDqXr for ; Mon, 3 Dec 2018 14:01:30 +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="X3VnDzjY"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="GylRJ0/P"; 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.28; helo=out4-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="X3VnDzjY"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="GylRJ0/P"; dkim-atps=neutral Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 437VB203rzzDqXr for ; Mon, 3 Dec 2018 14:00:57 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id CF9322082E; Sun, 2 Dec 2018 22:00:53 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Sun, 02 Dec 2018 22:00:53 -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=VgFWz4CEghEXpVwwKN4rdndEwfgm+waD0qTUeJU13zo=; b=X3VnD zjYa0zjfVy5T+gyjNCEwpT1oSy1afetO+rKPLM1moMAR9G7YVrbgji+5UYDZLK+8 v1FIYy/2WH2C6/wJ/P7qEP+4B1PO22XJ16BUOz33zoXDzI534lfcVkEHyhEBNWht /GTIeaJtFXTddy0Wu+RYf3IMMH+bEjvrktUM7/4Iw7v8p7NmuXVWdU4L2/TGB7lP Xu0Fe3RlOvWmADmMIAgJyxI5Pkz6RzrNXbIwnVxNqqeH0iUI1uLbp6PQfYVIn1wy HfIrg9XR5YsJxTrvrqT+CANh9cj4sHdCnR7cOQJIzhEvd4izqhddVa+bO4TdIDce oMn0W3rAR+j5SjH1A== 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=VgFWz4CEghEXpVwwKN4rdndEwfgm+waD0qTUeJU13zo=; b=GylRJ0/P moEwUPWlZMpwbW59fQ88U5fnbUHU2Hj+xZxukE7Kf1YaRZVECO/j7Hsj9ufBoty4 9O2s3YHS1ej1xiCLeQMPF6IZ4KCHhxY2PlHcIRk1P65FsrbGv11ZaNX+PIFGfDUj 3eYVgSElxz13orUYe2vIZWKRndIxtLVhLM3cTbv0xRLci22U72b7dBIWDzb5qBan Fvz/EWrm0u6W8leTwxg8YDK+OXWMtwxDG27i713nH3w2Lq0LMJLPigssN4q5VRk6 iB+ofGBSYb9KplalBHGUAFOc4Z/+Ub42OGQg/mCB6Jwl+2AAUdQMisz2T4y79sBJ Sd+1v6G+VDBtWw== X-ME-Sender: X-ME-Proxy: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id 667911039D; Sun, 2 Dec 2018 22:00:52 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [PATCH 3/3] ui/ncurses: Add option to clear IPMI boot mailbox Date: Mon, 3 Dec 2018 14:00:35 +1100 Message-Id: <20181203030035.26487-3-sam@mendozajonas.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181203030035.26487-1-sam@mendozajonas.com> References: <20181203030035.26487-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 --- 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 ++++++++++++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 1 deletion(-) 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 7c563c8e..a9c2b9a3 100644 --- a/lib/pb-protocol/pb-protocol.c +++ b/lib/pb-protocol/pb-protocol.c @@ -323,6 +323,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 */ @@ -624,6 +625,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; @@ -1219,6 +1222,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 f5392c89..77f8986d 100644 --- a/lib/types/types.h +++ b/lib/types/types.h @@ -187,6 +187,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 51861763..cd245d76 100644 --- a/ui/ncurses/nc-config.c +++ b/ui/ncurses/nc-config.c @@ -33,7 +33,7 @@ #include "nc-config.h" #include "nc-widgets.h" -#define N_FIELDS 48 +#define N_FIELDS 50 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; @@ -413,6 +417,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) @@ -520,6 +545,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, @@ -959,6 +996,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);