Re: [PATCH v4 5/5] efi: Use generic EFI loader for x86_64 and i386

2023-05-23 Thread Ard Biesheuvel
On Tue, 23 May 2023 at 17:32, Ard Biesheuvel  wrote:
>
> Switch the x86 based EFI platform builds to the generic EFI loader,
> which exposes the initrd via the LoadFile2 protocol instead of the
> x86-specific setup header. This will launch the Linux kernel via its EFI
> stub, which performs its own initialization in the EFI boot services
> context before calling ExitBootServices() and performing the bare metal
> Linux boot.
>
> Given that only Linux kernel versions v5.8 and later support this initrd
> loading method, the existing x86 loader is retained as a fallback, which
> will also be used for Linux kernels built without the EFI stub. In this
> case, GRUB calls ExitBootServices() before entering the Linux kernel,
> and all EFI related information is provided to the kernel via struct
> boot_params in the setup header, as before.
>
> Note that this means that booting EFI stub kernels older than v5.8 is
> not supported even when not using an initrd at all. Also, the EFI
> handover protocol, which has no basis in the UEFI specification, is not
> implemented.
>
> Signed-off-by: Ard Biesheuvel 

This patch needs the hunk below, which i failed to git add - apologies

--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -360,7 +360,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
((unused)),
 int argc, char *argv[])
 {
   int __attribute__ ((unused)) initrd_size, initrd_pages;
-  void *initrd_mem = NULL;
+  void *__attribute__ ((unused)) initrd_mem = NULL;
   grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
   grub_efi_status_t status;

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 2/5] efi: Add calling convention annotation to all prototypes

2023-05-23 Thread Ard Biesheuvel
UEFI mandates MS calling convention on x86_64, which was not supported
on GCC when UEFI support was first introduced into GRUB. However, now we
can use the ms_abi function type attribute to annotate functions and
function pointers as adhering to the MS calling convention, and the
compiler will generate the correct instruction sequence for us.

So let's add the appropriate annotation to all the function prototypes.
This will allow us to drop the special call wrappers in a subsequent
patch.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/efiemu/runtime/efiemu.c |  48 +-
 grub-core/kern/arm/efi/init.c |   2 +-
 include/grub/efi/api.h| 569 ++--
 include/grub/efi/tpm.h| 149 +++--
 4 files changed, 397 insertions(+), 371 deletions(-)

diff --git a/grub-core/efiemu/runtime/efiemu.c 
b/grub-core/efiemu/runtime/efiemu.c
index 5db1f347b5db54cc..53b3cce7b0c2ecf8 100644
--- a/grub-core/efiemu/runtime/efiemu.c
+++ b/grub-core/efiemu/runtime/efiemu.c
@@ -32,17 +32,17 @@
 #include 
 #include 
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_time (grub_efi_time_t *time,
 grub_efi_time_capabilities_t *capabilities);
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_time (grub_efi_time_t *time);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_wakeup_time (grub_efi_boolean_t *enabled,
grub_efi_boolean_t *pending,
grub_efi_time_t *time);
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_wakeup_time (grub_efi_boolean_t enabled,
grub_efi_time_t *time);
 
@@ -52,51 +52,51 @@ efiemu_set_wakeup_time (grub_efi_boolean_t enabled,
 #define PHYSICAL_ATTRIBUTE __attribute__ ((section(".text-physical")));
 #endif
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
grub_efi_uintn_t descriptor_size,
grub_efi_uint32_t descriptor_version,
grub_efi_memory_descriptor_t *virtual_map)
   PHYSICAL_ATTRIBUTE;
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_convert_pointer (grub_efi_uintn_t debug_disposition,
void **address)
   PHYSICAL_ATTRIBUTE;
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_variable (grub_efi_char16_t *variable_name,
 const grub_efi_guid_t *vendor_guid,
 grub_efi_uint32_t *attributes,
 grub_efi_uintn_t *data_size,
 void *data);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_next_variable_name (grub_efi_uintn_t *variable_name_size,
   grub_efi_char16_t *variable_name,
   grub_efi_guid_t *vendor_guid);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_variable (grub_efi_char16_t *variable_name,
 const grub_efi_guid_t *vendor_guid,
 grub_efi_uint32_t attributes,
 grub_efi_uintn_t data_size,
 void *data);
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_next_high_monotonic_count (grub_efi_uint32_t *high_count);
-void
+void __grub_efi_api
 efiemu_reset_system (grub_efi_reset_type_t reset_type,
 grub_efi_status_t reset_status,
 grub_efi_uintn_t data_size,
 grub_efi_char16_t *reset_data);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_set_virtual_address_map) (grub_efi_uintn_t,
  grub_efi_uintn_t,
  grub_efi_uint32_t,
  grub_efi_memory_descriptor_t *)
  PHYSICAL_ATTRIBUTE;
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition,
  void **address)
  PHYSICAL_ATTRIBUTE;
@@ -202,7 +202,7 @@ bcd_to_hex (grub_uint8_t in)
   return 10 * ((in & 0xf0) >> 4) + (in & 0x0f);
 }
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time,
   grub_efi_time_capabilities_t *capabilities)
 {
@@ -246,7 +246,7 @@ EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time,
   return GRUB_EFI_SUCCESS;
 }
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_set_time) (grub_efi_time_t *time)
 {
   LOG ('b');
@@ -265,7 +265,7 @@ EFI_FUNC (efiemu_set_time) (grub_efi_time_t *time)
 }
 
 /* Following 2 functions are vendor specific. So announce it as unsupported */
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_get_wakeup_time) (grub_efi_boolean_t *enabled,
  grub_efi_boolean_t *pending,

[PATCH v4 4/5] efi: Remove x86_64 call wrappers

2023-05-23 Thread Ard Biesheuvel
The call wrappers are no longer needed now that GCC can generate
function calls using MS calling convention, so let's get rid of them.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/Makefile.core.def  |   1 -
 grub-core/kern/x86_64/efi/callwrap.S | 129 
 include/grub/efi/api.h   |  73 ---
 3 files changed, 203 deletions(-)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index c69c4a3321d27ecd..1d88c4d1c2555f7f 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -236,7 +236,6 @@ kernel = {
 
   x86_64 = kern/x86_64/dl.c;
   x86_64_xen = kern/x86_64/dl.c;
-  x86_64_efi = kern/x86_64/efi/callwrap.S;
   x86_64_efi = kern/i386/efi/init.c;
   x86_64_efi = bus/pci.c;
 
diff --git a/grub-core/kern/x86_64/efi/callwrap.S 
b/grub-core/kern/x86_64/efi/callwrap.S
deleted file mode 100644
index 1337fd9fc823f8a4..
--- a/grub-core/kern/x86_64/efi/callwrap.S
+++ /dev/null
@@ -1,129 +0,0 @@
-/* callwrap.S - wrapper for x86_64 efi calls */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2006,2007,2009  Free Software Foundation, Inc.
- *
- *  GRUB is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  GRUB is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with GRUB.  If not, see .
- */
-
-#include 
-#include 
-
-/*
- * x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use
- * different call conversion, so we need to do some conversion.
- *
- * gcc:
- *   %rdi,  %rsi,  %rdx,  %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
- *
- * efi:
- *   %rcx,  %rdx,  %r8,  %r9,  32(%rsp), 40(%rsp), 48(%rsp), ...
- *
- */
-
-.file   "callwrap.S"
-.text
-
-FUNCTION(efi_wrap_0)
-   subq $40, %rsp
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_1)
-   subq $40, %rsp
-   mov  %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_2)
-   subq $40, %rsp
-   mov  %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_3)
-   subq $40, %rsp
-   mov  %rcx, %r8
-   mov  %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_4)
-   subq $40, %rsp
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_5)
-   subq $40, %rsp
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_6)
-   subq $56, %rsp
-   mov 56+8(%rsp), %rax
-   mov %rax, 40(%rsp)
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $56, %rsp
-   ret
-
-FUNCTION(efi_wrap_7)
-   subq $88, %rsp
-   mov 88+16(%rsp), %rax
-   mov %rax, 48(%rsp)
-   mov 88+8(%rsp), %rax
-   mov %rax, 40(%rsp)
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $88, %rsp
-   ret
-
-FUNCTION(efi_wrap_10)
-   subq $88, %rsp
-   mov 88+40(%rsp), %rax
-   mov %rax, 72(%rsp)
-   mov 88+32(%rsp), %rax
-   mov %rax, 64(%rsp)
-   mov 88+24(%rsp), %rax
-   mov %rax, 56(%rsp)
-   mov 88+16(%rsp), %rax
-   mov %rax, 48(%rsp)
-   mov 88+8(%rsp), %rax
-   mov %rax, 40(%rsp)
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $88, %rsp
-   ret
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index ebfa6c40fba34eae..fb881ae12d5ae73a 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1824,77 +1824,4 @@ struct initrd_media_device_path {
 } GRUB_PACKED;
 typedef struct initrd_media_device_path initrd_media_device_path_t;
 
