mbox series

[RFC,0/7] UEFI emulator for kexec

Message ID 20240718085759.13247-1-piliu@redhat.com
Headers show
Series UEFI emulator for kexec | expand

Message

Pingfan Liu July 18, 2024, 8:57 a.m. UTC
*** Background ***

As more PE format kernel images are introduced, it post challenge to kexec to
cope with the new format.

In my attempt to add support for arm64 zboot image in the kernel [1],
Ard suggested using an emulator to tackle this issue.  Last year, when
Jan tried to introduce UKI support in the kernel [2], Ard mentioned the
emulator approach again [3]

After discussion, Ard's approach seems to be a more promising solution
to handle PE format kernels once and for all.  This series follows that
approach and implements an emulator to emulate EFI boot time services,
allowing the efistub kernel to self-extract and boot.



*** Overview of implement ***
The whole model consits of three parts:

-1. The emulator
It is a self-relocatable PIC code, which is finally linked into kernel, but not
export any internal symbol to kernel.  It mainly contains: a PE file parser,
which loads PE format kernel, a group of functions to emulate efi boot service.

-2. inside kernel, PE-format loader
Its main task is to set up two extra kexec_segment, one for emulator, the other
for passing information from the first kernel to emulator.

-3. set up identity mapping only for the memory used by the emulator.
Here it relies on kimage_alloc_control_pages() to get pages, which will not
stamped during the process of kexec relocate (cp from src to dst). And since the
mapping only covers a small range of memory, it cost small amount memory.


*** To do ***

Currently, it only works on arm64 _zboot_ image on arm64 virt machine. For
arm64 UKI, I have not completed it. But it should be easy to archieve by
implementing EFI_LOAD_FILE2_PROTOCOL.LoadFile(). And with a slightly
improvement, it would work on x86. 

Besides that, as POC, I skip four functions in efistub: setup_graphics(),
efi_random_get_seed() and efi_enable_reset_attack_mitigation(),
efi_retrieve_eventlog(). Hence skipping the corresponding boot services.

Also, this series does not implement a memory allocator, which I plan to
implement with the help of bitmap.

About console, currently it hard code for arm64 virt machine, later it should
extract the information through ACPI table.

[1]: https://lore.kernel.org/linux-arm-kernel/ZBvKSis+dfnqa+Vz@piliu.users.ipa.redhat.com/T/#m42abb0ad3c10126b8b3bfae8a596deb707d6f76e
[2]: https://lore.kernel.org/lkml/20230918173607.421d2616@rotkaeppchen/T/
[3]: https://lore.kernel.org/lkml/20230918173607.421d2616@rotkaeppchen/T/#mc60aa591cb7616ceb39e1c98f352383f9ba6e985


Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Jan Hendrik Farr <kernel@jfarr.cc>
Cc: Philipp Rudo <prudo@redhat.com>
Cc: Lennart Poettering <mzxreary@0pointer.de>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
To: linux-arm-kernel@lists.infradead.org
To: kexec@lists.infradead.org
To: linux-efi@vger.kernel.org

