diff --git a/include/efi.h b/include/efi.h index d2513d14e8d..f5e8d632d47 100644 --- a/include/efi.h +++ b/include/efi.h @@ -621,6 +621,16 @@ struct efi_priv *efi_get_priv(void); */ void efi_set_priv(struct efi_priv *priv); +/** + * efi_move_priv() - Move EFI-private information to a new location + * + * Copies the existing EFI-private data to a new location and updates the + * global pointer. If there is no existing data, just sets the pointer. + * + * @new_priv: New location for private data + */ +void efi_move_priv(struct efi_priv *new_priv); + /** * efi_get_sys_table() - Get access to the main EFI system table * diff --git a/lib/efi_client/efi.c b/lib/efi_client/efi.c index 083ad1f423c..c4b1a24d6be 100644 --- a/lib/efi_client/efi.c +++ b/lib/efi_client/efi.c @@ -57,6 +57,12 @@ void efi_set_priv(struct efi_priv *priv) global_priv = priv; } +void efi_move_priv(struct efi_priv *new_priv) +{ + *new_priv = *global_priv; + global_priv = new_priv; +} + struct efi_system_table *efi_get_sys_table(void) { return global_priv->sys_table; diff --git a/lib/efi_client/efi_app.c b/lib/efi_client/efi_app.c index 878994a5763..0a817839f26 100644 --- a/lib/efi_client/efi_app.c +++ b/lib/efi_client/efi_app.c @@ -33,6 +33,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -389,6 +390,39 @@ U_BOOT_DRIVER(efi_sysreset) = { .ops = &efi_sysreset_ops, }; +/** + * efi_reserve_priv() - Event handler to reserve memory for struct efi_priv + * + * This handler is called during EVT_RESERVE_BOARD event to reserve memory + * for the efi_priv structure before other reservations. + * + * @ctx: Event context (unused) + * @event: Event information containing reserve_board data + * Return: 0 on success + */ +static int efi_reserve_priv(void *ctx, struct event *event) +{ + struct event_reserve_board *reserve = &event->data.reserve_board; + struct efi_priv *priv; + ulong addr; + + /* Reserve memory for efi_priv using the provided stack pointer */ + addr = ALIGN_DOWN(reserve->start_addr_sp - sizeof(struct efi_priv), 16); + priv = map_sysmem(addr, sizeof(struct efi_priv)); + + /* Update stack pointer for next reservation */ + reserve->start_addr_sp = addr; + + /* Move existing priv data (from stack) to reserved location */ + efi_move_priv(priv); + + log_debug("Reserving %zu bytes for EFI priv at: %08lx\n", + sizeof(struct efi_priv), addr); + + return 0; +} +EVENT_SPY_FULL(EVT_RESERVE_BOARD, efi_reserve_priv); + efi_status_t efi_startup(efi_handle_t image, struct efi_system_table *systab) { struct efi_priv local_priv, *priv = &local_priv;