-#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
-  || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
-  || defined(__riscv) || defined (__loongarch__)
-
-#define efi_call_0(func)   (func)()
-#define efi_call_1(func, a)(func)(a)
-#define efi_call_2(func, a, b) (func)(a, b)
-#define efi_call_3(func, a, b, c)  (func)(a, b, c)
-#define efi_call_4(func, a, b, c, d)   (func)(a, b, c, d)
-#define efi_call_5(func, a, b, c, d, e)(func)(a, b, c, d, e)
-#define efi_call_6(func, a, b, c, d, e, f) (func)(a, b, c, d, e, f)

[PATCH v4 3/5] efi: Drop all uses of efi_call_XX wrappers

2023-05-23 Thread Ard Biesheuvel
Now that GCC can generate function calls using the correct calling
convention for us, we can stop using the efi_call_XX () wrappers, and
just dereference the function pointers directly.

This avoids the untyped variadic wrapper routines, which means better
type checking for the method calls.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/commands/acpi.c |  8 +--
 grub-core/commands/efi/efitextmode.c  |  8 ++-
 grub-core/commands/efi/lsefi.c|  5 +-
 grub-core/commands/efi/tpm.c  | 21 
 grub-core/disk/efi/efidisk.c  |  7 +--
 grub-core/kern/arm/efi/init.c | 10 ++--
 grub-core/kern/efi/efi.c  | 56 ++--
 grub-core/kern/efi/init.c | 15 +++---
 grub-core/kern/efi/mm.c   | 17 +++---
 grub-core/kern/i386/efi/tsc.c |  2 +-
 grub-core/kern/ia64/efi/init.c| 14 ++---
 grub-core/kern/loongarch64/efi/init.c | 10 ++--
 grub-core/lib/efi/datetime.c  |  9 ++--
 grub-core/lib/efi/halt.c  |  4 +-
 grub-core/lib/efi/relocator.c |  6 +--
 grub-core/loader/efi/appleloader.c|  8 +--
 grub-core/loader/efi/chainloader.c| 20 +++
 grub-core/mmap/efi/mmap.c | 16 +++---
 grub-core/net/drivers/efi/efinet.c| 26 -
 grub-core/term/efi/console.c  | 29 +-
 grub-core/term/efi/serial.c   | 18 +++
 grub-core/video/efi_gop.c | 18 +++
 grub-core/video/efi_uga.c |  8 +--
 23 files changed, 165 insertions(+), 170 deletions(-)

diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c
index fda62f4ea98a6da8..ab067ae6e51d43af 100644
--- a/grub-core/commands/acpi.c
+++ b/grub-core/commands/acpi.c
@@ -762,10 +762,10 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int 
argc, char **args)
 struct grub_efi_guid acpi = GRUB_EFI_ACPI_TABLE_GUID;
 struct grub_efi_guid acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID;
 
-efi_call_2 
(grub_efi_system_table->boot_services->install_configuration_table,
-  , grub_acpi_get_rsdpv2 ());
-efi_call_2 
(grub_efi_system_table->boot_services->install_configuration_table,
-  , grub_acpi_get_rsdpv1 ());
+grub_efi_system_table->boot_services->install_configuration_table (,
+  
grub_acpi_get_rsdpv2 ());
+grub_efi_system_table->boot_services->install_configuration_table (,
+  
grub_acpi_get_rsdpv1 ());
   }
 #endif
 
