diff mbox series

[12/16] x86/boot: Add EFI kernel extraction interface

Message ID 8e9f2d7b0645e17efaa9eec0423f6d2c4a55fc16.1662459668.git.baskov@ispras.ru
State New
Headers show
Series x86_64: Improvements at compressed kernel stage | expand

Commit Message

Evgeniy Baskov Sept. 6, 2022, 10:41 a.m. UTC
To enable extraction of kernel image from EFI stub code directly
extraction code needs to have separate interface that avoid part
of low level initialization logic, i.e. serial port setup.

Add kernel extraction function callable from libstub as a part
of preparation for extracting the kernel directly from EFI environment.

Signed-off-by: Evgeniy Baskov <baskov@ispras.ru>
---
 arch/x86/boot/compressed/head_32.S |  3 +-
 arch/x86/boot/compressed/head_64.S |  2 +-
 arch/x86/boot/compressed/misc.c    | 85 +++++++++++++++++++++---------
 arch/x86/boot/compressed/misc.h    |  2 +
 arch/x86/boot/compressed/putstr.c  |  9 ++++
 5 files changed, 73 insertions(+), 28 deletions(-)

Comments

Ard Biesheuvel Oct. 19, 2022, 7:27 a.m. UTC | #1
On Tue, 6 Sept 2022 at 12:42, Evgeniy Baskov <baskov@ispras.ru> wrote:
>
> To enable extraction of kernel image from EFI stub code directly
> extraction code needs to have separate interface that avoid part
> of low level initialization logic, i.e. serial port setup.
>
> Add kernel extraction function callable from libstub as a part
> of preparation for extracting the kernel directly from EFI environment.
>
> Signed-off-by: Evgeniy Baskov <baskov@ispras.ru>
> ---
>  arch/x86/boot/compressed/head_32.S |  3 +-
>  arch/x86/boot/compressed/head_64.S |  2 +-
>  arch/x86/boot/compressed/misc.c    | 85 +++++++++++++++++++++---------
>  arch/x86/boot/compressed/misc.h    |  2 +
>  arch/x86/boot/compressed/putstr.c  |  9 ++++
>  5 files changed, 73 insertions(+), 28 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
> index 3b354eb9516d..b46a1c4109cf 100644
> --- a/arch/x86/boot/compressed/head_32.S
> +++ b/arch/x86/boot/compressed/head_32.S
> @@ -217,8 +217,7 @@ SYM_DATA(image_offset, .long 0)
>   */
>         .bss
>         .balign 4
> -boot_heap:
> -       .fill BOOT_HEAP_SIZE, 1, 0
> +SYM_DATA(boot_heap,    .fill BOOT_HEAP_SIZE, 1, 0)
>  boot_stack:
>         .fill BOOT_STACK_SIZE, 1, 0
>  boot_stack_end:
> diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
> index 889ca7176aa7..37ce094571b5 100644
> --- a/arch/x86/boot/compressed/head_64.S
> +++ b/arch/x86/boot/compressed/head_64.S
> @@ -1007,7 +1007,7 @@ SYM_FUNC_END(startup32_check_sev_cbit)
>   */
>         .bss
>         .balign 4
> -SYM_DATA_LOCAL(boot_heap,      .fill BOOT_HEAP_SIZE, 1, 0)
> +SYM_DATA(boot_heap,    .fill BOOT_HEAP_SIZE, 1, 0)
>
>  SYM_DATA_START_LOCAL(boot_stack)
>         .fill BOOT_STACK_SIZE, 1, 0
> diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
> index e2c0d05ac293..8016cc5c300e 100644
> --- a/arch/x86/boot/compressed/misc.c
> +++ b/arch/x86/boot/compressed/misc.c
> @@ -293,11 +293,11 @@ static void parse_elf(void *output, unsigned long output_len,
>   *             |-------uncompressed kernel image---------|
>   *
>   */
> -asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
> -                                 unsigned char *input_data,
> -                                 unsigned long input_len,
> -                                 unsigned char *output,
> -                                 unsigned long output_len)
> +static void *do_extract_kernel(void *rmode,
> +                              unsigned char *input_data,
> +                              unsigned long input_len,
> +                              unsigned char *output,
> +                              unsigned long output_len)
>  {
>         const unsigned long kernel_total_size = VO__end - VO__text;
>         unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
> @@ -311,18 +311,6 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
>
>         sanitize_boot_params(boot_params);
>
> -       init_default_io_ops();
> -
> -       /*
> -        * Detect TDX guest environment.
> -        *
> -        * It has to be done before console_init() in order to use
> -        * paravirtualized port I/O operations if needed.
> -        */
> -       early_tdx_detect();
> -
> -       init_bare_console();
> -
>         /*
>          * Save RSDP address for later use. Have this after console_init()
>          * so that early debugging output from the RSDP parsing code can be
> @@ -330,11 +318,6 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
>          */
>         boot_params->acpi_rsdp_addr = get_rsdp_addr();
>
> -       debug_putstr("early console in extract_kernel\n");
> -
> -       free_mem_ptr     = heap;        /* Heap */
> -       free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
> -
>         /*
>          * The memory hole needed for the kernel is the larger of either
>          * the entire decompressed kernel plus relocation table, or the
> @@ -387,12 +370,12 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
>         if (virt_addr & (MIN_KERNEL_ALIGN - 1))
>                 error("Destination virtual address inappropriately aligned");
>  #ifdef CONFIG_X86_64
> -       if (heap > 0x3fffffffffffUL)
> +       if (phys_addr > 0x3fffffffffffUL)
>                 error("Destination address too large");
>         if (virt_addr + max(output_len, kernel_total_size) > KERNEL_IMAGE_SIZE)
>                 error("Destination virtual address is beyond the kernel mapping area");
>  #else
> -       if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
> +       if (phys_addr > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
>                 error("Destination address too large");
>  #endif
>  #ifndef CONFIG_RELOCATABLE
> @@ -406,12 +389,64 @@ asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
>         parse_elf(output, output_len, virt_addr);
>         debug_putstr("done.\nBooting the kernel.\n");
>
> +       return output;
> +}
> +
> +asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
> +                                 unsigned char *input_data,
> +                                 unsigned long input_len,
> +                                 unsigned char *output,
> +                                 unsigned long output_len)
> +{
> +       void *entry;
> +
> +       init_default_io_ops();
> +
> +       /*
> +        * Detect TDX guest environment.
> +        *
> +        * It has to be done before console_init() in order to use
> +        * paravirtualized port I/O operations if needed.
> +        */
> +       early_tdx_detect();
> +
> +       init_bare_console();
> +
> +       debug_putstr("early console in extract_kernel\n");
> +
> +       free_mem_ptr     = heap;        /* Heap */
> +       free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
> +
> +       entry = do_extract_kernel(rmode, input_data,
> +                                 input_len, output, output_len);
> +
>         /* Disable exception handling before booting the kernel */
>         cleanup_exception_handling();
>
> -       return output;
> +       return entry;
>  }
>
> +void *efi_extract_kernel(struct boot_params *rmode,
> +                        struct efi_iofunc *iofunc,
> +                        unsigned char *input_data,
> +                        unsigned long input_len,
> +                        unsigned char *output,
> +                        unsigned long output_len)
> +{
> +       extern char boot_heap[BOOT_HEAP_SIZE];
> +
> +       free_mem_ptr     = (unsigned long)boot_heap;    /* Heap */
> +       free_mem_end_ptr = (unsigned long)boot_heap + BOOT_HEAP_SIZE;
> +
> +       init_efi_console(iofunc);
> +
> +       return do_extract_kernel(rmode, input_data,
> +                                input_len, output, output_len);
> +}
> +
> +
> +
> +
>  void fortify_panic(const char *name)
>  {
>         error("detected buffer overflow");
> diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
> index 39dc3de50268..b5aa0af6c59e 100644
> --- a/arch/x86/boot/compressed/misc.h
> +++ b/arch/x86/boot/compressed/misc.h
> @@ -26,6 +26,7 @@
>  #include <asm/boot.h>
>  #include <asm/bootparam.h>
>  #include <asm/desc_defs.h>
> +#include <asm/shared/extract.h>
>
>  #include "tdx.h"
>
> @@ -126,6 +127,7 @@ static inline void console_init(void)
>
>  /* putstr.c */
>  void init_bare_console(void);
> +void init_efi_console(struct efi_iofunc *iofunc);
>
>  #ifdef CONFIG_AMD_MEM_ENCRYPT
>  void sev_enable(struct boot_params *bp);
> diff --git a/arch/x86/boot/compressed/putstr.c b/arch/x86/boot/compressed/putstr.c
> index accba0de8be9..238d9677df61 100644
> --- a/arch/x86/boot/compressed/putstr.c
> +++ b/arch/x86/boot/compressed/putstr.c
> @@ -32,6 +32,15 @@ void init_bare_console(void)
>         console_init();
>  }
>
> +void init_efi_console(struct efi_iofunc *iofunc)

