From patchwork Tue Mar 17 02:12:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255986 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=hbfbzV2F; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGsP163Gz9sPF for ; Tue, 17 Mar 2020 13:12:40 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9B3C181927; Tue, 17 Mar 2020 03:12:27 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="hbfbzV2F"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0F9B581918; Tue, 17 Mar 2020 03:12:23 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x431.google.com (mail-pf1-x431.google.com [IPv6:2607:f8b0:4864:20::431]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id D41B5818F8 for ; Tue, 17 Mar 2020 03:12:17 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x431.google.com with SMTP id z65so11027874pfz.8 for ; Mon, 16 Mar 2020 19:12:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=yU/G8hRMmXDduue7vbj2dYNhX/7crrp0sSZbdpIaCHg=; b=hbfbzV2FJUp5jQkoBp7IZWmYzescUhciWLxdR79R3U0ZD9R910OYXte9ndOR0TWpBB 8PrT90j3hp5AAN5jIX96KWmLnYOv68ntq7z3OyqBKo4WYh/zlmUoP3SjGnqGOLQqODRx ihyqiYSCNctlsZLCPt1IGpTpO091LSeyDsyZ+fbMoHdR5wqF6+R3qOpwHfoOuyyyJARh fgN3Z36et13yzMFe9Gd03ciWwOctENP+9H2Zs5BF9ANfeJI+Bb7E4dEZXigR/vPDQbzs 9Syvotjwk5phutJ5JF8piThI1sqVJiCpuHB1mB/F7r3ps0+IgsdCf6IZugGPKkKsCxng hxWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=yU/G8hRMmXDduue7vbj2dYNhX/7crrp0sSZbdpIaCHg=; b=Ca4oIyf7vpbEmMPekh6kJnHmOA0NDnEvDvbJopQhTsxcJvmiDsSHk1AjKqKp3GKfVC VXVJnLzi2FUV0P0JviRxnWsRduugLgOE9Nsh11nF9hQ71u2/6TiQ8zAGzowSMwYgniDv 9zIE3Of0VPRp9JWjTGKrZOcD+VVl4by3Xpg4oE3MxjqrMdvBZRQ1QSX23LSVFwDiwya4 lc1sW1rIzGsKUhbQmu/yiOkzsdDzsZsf420jhiFm8Bl2ada+PWQY3wUzAkFqNIRpvc8c kuK/HucKg4itmlB/qIt9UO/HiSgIKzk1xiEknt+XpZay3bpoC6l00B7t3uBd0ZgajoTi oDiA== X-Gm-Message-State: ANhLgQ1uzhTURaM3KnqhJrxO9poUwnAHLhhbnGiw/TLiaTbLQ1pnvHMM RVLaDGL9mGqmb7DoRWcmJlhVIw== X-Google-Smtp-Source: ADFU+vsB8gvi0/wK+/vjRfstWkh9vcMqpj9AJ3WMXRaieVt/KRrppf9YVitaG5IYAKMbQu4niAXjqQ== X-Received: by 2002:a62:3786:: with SMTP id e128mr2810994pfa.124.1584411136328; Mon, 16 Mar 2020 19:12:16 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id s19sm1067243pfh.218.2020.03.16.19.12.15 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:15 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 01/14] efi_loader: define OsIndicationsSupported flags Date: Tue, 17 Mar 2020 11:12:34 +0900 Message-Id: <20200317021247.5849-2-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean These flags are expected to be set in OsIndicationsSupported variable if corresponding features are supported. See UEFI specification, section 8.5.4. In particular, capsule-related flags will be used in my capsule update patch. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- include/efi_api.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index 22396172e15f..73c0722b0168 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -57,6 +57,17 @@ typedef u16 efi_form_id_t; struct efi_event; +/* OsIndicationsSupported flags */ +#define EFI_OS_INDICATIONS_BOOT_TO_RW_UI 0x0000000000000001 +#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002 +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED \ + 0x0000000000000004 +#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED 0x0000000000000008 +#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED 0x0000000000000010 +#define EFI_OS_INDICATIONS_START_OS_RECOVERY 0x0000000000000020 +#define EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY 0x0000000000000040 +#define EFI_OS_INDICATIONS_JSON_CONFIG_DATA_REFRESH 0x0000000000000080 + /* EFI Boot Services table */ #define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42 struct efi_boot_services { From patchwork Tue Mar 17 02:12:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255987 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=rJh3xQQX; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGsd3VYCz9sPF for ; Tue, 17 Mar 2020 13:12:53 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B55D0818C7; Tue, 17 Mar 2020 03:12:39 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="rJh3xQQX"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0957081915; Tue, 17 Mar 2020 03:12:27 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x441.google.com (mail-pf1-x441.google.com [IPv6:2607:f8b0:4864:20::441]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 0BD4E81915 for ; Tue, 17 Mar 2020 03:12:21 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x441.google.com with SMTP id d25so3031795pfn.6 for ; Mon, 16 Mar 2020 19:12:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GA+p3fZ4j/59RBZM3JsheJYNrmN+Mkjqi5gFXxf8PRQ=; b=rJh3xQQX6Z7PmKOcG6cEvu3oBks2/axvIpfu6anZmdM0/D55MzekoYQ5hjssCwT/SQ kcNNO1PQ5H+fJWsubc9gnVvOno4J08IePFL5GSyXaQ6/uX2KSlejgOK758vE1UywMbvw r9zNBsOJx2fgM07JQPPnqaoL7hybFlWNhr5TnozTO+lfjRpJYF3Rh51j9Q1nguql25q5 UR5F9WkJ+yaTn0aRpqfp4ZP2hBS35amt/i7Z/HBLUKzSwmrrMXJ47TDK0jPPzBownI/D 1I3+SDNBSpjkzsg50k09JEowihLlzZftI0IvDbCHy7CMUaKbnhk5u9JFbPgtsO9Gz7iN Es2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GA+p3fZ4j/59RBZM3JsheJYNrmN+Mkjqi5gFXxf8PRQ=; b=LpkTZi/x0SvTH7RGYwlbE7M0JRsBdb0ZJegtzH0KTIlutBNJuYeKZX+8Zbv8COUwMe k5pmx00HRD0me8j8i8EbhF9vQBbw1yOFJWTihbj2jPBM+XpMryNmvYr/H8wBMzNFS4Vl jKqUZ9o5ZzpjO+mcNf5X8TBlUapbUkXnztI7JsSVo0UjzvKIUup/CorG4v3atxOsAh8A Xgg0gevk2JHqJsmuesZXBJtMFw56ZBHkJqX9s8YNFs8x8GtcqoHMR0/tqPORhSxrr6pp sJUvsJ2vL7jMnKp+ezN8barUfceikvyLFnfXDcjWVFG3m4TRj9BMinv9wzrQJTrC89Jg No5A== X-Gm-Message-State: ANhLgQ1hJINbdDA3vPx2G9n83QdPhnXHFx37u7Qjf5MLyDsIHbn2EDRR Nd1bxZ0uav03Rw3FdHwuHaEDGw== X-Google-Smtp-Source: ADFU+vt7Qj7QYPRbxnDH4OCM0FJHAcv7onIZYMcFme4dOsggC4CNd3Z7mUO4XA6PJOdm9pxCNrO3DQ== X-Received: by 2002:aa7:94a5:: with SMTP id a5mr2735806pfl.67.1584411139552; Mon, 16 Mar 2020 19:12:19 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id x9sm1076796pfa.60.2020.03.16.19.12.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:18 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 02/14] efi_loader: define System Resource Table macros Date: Tue, 17 Mar 2020 11:12:35 +0900 Message-Id: <20200317021247.5849-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean Some of those values will be used in an implementation of UEFI firmware management protocol as part of my capsule update patch. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- include/efi_api.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index 73c0722b0168..a99cc7acc475 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -1627,4 +1627,31 @@ struct efi_unicode_collation_protocol { #define LOAD_OPTION_CATEGORY_BOOT 0x00000000 #define LOAD_OPTION_CATEGORY_APP 0x00000100 +/* + * System Resource Table + */ +/* Firmware Type Definitions */ +#define ESRT_FW_TYPE_UNKNOWN 0x00000000 +#define ESRT_FW_TYPE_SYSTEMFIRMWARE 0x00000001 +#define ESRT_FW_TYPE_DEVICEFIRMWARE 0x00000002 +#define ESRT_FW_TYPE_UEFIDRIVER 0x00000003 + +/* Last Attempt Status Values */ +#define LAST_ATTEMPT_STATUS_SUCCESS 0x00000000 +#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL 0x00000001 +#define LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES 0x00000002 +#define LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION 0x00000003 +#define LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT 0x00000004 +#define LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR 0x00000005 +#define LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_AC 0x00000006 +#define LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT 0x00000007 +#define LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES 0x00000008 + +/* + * The LastAttemptStatus values of 0x1000 - 0x4000 are reserved for vendor + * usage. + */ +#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN 0x00001000 +#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX 0x00004000 + #endif From patchwork Tue Mar 17 02:12:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255992 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=QTOxv+TL; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGt11hMbz9sPF for ; Tue, 17 Mar 2020 13:13:13 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 183D98192E; Tue, 17 Mar 2020 03:12:45 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="QTOxv+TL"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3AAEE81926; Tue, 17 Mar 2020 03:12:32 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1042.google.com (mail-pj1-x1042.google.com [IPv6:2607:f8b0:4864:20::1042]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8E9BE818F8 for ; Tue, 17 Mar 2020 03:12:24 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pj1-x1042.google.com with SMTP id dw20so4606095pjb.0 for ; Mon, 16 Mar 2020 19:12:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=L0eP6sTbgRwJ02SbTyDpW70DKYKrpcpC0+IjXnSyYQg=; b=QTOxv+TLEWGiljIuL3bUu1vyPvs4tsMo5MIglM38V6aq3+4U2a3k4u3fdmHFckZiZt QyafYzbMPeJMBhKKw1WiSVT6LAo9xh5FtyvFf+fA171Q40eWFGVwGSIGf+sRlETpthYY aAWdOq8pqsuBvejD2f5jx9Q3VtOHRTOgFPD3no3921Y3SHFFJaKWydVs3QT0mcDYAolJ MkCboH8J7xoWMwzGarIJrHcfI6Nn39J3s5wT9PVnBDBVJsoklqBYLLDKR4DwkAFRNJva +30a8FxH1sc6TOn3DUxreV6GdCvL3Y9YkWC9r04NoWnYsFg4LYEbAeEHP8TcqcPM6ena Hw0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=L0eP6sTbgRwJ02SbTyDpW70DKYKrpcpC0+IjXnSyYQg=; b=s1jh90SYKuacxz09DwxVQQepiXJSAJdbMUIvZqnyHlc44LRVGg8iP4fmdSET4+y/t5 4qc6nFoj6KOIGxGtWSDer4PLax9NYuH3GABxiH5yjxUc1DYfytyXbqBHNVBqaQ+c4zz1 QOfFm4VKk7BP8HrZ6KlYwITSWb7N9ydyKkV9mzkrsgXs5mZITCwXNvAmWbsqj0im5nWZ YI7uQfhScasWtCI7L2lO3Yeo31oL0WlkSnNPyxZMporCajLuggd53RPUVPuSQ/s8/Dhl 0XtfITxP/+/u5cv8J2mwKjZFMmD/ZU2KcVGi1TjnHbBfmsmHjbj2PyPs7/VVbpOb1HP7 gxJA== X-Gm-Message-State: ANhLgQ10Fm6WLr/PAFxrNo5oK3ihxtGm+sTlA3ZAhaNuSV1xPrQRK0ow pWU1Zm6LO4g9hVg/GLmkEz8hsw== X-Google-Smtp-Source: ADFU+vtRlrxWrc5faDbkAyvPxdzwulroR9meIPtV5dHv6mNGgGoCrOkhSa3XEIvQ9siQ5gYycJIDVg== X-Received: by 2002:a17:902:bccc:: with SMTP id o12mr1973896pls.96.1584411142937; Mon, 16 Mar 2020 19:12:22 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id i2sm901035pjs.21.2020.03.16.19.12.22 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:22 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 03/14] efi_loader: export a couple of protocol related functions Date: Tue, 17 Mar 2020 11:12:36 +0900 Message-Id: <20200317021247.5849-4-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean This is a preparatory patch. Those functions will be used in an implementation of UEFI firmware management protocol as part of my capsule update patch. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- include/efi_loader.h | 14 ++++++++++++++ lib/efi_loader/efi_boottime.c | 16 ++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index d4c59b54c48b..c55bade6a508 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -456,6 +456,20 @@ efi_status_t efi_remove_all_protocols(const efi_handle_t handle); /* Install multiple protocol interfaces */ efi_status_t EFIAPI efi_install_multiple_protocol_interfaces (efi_handle_t *handle, ...); +/* Get handles that support a given protocol */ +efi_status_t EFIAPI efi_locate_handle_buffer( + enum efi_locate_search_type search_type, + const efi_guid_t *protocol, void *search_key, + efi_uintn_t *no_handles, efi_handle_t **buffer); +/* Close an previously opened protocol interface */ +efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle, + const efi_guid_t *protocol, + efi_handle_t agent_handle, + efi_handle_t controller_handle); +/* Open a protocol interface */ +efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle, + const efi_guid_t *protocol, + void **protocol_interface); /* Call this to create an event */ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, void (EFIAPI *notify_function) ( diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 1f598b357a5c..9860d5047502 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2106,10 +2106,10 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, * * Return: status code */ -static efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle, - const efi_guid_t *protocol, - efi_handle_t agent_handle, - efi_handle_t controller_handle) +efi_status_t EFIAPI efi_close_protocol(efi_handle_t handle, + const efi_guid_t *protocol, + efi_handle_t agent_handle, + efi_handle_t controller_handle) { struct efi_handler *handler; struct efi_open_protocol_info_item *item; @@ -2282,7 +2282,7 @@ static efi_status_t EFIAPI efi_protocols_per_handle( * * Return: status code */ -static efi_status_t EFIAPI efi_locate_handle_buffer( +efi_status_t EFIAPI efi_locate_handle_buffer( enum efi_locate_search_type search_type, const efi_guid_t *protocol, void *search_key, efi_uintn_t *no_handles, efi_handle_t **buffer) @@ -3182,9 +3182,9 @@ out: * * Return: status code */ -static efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle, - const efi_guid_t *protocol, - void **protocol_interface) +efi_status_t EFIAPI efi_handle_protocol(efi_handle_t handle, + const efi_guid_t *protocol, + void **protocol_interface) { return efi_open_protocol(handle, protocol, protocol_interface, efi_root, NULL, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); From patchwork Tue Mar 17 02:12:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255993 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=m6OALdoq; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGt65N82z9sPF for ; Tue, 17 Mar 2020 13:13:18 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D372C8192F; Tue, 17 Mar 2020 03:12:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="m6OALdoq"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 24BA781917; Tue, 17 Mar 2020 03:12:36 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1044.google.com (mail-pj1-x1044.google.com [IPv6:2607:f8b0:4864:20::1044]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7A8908191C for ; Tue, 17 Mar 2020 03:12:28 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pj1-x1044.google.com with SMTP id ca13so9701195pjb.2 for ; Mon, 16 Mar 2020 19:12:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6PvnheeH6nyEVU4YceyrQ5NWHtjwVcWzmcgRgpDTDN0=; b=m6OALdoq5IZV2kZHV7YmrRF/cpG4tOXZdS3Rm+A4Xu1zLrMHUPJ28ssWLnAo0Od9CH eiDXYAkblv+8aWLLX4a1si58rwfsOwrA9GDSmAic6j7rhkZ7YQZ5miarHdVrIdY+BScK oQC7rceyU3IhVZzbR+rC8GHQaPfWNJ8FXiunlzprwlImOlTAjLsJr2x0XW/r3CEHpZO+ La6b/oKoTVXbRHYX8zpeR3Z+Q0pOT2yYFr8LthLh0NZ7I3ZSyg0A4YWlKtIuEM21kCpO kKZSh+Ad/b8SyweXaOVx8JRUexAdcBHZXR6rpGzpx8K2YdC13fiIhx53ZTNZsEnZQMYw xaow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6PvnheeH6nyEVU4YceyrQ5NWHtjwVcWzmcgRgpDTDN0=; b=gt7QuRBEcbestDrdI39kdWZzZE1cjKqz1XXkTvkUGgj74l38Cb4ANg/zKFoY7ncy8w uf6Ckmz//PU7bgDLVvhTZuptUEfY9UFxO3AtRjMiTF5kKCaQFVGXkYAwXnyO9xLlIlTd OtmKgW6asSq7iB/iGn/b3XFTXQMqEti3g9iLGn6Qwhc4K/ynoLd1zwzQL1t2KET5gIN5 ekLvGLgXE5dX0Aud4wR0M4M4CK95L/+aV7BKCdcCGBeGx9Vsp8+Hob4602iztEPWOvfF uerZ1Fo03xax48YzPWLGQUaEgC4YD+GIHW/fAD0MIiOXZCbMEa1H+OMcpq6qAmPnLcYI VOGw== X-Gm-Message-State: ANhLgQ32UsgtO0JtwrLEUCHWJkqlporkaamJitE825OBITqYzDoBVdv/ g4eCtAjrbQjum3yZEsgoT8JsZg== X-Google-Smtp-Source: ADFU+vsOQcV3C7sjTif+diqCKvXMxLR7WbegjbBNI4OglDj/Eha02z6FUEWqbdnQ7yNQncA0tfbbVg== X-Received: by 2002:a17:90a:33e5:: with SMTP id n92mr2642954pjb.39.1584411146348; Mon, 16 Mar 2020 19:12:26 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id 134sm1134842pfy.27.2020.03.16.19.12.25 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:25 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 04/14] efi_loader: correct a definition of struct efi_capsule_header Date: Tue, 17 Mar 2020 11:12:37 +0900 Message-Id: <20200317021247.5849-5-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean See UEFI specification, section 8.5.3. In addition, the structure, efi_capsule_header, should be "packed" as it is a serialized binary format in a capsule file. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- include/efi_api.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index a99cc7acc475..4040c44855fa 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -218,11 +218,11 @@ enum efi_reset_type { #define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 struct efi_capsule_header { - efi_guid_t *capsule_guid; + efi_guid_t capsule_guid; u32 header_size; u32 flags; u32 capsule_image_size; -}; +} __packed; #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 From patchwork Tue Mar 17 02:12:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255994 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=uta2y9je; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGtL2MVsz9sPF for ; Tue, 17 Mar 2020 13:13:30 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0930881947; Tue, 17 Mar 2020 03:12:59 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="uta2y9je"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A7ED681935; Tue, 17 Mar 2020 03:12:41 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1043.google.com (mail-pj1-x1043.google.com [IPv6:2607:f8b0:4864:20::1043]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 5B2058192C for ; Tue, 17 Mar 2020 03:12:31 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pj1-x1043.google.com with SMTP id dw20so4606188pjb.0 for ; Mon, 16 Mar 2020 19:12:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1OgAQC4r9pmJBNesafp+RUof0paFwgy103JfG1bfffc=; b=uta2y9je31f64On+QREKiuoJXJqm13FaiwoHmU4KLjLk0slYL0XvWU/dsY0YqYfai1 LC2tNIQjkVEOOkXtRPv8qjLTTFyU8DMD7A1bzBqLFFx/ato9RekqdbTuu9aBXOQWNU0E PKb43IrWD4WElANETZPD5F79r7tP8vMX8leKIWOif3/joMI2K1Ef3nXsHS6ZPQblk5aP V1oApxR40iR+fxjKvIGFjK+McZpcYclvLi2Tpja/hK/HAne+vLc99XAbmnVhNi2PtsIX Oyxdv/jW5fUcS082p/TD1AsBTtriuqOQL6OK0cJgs6s2SYpCONaWLQ+KBM/MPiIaTkjT GYsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1OgAQC4r9pmJBNesafp+RUof0paFwgy103JfG1bfffc=; b=lJNBMDq0BkBONzq53ih7wM3B5Gf39ucf1oR1AaD0xMCDpUc1kRDSiZEj8IiHVWxitY T0jRnSKgbMEHLUH4Cl4RwoyPuSHiNO6qVJZiKM6INBbLUAMeONZm0EDWj0jmOvQjYYbN lAoy2+LFkdDbCnbD/u/PSElU4ZnhX9ppLH0BFRWW0hRwfPQ8Y5FPJ4WZEFpRRWJ1Kccs anXnfF0kBd5avMvB5zz8j1TJyc4PQyaKblAhaeMNppXn6YVmwArCE/A8Kgf3TL8CSTEs dBmq5CFB7Igl5iRJL463fiPdIzn4dMzLkqtZT3QQKRSy0VhV0AxeyzedzfhcnN+Zhl3N F3qQ== X-Gm-Message-State: ANhLgQ27CgjuXnaNsbAfyVMEIMjEgPegEw0sxnQEZGug+KQryNzM7oAU SRXw2XenAokUL4I8yxW6R+ZI0UcHQ7U= X-Google-Smtp-Source: ADFU+vvzAuAOlRZpzhx2S8V2dFhMrXf5kjMQ9mdiXNmdMb5xopm8E1DUm004XbgQZNrBXCj43ldKzQ== X-Received: by 2002:a17:902:7c15:: with SMTP id x21mr2057522pll.67.1584411149634; Mon, 16 Mar 2020 19:12:29 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id q12sm1057147pfh.158.2020.03.16.19.12.28 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:29 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 05/14] efi_loader: define UpdateCapsule api Date: Tue, 17 Mar 2020 11:12:38 +0900 Message-Id: <20200317021247.5849-6-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean In this commit, skeleton functions for capsule-related API's are added under CONFIG_EFI_CAPSULE_UPDATE configuration. Detailed implementation will be added in the succeeding patches. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 12 ++++ include/efi_loader.h | 11 ++++ lib/efi_loader/Kconfig | 7 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_capsule.c | 98 +++++++++++++++++++++++++++++++++ lib/efi_loader/efi_runtime.c | 104 ++++++++++++++++++++--------------- lib/efi_loader/efi_setup.c | 31 ++++++++--- 7 files changed, 213 insertions(+), 51 deletions(-) create mode 100644 lib/efi_loader/efi_capsule.c diff --git a/include/efi_api.h b/include/efi_api.h index 4040c44855fa..ac2b38801c0c 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -217,6 +217,10 @@ enum efi_reset_type { #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 #define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 +#define EFI_CAPSULE_REPORT_GUID \ + EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \ + 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3) + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; @@ -224,6 +228,14 @@ struct efi_capsule_header { u32 capsule_image_size; } __packed; +struct efi_capsule_result_variable_header { + u32 variable_total_size; + u32 reserved; + efi_guid_t capsule_guid; + struct efi_time capsule_processed; + efi_status_t capsule_status; +} __packed; + #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 diff --git a/include/efi_loader.h b/include/efi_loader.h index c55bade6a508..c3cb7735bf50 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -679,6 +679,17 @@ void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data); unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data); efi_status_t efi_bootmgr_load(efi_handle_t *handle); +/* Capsule update */ +efi_status_t EFIAPI efi_update_capsule( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list); +efi_status_t EFIAPI efi_query_capsule_caps( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type); + #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index a7afa3f29e88..2ef6cb124f3a 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -90,6 +90,13 @@ config EFI_UNICODE_COLLATION_PROTOCOL endif +config EFI_CAPSULE_UPDATE + bool "Enable capsule update support" + default n + help + Select this option if you want to use capsule update feature, + including firmware updates and variable updates. + config EFI_LOADER_BOUNCE_BUFFER bool "EFI Applications use bounce buffers for DMA operations" depends on ARM64 diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 04dc8648512b..f19096924bef 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -22,6 +22,7 @@ endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_bootmgr.o obj-y += efi_boottime.o +obj-$(CONFIG_EFI_CAPSULE_UPDATE) += efi_capsule.o obj-y += efi_console.o obj-y += efi_device_path.o obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c new file mode 100644 index 000000000000..d3f931910d10 --- /dev/null +++ b/lib/efi_loader/efi_capsule.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI Capsule + * + * Copyright (c) 2018 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include + +/* + * Launch a capsule + */ +/** + * efi_update_capsule() - process information from operating system + * + * This function implements the UpdateCapsule() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @scatter_gather_list: pointer to arry of physical pointers + * Return: status code + */ +efi_status_t EFIAPI efi_update_capsule( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list) +{ + struct efi_capsule_header *capsule; + unsigned int i; + efi_status_t ret; + + EFI_ENTRY("%p, %lu, %llu\n", capsule_header_array, capsule_count, + scatter_gather_list); + + if (!capsule_count) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + ret = EFI_SUCCESS; + for (i = 0, capsule = *capsule_header_array; i < capsule_count; + i++, capsule = *(++capsule_header_array)) { + } +out: + return EFI_EXIT(ret); +} + +/** + * efi_query_capsule_caps() - check if capsule is supported + * + * This function implements the QueryCapsuleCapabilities() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @maximum_capsule_size: maximum capsule size + * @reset_type: type of reset needed for capsule update + * Return: status code + */ +efi_status_t EFIAPI efi_query_capsule_caps( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type) +{ + struct efi_capsule_header *capsule __attribute__((unused)); + unsigned int i; + efi_status_t ret; + + EFI_ENTRY("%p, %lu, %p, %p\n", capsule_header_array, capsule_count, + maximum_capsule_size, reset_type); + + if (!maximum_capsule_size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + *maximum_capsule_size = U64_MAX; + *reset_type = EFI_RESET_COLD; + + ret = EFI_SUCCESS; + for (i = 0, capsule = *capsule_header_array; i < capsule_count; + i++, capsule = *(++capsule_header_array)) { + /* TODO */ + } +out: + return EFI_EXIT(ret); +} diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 4b3c843b2ced..1dce8d06abdb 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -107,6 +107,11 @@ efi_status_t efi_init_runtime_supported(void) #ifdef CONFIG_EFI_HAVE_RUNTIME_RESET efi_runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM; #endif +#ifdef CONFIG_EFI_CAPSULE_UPDATE + efi_runtime_services_supported |= + (EFI_RT_SUPPORTED_UPDATE_CAPSULE | + EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES); +#endif return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported", &efi_global_variable_guid, @@ -390,6 +395,50 @@ efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time) return EFI_UNSUPPORTED; } +/** + * efi_update_capsule_unsupported() - process information from operating system + * + * This function implements the UpdateCapsule() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @scatter_gather_list: pointer to arry of physical pointers + * Returns: status code + */ +efi_status_t __efi_runtime EFIAPI efi_update_capsule_unsupported( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list) +{ + return EFI_UNSUPPORTED; +} + +/** + * efi_query_capsule_caps_unsupported() - check if capsule is supported + * + * This function implements the QueryCapsuleCapabilities() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @maximum_capsule_size: maximum capsule size + * @reset_type: type of reset needed for capsule update + * Returns: status code + */ +efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps_unsupported( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type) +{ + return EFI_UNSUPPORTED; +} + /** * efi_is_runtime_service_pointer() - check if pointer points to runtime table * @@ -413,6 +462,12 @@ void efi_runtime_detach(void) efi_runtime_services.reset_system = efi_reset_system; efi_runtime_services.get_time = efi_get_time; efi_runtime_services.set_time = efi_set_time; +#ifdef CONFIG_EFI_CAPSULE_UPDATE + /* won't support at runtime */ + efi_runtime_services.update_capsule = efi_update_capsule_unsupported; + efi_runtime_services.query_capsule_caps = + efi_query_capsule_caps_unsupported; +#endif /* Update CRC32 */ efi_update_table_header_crc32(&efi_runtime_services.hdr); @@ -817,50 +872,6 @@ static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void) return EFI_UNSUPPORTED; } -/** - * efi_update_capsule() - process information from operating system - * - * This function implements the UpdateCapsule() runtime service. - * - * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. - * - * @capsule_header_array: pointer to array of virtual pointers - * @capsule_count: number of pointers in capsule_header_array - * @scatter_gather_list: pointer to arry of physical pointers - * Returns: status code - */ -efi_status_t __efi_runtime EFIAPI efi_update_capsule( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 scatter_gather_list) -{ - return EFI_UNSUPPORTED; -} - -/** - * efi_query_capsule_caps() - check if capsule is supported - * - * This function implements the QueryCapsuleCapabilities() runtime service. - * - * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. - * - * @capsule_header_array: pointer to array of virtual pointers - * @capsule_count: number of pointers in capsule_header_array - * @maximum_capsule_size: maximum capsule size - * @reset_type: type of reset needed for capsule update - * Returns: status code - */ -efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 *maximum_capsule_size, - u32 *reset_type) -{ - return EFI_UNSUPPORTED; -} - struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .hdr = { .signature = EFI_RUNTIME_SERVICES_SIGNATURE, @@ -878,7 +889,12 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .set_variable = efi_set_variable, .get_next_high_mono_count = (void *)&efi_unimplemented, .reset_system = &efi_reset_system_boottime, +#ifdef CONFIG_EFI_CAPSULE_UPDATE .update_capsule = efi_update_capsule, .query_capsule_caps = efi_query_capsule_caps, +#else + .update_capsule = efi_update_capsule_unsupported, + .query_capsule_caps = efi_query_capsule_caps_unsupported, +#endif .query_variable_info = efi_query_variable_info, }; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index de7b616c6daa..c485cad34022 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -82,6 +82,29 @@ out: return ret; } +/** + * efi_init_os_indications() - indicate supported features for OS requests + * + * Set the OsIndicationsSupported variable. + * + * Return: status code + */ +static efi_status_t efi_init_os_indications(void) +{ + u64 os_indications_supported = 0; + +#ifdef CONFIG_EFI_CAPSULE_UPDATE + os_indications_supported |= + EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED; +#endif + return EFI_CALL(efi_set_variable(L"OsIndicationsSupported", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(os_indications_supported), + &os_indications_supported)); +} + /** * efi_init_obj_list() - Initialize and populate EFI object list * @@ -89,7 +112,6 @@ out: */ efi_status_t efi_init_obj_list(void) { - u64 os_indications_supported = 0; /* None */ efi_status_t ret = EFI_SUCCESS; /* Initialize once only */ @@ -113,12 +135,7 @@ efi_status_t efi_init_obj_list(void) goto out; /* Indicate supported features */ - ret = EFI_CALL(efi_set_variable(L"OsIndicationsSupported", - &efi_global_variable_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - sizeof(os_indications_supported), - &os_indications_supported)); + ret = efi_init_os_indications(); if (ret != EFI_SUCCESS) goto out; From patchwork Tue Mar 17 02:12:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255996 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=wtF8j4pE; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGtr0qwWz9sPF for ; Tue, 17 Mar 2020 13:13:56 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 44F6681925; Tue, 17 Mar 2020 03:13:11 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="wtF8j4pE"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AFE2A8192C; Tue, 17 Mar 2020 03:12:51 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id BE0D781915 for ; Tue, 17 Mar 2020 03:12:34 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pj1-x1036.google.com with SMTP id d8so9688862pje.4 for ; Mon, 16 Mar 2020 19:12:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bvioGlfCRenJs79O4CujlxRtGogUa/MgwTHhUlRcAXc=; b=wtF8j4pEJ0RJwJDFgi7Dv9KNC2X/3CKTGHpM4tKvWly50i3qqgRyUEwnUI8ABdEqkV HwOjGF7PWPGs36zy0bk91W+hAnHQ6QnFBGgBHUYTLNMVX0V4WwAwyFM9HOE2Q01cuqoS tDVQs0e/OTMJuR3w8BKVxvWWNmWkbXrADLB87lh49i9vRFIu/WkKUDlisFjZyl1HaVqU ucdRtSwFiLld9S9Ty885/X1bTDHMGaOd1xabXSBsWKXh+5iFdk/GFFuNgxjWT/Zu8weJ i9BXJ8aqJJI9lD6xQrdOEZdtRFul/ZcUsfI7+QAudEQ+xW7rDLXZPL4xC1m2j3mYU2LA koKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bvioGlfCRenJs79O4CujlxRtGogUa/MgwTHhUlRcAXc=; b=JbVoaRMIbMdMUOZEHtTRuS0yfcKprk3WyMTzGcugTTG36NXKBAK6swOiRBKMEt7cwF Vb1Wo+Liq6i6RLo0OsV2rQ6us6S6WiouR7nGQ0O02Z6KdoctD1HdvySmCLAlD+tBVIgs LkQEqjFGlxFv502OLk7IWdJXWFHphUX9Tr0avXLXSg6aKiqQXACwgFesRMQXEswGY+EJ aZEFz+shYVqyidNle8y8RpFQcady7Efyfy8DBMq7aB3YHPC5Hx2ez0ot5FK/ZRgSgxZ+ oBAo1S5ilan9wCBv+DXSRQmBXb78U3OYpdIs8qCM6roTKadpo3nb5E6zVmaCm2ATPz1M hNOw== X-Gm-Message-State: ANhLgQ0HUbzhWOREv2PU7UBYVQGcBVHHTpatlkIlsTdLGzYtSwe+AqEh CVWlFdryF64TKqjq5hiEYCkPSw== X-Google-Smtp-Source: ADFU+vvJ2IInoaJypTsJtQrF5uins7bWmrRE97bF8Addj060Iv5WxTEPAS5a9LBQJa+DdQnrbVB0CA== X-Received: by 2002:a17:90a:e38a:: with SMTP id b10mr2720044pjz.137.1584411152922; Mon, 16 Mar 2020 19:12:32 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id w206sm1184872pfc.54.2020.03.16.19.12.31 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:32 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 06/14] efi_loader: capsule: add capsule_on_disk support Date: Tue, 17 Mar 2020 11:12:39 +0900 Message-Id: <20200317021247.5849-7-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean Capsule data can be loaded into the system either via UpdateCapsule runtime service or files on a file system (of boot device). The latter case is called "capsules on disk", and actual updates will take place at the next boot time. In this commit, we will support capsule on disk mechanism. Please note that U-Boot itself has no notion of "boot device" and all the capsule files to be executed will be identified only if they are located in a specific directory on a device that is determined by "BootXXXX" variables. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 18 ++ lib/efi_loader/Kconfig | 7 + lib/efi_loader/efi_boottime.c | 3 + lib/efi_loader/efi_capsule.c | 548 ++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_setup.c | 6 + 5 files changed, 582 insertions(+) diff --git a/include/efi_loader.h b/include/efi_loader.h index c3cb7735bf50..c701672e18db 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -178,6 +178,8 @@ extern const efi_guid_t efi_guid_hii_config_routing_protocol; extern const efi_guid_t efi_guid_hii_config_access_protocol; extern const efi_guid_t efi_guid_hii_database_protocol; extern const efi_guid_t efi_guid_hii_string_protocol; +/* GUID of capsule update result */ +extern const efi_guid_t efi_guid_capsule_report; /* GUID of RNG protocol */ extern const efi_guid_t efi_guid_rng_protocol; @@ -690,6 +692,22 @@ efi_status_t EFIAPI efi_query_capsule_caps( u64 *maximum_capsule_size, u32 *reset_type); +#ifdef CONFIG_EFI_CAPSULE_ON_DISK +#define EFI_CAPSULE_DIR L"\\EFI\\UpdateCapsule\\" + +/* Hook at initialization */ +efi_status_t efi_launch_capsules(void); +/* Notify ExitBootServices() is called */ +void efi_capsule_boot_exit_notify(void); +#else +static inline efi_status_t efi_launch_capsules(void) +{ + return EFI_SUCCESS; +} + +static inline efi_capsule_boot_exit_notify(void) {} +#endif /* CONFIG_EFI_CAPSULE_ON_DISK */ + #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 2ef6cb124f3a..95e10f7d981b 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -97,6 +97,13 @@ config EFI_CAPSULE_UPDATE Select this option if you want to use capsule update feature, including firmware updates and variable updates. +config EFI_CAPSULE_ON_DISK + bool "Enable capsule-on-disk support" + depends on EFI_CAPSULE_UPDATE + default n + help + Select this option if you want to use capsule-on-disk feature. + config EFI_LOADER_BOUNCE_BUFFER bool "EFI Applications use bounce buffers for DMA operations" depends on ARM64 diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 9860d5047502..c2a789b4f910 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1981,6 +1981,9 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, /* Notify variable services */ efi_variables_boot_exit_notify(); + /* Notify capsule services */ + efi_capsule_boot_exit_notify(); + /* Remove all events except EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE */ list_for_each_entry_safe(evt, next_event, &efi_events, link) { if (evt->type != EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index d3f931910d10..f3e2a555a6b9 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -10,8 +10,14 @@ #include #include #include +#include #include +const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; + +/* for file system access */ +static struct efi_file_handle *bootdev_root; + /* * Launch a capsule */ @@ -96,3 +102,545 @@ efi_status_t EFIAPI efi_query_capsule_caps( out: return EFI_EXIT(ret); } + +#ifdef CONFIG_EFI_CAPSULE_ON_DISK +static void efi_capsule_result_variable(int num, + struct efi_capsule_header *capsule, + efi_status_t return_status) +{ + char variable_name[12]; + u16 variable_name16[12], *p; + struct efi_capsule_result_variable_header result; + struct efi_time time; + efi_status_t ret; + + sprintf(variable_name, "Capsule%04X", num); + p = variable_name16; + utf8_utf16_strncpy(&p, variable_name, 11); + result.variable_total_size = sizeof(result); + result.capsule_guid = capsule->capsule_guid; + ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL)); + if (ret == EFI_SUCCESS) + memcpy(&result.capsule_processed, &time, sizeof(time)); + else + memset(&result.capsule_processed, 0, sizeof(time)); + result.capsule_status = return_status; + ret = EFI_CALL(efi_set_variable(variable_name16, + &efi_guid_capsule_report, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(result), &result)); + if (ret) + EFI_PRINT("EFI Capsule: creating %s failed\n", variable_name); +} + +static efi_status_t get_dp_device(u16 *boot_var, + struct efi_device_path **device_dp) +{ + void *buf = NULL; + efi_uintn_t size; + struct efi_load_option lo; + struct efi_device_path *file_dp; + efi_status_t ret; + + size = 0; + ret = EFI_CALL(efi_get_variable(boot_var, &efi_global_variable_guid, + NULL, &size, NULL)); + if (ret == EFI_BUFFER_TOO_SMALL) { + buf = malloc(size); + if (!buf) + return EFI_OUT_OF_RESOURCES; + ret = EFI_CALL(efi_get_variable(boot_var, + &efi_global_variable_guid, + NULL, &size, buf)); + } + if (ret != EFI_SUCCESS) + return ret; + + efi_deserialize_load_option(&lo, buf); + + if (lo.attributes & LOAD_OPTION_ACTIVE) { + efi_dp_split_file_path(lo.file_path, device_dp, &file_dp); + efi_free_pool(file_dp); + + ret = EFI_SUCCESS; + } else { + ret = EFI_NOT_FOUND; + } + + free(buf); + + return ret; +} + +static bool device_is_present(struct efi_device_path *dp) +{ + efi_handle_t handle; + struct efi_handler *handler; + efi_status_t ret; + + handle = efi_dp_find_obj(dp, NULL); + if (!handle) + return false; + + /* check if this is a block device */ + ret = efi_search_protocol(handle, &efi_block_io_guid, &handler); + if (ret != EFI_SUCCESS) + return false; + + return true; +} + +static efi_status_t find_boot_device(void) +{ + char boot_var[9]; + u16 boot_var16[9], *p, bootnext, *boot_order = NULL; + efi_uintn_t size; + int i, num; + struct efi_simple_file_system_protocol *volume; + struct efi_device_path *boot_dev = NULL; + efi_status_t ret; + + /* find active boot device in BootNext */ + bootnext = 0; + size = sizeof(bootnext); + ret = EFI_CALL(efi_get_variable(L"BootNext", + (efi_guid_t *)&efi_global_variable_guid, + NULL, &size, &bootnext)); + if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) { + /* BootNext does exist here */ + if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) { + printf("BootNext must be 16-bit integer\n"); + goto skip; + } + sprintf((char *)boot_var, "Boot%04X", bootnext); + p = boot_var16; + utf8_utf16_strcpy(&p, boot_var); + + ret = get_dp_device(boot_var16, &boot_dev); + if (ret == EFI_SUCCESS) { + if (device_is_present(boot_dev)) { + goto out; + } else { + efi_free_pool(boot_dev); + boot_dev = NULL; + } + } + } + +skip: + /* find active boot device in BootOrder */ + size = 0; + ret = EFI_CALL(efi_get_variable(L"BootOrder", &efi_global_variable_guid, + NULL, &size, NULL)); + if (ret == EFI_BUFFER_TOO_SMALL) { + boot_order = malloc(size); + if (!boot_order) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + ret = EFI_CALL(efi_get_variable( + L"BootOrder", &efi_global_variable_guid, + NULL, &size, boot_order)); + } + if (ret != EFI_SUCCESS) + goto out; + + /* check in higher order */ + num = size / sizeof(u16); + for (i = 0; i < num; i++) { + sprintf((char *)boot_var, "Boot%04X", boot_order[i]); + p = boot_var16; + utf8_utf16_strcpy(&p, boot_var); + ret = get_dp_device(boot_var16, &boot_dev); + if (ret != EFI_SUCCESS) + continue; + + if (device_is_present(boot_dev)) + break; + + efi_free_pool(boot_dev); + boot_dev = NULL; + } +out: + if (boot_dev) { + u16 *path_str; + + path_str = efi_dp_str(boot_dev); + EFI_PRINT("EFI Capsule: bootdev is %ls\n", path_str); + efi_free_pool(path_str); + + volume = efi_fs_from_path(boot_dev); + if (!volume) + ret = EFI_DEVICE_ERROR; + else + ret = EFI_CALL(volume->open_volume(volume, + &bootdev_root)); + efi_free_pool(boot_dev); + } else { + ret = EFI_NOT_FOUND; + } + free(boot_order); + + return ret; +} + +/* + * Traverse a capsule directory in boot device + * Called by initialization code, and returns an array of capsule file + * names in @files + */ +static efi_status_t efi_capsule_scan_dir(u16 ***files, int *num) +{ + struct efi_file_handle *dirh; + struct efi_file_info *dirent; + efi_uintn_t dirent_size, tmp_size; + int count; + u16 **tmp_files; + efi_status_t ret; + + ret = find_boot_device(); + if (ret == EFI_NOT_FOUND) { + EFI_PRINT("EFI Capsule: bootdev is not set\n"); + *num = 0; + return EFI_SUCCESS; + } else if (ret != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + /* count capsule files */ + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh, + EFI_CAPSULE_DIR, + EFI_FILE_MODE_READ, 0)); + if (ret != EFI_SUCCESS) { + *num = 0; + return EFI_SUCCESS; + } + + dirent_size = 256; + dirent = malloc(dirent_size); + if (!dirent) + return EFI_OUT_OF_RESOURCES; + + count = 0; + while (1) { + tmp_size = dirent_size; + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent)); + if (ret == EFI_BUFFER_TOO_SMALL) { + dirent = realloc(dirent, tmp_size); + if (!dirent) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + dirent_size = tmp_size; + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent)); + } + if (ret != EFI_SUCCESS) + goto err; + if (!tmp_size) + break; + + if (!(dirent->attribute & EFI_FILE_DIRECTORY) && + u16_strcmp(dirent->file_name, L".") && + u16_strcmp(dirent->file_name, L"..")) + count++; + } + + ret = EFI_CALL((*dirh->setpos)(dirh, 0)); + if (ret != EFI_SUCCESS) + goto err; + + /* make a list */ + tmp_files = malloc(count * sizeof(*files)); + if (!tmp_files) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + + count = 0; + while (1) { + tmp_size = dirent_size; + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent)); + if (ret != EFI_SUCCESS) + goto err; + if (!tmp_size) + break; + + if (!(dirent->attribute & EFI_FILE_DIRECTORY) && + u16_strcmp(dirent->file_name, L".") && + u16_strcmp(dirent->file_name, L"..")) + tmp_files[count++] = u16_strdup(dirent->file_name); + } + /* ignore an error */ + EFI_CALL((*dirh->close)(dirh)); + + /* in ascii order */ + /* FIXME: u16 version of strcasecmp */ + qsort(tmp_files, count, sizeof(*tmp_files), + (int (*)(const void *, const void *))strcasecmp); + *files = tmp_files; + *num = count; + ret = EFI_SUCCESS; +err: + free(dirent); + + return ret; +} + +/* + * Read in a capsule file + */ +static efi_status_t efi_capsule_read_file(u16 *filename, + struct efi_capsule_header **capsule) +{ + struct efi_file_handle *dirh, *fh; + struct efi_file_info *file_info = NULL; + struct efi_capsule_header *buf = NULL; + efi_uintn_t size; + efi_status_t ret; + + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh, + EFI_CAPSULE_DIR, + EFI_FILE_MODE_READ, 0)); + if (ret != EFI_SUCCESS) + return ret; + ret = EFI_CALL((*dirh->open)(dirh, &fh, filename, + EFI_FILE_MODE_READ, 0)); + /* ignore an error */ + EFI_CALL((*dirh->close)(dirh)); + if (ret != EFI_SUCCESS) + return ret; + + /* file size */ + size = 0; + ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid, + &size, file_info)); + if (ret == EFI_BUFFER_TOO_SMALL) { + file_info = malloc(size); + if (!file_info) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid, + &size, file_info)); + } + if (ret != EFI_SUCCESS) + goto err; + size = file_info->file_size; + free(file_info); + buf = malloc(size); + if (!buf) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + + /* fetch data */ + ret = EFI_CALL((*fh->read)(fh, &size, buf)); + if (ret == EFI_SUCCESS) { + if (size >= buf->capsule_image_size) { + *capsule = buf; + } else { + free(buf); + ret = EFI_INVALID_PARAMETER; + } + } else { + free(buf); + } +err: + EFI_CALL((*fh->close)(fh)); + + return ret; +} + +static efi_status_t efi_capsule_delete_file(u16 *filename) +{ + struct efi_file_handle *dirh, *fh; + efi_status_t ret; + + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh, + EFI_CAPSULE_DIR, + EFI_FILE_MODE_READ, 0)); + if (ret != EFI_SUCCESS) + return ret; + ret = EFI_CALL((*dirh->open)(dirh, &fh, filename, + EFI_FILE_MODE_READ, 0)); + /* ignore an error */ + EFI_CALL((*dirh->close)(dirh)); + + ret = EFI_CALL((*fh->delete)(fh)); + + return ret; +} + +static void efi_capsule_scan_done(void) +{ + EFI_CALL((*bootdev_root->close)(bootdev_root)); + bootdev_root = NULL; +} + +efi_status_t __weak arch_efi_load_capsule_drivers(void) +{ + return EFI_SUCCESS; +} + +static int get_last_capsule(void) +{ + u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */ + char value[11], *p; + efi_uintn_t size; + unsigned long num = 0xffff; + efi_status_t ret; + + size = sizeof(value16); + ret = EFI_CALL(efi_get_variable(L"CapsuleLast", + &efi_guid_capsule_report, + NULL, &size, value16)); + if (ret != EFI_SUCCESS || u16_strncmp(value16, L"Capsule", 7)) + goto err; + + p = value; + utf16_utf8_strcpy(&p, value16); + strict_strtoul(&value[7], 16, &num); +err: + return (int)num; +} + +/* + * Launch all the capsules in system at boot time + * + * Called by efi init code + */ +efi_status_t efi_launch_capsules(void) +{ + struct efi_capsule_header *capsule = NULL; + u16 **files; + int nfiles, num, i; + char variable_name[12]; + u16 variable_name16[12], *p; + efi_status_t ret; + + num = get_last_capsule(); + + /* Load capsule drivers */ + ret = arch_efi_load_capsule_drivers(); + if (ret != EFI_SUCCESS) + return ret; + + /* + * Find capsules on disk. + * All the capsules are collected at the beginning because + * capsule files will be removed instantly. + */ + nfiles = 0; + files = NULL; + ret = efi_capsule_scan_dir(&files, &nfiles); + if (ret != EFI_SUCCESS) + return ret; + if (!nfiles) + return EFI_SUCCESS; + + /* Launch capsules */ + for (i = 0, ++num; i < nfiles; i++, num++) { + EFI_PRINT("EFI Capsule from %ls ...\n", files[i]); + if (num > 0xffff) + num = 0; + ret = efi_capsule_read_file(files[i], &capsule); + if (ret == EFI_SUCCESS) { + ret = EFI_CALL(efi_update_capsule(&capsule, 1, 0)); + if (ret != EFI_SUCCESS) + EFI_PRINT("EFI Capsule update failed at %ls\n", + files[i]); + + free(capsule); + } else { + EFI_PRINT("EFI Capsule read failed\n"); + } + /* create CapsuleXXXX */ + efi_capsule_result_variable(num, capsule, ret); + + /* delete a capsule either in case of success or failure */ + ret = efi_capsule_delete_file(files[i]); + if (ret != EFI_SUCCESS) + EFI_PRINT("EFI Capsule deletion of capsule failed at %ls\n", + files[i]); + } + efi_capsule_scan_done(); + + for (i = 0; i < nfiles; i++) + free(files[i]); + free(files); + + /* CapsuleMax */ + p = variable_name16; + utf8_utf16_strncpy(&p, "CapsuleFFFF", 11); + EFI_CALL(efi_set_variable(L"CapsuleMax", &efi_guid_capsule_report, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + 22, variable_name16)); + + /* CapsuleLast */ + sprintf(variable_name, "Capsule%04X", num - 1); + p = variable_name16; + utf8_utf16_strncpy(&p, variable_name, 11); + EFI_CALL(efi_set_variable(L"CapsuleLast", &efi_guid_capsule_report, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + 22, variable_name16)); + + return ret; +} + +/* + * Dummy functions after ExitBootServices() + */ +efi_status_t EFIAPI efi_update_capsule_runtime( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list) +{ + return EFI_UNSUPPORTED; +} + +efi_status_t EFIAPI efi_query_capsule_caps_runtime( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type) +{ + return EFI_UNSUPPORTED; +} + +/** + * efi_capsule_boot_exit_notify() - notify ExitBootServices() is called + */ +void efi_capsule_boot_exit_notify(void) +{ + efi_runtime_services.update_capsule = efi_update_capsule_runtime; + efi_runtime_services.query_capsule_caps = + efi_query_capsule_caps_runtime; + efi_update_table_header_crc32(&efi_runtime_services.hdr); +} +#else +/* + * Dummy functions for runtime services + */ +efi_status_t EFIAPI efi_update_capsule( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list) +{ + return EFI_UNSUPPORTED; +} + +efi_status_t EFIAPI efi_query_capsule_caps( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type) +{ + return EFI_UNSUPPORTED; +} +#endif /* CONFIG_EFI_CAPSULE_ON_DISK */ diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index c485cad34022..309defc5e40d 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -96,6 +96,10 @@ static efi_status_t efi_init_os_indications(void) #ifdef CONFIG_EFI_CAPSULE_UPDATE os_indications_supported |= EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED; +#endif +#ifdef CONFIG_EFI_CAPSULE_ON_DISK + os_indications_supported |= + EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED; #endif return EFI_CALL(efi_set_variable(L"OsIndicationsSupported", &efi_global_variable_guid, @@ -196,6 +200,8 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + /* Execute capsules after reboot */ + ret = efi_launch_capsules(); out: efi_obj_list_initialized = ret; return ret; From patchwork Tue Mar 17 02:12:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255995 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=V4yr2Zaq; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGtb66nFz9sPF for ; Tue, 17 Mar 2020 13:13:43 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 22C0A81927; Tue, 17 Mar 2020 03:13:06 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="V4yr2Zaq"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3D2AB81935; Tue, 17 Mar 2020 03:12:50 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9C65181924 for ; Tue, 17 Mar 2020 03:12:37 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pl1-x641.google.com with SMTP id t16so1872056plr.8 for ; Mon, 16 Mar 2020 19:12:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qoNzBvM3NDmt96W1XNXwBt0JqabQGvi0orZ/pDRRSbs=; b=V4yr2ZaqThuUE5GGnWFfAch97t5dp0vXdRqo5eHy+fz86apLTPDyWBKwBw62o7LkoI Q3hwsqF3kt2gwW2YBZ0TH504kdgp26SQo+tdtyEjNJq6hBRbTSSzMg5/tUD6I4P6ySN3 PFNIB0/lKcFteN2NLPDXFBgy2/N5AvczGUKCQfLkJnsYUefynCZtRltUA6TYke0M6YT1 mkynxoOB7P8JZiYloiQ1okn6kt5YIIfaDvGP7JUjj4j577O7Vb7avi1LWkmgym8onrZD YaFgPEZ6yQRV/OcJ5Bl+WgW4+IyejYuuIGBYg0pDlxEdksu6CcBAoa7HAtz+Lkbe2GQr kjug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qoNzBvM3NDmt96W1XNXwBt0JqabQGvi0orZ/pDRRSbs=; b=MedsIBjRDjenb4i9Q6ZbEW5xwO6U1Ed6B5vnbReE6Ff3YKcs3Nq+xKoVskgyfXO9Ua 63x2gdXFzQpQ4maGFoUDStzUHYuHIfY3qMMwyUBHyKQAG+Q5W4WT0SpFoG02qKBhua0/ jc6XQ//weaohKW3Xyr+KqusiJQi9yMfY4LGGTGkO11sMToUYOMKLAT/IE5RxdZnVejmO 0VN96DRSD6JZD1ZSKSBaNuH0L196q2/HtspiNjiqqxAVi6K7WHcdwaO+XBykLl3ldz3Q bc3/aciH44En4EEMibOro2u+Rfr0U7ny+oUM5Z6rNEOqbnaNeazWwnv+k0pLA1IWSbGM s0IQ== X-Gm-Message-State: ANhLgQ3EC1yzeoghc0KSH3f4bAvexOj7LqR9cxm/DPdHjn3LD3Dda7KM MlcRSx90G8flJSttl2jrPXrADQ== X-Google-Smtp-Source: ADFU+vvFVPaB0lO+x6CoIwgrgirV2ETwpkbn9dRUVL14KuVGSQ70T2VxmSCUg6jPj+IKlo32xfFqWg== X-Received: by 2002:a17:90a:348a:: with SMTP id p10mr2789264pjb.120.1584411156119; Mon, 16 Mar 2020 19:12:36 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id y28sm683226pgc.69.2020.03.16.19.12.35 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:35 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 07/14] efi_loader: capsule: add memory range capsule definitions Date: Tue, 17 Mar 2020 11:12:40 +0900 Message-Id: <20200317021247.5849-8-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean Memory range capsule gives us a way to notify that some memory regions should be left untouched across the next reset. See UEFI specification, section 8.5.3. Since how we should handle this kind of capsule is totally up to the system, no implementation will be added in this commit. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index ac2b38801c0c..b7bf21cac7ad 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -221,6 +221,10 @@ enum efi_reset_type { EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \ 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3) +#define EFI_MEMORY_RANGE_CAPSULE_GUID \ + EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \ + 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72) + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; @@ -236,6 +240,19 @@ struct efi_capsule_result_variable_header { efi_status_t capsule_status; } __packed; +struct efi_memory_range { + efi_physical_addr_t address; + u64 length; +}; + +struct efi_memory_range_capsule { + struct efi_capsule_header *header; + /* EFI_MEMORY_TYPE: 0x80000000-0xFFFFFFFF */ + enum efi_mem_type os_requested_memory_type; + u64 number_of_memory_ranges; + struct efi_memory_range memory_ranges[]; +} __packed; + #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 From patchwork Tue Mar 17 02:12:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255997 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=smlVcjI4; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGv35Z5Nz9sPR for ; Tue, 17 Mar 2020 13:14:07 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7A09681938; Tue, 17 Mar 2020 03:13:22 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="smlVcjI4"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 07EB881938; Tue, 17 Mar 2020 03:12:57 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 0950E81930 for ; Tue, 17 Mar 2020 03:12:41 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x442.google.com with SMTP id d25so3032183pfn.6 for ; Mon, 16 Mar 2020 19:12:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pssAQfpCZKnNGQVWcvixP1zBpUP0yP1TXOjk6EYIFS4=; b=smlVcjI4L+6u6a5E0VpHp5HzDlKxXjvmTA7r23Mf3hXMMIUEOnCpMyUfB8kqjkt+D6 aPYJjjAgGOQMFdw7aue/D/a6xRybAq7nGRlgx4hN7PEZMYPvWC94OiT4FS9SxfemlYEU GOx+Jxhb5Payjqmi8UaKKMAx94+bkJjm4U5Xgt3DIXBSvVALmPXncgF4lQbQCBZ3xqFh R7wD8g3qA4W/dM07gu++r4B/z+QQ/PwNjiiSSuwNU8mGGU7qcKz15yxYzVdVZYx9UPJt I2fYYAUByt5piq+W6RA3y3L+ej8xSn0qRuPTbD9+tkfMUqCGBolr4g0uTJDHXM/PEpRE TJLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pssAQfpCZKnNGQVWcvixP1zBpUP0yP1TXOjk6EYIFS4=; b=kpRa2ud4jD8l2zT3DeSb1BygtxdrIsmTDsoPorQ80xGSHX7zp//YHTN5DCRTHL++uj OtjfVoG3If4cxHEYzWNPRWROyCMWHs7UjEaZuev6hctX2HemN6WcC4qKY5/emaSnB6qd zn57EOn2cV/6F6RWjS/Ts/NeXOSwk3rvezfZvZs2WUf31laBEQZF1sUWym7lCtGp0ORY rXALDd4BZaNtWUIjhBhuWZqth0vx7i4tfPKai/r9JYkiWmjTKdgTUdPX/hRPQ3vv8S8k 97bz0WqiQjjaB4sH7elYTGQG6JZ8SrWDpK6IvmUcYjsWEqhcN9aljvn1oYLAbUoBBTkG aCKQ== X-Gm-Message-State: ANhLgQ0jjXyqJdI/BYVmT2ZHXqZRSHUJBaeCnpC4wlTTHzIhp+pd2PqM s10BmEcJD3EXVor53vCUrnTWuw== X-Google-Smtp-Source: ADFU+vvuIUj2RNIO9H7Ei63sN50W1We83fjD7/41VGMrjUHqDmza5ZITxbsl8d3X2PDnwaxOQ4qaQQ== X-Received: by 2002:a63:e24c:: with SMTP id y12mr2626927pgj.244.1584411159361; Mon, 16 Mar 2020 19:12:39 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id u12sm1040689pfm.165.2020.03.16.19.12.38 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:38 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 08/14] efi_loader: capsule: support firmware update Date: Tue, 17 Mar 2020 11:12:41 +0900 Message-Id: <20200317021247.5849-9-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean A capsule tagged with the guid, EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID, is handled as a firmware update object. What efi_update_capsule() basically does is to load any firmware management protocol (or fmp) drivers contained in a capsule, find out an appropriate fmp driver and then invoke its set_image() interface against each binary in a capsule. In this commit, however, installing drivers is not supported yet. The result of applying a capsule is set to be stored in "CapsuleXXXX" variable, but its implementation is deferred to a fmp driver. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 127 +++++++++++++++++++++++++++ lib/efi_loader/Kconfig | 12 +++ lib/efi_loader/efi_capsule.c | 165 +++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_setup.c | 4 + 4 files changed, 308 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index b7bf21cac7ad..e103369186a2 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -225,6 +225,10 @@ enum efi_reset_type { EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \ 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72) +#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID \ + EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \ + 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a) + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; @@ -253,6 +257,32 @@ struct efi_memory_range_capsule { struct efi_memory_range memory_ranges[]; } __packed; +struct efi_firmware_management_capsule_header { + u32 version; + u16 embedded_driver_count; + u16 payload_item_count; + u64 item_offset_list[]; +} __packed; + +struct efi_firmware_management_capsule_image_header { + u32 version; + efi_guid_t update_image_type_id; + u8 update_image_index; + u8 reserved[3]; + u32 update_image_size; + u32 update_vendor_code_size; + u64 update_hardware_instance; +} __packed; + +struct efi_capsule_result_variable_fmp { + u16 version; + u8 payload_index; + u8 update_image_index; + efi_guid_t update_image_type_id; + // u16 capsule_file_name[]; + // u16 capsule_target[]; +} __packed; + #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 @@ -1683,4 +1713,101 @@ struct efi_unicode_collation_protocol { #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN 0x00001000 #define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX 0x00004000 +/* + * Firmware management protocol + */ +#define EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID \ + EFI_GUID(0x86c77a67, 0x0b97, 0x4633, 0xa1, 0x87, \ + 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7) + +#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID \ + EFI_GUID(0xae13ff2d, 0x9ad4, 0x4e25, 0x9a, 0xc8, \ + 0x6d, 0x80, 0xb3, 0xb2, 0x21, 0x47) + +#define EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE 0x1 +#define EFI_IMAGE_ATTRIBUTE_RESET_REQUIRED 0x2 +#define EFI_IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x4 +#define EFI_IMAGE_ATTRIBUTE_IN_USE 0x8 +#define EFI_IMAGE_ATTRIBUTE_UEFI_IMAGE 0x10 + +#define EFI_IMAGE_COMPATIBILITY_CHECK_SUPPORTED 0x1 +#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION 4 + +#define EFI_IMAGE_UPDATABLE_VALID 0x1 +#define EFI_IMAGE_UPDATABLE_INVALID 0x2 +#define EFI_IMAGE_UPDATABLE_INVALID_TYPE 0x4 +#define EFI_IMAGE_UPDATABLE_INVALID_OLLD 0x8 +#define EFI_IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE 0x10 + +#define EFI_PACKAGE_ATTRIBUTE_VERSION_UPDATABLE 0x1 +#define EFI_PACKAGE_ATTRIBUTE_RESET_REQUIRED 0x2 +#define EFI_PACKAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x4 + +typedef struct efi_firmware_image_dependencies { + u8 dependencies[0]; +} efi_fmp_dep_t; + +struct efi_firmware_image_descriptor { + u8 image_index; + efi_guid_t image_type_id; + u64 image_id; + u16 *image_id_name; + u32 version; + u16 *version_name; + efi_uintn_t size; + u64 attributes_supported; + u64 attributes_setting; + u64 compatibilities; + u32 lowest_supported_image_version; + u32 last_attempt_version; + u32 last_attempt_status; + u64 hardware_instance; + efi_fmp_dep_t *dependencies; +}; + +struct efi_firmware_management_protocol { + efi_status_t (EFIAPI *get_image_info)( + struct efi_firmware_management_protocol *this, + efi_uintn_t *image_info_size, + struct efi_firmware_image_descriptor *image_info, + u32 *descriptor_version, + u8 *descriptor_count, + efi_uintn_t *descriptor_size, + u32 *package_version, + u16 **package_version_name); + efi_status_t (EFIAPI *get_image)( + struct efi_firmware_management_protocol *this, + u8 image_index, + void *image, + efi_uintn_t *image_size); + efi_status_t (EFIAPI *set_image)( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t image_size, + const void *vendor_code, + efi_status_t (*progress)(efi_uintn_t completion), + u16 **abort_reason); + efi_status_t (EFIAPI *check_image)( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t *image_size, + u32 *image_updatable); + efi_status_t (EFIAPI *get_package_info)( + struct efi_firmware_management_protocol *this, + u32 *package_version, + u16 **package_version_name, + u32 *package_version_name_maxlen, + u64 *attributes_supported, + u64 *attributes_setting); + efi_status_t (EFIAPI *set_package_info)( + struct efi_firmware_management_protocol *this, + const void *image, + efi_uintn_t *image_size, + const void *vendor_code, + u32 package_version, + const u16 *package_version_name); +}; + #endif diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 95e10f7d981b..43d6f75d557a 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -97,6 +97,18 @@ config EFI_CAPSULE_UPDATE Select this option if you want to use capsule update feature, including firmware updates and variable updates. + +if EFI_CAPSULE_UPDATE + +config EFI_CAPSULE_UPDATE_FIRMWARE + bool "Capsule based firmware update" + default n + help + Select this option if you want to enable capsule-based + firmware update + +endif + config EFI_CAPSULE_ON_DISK bool "Enable capsule-on-disk support" depends on EFI_CAPSULE_UPDATE diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index f3e2a555a6b9..f3526beed681 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -14,10 +14,164 @@ #include const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; +static const efi_guid_t efi_guid_firmware_management_capsule_id = + EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; +const efi_guid_t efi_guid_firmware_management_protocol = + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID; /* for file system access */ static struct efi_file_handle *bootdev_root; +#ifdef CONFIG_EFI_CAPSULE_UPDATE_FIRMWARE +/* + * Handle firmware management capsules + */ +static struct efi_firmware_management_protocol * +efi_fmp_find(efi_guid_t *image_type, u64 instance, efi_handle_t *handles, + efi_uintn_t no_handles) +{ + efi_handle_t *handle; + struct efi_firmware_management_protocol *fmp; + struct efi_firmware_image_descriptor *image_info, *desc; + efi_uintn_t info_size, descriptor_size; + u32 descriptor_version; + u8 descriptor_count; + bool found = false; + int i; + efi_status_t ret; + + for (i = 0, handle = handles; i < no_handles; i++, handle++) { + ret = EFI_CALL(efi_handle_protocol( + *handle, + &efi_guid_firmware_management_protocol, + (void **)&fmp)); + if (ret != EFI_SUCCESS) + continue; + + /* get device's image info */ + info_size = 0; + image_info = NULL; + descriptor_version = 0; + descriptor_count = 0; + descriptor_size = 0; + ret = fmp->get_image_info(fmp, &info_size, image_info, + &descriptor_version, &descriptor_count, + &descriptor_size, NULL, NULL); + if (ret != EFI_BUFFER_TOO_SMALL) + goto skip; + image_info = malloc(info_size); + if (!image_info) + goto skip; + + ret = fmp->get_image_info(fmp, &info_size, image_info, + &descriptor_version, &descriptor_count, + &descriptor_size, NULL, NULL); + if (ret != EFI_SUCCESS) + goto skip; + + /* matching */ + for (i = 0, desc = image_info; i < descriptor_count; + i++, desc = (void *)desc + descriptor_size) + if (!guidcmp(&desc->image_type_id, image_type) && + (!instance || + ((descriptor_version >= 3) && + (desc->hardware_instance == instance)))) + found = true; + +skip: + free(image_info); + EFI_CALL(efi_close_protocol( + (efi_handle_t)fmp, + &efi_guid_firmware_management_protocol, + NULL, NULL)); + if (found) + return fmp; + } + + return NULL; +} + +static efi_status_t efi_capsule_update_firmware( + struct efi_firmware_management_capsule_header *capsule) +{ + struct efi_firmware_management_capsule_image_header *image; + void *image_binary, *vendor_code; + efi_handle_t *handles; + efi_uintn_t no_handles; + int item; + struct efi_firmware_management_protocol *fmp; + u16 *abort_reason; + efi_status_t ret = EFI_SUCCESS; + + if (capsule->version != 0x00000001) + return EFI_INVALID_PARAMETER; + + /* Drivers */ + /* TODO: support loading drivers */ + + handles = NULL; + ret = EFI_CALL(efi_locate_handle_buffer( + BY_PROTOCOL, + &efi_guid_firmware_management_protocol, + NULL, &no_handles, (efi_handle_t **)&handles)); + if (ret != EFI_SUCCESS) + return EFI_UNSUPPORTED; + + /* Payload */ + for (item = capsule->embedded_driver_count; + item < capsule->embedded_driver_count + + capsule->payload_item_count; item++) { + image = (struct efi_firmware_management_capsule_image_header *) + ((void *)capsule + capsule->item_offset_list[item]); + + if (image->version != 0x00000001 && + image->version != 0x00000002 && + image->version != 0x00000003) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* find a device for update firmware */ + fmp = efi_fmp_find(&image->update_image_type_id, + image->version == 0x1 ? 0 : + image->update_hardware_instance, + handles, no_handles); + if (!fmp) { + printf("EFI Capsule: not support firmware type: %pUl\n", + &image->update_image_type_id); + ret = EFI_UNSUPPORTED; + goto out; + } + + /* do it */ + image_binary = (void *)image + sizeof(*image); + vendor_code = image_binary + image->update_image_size; + + abort_reason = NULL; + ret = fmp->set_image(fmp, image->update_image_index, + image_binary, image->update_image_size, + vendor_code, NULL, &abort_reason); + if (ret != EFI_SUCCESS) { + printf("EFI Capsule: firmware update failed: %ls\n", + abort_reason); + efi_free_pool(abort_reason); + goto out; + } + } + +out: + efi_free_pool(handles); + + return ret; +} +#else +static efi_status_t efi_capsule_update_firmware( + struct efi_firmware_management_capsule_header *capsule) +{ + return EFI_UNSUPPORTED; +} +#endif /* CONFIG_EFI_CAPSULE_UPDATE_FIRMWARE */ + /* * Launch a capsule */ @@ -54,6 +208,17 @@ efi_status_t EFIAPI efi_update_capsule( ret = EFI_SUCCESS; for (i = 0, capsule = *capsule_header_array; i < capsule_count; i++, capsule = *(++capsule_header_array)) { + EFI_PRINT("EFI Capsule (guid:%pUl)\n", &capsule->capsule_guid); + if (!guidcmp(&capsule->capsule_guid, + &efi_guid_firmware_management_capsule_id)) + ret = efi_capsule_update_firmware( + (struct efi_firmware_management_capsule_header *) + ((void *)capsule + sizeof(*capsule))); + else + ret = EFI_UNSUPPORTED; + + if (ret != EFI_SUCCESS) + goto out; } out: return EFI_EXIT(ret); diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 309defc5e40d..ca2d03c44610 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -100,6 +100,10 @@ static efi_status_t efi_init_os_indications(void) #ifdef CONFIG_EFI_CAPSULE_ON_DISK os_indications_supported |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED; +#endif +#ifdef CONFIG_EFI_CAPSULE_UPDATE_FIRMWARE + os_indications_supported |= + EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; #endif return EFI_CALL(efi_set_variable(L"OsIndicationsSupported", &efi_global_variable_guid, From patchwork Tue Mar 17 02:12:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255999 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=Vjs4rcwR; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGvS6FVpz9sPF for ; Tue, 17 Mar 2020 13:14:28 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id F286F81940; Tue, 17 Mar 2020 03:13:29 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="Vjs4rcwR"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5CF7681925; Tue, 17 Mar 2020 03:13:00 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3C0688191C for ; Tue, 17 Mar 2020 03:12:44 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pg1-x541.google.com with SMTP id z72so992336pgz.3 for ; Mon, 16 Mar 2020 19:12:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=tzh4Ui16ONZ41gJ11pl3qDLawINMVLznypnGFOp7mvI=; b=Vjs4rcwRUDMlOfv3IyoZ0FTQq+a3c6KQRaiTD5HUu7jK+HI5skhi4/cCagadSqBPyF GRxC++TZCOuEBVJV+8lQVXJbfSB35pC/jwndv8tfBmovlZoePI7xZUyGsmO7YS6PpBbb sPmyB6GOUIRlpnCfNm3WuSqN8ELbhUNG6XxPgBZW07lZLh/4YeF1HSm24nDyMSI772px fCp8VD1lsujkqUuW6Dv919JBYQlGLhYipA6HCgArn1IGxcrVEF63WdnyfqqDRjXmEzsQ vTNdOo5v71hQ+sBtAzGi0yQ/Lo8RIO6PuuMH2TIPDpWwVn1ax5SzzaockeRJ9V/jC+cO 2xJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tzh4Ui16ONZ41gJ11pl3qDLawINMVLznypnGFOp7mvI=; b=Jj/xQUOWqpPcfQA7z/Cc02h1WenNAuMtFnNECXH8g3ZcIkq2nnrGfl86j7dSF3YtDS 8wu7Cq0Kd0s2ztuuqVc+sBMLdiJwCY5wwsBIfkzLRlnKnXA+TmuuhfsHc9qaxyTYmxHl wDmTVAz98srCZor2+bPxEWcjYYj2cwD0feIBqQxypIGWiEtTWgDSMva0Euoxy8zd3p8i vB7RkFj/y6kaSyWn4SzCFks5mp7z34wLb5K+UW6r2daAmAxQDdvFmVJhGtQYV2THeS+G NeUf3vs89BrlEi3kFcNR3vg9Ri+QG4xfpXqCMu9O7wJcN5AyMoaoewjgKUlf1WnFhfKP rRfQ== X-Gm-Message-State: ANhLgQ3tcr4ki63LOTpf6tezik4Z0WbfBBJlNfKyknTFQkLPY4/Ej5Te R6Ic5CkfT1Svn2gPtGNdQIkB1Q== X-Google-Smtp-Source: ADFU+vuN12V7BY0bw3gWPxTxTdS6sGMyNa/1+C/p1tUK5GKzzCGqmqQG57kICev92t3fmufgkyRrDQ== X-Received: by 2002:a62:3784:: with SMTP id e126mr2669806pfa.50.1584411162616; Mon, 16 Mar 2020 19:12:42 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id c11sm1097802pfc.216.2020.03.16.19.12.41 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:42 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 09/14] efi_loader: add simple firmware management protocol for FIT image Date: Tue, 17 Mar 2020 11:12:42 +0900 Message-Id: <20200317021247.5849-10-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean In this commit, a very simple firmware management protocol driver is implemented. It will take a single FIT image firmware in a capsule and apply the data using an existing update_tftp() interface. To specify a device and location to be updated, CONFIG_EFI_CAPSULE_FIT_INTERFACE, and CONFIG_EFI_CAPSULE_FIT_DEVICE are used. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 3 + lib/efi_loader/Kconfig | 24 ++++- lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_firmware.c | 191 ++++++++++++++++++++++++++++++++++ 4 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 lib/efi_loader/efi_firmware.c diff --git a/include/efi_loader.h b/include/efi_loader.h index c701672e18db..79bdf9586d24 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -134,6 +134,7 @@ extern const struct efi_hii_config_access_protocol efi_hii_config_access; extern const struct efi_hii_database_protocol efi_hii_database; extern const struct efi_hii_string_protocol efi_hii_string; extern const struct efi_rng_protocol efi_rng_protocol; +extern const struct efi_firmware_management_protocol efi_fmp_fit; uint16_t *efi_dp_str(struct efi_device_path *dp); @@ -180,6 +181,8 @@ extern const efi_guid_t efi_guid_hii_database_protocol; extern const efi_guid_t efi_guid_hii_string_protocol; /* GUID of capsule update result */ extern const efi_guid_t efi_guid_capsule_report; +/* GUID of firmware management protocol */ +extern const efi_guid_t efi_guid_firmware_management_protocol; /* GUID of RNG protocol */ extern const efi_guid_t efi_guid_rng_protocol; diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 43d6f75d557a..41b1e9b5543c 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -97,7 +97,6 @@ config EFI_CAPSULE_UPDATE Select this option if you want to use capsule update feature, including firmware updates and variable updates. - if EFI_CAPSULE_UPDATE config EFI_CAPSULE_UPDATE_FIRMWARE @@ -107,6 +106,29 @@ config EFI_CAPSULE_UPDATE_FIRMWARE Select this option if you want to enable capsule-based firmware update +config EFI_CAPSULE_FIT_SIMPLE + bool "Firmware management protocol for simple FIT image" + depends on EFI_CAPSULE_UPDATE_FIRMWARE + depends on FIT + select UPDATE_TFTP + select DFU + default n + help + Select this option if you want to enable firmware management protocol + for simple FIT image + +config EFI_CAPSULE_FIT_INTERFACE + string "Storage interface for storing FIT image" + depends on EFI_CAPSULE_FIT_SIMPLE + help + Define storage interface for storing FIT image + +config EFI_CAPSULE_FIT_DEVICE + string "Storage device for storing FIT image" + depends on EFI_CAPSULE_FIT_SIMPLE + help + Define storage device for storing FIT image + endif config EFI_CAPSULE_ON_DISK diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index f19096924bef..50da10e0e3d9 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_bootmgr.o obj-y += efi_boottime.o obj-$(CONFIG_EFI_CAPSULE_UPDATE) += efi_capsule.o +obj-$(CONFIG_EFI_CAPSULE_FIT_SIMPLE) += efi_firmware.o obj-y += efi_console.o obj-y += efi_device_path.o obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c new file mode 100644 index 000000000000..021c93196242 --- /dev/null +++ b/lib/efi_loader/efi_firmware.c @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI Firmware management protocol for FIT image + * + * Copyright (c) 2018 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include + +/* + * This FIMRWARE_MANAGEMENT_PROTOCOL driver provides a simple + * firmware update method, and handles + * - a single region of firmware via DFU + * but doesn't support + * - versioning of firmware image + * - package information + */ +const efi_guid_t efi_firmware_image_type_uboot_fit = + EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID; + +static +efi_status_t EFIAPI efi_fmp_fit_get_image_info( + struct efi_firmware_management_protocol *this, + efi_uintn_t *image_info_size, + struct efi_firmware_image_descriptor *image_info, + u32 *descriptor_version, + u8 *descriptor_count, + efi_uintn_t *descriptor_size, + u32 *package_version, + u16 **package_version_name) +{ + efi_status_t ret = EFI_SUCCESS; + + EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, + image_info_size, image_info, + descriptor_version, descriptor_count, descriptor_size, + package_version, package_version_name); + + if (!image_info_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (*image_info_size < sizeof(*image_info)) { + *image_info_size = sizeof(*image_info); + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + } + + if (!image_info) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + *image_info_size = sizeof(*image_info); + if (descriptor_version) + *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; + if (descriptor_count) + *descriptor_count = 1; + if (descriptor_size) + *descriptor_size = sizeof(*image_info); + if (package_version) + *package_version = 0xffffffff; /* not supported */ + if (package_version_name) + *package_version_name = NULL; /* not supported */ + + image_info[0].image_index = 1; + image_info[0].image_type_id = efi_firmware_image_type_uboot_fit; + image_info[0].image_id = 0; + image_info[0].image_id_name = L"fw_simple"; + image_info[0].version = 0; /* not supported */ + image_info[0].version_name = NULL; /* not supported */ + image_info[0].size = 0; +#if defined(CONFIG_FIT) && defined(CONFIG_UPDATE_TFTP) + image_info[0].attributes_supported = + EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; + image_info[0].attributes_setting = EFI_IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; +#else + image_info[0].attributes_supported = 0; + image_info[0].attributes_setting = 0; +#endif + image_info[0].lowest_supported_image_version = 0; + image_info[0].last_attempt_version = 0; + image_info[0].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; + image_info[0].hardware_instance = 1; + image_info[0].dependencies = NULL; + + return EFI_EXIT(ret); +} + +static +efi_status_t EFIAPI efi_fmp_fit_get_image( + struct efi_firmware_management_protocol *this, + u8 image_index, + void *image, + efi_uintn_t *image_size) +{ + EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +static +efi_status_t EFIAPI efi_fmp_fit_set_image( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t image_size, + const void *vendor_code, + efi_status_t (*progress)(efi_uintn_t completion), + u16 **abort_reason) +{ + EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image, + image_size, vendor_code, progress, abort_reason); + +#if defined(CONFIG_FIT) && defined(CONFIG_UPDATE_TFTP) + if (!image || image_index != 1) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (update_tftp((ulong)image, CONFIG_EFI_CAPSULE_FIT_INTERFACE, + CONFIG_EFI_CAPSULE_FIT_DEVICE)) + return EFI_EXIT(EFI_DEVICE_ERROR); + + return EFI_EXIT(EFI_SUCCESS); +#else + return EFI_EXIT(EFI_UNSUPPORTED); +#endif +} + +static +efi_status_t EFIAPI efi_fmp_fit_check_image( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t *image_size, + u32 *image_updatable) +{ + EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size, + image_updatable); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +static +efi_status_t EFIAPI efi_fmp_fit_get_package_info( + struct efi_firmware_management_protocol *this, + u32 *package_version, + u16 **package_version_name, + u32 *package_version_name_maxlen, + u64 *attributes_supported, + u64 *attributes_setting) +{ + EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version, + package_version_name, package_version_name_maxlen, + attributes_supported, attributes_setting); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +static +efi_status_t EFIAPI efi_fmp_fit_set_package_info( + struct efi_firmware_management_protocol *this, + const void *image, + efi_uintn_t *image_size, + const void *vendor_code, + u32 package_version, + const u16 *package_version_name) +{ + EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code, + package_version, package_version_name); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +const struct efi_firmware_management_protocol efi_fmp_fit_simple = { + .get_image_info = efi_fmp_fit_get_image_info, + .get_image = efi_fmp_fit_get_image, + .set_image = efi_fmp_fit_set_image, + .check_image = efi_fmp_fit_check_image, + .get_package_info = efi_fmp_fit_get_package_info, + .set_package_info = efi_fmp_fit_set_package_info, +}; + +efi_status_t arch_efi_load_capsule_drivers(void) +{ + efi_status_t ret; + + ret = EFI_CALL(efi_install_multiple_protocol_interfaces( + &efi_root, &efi_guid_firmware_management_protocol, + &efi_fmp_fit_simple, NULL)); + + return ret; +} From patchwork Tue Mar 17 02:12:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1255998 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=CHpLW+ag; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGvG6lbFz9sPF for ; Tue, 17 Mar 2020 13:14:18 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 85B6D818F6; Tue, 17 Mar 2020 03:13:26 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="CHpLW+ag"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BD3F581948; Tue, 17 Mar 2020 03:12:58 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 4F2BF81940 for ; Tue, 17 Mar 2020 03:12:47 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pg1-x541.google.com with SMTP id 37so10824014pgm.11 for ; Mon, 16 Mar 2020 19:12:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qatP+gF0wPSxY6pZnM0iBJPfs0q9btowBf4KNOBdEYk=; b=CHpLW+agzOiTWUINpUlfynLD47ai7otM18NWwdytOLSgsxjdRv17eZdsaMkz3G7goD LINb4ZUuH7w7rbqgiZA/In7JfyqorDVi4lqvpVUHO3JIL1vDDsFMbZo9nsAR3Ojwgqiv mcQwwWJt+9eJDnBQY3zmqBUmnykqwuMUjE68TYRUgOmUJOaiGRAlLWKKB622yfdAFEat 8SZgJUc0Sl6I36xC3OaO0Je9W1ImKOSWNu9ZnEn/9DNnG72t9huiY7oNHS9CpVi5Lhx0 dfj2rjILTpV0KMi5EQWS8MV9Lt0b2gcvi5OqgdhG7V4T8X9Bg6qBLp6ZLM966Ov7xZG6 Z2Gg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qatP+gF0wPSxY6pZnM0iBJPfs0q9btowBf4KNOBdEYk=; b=FUjQTPBsDPMpE0v2IfcT4XvSSajU+WzLkwE64TpiMEg2ltzpb98hMkeYNS/Q8vM1hE HZKRkDWhzNb5nS/9eewjC8b21TdhuubnGZD2kHObbDd8I6rHmg+9HUZKXhW7U98fly30 DNOP+1t7aGCLIeoQ5MsA4bnOE/BNd/36dtQO0tVeCrqC+I3yoJ6PEps07qUvgS8pq3xC L0WzpAp5zZSR08nCe5iXo45A/ZlUCd26paxLRdn3Q6pHGo8knEqOVHzXtfVHYkVwIeda /Cn4kZcow5YKXOi+qad7qHtlKa/x1THn4qborrJ9bs79M9IRpqm2liFKN3QqNO/V1HFR tU0g== X-Gm-Message-State: ANhLgQ1fosb91Lc9JNjWnfOlKraTxmjMktKV9pDceK7na48EjNVixFgk VPAGk4UnmzO6MoC/cyPQDYIxHw== X-Google-Smtp-Source: ADFU+vsP1lotCyag/cqh0JtFA84OdLnDtMN1yX0hTcn4sz9FUiCvYhTuuIjIpHNPRwS2Zgtco6dPGg== X-Received: by 2002:a65:5846:: with SMTP id s6mr2720329pgr.179.1584411165804; Mon, 16 Mar 2020 19:12:45 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id z125sm1104271pfz.92.2020.03.16.19.12.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:45 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 10/14] efi_loader: capsule: support variable update Date: Tue, 17 Mar 2020 11:12:43 +0900 Message-Id: <20200317021247.5849-11-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean See EBBR specification v1.0. A capsule tagged with the guid, EFI_VARIABLE_STORAGE_GUID, will be handled as a variable update object. What efi_update_capsule() basically does is to re-play SetVariable against each variable entry in a capsule. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 18 +++++++++++++++ lib/efi_loader/Kconfig | 7 ++++++ lib/efi_loader/efi_capsule.c | 45 ++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index e103369186a2..30807942380b 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -229,6 +229,10 @@ enum efi_reset_type { EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \ 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a) +#define EFI_VARIABLE_STORAGE_GUID \ + EFI_GUID(0x1a3fb419, 0x2171, 0x458d, 0xb8, 0xb4, \ + 0xbe, 0xa3, 0x0c, 0x9f, 0x6b, 0xab) + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; @@ -283,6 +287,20 @@ struct efi_capsule_result_variable_fmp { // u16 capsule_target[]; } __packed; +struct efi_ebbr_variable { + u16 variable_name[64]; + efi_guid_t vendor_guid; + u32 attributes; + u32 data_size; + u8 data[]; +}; + +struct efi_ebbr_variable_bundle { + struct efi_capsule_header header; + u8 reserved[0]; + struct efi_ebbr_variable variables[]; +} __packed; + #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 41b1e9b5543c..616e2acbe102 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -129,6 +129,13 @@ config EFI_CAPSULE_FIT_DEVICE help Define storage device for storing FIT image +config EFI_CAPSULE_UPDATE_VARIABLE + bool "Capsule based variable update" + default n + help + Select this option if you want to enable capsule-based + variable update support + endif config EFI_CAPSULE_ON_DISK diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index f3526beed681..1293270aea95 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -18,6 +18,7 @@ static const efi_guid_t efi_guid_firmware_management_capsule_id = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; const efi_guid_t efi_guid_firmware_management_protocol = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID; +static const efi_guid_t efi_guid_variable_storage = EFI_VARIABLE_STORAGE_GUID; /* for file system access */ static struct efi_file_handle *bootdev_root; @@ -172,6 +173,45 @@ static efi_status_t efi_capsule_update_firmware( } #endif /* CONFIG_EFI_CAPSULE_UPDATE_FIRMWARE */ +#ifdef CONFIG_EFI_CAPSULE_UPDATE_VARIABLE +/* + * Execute a log of variable changes + */ +static efi_status_t +efi_capsule_update_variables(struct efi_ebbr_variable_bundle *bundle) +{ + struct efi_ebbr_variable *variable; + efi_status_t ret = EFI_SUCCESS; + + for (variable = (void *)bundle + bundle->header.header_size; + (void *)variable + < ((void *)bundle + bundle->header.capsule_image_size); + variable = (struct efi_ebbr_variable *) + ((void *)variable + + sizeof(*variable) + variable->data_size)) { + ret = efi_set_variable(variable->variable_name, + &variable->vendor_guid, + variable->attributes, + variable->data_size, + &variable->data); + /* Should NOT_FOUND always be treated as success? */ + if (ret == EFI_NOT_FOUND) + ret = EFI_SUCCESS; + EFI_PRINT("Capsule variable update %s: %ls\n", + ret == EFI_SUCCESS ? "succeeded" : "failed", + variable->variable_name); + } + + return ret; +} +#else +static efi_status_t +efi_capsule_update_variables(struct efi_ebbr_variable_bundle *bundle) +{ + return EFI_UNSUPPORTED; +} +#endif /* CONFIG_EFI_CAPSULE_UPDATE_VARIABLE */ + /* * Launch a capsule */ @@ -214,6 +254,11 @@ efi_status_t EFIAPI efi_update_capsule( ret = efi_capsule_update_firmware( (struct efi_firmware_management_capsule_header *) ((void *)capsule + sizeof(*capsule))); + else if (!guidcmp(&capsule->capsule_guid, + &efi_guid_variable_storage)) + ret = efi_capsule_update_variables( + (struct efi_ebbr_variable_bundle *) + capsule); else ret = EFI_UNSUPPORTED; From patchwork Tue Mar 17 02:12:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1256000 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=vHig+2UI; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGvh0q67z9sPF for ; Tue, 17 Mar 2020 13:14:40 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 841CA8195C; Tue, 17 Mar 2020 03:13:33 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="vHig+2UI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 39B7781938; Tue, 17 Mar 2020 03:13:02 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pl1-x642.google.com (mail-pl1-x642.google.com [IPv6:2607:f8b0:4864:20::642]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A36E98191B for ; Tue, 17 Mar 2020 03:12:50 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pl1-x642.google.com with SMTP id f8so8889654plt.10 for ; Mon, 16 Mar 2020 19:12:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZN2NfRArDSsCb9/62Vdrxu7k1YFYPwYow+bZMszRjEk=; b=vHig+2UIAadloQqT9/5plQJH89M2/5hdY1+njQSWuNszDjv04vFnQEYvbsKaguu7O8 3fBmIaocAJEkBGOJoCp+egaZ0r0GuVpIbHZj7DmjouaqPXj3yxeWu8mtcI5SHX7nOus4 JGqJrnaR6aH0z7dLeVT98tbwt95ZpPTl8Xqg3p2i+NmUM7A8dk+fesoxjdxpWJJTbUsr CmzHETmKaRmdSSrOpWd0RcSSzJLGnOXnkmXLo5AalcLzNqqz9sRlMPngLNGJYz/MGb5U HE3Sp2GVSSCw4w1WFsA1wbTfICSFzFB2vtHcA/EdvNQaY9sd3anal91djCqWb74xOxfN Y/Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZN2NfRArDSsCb9/62Vdrxu7k1YFYPwYow+bZMszRjEk=; b=X2uM+BKmSBa4XSDzuTJCoOj48Ojs5d+qt9qEvDqP1O4m8gVCr7znsv7SjZvnH3Wn16 4/0S+LaT+LuOmT854Hv0h9EdJT7Cs/anMrmzDIGy8+F8V6lBdAVCspfENTcEsDth5hDq SG4L6HWYrVU21payFQT6f0aIv7jAVbsMqm6aEzIWiITXO3wocxLitheQiAMfl86d8Si8 DI5c3DI9iHiUGbG098hl61SLh39TPtbaLTNteZRtdo7dvaSLM1eR7qzsARTVNO0HSV/I 64lTPTn1abObnzDFq/mxEdSZH6lSOOx1gYHJXI6L7q6Eaf9rSsyQW6MTQKYDxH7ooYU0 68wQ== X-Gm-Message-State: ANhLgQ2VTOljgArG6CuKr26+STcthMGJfWx1JYQnM4c6gypXhrO8UwCD GCX13n4uDwVe7qrrUMDh2cvofQ== X-Google-Smtp-Source: ADFU+vvCPlLZ+GNeuRxPhR37lJsM9vWZtizj66DknKrcul/VJVLaAHhsgPFRmulEpTCRVYkvbjL1PQ== X-Received: by 2002:a17:90a:e7c8:: with SMTP id kb8mr2557914pjb.79.1584411168963; Mon, 16 Mar 2020 19:12:48 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id 3sm1074844pfe.161.2020.03.16.19.12.47 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:48 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 11/14] efi_loader: variable: export variables table for runtime access Date: Tue, 17 Mar 2020 11:12:44 +0900 Message-Id: <20200317021247.5849-12-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean There are platforms on which OS's won't be able to access UEFI variables at runtime (i.e. after ExitBootServices). With this patch, all the UEFI variables are exported as a configuration table so as to enable retrieving variables' values from the table, and later modifying them via capsule-on-disk if necessary. The idea is based on Peter's proposal[1] in boot-arch ML. [1] https://lists.linaro.org/pipermail/boot-architecture/2018-October/000883.html Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 7 +++ lib/efi_loader/Kconfig | 10 ++++ lib/efi_loader/efi_boottime.c | 10 ++++ lib/efi_loader/efi_capsule.c | 4 ++ lib/efi_loader/efi_variable.c | 109 ++++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+) diff --git a/include/efi_loader.h b/include/efi_loader.h index 79bdf9586d24..93ed5502821c 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -183,6 +183,8 @@ extern const efi_guid_t efi_guid_hii_string_protocol; extern const efi_guid_t efi_guid_capsule_report; /* GUID of firmware management protocol */ extern const efi_guid_t efi_guid_firmware_management_protocol; +/* GUID of runtime variable access */ +extern const efi_guid_t efi_guid_variable_storage; /* GUID of RNG protocol */ extern const efi_guid_t efi_guid_rng_protocol; @@ -659,6 +661,10 @@ efi_status_t EFIAPI efi_query_variable_info( u64 *remaining_variable_storage_size, u64 *maximum_variable_size); +#ifdef CONFIG_EFI_VARIABLE_EXPORT +efi_status_t efi_install_variables_table(void); +#endif + /* * See section 3.1.3 in the v2.7 UEFI spec for more details on * the layout of EFI_LOAD_OPTION. In short it is: @@ -683,6 +689,7 @@ struct efi_load_option { void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data); unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data); efi_status_t efi_bootmgr_load(efi_handle_t *handle); +efi_status_t efi_install_variables_table(void); /* Capsule update */ efi_status_t EFIAPI efi_update_capsule( diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 616e2acbe102..edb8d19059ea 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -41,6 +41,16 @@ config EFI_SET_TIME Provide the SetTime() runtime service at boottime. This service can be used by an EFI application to adjust the real time clock. +config EFI_VARIABLE_EXPORT + bool "Export variables table as configuration table" + depends on !EFI_VARIABLE_RUNTIME_ACCESS + depends on EFI_CAPSULE_UPDATE_VARIABLE + default y + help + Select this option if you want to export UEFI variables as + configuration table so that OS can still get UEFI variable's + value. + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index c2a789b4f910..406644e4da67 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2898,6 +2898,16 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, if (ret != EFI_SUCCESS) return EFI_EXIT(EFI_INVALID_PARAMETER); +#ifdef CONFIG_EFI_VARIABLE_EXPORT + /* Install variables database as a configuration table */ + ret = efi_install_variables_table(); + if (ret != EFI_SUCCESS) + return EFI_EXIT(ret); +#endif + /* + * TODO: remove a table after image is terminated. + */ + image_obj->exit_data_size = exit_data_size; image_obj->exit_data = exit_data; diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 1293270aea95..6b737aec1b28 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -18,7 +18,11 @@ static const efi_guid_t efi_guid_firmware_management_capsule_id = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; const efi_guid_t efi_guid_firmware_management_protocol = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID; +#ifdef CONFIG_EFI_VARIABLE_EXPORT +const efi_guid_t efi_guid_variable_storage = EFI_VARIABLE_STORAGE_GUID; +#else static const efi_guid_t efi_guid_variable_storage = EFI_VARIABLE_STORAGE_GUID; +#endif /* for file system access */ static struct efi_file_handle *bootdev_root; diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index c316bdfec0e4..270e5211f633 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -641,3 +641,112 @@ efi_status_t efi_init_variables(void) { return EFI_SUCCESS; } + +#ifdef CONFIG_EFI_VARIABLE_EXPORT +/** + * efi_install_variables_table() - install variables table + * + * This function adds a configuration table that contains all the cache + * data of UEFI variables for runtime access. + * + * Return: status code + */ +efi_status_t efi_install_variables_table(void) +{ + u16 var_name16[64]; + efi_uintn_t var_name16_len; + efi_guid_t guid; + u32 attributes; + struct efi_capsule_header capsule; + u8 *data = NULL, *p; + efi_uintn_t capsule_size; + struct efi_ebbr_variable variable; + u8 *var_buf; + efi_uintn_t var_size, var_max_size; + efi_status_t ret; + + capsule.capsule_guid = efi_guid_variable_storage; + capsule.header_size = sizeof(capsule); + capsule.flags = CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; + capsule_size = sizeof(capsule); + + /* Determine size of capsule */ + var_name16[0] = 0; + var_name16_len = 64; + var_buf = NULL; + var_max_size = 0; + for (;;) { + ret = EFI_CALL(efi_get_next_variable_name(&var_name16_len, + var_name16, + &guid)); + if (ret == EFI_NOT_FOUND) + break; + else if (ret != EFI_SUCCESS) + goto out; + + var_size = 0; + ret = EFI_CALL(efi_get_variable(var_name16, &guid, &attributes, + &var_size, var_buf)); + if (ret != EFI_BUFFER_TOO_SMALL) + goto out; + + capsule_size += sizeof(variable) + var_size; + if (var_size > var_max_size) + var_max_size = var_size; + } + capsule.capsule_image_size = capsule_size; + + ret = efi_allocate_pool(EFI_RUNTIME_SERVICES_DATA, + capsule_size, (void **)&data); + if (ret != EFI_SUCCESS) + return EFI_OUT_OF_RESOURCES; + + var_buf = malloc(var_max_size); + if (!var_buf) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + /* Copy data */ + p = data; + memcpy(p, &capsule, sizeof(capsule)); + p += sizeof(capsule); + + var_name16[0] = 0; + for (;;) { + ret = EFI_CALL(efi_get_next_variable_name(&var_name16_len, + var_name16, &guid)); + if (ret == EFI_NOT_FOUND) + break; + else if (ret != EFI_SUCCESS) + goto out; + + var_size = var_max_size; + ret = EFI_CALL(efi_get_variable(var_name16, &guid, &attributes, + &var_size, var_buf)); + if (ret != EFI_SUCCESS) + /* should not happen */ + goto out; + + u16_strcpy(variable.variable_name, var_name16); + variable.vendor_guid = guid; + variable.attributes = attributes; + variable.data_size = var_size; + + memcpy(p, &variable, sizeof(variable)); + p += sizeof(variable); + memcpy(p, var_buf, var_size); + p += var_size; + } + + ret = EFI_CALL(efi_install_configuration_table( + &efi_guid_variable_storage, data)); + +out: + free(var_buf); + if (ret != EFI_SUCCESS && data) + efi_free_pool(data); + + return ret; +} +#endif /* CONFIG_EFI_VARIABLE_EXPORT */ From patchwork Tue Mar 17 02:12:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1256002 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=hpVOeRbw; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGw54pZ0z9sPF for ; Tue, 17 Mar 2020 13:15:01 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EB28681960; Tue, 17 Mar 2020 03:13:40 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="hpVOeRbw"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 141A481942; Tue, 17 Mar 2020 03:13:10 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x444.google.com (mail-pf1-x444.google.com [IPv6:2607:f8b0:4864:20::444]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id DE7958192C for ; Tue, 17 Mar 2020 03:12:53 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x444.google.com with SMTP id f206so30369pfa.10 for ; Mon, 16 Mar 2020 19:12:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fTGo2CsiBXVuo4jEo/eJIkDuHApFTNkMBs3ZBeOncI0=; b=hpVOeRbwcte4gcSZvYOnuHsyEseszgBhM2UwO7NXOJsMrM7hBpLm8RManHPZRXCr47 tWAKZYScqyLnvp+As1J/arOkoe1z71F+SDMhv0L4XMdLQloXtKvfHVhJngXIx0wzYueb o6hwx4ixvI0ArBvjNDs2iIUbsQORQf2rXbYiD4STIopE6UU8V8OFyNeC5cTFwEXOG9hg HzTEix+5FbGfXYeUNmt5qNv/rmHJoFC/40yN+40yICRHyLto4AINWw73p6c45VaGSZYa 8HTZ/QxZXVrjb76C/ifw/yqC61C/5V6eEaNCW0Dn36f8ucc9EXRgq3DI79YdZ9blMqv3 9ZQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fTGo2CsiBXVuo4jEo/eJIkDuHApFTNkMBs3ZBeOncI0=; b=sWmZVFmGSVo9GS802/MCkEVxt6Zq3qB63zotP1MBnx5nxNmYlRr3MD/51Kk4eaDcK5 jrpTTkj8po5VIVwSeN+ik8mwBOthyuyzY2lHNLkFeyfYa80RDoFs9Cmaay+iqpsrtSBq lr2TdLnWS5mPoUasRIvfgvvd/aDVlitgBhv33xGuwYX1cL1iXvU8eAX6+9FLLnedsJBT gKEnaI4ol6hzzl35HZbh1bmydzmzPds7FwzfHS8fzB1EWoeRxlM3avBiv3o7TBwbra4L CI9EFIoI+zRs/ap39ZXVE2+kcc4ZXX2w7WinLDMtp/qw+sl9/u8BEETDQHoVDziB/CO2 2W3w== X-Gm-Message-State: ANhLgQ1IGMbVR7mrxWrh+/apKm5ggw90xl83gskOoYuCkoFaErpZ1Mb0 DjPSTkldN8y0J6sDIq4zAPkItw== X-Google-Smtp-Source: ADFU+vtDyzoHmDbbM3aHa/qe+RnaDlOhXJEhpZlIOAyiTsjSEuTXIWsAEZsIfZxtu0vF92kV8y5ymA== X-Received: by 2002:a63:348b:: with SMTP id b133mr2786433pga.372.1584411172313; Mon, 16 Mar 2020 19:12:52 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id d23sm1082109pfq.210.2020.03.16.19.12.51 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:51 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 12/14] cmd: add "efidebug capsule" command Date: Tue, 17 Mar 2020 11:12:45 +0900 Message-Id: <20200317021247.5849-13-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean "efidebug capsule" is more or less a debugging utility. efidebug capsule update: invoke UpdateCapsule against data on memory efidebug capsule show: show a header of a capsule efidebug capsule result: dump a capsule result variable Signed-off-by: AKASHI Takahiro --- cmd/efidebug.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 3a50dafbbca6..604f4b42e9ad 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -18,6 +18,227 @@ #define BS systab.boottime #define RT systab.runtime +#ifdef CONFIG_EFI_CAPSULE_UPDATE +/** + * do_efi_capsule_update() - process a capsule update + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule update" sub-command. + * process a capsule update. + * + * efidebug capsule update [-v] + */ +static int do_efi_capsule_update(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct efi_capsule_header *capsule; + int verbose = 0; + char *endp; + efi_status_t ret; + + if (argc != 2 && argc != 3) + return CMD_RET_USAGE; + + if (argc == 3) { + if (strcmp(argv[1], "-v")) + return CMD_RET_USAGE; + + verbose = 1; + argc--; + argv++; + } + + capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16); + if (endp == argv[1]) { + printf("Invalid address: %s", argv[1]); + return CMD_RET_FAILURE; + } + + if (verbose) { + printf("Capsule guid: %pUl\n", &capsule->capsule_guid); + printf("Capsule flags: 0x%x\n", capsule->flags); + printf("Capsule header size: 0x%x\n", capsule->header_size); + printf("Capsule image size: 0x%x\n", + capsule->capsule_image_size); + } + + ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL)); + if (ret) { + printf("Cannot handle a capsule at %p", capsule); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +/** + * do_efi_capsule_show() - show capsule information + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule show" sub-command. + * show capsule information. + * + * efidebug capsule show + */ +static int do_efi_capsule_show(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct efi_capsule_header *capsule; + char *endp; + + if (argc != 2) + return CMD_RET_USAGE; + + capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16); + if (endp == argv[1]) { + printf("Invalid address: %s", argv[1]); + return CMD_RET_FAILURE; + } + + printf("Capsule guid: %pUl\n", &capsule->capsule_guid); + printf("Capsule flags: 0x%x\n", capsule->flags); + printf("Capsule header size: 0x%x\n", capsule->header_size); + printf("Capsule image size: 0x%x\n", + capsule->capsule_image_size); + + return CMD_RET_SUCCESS; +} + +/** + * do_efi_capsule_res() - show a capsule update result + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule result" sub-command. + * show a capsule update result. + * If result number is not specified, CapsuleLast will be shown. + * + * efidebug capsule result [] + */ +static int do_efi_capsule_res(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + int capsule_id; + char *endp; + char var_name[12]; + u16 var_name16[12], *p; + efi_guid_t guid; + struct efi_capsule_result_variable_header *result = NULL; + efi_uintn_t size; + efi_status_t ret; + + if (argc != 1 && argc != 2) + return CMD_RET_USAGE; + + guid = efi_guid_capsule_report; + if (argc == 1) { + size = sizeof(var_name16); + ret = EFI_CALL(RT->get_variable(L"CapsuleLast", &guid, NULL, + &size, var_name16)); + if (ret != EFI_SUCCESS) { + if (ret == EFI_NOT_FOUND) + printf("CapsuleLast doesn't exist\n"); + else + printf("Failed to get CapsuleLast\n"); + + return CMD_RET_FAILURE; + } + printf("CapsuleLast is %ls\n", var_name16); + } else { + argc--; + argv++; + + capsule_id = simple_strtoul(argv[0], &endp, 16); + if (capsule_id < 0 || capsule_id > 0xffff) + return CMD_RET_USAGE; + + sprintf(var_name, "Capsule%04X", capsule_id); + p = var_name16; + utf8_utf16_strncpy(&p, var_name, 9); + } + + size = 0; + ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL)); + if (ret == EFI_BUFFER_TOO_SMALL) { + result = malloc(size); + ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, + result)); + if (ret != EFI_SUCCESS) { + free(result); + printf("Failed to get %ls\n", var_name16); + + return CMD_RET_FAILURE; + } + } + + printf("Result total size: 0x%x\n", result->variable_total_size); + printf("Capsule guid: %pUl\n", &result->capsule_guid); + printf("Time processed: %04d-%02d-%02d %02d:%02d:%02d\n", + result->capsule_processed.year, result->capsule_processed.month, + result->capsule_processed.day, result->capsule_processed.hour, + result->capsule_processed.minute, + result->capsule_processed.second); + printf("Capsule status: 0x%lx\n", result->capsule_status); + + free(result); + + return CMD_RET_SUCCESS; +} + +static cmd_tbl_t cmd_efidebug_capsule_sub[] = { + U_BOOT_CMD_MKENT(update, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_update, + "", ""), + U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show, + "", ""), + U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res, + "", ""), +}; + +/** + * do_efi_capsule() - manage UEFI capsules + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, + * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule" sub-command. + */ +static int do_efi_capsule(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + cmd_tbl_t *cp; + + if (argc < 2) + return CMD_RET_USAGE; + + argc--; argv++; + + cp = find_cmd_tbl(argv[0], cmd_efidebug_capsule_sub, + ARRAY_SIZE(cmd_efidebug_capsule_sub)); + if (!cp) + return CMD_RET_USAGE; + + return cp->cmd(cmdtp, flag, argc, argv); +} +#endif /* CONFIG_EFI_CAPSULE_UPDATE */ + /** * efi_get_device_handle_info() - get information of UEFI device * @@ -1079,6 +1300,10 @@ static int do_efi_boot_opt(cmd_tbl_t *cmdtp, int flag, static cmd_tbl_t cmd_efidebug_sub[] = { U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""), +#ifdef CONFIG_EFI_CAPSULE_UPDATE + U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule, + "", ""), +#endif U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices, "", ""), U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers, @@ -1149,6 +1374,15 @@ static char efidebug_help_text[] = "efidebug boot order [ [ [ [...]]]]\n" " - set/show UEFI boot order\n" "\n" +#ifdef CONFIG_EFI_CAPSULE_UPDATE + "efidebug capsule update [-v] \n" + " - process a capsule\n" + "efidebug capsule show \n" + " - show capsule information\n" + "efidebug capsule result []\n" + " - show a capsule update result\n" + "\n" +#endif "efidebug devices\n" " - show UEFI devices\n" "efidebug drivers\n" From patchwork Tue Mar 17 02:12:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1256003 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=T+SoUq1D; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGwJ70BYz9sPF for ; Tue, 17 Mar 2020 13:15:12 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 34A2D81964; Tue, 17 Mar 2020 03:13:45 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="T+SoUq1D"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 522B68191C; Tue, 17 Mar 2020 03:13:13 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1041.google.com (mail-pj1-x1041.google.com [IPv6:2607:f8b0:4864:20::1041]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3F70C81917 for ; Tue, 17 Mar 2020 03:12:57 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pj1-x1041.google.com with SMTP id dw20so4606571pjb.0 for ; Mon, 16 Mar 2020 19:12:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RpfnHv4SSXat1Q2Giu/5dcO0fE7/HeyqRcdN1uFkNEY=; b=T+SoUq1D+E/VmozLLaX367iyX9zV+LqAESgK0NhUiaM9Mo7IWAg3eLXIoW5IVQhU8L d3M2gUi3k38dU9Uh+I0Zost3FzFDZ+10aM4B12UPBcyYjZyqYeMO7RlAxzhvPf6CSR8R IRSvbaTa/v5/qbULZCvOb1Pp1vIo4A2BtwbsAoPtaFLBsgxReOaiPDaqPc/XwZf9tGsc c1mBLbh45VJik3ITik+Ej3I+gB3kul0h/fTi3EzkHxVWsa29D3KIWc80HMNqqFU1aDZ1 3F1iTY20M420PzvEXD+BL2yN5Hly62KXVxR1tRBUL7al9bNryHXVl9ekovyLYyz7SwFt KyOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RpfnHv4SSXat1Q2Giu/5dcO0fE7/HeyqRcdN1uFkNEY=; b=bqbnpQt9Rww25wNQ+aHJ7EZvQlif1d4GFWPKIPNjtiUoe1pqkQpeoLzsE0ZQR4NHX3 wzYhHJQaZkPzVVluRtGnVbh6q2VXhgaoMlbHuNiTik4uaDALuJtpuDEY8PLmUOypykDi zrl/O8y4D1YUrufiHArYRiHswDdLp94RkNndToMB5KT2u2uL6wIv4giiA+L30t8mQX6z 8qtkX4xPHI8mZw/wH15v7bM4DCsuDduQE+/6CO1jXAST0r5tufSIy/8PWM8qsHp5CViC YAJmwUVVMVpZZUKpxgV2Vj+eB5BtC8VXlqMNVefzYInfwjgYeDfV+FHIPFgwjyThSAFI 4rQA== X-Gm-Message-State: ANhLgQ1HrJiiLwQqKLHqaTZkGz9etJXKP11gChsZ+PCWzU82yxP3gaSJ g3anKsgoN7bCjEmnT9s/6lqoMg== X-Google-Smtp-Source: ADFU+vsWw7A/VO5wMPDhNG+xvobumpeRy0wiKZV56Rzqi+QWjxk1EE3AGSlUqCtdCRaBdITpB7mudA== X-Received: by 2002:a17:90a:2103:: with SMTP id a3mr2635077pje.181.1584411175598; Mon, 16 Mar 2020 19:12:55 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id r13sm715590pgf.1.2020.03.16.19.12.54 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:54 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 13/14] tools: add mkeficapsule command for UEFI capsule update test Date: Tue, 17 Mar 2020 11:12:46 +0900 Message-Id: <20200317021247.5849-14-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean This is a utility mainly for test purpose. mkeficapsule -f: create a FIT image firmware capsule mkeficapsule -v: create a specific test case capsule for variables Having said that, you will be able to customize the code to fit your specific requirements for your platform. Signed-off-by: AKASHI Takahiro --- tools/Makefile | 3 + tools/mkeficapsule.c | 501 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 504 insertions(+) create mode 100644 tools/mkeficapsule.c diff --git a/tools/Makefile b/tools/Makefile index 99be724b82a5..fe07f8952f49 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -222,6 +222,9 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs hostprogs-$(CONFIG_ASN1_COMPILER) += asn1_compiler HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include +# TODO: only build this for capsule pytest +hostprogs-$(CONFIG_EFI_CAPSULE_UPDATE) += mkeficapsule + # We build some files with extra pedantic flags to try to minimize things # that won't build on some weird host compiler -- though there are lots of # exceptions for files that aren't complaint. diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c new file mode 100644 index 000000000000..732a54811df9 --- /dev/null +++ b/tools/mkeficapsule.c @@ -0,0 +1,501 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +/* + * TODO: use libefi/libgnuefi headers + */ + +typedef u_int8_t u8; +typedef u_int16_t u16; +typedef u_int32_t u32; +typedef u_int64_t u64; + +/* include/efi.h */ +typedef struct { + u8 b[16]; +} efi_guid_t; + +#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ + {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, \ + ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } } + +#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 + +/* include/efi_api.h */ +#define EFI_GLOBAL_VARIABLE_GUID \ + EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, \ + 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c) + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 +#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 + +#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID \ + EFI_GUID(0xae13ff2d, 0x9ad4, 0x4e25, 0x9a, 0xc8, \ + 0x6d, 0x80, 0xb3, 0xb2, 0x21, 0x47) + +#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID \ + EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \ + 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a) + +#define EFI_VARIABLE_STORAGE_GUID \ + EFI_GUID(0x1a3fb419, 0x2171, 0x458d, 0xb8, 0xb4, \ + 0xbe, 0xa3, 0x0c, 0x9f, 0x6b, 0xab) + +struct efi_capsule_header { + efi_guid_t capsule_guid; + u32 header_size; + u32 flags; + u32 capsule_image_size; +} __attribute__((packed)); + +struct efi_capsule_block_descriptor { + u64 length; + union { + u64 data_block; + u64 continuation_ptr; + }; +} __attribute__((packed)); + +struct efi_firmware_management_capsule_header { + u32 version; + u16 embedded_driver_count; + u16 payload_item_count; + u64 item_offset_list[]; +} __attribute__((packed)); + +struct efi_firmware_management_capsule_image_header { + u32 version; + efi_guid_t update_image_type_id; + u8 update_image_index; + u8 reserved[3]; + u32 update_image_size; + u32 update_vendor_code_size; + u64 update_hardware_instance; +} __attribute__((packed)); + +struct efi_ebbr_variable { + u16 variable_name[64]; + efi_guid_t vendor_guid; + u32 attributes; + u32 data_size; + u8 data[]; +}; + +struct efi_ebbr_variable_bundle { + struct efi_capsule_header header; + u8 reserved[0]; + struct efi_ebbr_variable variables[]; +} __attribute__((packed)); + +efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; +efi_guid_t efi_guid_image_type_uboot_fit = + EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID; +efi_guid_t efi_guid_variable_storage = EFI_VARIABLE_STORAGE_GUID; +efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; + +/* generated by efi boot add 3 TEST scsi 0:0 /EFI/Images/hello.efi "" */ +char boot_var3[] = "0100000052005400450053005400000001041400b9731de684a3cc4aaeab82e828f3628b0302080000000000040432005c005c004500460049005c0049006d0061006700650073005c00680065006c006c006f002e0065006600690000007fff040000"; +u16 boot_order[] = { + 0x0003, + 0x0002, +}; + +/* efi_variable.c */ +static int hex(int ch) +{ + if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + if (ch >= '0' && ch <= '9') + return ch - '0'; + if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + return -1; +} + +static int hex2mem(u8 *mem, const char *hexstr, int size) +{ + int nibble; + int i; + + for (i = 0; i < size; i++) { + if (*hexstr == '\0') + break; + + nibble = hex(*hexstr); + if (nibble < 0) + return -1; + + *mem = nibble; + hexstr++; + + nibble = hex(*hexstr); + if (nibble < 0) + return -1; + + *mem = (*mem << 4) | nibble; + hexstr++; + mem++; + } + + return i; +} + +void wcharcpy(u16 *dst, wchar_t *src, size_t n) +{ + int i; + + for (i = 0; i < n; i++) + *dst++ = *src++; +} + +static int create_fwbin(char *bin, char *path) +{ + struct efi_capsule_header header; + struct efi_firmware_management_capsule_header capsule; + struct efi_firmware_management_capsule_image_header image; + FILE *f, *g; + struct stat bin_stat; + u8 *data; + size_t size; + + g = fopen(bin, "r"); + if (!g) { + printf("cannot open %s\n", bin); + return -1; + } + if (stat(bin, &bin_stat) < 0) { + printf("cannot determine the size of %s\n", bin); + goto err_1; + } + data = malloc(bin_stat.st_size); + if (!data) { + printf("cannot allocate memory: %lx\n", bin_stat.st_size); + goto err_1; + } + f = fopen(path, "w"); + if (!f) { + printf("cannot open %s\n", path); + goto err_2; + } + header.capsule_guid = efi_guid_fm_capsule; + header.header_size = sizeof(header); + header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */ + header.capsule_image_size = sizeof(header) + + sizeof(capsule) + sizeof(u64) + + sizeof(image) + + bin_stat.st_size; + + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + goto err_3; + } + + capsule.version = 0x00000001; + capsule.embedded_driver_count = 0; + capsule.payload_item_count = 1; + capsule.item_offset_list[0] = sizeof(capsule) + sizeof(u64); + size = fwrite(&capsule, 1, sizeof(capsule) + sizeof(u64), f); + if (size < (sizeof(capsule) + sizeof(u64))) { + printf("write failed (%lx)\n", size); + goto err_3; + } + + image.version = 0x00000002; + image.update_image_type_id = efi_guid_image_type_uboot_fit; + image.update_image_index = 1; + image.update_image_size = bin_stat.st_size; + image.update_vendor_code_size = 0; /* none */ + image.update_hardware_instance = 1; + + size = fwrite(&image, 1, sizeof(image), f); + if (size < sizeof(image)) { + printf("write failed (%lx)\n", size); + goto err_3; + } + size = fread(data, 1, bin_stat.st_size, g); + if (size < bin_stat.st_size) { + printf("read failed (%lx)\n", size); + goto err_3; + } + size = fwrite(data, 1, bin_stat.st_size, f); + if (size < bin_stat.st_size) { + printf("write failed (%lx)\n", size); + goto err_3; + } + + fclose(f); + fclose(g); + free(data); + + return 0; + +err_3: + fclose(f); +err_2: + free(data); +err_1: + fclose(g); + + return -1; +} + +static int create_test1(char *path) +{ + FILE *f; + size_t size; + struct efi_capsule_header header; + struct efi_ebbr_variable variable; + u8 *data; + size_t data_size; + + f = fopen(path, "w"); + if (!f) { + printf("cannot open %s\n", path); + return -1; + } + header.capsule_guid = efi_guid_variable_storage; + header.header_size = sizeof(header); + header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */ + header.capsule_image_size = sizeof(header); + + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + return -1; + } + + /* add a new variable */ + data_size = sizeof(boot_var3) / 2; + data = malloc(data_size); + if (!data) { + printf("memory allocation failed\n"); + return -1; + } + hex2mem(data, boot_var3, data_size); + wcharcpy(variable.variable_name, L"Boot0003", 9); + variable.vendor_guid = efi_global_variable_guid; + variable.attributes = (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS); + variable.data_size = data_size; + header.capsule_image_size += sizeof(variable) + variable.data_size; + + size = fwrite(&variable, 1, sizeof(variable), f); + if (size < sizeof(variable)) { + printf("write failed (%lx)\n", size); + return -1; + } + size = fwrite(data, 1, data_size, f); + if (size < data_size) { + printf("write failed (%lx)\n", size); + return -1; + } + + /* update capsule image size */ + rewind(f); + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + return -1; + } + + fclose(f); + + return 0; +} + +static int create_test2(char *path) +{ + FILE *f; + size_t size; + struct efi_capsule_header header; + struct efi_ebbr_variable variable; + + f = fopen(path, "w"); + if (!f) { + printf("cannot open %s\n", path); + return -1; + } + header.capsule_guid = efi_guid_variable_storage; + header.header_size = sizeof(header); + header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */ + header.capsule_image_size = sizeof(header); + + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + return -1; + } + + /* modify an existing variable */ + wcharcpy(variable.variable_name, L"BootOrder", 10); + variable.vendor_guid = efi_global_variable_guid; + variable.attributes = (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS); + variable.data_size = sizeof(boot_order); + header.capsule_image_size += sizeof(variable) + variable.data_size; + + size = fwrite(&variable, 1, sizeof(variable), f); + if (size < sizeof(variable)) { + printf("write failed (%lx)\n", size); + return -1; + } + size = fwrite(boot_order, 1, sizeof(boot_order), f); + if (size < sizeof(boot_order)) { + printf("write failed (%lx)\n", size); + return -1; + } + + /* delete an existing variable */ + wcharcpy(variable.variable_name, L"Boot0001", 9); + variable.vendor_guid = efi_global_variable_guid; + variable.attributes = (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS); + variable.data_size = 0; + header.capsule_image_size += sizeof(variable) + variable.data_size; + + size = fwrite(&variable, 1, sizeof(variable), f); + if (size < sizeof(variable)) { + printf("write failed (%lx)\n", size); + return -1; + } + + /* update capsule image size */ + rewind(f); + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + return -1; + } + + fclose(f); + + return 0; +} + +static int create_test3(char *path) +{ + FILE *f; + size_t size; + struct efi_capsule_header header; + struct efi_ebbr_variable variable; + + f = fopen(path, "w"); + if (!f) { + printf("cannot open %s\n", path); + return -1; + } + header.capsule_guid = efi_guid_variable_storage; + header.header_size = sizeof(header); + header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */ + header.capsule_image_size = sizeof(header); + + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + return -1; + } + + /* delete a non-existing variable */ + wcharcpy(variable.variable_name, L"FooVar", 9); + variable.vendor_guid = efi_global_variable_guid; + variable.attributes = (EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS); + variable.data_size = 0; + header.capsule_image_size += sizeof(variable) + variable.data_size; + + size = fwrite(&variable, 1, sizeof(variable), f); + if (size < sizeof(variable)) { + printf("write failed (%lx)\n", size); + return -1; + } + + /* update capsule image size */ + rewind(f); + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + return -1; + } + + fclose(f); + + return 0; +} + +void print_usage(void) +{ + printf("mkeficapsule [-f | -t ]\n"); +} + +/* + * Usage: + * $ mkeficapsule [-f | -t ] + */ +int main(int argc, char **argv) +{ + int test_no; + + if (argc != 4) { + print_usage(); + return -1; + } + + if (!strcmp(argv[1], "-f")) { + if (create_fwbin(argv[2], argv[3]) < 0) { + printf("Creating firmware capsule for %s failed\n", + argv[2]); + return -1; + } + + return 0; + } else if (!strcmp(argv[1], "-v")) { + test_no = atoi(argv[2]); + + switch (test_no) { + case 1: + if (create_test1(argv[3]) < 0) { + printf("Creating test%02x failed\n", test_no); + return -1; + } + break; + case 2: + if (create_test2(argv[3]) < 0) { + printf("Creating test%02x failed\n", test_no); + return -1; + } + break; + case 3: + if (create_test3(argv[3]) < 0) { + printf("Creating test%02x failed\n", test_no); + return -1; + } + break; + default: + printf("Invalid test number: %s\n", argv[2]); + return -1; + } + + return 0; + } + + print_usage(); + return -1; +} From patchwork Tue Mar 17 02:12:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1256001 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=VFjLDW9z; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48hGvt273dz9sPF for ; Tue, 17 Mar 2020 13:14:50 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 10A3D8194E; Tue, 17 Mar 2020 03:13:38 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="VFjLDW9z"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9332781955; Tue, 17 Mar 2020 03:13:12 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x42c.google.com (mail-pf1-x42c.google.com [IPv6:2607:f8b0:4864:20::42c]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A3E82818F6 for ; Tue, 17 Mar 2020 03:13:00 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x42c.google.com with SMTP id i13so11051498pfe.3 for ; Mon, 16 Mar 2020 19:13:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=E5zGzgfxvJisbC9GuKCZ/6CFaYbSbqKup2LkECucWkI=; b=VFjLDW9zLpe8OtDmvN4BS+EHAzeRdYVc9wi/TKr4/ro6kUhie8LaJQajpGpLwP5Wit VtH2Cf7wFfHH/LPccj00KBNb2KfKXT0kQO+t/JKLO26SWxvWmuVR7BrbKQITMRxVyTie X7/EcHr/kN0SYxQ0gAt4CBMU1Hl3uFdUQDCMuJeXloqU0VttysB49rqnoRGozlw87NOb vPHEgk3PxXeJgUz/QdsjO5FsnSBHLvb+8P82w0jR2xB9XPGnHqTp4ElGjCzUM8Q8EJiS NXL4CkgHUjFCFZ6b00gxTHS/lv3cRNOC1J2u79A4fi4Jc2oQDvz00NJ9gshBiM7msxZh 5jHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=E5zGzgfxvJisbC9GuKCZ/6CFaYbSbqKup2LkECucWkI=; b=jRgaNt39y8sex3rg6OISJ2HE99Azl/nD8AhEg5hzIQU9nixWMcvgTAhLiYrMEMB1LJ nMOcaphnots1TLFrDM24CCKsppHLqtH5UEQ+cRTPIfpO7AdEdVXbTaE1gGvuVMtCXYf3 1TTdQ7DiFBV4qbwov2tk78TuG5dCrxX6KeGh0F48oYduWHAlQxW0LQqFncYzga+MAiAP TDn+D3GOQPjh2hyRuboMdTLLvs+HCussWgeB+cibeg5zf2op+j1UsPb7uPUfSCdbJMpn VzyatpUo+nKV6PygrJxa2xyY4khtjTAwUr6syQHc00S/SKnytUVS1YOD7nqG5plBaxbx Khog== X-Gm-Message-State: ANhLgQ1V+1k9O5duS5s6HLLbSsTfD3xHmJvKunzM8up6Q2/DrZQiq06G zOMHlKUOIxVhQb8XM1FZZQkjdQ== X-Google-Smtp-Source: ADFU+vsKJyIE5vx6rVmA47L5yj9WD4Gp+REswtAbPSE1jWrUPuQljcBM/q/vXlihzSUM68P5YhWSJg== X-Received: by 2002:a62:de83:: with SMTP id h125mr2619422pfg.161.1584411178951; Mon, 16 Mar 2020 19:12:58 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id e184sm1038934pfh.219.2020.03.16.19.12.57 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 16 Mar 2020 19:12:58 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: ilias.apalodimas@linaro.org, sughosh.ganu@linaro.org, u-boot@lists.denx.de Subject: [RFC 14/14] test/py: add efi capsule test Date: Tue, 17 Mar 2020 11:12:47 +0900 Message-Id: <20200317021247.5849-15-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317021247.5849-1-takahiro.akashi@linaro.org> References: <20200317021247.5849-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean We will have two pytest scenarios for capsule update here. * for firmware update (based on simple firmware management protocol) * for variable update Both can run on sandbox build and gives you some idea about how they should work on production system. Signed-off-by: AKASHI Takahiro --- test/py/tests/test_efi_capsule/conftest.py | 109 ++++++++++++++ test/py/tests/test_efi_capsule/defs.py | 21 +++ .../test_efi_capsule/test_capsule_firmware.py | 102 +++++++++++++ .../test_efi_capsule/test_capsule_variable.py | 141 ++++++++++++++++++ test/py/tests/test_efi_capsule/uboot_env.its | 25 ++++ 5 files changed, 398 insertions(+) create mode 100644 test/py/tests/test_efi_capsule/conftest.py create mode 100644 test/py/tests/test_efi_capsule/defs.py create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware.py create mode 100644 test/py/tests/test_efi_capsule/test_capsule_variable.py create mode 100644 test/py/tests/test_efi_capsule/uboot_env.its diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py new file mode 100644 index 000000000000..5d50df95cdf0 --- /dev/null +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020, Linaro Limited +# Author: AKASHI Takahiro + +import os +import os.path +import pytest +import re +from subprocess import call, check_call, check_output, CalledProcessError +from defs import * + +# from test/py/conftest.py +def tool_is_in_path(tool): + for path in os.environ["PATH"].split(os.pathsep): + fn = os.path.join(path, tool) + if os.path.isfile(fn) and os.access(fn, os.X_OK): + return True + return False + +# +# Fixture for UEFI secure boot test +# +@pytest.fixture(scope='session') +def efi_capsule_data(request, u_boot_config): + """Set up a file system to be used in UEFI capsule test. + + Args: + request: Pytest request object. + u_boot_config: U-boot configuration. + + Return: + A path to disk image to be used for testing + """ + image_path = u_boot_config.persistent_data_dir + image_path = image_path + '/' + EFI_BOOTDEV_IMAGE_NAME + image_size = EFI_BOOTDEV_IMAGE_SIZE + part_size = EFI_BOOTDEV_PART_SIZE + fs_type = EFI_BOOTDEV_FS_TYPE + + try: + # non_root = tool_is_in_path('udisksctl') + non_root = False + + # create a disk/partition + check_call('dd if=/dev/zero of=%s bs=1MiB count=%d' + % (image_path, image_size), shell=True) + check_call('sgdisk %s -n 1:0:+%dMiB' + % (image_path, part_size), shell=True) + # create a file system + check_call('dd if=/dev/zero of=%s.tmp bs=1MiB count=%d' + % (image_path, part_size), shell=True) + check_call('mkfs -t %s %s.tmp' % (fs_type, image_path), shell=True) + check_call('dd if=%s.tmp of=%s bs=1MiB seek=1 count=%d conv=notrunc' + % (image_path, image_path, 1), shell=True) + check_call('rm %s.tmp' % image_path, shell=True) + if non_root: + out_data = check_output('udisksctl loop-setup -f %s -o %d' + % (image_path, 1048576), shell=True).decode() + m = re.search('(?<= as )(.*)\.', out_data) + loop_dev = m.group(1) + # print('loop device is: %s' % loop_dev) + out_data = check_output('udisksctl info -b %s' + % loop_dev, shell=True).decode() + m = re.search('MountPoints:[ \t]+(.*)', out_data) + mnt_point = m.group(1) + else: + loop_dev = check_output('sudo losetup -o 1MiB --sizelimit %dMiB --show -f %s | tr -d "\n"' + % (part_size, image_path), shell=True).decode() + mnt_point = '/mnt' + check_call('sudo mount -t %s -o umask=000 %s %s' + % (fs_type, loop_dev, mnt_point), shell=True) + + # print('1: mount point is: %s' % mnt_point) + + # Add variable capsules + check_call('mkdir -p %s%s' % (mnt_point, CAPSULE_DATA_DIR), shell=True) + check_call('mkdir -p %s%s' % (mnt_point, CAPSULE_INSTALL_DIR), shell=True) + check_call('%s/tools/mkeficapsule -v 1 %s%s/tESt01' + % (u_boot_config.build_dir, mnt_point, + CAPSULE_DATA_DIR), shell=True) + check_call('%s/tools/mkeficapsule -v 2 %s%s/Test02' + % (u_boot_config.build_dir, + mnt_point, CAPSULE_DATA_DIR), shell=True) + check_call('%s/tools/mkeficapsule -v 3 %s%s/TeST03' + % (u_boot_config.build_dir, + mnt_point, CAPSULE_DATA_DIR), shell=True) + + # Create its for FIT image + check_call('sed -e \"s?BINFILE?%s%s/%s?\" %s/test/py/tests/test_efi_capsule/uboot_env.its > %s%s/uboot_env.its' + % (mnt_point, CAPSULE_DATA_DIR, FW_BIN, + u_boot_config.source_dir, + mnt_point, CAPSULE_DATA_DIR), shell=True) + + if non_root: + call('udisksctl unmount -b %s' % loop_dev, shell=True) + # not needed + # check_call('udisksctl loop-delete -b %s' % loop_dev, shell=True) + else: + call('sudo umount %s' % loop_dev, shell=True) + call('sudo losetup -d %s' % loop_dev, shell=True) + + except CalledProcessError as e: + pytest.skip('Setup failed: %s' % e.cmd) + return + else: + yield image_path + finally: + print('1: mount point is: %s' % mnt_point) + # call('rm -f %s' % image_path, shell=True) diff --git a/test/py/tests/test_efi_capsule/defs.py b/test/py/tests/test_efi_capsule/defs.py new file mode 100644 index 000000000000..c2083b59c19f --- /dev/null +++ b/test/py/tests/test_efi_capsule/defs.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0+ + +# Disk image name +EFI_BOOTDEV_IMAGE_NAME='test_efi_capsule.img' + +# Size in MiB +EFI_BOOTDEV_IMAGE_SIZE=16 +EFI_BOOTDEV_PART_SIZE=8 + +# Partition file system type +EFI_BOOTDEV_FS_TYPE='vfat' + +# Owner guid +GUID='11111111-2222-3333-4444-123456789abc' + +# Directories +CAPSULE_DATA_DIR='/EFI/CapsuleTestData' +CAPSULE_INSTALL_DIR='/EFI/UpdateCapsule' + +# +FW_BIN='spi_sf.bin' diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py new file mode 100644 index 000000000000..52f8fa108ebd --- /dev/null +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Capsule Update for Simple FIT Image Test + +""" +This test verifies capsule-on-disk firmware update +""" + +import pytest +import re +from defs import * +from subprocess import call, check_call, check_output, CalledProcessError + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_capsule_fit_simple') +@pytest.mark.buildconfigspec('efi_capsule_on_disk') +@pytest.mark.buildconfigspec('dfu') +@pytest.mark.buildconfigspec('dfu_sf') +@pytest.mark.buildconfigspec('dfu_tftp') +@pytest.mark.buildconfigspec('cmd_efidebug') +@pytest.mark.buildconfigspec('cmd_fat') +@pytest.mark.buildconfigspec('cmd_nvedit_efi') +@pytest.mark.slow +class TestEfiCapsuleFirmwareSimple(object): + def test_efi_capsule_fw1(self, u_boot_config, u_boot_console, efi_capsule_data): + """ + Test Case 1 - Update U-Boot environment on SPI Flash + """ + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 1-a, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""', + 'efidebug boot order 1', + 'env set dfu_alt_info sf raw 0 0x200000', + 'env set FW_STATUS This is Old environment', + 'env print FW_STATUS', + 'env save']) + assert('Old environment' in ''.join(output)) + + output = u_boot_console.run_command_list([ + 'env set FW_STATUS This is New environment', + 'env export -c 5000000', + 'fatwrite host 0:1 5000000 %s/%s $filesize' + % (CAPSULE_DATA_DIR, FW_BIN), + 'setenv -e -guid 39b68c46-f7fb-441b-b6ec-16b0f69821f3 Capsule0000', + 'fatls host 0:1 %s' % CAPSULE_DATA_DIR + ]) + assert(('%s' % FW_BIN) in ''.join(output)) + + + try: + part_size = EFI_BOOTDEV_PART_SIZE + fs_type = EFI_BOOTDEV_FS_TYPE + mnt_point = '/mnt' + + loop_dev = check_output('sudo losetup -o 1MiB --sizelimit %dMiB --show -f %s | tr -d "\n"' + % (part_size, disk_img), shell=True).decode() + check_call('sudo mount -t %s -o umask=000 %s %s' + % (fs_type, loop_dev, mnt_point), shell=True) + check_call('%s/tools/mkimage -f %s%s/uboot_env.its %s%s/uboot_env.itb' + % (u_boot_config.build_dir, + mnt_point, CAPSULE_DATA_DIR, + mnt_point, CAPSULE_DATA_DIR), shell=True) + check_call('%s/tools/mkeficapsule -f %s%s/uboot_env.itb %s%s/Test01' + % (u_boot_config.build_dir, + mnt_point, CAPSULE_DATA_DIR, + mnt_point, CAPSULE_INSTALL_DIR), shell=True) + check_call('sudo umount %s' % loop_dev, shell=True) + check_call('sudo losetup -d %s' % loop_dev, shell=True) + except CalledProcessError: + assert('failed to create firmware capsule') + + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 1-b, after reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'env print FW_STATUS']) + assert('Old environment' in ''.join(output)) + + output = u_boot_console.run_command('fatls host 0:1 %s' + % CAPSULE_INSTALL_DIR) + assert('Test01' in output) + + output = u_boot_console.run_command('env print -e -all Capsule0000') + # assert('Capsule0000 not found' in output) + + # output = u_boot_console.run_command('printenv -e -all Capsule0000') + # assert('00000000: 01' in output) + + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 1-c, after reboot'): + output = u_boot_console.run_command('env print FW_STATUS') + assert('New environment' in ''.join(output)) + + output = u_boot_console.run_command( + 'fatls host 0:1 %s/Test01' % CAPSULE_INSTALL_DIR) + assert('' == output) diff --git a/test/py/tests/test_efi_capsule/test_capsule_variable.py b/test/py/tests/test_efi_capsule/test_capsule_variable.py new file mode 100644 index 000000000000..baf4329e9a27 --- /dev/null +++ b/test/py/tests/test_efi_capsule/test_capsule_variable.py @@ -0,0 +1,141 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Capsule Update for Variables Test + +""" +This test verifies capsule-on-disk variable update +""" + +import pytest +import re +from defs import * + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_capsule_update_variable') +@pytest.mark.buildconfigspec('efi_capsule_on_disk') +@pytest.mark.buildconfigspec('cmd_fat') +@pytest.mark.buildconfigspec('cmd_nvedit_efi') +@pytest.mark.slow +class TestEfiCapsuleVariable(object): + def test_efi_capsule_var1(self, u_boot_console, efi_capsule_data): + """ + Test Case 1 - Add a new UEFI variable + """ + u_boot_console.restart_uboot() + + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 1, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""', + 'efidebug boot order 1', + 'setenv -e -guid 39b68c46-f7fb-441b-b6ec-16b0f69821f3 Capsule0000', + 'setenv -e -guid 39b68c46-f7fb-441b-b6ec-16b0f69821f3 Capsule0001', + 'setenv -e -guid 39b68c46-f7fb-441b-b6ec-16b0f69821f3 Capsule0002', + 'setenv -e Boot0003', + 'saveenv', + 'fatload host 0:1 0x5000000 %s/tESt01' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 0x5000000 %s/tESt01 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert('tESt01' in ''.join(output)) + + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 1, after reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'printenv -e Boot0003']) + assert('Boot0003:' in ''.join(output)) + + output = u_boot_console.run_command( + 'printenv -e -all') + + output = u_boot_console.run_command( + 'efidebug capsule result') + assert('CapsuleLast is' in output) + assert('Capsule status: 0x0' in output) + + output = u_boot_console.run_command( + 'fatls host 0:1 %s/tESt01' % CAPSULE_INSTALL_DIR) + u_boot_console.run_command('fatrm host 0:1 %s/tESt01' + % CAPSULE_INSTALL_DIR) + assert('' == output) + + def test_efi_capsule_var2(self, u_boot_console, efi_capsule_data): + """ + Test Case 2 - Modify/Delete existing variables + """ + u_boot_console.restart_uboot() + + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 2, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 TEST1 host 0:1 /helloworld.efi ""', + 'efidebug boot add 2 TEST2 host 0:1 /helloworld.efi ""', + 'efidebug boot order 1 2', + 'saveenv', + 'fatload host 0:1 0x5000000 %s/Test02' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 0x5000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert('Test02' in ''.join(output)) + + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 2, after reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'printenv -e BootOrder']) + assert('00000000: 03 00 02 00' in ''.join(output)) + + output = u_boot_console.run_command( + 'printenv -e Boot0001') + assert('"Boot0001" not defined' in output) + + output = u_boot_console.run_command( + 'efidebug capsule result') + assert('CapsuleLast is' in output) + assert('Capsule status: 0x0' in output) + + output = u_boot_console.run_command( + 'fatls host 0:1 %s/Test02' % CAPSULE_INSTALL_DIR) + u_boot_console.run_command('fatrm host 0:1 %s/Test02' % CAPSULE_INSTALL_DIR) + assert('' == ''.join(output)) + + def test_efi_capsule_var3(self, u_boot_console, efi_capsule_data): + """ + Test Case 3 - Modify a non-existing variable + """ + u_boot_console.restart_uboot() + + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 3, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""', + 'efidebug boot order 1', + 'saveenv', + 'fatload host 0:1 0x5000000 %s/TeST03' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 0x5000000 %s/TeST03 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert('TeST03' in ''.join(output)) + + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 3, after reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'printenv -e FooVar']) + assert('"FooVar" not defined' in ''.join(output)) + + output = u_boot_console.run_command( + 'efidebug capsule result') + assert('CapsuleLast is' in output) + assert('Capsule status: 0x0' in output) + + output = u_boot_console.run_command( + 'fatls host 0:1 %s/TeST03' % CAPSULE_INSTALL_DIR) + u_boot_console.run_command('fatrm host 0:1 %s/TeST03' % CAPSULE_INSTALL_DIR) + assert('' == ''.join(output)) diff --git a/test/py/tests/test_efi_capsule/uboot_env.its b/test/py/tests/test_efi_capsule/uboot_env.its new file mode 100644 index 000000000000..a4484db45834 --- /dev/null +++ b/test/py/tests/test_efi_capsule/uboot_env.its @@ -0,0 +1,25 @@ +/* + * Automatic software update for U-Boot + * Make sure the flashing addresses ('load' prop) is correct for your board! + */ + +/dts-v1/; + +/ { + description = "Automatic U-Boot environment update"; + #address-cells = <2>; + + images { + sf@0 { + description = "U-Boot environment on SPI Flash"; + data = /incbin/("BINFILE"); + compression = "none"; + type = "firmware"; + arch = "sandbox"; + load = <0>; + hash-1 { + algo = "sha1"; + }; + }; + }; +};