From patchwork Wed Jun 5 04:21:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1110294 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=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="gumXfDDU"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 45JbHM4ZwXz9s3Z for ; Wed, 5 Jun 2019 14:22:39 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 20097C21DB3; Wed, 5 Jun 2019 04:22:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id BA68CC21DA2; Wed, 5 Jun 2019 04:21:14 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 8CF65C21DFD; Wed, 5 Jun 2019 04:21:02 +0000 (UTC) Received: from mail-pg1-f196.google.com (mail-pg1-f196.google.com [209.85.215.196]) by lists.denx.de (Postfix) with ESMTPS id 73DB1C21DB3 for ; Wed, 5 Jun 2019 04:20:59 +0000 (UTC) Received: by mail-pg1-f196.google.com with SMTP id s27so6041833pgl.2 for ; Tue, 04 Jun 2019 21:20:59 -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=WMSdPWLu57Myt9KHrIGuP/8PkZ7OdSmXVyo8lXhXueI=; b=gumXfDDULmxKlbkRk8Q8qKuL7KGbuuRRqmoiX4+72xQg/rAdtaljdfqKTySnnixtC3 PeBevUERw1re5n+EBHis8/uwpz3zHuKh9zce9YvaCsdmmFQDX8q5yPhEphFwZSK40Kzx /Lx4x8W89pPghjaMSxXdSFVRNWEdIQEhwe3xVLa2nzJPdL7NdjLHZdF8mPfCcV8kDmVu 96uQftNbry+rLWGXjq8BMx4GhRO6rfvAYqJsZMuoLVubPiZL4/2ZP16lvER18jv4OMpG 1UqdgjU5p/Hj2CDfpZLAD8yAjJWpkrlF/igdQYweZ37Rf1YKi+STeTCwJLjElDF9Db1B X0YA== 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=WMSdPWLu57Myt9KHrIGuP/8PkZ7OdSmXVyo8lXhXueI=; b=OvB8Y8oEdDezlyK8FT7/EajHyfNpD2cacEm0294je9DIcJ8mUPOQmEpa1lywAz9rn3 YV4D90OqcnrytiE8jmw8zbnWmy0osWSAtjTXIbQAlrIAgsTaZreEg32pSqjs9Pw/zJX8 Wb66oFLGql6oWTcsfrSOdQVmaPfjeslY8iYlGdZDQn0lvdLp4kUX/Qb4TM8emguzR9mX klraOo7h6sNBmmkiPfciHgAq+kmq5NQHQIge6GIGcSMN4soiAxilIP+axHegQrVYMEnU ppoiR+SR4kAFwJU4OMzmJPGDuoTuViOyCouza4o+f8xM9wlQLG3/ireYP3bwzpHc+Eh+ H9Vg== X-Gm-Message-State: APjAAAWNzONiVFw+8wmi1SsoOZZ/VEXZkLcWVbZ1oGH3KBeGQEmMH0ve k3WxOJpG0GB3lcdfBsNa5eLdrw== X-Google-Smtp-Source: APXvYqwxN7g7UBlLYwKZ0qPqi/wf5ONIXh14eyYHpDYYt8CfVEJdEhCQK6J4XJnpmPg2i98gQVt7SA== X-Received: by 2002:a65:5344:: with SMTP id w4mr1596888pgr.8.1559708456857; Tue, 04 Jun 2019 21:20:56 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id 63sm9266784pfv.149.2019.06.04.21.20.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Jun 2019 21:20:56 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Date: Wed, 5 Jun 2019 13:21:37 +0900 Message-Id: <20190605042142.15113-2-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190605042142.15113-1-takahiro.akashi@linaro.org> References: <20190605042142.15113-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 1/6] efi_loader: runtime: make SetVirtualAddressMap configurable X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" OS does not always need to call SetVirtualAddressMap. (Ard confirmed this on arm64 linux.) So let this API configurable. If disabled, it will return EFI_UNSUPPORTED as UEFI specification requires. Signed-off-by: AKASHI Takahiro --- lib/efi_loader/Kconfig | 7 +++++++ lib/efi_loader/efi_runtime.c | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 8bf4b1754d06..bb9c7582b14d 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -44,6 +44,13 @@ 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_RUNTIME_SET_VIRTUAL_ADDRESS_MAP + bool "runtime service: SetVirtualAddressMap" + default n + help + Enable SetVirtualAddressMap runtime service. This API will be + called by OS just before it enters into virtual address mode. + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 9c50955c9bd0..60442cb21d37 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -374,10 +374,12 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { /* do_reset is gone */ .ptr = &efi_runtime_services.reset_system, .patchto = efi_reset_system, +#ifdef CONFIG_RUNTIME_SET_VIRTUAL_ADDRESS_MAP }, { /* invalidate_*cache_all are gone */ .ptr = &efi_runtime_services.set_virtual_address_map, .patchto = &efi_unimplemented, +#endif }, { /* RTC accessors are gone */ .ptr = &efi_runtime_services.get_time, @@ -512,6 +514,7 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) invalidate_icache_all(); } +#ifdef CONFIG_RUNTIME_SET_VIRTUAL_ADDRESS_MAP /** * efi_set_virtual_address_map() - change from physical to virtual mapping * @@ -619,6 +622,7 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( return EFI_EXIT(EFI_INVALID_PARAMETER); } +#endif /* CONFIG_RUNTIME_SET_VIRTUAL_ADDRESS_MAP */ /** * efi_add_runtime_mmio() - add memory-mapped IO region @@ -796,7 +800,11 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .set_time = &efi_set_time_boottime, .get_wakeup_time = (void *)&efi_unimplemented, .set_wakeup_time = (void *)&efi_unimplemented, +#ifdef CONFIG_RUNTIME_SET_VIRTUAL_ADDRESS_MAP .set_virtual_address_map = &efi_set_virtual_address_map, +#else + .set_virtual_address_map = (void *)&efi_unimplemented, +#endif .convert_pointer = (void *)&efi_invalid_parameter, .get_variable = efi_get_variable, .get_next_variable_name = efi_get_next_variable_name, From patchwork Wed Jun 5 04:21:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1110293 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=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="eIzm1Y+O"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 45JbGW2Xp5z9s3Z for ; Wed, 5 Jun 2019 14:21:55 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id D9071C21DF8; Wed, 5 Jun 2019 04:21:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 3EE35C21DB6; Wed, 5 Jun 2019 04:21:13 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 24882C21E15; Wed, 5 Jun 2019 04:21:04 +0000 (UTC) Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) by lists.denx.de (Postfix) with ESMTPS id 40997C21BE5 for ; Wed, 5 Jun 2019 04:21:01 +0000 (UTC) Received: by mail-pf1-f178.google.com with SMTP id a23so14073842pff.4 for ; Tue, 04 Jun 2019 21:21:01 -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=Zb6y2MHh8IF+efiwfvSi0VIbvG8477J/kldRLjkWc1E=; b=eIzm1Y+Otgf0QA8xuGtmsLvRUbJNbGPRko0rEIKyH5Ynm7z/0veQhVfr4isgrhz2ZX 0zZlbQ6FzZh9Zgv+TMYBHOVczK5ia1zUW4mQjJTGNfJVvW0BYBw0Ail7m09CvuP6RbiY ipo306my/qeI6lF78gsrHO40Tg7qTu95ltUXh7ZyBV9XqduN/RK8g/kEKmIxD2EWn72u m/DzfTwGQBdpHITr/4ZDIn3Ni49l2sLQ35zFW+yp1SbVFMYWsWblPDjO6A4/TAz+ka4U XXl3sGJHhW7kjXlSdtdwNRKrYOvNOrr59FzEfpHZy3xDF5mhrCjAKtkabP/BzgVvAmCc nSRw== 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=Zb6y2MHh8IF+efiwfvSi0VIbvG8477J/kldRLjkWc1E=; b=oaodgSR4Ub5hgFLsY1IZcTo9zg5enBHuD0s3kwHeDvxwnLeDoUl4pul4rrnCwUBdnU GSW8/uuBV/jGt/cb8V8B2p4+OK1CVpKV4YrN7M1cOEBgXAQgri13qWIO3j8tmTe1Wgka +YGAHxWpIx5B9ctsUbnO3feV4Q8QKUI7COrhYCY93U93aG7L+85c1UrQr8kCdEARSlQ7 v3YizJKbxmM4eOYlKUHA/o8pNsbZBqnKIQn0foEknDI5GVDmrj3qnS7yca2hmGB0qX9j VlW7uvU4GtOG1WlP4jVxy8UsepxBVXGS3ZBsTQAVDJ9wto5Mle0zLWaomRMIKYl/DUeY 3lNQ== X-Gm-Message-State: APjAAAV+0nMCrQWCEjwNzbUcSwPApCyMlRzNzdO9+d2mrGWMOHSCXWY9 uoCn4qXSG58N+RiuiN4yLznDWg== X-Google-Smtp-Source: APXvYqxXWyrvtr7oJdLMene7fByl1WRYS5odBV79wqF5u8VGDVlZPUoBE15akHbn+iKVmQHbMFmgYw== X-Received: by 2002:aa7:82cd:: with SMTP id f13mr44014007pfn.203.1559708459690; Tue, 04 Jun 2019 21:20:59 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id i5sm1044887pjj.8.2019.06.04.21.20.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Jun 2019 21:20:59 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Date: Wed, 5 Jun 2019 13:21:38 +0900 Message-Id: <20190605042142.15113-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190605042142.15113-1-takahiro.akashi@linaro.org> References: <20190605042142.15113-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 2/6] efi: add RuntimeServicesSupported variable X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" This variable is defined in UEFI specification 2.8, section 8.1. Its value should be updated whenever we add any usable runtime services function. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 15 +++++++++++++++ include/efi_loader.h | 3 +++ lib/efi_loader/efi_runtime.c | 28 ++++++++++++++++++++++++++++ lib/efi_loader/efi_setup.c | 5 +++++ 4 files changed, 51 insertions(+) diff --git a/include/efi_api.h b/include/efi_api.h index 65584dd2d82a..d7d95edd4dfc 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -213,6 +213,21 @@ struct efi_capsule_header { u32 capsule_image_size; }; +#define EFI_RT_SUPPORTED_GET_TIME 0x0001 +#define EFI_RT_SUPPORTED_SET_TIME 0x0002 +#define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 +#define EFI_RT_SUPPORTED_SET_WAKEUP_TIME 0x0008 +#define EFI_RT_SUPPORTED_GET_VARIABLE 0x0010 +#define EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME 0x0020 +#define EFI_RT_SUPPORTED_SET_VARIABLE 0x0040 +#define EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP 0x0080 +#define EFI_RT_SUPPORTED_CONVERT_POINTER 0x0100 +#define EFI_RT_SUPPORTED_GET_NEXT_HIGH_MONOTONIC_COUNT 0x0200 +#define EFI_RT_SUPPORTED_RESET_SYSTEM 0x0400 +#define EFI_RT_SUPPORTED_UPDATE_CAPSULE 0x0800 +#define EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES 0x1000 +#define EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO 0x2000 + struct efi_runtime_services { struct efi_table_hdr hdr; efi_status_t (EFIAPI *get_time)(struct efi_time *time, diff --git a/include/efi_loader.h b/include/efi_loader.h index 23ce73226762..7bd8002e303e 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -573,6 +573,9 @@ static inline int guidcmp(const efi_guid_t *g1, const efi_guid_t *g2) #define __efi_runtime_data __attribute__ ((section (".data.efi_runtime"))) #define __efi_runtime __attribute__ ((section (".text.efi_runtime"))) +/* Indicate supported runtime services */ +efi_status_t efi_init_runtime_supported(void); + /* Update CRC32 in table header */ void __efi_runtime efi_update_table_header_crc32(struct efi_table_hdr *table); diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 60442cb21d37..cf202bb9ec07 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -89,6 +89,34 @@ struct elf_rela { * handle a good number of runtime callbacks */ +efi_status_t efi_init_runtime_supported(void) +{ + u16 efi_runtime_services_supported; + + /* + * This value must be synced with efi_runtime_detach_list + * as well as efi_runtime_services. + */ + efi_runtime_services_supported = EFI_RT_SUPPORTED_RESET_SYSTEM; +#ifdef CONFIG_EFI_GET_TIME + efi_runtime_services_supported |= EFI_RT_SUPPORTED_GET_TIME; +#endif +#ifdef CONFIG_EFI_SET_TIME + efi_runtime_services_supported |= EFI_RT_SUPPORTED_SET_TIME; +#endif +#ifdef CONFIG_EFI_RUNTIME_SET_VIRTUAL_ADDRESS_MAP + efi_runtime_services_supported |= + EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP; +#endif + + return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(efi_runtime_services_supported), + &efi_runtime_services_supported)); +} + /** * efi_update_table_header_crc32() - Update crc32 in table header * diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 45d6aca051f3..75fa344060d5 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -123,6 +123,11 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + /* Indicate supported runtime services */ + ret = efi_init_runtime_supported(); + if (ret != EFI_SUCCESS) + goto out; + /* Initialize system table */ ret = efi_initialize_system_table(); if (ret != EFI_SUCCESS) From patchwork Wed Jun 5 04:21:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1110295 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=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="tTcvn58R"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 45JbHz5tZ1z9s3Z for ; Wed, 5 Jun 2019 14:23:11 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 7C06FC21C3F; Wed, 5 Jun 2019 04:22:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 7CA25C21DF9; Wed, 5 Jun 2019 04:21:21 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id B4BCEC21DD4; Wed, 5 Jun 2019 04:21:06 +0000 (UTC) Received: from mail-pg1-f193.google.com (mail-pg1-f193.google.com [209.85.215.193]) by lists.denx.de (Postfix) with ESMTPS id C3E07C21DA2 for ; Wed, 5 Jun 2019 04:21:03 +0000 (UTC) Received: by mail-pg1-f193.google.com with SMTP id v11so11649186pgl.5 for ; Tue, 04 Jun 2019 21:21:03 -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=rgYo04PIrTb5mkCktON7TVufFICJqtEwGY/zjOIGiwU=; b=tTcvn58RHBPfPSdn+0VtGWV+FseMR1cCDuRAu9frDP83kiBW+Qf51OVpUadhyrWu01 W50cIfLvlcs+GkdqmCT6Hgieb3rROZwRPn0wCuvl/6uFvLt9te4NYaOuQEStKrO6gFlK 9bQ6BBsI/NaeGnb7rgFCUD10Z1OMXnJDo64T0fwVuz5lEgCcaHVHPuFU6URFe3Qx8xV4 /jikY8PqEYmfo7aEi3dFlv03Q2dhdXPo0AYV+ojrrXb339tvIh0Fw2oM78/TQ8x7lK3R 5iG/O1oQ1/ye2PaGjQrozfckkve6uy51zilyUv3tzUpKW5Wu6zb95DGw/cxNcd5kufNQ sYEA== 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=rgYo04PIrTb5mkCktON7TVufFICJqtEwGY/zjOIGiwU=; b=GbDktIncs0K08OySEvadtq5s3y5HO5Of/45aYKJpZmiBYAy+ElJexXMvspEHI6AyXd dav9opQGWJS6kE9ttJrl+StwL1UBa8lJVWaRqzlB2vfKshHnfUo+n4ZzxmYOZ7J2MrzI TrMO9zpPPL8bgAA8qYo9p4BAkqslBPmNwu7HqntrpV6o9GvvXyzPXjCoSjvvIH9sAFF0 sByAEgNZ/6LT2EYf314s+cO5QsbkcUjcgsI/HSuFH/yFbY5x1vyuBSTXCUb+QsctKhJh El+J6qLdNrkqu30qIAjfIg/GYnpl/leRrf6IjHBadim0UicHQy0cWaZU6MmuKm6yH+c0 C6pg== X-Gm-Message-State: APjAAAW1q5+hVCR95hhJV4XtD38Loj5898UHHGws3+MsYhPtGrOzgcP4 EoZoW1Cx9BFAOZEOHATEqqNEJg== X-Google-Smtp-Source: APXvYqzpHt1o82gAEG1vqBRbt5xS631EylDcOrIzEaxnvSBLJP6SleiBfj8eYHEJK02ZvqMYx62dkg== X-Received: by 2002:a65:51cb:: with SMTP id i11mr1544848pgq.390.1559708462458; Tue, 04 Jun 2019 21:21:02 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id e6sm14467070pfi.42.2019.06.04.21.21.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Jun 2019 21:21:02 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Date: Wed, 5 Jun 2019 13:21:39 +0900 Message-Id: <20190605042142.15113-4-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190605042142.15113-1-takahiro.akashi@linaro.org> References: <20190605042142.15113-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 3/6] efi_loader: support convert_pointer at runtime X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" With this patch, ConvertPointer runtime service is enabled. This function will be useful only after SetVirtualAddressMap is called and before it exits according to UEFI specification. Signed-off-by: AKASHI Takahiro --- lib/efi_loader/Kconfig | 8 ++++ lib/efi_loader/efi_runtime.c | 81 ++++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 23 deletions(-) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index bb9c7582b14d..e2ef43157568 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -51,6 +51,14 @@ config EFI_RUNTIME_SET_VIRTUAL_ADDRESS_MAP Enable SetVirtualAddressMap runtime service. This API will be called by OS just before it enters into virtual address mode. +config EFI_RUNTIME_CONVERT_POINTER + bool "runtime service: ConvertPointer" + default n + help + Enable ConvertPointer runtime service. This API will be expected + to be called by UEFI drivers in relocating themselves to virtual + address space. + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index cf202bb9ec07..ff3684a4b692 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -27,7 +27,6 @@ LIST_HEAD(efi_runtime_mmio); static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void); static efi_status_t __efi_runtime EFIAPI efi_device_error(void); -static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void); /* * TODO(sjg@chromium.org): These defines and structures should come from the ELF @@ -108,6 +107,10 @@ efi_status_t efi_init_runtime_supported(void) efi_runtime_services_supported |= EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP; #endif +#ifdef CONFIG_EFI_RUNTIME_CONVERT_POINTER + efi_runtime_services_supported |= + EFI_RT_SUPPORTED_CONVERT_POINTER; +#endif return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported", &efi_global_variable_guid, @@ -392,6 +395,39 @@ efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time) return EFI_UNSUPPORTED; } +#ifdef CONFIG_EFI_RUNTIME_CONVERT_POINTER +static struct efi_mem_desc *efi_virtmap __efi_runtime_data; +static int efi_virtmap_num __efi_runtime_data; + +static efi_status_t __efi_runtime EFIAPI efi_convert_pointer(unsigned long dbg, + void **address) +{ + struct efi_mem_desc *map; + efi_physical_addr_t addr; + int i; + + if (!efi_virtmap) + return EFI_UNSUPPORTED; + + if (!address) + return EFI_INVALID_PARAMETER; + + for (i = 0, map = efi_virtmap; i < efi_virtmap_num; i++, map++) { + addr = (efi_physical_addr_t)*address; + if (addr >= map->physical_start && + (addr < (map->physical_start + + (map->num_pages << EFI_PAGE_SHIFT)))) { + *address = (void *)map->virtual_start; + *address += addr - map->physical_start; + + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} +#endif + struct efi_runtime_detach_list_struct { void *ptr; void *patchto; @@ -599,6 +635,10 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( return EFI_EXIT(EFI_INVALID_PARAMETER); } + efi_virtmap = virtmap; + efi_virtmap_num = n; + +#if 0 /* FIXME: This code is fragile as calloc is used in add_runtime_mmio */ /* Rebind mmio pointers */ for (i = 0; i < n; i++) { struct efi_mem_desc *map = (void*)virtmap + @@ -622,14 +662,14 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( *lmmio->ptr = (void *)new_addr; } } - if ((map_start <= (uintptr_t)systab.tables) && - (map_end >= (uintptr_t)systab.tables)) { - char *ptr = (char *)systab.tables; - - ptr += off; - systab.tables = (struct efi_configuration_table *)ptr; - } } +#endif + + /* FIXME */ + efi_convert_pointer(0, (void **)&systab.tables); + + /* All fixes must be done before this line */ + efi_virtmap = NULL; /* Move the actual runtime code over */ for (i = 0; i < n; i++) { @@ -644,6 +684,11 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( /* Once we're virtual, we can no longer handle complex callbacks */ efi_runtime_detach(new_offset); + + /* + * FIXME: + * We can no longer update RuntimeServicesSupported. + */ return EFI_EXIT(EFI_SUCCESS); } } @@ -733,20 +778,6 @@ static efi_status_t __efi_runtime EFIAPI efi_device_error(void) return EFI_DEVICE_ERROR; } -/** - * efi_invalid_parameter() - replacement function, returns EFI_INVALID_PARAMETER - * - * This function is used after SetVirtualAddressMap() is called as replacement - * for services that are not available anymore due to constraints of the U-Boot - * implementation. - * - * Return: EFI_INVALID_PARAMETER - */ -static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void) -{ - return EFI_INVALID_PARAMETER; -} - /** * efi_update_capsule() - process information from operating system * @@ -833,7 +864,11 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { #else .set_virtual_address_map = (void *)&efi_unimplemented, #endif - .convert_pointer = (void *)&efi_invalid_parameter, +#ifdef CONFIG_EFI_RUNTIME_CONVERT_POINTER + .convert_pointer = &efi_convert_pointer, +#else + .convert_pointer = (void *)&efi_unimplemented, +#endif .get_variable = efi_get_variable, .get_next_variable_name = efi_get_next_variable_name, .set_variable = efi_set_variable, From patchwork Wed Jun 5 04:21:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1110292 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=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="PvmTcM3j"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 45JbFy0KX4z9s3Z for ; Wed, 5 Jun 2019 14:21:25 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id BBF05C21D83; Wed, 5 Jun 2019 04:21:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id A7CCEC21E1B; Wed, 5 Jun 2019 04:21:11 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 62C7EC21C93; Wed, 5 Jun 2019 04:21:07 +0000 (UTC) Received: from mail-pf1-f195.google.com (mail-pf1-f195.google.com [209.85.210.195]) by lists.denx.de (Postfix) with ESMTPS id CEEE9C21DF8 for ; Wed, 5 Jun 2019 04:21:06 +0000 (UTC) Received: by mail-pf1-f195.google.com with SMTP id a186so13354936pfa.5 for ; Tue, 04 Jun 2019 21:21:06 -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=Q+5LeE70S5llGOY0VPQG0lDxbKkUISoa/3LBBlso7Wg=; b=PvmTcM3jzSG9WDfRUNgy+N/gVY4a35W4uVFOTg0Rzd64kiRVvn1rv3cX8lgJqMXgsG Lzzafz8AhJWBFrq9m8U2twz5A9H1pr90+ZuNbfrWSDfu7ivmk5aT5RtqA53q2h1fI6XA 0eG3YUdHrxDlIKmchQe0GTgsUxuIROOUWux7HfXaIXivqeluYdYyGW94eBnjRvOt2YdS vQVwFPCB8fQo877ZKkX5vmj6rT0EBxkgp00Hl8BsehL8w8CJE+yTy4qqkadQv/mtpa9W I+faRG8gAzGG1nVJxBCTIIkYWILlDn0krQ5yVoJ+QeOOsqlr6PjBATkhlvm/+Yrs7ywt H89Q== 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=Q+5LeE70S5llGOY0VPQG0lDxbKkUISoa/3LBBlso7Wg=; b=C9IdqBsWcHJZcwjJHX8Eq0eJdJ+N/V8t71/284gTAMNdNtiN9csmWVL8kXmhd7RATJ UXD8EJh3RSk5oBTDNERA7TDt9W/HHAJspGg75CeT7FE9hg+8YkzuRy/FaQ61t6Zodw7O G6enZ+ebiO2eIyJhwd48Xf4iu3uIj9O+8OqULZdw8qDJyxOYhFiAJjO51YBgk5fGUqxN 0aJWJsbII1a4C3L7fa8WrRIyc5w/fGr6zCyTHgcRjPX4eK2ByFw15fzdXWyZfwEegaH/ opCa0viCZ5LajZEEgFKbSHwMhJvUiUZbKsLn5nqHnsvl/OkZtdMqEqTsOzTSk1DI1Al/ 5YLw== X-Gm-Message-State: APjAAAXn5ySPgHroSJYhvXt4tb8fl89djqAkAOo1wMDsmjABcEvW6HKH aIoAakQqNwtc9YAWmjLbl73m3GPOd/w= X-Google-Smtp-Source: APXvYqzcZZEjt4VeO+rSEu7NI+B53AYXLk1g5FFaxpXFH/gXHoVy40yEJCljEWZoBP1Hey/92UXrIA== X-Received: by 2002:a63:5d45:: with SMTP id o5mr1637661pgm.40.1559708465461; Tue, 04 Jun 2019 21:21:05 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id t7sm16067499pjq.20.2019.06.04.21.21.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Jun 2019 21:21:04 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Date: Wed, 5 Jun 2019 13:21:40 +0900 Message-Id: <20190605042142.15113-5-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190605042142.15113-1-takahiro.akashi@linaro.org> References: <20190605042142.15113-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de, Alexander Graf , Ard Biesheuvel Subject: [U-Boot] [RFC 4/6] efi_loader: Patch non-runtime code out at ExitBootServices already X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" From: Alexander Graf While discussing something completely different, Ard pointed out that it might be legal to omit calling SetVirtualAddressMap altogether. There is even a patch on the Linux Kernel Mailing List that implements such behavior by now: https://patchwork.kernel.org/patch/10782393/ While that sounds great, we currently rely on the SetVirtualAddressMap call to remove all references to code that would not work outside of boot services. So let's patch out those bits already on the call to ExitBootServices, so that we can successfully run even when an OS chooses to omit any call to SetVirtualAddressMap. Reported-by: Ard Biesheuvel Signed-off-by: Alexander Graf OpenBSD is not calling SetVirtualAddressMap on ARM 32 bit. Adjust selftest: expect 'U-Boot' instead of 'resetting'. Reviewed-by: Heinrich Schuchardt --- include/efi_loader.h | 2 ++ lib/efi_loader/efi_boottime.c | 1 + lib/efi_loader/efi_runtime.c | 25 ++++++++++++++++++++----- test/py/tests/test_efi_selftest.py | 4 ++-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 7bd8002e303e..93f7ece814a0 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -381,6 +381,8 @@ void efi_save_gd(void); void efi_restore_gd(void); /* Call this to relocate the runtime section to an address space */ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map); +/* Call this when we start to live in a runtime only world */ +void efi_runtime_detach(ulong offset); /* Call this to set the current device name */ void efi_set_bootdev(const char *dev, const char *devnr, const char *path); /* Add a new object to the object list. */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 7d1d6e92138e..e4abaf3601d9 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1932,6 +1932,7 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, bootm_disable_interrupts(); /* Disable boot time services */ + efi_runtime_detach((ulong)gd->relocaddr); systab.con_in_handle = NULL; systab.con_in = NULL; systab.con_out_handle = NULL; diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index ff3684a4b692..fc5bdee80e00 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -433,7 +433,7 @@ struct efi_runtime_detach_list_struct { void *patchto; }; -static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { +static struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { { /* do_reset is gone */ .ptr = &efi_runtime_services.reset_system, @@ -490,7 +490,15 @@ static bool efi_runtime_tobedetached(void *p) return false; } -static void efi_runtime_detach(ulong offset) +/** + * efi_runtime_detach() - Remove any dependency on non-runtime sections + * + * This function patches all remaining code to be self-sufficient inside + * runtime sections. Any calls to non-runtime will be removed after this. + * + * @offset: relocaddr for pre-set_v_a_space, offset to VA after + */ +__efi_runtime void efi_runtime_detach(ulong offset) { int i; ulong patchoff = offset - (ulong)gd->relocaddr; @@ -506,6 +514,8 @@ static void efi_runtime_detach(ulong offset) /* Update CRC32 */ efi_update_table_header_crc32(&efi_runtime_services.hdr); + + invalidate_icache_all(); } /* Relocate EFI runtime to uboot_reloc_base = offset */ @@ -593,19 +603,25 @@ void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) * @virtmap: virtual address mapping information * Return: status code */ -static efi_status_t EFIAPI efi_set_virtual_address_map( +static __efi_runtime efi_status_t EFIAPI efi_set_virtual_address_map( unsigned long memory_map_size, unsigned long descriptor_size, uint32_t descriptor_version, struct efi_mem_desc *virtmap) { + static __efi_runtime_data bool is_patched; int n = memory_map_size / descriptor_size; int i; int rt_code_sections = 0; + if (is_patched) + return EFI_INVALID_PARAMETER; + EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size, descriptor_version, virtmap); + is_patched = true; + /* * TODO: * Further down we are cheating. While really we should implement @@ -681,8 +697,7 @@ static efi_status_t EFIAPI efi_set_virtual_address_map( map->physical_start + gd->relocaddr; efi_runtime_relocate(new_offset, map); - /* Once we're virtual, we can no longer handle - complex callbacks */ + /* We need to repatch callbacks for their new VA */ efi_runtime_detach(new_offset); /* diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py index 07e4db045284..f950911655a3 100644 --- a/test/py/tests/test_efi_selftest.py +++ b/test/py/tests/test_efi_selftest.py @@ -20,7 +20,7 @@ def test_efi_selftest(u_boot_console): if m != 0: raise Exception('Failures occurred during the EFI selftest') u_boot_console.run_command(cmd='', wait_for_echo=False, wait_for_prompt=False); - m = u_boot_console.p.expect(['resetting', 'U-Boot']) + m = u_boot_console.p.expect(['U-Boot']) if m != 0: raise Exception('Reset failed during the EFI selftest') u_boot_console.restart_uboot(); @@ -47,7 +47,7 @@ def test_efi_selftest_watchdog_reboot(u_boot_console): assert '\'watchdog reboot\'' in output u_boot_console.run_command(cmd='setenv efi_selftest watchdog reboot') u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False) - m = u_boot_console.p.expect(['resetting', 'U-Boot']) + m = u_boot_console.p.expect(['U-Boot']) if m != 0: raise Exception('Reset failed in \'watchdog reboot\' test') u_boot_console.restart_uboot(); From patchwork Wed Jun 5 04:21:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1110297 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=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="bhAftski"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 45JbMN05Lxz9s3Z for ; Wed, 5 Jun 2019 14:26:07 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 9C52CC21DE8; Wed, 5 Jun 2019 04:26:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id F38F2C21DD3; Wed, 5 Jun 2019 04:21:37 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id BAD1BC21E1E; Wed, 5 Jun 2019 04:21:11 +0000 (UTC) Received: from mail-pg1-f193.google.com (mail-pg1-f193.google.com [209.85.215.193]) by lists.denx.de (Postfix) with ESMTPS id A94A0C21DE8 for ; Wed, 5 Jun 2019 04:21:10 +0000 (UTC) Received: by mail-pg1-f193.google.com with SMTP id s27so6042074pgl.2 for ; Tue, 04 Jun 2019 21:21:10 -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=342d1/63bMn1rPIXKFzg6BrkrFUFk+3C3hP2eN3VFXs=; b=bhAftski2jDh74l6OR6ucYobWgx+EhO0JL1LhEkiGgWdNHgyt+Rk4OhPWMIeBfsS3e tXK4ORmhtqNvyeb9C7qXodE4jyfnUZKZ4xsQVWlr3Ja1EiPwJg3BAMxpsDxb6LQoYpLJ JK2YtXwHCw48FZjhyAwF7OYV7QmGsAoSprW4DZ1upftBh+X/tLLjlmmoD4xVR9x6ZBnX P6W5DeG9fdPJn/T3ItENypPh6P7Ba8DTc6el70yIJMD3kEoGKPZEoG+vkUIgI775cEq8 0mU7fFjLzmRLxHfCYL3w1BnFdnneEVy3qHNFIv/Zs6WXbneRfbZa1r7b9nBylHd97vOz 6R2g== 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=342d1/63bMn1rPIXKFzg6BrkrFUFk+3C3hP2eN3VFXs=; b=MPM7WH5EbOm5HONF7MDlAikHCB7UK3kpLSe/1B0ArUQ5+6IjTiU+/5bMluFIow9Vwi XOH8g7/ZHNW45i6XGz9YMjpZ74cSPOMueyZTRHrsVOub4N+Vn0smDxPIN4oqwflOA5IY 8SGzZ49vk6RxqLptuepd47rCvfJMiJnIm5UEzaRSZcxnWSB0rt4wbraHIQJerZ84xaBw 9FAFuJ/WShExJjcPFKoJ8q70C+IYzP359f5+WJwMSlBUkaW+CRmDLctVNxQthOjSct6R wsN2Z/RUYXPj1qVTPqlKg7MTZ2/OvkqJdGh00LSMfO4mOkpULBkVmWT5E9Fi1wPcmrj/ f0fw== X-Gm-Message-State: APjAAAUw1XM/05+xaGB3XCea93IPQjANcqfJzz9E3OfQDumuRFRR+F8Y 1DN85SD5ebqnZzqyM5D/QVq+fw== X-Google-Smtp-Source: APXvYqwyvX0ErfcP45XK6i7aFohwtHoPRua9eas6vzH/gzu9UoP+uqcpwUIQ+Gga63qphHgk84y3jw== X-Received: by 2002:a65:51c7:: with SMTP id i7mr1575579pgq.211.1559708469370; Tue, 04 Jun 2019 21:21:09 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id e5sm5254924pjj.2.2019.06.04.21.21.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Jun 2019 21:21:08 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Date: Wed, 5 Jun 2019 13:21:41 +0900 Message-Id: <20190605042142.15113-6-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190605042142.15113-1-takahiro.akashi@linaro.org> References: <20190605042142.15113-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 5/6] cmd: efidebug: add "boot exit" sub-command X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" With "boot exit" sub-command, we will let the system to exit UEFI Boottime Services. This is mainly for testing. Signed-off-by: AKASHI Takahiro --- cmd/efidebug.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/cmd/efidebug.c b/cmd/efidebug.c index e65722625455..d6abf08c93cc 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -977,6 +977,66 @@ out: return ret; } +/** + * do_efi_boot_exit() - exit boottime services + * + * @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 "boot exit" sub-command. + * - boot exit + */ +static int do_efi_boot_exit(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct efi_mem_desc *memmap; + efi_uintn_t map_size, map_key, desc_size; + u32 desc_version; + efi_status_t ret; + + if (argc != 1) + return CMD_RET_USAGE; + + memmap = NULL; + map_size = 0; + ret = EFI_CALL(BS->get_memory_map(&map_size, memmap, &map_key, + &desc_size, &desc_version)); + if (ret == EFI_BUFFER_TOO_SMALL) { + map_size += sizeof(struct efi_mem_desc); /* for my own */ + ret = EFI_CALL(BS->allocate_pool(EFI_LOADER_DATA, + map_size, (void *)&memmap)); + if (ret != EFI_SUCCESS) { + printf("Out of memory\n"); + return CMD_RET_FAILURE; + } + ret = EFI_CALL(BS->get_memory_map(&map_size, memmap, + &map_key, + &desc_size, &desc_version)); + } + if (ret != EFI_SUCCESS) { + printf("Getting UEFI memory map failed (%zu)\n", + ret & ~EFI_ERROR_MASK); + goto err; + } + + ret = EFI_CALL(BS->exit_boot_services(efi_root, map_key)); + if (ret == EFI_SUCCESS) + return CMD_RET_SUCCESS; + + printf("exiting Boottime Services failed (%zu)\n", + ret & ~EFI_ERROR_MASK); + +err: + if (memmap) + EFI_CALL(BS->free_pool(memmap)); + + return CMD_RET_FAILURE; +} + static cmd_tbl_t cmd_efidebug_boot_sub[] = { U_BOOT_CMD_MKENT(add, CONFIG_SYS_MAXARGS, 1, do_efi_boot_add, "", ""), U_BOOT_CMD_MKENT(rm, CONFIG_SYS_MAXARGS, 1, do_efi_boot_rm, "", ""), @@ -984,6 +1044,7 @@ static cmd_tbl_t cmd_efidebug_boot_sub[] = { U_BOOT_CMD_MKENT(next, CONFIG_SYS_MAXARGS, 1, do_efi_boot_next, "", ""), U_BOOT_CMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_efi_boot_order, "", ""), + U_BOOT_CMD_MKENT(exit, CONFIG_SYS_MAXARGS, 1, do_efi_boot_exit, "", ""), }; /** @@ -1087,6 +1148,8 @@ static char efidebug_help_text[] = " - set UEFI BootNext variable\n" "efidebug boot order [ [ [ [...]]]]\n" " - set/show UEFI boot order\n" + "efidebug boot exit\n" + " - exit UEFI Boottime Services\n" "\n" "efidebug devices\n" " - show uefi devices\n" From patchwork Wed Jun 5 04:21:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1110296 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=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="aW5wQIrH"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 45JbJV4h7Jz9sCJ for ; Wed, 5 Jun 2019 14:23:38 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 483C3C21E0D; Wed, 5 Jun 2019 04:22:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 36ECEC21C50; Wed, 5 Jun 2019 04:21:29 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id A0796C21D72; Wed, 5 Jun 2019 04:21:18 +0000 (UTC) Received: from mail-pf1-f195.google.com (mail-pf1-f195.google.com [209.85.210.195]) by lists.denx.de (Postfix) with ESMTPS id D83ADC21DD3 for ; Wed, 5 Jun 2019 04:21:13 +0000 (UTC) Received: by mail-pf1-f195.google.com with SMTP id s11so14044456pfm.12 for ; Tue, 04 Jun 2019 21:21:13 -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=Yttj8bWRNSg74MxE+OZOAtE+i6RxpLfgG2ArGtZKXhk=; b=aW5wQIrHGCSnTmzfCRqXlkEMaDg9xJhV+91AI3W/DNFvVVkqyNmn4EU00EhisTffbk WTqFM+TmzAQJ+cL/ANjjUN8jNUxDO6pfmeh4kQGN2zGtomBt/Wxp19wZ0Au9ZavhrDXJ 4jb2Z+LRR3AwobM73a1cBexilLIYtQzjF+hneMhadMRGcy6RMDryecQWODKLAr+5fTGU ZeANczo/cvGp49hFWdZRAeyMWWFA/yW0nsAwJXmFAygKuNpTLGOBy4Nl9ehPAdJQGT8y yi8LmgBvRyTwK3ampTgEq9FrvD44gXiydCoTyQAf2WGG7vbk3xZBxODOpUY8L7szQt2K iYDg== 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=Yttj8bWRNSg74MxE+OZOAtE+i6RxpLfgG2ArGtZKXhk=; b=kqDS9UoVYSoH+h9Vh7IfipxwrRn2Mbe4FsncOKk/hZhkXCCkixkKh/aLOxvqZvRfiv 4Nit7iGR81iXGXC769sFPR2St9t2aPAwwqkobjDuXPbzY2LpBGLaDXR3NZEddM3O9hRM 7a7KxEHKmewku3jijox7gcwME/7q0Nxk0Xsy4n4P5hWL2cZiVOcJSqvFkFFNoKk6h8CB QaAvbagYAp4gFIb8qYx4KGDa2ZkuikCVm3T664uskeFb9xGPvuylkxx17O00BGImqpef +mxVZmohTRND1JT0iPGvCMiDeDBPQCHUUy9entC7atJ0aGpuio+Z98+T0Q5voeKj/m37 v8Qw== X-Gm-Message-State: APjAAAU+XK+P8VzRMR6s0i3dtNo58i1C0vVJE/8/PqK67WFSVNHciZh7 iLsESTC7doOzhCfHJG9VvXTQc96k1Cs= X-Google-Smtp-Source: APXvYqwycO5KwtORvyfMetK5y63V8V0kzFR5mchAfsmKzUiLKWWNLjKCr50aWj/jcUnIvAM6HkJQKA== X-Received: by 2002:a17:90a:8c82:: with SMTP id b2mr40475695pjo.97.1559708472340; Tue, 04 Jun 2019 21:21:12 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id l23sm22700983pgh.68.2019.06.04.21.21.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Jun 2019 21:21:11 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Date: Wed, 5 Jun 2019 13:21:42 +0900 Message-Id: <20190605042142.15113-7-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190605042142.15113-1-takahiro.akashi@linaro.org> References: <20190605042142.15113-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 6/6] efi_loader: variable: support runtime variable access via cache X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 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" With this patch, cache buffer for UEFI variables will be created so that we will still be able to access, at least retrieve, UEFI variables when we exit from boottime services, This feature is a "should" behavior described in EBBR v1.0 section 2.5.3. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 17 ++ lib/efi_loader/Kconfig | 9 + lib/efi_loader/efi_boottime.c | 10 +- lib/efi_loader/efi_runtime.c | 13 + lib/efi_loader/efi_variable.c | 467 ++++++++++++++++++++++++++++++++++ 5 files changed, 515 insertions(+), 1 deletion(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 93f7ece814a0..acab657b9d70 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -620,6 +620,23 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, const efi_guid_t *vendor, u32 attributes, efi_uintn_t data_size, const void *data); +#ifdef CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING +efi_status_t efi_freeze_variable_table(void); + +/* runtime version of APIs */ +efi_status_t +__efi_runtime EFIAPI efi_get_variable_runtime(u16 *variable_name, + const efi_guid_t *vendor, + u32 *attributes, + efi_uintn_t *data_size, + void *data); +efi_status_t +__efi_runtime EFIAPI efi_get_next_variable_name_runtime( + efi_uintn_t *variable_name_size, + u16 *variable_name, + const efi_guid_t *vendor); +#endif /* CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING */ + /* * 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: diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index e2ef43157568..3f284795648f 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -59,6 +59,15 @@ config EFI_RUNTIME_CONVERT_POINTER to be called by UEFI drivers in relocating themselves to virtual address space. +config EFI_RUNTIME_GET_VARIABLE_CACHING + bool "runtime_service: GetVariable: Enable runtime access via cache (read-only)" + default y + help + Select this option if you want to access UEFI variables at + runtime even though you cannot update values on the fly. + With or without this option, you can access UEFI variables + at boottime. + 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 e4abaf3601d9..14e343abbd43 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1892,6 +1892,9 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, efi_uintn_t map_key) { struct efi_event *evt; +#ifdef CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING + efi_status_t ret; +#endif EFI_ENTRY("%p, %zx", image_handle, map_key); @@ -1921,7 +1924,12 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, } } - /* TODO: Should persist EFI variables here */ +#ifdef CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING + /* No more variable update */ + ret = efi_freeze_variable_table(); + if (ret != EFI_SUCCESS) + return EFI_EXIT(ret); +#endif board_quiesce_devices(); diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index fc5bdee80e00..b60f70f04613 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -111,6 +111,11 @@ efi_status_t efi_init_runtime_supported(void) efi_runtime_services_supported |= EFI_RT_SUPPORTED_CONVERT_POINTER; #endif +#ifdef CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING + efi_runtime_services_supported |= + (EFI_RT_SUPPORTED_GET_VARIABLE | + EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME); +#endif return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported", &efi_global_variable_guid, @@ -469,10 +474,18 @@ static struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { .patchto = NULL, }, { .ptr = &efi_runtime_services.get_variable, +#ifdef CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING + .patchto = &efi_get_variable_runtime, +#else .patchto = &efi_device_error, +#endif }, { .ptr = &efi_runtime_services.get_next_variable_name, +#ifdef CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING + .patchto = &efi_get_next_variable_name, +#else .patchto = &efi_device_error, +#endif }, { .ptr = &efi_runtime_services.set_variable, .patchto = &efi_device_error, diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index d9887be938c2..ee21892dd291 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -706,3 +706,470 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, return EFI_EXIT(ret); } + +#ifdef CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING +/* + * runtime version of APIs + * We only support read-only variable access. + * The table is in U-Boot's hash table format, but has its own + * _ENTRY structure for specific use. + * + * Except for efi_freeze_variable_table(), which is to be called in + * exit_boot_services(), all the functions and data below must be + * placed in either RUNTIME_SERVICES_CODE or RUNTIME_SERVICES_DATA. + */ +typedef struct _ENTRY { + unsigned int used; /* hash value; 0 for not used */ + size_t name; /* name offset from itself */ + efi_guid_t vendor; + u32 attributes; + size_t data; /* data offset from itself */ + size_t data_size; +} _ENTRY; + +static inline u16 *entry_name(_ENTRY *e) { return (void *)e + e->name; } +static inline u16 *entry_data(_ENTRY *e) { return (void *)e + e->data; } + +static struct hsearch_data *efi_variable_table __efi_runtime_data; + +static size_t __efi_runtime u16_strlen_runtime(const u16 *s1) +{ + size_t n = 0; + + while (*s1) { + n++; + s1++; + } + + return n; +} + +static int __efi_runtime memcmp_runtime(const void *m1, const void *m2, + size_t n) +{ + while (n && *(u8 *)m1 == *(u8 *)m2) { + n--; + m1++; + m2++; + } + + if (n) + return *(u8 *)m1 - *(u8 *)m2; + + return 0; +} + +static void __efi_runtime memcpy_runtime(void *m1, const void *m2, size_t n) +{ + for (; n; n--, m1++, m2++) + *(u8 *)m1 = *(u8 *)m2; +} + +static int __efi_runtime efi_cmpkey(_ENTRY *e, const u16 *name, + const efi_guid_t *vendor) +{ + size_t name_len; + + name_len = u16_strlen_runtime(entry_name(e)); + + /* return zero if matched */ + return name_len != u16_strlen_runtime(name) || + memcmp_runtime(entry_name(e), name, name_len * 2) || + memcmp_runtime(e->vendor.b, vendor->b, sizeof(vendor)); +} + +/* simplified and slightly different version of hsearch_r() */ +static int __efi_runtime hsearch_runtime(const u16 *name, + const efi_guid_t *vendor, + ACTION action, + _ENTRY **retval, + struct hsearch_data *htab) +{ + unsigned int hval; + unsigned int count; + unsigned int len; + unsigned int idx, new; + + /* Compute an value for the given string. */ + len = u16_strlen_runtime(name); + hval = len; + count = len; + while (count-- > 0) { + hval <<= 4; + hval += name[count]; + } + + /* + * First hash function: + * simply take the modulo but prevent zero. + */ + hval %= htab->size; + if (hval == 0) + ++hval; + + /* The first index tried. */ + new = -1; /* not found */ + idx = hval; + + if (htab->table[idx].used) { + /* + * Further action might be required according to the + * action value. + */ + unsigned int hval2; + + if (htab->table[idx].used == hval && + !efi_cmpkey(&htab->table[idx], name, vendor)) { + if (action == FIND) { + *retval = &htab->table[idx]; + return idx; + } + /* we don't need to support overwrite */ + return -1; + } + + /* + * Second hash function: + * as suggested in [Knuth] + */ + hval2 = 1 + hval % (htab->size - 2); + + do { + /* + * Because SIZE is prime this guarantees to + * step through all available indices. + */ + if (idx <= hval2) + idx = htab->size + idx - hval2; + else + idx -= hval2; + + /* + * If we visited all entries leave the loop + * unsuccessfully. + */ + if (idx == hval) + break; + + /* If entry is found use it. */ + if (htab->table[idx].used == hval && + !efi_cmpkey(&htab->table[idx], name, vendor)) { + if (action == FIND) { + *retval = &htab->table[idx]; + return idx; + } + /* we don't need to support overwrite */ + return -1; + } + } while (htab->table[idx].used); + + if (!htab->table[idx].used) + new = idx; + } else { + new = idx; + } + + /* + * An empty bucket has been found. + * The following code should never be executed after + * exit_boot_services() + */ + if (action == ENTER) { + /* + * If table is full and another entry should be + * entered return with error. + */ + if (htab->filled == htab->size) { + *retval = NULL; + return 0; + } + + /* Create new entry */ + htab->table[new].used = hval; + ++htab->filled; + + /* return new entry */ + *retval = &htab->table[new]; + return 1; + } + + *retval = NULL; + return 0; +} + +/* from lib/hashtable.c */ +static inline int isprime(unsigned int number) +{ + /* no even number will be passed */ + unsigned int div = 3; + + while (div * div < number && number % div != 0) + div += 2; + + return number % div != 0; +} + +efi_status_t efi_freeze_variable_table(void) +{ + int var_num = 0; + size_t var_data_size = 0; + u16 *name; + efi_uintn_t name_buf_len, name_len; + efi_guid_t vendor; + u32 attributes; + u8 *mem_pool, *var_buf = NULL; + size_t table_size, var_size, var_buf_size; + _ENTRY *new = NULL; + efi_status_t ret; + + /* phase-1 loop */ + name_buf_len = 128; + name = malloc(name_buf_len); + if (!name) + return EFI_OUT_OF_RESOURCES; + name[0] = 0; + for (;;) { + name_len = name_buf_len; + ret = EFI_CALL(efi_get_next_variable_name(&name_len, name, + &vendor)); + if (ret == EFI_NOT_FOUND) { + break; + } else if (ret == EFI_BUFFER_TOO_SMALL) { + u16 *buf; + + name_buf_len = name_len; + buf = realloc(name, name_buf_len); + if (!buf) { + free(name); + return EFI_OUT_OF_RESOURCES; + } + name = buf; + name_len = name_buf_len; + ret = EFI_CALL(efi_get_next_variable_name(&name_len, + name, + &vendor)); + } + + if (ret != EFI_SUCCESS) + return ret; + + var_size = 0; + ret = EFI_CALL(efi_get_variable(name, &vendor, &attributes, + &var_size, NULL)); + if (ret != EFI_BUFFER_TOO_SMALL) + return ret; + + if (!(attributes & EFI_VARIABLE_RUNTIME_ACCESS)) + continue; + + var_num++; + var_data_size += (u16_strlen_runtime(name) + 1) * sizeof(u16); + var_data_size += var_size; + /* mem_pool must 2-byte aligned for u16 variable name */ + if (var_data_size & 0x1) + var_data_size++; + } + + /* + * total of entries in hash table must be a prime number. + * The logic below comes from lib/hashtable.c + */ + var_num |= 1; /* make odd */ + while (!isprime(var_num)) + var_num += 2; + + /* We need table[var_num] for hsearch_runtime algo */ + table_size = sizeof(*efi_variable_table) + + sizeof(_ENTRY) * (var_num + 1) + var_data_size; + ret = efi_allocate_pool(EFI_RUNTIME_SERVICES_DATA, + table_size, (void **)&efi_variable_table); + if (ret != EFI_SUCCESS) + return ret; + + efi_variable_table->size = var_num; + efi_variable_table->table = (void *)efi_variable_table + + sizeof(*efi_variable_table); + mem_pool = (u8 *)efi_variable_table->table + + sizeof(_ENTRY) * (var_num + 1); + + var_buf_size = 128; + var_buf = malloc(var_buf_size); + if (!var_buf) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + + /* phase-2 loop */ + name[0] = 0; + name_len = name_buf_len; + for (;;) { + name_len = name_buf_len; + ret = EFI_CALL(efi_get_next_variable_name(&name_len, name, + &vendor)); + if (ret == EFI_NOT_FOUND) + break; + else if (ret != EFI_SUCCESS) + goto err; + + var_size = var_buf_size; + ret = EFI_CALL(efi_get_variable(name, &vendor, &attributes, + &var_size, var_buf)); + if (ret == EFI_BUFFER_TOO_SMALL) { + free(var_buf); + var_buf_size = var_size; + var_buf = malloc(var_buf_size); + if (!var_buf) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + ret = EFI_CALL(efi_get_variable(name, &vendor, + &attributes, + &var_size, var_buf)); + } + if (ret != EFI_SUCCESS) + goto err; + + if (!(attributes & EFI_VARIABLE_RUNTIME_ACCESS)) + continue; + + if (hsearch_runtime(name, &vendor, ENTER, &new, + efi_variable_table) <= 0) { + /* This should not happen */ + ret = EFI_INVALID_PARAMETER; + goto err; + } + + /* allocate space from RUNTIME DATA */ + name_len = (u16_strlen_runtime(name) + 1) * sizeof(u16); + memcpy_runtime(mem_pool, name, name_len); + new->name = mem_pool - (u8 *)new; /* offset */ + mem_pool += name_len; + + memcpy_runtime(&new->vendor.b, &vendor.b, sizeof(vendor)); + + new->attributes = attributes; + + memcpy_runtime(mem_pool, var_buf, var_size); + new->data = mem_pool - (u8 *)new; /* offset */ + new->data_size = var_size; + mem_pool += var_size; + + /* mem_pool must 2-byte aligned for u16 variable name */ + if ((uintptr_t)mem_pool & 0x1) + mem_pool++; + } +#ifdef DEBUG + name[0] = 0; + name_len = name_buf_len; + for (;;) { + name_len = name_buf_len; + ret = efi_get_next_variable_name_runtime(&name_len, name, + &vendor); + if (ret == EFI_NOT_FOUND) + break; + else if (ret != EFI_SUCCESS) + goto err; + + var_size = var_buf_size; + ret = efi_get_variable_runtime(name, &vendor, &attributes, + &var_size, var_buf); + if (ret != EFI_SUCCESS) + goto err; + + printf("%ls_%pUl:\n", name, &vendor); + printf(" attributes: 0x%x\n", attributes); + printf(" value (size: 0x%lx)\n", var_size); + } +#endif + ret = EFI_SUCCESS; + +err: + free(name); + free(var_buf); + if (ret != EFI_SUCCESS && efi_variable_table) { + efi_free_pool(efi_variable_table); + efi_variable_table = NULL; + } + + return ret; +} + +efi_status_t +__efi_runtime EFIAPI efi_get_variable_runtime(u16 *variable_name, + const efi_guid_t *vendor, + u32 *attributes, + efi_uintn_t *data_size, + void *data) +{ + _ENTRY *new; + + if (!variable_name || !vendor || !data_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (hsearch_runtime(variable_name, vendor, FIND, &new, + efi_variable_table) <= 0) + return EFI_NOT_FOUND; + + if (attributes) + *attributes = new->attributes; + if (*data_size < new->data_size) { + *data_size = new->data_size; + return EFI_BUFFER_TOO_SMALL; + } + + *data_size = new->data_size; + memcpy_runtime(data, entry_data(new), new->data_size); + + return EFI_SUCCESS; +} + +static int prev_idx __efi_runtime_data; + +efi_status_t +__efi_runtime EFIAPI efi_get_next_variable_name_runtime( + efi_uintn_t *variable_name_size, + u16 *variable_name, + const efi_guid_t *vendor) +{ + _ENTRY *e; + u16 *name; + efi_uintn_t name_size; + + if (!variable_name_size || !variable_name || !vendor) + return EFI_INVALID_PARAMETER; + + if (variable_name[0]) { + /* sanity check for previous variable */ + if (prev_idx < 0) + return EFI_INVALID_PARAMETER; + + e = &efi_variable_table->table[prev_idx]; + if (!e->used || efi_cmpkey(e, variable_name, vendor)) + return EFI_INVALID_PARAMETER; + } else { + prev_idx = -1; + } + + /* next variable */ + while (++prev_idx <= efi_variable_table->size) { + e = &efi_variable_table->table[prev_idx]; + if (e->used) + break; + } + if (prev_idx > efi_variable_table->size) + return EFI_NOT_FOUND; + + name = entry_name(e); + name_size = (u16_strlen_runtime(name) + 1) + * sizeof(u16); + if (*variable_name_size < name_size) { + *variable_name_size = name_size; + return EFI_BUFFER_TOO_SMALL; + } + + memcpy_runtime(variable_name, name, name_size); + memcpy_runtime((void *)&vendor->b, &e->vendor.b, sizeof(vendor)); + + return EFI_SUCCESS; +} +#endif /* CONFIG_EFI_RUNTIME_GET_VARIABLE_CACHING */