diff --git a/grub-core/commands/efi/efitextmode.c 
b/grub-core/commands/efi/efitextmode.c
index 3679f6b4d8028bc7..198bc694d3fc3c3b 100644
--- a/grub-core/commands/efi/efitextmode.c
+++ b/grub-core/commands/efi/efitextmode.c
@@ -36,7 +36,7 @@ grub_efi_set_mode (grub_efi_simple_text_output_interface_t *o,
 
   if (mode != o->mode->mode)
 {
-  status = efi_call_2 (o->set_mode, o, mode);
+  status = o->set_mode (o, mode);
   if (status == GRUB_EFI_SUCCESS)
;
   else if (status == GRUB_EFI_DEVICE_ERROR)
@@ -79,8 +79,7 @@ grub_cmd_efitextmode (grub_command_t cmd __attribute__ 
((unused)),
   grub_printf_ (N_("Available modes for console output device.\n"));
 
   for (i = 0; i < o->mode->max_mode; i++)
-   if (GRUB_EFI_SUCCESS == efi_call_4 (o->query_mode, o, i,
-   , ))
+   if (GRUB_EFI_SUCCESS == o->query_mode (o, i, , ))
  grub_printf_ (N_(" [%" PRIuGRUB_EFI_UINT32_T "]  Col %5"
   PRIuGRUB_EFI_UINTN_T " Row %5" PRIuGRUB_EFI_UINTN_T
   " %c\n"),
@@ -129,8 +128,7 @@ grub_cmd_efitextmode (grub_command_t cmd __attribute__ 
((unused)),
   N_("non-numeric or invalid rows number `%s'"), 
args[1]);
 
   for (i = 0; i < o->mode->max_mode; i++)
-   if (GRUB_EFI_SUCCESS == efi_call_4 (o->query_mode, o, i,
-   , ))
+   if (GRUB_EFI_SUCCESS == o->query_mode (o, i, , ))
  if (u_columns == columns && u_rows == rows)
return grub_efi_set_mode (o, (grub_efi_int32_t) i);
 
diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
index c304d25ccdd6f32b..53970149785a28f8 100644
--- a/grub-core/commands/efi/lsefi.c
+++ b/grub-core/commands/efi/lsefi.c
@@ -108,8 +108,9 @@ grub_cmd_lsefi (grub_command_t cmd __attribute__ ((unused)),
  grub_efi_print_device_path (dp);
}
 
-  status = efi_call_3 
(grub_efi_system_table->boot_services->protocols_per_handle,
-  handle, , _protocols);
+  status = grub_efi_system_table->boot_services->protocols_per_handle 
(handle,
+  
,
+  
_protocols);
   if (status != GRUB_EFI_SUCCESS) {
grub_printf ("Unable to retrieve protocols\n");
continue;

[PATCH v4 1/5] efi: Make EFI PXE protocol methods non-callable

2023-05-23 Thread Ard Biesheuvel
The grub_efi_pxe_t struct definition has placeholders for the various
protocol method pointers, given that they are never called in the code,
and the prototypes have been omitted, and therefore do not comply with
the UEFI spec.

So let's convert them into void* pointers, so they cannot be called
inadvertently.

Signed-off-by: Ard Biesheuvel 
---
 include/grub/efi/api.h | 24 ++--
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 4ae5e51c9013ceb3..7077d2265df9b20a 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1539,18 +1539,18 @@ typedef struct grub_efi_pxe_mode
 typedef struct grub_efi_pxe
 {
   grub_uint64_t rev;
-  void (*start) (void);
-  void (*stop) (void);
-  void (*dhcp) (void);
-  void (*discover) (void);
-  void (*mftp) (void);
-  void (*udpwrite) (void);
-  void (*udpread) (void);
-  void (*setipfilter) (void);
-  void (*arp) (void);
-  void (*setparams) (void);
-  void (*setstationip) (void);
-  void (*setpackets) (void);
+  void *start;
+  void *stop;
+  void *dhcp;
+  void *discover;
+  void *mftp;
+  void *udpwrite;
+  void *udpread;
+  void *setipfilter;
+  void *arp;
+  void *setparams;
+  void *setstationip;
+  void *setpackets;
   struct grub_efi_pxe_mode *mode;
 } grub_efi_pxe_t;
 
-- 
2.39.2


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 0/5] efi: Implement generic EFI boot for x86

2023-05-23 Thread Ard Biesheuvel
Switch the i386-efi and x86_64-efi builds to the generic EFI loader,
which enters the Linux kernel via the EFI stub and provides the initrd
via the LoadFile2 protocol. This unifies x86 with other EFI
architectures, and removes the dependency on the setup header and struct
bootparams.

Do some preparatory cleanup first, so we no longer need to rely on the
MS to SysV calling convention translation code.

Changes since v3:
- add missing efiapi annotations to efiemu routines
- work around dead code warning from Coverity by making unnecessary
  changes to the initrd loading logic in the generic EFI loader

Changes since v2:
- rebase onto latest master, which has the Loongarch changes
- retain Itanium support for now
- simplify the fallback logic - attempt to load the image as usual, and
  fallback on failure or if the image does not implement LoadFile2

Changes since v1:
- drop Itanium support, which is a maintenance burden as it shares the
  EFI code with other architectures, but does not have a EFI stub in
  Linux, and there is no way to test whether our changes break the boot
  for it or not;
- enable generic EFI for i386 as well
- wire up the existing x86 code as a fallback for kernels that lack EFI
  stub or LoadFile2 support. This removes the need for additional
  changes to support v5.8 or older kernels.

Cc: Daniel Kiper 
Cc: Glenn Washburn 

Ard Biesheuvel (5):
  efi: Make EFI PXE protocol methods non-callable
  efi: Add calling convention annotation to all prototypes
  efi: Drop all uses of efi_call_XX wrappers
  efi: Remove x86_64 call wrappers
  efi: Use generic EFI loader for x86_64 and i386

 grub-core/Makefile.core.def   |   3 +-
 grub-core/commands/acpi.c |   8 +-
 grub-core/commands/efi/efitextmode.c  |   8 +-
 grub-core/commands/efi/lsefi.c|   5 +-
 grub-core/commands/efi/tpm.c  |  21 +-
 grub-core/disk/efi/efidisk.c  |   7 +-
 grub-core/efiemu/runtime/efiemu.c |  48 +-
 grub-core/kern/arm/efi/init.c |  12 +-
 grub-core/kern/efi/efi.c  |  56 +-
 grub-core/kern/efi/init.c |  15 +-
 grub-core/kern/efi/mm.c   |  17 +-
 grub-core/kern/i386/efi/tsc.c |   2 +-
 grub-core/kern/ia64/efi/init.c|  14 +-
 grub-core/kern/loongarch64/efi/init.c |  10 +-
 grub-core/kern/x86_64/efi/callwrap.S  | 129 
 grub-core/lib/efi/datetime.c  |   9 +-
 grub-core/lib/efi/halt.c  |   4 +-
 grub-core/lib/efi/relocator.c |   6 +-
 grub-core/loader/efi/appleloader.c|   8 +-
 grub-core/loader/efi/chainloader.c|  20 +-
 grub-core/loader/efi/linux.c  |  47 +-
 grub-core/loader/i386/linux.c |   8 +
 grub-core/mmap/efi/mmap.c |  16 +-
 grub-core/net/drivers/efi/efinet.c|  26 +-
 grub-core/term/efi/console.c  |  29 +-
 grub-core/term/efi/serial.c   |  18 +-
 grub-core/video/efi_gop.c |  18 +-
 grub-core/video/efi_uga.c |   8 +-
 include/grub/efi/api.h| 666 +---
 include/grub/efi/efi.h|   2 +-
 include/grub/efi/tpm.h| 149 +++--
 31 files changed, 628 insertions(+), 761 deletions(-)
 delete mode 100644 grub-core/kern/x86_64/efi/callwrap.S

-- 
2.39.2


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v4 5/5] efi: Use generic EFI loader for x86_64 and i386

2023-05-23 Thread Ard Biesheuvel
Switch the x86 based EFI platform builds to the generic EFI loader,
which exposes the initrd via the LoadFile2 protocol instead of the
x86-specific setup header. This will launch the Linux kernel via its EFI
stub, which performs its own initialization in the EFI boot services
context before calling ExitBootServices() and performing the bare metal
Linux boot.

Given that only Linux kernel versions v5.8 and later support this initrd
loading method, the existing x86 loader is retained as a fallback, which
will also be used for Linux kernels built without the EFI stub. In this
case, GRUB calls ExitBootServices() before entering the Linux kernel,
and all EFI related information is provided to the kernel via struct
boot_params in the setup header, as before.

Note that this means that booting EFI stub kernels older than v5.8 is
not supported even when not using an initrd at all. Also, the EFI
handover protocol, which has no basis in the UEFI specification, is not
implemented.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/Makefile.core.def   |  2 +
 grub-core/loader/efi/linux.c  | 47 ++--
 grub-core/loader/i386/linux.c |  8 
 include/grub/efi/efi.h|  2 +-
 4 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1d88c4d1c2555f7f..e58b511242618df7 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1853,6 +1853,8 @@ module = {
   loongarch64 = loader/efi/linux.c;
   riscv32 = loader/efi/linux.c;
   riscv64 = loader/efi/linux.c;
+  i386_efi = loader/efi/linux.c;
+  x86_64_efi = loader/efi/linux.c;
   emu = loader/emu/linux.c;
   common = loader/linux.c;
   common = lib/cmdline.c;
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 15e0686549d7ecca..90ad1a7b82a76066 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -69,6 +69,12 @@ static initrd_media_device_path_t initrd_lf2_device_path = {
   }
 };
 
+extern grub_err_t
+grub_cmd_linux_x86_legacy (grub_command_t cmd, int argc, char *argv[]);
+
+extern grub_err_t
+grub_cmd_initrd_x86_legacy (grub_command_t cmd, int argc, char *argv[]);
+
 static grub_efi_status_t __grub_efi_api
 grub_efi_initrd_load_file2 (grub_efi_load_file2_t *this,
 grub_efi_device_path_t *device_path,
@@ -125,6 +131,7 @@ grub_arch_efi_linux_load_image_header (grub_file_t file,
   return GRUB_ERR_NONE;
 }
 
+#if !defined(__i386__) && !defined(__x86_64__)
 static grub_err_t
 finalize_params_linux (void)
 {
@@ -169,6 +176,7 @@ failure:
   grub_fdt_unload();
   return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
 }
+#endif
 
 grub_err_t
 grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
@@ -231,8 +239,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, 
grub_size_t size, char *args)
 static grub_err_t
 grub_linux_boot (void)
 {
+#if !defined(__i386__) && !defined(__x86_64__)
   if (finalize_params_linux () != GRUB_ERR_NONE)
 return grub_errno;
+#endif
 
   return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr,
   kernel_size, linux_args));
@@ -253,7 +263,9 @@ grub_linux_unload (void)
   if (kernel_addr)
 grub_efi_free_pages ((grub_addr_t) kernel_addr,
 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+#if !defined(__i386__) && !defined(__x86_64__)
   grub_fdt_unload ();
+#endif
 
   if (initrd_lf2_handle != NULL)
 {
@@ -269,6 +281,7 @@ grub_linux_unload (void)
   return GRUB_ERR_NONE;
 }
 
+#if !defined(__i386__) && !defined(__x86_64__)
 /*
  * As per linux/Documentation/arm/Booting
  * ARM initrd needs to be covered by kernel linear mapping,
@@ -304,6 +317,7 @@ allocate_initrd_mem (int initrd_pages)
   GRUB_EFI_ALLOCATE_MAX_ADDRESS,
   GRUB_EFI_LOADER_DATA);
 }
+#endif
 
 static grub_efi_status_t __grub_efi_api
 grub_efi_initrd_load_file2 (grub_efi_load_file2_t *this,
@@ -345,7 +359,7 @@ static grub_err_t
 grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 int argc, char *argv[])
 {
-  int initrd_size, initrd_pages;
+  int __attribute__ ((unused)) initrd_size, initrd_pages;
   void *initrd_mem = NULL;
   grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
   grub_efi_status_t status;
@@ -356,6 +370,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ 
((unused)),
   goto fail;
 }
 
+#if defined(__i386__) || defined(__x86_64__)
+  if (!initrd_use_loadfile2)
+return grub_cmd_initrd_x86_legacy (cmd, argc, argv);
+#endif
+
   if (!loaded)
 {
   grub_error (GRUB_ERR_BAD_ARGUMENT,
@@ -391,6 +410,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ 
((unused)),
   return GRUB_ERR_NONE;
 }
 
+#if !defined(__i386__) && !defined(__x86_64__)
   initrd_size = grub_get_initrd_size (_ctx);
   grub_dprintf ("linux", "Loading 

Re: [PATCH v3 0/5] efi: Implement generic EFI boot for x86

2023-05-23 Thread Daniel Kiper
On Tue, May 23, 2023 at 10:23:50AM +0200, Ard Biesheuvel wrote:
> Switch the i386-efi and x86_64-efi builds to the generic EFI loader,
> which enters the Linux kernel via the EFI stub and provides the initrd
> via the LoadFile2 protocol. This unifies x86 with other EFI
> architectures, and removes the dependency on the setup header and struct
> bootparams.
>
> Do some preparatory cleanup first, so we no longer need to rely on the
> MS to SysV calling convention translation code.
>
> Changes since v2:
> - rebase onto latest master, which has the Loongarch changes
> - retain Itanium support for now
> - simplify the fallback logic - attempt to load the image as usual, and
>   fallback on failure or if the image does not implement LoadFile2
>
> Changes since v1:
> - drop Itanium support, which is a maintenance burden as it shares the
>   EFI code with other architectures, but does not have a EFI stub in
>   Linux, and there is no way to test whether our changes break the boot
>   for it or not;
> - enable generic EFI for i386 as well
> - wire up the existing x86 code as a fallback for kernels that lack EFI
>   stub or LoadFile2 support. This removes the need for additional
>   changes to support v5.8 or older kernels.
>
> Cc: Daniel Kiper 
> Cc: Glenn Washburn 
>
> Ard Biesheuvel (5):
>   efi: Make EFI PXE protocol methods non-callable
>   efi: Add calling convention annotation to all prototypes
>   efi: Drop all uses of efi_call_XX wrappers
>   efi: Remove x86_64 call wrappers
>   efi: Use generic EFI loader for x86_64 and i386

I run test and Coverity builds and they reported some problems. You can
find in attachments a fix for the build problems and a Coverity report.
Please take a look...

Otherwise patches LGTM...

Thanks,

Daniel
diff --git a/grub-core/efiemu/runtime/efiemu.c b/grub-core/efiemu/runtime/efiemu.c
index 5db1f347b..53b3cce7b 100644
--- a/grub-core/efiemu/runtime/efiemu.c
+++ b/grub-core/efiemu/runtime/efiemu.c
@@ -32,17 +32,17 @@
 #include 
 #include 
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_time (grub_efi_time_t *time,
 		 grub_efi_time_capabilities_t *capabilities);
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_time (grub_efi_time_t *time);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_wakeup_time (grub_efi_boolean_t *enabled,
 			grub_efi_boolean_t *pending,
 			grub_efi_time_t *time);
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_wakeup_time (grub_efi_boolean_t enabled,
 			grub_efi_time_t *time);
 
@@ -52,51 +52,51 @@ efiemu_set_wakeup_time (grub_efi_boolean_t enabled,
 #define PHYSICAL_ATTRIBUTE __attribute__ ((section(".text-physical")));
 #endif
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
 grub_efi_uintn_t descriptor_size,
 grub_efi_uint32_t descriptor_version,
 grub_efi_memory_descriptor_t *virtual_map)
   PHYSICAL_ATTRIBUTE;
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_convert_pointer (grub_efi_uintn_t debug_disposition,
 			void **address)
   PHYSICAL_ATTRIBUTE;
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_variable (grub_efi_char16_t *variable_name,
 		 const grub_efi_guid_t *vendor_guid,
 		 grub_efi_uint32_t *attributes,
 		 grub_efi_uintn_t *data_size,
 		 void *data);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_next_variable_name (grub_efi_uintn_t *variable_name_size,
 			   grub_efi_char16_t *variable_name,
 			   grub_efi_guid_t *vendor_guid);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_set_variable (grub_efi_char16_t *variable_name,
 		 const grub_efi_guid_t *vendor_guid,
 		 grub_efi_uint32_t attributes,
 		 grub_efi_uintn_t data_size,
 		 void *data);
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 efiemu_get_next_high_monotonic_count (grub_efi_uint32_t *high_count);
-void
+void __grub_efi_api
 efiemu_reset_system (grub_efi_reset_type_t reset_type,
 		 grub_efi_status_t reset_status,
 		 grub_efi_uintn_t data_size,
 		 grub_efi_char16_t *reset_data);
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_set_virtual_address_map) (grub_efi_uintn_t,
 	  grub_efi_uintn_t,
 	  grub_efi_uint32_t,
 	  grub_efi_memory_descriptor_t *)
  PHYSICAL_ATTRIBUTE;
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition,
   void **address)
  PHYSICAL_ATTRIBUTE;
@@ -202,7 +202,7 @@ bcd_to_hex (grub_uint8_t in)
   return 10 * ((in & 0xf0) >> 4) + (in & 0x0f);
 }
 
-grub_efi_status_t
+grub_efi_status_t __grub_efi_api
 EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time,
 			   grub_efi_time_capabilities_t *capabilities)
 {
@@ -246,7 +246,7 @@ EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time,
   return GRUB_EFI_SUCCESS;
 }
 
-grub_efi_status_t

Re: [PATCH 0/4] Address coverity untrusted loop bound bugs in multiboot_elfxx.c

2023-05-23 Thread Daniel Kiper
On Mon, May 22, 2023 at 04:52:45PM -0400, Alec Brown wrote:
> Coverity has listed two untrusted loop bound bugs in
> grub-core/loader/multiboot_elfxx.c. They are CID 314029 and CID 314038. After
> testing the first patch, the CID changed to an untrusted loop bound for line
> 244: shdr = grub_calloc (shnum, ehdr->e_shentsize);. I added a second patch to
> address this, but after making these changes, it reverted to the original bug 
> of
> using tainted data in grub_memset(). The third patch addresses Coverity's 
> issue
> with phdr() in grub_memset() and reduces the bug to only having an issue with
> using phnum as an untrusted loop bound. However, we can ignore this since 
> phnum
> is already getting checked earlier in the function.
>
> I've also bundled a use-after-free patch with this patch set at the end.
>
> Alec Brown (4):
>   elf: Check program memory isn't larger than allocated memory size
>   elf: Check section header region before allocating memory
>   elf: check program header offset doesn't exceed constraints
>   efi: Fix use-after-free in finish boot services

For all the patches Reviewed-by: Daniel Kiper ...

Thank you for fixing these issues!

Daniel

___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v3 1/5] efi: Make EFI PXE protocol methods non-callable

2023-05-23 Thread Ard Biesheuvel
The grub_efi_pxe_t struct definition has placeholders for the various
protocol method pointers, given that they are never called in the code,
and the prototypes have been omitted, and therefore do not comply with
the UEFI spec.

So let's convert them into void* pointers, so they cannot be called
inadvertently.

Signed-off-by: Ard Biesheuvel 
---
 include/grub/efi/api.h | 24 ++--
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 4ae5e51c9013ceb3..7077d2265df9b20a 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1539,18 +1539,18 @@ typedef struct grub_efi_pxe_mode
 typedef struct grub_efi_pxe
 {
   grub_uint64_t rev;
-  void (*start) (void);
-  void (*stop) (void);
-  void (*dhcp) (void);
-  void (*discover) (void);
-  void (*mftp) (void);
-  void (*udpwrite) (void);
-  void (*udpread) (void);
-  void (*setipfilter) (void);
-  void (*arp) (void);
-  void (*setparams) (void);
-  void (*setstationip) (void);
-  void (*setpackets) (void);
+  void *start;
+  void *stop;
+  void *dhcp;
+  void *discover;
+  void *mftp;
+  void *udpwrite;
+  void *udpread;
+  void *setipfilter;
+  void *arp;
+  void *setparams;
+  void *setstationip;
+  void *setpackets;
   struct grub_efi_pxe_mode *mode;
 } grub_efi_pxe_t;
 
-- 
2.39.2


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v3 5/5] efi: Use generic EFI loader for x86_64 and i386

2023-05-23 Thread Ard Biesheuvel
Switch the x86 based EFI platform builds to the generic EFI loader,
which exposes the initrd via the LoadFile2 protocol instead of the
x86-specific setup header. This will launch the Linux kernel via its EFI
stub, which performs its own initialization in the EFI boot services
context before calling ExitBootServices() and performing the bare metal
Linux boot.

Given that only Linux kernel versions v5.8 and later support this initrd
loading method, the existing x86 loader is retained as a fallback, which
will also be used for Linux kernels built without the EFI stub. In this
case, GRUB calls ExitBootServices() before entering the Linux kernel,
and all EFI related information is provided to the kernel via struct
boot_params in the setup header, as before.

Note that this means that booting EFI stub kernels older than v5.8 is
not supported even when not using an initrd at all. Also, the EFI
handover protocol, which has no basis in the UEFI specification, is not
implemented.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/Makefile.core.def   |  2 +
 grub-core/loader/efi/linux.c  | 40 +++-
 grub-core/loader/i386/linux.c |  8 
 include/grub/efi/efi.h|  2 +-
 4 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 1d88c4d1c2555f7f..e58b511242618df7 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1853,6 +1853,8 @@ module = {
   loongarch64 = loader/efi/linux.c;
   riscv32 = loader/efi/linux.c;
   riscv64 = loader/efi/linux.c;
+  i386_efi = loader/efi/linux.c;
+  x86_64_efi = loader/efi/linux.c;
   emu = loader/emu/linux.c;
   common = loader/linux.c;
   common = lib/cmdline.c;
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 15e0686549d7ecca..bb44de6beec73378 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -69,6 +69,12 @@ static initrd_media_device_path_t initrd_lf2_device_path = {
   }
 };
 
+extern grub_err_t
+grub_cmd_linux_x86_legacy (grub_command_t cmd, int argc, char *argv[]);
+
+extern grub_err_t
+grub_cmd_initrd_x86_legacy (grub_command_t cmd, int argc, char *argv[]);
+
 static grub_efi_status_t __grub_efi_api
 grub_efi_initrd_load_file2 (grub_efi_load_file2_t *this,
 grub_efi_device_path_t *device_path,
@@ -125,6 +131,7 @@ grub_arch_efi_linux_load_image_header (grub_file_t file,
   return GRUB_ERR_NONE;
 }
 
+#if !defined(__i386__) && !defined(__x86_64__)
 static grub_err_t
 finalize_params_linux (void)
 {
@@ -169,6 +176,7 @@ failure:
   grub_fdt_unload();
   return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
 }
+#endif
 
 grub_err_t
 grub_arch_efi_linux_boot_image (grub_addr_t addr, grub_size_t size, char *args)
@@ -231,8 +239,10 @@ grub_arch_efi_linux_boot_image (grub_addr_t addr, 
grub_size_t size, char *args)
 static grub_err_t
 grub_linux_boot (void)
 {
+#if !defined(__i386__) && !defined(__x86_64__)
   if (finalize_params_linux () != GRUB_ERR_NONE)
 return grub_errno;
+#endif
 
   return (grub_arch_efi_linux_boot_image((grub_addr_t)kernel_addr,
   kernel_size, linux_args));
@@ -253,7 +263,9 @@ grub_linux_unload (void)
   if (kernel_addr)
 grub_efi_free_pages ((grub_addr_t) kernel_addr,
 GRUB_EFI_BYTES_TO_PAGES (kernel_size));
+#if !defined(__i386__) && !defined(__x86_64__)
   grub_fdt_unload ();
+#endif
 
   if (initrd_lf2_handle != NULL)
 {
@@ -269,6 +281,7 @@ grub_linux_unload (void)
   return GRUB_ERR_NONE;
 }
 
+#if !defined(__i386__) && !defined(__x86_64__)
 /*
  * As per linux/Documentation/arm/Booting
  * ARM initrd needs to be covered by kernel linear mapping,
@@ -304,6 +317,7 @@ allocate_initrd_mem (int initrd_pages)
   GRUB_EFI_ALLOCATE_MAX_ADDRESS,
   GRUB_EFI_LOADER_DATA);
 }
+#endif
 
 static grub_efi_status_t __grub_efi_api
 grub_efi_initrd_load_file2 (grub_efi_load_file2_t *this,
@@ -345,7 +359,7 @@ static grub_err_t
 grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
 int argc, char *argv[])
 {
-  int initrd_size, initrd_pages;
+  int __attribute__ ((unused)) initrd_size, initrd_pages;
   void *initrd_mem = NULL;
   grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
   grub_efi_status_t status;
@@ -356,6 +370,11 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ 
((unused)),
   goto fail;
 }
 
+#if defined(__i386__) || defined(__x86_64__)
+  if (!initrd_use_loadfile2)
+return grub_cmd_initrd_x86_legacy (cmd, argc, argv);
+#endif
+
   if (!loaded)
 {
   grub_error (GRUB_ERR_BAD_ARGUMENT,
@@ -391,6 +410,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ 
((unused)),
   return GRUB_ERR_NONE;
 }
 
+#if !defined(__i386__) && !defined(__x86_64__)
   initrd_size = grub_get_initrd_size (_ctx);
   grub_dprintf ("linux", "Loading 

[PATCH v3 2/5] efi: Add calling convention annotation to all prototypes

2023-05-23 Thread Ard Biesheuvel
UEFI mandates MS calling convention on x86_64, which was not supported
on GCC when UEFI support was first introduced into GRUB. However, now we
can use the ms_abi function type attribute to annotate functions and
function pointers as adhering to the MS calling convention, and the
compiler will generate the correct instruction sequence for us.

So let's add the appropriate annotation to all the function prototypes.
This will allow us to drop the special call wrappers in a subsequent
patch.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/kern/arm/efi/init.c |   2 +-
 include/grub/efi/api.h| 569 ++--
 include/grub/efi/tpm.h| 149 +++--
 3 files changed, 373 insertions(+), 347 deletions(-)

diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c
index 7fcf91bf41168d4a..ab48342f3cda116d 100644
--- a/grub-core/kern/arm/efi/init.c
+++ b/grub-core/kern/arm/efi/init.c
@@ -34,7 +34,7 @@ grub_efi_get_time_ms (void)
   return tmr;
 }
 
-static void
+static void __grub_efi_api
 increment_timer (grub_efi_event_t event __attribute__ ((unused)),
 void *context __attribute__ ((unused)))
 {
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index 7077d2265df9b20a..ebfa6c40fba34eae 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1127,209 +1127,210 @@ struct grub_efi_boot_services
   grub_efi_table_header_t hdr;
 
   grub_efi_tpl_t
-  (*raise_tpl) (grub_efi_tpl_t new_tpl);
+  (__grub_efi_api *raise_tpl) (grub_efi_tpl_t new_tpl);
 
   void
-  (*restore_tpl) (grub_efi_tpl_t old_tpl);
+  (__grub_efi_api *restore_tpl) (grub_efi_tpl_t old_tpl);
 
   grub_efi_status_t
-  (*allocate_pages) (grub_efi_allocate_type_t type,
-grub_efi_memory_type_t memory_type,
-grub_efi_uintn_t pages,
-grub_efi_physical_address_t *memory);
+  (__grub_efi_api *allocate_pages) (grub_efi_allocate_type_t type,
+   grub_efi_memory_type_t memory_type,
+   grub_efi_uintn_t pages,
+   grub_efi_physical_address_t *memory);
 
   grub_efi_status_t
-  (*free_pages) (grub_efi_physical_address_t memory,
-grub_efi_uintn_t pages);
+  (__grub_efi_api *free_pages) (grub_efi_physical_address_t memory,
+   grub_efi_uintn_t pages);
 
   grub_efi_status_t
-  (*get_memory_map) (grub_efi_uintn_t *memory_map_size,
-grub_efi_memory_descriptor_t *memory_map,
-grub_efi_uintn_t *map_key,
-grub_efi_uintn_t *descriptor_size,
-grub_efi_uint32_t *descriptor_version);
+  (__grub_efi_api *get_memory_map) (grub_efi_uintn_t *memory_map_size,
+   grub_efi_memory_descriptor_t *memory_map,
+   grub_efi_uintn_t *map_key,
+   grub_efi_uintn_t *descriptor_size,
+   grub_efi_uint32_t *descriptor_version);
 
   grub_efi_status_t
-  (*allocate_pool) (grub_efi_memory_type_t pool_type,
-   grub_efi_uintn_t size,
-   void **buffer);
+  (__grub_efi_api *allocate_pool) (grub_efi_memory_type_t pool_type,
+  grub_efi_uintn_t size,
+  void **buffer);
 
   grub_efi_status_t
-  (*free_pool) (void *buffer);
+  (__grub_efi_api *free_pool) (void *buffer);
 
   grub_efi_status_t
-  (*create_event) (grub_efi_uint32_t type,
-  grub_efi_tpl_t notify_tpl,
-  void (*notify_function) (grub_efi_event_t event,
-   void *context),
-  void *notify_context,
-  grub_efi_event_t *event);
+  (__grub_efi_api *create_event) (grub_efi_uint32_t type,
+ grub_efi_tpl_t notify_tpl,
+ void (__grub_efi_api *notify_function) 
(grub_efi_event_t,
+ void 
*context),
+ void *notify_context,
+ grub_efi_event_t *event);
 
   grub_efi_status_t
-  (*set_timer) (grub_efi_event_t event,
-   grub_efi_timer_delay_t type,
-   grub_efi_uint64_t trigger_time);
+  (__grub_efi_api *set_timer) (grub_efi_event_t event,
+  grub_efi_timer_delay_t type,
+  grub_efi_uint64_t trigger_time);
 
   grub_efi_status_t
-  (*wait_for_event) (grub_efi_uintn_t num_events,
-grub_efi_event_t *event,
-grub_efi_uintn_t *index);
+  (__grub_efi_api *wait_for_event) (grub_efi_uintn_t num_events,
+   grub_efi_event_t *event,
+   grub_efi_uintn_t *index);
 
   grub_efi_status_t
-  (*signal_event) 

[PATCH v3 0/5] efi: Implement generic EFI boot for x86

2023-05-23 Thread Ard Biesheuvel
Switch the i386-efi and x86_64-efi builds to the generic EFI loader,
which enters the Linux kernel via the EFI stub and provides the initrd
via the LoadFile2 protocol. This unifies x86 with other EFI
architectures, and removes the dependency on the setup header and struct
bootparams.

Do some preparatory cleanup first, so we no longer need to rely on the
MS to SysV calling convention translation code.

Changes since v2:
- rebase onto latest master, which has the Loongarch changes
- retain Itanium support for now
- simplify the fallback logic - attempt to load the image as usual, and
  fallback on failure or if the image does not implement LoadFile2

Changes since v1:
- drop Itanium support, which is a maintenance burden as it shares the
  EFI code with other architectures, but does not have a EFI stub in
  Linux, and there is no way to test whether our changes break the boot
  for it or not;
- enable generic EFI for i386 as well
- wire up the existing x86 code as a fallback for kernels that lack EFI
  stub or LoadFile2 support. This removes the need for additional
  changes to support v5.8 or older kernels.

Cc: Daniel Kiper 
Cc: Glenn Washburn 

Ard Biesheuvel (5):
  efi: Make EFI PXE protocol methods non-callable
  efi: Add calling convention annotation to all prototypes
  efi: Drop all uses of efi_call_XX wrappers
  efi: Remove x86_64 call wrappers
  efi: Use generic EFI loader for x86_64 and i386

 grub-core/Makefile.core.def   |   3 +-
 grub-core/commands/acpi.c |   8 +-
 grub-core/commands/efi/efitextmode.c  |   8 +-
 grub-core/commands/efi/lsefi.c|   5 +-
 grub-core/commands/efi/tpm.c  |  21 +-
 grub-core/disk/efi/efidisk.c  |   7 +-
 grub-core/kern/arm/efi/init.c |  12 +-
 grub-core/kern/efi/efi.c  |  56 +-
 grub-core/kern/efi/init.c |  15 +-
 grub-core/kern/efi/mm.c   |  17 +-
 grub-core/kern/i386/efi/tsc.c |   2 +-
 grub-core/kern/ia64/efi/init.c|  14 +-
 grub-core/kern/loongarch64/efi/init.c |  10 +-
 grub-core/kern/x86_64/efi/callwrap.S  | 129 
 grub-core/lib/efi/datetime.c  |   9 +-
 grub-core/lib/efi/halt.c  |   4 +-
 grub-core/lib/efi/relocator.c |   6 +-
 grub-core/loader/efi/appleloader.c|   8 +-
 grub-core/loader/efi/chainloader.c|  20 +-
 grub-core/loader/efi/linux.c  |  40 +-
 grub-core/loader/i386/linux.c |   8 +
 grub-core/mmap/efi/mmap.c |  16 +-
 grub-core/net/drivers/efi/efinet.c|  26 +-
 grub-core/term/efi/console.c  |  29 +-
 grub-core/term/efi/serial.c   |  18 +-
 grub-core/video/efi_gop.c |  18 +-
 grub-core/video/efi_uga.c |   8 +-
 include/grub/efi/api.h| 666 +---
 include/grub/efi/efi.h|   2 +-
 include/grub/efi/tpm.h| 149 +++--
 30 files changed, 600 insertions(+), 734 deletions(-)
 delete mode 100644 grub-core/kern/x86_64/efi/callwrap.S

-- 
2.39.2


___
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel


[PATCH v3 3/5] efi: Drop all uses of efi_call_XX wrappers

2023-05-23 Thread Ard Biesheuvel
Now that GCC can generate function calls using the correct calling
convention for us, we can stop using the efi_call_XX () wrappers, and
just dereference the function pointers directly.

This avoids the untyped variadic wrapper routines, which means better
type checking for the method calls.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/commands/acpi.c |  8 +--
 grub-core/commands/efi/efitextmode.c  |  8 ++-
 grub-core/commands/efi/lsefi.c|  5 +-
 grub-core/commands/efi/tpm.c  | 21 
 grub-core/disk/efi/efidisk.c  |  7 +--
 grub-core/kern/arm/efi/init.c | 10 ++--
 grub-core/kern/efi/efi.c  | 56 ++--
 grub-core/kern/efi/init.c | 15 +++---
 grub-core/kern/efi/mm.c   | 17 +++---
 grub-core/kern/i386/efi/tsc.c |  2 +-
 grub-core/kern/ia64/efi/init.c| 14 ++---
 grub-core/kern/loongarch64/efi/init.c | 10 ++--
 grub-core/lib/efi/datetime.c  |  9 ++--
 grub-core/lib/efi/halt.c  |  4 +-
 grub-core/lib/efi/relocator.c |  6 +--
 grub-core/loader/efi/appleloader.c|  8 +--
 grub-core/loader/efi/chainloader.c| 20 +++
 grub-core/mmap/efi/mmap.c | 16 +++---
 grub-core/net/drivers/efi/efinet.c| 26 -
 grub-core/term/efi/console.c  | 29 +-
 grub-core/term/efi/serial.c   | 18 +++
 grub-core/video/efi_gop.c | 18 +++
 grub-core/video/efi_uga.c |  8 +--
 23 files changed, 165 insertions(+), 170 deletions(-)

diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c
index fda62f4ea98a6da8..ab067ae6e51d43af 100644
--- a/grub-core/commands/acpi.c
+++ b/grub-core/commands/acpi.c
@@ -762,10 +762,10 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int 
argc, char **args)
 struct grub_efi_guid acpi = GRUB_EFI_ACPI_TABLE_GUID;
 struct grub_efi_guid acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID;
 
-efi_call_2 
(grub_efi_system_table->boot_services->install_configuration_table,
-  , grub_acpi_get_rsdpv2 ());
-efi_call_2 
(grub_efi_system_table->boot_services->install_configuration_table,
-  , grub_acpi_get_rsdpv1 ());
+grub_efi_system_table->boot_services->install_configuration_table (,
+  
grub_acpi_get_rsdpv2 ());
+grub_efi_system_table->boot_services->install_configuration_table (,
+  
grub_acpi_get_rsdpv1 ());
   }
 #endif
 
diff --git a/grub-core/commands/efi/efitextmode.c 
b/grub-core/commands/efi/efitextmode.c
index 3679f6b4d8028bc7..198bc694d3fc3c3b 100644
--- a/grub-core/commands/efi/efitextmode.c
+++ b/grub-core/commands/efi/efitextmode.c
@@ -36,7 +36,7 @@ grub_efi_set_mode (grub_efi_simple_text_output_interface_t *o,
 
   if (mode != o->mode->mode)
 {
-  status = efi_call_2 (o->set_mode, o, mode);
+  status = o->set_mode (o, mode);
   if (status == GRUB_EFI_SUCCESS)
;
   else if (status == GRUB_EFI_DEVICE_ERROR)
@@ -79,8 +79,7 @@ grub_cmd_efitextmode (grub_command_t cmd __attribute__ 
((unused)),
   grub_printf_ (N_("Available modes for console output device.\n"));
 
   for (i = 0; i < o->mode->max_mode; i++)
-   if (GRUB_EFI_SUCCESS == efi_call_4 (o->query_mode, o, i,
-   , ))
+   if (GRUB_EFI_SUCCESS == o->query_mode (o, i, , ))
  grub_printf_ (N_(" [%" PRIuGRUB_EFI_UINT32_T "]  Col %5"
   PRIuGRUB_EFI_UINTN_T " Row %5" PRIuGRUB_EFI_UINTN_T
   " %c\n"),
@@ -129,8 +128,7 @@ grub_cmd_efitextmode (grub_command_t cmd __attribute__ 
((unused)),
   N_("non-numeric or invalid rows number `%s'"), 
args[1]);
 
   for (i = 0; i < o->mode->max_mode; i++)
-   if (GRUB_EFI_SUCCESS == efi_call_4 (o->query_mode, o, i,
-   , ))
+   if (GRUB_EFI_SUCCESS == o->query_mode (o, i, , ))
  if (u_columns == columns && u_rows == rows)
return grub_efi_set_mode (o, (grub_efi_int32_t) i);
 
diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
index c304d25ccdd6f32b..53970149785a28f8 100644
--- a/grub-core/commands/efi/lsefi.c
+++ b/grub-core/commands/efi/lsefi.c
@@ -108,8 +108,9 @@ grub_cmd_lsefi (grub_command_t cmd __attribute__ ((unused)),
  grub_efi_print_device_path (dp);
}
 
-  status = efi_call_3 
(grub_efi_system_table->boot_services->protocols_per_handle,
-  handle, , _protocols);
+  status = grub_efi_system_table->boot_services->protocols_per_handle 
(handle,
+  
,
+  
_protocols);
   if (status != GRUB_EFI_SUCCESS) {
grub_printf ("Unable to retrieve protocols\n");
continue;

[PATCH v3 4/5] efi: Remove x86_64 call wrappers

2023-05-23 Thread Ard Biesheuvel
The call wrappers are no longer needed now that GCC can generate
function calls using MS calling convention, so let's get rid of them.

Signed-off-by: Ard Biesheuvel 
---
 grub-core/Makefile.core.def  |   1 -
 grub-core/kern/x86_64/efi/callwrap.S | 129 
 include/grub/efi/api.h   |  73 ---
 3 files changed, 203 deletions(-)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index c69c4a3321d27ecd..1d88c4d1c2555f7f 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -236,7 +236,6 @@ kernel = {
 
   x86_64 = kern/x86_64/dl.c;
   x86_64_xen = kern/x86_64/dl.c;
-  x86_64_efi = kern/x86_64/efi/callwrap.S;
   x86_64_efi = kern/i386/efi/init.c;
   x86_64_efi = bus/pci.c;
 
diff --git a/grub-core/kern/x86_64/efi/callwrap.S 
b/grub-core/kern/x86_64/efi/callwrap.S
deleted file mode 100644
index 1337fd9fc823f8a4..
--- a/grub-core/kern/x86_64/efi/callwrap.S
+++ /dev/null
@@ -1,129 +0,0 @@
-/* callwrap.S - wrapper for x86_64 efi calls */
-/*
- *  GRUB  --  GRand Unified Bootloader
- *  Copyright (C) 2006,2007,2009  Free Software Foundation, Inc.
- *
- *  GRUB is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  GRUB is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with GRUB.  If not, see .
- */
-
-#include 
-#include 
-
-/*
- * x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use
- * different call conversion, so we need to do some conversion.
- *
- * gcc:
- *   %rdi,  %rsi,  %rdx,  %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ...
- *
- * efi:
- *   %rcx,  %rdx,  %r8,  %r9,  32(%rsp), 40(%rsp), 48(%rsp), ...
- *
- */
-
-.file   "callwrap.S"
-.text
-
-FUNCTION(efi_wrap_0)
-   subq $40, %rsp
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_1)
-   subq $40, %rsp
-   mov  %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_2)
-   subq $40, %rsp
-   mov  %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_3)
-   subq $40, %rsp
-   mov  %rcx, %r8
-   mov  %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_4)
-   subq $40, %rsp
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_5)
-   subq $40, %rsp
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $40, %rsp
-   ret
-
-FUNCTION(efi_wrap_6)
-   subq $56, %rsp
-   mov 56+8(%rsp), %rax
-   mov %rax, 40(%rsp)
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $56, %rsp
-   ret
-
-FUNCTION(efi_wrap_7)
-   subq $88, %rsp
-   mov 88+16(%rsp), %rax
-   mov %rax, 48(%rsp)
-   mov 88+8(%rsp), %rax
-   mov %rax, 40(%rsp)
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $88, %rsp
-   ret
-
-FUNCTION(efi_wrap_10)
-   subq $88, %rsp
-   mov 88+40(%rsp), %rax
-   mov %rax, 72(%rsp)
-   mov 88+32(%rsp), %rax
-   mov %rax, 64(%rsp)
-   mov 88+24(%rsp), %rax
-   mov %rax, 56(%rsp)
-   mov 88+16(%rsp), %rax
-   mov %rax, 48(%rsp)
-   mov 88+8(%rsp), %rax
-   mov %rax, 40(%rsp)
-   mov %r9, 32(%rsp)
-   mov %r8, %r9
-   mov %rcx, %r8
-   mov %rsi, %rcx
-   call *%rdi
-   addq $88, %rsp
-   ret
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
index ebfa6c40fba34eae..fb881ae12d5ae73a 100644
--- a/include/grub/efi/api.h
+++ b/include/grub/efi/api.h
@@ -1824,77 +1824,4 @@ struct initrd_media_device_path {
 } GRUB_PACKED;
 typedef struct initrd_media_device_path initrd_media_device_path_t;
 
-#if (GRUB_TARGET_SIZEOF_VOID_P == 4) || defined (__ia64__) \
-  || defined (__aarch64__) || defined (__MINGW64__) || defined (__CYGWIN__) \
-  || defined(__riscv) || defined (__loongarch__)
-
-#define efi_call_0(func)   (func)()
-#define efi_call_1(func, a)(func)(a)
-#define efi_call_2(func, a, b) (func)(a, b)
-#define efi_call_3(func, a, b, c)  (func)(a, b, c)
-#define efi_call_4(func, a, b, c, d)   (func)(a, b, c, d)
-#define efi_call_5(func, a, b, c, d, e)(func)(a, b, c, d, e)
-#define efi_call_6(func, a, b, c, d, e, f) (func)(a, b, c, d, e, f)