Pingfan Liu (7):
  efi/libstub: Ask efi_random_alloc() to skip unusable memory
  debug/libstub: cheats to step around some boot service
  efi/emulator: Initial rountines to emulate EFI boot time service
  efi/emulator: Turn on mmu for arm64
  arm64: mm: Change to prototype of
  arm64: kexec: Prepare page table for emulator
  kexec: Introduce kexec_pe_image to parse and load PE file

 arch/arm64/include/asm/kexec.h                |   3 +
 arch/arm64/include/asm/mmu.h                  |   6 +
 arch/arm64/kernel/Makefile                    |   2 +-
 arch/arm64/kernel/kexec_image.c               |   1 +
 arch/arm64/kernel/kexec_pe_image.c            | 519 ++++++++++++++++++
 arch/arm64/kernel/machine_kexec.c             |  90 ++-
 arch/arm64/kernel/machine_kexec_file.c        |   1 +
 arch/arm64/mm/mmu.c                           |  67 ++-
 drivers/firmware/efi/Makefile                 |   1 +
 drivers/firmware/efi/efi_emulator/Makefile    |  98 ++++
 .../firmware/efi/efi_emulator/amba-pl011.c    |  80 +++
 .../efi_emulator/arm64_emulator_service.lds   |  45 ++
 .../firmware/efi/efi_emulator/arm64_proc.S    | 172 ++++++
 .../firmware/efi/efi_emulator/config_table.c  |  23 +
 drivers/firmware/efi/efi_emulator/core.c      | 211 +++++++
 drivers/firmware/efi/efi_emulator/earlycon.h  |  19 +
 .../firmware/efi/efi_emulator/efi_emulator.S  |  12 +
 drivers/firmware/efi/efi_emulator/emulator.h  |  66 +++
 drivers/firmware/efi/efi_emulator/entry.c     |  64 +++
 drivers/firmware/efi/efi_emulator/head.S      |  10 +
 drivers/firmware/efi/efi_emulator/initrd.c    |  15 +
 drivers/firmware/efi/efi_emulator/lib.c       |  73 +++
 drivers/firmware/efi/efi_emulator/memory.c    |  27 +
 .../firmware/efi/efi_emulator/memory_api.c    |  73 +++
 drivers/firmware/efi/efi_emulator/misc.c      |  76 +++
 drivers/firmware/efi/efi_emulator/pe_loader.c | 124 +++++
 drivers/firmware/efi/efi_emulator/printf.c    | 389 +++++++++++++
 .../efi/efi_emulator/runtime_service.c        |  28 +
 .../firmware/efi/libstub/efi-stub-helper.c    |   3 +
 drivers/firmware/efi/libstub/efi-stub.c       |   2 +
 drivers/firmware/efi/libstub/random.c         |   2 +
 drivers/firmware/efi/libstub/randomalloc.c    |   5 +
 drivers/firmware/efi/libstub/tpm.c            |   4 +
 include/linux/efi_emulator.h                  |  46 ++
 include/linux/kexec.h                         |   5 +
 35 files changed, 2327 insertions(+), 35 deletions(-)
 create mode 100644 arch/arm64/kernel/kexec_pe_image.c
 create mode 100644 drivers/firmware/efi/efi_emulator/Makefile
 create mode 100644 drivers/firmware/efi/efi_emulator/amba-pl011.c
 create mode 100644 drivers/firmware/efi/efi_emulator/arm64_emulator_service.lds
 create mode 100644 drivers/firmware/efi/efi_emulator/arm64_proc.S
 create mode 100644 drivers/firmware/efi/efi_emulator/config_table.c
 create mode 100644 drivers/firmware/efi/efi_emulator/core.c
 create mode 100644 drivers/firmware/efi/efi_emulator/earlycon.h
 create mode 100644 drivers/firmware/efi/efi_emulator/efi_emulator.S
 create mode 100644 drivers/firmware/efi/efi_emulator/emulator.h
 create mode 100644 drivers/firmware/efi/efi_emulator/entry.c
 create mode 100644 drivers/firmware/efi/efi_emulator/head.S
 create mode 100644 drivers/firmware/efi/efi_emulator/initrd.c
 create mode 100644 drivers/firmware/efi/efi_emulator/lib.c
 create mode 100644 drivers/firmware/efi/efi_emulator/memory.c
 create mode 100644 drivers/firmware/efi/efi_emulator/memory_api.c
 create mode 100644 drivers/firmware/efi/efi_emulator/misc.c
 create mode 100644 drivers/firmware/efi/efi_emulator/pe_loader.c
 create mode 100644 drivers/firmware/efi/efi_emulator/printf.c
 create mode 100644 drivers/firmware/efi/efi_emulator/runtime_service.c
 create mode 100644 include/linux/efi_emulator.h