struct efi_iofunc does not exist yet

> +{
> +       __putstr = iofunc->putstr;
> +       __puthex = iofunc->puthex;
> +#ifdef CONFIG_X86_64
> +       kernel_add_identity_map = iofunc->map_range;
> +#endif
> +}
> +
>  static void scroll(void)
>  {
>         int i;
> --
> 2.35.1
>
Evgeniy Baskov Oct. 20, 2022, 12:14 p.m. UTC | #2
On 2022-10-19 10:27, Ard Biesheuvel wrote:
> On Tue, 6 Sept 2022 at 12:42, Evgeniy Baskov <baskov@ispras.ru> wrote:
...
>> 
>> +void init_efi_console(struct efi_iofunc *iofunc)
> 
> struct efi_iofunc does not exist yet
> 

My bad, will move the definition from the next patch to this one.
Thanks for pointing out.
diff mbox series

Patch

diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 3b354eb9516d..b46a1c4109cf 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -217,8 +217,7 @@  SYM_DATA(image_offset, .long 0)
  */
 	.bss
 	.balign 4
-boot_heap:
-	.fill BOOT_HEAP_SIZE, 1, 0
+SYM_DATA(boot_heap,	.fill BOOT_HEAP_SIZE, 1, 0)
 boot_stack:
 	.fill BOOT_STACK_SIZE, 1, 0
 boot_stack_end:
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 889ca7176aa7..37ce094571b5 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -1007,7 +1007,7 @@  SYM_FUNC_END(startup32_check_sev_cbit)
  */
 	.bss
 	.balign 4
-SYM_DATA_LOCAL(boot_heap,	.fill BOOT_HEAP_SIZE, 1, 0)
+SYM_DATA(boot_heap,	.fill BOOT_HEAP_SIZE, 1, 0)
 
 SYM_DATA_START_LOCAL(boot_stack)
 	.fill BOOT_STACK_SIZE, 1, 0
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index e2c0d05ac293..8016cc5c300e 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -293,11 +293,11 @@  static void parse_elf(void *output, unsigned long output_len,
  *             |-------uncompressed kernel image---------|
  *
  */
-asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
-				  unsigned char *input_data,
-				  unsigned long input_len,
-				  unsigned char *output,
-				  unsigned long output_len)
+static void *do_extract_kernel(void *rmode,
+			       unsigned char *input_data,
+			       unsigned long input_len,
+			       unsigned char *output,
+			       unsigned long output_len)
 {
 	const unsigned long kernel_total_size = VO__end - VO__text;
 	unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
@@ -311,18 +311,6 @@  asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
 
 	sanitize_boot_params(boot_params);
 
-	init_default_io_ops();
-
-	/*
-	 * Detect TDX guest environment.
-	 *
-	 * It has to be done before console_init() in order to use
-	 * paravirtualized port I/O operations if needed.
-	 */
-	early_tdx_detect();
-
-	init_bare_console();
-
 	/*
 	 * Save RSDP address for later use. Have this after console_init()
 	 * so that early debugging output from the RSDP parsing code can be
@@ -330,11 +318,6 @@  asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
 	 */
 	boot_params->acpi_rsdp_addr = get_rsdp_addr();
 
-	debug_putstr("early console in extract_kernel\n");
-
-	free_mem_ptr     = heap;	/* Heap */
-	free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
-
 	/*
 	 * The memory hole needed for the kernel is the larger of either
 	 * the entire decompressed kernel plus relocation table, or the
@@ -387,12 +370,12 @@  asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
 	if (virt_addr & (MIN_KERNEL_ALIGN - 1))
 		error("Destination virtual address inappropriately aligned");
 #ifdef CONFIG_X86_64
-	if (heap > 0x3fffffffffffUL)
+	if (phys_addr > 0x3fffffffffffUL)
 		error("Destination address too large");
 	if (virt_addr + max(output_len, kernel_total_size) > KERNEL_IMAGE_SIZE)
 		error("Destination virtual address is beyond the kernel mapping area");
 #else
-	if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
+	if (phys_addr > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
 		error("Destination address too large");
 #endif
 #ifndef CONFIG_RELOCATABLE
@@ -406,12 +389,64 @@  asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
 	parse_elf(output, output_len, virt_addr);
 	debug_putstr("done.\nBooting the kernel.\n");
 
+	return output;
+}
+
+asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
+				  unsigned char *input_data,
+				  unsigned long input_len,
+				  unsigned char *output,
+				  unsigned long output_len)
+{
+	void *entry;
+
+	init_default_io_ops();
+
+	/*
+	 * Detect TDX guest environment.
+	 *
+	 * It has to be done before console_init() in order to use
+	 * paravirtualized port I/O operations if needed.
+	 */
+	early_tdx_detect();
+
+	init_bare_console();
+
+	debug_putstr("early console in extract_kernel\n");
+
+	free_mem_ptr     = heap;	/* Heap */
+	free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
+
+	entry = do_extract_kernel(rmode, input_data,
+				  input_len, output, output_len);
+
 	/* Disable exception handling before booting the kernel */
 	cleanup_exception_handling();
 
-	return output;
+	return entry;
 }
 
+void *efi_extract_kernel(struct boot_params *rmode,
+			 struct efi_iofunc *iofunc,
+			 unsigned char *input_data,
+			 unsigned long input_len,
+			 unsigned char *output,
+			 unsigned long output_len)
+{
+	extern char boot_heap[BOOT_HEAP_SIZE];
+
+	free_mem_ptr     = (unsigned long)boot_heap;	/* Heap */
+	free_mem_end_ptr = (unsigned long)boot_heap + BOOT_HEAP_SIZE;
+
+	init_efi_console(iofunc);
+
+	return do_extract_kernel(rmode, input_data,
+				 input_len, output, output_len);
+}
+
+
+
+
 void fortify_panic(const char *name)
 {
 	error("detected buffer overflow");
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 39dc3de50268..b5aa0af6c59e 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -26,6 +26,7 @@ 
 #include <asm/boot.h>
 #include <asm/bootparam.h>
 #include <asm/desc_defs.h>
+#include <asm/shared/extract.h>
 
 #include "tdx.h"
 
@@ -126,6 +127,7 @@  static inline void console_init(void)
 
 /* putstr.c */
 void init_bare_console(void);
+void init_efi_console(struct efi_iofunc *iofunc);
 
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 void sev_enable(struct boot_params *bp);
diff --git a/arch/x86/boot/compressed/putstr.c b/arch/x86/boot/compressed/putstr.c
index accba0de8be9..238d9677df61 100644
--- a/arch/x86/boot/compressed/putstr.c
+++ b/arch/x86/boot/compressed/putstr.c
@@ -32,6 +32,15 @@  void init_bare_console(void)
 	console_init();
 }
 
+void init_efi_console(struct efi_iofunc *iofunc)
+{
+	__putstr = iofunc->putstr;
+	__puthex = iofunc->puthex;
+#ifdef CONFIG_X86_64
+	kernel_add_identity_map = iofunc->map_range;
+#endif
+}
+
 static void scroll(void)
 {
 	int i;