From: Matthew Garrett <mjg59@srcf.ucam.org>
To: u-boot@lists.denx.de
Cc: "Matthew Garrett" <mgarrett@aurora.tech>,
"Bin Meng" <bmeng.cn@gmail.com>,
"Caleb Connolly" <caleb.connolly@linaro.org>,
"Heinrich Schuchardt" <xypron.glpk@gmx.de>,
"Ilias Apalodimas" <ilias.apalodimas@linaro.org>,
"Mattijs Korpershoek" <mkorpershoek@baylibre.com>,
"Simon Glass" <sjg@chromium.org>,
"Sughosh Ganu" <sughosh.ganu@linaro.org>,
"Tom Rini" <trini@konsulko.com>,
"Vincent Stehlé" <vincent.stehle@arm.com>
Subject: [PATCH 01/10] Add EFI handover support to bootm
Date: Sat, 23 Nov 2024 11:55:00 -0800 [thread overview]
Message-ID: <20241123195616.305687-2-mjg59@srcf.ucam.org> (raw)
In-Reply-To: <20241123195616.305687-1-mjg59@srcf.ucam.org>
From: Matthew Garrett <mgarrett@aurora.tech>
We want to jump into the EFI stub in the kernel so it can perform
appropriate init and call ExitBootServices. Add support for doing that,
including ensuring that we copy the kernel to somewhere that's not
currently being used by the firmware.
Signed-off-by: Matthew Garrett <mgarrett@aurora.tech>
---
arch/x86/lib/bootm.c | 49 ++++++++++++++++++++++++++++++--------------
boot/bootm.c | 5 +++++
include/bootm.h | 6 ++++++
include/efi.h | 1 +
lib/efi/efi.c | 1 +
lib/efi/efi_app.c | 36 ++++++++++++++++++++++++++++++++
6 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index 55f581836df..c4446b1f9c6 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -150,6 +150,38 @@ error:
return 1;
}
+typedef void(*handover_func)(void *, struct efi_system_table *sys_table, struct
+boot_params *params);
+
+int efi_boot(ulong setup_base, ulong entry, bool image_64bit)
+{
+ struct boot_params *params = (struct boot_params *)setup_base;
+ struct setup_header *hdr = ¶ms->hdr;
+ struct efi_priv *priv = efi_get_priv();
+ handover_func hf;
+ int offset = 0;
+
+ if (IS_ENABLED(CONFIG_EFI_APP_64BIT)) {
+ if (!image_64bit) {
+ printf("## Can only boot 64-bit kernels\n");
+ return 1;
+ }
+ offset = 512;
+ } else if (image_64bit) {
+ printf("# Can only boot 32-bit kernels\n");
+ return 1;
+ }
+
+ hdr->code32_start = (int)entry;
+ hdr->type_of_loader = 0x80; /* U-Boot, from Linux Documentation/x86/boot.rst */
+
+ hf = (handover_func)(entry + hdr->handover_offset + offset);
+ asm volatile ("cli");
+ priv->loaded_image->image_base = (char *)entry;
+ hf(priv->parent_image, priv->sys_table, params);
+ return -EFAULT;
+}
+
int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit)
{
bootm_announce_and_cleanup();
@@ -158,21 +190,8 @@ int boot_linux_kernel(ulong setup_base, ulong entry, bool image_64bit)
timestamp_add_now(TS_U_BOOT_START_KERNEL);
#endif
- /*
- * Exit EFI boot services just before jumping, after all console
- * output, since the console won't be available afterwards.
- */
- if (IS_ENABLED(CONFIG_EFI_APP)) {
- int ret;
-
- ret = efi_store_memory_map(efi_get_priv());
- if (ret)
- return ret;
- printf("Exiting EFI boot services\n");
- ret = efi_call_exit_boot_services();
- if (ret)
- return ret;
- }
+ if (IS_ENABLED(CONFIG_EFI_APP))
+ return efi_boot(setup_base, entry, image_64bit)
if (image_64bit) {
if (!cpu_has_64bit()) {
diff --git a/boot/bootm.c b/boot/bootm.c
index 16a43d519a8..d5caa4cdb31 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -49,6 +49,10 @@ __weak void board_quiesce_devices(void)
{
}
+__weak void board_fixup_os(image_info_t *os)
+{
+}
+
#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
/**
* image_get_kernel - verify legacy format kernel image
@@ -999,6 +1003,7 @@ int bootm_run_states(struct bootm_info *bmi, int states)
/* Load the OS */
if (!ret && (states & BOOTM_STATE_LOADOS)) {
iflag = bootm_disable_interrupts();
+ board_fixup_os(&images->os);
ret = bootm_load_os(images, 0);
if (ret && ret != BOOTM_ERR_OVERLAP)
goto err;
diff --git a/include/bootm.h b/include/bootm.h
index 61160705215..b0d10123b53 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -217,6 +217,12 @@ void arch_preboot_os(void);
*/
void board_quiesce_devices(void);
+/*
+ * boards should define this if they need to fix up the kernel before boot
+ * (eg, by modifying the desired load address).
+ */
+void board_fixup_os(image_info_t *os);
+
/**
* switch_to_non_secure_mode() - switch to non-secure mode
*/
diff --git a/include/efi.h b/include/efi.h
index c559fda3004..1d06230439f 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -459,6 +459,7 @@ static inline struct efi_mem_desc *efi_get_next_mem_desc(
*/
struct efi_priv {
efi_handle_t parent_image;
+ struct efi_loaded_image *loaded_image;
struct efi_system_table *sys_table;
struct efi_boot_services *boot;
struct efi_runtime_services *run;
diff --git a/lib/efi/efi.c b/lib/efi/efi.c
index bcb34d67465..bb1d9e24f84 100644
--- a/lib/efi/efi.c
+++ b/lib/efi/efi.c
@@ -113,6 +113,7 @@ int efi_init(struct efi_priv *priv, const char *banner, efi_handle_t image,
efi_puts(priv, "Failed to get loaded image protocol\n");
return ret;
}
+ priv->loaded_image = loaded_image;
priv->image_data_type = loaded_image->image_data_type;
return 0;
diff --git a/lib/efi/efi_app.c b/lib/efi/efi_app.c
index 9b94a93ee4f..7c3ef9a7926 100644
--- a/lib/efi/efi_app.c
+++ b/lib/efi/efi_app.c
@@ -14,6 +14,7 @@
#include <efi.h>
#include <efi_api.h>
#include <errno.h>
+#include <image.h>
#include <init.h>
#include <malloc.h>
#include <sysreset.h>
@@ -218,6 +219,41 @@ static int efi_sysreset_request(struct udevice *dev, enum sysreset_t type)
return -EINPROGRESS;
}
+/*
+ * Attempt to relocate the kernel to somewhere the firmware isn't using
+ */
+#define PAGE_SIZE_BITS 12
+void board_fixup_os(image_info_t *os)
+{
+ int pages;
+ ulong load_addr;
+ u64 addr;
+ efi_status_t status;
+ struct efi_priv *priv = efi_get_priv();
+ struct efi_boot_services *boot = priv->boot;
+
+ pages = (os->image_len + ((1 << PAGE_SIZE_BITS) - 1)) >> PAGE_SIZE_BITS;
+
+ addr = os->load;
+
+ /* Try to allocate at the preferred address */
+ status = boot->allocate_pages(EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+ pages, &addr);
+ if (status == EFI_SUCCESS)
+ return;
+
+ /* That failed, so try allocating anywhere there's enough room */
+ status = boot->allocate_pages(EFI_ALLOCATE_ANY_PAGES, EFI_LOADER_DATA, pages, &addr);
+ if (status == EFI_SUCCESS) {
+ /* Make sure bootm knows where we loaded the image */
+ os->load = addr;
+ return;
+ }
+
+ printf("Failed to alloc %lx bytes at %lx: %lx\n", os->image_len, load_addr,
+ status);
+}
+
static const struct udevice_id efi_sysreset_ids[] = {
{ .compatible = "efi,reset" },
{ }
--
2.47.0
next prev parent reply other threads:[~2024-11-23 21:49 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-23 19:54 [PATCH 00/10] Improve UEFI app support Matthew Garrett
2024-11-23 19:55 ` Matthew Garrett [this message]
2024-11-24 14:43 ` [PATCH 01/10] Add EFI handover support to bootm Heinrich Schuchardt
2024-11-24 19:29 ` Matthew Garrett
2024-11-24 19:51 ` Heinrich Schuchardt
2024-12-08 23:06 ` Simon Glass
2024-11-25 13:46 ` Ilias Apalodimas
2024-12-01 16:12 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-11-23 19:55 ` [PATCH 02/10] Add part_find command Matthew Garrett
2024-12-01 16:12 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-12-10 8:21 ` Heinrich Schuchardt
2024-12-10 16:16 ` Simon Glass
2024-11-23 19:55 ` [PATCH 03/10] Add a command to find a load address Matthew Garrett
2024-11-24 15:56 ` Tom Rini
2024-12-01 16:12 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-11-23 19:55 ` [PATCH 04/10] Hook up EFI env variable support in the EFI app Matthew Garrett
2024-12-01 16:12 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-11-23 19:55 ` [PATCH 05/10] Add EFI network driver Matthew Garrett
2024-12-01 16:12 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-11-23 19:55 ` [PATCH 06/10] Add UEFI TPM2 driver Matthew Garrett
2024-12-01 16:12 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-11-23 19:55 ` [PATCH 07/10] Support separate DTB files with the UEFI app Matthew Garrett
2024-11-25 13:55 ` Ilias Apalodimas
2024-12-01 16:14 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-11-23 19:55 ` [PATCH 08/10] Use the correct ramdisk address Matthew Garrett
2024-12-01 16:14 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-11-23 19:55 ` [PATCH 09/10] Fix efi_bind_block Matthew Garrett
2024-11-25 13:40 ` Ilias Apalodimas
2024-12-09 2:28 ` Simon Glass
2024-12-01 16:14 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-12-10 8:45 ` Heinrich Schuchardt
2024-12-10 16:17 ` Simon Glass
2024-12-10 17:11 ` Tom Rini
2024-12-11 17:50 ` Janis Danisevskis
2024-12-11 17:59 ` Ilias Apalodimas
2024-12-11 20:23 ` Simon Glass
2024-12-11 22:28 ` Janis Danisevskis
2024-11-23 19:55 ` [PATCH 10/10] Add command to set an environment variable to an EFI variable Matthew Garrett
2024-11-24 14:58 ` Heinrich Schuchardt
2024-12-01 16:14 ` Simon Glass
2024-12-08 15:29 ` Simon Glass
2024-12-09 2:28 ` Simon Glass
2024-11-24 14:40 ` [PATCH 00/10] Improve UEFI app support Heinrich Schuchardt
2024-12-01 16:15 ` Simon Glass
2024-12-08 15:28 ` Simon Glass
2024-12-08 15:51 ` Tom Rini
2024-12-08 18:50 ` Tom Rini
2024-12-08 23:07 ` Simon Glass
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=20241123195616.305687-2-mjg59@srcf.ucam.org \
--to=mjg59@srcf.ucam.org \
--cc=bmeng.cn@gmail.com \
--cc=caleb.connolly@linaro.org \
--cc=ilias.apalodimas@linaro.org \
--cc=mgarrett@aurora.tech \
--cc=mkorpershoek@baylibre.com \
--cc=sjg@chromium.org \
--cc=sughosh.ganu@linaro.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
--cc=vincent.stehle@arm.com \
--cc=xypron.glpk@gmx.de \
/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