From: Rob Clark <robdclark@gmail.com>
To: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Rob Clark <robdclark@chromium.org>,
Ard Biesheuvel <ard.biesheuvel@linaro.org>,
Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>,
Ingo Molnar <mingo@kernel.org>, Kairui Song <kasong@redhat.com>,
Hans de Goede <hdegoede@redhat.com>,
Matthew Garrett <matthewgarrett@google.com>,
linux-efi@vger.kernel.org (open list:EXTENSIBLE FIRMWARE
INTERFACE (EFI)), linux-kernel@vger.kernel.org (open list)
Subject: [PATCH] efi/fdt: install new fdt config table
Date: Sat, 30 Nov 2019 11:50:40 -0800 [thread overview]
Message-ID: <20191130195045.2005835-1-robdclark@gmail.com> (raw)
From: Rob Clark <robdclark@chromium.org>
If there is an fdt config table, replace it with the newly allocated one
before calling ExitBootServices().
Signed-off-by: Rob Clark <robdclark@chromium.org>
---
The DtbLoader.efi[1] driver, which Leif created for EBBR boot on the
"windows" aarch64 laptops, tries to detect in an EBS hook, whether the
HLOS is using DT. It does this by realizing that the kernel cmdline is
patched in to the fdt, and comparing the CRC. If the CRC has changed,
that means the HLOS is using DT boot, so it removes the ACPI config
tables, so that the HLOS does not see two conflicting sets of config
tables.
However, I realized this mechanism does not work when directly loading
the linux kernel as an efi executable (ie. without an intermediary like
grub doing it's own DT modifications), because efi/libstub is modifying
a copy of the DT config table.
If we update the config table with the new DT, then it will realize
properly that the HLOS is using DT.
[1] https://git.linaro.org/people/leif.lindholm/edk2.git/log/?h=dtbloader
.../firmware/efi/libstub/efi-stub-helper.c | 32 +++++++++++++++++++
drivers/firmware/efi/libstub/efistub.h | 2 ++
drivers/firmware/efi/libstub/fdt.c | 2 ++
3 files changed, 36 insertions(+)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 35dbc2791c97..210070f3b231 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -953,3 +953,35 @@ void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid)
else
return get_efi_config_table32(sys_table, guid);
}
+
+#define REPLACE_EFI_CONFIG_TABLE(bits) \
+static void *replace_efi_config_table##bits(efi_system_table_t *_sys_table, \
+ efi_guid_t guid, void *table) \
+{ \
+ efi_system_table_##bits##_t *sys_table; \
+ efi_config_table_##bits##_t *tables; \
+ int i; \
+ \
+ sys_table = (typeof(sys_table))_sys_table; \
+ tables = (typeof(tables))(unsigned long)sys_table->tables; \
+ \
+ for (i = 0; i < sys_table->nr_tables; i++) { \
+ if (efi_guidcmp(tables[i].guid, guid) != 0) \
+ continue; \
+ \
+ tables[i].table = (uintptr_t)table; \
+ return; \
+ } \
+}
+REPLACE_EFI_CONFIG_TABLE(32)
+REPLACE_EFI_CONFIG_TABLE(64)
+
+/* replaces an existing config table: */
+void replace_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid,
+ void *table)
+{
+ if (efi_is_64bit())
+ replace_efi_config_table64(sys_table, guid, table);
+ else
+ replace_efi_config_table32(sys_table, guid, table);
+}
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index 7f1556fd867d..66f2927ce26f 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -66,6 +66,8 @@ efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
void *get_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid);
+void replace_efi_config_table(efi_system_table_t *sys_table, efi_guid_t guid,
+ void *table);
/* Helper macros for the usual case of using simple C variables: */
#ifndef fdt_setprop_inplace_var
diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index 0bf0190917e0..15887ec2dc3b 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -313,6 +313,8 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
priv.runtime_entry_count = &runtime_entry_count;
priv.new_fdt_addr = (void *)*new_fdt_addr;
+ replace_efi_config_table(sys_table, DEVICE_TREE_GUID, priv.new_fdt_addr);
+
status = efi_exit_boot_services(sys_table, handle, &map, &priv, exit_boot_func);
if (status == EFI_SUCCESS) {
--
2.23.0
next reply other threads:[~2019-11-30 19:51 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-30 19:50 Rob Clark [this message]
2019-12-02 9:35 ` [PATCH] efi/fdt: install new fdt config table Ard Biesheuvel
2019-12-02 12:29 ` Leif Lindholm
2019-12-02 15:57 ` Rob Clark
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191130195045.2005835-1-robdclark@gmail.com \
--to=robdclark@gmail.com \
--cc=ard.biesheuvel@linaro.org \
--cc=hdegoede@redhat.com \
--cc=jarkko.sakkinen@linux.intel.com \
--cc=kasong@redhat.com \
--cc=leif.lindholm@linaro.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=matthewgarrett@google.com \
--cc=mingo@kernel.org \
--cc=robdclark@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox