From patchwork Thu Jan 18 05:05:17 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: 862762 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zMXFY2lVNz9t1t for ; Thu, 18 Jan 2018 16:14:41 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="yMEy0vjk"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="XtajrpTg"; 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 3zMXFY1JfdzF0mn for ; Thu, 18 Jan 2018 16:14:41 +1100 (AEDT) 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="yMEy0vjk"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="XtajrpTg"; dkim-atps=neutral X-Original-To: petitboot@lists.ozlabs.org Delivered-To: petitboot@lists.ozlabs.org Authentication-Results: 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; dkim=pass (2048-bit key; unprotected) header.d=mendozajonas.com header.i=@mendozajonas.com header.b="yMEy0vjk"; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b="XtajrpTg"; 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 3zMXCj4SlbzF0hS for ; Thu, 18 Jan 2018 16:13:05 +1100 (AEDT) Received: from compute2.internal (compute2.nyi.internal [10.202.2.42]) by mailout.nyi.internal (Postfix) with ESMTP id 0601C20FCD; Thu, 18 Jan 2018 00:05:49 -0500 (EST) Received: from frontend2 ([10.202.2.161]) by compute2.internal (MEProxy); Thu, 18 Jan 2018 00:05:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= mendozajonas.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=4JFWI+jhsmmsFVes+pdsQJNdaFxptVeKnUwUEFejQtw=; b=yMEy0vjk +AtdhSC8nPUJStb7eFD+lMat4x+SGHTY6zNEJTnuPuf4T0xtQ3/PtydR9RN6waip FCNmfT4j/4aTDcGWjB6dni9B1K+xmTHMSmZ1+DVI1IB67LKV3YND+/HPuZTA0VLb bUsQKQ0FINkr+XHHgI8W4r4Iasy9gEvUh5hV9E4rIo/b16J+ZM+AKg6ZbDL2F02G yBJDKX/fNFZqOm/376NAm/CRcwBQsaTCh8VdfWnVEk86QtLWy7M0pB6pPKNUA7r1 pJnUlqUWmguwrz0UHprATKMPe2Kh+QZvRImZe2+8VUMQaVMrNd9qfLXY1QgcmJfL 4u3ar4kUVlYFBw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:message-id :references:subject:to:x-me-sender:x-me-sender:x-sasl-enc; s= fm1; bh=4JFWI+jhsmmsFVes+pdsQJNdaFxptVeKnUwUEFejQtw=; b=XtajrpTg lG7mm8G+j6z8QwGqgvx2qVIGASIqagV/ZG1MbKfL5gRhXG4pOnKIUYRhdqTf8D3I LTqgA7H6TxQc2g1nsw4R+7YmsaDeR//5AaZjRSxnRrLNfCXR4MuY3eJjt0k9iWSJ dBoZ/EqAtxNBvAgWUgWTpc5/rSAAXRF47sNxFfMuYQLmAeVfiIge/PEtIMUpYaSb 3jSx2grbM+exvqWSwso1vYF3g8THE4F+n/enbnFCpfdhXpA2+cjzaB4VlDuLBzvf LzsqBp/aM3PW0avlcMGnIl5RZeNK1rrEhs9BrI5+J2SNRxuycy2Kpe0gNpUdUkpT ptjwNn2ryjRGdQ== X-ME-Sender: Received: from v4.ozlabs.ibm.com (unknown [122.99.82.10]) by mail.messagingengine.com (Postfix) with ESMTPA id D45D4240F8; Thu, 18 Jan 2018 00:05:47 -0500 (EST) From: Samuel Mendoza-Jonas To: petitboot@lists.ozlabs.org Subject: [[RFC PATCH] v2 14/14] discover/platform-powerpc-update: Implement OpenBMC support Date: Thu, 18 Jan 2018 16:05:17 +1100 Message-Id: <20180118050517.2442-15-sam@mendozajonas.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180118050517.2442-1-sam@mendozajonas.com> References: <20180118050517.2442-1-sam@mendozajonas.com> X-BeenThere: petitboot@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Petitboot bootloader development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Samuel Mendoza-Jonas MIME-Version: 1.0 Errors-To: petitboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Petitboot" Add support for firmware updates on POWER platforms whose firmware is backed by BMCs using Virtual-PNOR (VPNOR). At the moment this is exclusively POWER9 "Witherspoon" machines. This requires the Host to have network connectivity to the BMC since there is no in-band method to update the firmware on these machines. Platform updates are currently only intended for development use, and explicitly not recommended in production environments. This is primarily because there is no authentication or verification of the update metadata or update source due to the lack of HTTPS and certificate management in existing Petitboot environments (eg. op-build). Platform updates are only enabled if the "petitboot,platform_update?" parameter is set to true, and are by default disabled. Signed-off-by: Samuel Mendoza-Jonas --- discover/platform-powerpc-update.c | 147 ++++++++++++++++++++++++++++++++++++- discover/platform-powerpc-update.h | 6 ++ discover/platform-powerpc.c | 34 ++++++++- 3 files changed, 183 insertions(+), 4 deletions(-) diff --git a/discover/platform-powerpc-update.c b/discover/platform-powerpc-update.c index d257bdd..faa72c1 100644 --- a/discover/platform-powerpc-update.c +++ b/discover/platform-powerpc-update.c @@ -20,7 +20,10 @@ struct update_data { void (*status_fn)(void *arg, struct status *status, enum update_status state); void *status_arg; - const char *nvram_file; + union { + const char *nvram_file; + const char *bmc_ip; + }; enum { PFLASH_UNKNOWN = 0, PFLASH_ERASE, @@ -88,6 +91,148 @@ static int pflash_progress_cb(void *arg) return 0; } +static void rest_update_update_cb(struct process *process) +{ + struct update_data *data = process->data; + struct status status; + + status.backlog = false; + if (process->exit_status) { + status.type = STATUS_ERROR; + status.message = talloc_asprintf(data, + _("Failed to activate image")); + data->status_fn(data->status_arg, &status, + UPDATE_ERROR); + pb_log("Failed to activate BMC image\n"); + } else { + status.type = STATUS_INFO; + status.message = talloc_asprintf(data, + _("Image activated - update complete!")); + data->status_fn(data->status_arg, &status, + UPDATE_COMPLETED); + pb_log("BMC image activated\n"); + } + + pb_log("%s\n", process->stdout_buf); + talloc_free(data); +} + +static void rest_update_upload_cb(struct process *process) +{ + struct update_data *data = process->data; + struct process *p; + struct status status; + char *image_version; + int rc; + + if (process->exit_status) { + pb_log("REST API Upload Failed!\n"); + pb_log("%s\n", process->stdout_buf); + + status.backlog = false; + status.type = STATUS_ERROR; + status.message = talloc_asprintf(process, + _("Failed to upload update image")); + data->status_fn(data->status_arg, &status, + UPDATE_ERROR); + goto out; + } + + image_version = process->stdout_data; + pb_log("Uploaded image to BMC with version '%s'\n", image_version); + status.backlog = false; + status.type = STATUS_INFO; + status.message = talloc_asprintf(process, _("Image Uploaded")); + data->status_fn(data->status_arg, &status, + UPDATE_RUNNING); + + /* Activate new image */ + const char *argv[] = { + pb_system_apps.obmc_update, + "update", + image_version, + data->bmc_ip, + NULL + }; + + p = process_create(data); + if (!p) { + pb_log("update: Failed to create p\n"); + goto out; + } + + p->path = pb_system_apps.obmc_update; + p->argv = argv; + p->keep_stdout = true; + p->exit_cb = rest_update_update_cb; + p->data = data; + rc = process_run_async(p); + + if (rc || p->exit_status) { + pb_log("Error updating firmware\n"); + talloc_free(p); + } + +out: + talloc_free(status.message); + talloc_free(process); +} + +int platform_update_rest(void *ctx, struct pb_url *url, const char *file, + void (*status_fn)(void *arg, struct status *status, + enum update_status state), + void *status_arg, + const struct system_info *info) +{ + struct update_data *data; + struct process *process; + int rc; + + /* Only compressed squashfs accepted */ + if (!pb_url_check_extension(url, ".squashfs.tar")) { + pb_log("update: Only .squashfs.tar files supported\n"); + return -1; + } + + data = talloc_zero(ctx, struct update_data); + if (!data) + return -1; + + data->status_fn = status_fn; + data->status_arg = status_arg; + data->bmc_ip = talloc_strdup(data, info->bmc_ip); + + /* Upload new image */ + const char *argv[] = { + pb_system_apps.obmc_update, + "upload", + file, + data->bmc_ip, + NULL + }; + + process = process_create(ctx); + if (!process) { + pb_log("update: Failed to create process\n"); + talloc_free(data); + return -1; + } + + process->path = pb_system_apps.obmc_update; + process->argv = argv; + process->keep_stdout = true; + process->exit_cb = rest_update_upload_cb; + process->data = data; + rc = process_run_async(process); + + if (rc || process->exit_status) { + pb_log("Error updating firmware\n"); + talloc_free(process); + talloc_free(data); + } + return rc; +} + /* Restore NVRAM contents after update for flash based update */ static void nvram_restore_cb(struct process *process) { diff --git a/discover/platform-powerpc-update.h b/discover/platform-powerpc-update.h index e629cd5..4f25d08 100644 --- a/discover/platform-powerpc-update.h +++ b/discover/platform-powerpc-update.h @@ -4,6 +4,12 @@ #include "config.h" #include +int platform_update_rest(void *ctx, struct pb_url *url, const char *file, + void (*status_fn)(void *arg, struct status *status, + enum update_status state), + void *status_arg, + const struct system_info *info); + int platform_update_flash(void *ctx, struct pb_url *url, const char *file, void (*status_fn)(void *arg, struct status *status, enum update_status state), diff --git a/discover/platform-powerpc.c b/discover/platform-powerpc.c index 4b7ee60..1b75512 100644 --- a/discover/platform-powerpc.c +++ b/discover/platform-powerpc.c @@ -1356,6 +1356,20 @@ static void pre_boot(struct platform *p, const struct config *config) platform->set_os_boot_sensor(platform); } +static void bmc_check_rest_cb(struct process *process) +{ + struct platform_powerpc *platform = process->data; + + pb_debug("%s returns with status %d\n", __func__, process->exit_status); + + if (process->exit_status) + platform->update = platform_update_flash; + else + platform->update = platform_update_rest; + + process_release(process); +} + static int get_sysinfo(struct platform *p, struct system_info *sysinfo) { struct platform_powerpc *platform = p->platform_data; @@ -1400,10 +1414,24 @@ static int get_sysinfo(struct platform *p, struct system_info *sysinfo) if (platform->get_platform_versions(sysinfo)) pb_log("Failed to read platform versions\n"); - if (platform->type == POWERPC_PLATFORM_BMC) - platform->update = platform_update_flash; - else + if (platform->type == POWERPC_PLATFORM_FSP) { platform->update = NULL; + } else if (platform->type == POWERPC_PLATFORM_BMC && sysinfo->bmc_ip) { + process = process_create(platform); + process->path = pb_system_apps.obmc_update; + process->argv = argv; + process->exit_cb = bmc_check_rest_cb; + process->data = platform; + + rc = process_run_async(process); + if (rc) { + process_release(process); + pb_log("Failed to call obmc_update tool\n"); + /* Assume normal flash */ + platform->update = platform_update_flash; + } + } else + pb_log("Can not check BMC update method - no IP address\n"); sysinfo->update_support = platform->type == POWERPC_PLATFORM_BMC;