mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10.git
synced 2026-09-09 00:07:04 +08:00
Merge: efi: Backport EFI support up through linux v6.17
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1845 JIRA: https://issues.redhat.com/browse/RHEL-129401 This mostly involves commits in drivers/firmware/efi/, arch/x86/platform/efi/,\ arch/x86/boot/compressed/, and commits to the source files include/linux/efi.h,\ and arch/x86/kernel/head64.c. No additional arm64-specific EFI commits were necessary. Omitted fix: 5a821e2d69e2 ("powerpc/boot: Fix build with gcc 15") - This is an independent fix that is entirely unrelated to EFI. Flagged for a "Fixes Warning" because it cites ee2ab467bddf ("x86/boot: Use '-std=gnu11' to fix build with GCC 15") which is included in this patch set. Tested: - Boot tested on EFI-based x86_64 and arm64 bare metal systems - Boot tested on x86_64 legacy BIOS VM guest - Boot tested SEV guest on AMD x86_64 with test kernel in both host and guest Signed-off-by: Lenny Szubowicz <lszubowi@redhat.com> Approved-by: Vitaly Kuznetsov <vkuznets@redhat.com> Approved-by: Vladis Dronov <vdronov@redhat.com> Approved-by: David Arcari <darcari@redhat.com> Approved-by: Mark Langsdorf <mlangsdo@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
@@ -1029,16 +1029,6 @@ Offset/size: 0x000c/4
|
||||
This field contains maximal allowed type for setup_data and setup_indirect structs.
|
||||
|
||||
|
||||
The Image Checksum
|
||||
==================
|
||||
|
||||
From boot protocol version 2.08 onwards the CRC-32 is calculated over
|
||||
the entire file using the characteristic polynomial 0x04C11DB7 and an
|
||||
initial remainder of 0xffffffff. The checksum is appended to the
|
||||
file; therefore the CRC of the file up to the limit specified in the
|
||||
syssize field of the header is always 0.
|
||||
|
||||
|
||||
The Kernel Command Line
|
||||
=======================
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
@ is accepted as an EFI binary. Booting via the UEFI stub
|
||||
@ will not execute those instructions, but the ARM/Linux
|
||||
@ boot protocol does, so we need some NOPs here.
|
||||
.inst MZ_MAGIC | (0xe225 << 16) @ eor r5, r5, 0x4d000
|
||||
.inst IMAGE_DOS_SIGNATURE | (0xe225 << 16) @ eor r5, r5, 0x4d000
|
||||
eor r5, r5, 0x4d000 @ undo previous insn
|
||||
#else
|
||||
__nop
|
||||
@@ -43,7 +43,7 @@
|
||||
.long pe_header - start @ Offset to the PE header.
|
||||
|
||||
pe_header:
|
||||
.long PE_MAGIC
|
||||
.long IMAGE_NT_SIGNATURE
|
||||
|
||||
coff_header:
|
||||
.short IMAGE_FILE_MACHINE_THUMB @ Machine
|
||||
@@ -60,7 +60,7 @@ coff_header:
|
||||
#define __pecoff_code_size (__pecoff_data_start - __efi_start)
|
||||
|
||||
optional_header:
|
||||
.short PE_OPT_MAGIC_PE32 @ PE32 format
|
||||
.short IMAGE_NT_OPTIONAL_HDR32_MAGIC @ PE32 format
|
||||
.byte 0x02 @ MajorLinkerVersion
|
||||
.byte 0x14 @ MinorLinkerVersion
|
||||
.long __pecoff_code_size @ SizeOfCode
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
.macro __EFI_PE_HEADER
|
||||
#ifdef CONFIG_EFI
|
||||
.set .Lpe_header_offset, . - .L_head
|
||||
.long PE_MAGIC
|
||||
.long IMAGE_NT_SIGNATURE
|
||||
.short IMAGE_FILE_MACHINE_ARM64 // Machine
|
||||
.short .Lsection_count // NumberOfSections
|
||||
.long 0 // TimeDateStamp
|
||||
@@ -40,7 +40,7 @@
|
||||
IMAGE_FILE_LINE_NUMS_STRIPPED // Characteristics
|
||||
|
||||
.Loptional_header:
|
||||
.short PE_OPT_MAGIC_PE32PLUS // PE32+ format
|
||||
.short IMAGE_NT_OPTIONAL_HDR64_MAGIC // PE32+ format
|
||||
.byte 0x02 // MajorLinkerVersion
|
||||
.byte 0x14 // MinorLinkerVersion
|
||||
.long __initdata_begin - .Lefi_header_end // SizeOfCode
|
||||
@@ -66,7 +66,7 @@
|
||||
.long .Lefi_header_end - .L_head // SizeOfHeaders
|
||||
.long 0 // CheckSum
|
||||
.short IMAGE_SUBSYSTEM_EFI_APPLICATION // Subsystem
|
||||
.short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT // DllCharacteristics
|
||||
.short IMAGE_DLLCHARACTERISTICS_NX_COMPAT // DllCharacteristics
|
||||
.quad 0 // SizeOfStackReserve
|
||||
.quad 0 // SizeOfStackCommit
|
||||
.quad 0 // SizeOfHeapReserve
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <asm/set_memory.h>
|
||||
|
||||
.macro __EFI_PE_HEADER
|
||||
.long PE_MAGIC
|
||||
.long IMAGE_NT_SIGNATURE
|
||||
coff_header:
|
||||
#ifdef CONFIG_64BIT
|
||||
.short IMAGE_FILE_MACHINE_RISCV64 // Machine
|
||||
@@ -27,9 +27,9 @@ coff_header:
|
||||
|
||||
optional_header:
|
||||
#ifdef CONFIG_64BIT
|
||||
.short PE_OPT_MAGIC_PE32PLUS // PE32+ format
|
||||
.short IMAGE_NT_OPTIONAL_HDR64_MAGIC // PE32+ format
|
||||
#else
|
||||
.short PE_OPT_MAGIC_PE32 // PE32 format
|
||||
.short IMAGE_NT_OPTIONAL_HDR32_MAGIC // PE32 format
|
||||
#endif
|
||||
.byte 0x02 // MajorLinkerVersion
|
||||
.byte 0x14 // MinorLinkerVersion
|
||||
@@ -64,7 +64,7 @@ extra_header_fields:
|
||||
.long efi_header_end - _start // SizeOfHeaders
|
||||
.long 0 // CheckSum
|
||||
.short IMAGE_SUBSYSTEM_EFI_APPLICATION // Subsystem
|
||||
.short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT // DllCharacteristics
|
||||
.short IMAGE_DLLCHARACTERISTICS_NX_COMPAT // DllCharacteristics
|
||||
.quad 0 // SizeOfStackReserve
|
||||
.quad 0 // SizeOfStackCommit
|
||||
.quad 0 // SizeOfHeapReserve
|
||||
|
||||
@@ -279,6 +279,7 @@ archheaders:
|
||||
###
|
||||
# Kernel objects
|
||||
|
||||
core-y += arch/x86/boot/startup/
|
||||
libs-y += arch/x86/lib/
|
||||
|
||||
# drivers-y are linked after core-y
|
||||
|
||||
@@ -12,3 +12,4 @@ fdimage
|
||||
mtools.conf
|
||||
image.iso
|
||||
hdimage
|
||||
tools/
|
||||
|
||||
@@ -35,7 +35,6 @@ setup-y += video-vesa.o
|
||||
setup-y += video-bios.o
|
||||
|
||||
targets += $(setup-y)
|
||||
hostprogs := tools/build
|
||||
hostprogs += mkcpustr
|
||||
|
||||
HOST_EXTRACFLAGS += -I$(srctree)/tools/include \
|
||||
@@ -61,11 +60,9 @@ KBUILD_CFLAGS += $(CONFIG_CC_IMPLICIT_FALLTHROUGH)
|
||||
$(obj)/bzImage: asflags-y := $(SVGA_MODE)
|
||||
|
||||
quiet_cmd_image = BUILD $@
|
||||
silent_redirect_image = >/dev/null
|
||||
cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin \
|
||||
$(obj)/zoffset.h $@ $($(quiet)redirect_image)
|
||||
cmd_image = (dd if=$< bs=4k conv=sync status=none; cat $(filter-out $<,$(real-prereqs))) >$@
|
||||
|
||||
$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
|
||||
$(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin FORCE
|
||||
$(call if_changed,image)
|
||||
@$(kecho) 'Kernel: $@ is ready' ' (#'$(or $(KBUILD_BUILD_VERSION),`cat .version`)')'
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
|
||||
# avoid errors with '-march=i386', and future flags may depend on the target to
|
||||
# be valid.
|
||||
KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS)
|
||||
KBUILD_CFLAGS += -std=gnu11
|
||||
KBUILD_CFLAGS += -fno-strict-aliasing -fPIE
|
||||
KBUILD_CFLAGS += -Wundef
|
||||
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
|
||||
@@ -104,8 +105,8 @@ vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o $(obj)/td
|
||||
vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
|
||||
|
||||
vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
|
||||
vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
|
||||
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
|
||||
vmlinux-libs-$(CONFIG_X86_64) += $(objtree)/arch/x86/boot/startup/lib.a
|
||||
vmlinux-objs-$(CONFIG_EFI_SBAT) += $(obj)/sbat.o
|
||||
|
||||
ifdef CONFIG_EFI_SBAT
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
|
||||
*
|
||||
* Early support for invoking 32-bit EFI services from a 64-bit kernel.
|
||||
*
|
||||
* Because this thunking occurs before ExitBootServices() we have to
|
||||
* restore the firmware's 32-bit GDT and IDT before we make EFI service
|
||||
* calls.
|
||||
*
|
||||
* On the plus side, we don't have to worry about mangling 64-bit
|
||||
* addresses into 32-bits because we're executing with an identity
|
||||
* mapped pagetable and haven't transitioned to 64-bit virtual addresses
|
||||
* yet.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/page_types.h>
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
.code64
|
||||
.text
|
||||
/*
|
||||
* When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode()
|
||||
* is the first thing that runs after switching to long mode. Depending on
|
||||
* whether the EFI handover protocol or the compat entry point was used to
|
||||
* enter the kernel, it will either branch to the common 64-bit EFI stub
|
||||
* entrypoint efi_stub_entry() directly, or via the 64-bit EFI PE/COFF
|
||||
* entrypoint efi_pe_entry(). In the former case, the bootloader must provide a
|
||||
* struct bootparams pointer as the third argument, so the presence of such a
|
||||
* pointer is used to disambiguate.
|
||||
*
|
||||
* +--------------+
|
||||
* +------------------+ +------------+ +------>| efi_pe_entry |
|
||||
* | efi32_pe_entry |---->| | | +-----------+--+
|
||||
* +------------------+ | | +------+----------------+ |
|
||||
* | startup_32 |---->| startup_64_mixed_mode | |
|
||||
* +------------------+ | | +------+----------------+ |
|
||||
* | efi32_stub_entry |---->| | | |
|
||||
* +------------------+ +------------+ | |
|
||||
* V |
|
||||
* +------------+ +----------------+ |
|
||||
* | startup_64 |<----| efi_stub_entry |<--------+
|
||||
* +------------+ +----------------+
|
||||
*/
|
||||
SYM_FUNC_START(startup_64_mixed_mode)
|
||||
lea efi32_boot_args(%rip), %rdx
|
||||
mov 0(%rdx), %edi
|
||||
mov 4(%rdx), %esi
|
||||
|
||||
/* Switch to the firmware's stack */
|
||||
movl efi32_boot_sp(%rip), %esp
|
||||
andl $~7, %esp
|
||||
|
||||
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
|
||||
mov 8(%rdx), %edx // saved bootparams pointer
|
||||
test %edx, %edx
|
||||
jnz efi_stub_entry
|
||||
#endif
|
||||
/*
|
||||
* efi_pe_entry uses MS calling convention, which requires 32 bytes of
|
||||
* shadow space on the stack even if all arguments are passed in
|
||||
* registers. We also need an additional 8 bytes for the space that
|
||||
* would be occupied by the return address, and this also results in
|
||||
* the correct stack alignment for entry.
|
||||
*/
|
||||
sub $40, %rsp
|
||||
mov %rdi, %rcx // MS calling convention
|
||||
mov %rsi, %rdx
|
||||
jmp efi_pe_entry
|
||||
SYM_FUNC_END(startup_64_mixed_mode)
|
||||
|
||||
SYM_FUNC_START(__efi64_thunk)
|
||||
push %rbp
|
||||
push %rbx
|
||||
|
||||
movl %ds, %eax
|
||||
push %rax
|
||||
movl %es, %eax
|
||||
push %rax
|
||||
movl %ss, %eax
|
||||
push %rax
|
||||
|
||||
/* Copy args passed on stack */
|
||||
movq 0x30(%rsp), %rbp
|
||||
movq 0x38(%rsp), %rbx
|
||||
movq 0x40(%rsp), %rax
|
||||
|
||||
/*
|
||||
* Convert x86-64 ABI params to i386 ABI
|
||||
*/
|
||||
subq $64, %rsp
|
||||
movl %esi, 0x0(%rsp)
|
||||
movl %edx, 0x4(%rsp)
|
||||
movl %ecx, 0x8(%rsp)
|
||||
movl %r8d, 0xc(%rsp)
|
||||
movl %r9d, 0x10(%rsp)
|
||||
movl %ebp, 0x14(%rsp)
|
||||
movl %ebx, 0x18(%rsp)
|
||||
movl %eax, 0x1c(%rsp)
|
||||
|
||||
leaq 0x20(%rsp), %rbx
|
||||
sgdt (%rbx)
|
||||
sidt 16(%rbx)
|
||||
|
||||
leaq 1f(%rip), %rbp
|
||||
|
||||
/*
|
||||
* Switch to IDT and GDT with 32-bit segments. These are the firmware
|
||||
* GDT and IDT that were installed when the kernel started executing.
|
||||
* The pointers were saved by the efi32_entry() routine below.
|
||||
*
|
||||
* Pass the saved DS selector to the 32-bit code, and use far return to
|
||||
* restore the saved CS selector.
|
||||
*/
|
||||
lidt efi32_boot_idt(%rip)
|
||||
lgdt efi32_boot_gdt(%rip)
|
||||
|
||||
movzwl efi32_boot_ds(%rip), %edx
|
||||
movzwq efi32_boot_cs(%rip), %rax
|
||||
pushq %rax
|
||||
leaq efi_enter32(%rip), %rax
|
||||
pushq %rax
|
||||
lretq
|
||||
|
||||
1: addq $64, %rsp
|
||||
movq %rdi, %rax
|
||||
|
||||
pop %rbx
|
||||
movl %ebx, %ss
|
||||
pop %rbx
|
||||
movl %ebx, %es
|
||||
pop %rbx
|
||||
movl %ebx, %ds
|
||||
/* Clear out 32-bit selector from FS and GS */
|
||||
xorl %ebx, %ebx
|
||||
movl %ebx, %fs
|
||||
movl %ebx, %gs
|
||||
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
RET
|
||||
SYM_FUNC_END(__efi64_thunk)
|
||||
|
||||
.code32
|
||||
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
|
||||
SYM_FUNC_START(efi32_stub_entry)
|
||||
call 1f
|
||||
1: popl %ecx
|
||||
leal (efi32_boot_args - 1b)(%ecx), %ebx
|
||||
|
||||
/* Clear BSS */
|
||||
xorl %eax, %eax
|
||||
leal (_bss - 1b)(%ecx), %edi
|
||||
leal (_ebss - 1b)(%ecx), %ecx
|
||||
subl %edi, %ecx
|
||||
shrl $2, %ecx
|
||||
cld
|
||||
rep stosl
|
||||
|
||||
add $0x4, %esp /* Discard return address */
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
movl %esi, 8(%ebx)
|
||||
jmp efi32_entry
|
||||
SYM_FUNC_END(efi32_stub_entry)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* EFI service pointer must be in %edi.
|
||||
*
|
||||
* The stack should represent the 32-bit calling convention.
|
||||
*/
|
||||
SYM_FUNC_START_LOCAL(efi_enter32)
|
||||
/* Load firmware selector into data and stack segment registers */
|
||||
movl %edx, %ds
|
||||
movl %edx, %es
|
||||
movl %edx, %fs
|
||||
movl %edx, %gs
|
||||
movl %edx, %ss
|
||||
|
||||
/* Reload pgtables */
|
||||
movl %cr3, %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Disable long mode via EFER */
|
||||
movl $MSR_EFER, %ecx
|
||||
rdmsr
|
||||
btrl $_EFER_LME, %eax
|
||||
wrmsr
|
||||
|
||||
call *%edi
|
||||
|
||||
/* We must preserve return value */
|
||||
movl %eax, %edi
|
||||
|
||||
/*
|
||||
* Some firmware will return with interrupts enabled. Be sure to
|
||||
* disable them before we switch GDTs and IDTs.
|
||||
*/
|
||||
cli
|
||||
|
||||
lidtl 16(%ebx)
|
||||
lgdtl (%ebx)
|
||||
|
||||
movl %cr4, %eax
|
||||
btsl $(X86_CR4_PAE_BIT), %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
movl %cr3, %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
movl $MSR_EFER, %ecx
|
||||
rdmsr
|
||||
btsl $_EFER_LME, %eax
|
||||
wrmsr
|
||||
|
||||
xorl %eax, %eax
|
||||
lldt %ax
|
||||
|
||||
pushl $__KERNEL_CS
|
||||
pushl %ebp
|
||||
|
||||
/* Enable paging */
|
||||
movl %cr0, %eax
|
||||
btsl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
lret
|
||||
SYM_FUNC_END(efi_enter32)
|
||||
|
||||
/*
|
||||
* This is the common EFI stub entry point for mixed mode.
|
||||
*
|
||||
* Arguments: %ecx image handle
|
||||
* %edx EFI system table pointer
|
||||
*
|
||||
* Since this is the point of no return for ordinary execution, no registers
|
||||
* are considered live except for the function parameters. [Note that the EFI
|
||||
* stub may still exit and return to the firmware using the Exit() EFI boot
|
||||
* service.]
|
||||
*/
|
||||
SYM_FUNC_START_LOCAL(efi32_entry)
|
||||
call 1f
|
||||
1: pop %ebx
|
||||
|
||||
/* Save firmware GDTR and code/data selectors */
|
||||
sgdtl (efi32_boot_gdt - 1b)(%ebx)
|
||||
movw %cs, (efi32_boot_cs - 1b)(%ebx)
|
||||
movw %ds, (efi32_boot_ds - 1b)(%ebx)
|
||||
|
||||
/* Store firmware IDT descriptor */
|
||||
sidtl (efi32_boot_idt - 1b)(%ebx)
|
||||
|
||||
/* Store firmware stack pointer */
|
||||
movl %esp, (efi32_boot_sp - 1b)(%ebx)
|
||||
|
||||
/* Store boot arguments */
|
||||
leal (efi32_boot_args - 1b)(%ebx), %ebx
|
||||
movl %ecx, 0(%ebx)
|
||||
movl %edx, 4(%ebx)
|
||||
movb $0x0, 12(%ebx) // efi_is64
|
||||
|
||||
/*
|
||||
* Allocate some memory for a temporary struct boot_params, which only
|
||||
* needs the minimal pieces that startup_32() relies on.
|
||||
*/
|
||||
subl $PARAM_SIZE, %esp
|
||||
movl %esp, %esi
|
||||
movl $PAGE_SIZE, BP_kernel_alignment(%esi)
|
||||
movl $_end - 1b, BP_init_size(%esi)
|
||||
subl $startup_32 - 1b, BP_init_size(%esi)
|
||||
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
jmp startup_32
|
||||
SYM_FUNC_END(efi32_entry)
|
||||
|
||||
/*
|
||||
* efi_status_t efi32_pe_entry(efi_handle_t image_handle,
|
||||
* efi_system_table_32_t *sys_table)
|
||||
*/
|
||||
SYM_FUNC_START(efi32_pe_entry)
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %ebx // save callee-save registers
|
||||
pushl %edi
|
||||
|
||||
call verify_cpu // check for long mode support
|
||||
testl %eax, %eax
|
||||
movl $0x80000003, %eax // EFI_UNSUPPORTED
|
||||
jnz 2f
|
||||
|
||||
movl 8(%ebp), %ecx // image_handle
|
||||
movl 12(%ebp), %edx // sys_table
|
||||
jmp efi32_entry // pass %ecx, %edx
|
||||
// no other registers remain live
|
||||
|
||||
2: popl %edi // restore callee-save registers
|
||||
popl %ebx
|
||||
leave
|
||||
RET
|
||||
SYM_FUNC_END(efi32_pe_entry)
|
||||
|
||||
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
|
||||
.org efi32_stub_entry + 0x200
|
||||
.code64
|
||||
SYM_FUNC_START_NOALIGN(efi64_stub_entry)
|
||||
jmp efi_handover_entry
|
||||
SYM_FUNC_END(efi64_stub_entry)
|
||||
#endif
|
||||
|
||||
.data
|
||||
.balign 8
|
||||
SYM_DATA_START_LOCAL(efi32_boot_gdt)
|
||||
.word 0
|
||||
.quad 0
|
||||
SYM_DATA_END(efi32_boot_gdt)
|
||||
|
||||
SYM_DATA_START_LOCAL(efi32_boot_idt)
|
||||
.word 0
|
||||
.quad 0
|
||||
SYM_DATA_END(efi32_boot_idt)
|
||||
|
||||
SYM_DATA_LOCAL(efi32_boot_cs, .word 0)
|
||||
SYM_DATA_LOCAL(efi32_boot_ds, .word 0)
|
||||
SYM_DATA_LOCAL(efi32_boot_sp, .long 0)
|
||||
SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
|
||||
SYM_DATA(efi_is64, .byte 1)
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/desc_defs.h>
|
||||
#include <asm/trapnr.h>
|
||||
#include "pgtable.h"
|
||||
|
||||
/*
|
||||
* Fix alignment at 16 bytes. Following CONFIG_FUNCTION_ALIGNMENT will result
|
||||
@@ -263,13 +262,6 @@ SYM_FUNC_START(startup_32)
|
||||
* used to perform that far jump.
|
||||
*/
|
||||
leal rva(startup_64)(%ebp), %eax
|
||||
#ifdef CONFIG_EFI_MIXED
|
||||
cmpb $1, rva(efi_is64)(%ebp)
|
||||
je 1f
|
||||
leal rva(startup_64_mixed_mode)(%ebp), %eax
|
||||
1:
|
||||
#endif
|
||||
|
||||
pushl $__KERNEL_CS
|
||||
pushl %eax
|
||||
|
||||
@@ -483,110 +475,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
|
||||
jmp *%rax
|
||||
SYM_FUNC_END(.Lrelocated)
|
||||
|
||||
/*
|
||||
* This is the 32-bit trampoline that will be copied over to low memory. It
|
||||
* will be called using the ordinary 64-bit calling convention from code
|
||||
* running in 64-bit mode.
|
||||
*
|
||||
* Return address is at the top of the stack (might be above 4G).
|
||||
* The first argument (EDI) contains the address of the temporary PGD level
|
||||
* page table in 32-bit addressable memory which will be programmed into
|
||||
* register CR3.
|
||||
*/
|
||||
.section ".rodata", "a", @progbits
|
||||
SYM_CODE_START(trampoline_32bit_src)
|
||||
/*
|
||||
* Preserve callee save 64-bit registers on the stack: this is
|
||||
* necessary because the architecture does not guarantee that GPRs will
|
||||
* retain their full 64-bit values across a 32-bit mode switch.
|
||||
*/
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
|
||||
/* Preserve top half of RSP in a legacy mode GPR to avoid truncation */
|
||||
movq %rsp, %rbx
|
||||
shrq $32, %rbx
|
||||
|
||||
/* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
|
||||
pushq $__KERNEL32_CS
|
||||
leaq 0f(%rip), %rax
|
||||
pushq %rax
|
||||
lretq
|
||||
|
||||
/*
|
||||
* The 32-bit code below will do a far jump back to long mode and end
|
||||
* up here after reconfiguring the number of paging levels. First, the
|
||||
* stack pointer needs to be restored to its full 64-bit value before
|
||||
* the callee save register contents can be popped from the stack.
|
||||
*/
|
||||
.Lret:
|
||||
shlq $32, %rbx
|
||||
orq %rbx, %rsp
|
||||
|
||||
/* Restore the preserved 64-bit registers */
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
retq
|
||||
|
||||
.code32
|
||||
0:
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Point CR3 to the trampoline's new top level page table */
|
||||
movl %edi, %cr3
|
||||
|
||||
/* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
|
||||
movl $MSR_EFER, %ecx
|
||||
rdmsr
|
||||
btsl $_EFER_LME, %eax
|
||||
/* Avoid writing EFER if no change was made (for TDX guest) */
|
||||
jc 1f
|
||||
wrmsr
|
||||
1:
|
||||
/* Toggle CR4.LA57 */
|
||||
movl %cr4, %eax
|
||||
btcl $X86_CR4_LA57_BIT, %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
/* Enable paging again. */
|
||||
movl %cr0, %eax
|
||||
btsl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/*
|
||||
* Return to the 64-bit calling code using LJMP rather than LRET, to
|
||||
* avoid the need for a 32-bit addressable stack. The destination
|
||||
* address will be adjusted after the template code is copied into a
|
||||
* 32-bit addressable buffer.
|
||||
*/
|
||||
.Ljmp: ljmpl $__KERNEL_CS, $(.Lret - trampoline_32bit_src)
|
||||
SYM_CODE_END(trampoline_32bit_src)
|
||||
|
||||
/*
|
||||
* This symbol is placed right after trampoline_32bit_src() so its address can
|
||||
* be used to infer the size of the trampoline code.
|
||||
*/
|
||||
SYM_DATA(trampoline_ljmp_imm_offset, .word .Ljmp + 1 - trampoline_32bit_src)
|
||||
|
||||
/*
|
||||
* The trampoline code has a size limit.
|
||||
* Make sure we fail to compile if the trampoline code grows
|
||||
* beyond TRAMPOLINE_32BIT_CODE_SIZE bytes.
|
||||
*/
|
||||
.org trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE
|
||||
|
||||
.text
|
||||
SYM_FUNC_START_LOCAL_NOALIGN(.Lno_longmode)
|
||||
/* This isn't an x86-64 CPU, so hang intentionally, we cannot continue */
|
||||
1:
|
||||
|
||||
@@ -38,7 +38,7 @@ void arch_accept_memory(phys_addr_t start, phys_addr_t end)
|
||||
if (early_is_tdx_guest()) {
|
||||
if (!tdx_accept_memory(start, end))
|
||||
panic("TDX: Failed to accept memory\n");
|
||||
} else if (sev_snp_enabled()) {
|
||||
} else if (early_is_sevsnp_guest()) {
|
||||
snp_accept_memory(start, end);
|
||||
} else {
|
||||
error("Cannot accept memory: unknown platform\n");
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "misc.h"
|
||||
#include "error.h"
|
||||
#include "pgtable.h"
|
||||
#include "../string.h"
|
||||
#include "../voffset.h"
|
||||
#include <asm/bootparam_utils.h>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#ifndef BOOT_COMPRESSED_PAGETABLE_H
|
||||
#define BOOT_COMPRESSED_PAGETABLE_H
|
||||
|
||||
#define TRAMPOLINE_32BIT_SIZE (2 * PAGE_SIZE)
|
||||
|
||||
#define TRAMPOLINE_32BIT_CODE_OFFSET PAGE_SIZE
|
||||
#define TRAMPOLINE_32BIT_CODE_SIZE 0xA0
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
extern unsigned long *trampoline_32bit;
|
||||
|
||||
extern void trampoline_32bit_src(void *trampoline, bool enable_5lvl);
|
||||
|
||||
extern const u16 trampoline_ljmp_imm_offset;
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* BOOT_COMPRESSED_PAGETABLE_H */
|
||||
@@ -1,9 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "misc.h"
|
||||
#include <asm/bootparam.h>
|
||||
#include <asm/bootparam_utils.h>
|
||||
#include <asm/e820/types.h>
|
||||
#include <asm/processor.h>
|
||||
#include "pgtable.h"
|
||||
#include "../string.h"
|
||||
#include "efi.h"
|
||||
|
||||
@@ -107,6 +107,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable)
|
||||
bool l5_required = false;
|
||||
|
||||
/* Initialize boot_params. Required for cmdline_find_option_bool(). */
|
||||
sanitize_boot_params(bp);
|
||||
boot_params_ptr = bp;
|
||||
|
||||
/*
|
||||
|
||||
@@ -164,10 +164,7 @@ bool sev_snp_enabled(void)
|
||||
|
||||
static void __page_state_change(unsigned long paddr, enum psc_op op)
|
||||
{
|
||||
u64 val;
|
||||
|
||||
if (!sev_snp_enabled())
|
||||
return;
|
||||
u64 val, msr;
|
||||
|
||||
/*
|
||||
* If private -> shared then invalidate the page before requesting the
|
||||
@@ -176,6 +173,9 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
|
||||
if (op == SNP_PAGE_STATE_SHARED)
|
||||
pvalidate_4k_page(paddr, paddr, false);
|
||||
|
||||
/* Save the current GHCB MSR value */
|
||||
msr = sev_es_rd_ghcb_msr();
|
||||
|
||||
/* Issue VMGEXIT to change the page state in RMP table. */
|
||||
sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op));
|
||||
VMGEXIT();
|
||||
@@ -185,6 +185,9 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
|
||||
if ((GHCB_RESP_CODE(val) != GHCB_MSR_PSC_RESP) || GHCB_MSR_PSC_RESP_VAL(val))
|
||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
|
||||
|
||||
/* Restore the GHCB MSR value */
|
||||
sev_es_wr_ghcb_msr(msr);
|
||||
|
||||
/*
|
||||
* Now that page state is changed in the RMP table, validate it so that it is
|
||||
* consistent with the RMP entry.
|
||||
@@ -195,11 +198,17 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
|
||||
|
||||
void snp_set_page_private(unsigned long paddr)
|
||||
{
|
||||
if (!sev_snp_enabled())
|
||||
return;
|
||||
|
||||
__page_state_change(paddr, SNP_PAGE_STATE_PRIVATE);
|
||||
}
|
||||
|
||||
void snp_set_page_shared(unsigned long paddr)
|
||||
{
|
||||
if (!sev_snp_enabled())
|
||||
return;
|
||||
|
||||
__page_state_change(paddr, SNP_PAGE_STATE_SHARED);
|
||||
}
|
||||
|
||||
@@ -223,56 +232,10 @@ static bool early_setup_ghcb(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static phys_addr_t __snp_accept_memory(struct snp_psc_desc *desc,
|
||||
phys_addr_t pa, phys_addr_t pa_end)
|
||||
{
|
||||
struct psc_hdr *hdr;
|
||||
struct psc_entry *e;
|
||||
unsigned int i;
|
||||
|
||||
hdr = &desc->hdr;
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
|
||||
e = desc->entries;
|
||||
|
||||
i = 0;
|
||||
while (pa < pa_end && i < VMGEXIT_PSC_MAX_ENTRY) {
|
||||
hdr->end_entry = i;
|
||||
|
||||
e->gfn = pa >> PAGE_SHIFT;
|
||||
e->operation = SNP_PAGE_STATE_PRIVATE;
|
||||
if (IS_ALIGNED(pa, PMD_SIZE) && (pa_end - pa) >= PMD_SIZE) {
|
||||
e->pagesize = RMP_PG_SIZE_2M;
|
||||
pa += PMD_SIZE;
|
||||
} else {
|
||||
e->pagesize = RMP_PG_SIZE_4K;
|
||||
pa += PAGE_SIZE;
|
||||
}
|
||||
|
||||
e++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (vmgexit_psc(boot_ghcb, desc))
|
||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
|
||||
|
||||
pvalidate_pages(desc);
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
void snp_accept_memory(phys_addr_t start, phys_addr_t end)
|
||||
{
|
||||
struct snp_psc_desc desc = {};
|
||||
unsigned int i;
|
||||
phys_addr_t pa;
|
||||
|
||||
if (!boot_ghcb && !early_setup_ghcb())
|
||||
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
|
||||
|
||||
pa = start;
|
||||
while (pa < end)
|
||||
pa = __snp_accept_memory(&desc, pa, end);
|
||||
for (phys_addr_t pa = start; pa < end; pa += PAGE_SIZE)
|
||||
__page_state_change(pa, SNP_PAGE_STATE_PRIVATE);
|
||||
}
|
||||
|
||||
void sev_es_shutdown_ghcb(void)
|
||||
@@ -681,3 +644,43 @@ void sev_prep_identity_maps(unsigned long top_level_pgt)
|
||||
|
||||
sev_verify_cbit(top_level_pgt);
|
||||
}
|
||||
|
||||
bool early_is_sevsnp_guest(void)
|
||||
{
|
||||
static bool sevsnp;
|
||||
|
||||
if (sevsnp)
|
||||
return true;
|
||||
|
||||
if (!(sev_get_status() & MSR_AMD64_SEV_SNP_ENABLED))
|
||||
return false;
|
||||
|
||||
sevsnp = true;
|
||||
|
||||
if (!snp_vmpl) {
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
/*
|
||||
* CPUID Fn8000_001F_EAX[28] - SVSM support
|
||||
*/
|
||||
eax = 0x8000001f;
|
||||
ecx = 0;
|
||||
native_cpuid(&eax, &ebx, &ecx, &edx);
|
||||
if (eax & BIT(28)) {
|
||||
struct msr m;
|
||||
|
||||
/* Obtain the address of the calling area to use */
|
||||
boot_rdmsr(MSR_SVSM_CAA, &m);
|
||||
boot_svsm_caa = (void *)m.q;
|
||||
boot_svsm_caa_pa = m.q;
|
||||
|
||||
/*
|
||||
* The real VMPL level cannot be discovered, but the
|
||||
* memory acceptance routines make no use of that so
|
||||
* any non-zero value suffices here.
|
||||
*/
|
||||
snp_vmpl = U8_MAX;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,15 @@
|
||||
|
||||
bool sev_snp_enabled(void);
|
||||
void snp_accept_memory(phys_addr_t start, phys_addr_t end);
|
||||
u64 sev_get_status(void);
|
||||
bool early_is_sevsnp_guest(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline bool sev_snp_enabled(void) { return false; }
|
||||
static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
|
||||
static inline u64 sev_get_status(void) { return 0; }
|
||||
static inline bool early_is_sevsnp_guest(void) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ SECTIONS
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
|
||||
/* Add 4 bytes of extra space for a CRC-32 checksum */
|
||||
/* Add 4 bytes of extra space for the obsolete CRC-32 checksum */
|
||||
. = ALIGN(. + 4, 0x200);
|
||||
_edata = . ;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ SYSSEG = 0x1000 /* historical load address >> 4 */
|
||||
.section ".bstext", "ax"
|
||||
#ifdef CONFIG_EFI_STUB
|
||||
# "MZ", MS-DOS header
|
||||
.word MZ_MAGIC
|
||||
.word IMAGE_DOS_SIGNATURE
|
||||
.org 0x38
|
||||
#
|
||||
# Offset to the PE header.
|
||||
@@ -51,16 +51,16 @@ SYSSEG = 0x1000 /* historical load address >> 4 */
|
||||
.long LINUX_PE_MAGIC
|
||||
.long pe_header
|
||||
pe_header:
|
||||
.long PE_MAGIC
|
||||
.long IMAGE_NT_SIGNATURE
|
||||
|
||||
coff_header:
|
||||
#ifdef CONFIG_X86_32
|
||||
.set image_file_add_flags, IMAGE_FILE_32BIT_MACHINE
|
||||
.set pe_opt_magic, PE_OPT_MAGIC_PE32
|
||||
.set pe_opt_magic, IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
||||
.word IMAGE_FILE_MACHINE_I386
|
||||
#else
|
||||
.set image_file_add_flags, 0
|
||||
.set pe_opt_magic, PE_OPT_MAGIC_PE32PLUS
|
||||
.set pe_opt_magic, IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
||||
.word IMAGE_FILE_MACHINE_AMD64
|
||||
#endif
|
||||
.word section_count # nr_sections
|
||||
@@ -111,7 +111,7 @@ extra_header_fields:
|
||||
.long salign # SizeOfHeaders
|
||||
.long 0 # CheckSum
|
||||
.word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application)
|
||||
.word IMAGE_DLL_CHARACTERISTICS_NX_COMPAT # DllCharacteristics
|
||||
.word IMAGE_DLLCHARACTERISTICS_NX_COMPAT # DllCharacteristics
|
||||
#ifdef CONFIG_X86_32
|
||||
.long 0 # SizeOfStackReserve
|
||||
.long 0 # SizeOfStackCommit
|
||||
|
||||
@@ -45,6 +45,8 @@ SECTIONS
|
||||
|
||||
setup_size = ALIGN(ABSOLUTE(.), 4096);
|
||||
setup_sects = ABSOLUTE(setup_size / 512);
|
||||
ASSERT(setup_sects >= 5, "The setup must be at least 5 sectors in size");
|
||||
ASSERT(setup_sects <= 64, "The setup must be at most 64 sectors in size");
|
||||
}
|
||||
|
||||
. = ALIGN(16);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
KBUILD_AFLAGS += -D__DISABLE_EXPORTS
|
||||
|
||||
lib-$(CONFIG_X86_64) += la57toggle.o
|
||||
lib-$(CONFIG_EFI_MIXED) += efi-mixed.o
|
||||
@@ -0,0 +1,253 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
|
||||
*
|
||||
* Early support for invoking 32-bit EFI services from a 64-bit kernel.
|
||||
*
|
||||
* Because this thunking occurs before ExitBootServices() we have to
|
||||
* restore the firmware's 32-bit GDT and IDT before we make EFI service
|
||||
* calls.
|
||||
*
|
||||
* On the plus side, we don't have to worry about mangling 64-bit
|
||||
* addresses into 32-bits because we're executing with an identity
|
||||
* mapped pagetable and haven't transitioned to 64-bit virtual addresses
|
||||
* yet.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/desc_defs.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/page_types.h>
|
||||
#include <asm/pgtable_types.h>
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
.text
|
||||
.code32
|
||||
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
|
||||
SYM_FUNC_START(efi32_stub_entry)
|
||||
call 1f
|
||||
1: popl %ecx
|
||||
|
||||
/* Clear BSS */
|
||||
xorl %eax, %eax
|
||||
leal (_bss - 1b)(%ecx), %edi
|
||||
leal (_ebss - 1b)(%ecx), %ecx
|
||||
subl %edi, %ecx
|
||||
shrl $2, %ecx
|
||||
cld
|
||||
rep stosl
|
||||
|
||||
add $0x4, %esp /* Discard return address */
|
||||
movl 8(%esp), %ebx /* struct boot_params pointer */
|
||||
jmp efi32_startup
|
||||
SYM_FUNC_END(efi32_stub_entry)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called using a far call from __efi64_thunk() below, using the x86_64 SysV
|
||||
* ABI (except for R8/R9 which are inaccessible to 32-bit code - EAX/EBX are
|
||||
* used instead). EBP+16 points to the arguments passed via the stack.
|
||||
*
|
||||
* The first argument (EDI) is a pointer to the boot service or protocol, to
|
||||
* which the remaining arguments are passed, each truncated to 32 bits.
|
||||
*/
|
||||
SYM_FUNC_START_LOCAL(efi_enter32)
|
||||
/*
|
||||
* Convert x86-64 SysV ABI params to i386 ABI
|
||||
*/
|
||||
pushl 32(%ebp) /* Up to 3 args passed via the stack */
|
||||
pushl 24(%ebp)
|
||||
pushl 16(%ebp)
|
||||
pushl %ebx /* R9 */
|
||||
pushl %eax /* R8 */
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %esi
|
||||
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Disable long mode via EFER */
|
||||
movl $MSR_EFER, %ecx
|
||||
rdmsr
|
||||
btrl $_EFER_LME, %eax
|
||||
wrmsr
|
||||
|
||||
call *%edi
|
||||
|
||||
/* We must preserve return value */
|
||||
movl %eax, %edi
|
||||
|
||||
call efi32_enable_long_mode
|
||||
|
||||
addl $32, %esp
|
||||
movl %edi, %eax
|
||||
lret
|
||||
SYM_FUNC_END(efi_enter32)
|
||||
|
||||
.code64
|
||||
SYM_FUNC_START(__efi64_thunk)
|
||||
push %rbp
|
||||
movl %esp, %ebp
|
||||
push %rbx
|
||||
|
||||
/* Move args #5 and #6 into 32-bit accessible registers */
|
||||
movl %r8d, %eax
|
||||
movl %r9d, %ebx
|
||||
|
||||
lcalll *efi32_call(%rip)
|
||||
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
RET
|
||||
SYM_FUNC_END(__efi64_thunk)
|
||||
|
||||
.code32
|
||||
SYM_FUNC_START_LOCAL(efi32_enable_long_mode)
|
||||
movl %cr4, %eax
|
||||
btsl $(X86_CR4_PAE_BIT), %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
movl $MSR_EFER, %ecx
|
||||
rdmsr
|
||||
btsl $_EFER_LME, %eax
|
||||
wrmsr
|
||||
|
||||
/* Disable interrupts - the firmware's IDT does not work in long mode */
|
||||
cli
|
||||
|
||||
/* Enable paging */
|
||||
movl %cr0, %eax
|
||||
btsl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
ret
|
||||
SYM_FUNC_END(efi32_enable_long_mode)
|
||||
|
||||
/*
|
||||
* This is the common EFI stub entry point for mixed mode. It sets up the GDT
|
||||
* and page tables needed for 64-bit execution, after which it calls the
|
||||
* common 64-bit EFI entrypoint efi_stub_entry().
|
||||
*
|
||||
* Arguments: 0(%esp) image handle
|
||||
* 4(%esp) EFI system table pointer
|
||||
* %ebx struct boot_params pointer (or NULL)
|
||||
*
|
||||
* Since this is the point of no return for ordinary execution, no registers
|
||||
* are considered live except for the function parameters. [Note that the EFI
|
||||
* stub may still exit and return to the firmware using the Exit() EFI boot
|
||||
* service.]
|
||||
*/
|
||||
SYM_FUNC_START_LOCAL(efi32_startup)
|
||||
movl %esp, %ebp
|
||||
|
||||
subl $8, %esp
|
||||
sgdtl (%esp) /* Save GDT descriptor to the stack */
|
||||
movl 2(%esp), %esi /* Existing GDT pointer */
|
||||
movzwl (%esp), %ecx /* Existing GDT limit */
|
||||
inc %ecx /* Existing GDT size */
|
||||
andl $~7, %ecx /* Ensure size is multiple of 8 */
|
||||
|
||||
subl %ecx, %esp /* Allocate new GDT */
|
||||
andl $~15, %esp /* Realign the stack */
|
||||
movl %esp, %edi /* New GDT address */
|
||||
leal 7(%ecx), %eax /* New GDT limit */
|
||||
pushw %cx /* Push 64-bit CS (for LJMP below) */
|
||||
pushl %edi /* Push new GDT address */
|
||||
pushw %ax /* Push new GDT limit */
|
||||
|
||||
/* Copy GDT to the stack and add a 64-bit code segment at the end */
|
||||
movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) & 0xffffffff, (%edi,%ecx)
|
||||
movl $GDT_ENTRY(DESC_CODE64, 0, 0xfffff) >> 32, 4(%edi,%ecx)
|
||||
shrl $2, %ecx
|
||||
cld
|
||||
rep movsl /* Copy the firmware GDT */
|
||||
lgdtl (%esp) /* Switch to the new GDT */
|
||||
|
||||
call 1f
|
||||
1: pop %edi
|
||||
|
||||
/* Record mixed mode entry */
|
||||
movb $0x0, (efi_is64 - 1b)(%edi)
|
||||
|
||||
/* Set up indirect far call to re-enter 32-bit mode */
|
||||
leal (efi32_call - 1b)(%edi), %eax
|
||||
addl %eax, (%eax)
|
||||
movw %cs, 4(%eax)
|
||||
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Set up 1:1 mapping */
|
||||
leal (pte - 1b)(%edi), %eax
|
||||
movl $_PAGE_PRESENT | _PAGE_RW | _PAGE_PSE, %ecx
|
||||
leal (_PAGE_PRESENT | _PAGE_RW)(%eax), %edx
|
||||
2: movl %ecx, (%eax)
|
||||
addl $8, %eax
|
||||
addl $PMD_SIZE, %ecx
|
||||
jnc 2b
|
||||
|
||||
movl $PAGE_SIZE, %ecx
|
||||
.irpc l, 0123
|
||||
movl %edx, \l * 8(%eax)
|
||||
addl %ecx, %edx
|
||||
.endr
|
||||
addl %ecx, %eax
|
||||
movl %edx, (%eax)
|
||||
movl %eax, %cr3
|
||||
|
||||
call efi32_enable_long_mode
|
||||
|
||||
/* Set up far jump to 64-bit mode (CS is already on the stack) */
|
||||
leal (efi_stub_entry - 1b)(%edi), %eax
|
||||
movl %eax, 2(%esp)
|
||||
|
||||
movl 0(%ebp), %edi
|
||||
movl 4(%ebp), %esi
|
||||
movl %ebx, %edx
|
||||
ljmpl *2(%esp)
|
||||
SYM_FUNC_END(efi32_startup)
|
||||
|
||||
/*
|
||||
* efi_status_t efi32_pe_entry(efi_handle_t image_handle,
|
||||
* efi_system_table_32_t *sys_table)
|
||||
*/
|
||||
SYM_FUNC_START(efi32_pe_entry)
|
||||
pushl %ebx // save callee-save registers
|
||||
|
||||
/* Check whether the CPU supports long mode */
|
||||
movl $0x80000001, %eax // assume extended info support
|
||||
cpuid
|
||||
btl $29, %edx // check long mode bit
|
||||
jnc 1f
|
||||
leal 8(%esp), %esp // preserve stack alignment
|
||||
xor %ebx, %ebx // no struct boot_params pointer
|
||||
jmp efi32_startup // only ESP and EBX remain live
|
||||
1: movl $0x80000003, %eax // EFI_UNSUPPORTED
|
||||
popl %ebx
|
||||
RET
|
||||
SYM_FUNC_END(efi32_pe_entry)
|
||||
|
||||
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
|
||||
.org efi32_stub_entry + 0x200
|
||||
.code64
|
||||
SYM_FUNC_START_NOALIGN(efi64_stub_entry)
|
||||
jmp efi_handover_entry
|
||||
SYM_FUNC_END(efi64_stub_entry)
|
||||
#endif
|
||||
|
||||
.data
|
||||
.balign 8
|
||||
SYM_DATA_START_LOCAL(efi32_call)
|
||||
.long efi_enter32 - .
|
||||
.word 0x0
|
||||
SYM_DATA_END(efi32_call)
|
||||
SYM_DATA(efi_is64, .byte 1)
|
||||
|
||||
.bss
|
||||
.balign PAGE_SIZE
|
||||
SYM_DATA_LOCAL(pte, .fill 6 * PAGE_SIZE, 1, 0)
|
||||
@@ -0,0 +1,111 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/boot.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/processor-flags.h>
|
||||
|
||||
/*
|
||||
* This is the 32-bit trampoline that will be copied over to low memory. It
|
||||
* will be called using the ordinary 64-bit calling convention from code
|
||||
* running in 64-bit mode.
|
||||
*
|
||||
* Return address is at the top of the stack (might be above 4G).
|
||||
* The first argument (EDI) contains the address of the temporary PGD level
|
||||
* page table in 32-bit addressable memory which will be programmed into
|
||||
* register CR3.
|
||||
*/
|
||||
|
||||
.section ".rodata", "a", @progbits
|
||||
SYM_CODE_START(trampoline_32bit_src)
|
||||
/*
|
||||
* Preserve callee save 64-bit registers on the stack: this is
|
||||
* necessary because the architecture does not guarantee that GPRs will
|
||||
* retain their full 64-bit values across a 32-bit mode switch.
|
||||
*/
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %rbp
|
||||
pushq %rbx
|
||||
|
||||
/* Preserve top half of RSP in a legacy mode GPR to avoid truncation */
|
||||
movq %rsp, %rbx
|
||||
shrq $32, %rbx
|
||||
|
||||
/* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
|
||||
pushq $__KERNEL32_CS
|
||||
leaq 0f(%rip), %rax
|
||||
pushq %rax
|
||||
lretq
|
||||
|
||||
/*
|
||||
* The 32-bit code below will do a far jump back to long mode and end
|
||||
* up here after reconfiguring the number of paging levels. First, the
|
||||
* stack pointer needs to be restored to its full 64-bit value before
|
||||
* the callee save register contents can be popped from the stack.
|
||||
*/
|
||||
.Lret:
|
||||
shlq $32, %rbx
|
||||
orq %rbx, %rsp
|
||||
|
||||
/* Restore the preserved 64-bit registers */
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
retq
|
||||
|
||||
.code32
|
||||
0:
|
||||
/* Disable paging */
|
||||
movl %cr0, %eax
|
||||
btrl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Point CR3 to the trampoline's new top level page table */
|
||||
movl %edi, %cr3
|
||||
|
||||
/* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
|
||||
movl $MSR_EFER, %ecx
|
||||
rdmsr
|
||||
btsl $_EFER_LME, %eax
|
||||
/* Avoid writing EFER if no change was made (for TDX guest) */
|
||||
jc 1f
|
||||
wrmsr
|
||||
1:
|
||||
/* Toggle CR4.LA57 */
|
||||
movl %cr4, %eax
|
||||
btcl $X86_CR4_LA57_BIT, %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
/* Enable paging again. */
|
||||
movl %cr0, %eax
|
||||
btsl $X86_CR0_PG_BIT, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/*
|
||||
* Return to the 64-bit calling code using LJMP rather than LRET, to
|
||||
* avoid the need for a 32-bit addressable stack. The destination
|
||||
* address will be adjusted after the template code is copied into a
|
||||
* 32-bit addressable buffer.
|
||||
*/
|
||||
.Ljmp: ljmpl $__KERNEL_CS, $(.Lret - trampoline_32bit_src)
|
||||
SYM_CODE_END(trampoline_32bit_src)
|
||||
|
||||
/*
|
||||
* This symbol is placed right after trampoline_32bit_src() so its address can
|
||||
* be used to infer the size of the trampoline code.
|
||||
*/
|
||||
SYM_DATA(trampoline_ljmp_imm_offset, .word .Ljmp + 1 - trampoline_32bit_src)
|
||||
|
||||
/*
|
||||
* The trampoline code has a size limit.
|
||||
* Make sure we fail to compile if the trampoline code grows
|
||||
* beyond TRAMPOLINE_32BIT_CODE_SIZE bytes.
|
||||
*/
|
||||
.org trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE
|
||||
@@ -1,2 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
build
|
||||
@@ -1,247 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
* Copyright (C) 1997 Martin Mares
|
||||
* Copyright (C) 2007 H. Peter Anvin
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file builds a disk-image from three different files:
|
||||
*
|
||||
* - setup: 8086 machine code, sets up system parm
|
||||
* - system: 80386 code for actual system
|
||||
* - zoffset.h: header with ZO_* defines
|
||||
*
|
||||
* It does some checking that all files are of the correct type, and writes
|
||||
* the result to the specified destination, removing headers and padding to
|
||||
* the right amount. It also writes some system data to stdout.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Changes by tytso to allow root device specification
|
||||
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
|
||||
* Cross compiling fixes by Gertjan van Wingerde, July 1996
|
||||
* Rewritten by Martin Mares, April 1997
|
||||
* Substantially overhauled by H. Peter Anvin, April 2007
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <tools/le_byteshift.h>
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
/* Minimal number of setup sectors */
|
||||
#define SETUP_SECT_MIN 5
|
||||
#define SETUP_SECT_MAX 64
|
||||
|
||||
/* This must be large enough to hold the entire setup */
|
||||
u8 buf[SETUP_SECT_MAX*512];
|
||||
|
||||
static unsigned long _edata;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
static const u32 crctab32[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
||||
0x2d02ef8d
|
||||
};
|
||||
|
||||
static u32 partial_crc32_one(u8 c, u32 crc)
|
||||
{
|
||||
return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
|
||||
static u32 partial_crc32(const u8 *s, int len, u32 crc)
|
||||
{
|
||||
while (len--)
|
||||
crc = partial_crc32_one(*s++, crc);
|
||||
return crc;
|
||||
}
|
||||
|
||||
static void die(const char * str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
vfprintf(stderr, str, args);
|
||||
va_end(args);
|
||||
fputc('\n', stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
die("Usage: build setup system zoffset.h image");
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse zoffset.h and find the entry points. We could just #include zoffset.h
|
||||
* but that would mean tools/build would have to be rebuilt every time. It's
|
||||
* not as if parsing it is hard...
|
||||
*/
|
||||
#define PARSE_ZOFS(p, sym) do { \
|
||||
if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym))) \
|
||||
sym = strtoul(p + 11 + sizeof(#sym), NULL, 16); \
|
||||
} while (0)
|
||||
|
||||
static void parse_zoffset(char *fname)
|
||||
{
|
||||
FILE *file;
|
||||
char *p;
|
||||
int c;
|
||||
|
||||
file = fopen(fname, "r");
|
||||
if (!file)
|
||||
die("Unable to open `%s': %m", fname);
|
||||
c = fread(buf, 1, sizeof(buf) - 1, file);
|
||||
if (ferror(file))
|
||||
die("read-error on `zoffset.h'");
|
||||
fclose(file);
|
||||
buf[c] = 0;
|
||||
|
||||
p = (char *)buf;
|
||||
|
||||
while (p && *p) {
|
||||
PARSE_ZOFS(p, _edata);
|
||||
|
||||
p = strchr(p, '\n');
|
||||
while (p && (*p == '\r' || *p == '\n'))
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
unsigned int i, sz, setup_sectors;
|
||||
int c;
|
||||
struct stat sb;
|
||||
FILE *file, *dest;
|
||||
int fd;
|
||||
void *kernel;
|
||||
u32 crc = 0xffffffffUL;
|
||||
|
||||
if (argc != 5)
|
||||
usage();
|
||||
parse_zoffset(argv[3]);
|
||||
|
||||
dest = fopen(argv[4], "w");
|
||||
if (!dest)
|
||||
die("Unable to write `%s': %m", argv[4]);
|
||||
|
||||
/* Copy the setup code */
|
||||
file = fopen(argv[1], "r");
|
||||
if (!file)
|
||||
die("Unable to open `%s': %m", argv[1]);
|
||||
c = fread(buf, 1, sizeof(buf), file);
|
||||
if (ferror(file))
|
||||
die("read-error on `setup'");
|
||||
if (c < 1024)
|
||||
die("The setup must be at least 1024 bytes");
|
||||
if (get_unaligned_le16(&buf[510]) != 0xAA55)
|
||||
die("Boot block hasn't got boot flag (0xAA55)");
|
||||
fclose(file);
|
||||
|
||||
/* Pad unused space with zeros */
|
||||
setup_sectors = (c + 4095) / 4096;
|
||||
setup_sectors *= 8;
|
||||
if (setup_sectors < SETUP_SECT_MIN)
|
||||
setup_sectors = SETUP_SECT_MIN;
|
||||
i = setup_sectors*512;
|
||||
memset(buf+c, 0, i-c);
|
||||
|
||||
/* Open and stat the kernel file */
|
||||
fd = open(argv[2], O_RDONLY);
|
||||
if (fd < 0)
|
||||
die("Unable to open `%s': %m", argv[2]);
|
||||
if (fstat(fd, &sb))
|
||||
die("Unable to stat `%s': %m", argv[2]);
|
||||
if (_edata != sb.st_size)
|
||||
die("Unexpected file size `%s': %u != %u", argv[2], _edata,
|
||||
sb.st_size);
|
||||
sz = _edata - 4;
|
||||
kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (kernel == MAP_FAILED)
|
||||
die("Unable to mmap '%s': %m", argv[2]);
|
||||
|
||||
crc = partial_crc32(buf, i, crc);
|
||||
if (fwrite(buf, 1, i, dest) != i)
|
||||
die("Writing setup failed");
|
||||
|
||||
/* Copy the kernel code */
|
||||
crc = partial_crc32(kernel, sz, crc);
|
||||
if (fwrite(kernel, 1, sz, dest) != sz)
|
||||
die("Writing kernel failed");
|
||||
|
||||
/* Write the CRC */
|
||||
put_unaligned_le32(crc, buf);
|
||||
if (fwrite(buf, 1, 4, dest) != 4)
|
||||
die("Writing CRC failed");
|
||||
|
||||
/* Catch any delayed write failures */
|
||||
if (fclose(dest))
|
||||
die("Writing image failed");
|
||||
|
||||
close(fd);
|
||||
|
||||
/* Everything is OK */
|
||||
return 0;
|
||||
}
|
||||
@@ -1475,11 +1475,13 @@ int __init sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
|
||||
* This is needed by the OVMF UEFI firmware which will use whatever it finds in
|
||||
* the GHCB MSR as its GHCB to talk to the hypervisor. So make sure the per-cpu
|
||||
* runtime GHCBs used by the kernel are also mapped in the EFI page-table.
|
||||
*
|
||||
* When running under SVSM the CA page is needed too, so map it as well.
|
||||
*/
|
||||
int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
|
||||
int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd)
|
||||
{
|
||||
unsigned long address, pflags, pflags_enc;
|
||||
struct sev_es_runtime_data *data;
|
||||
unsigned long address, pflags;
|
||||
int cpu;
|
||||
u64 pfn;
|
||||
|
||||
@@ -1487,6 +1489,7 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
|
||||
return 0;
|
||||
|
||||
pflags = _PAGE_NX | _PAGE_RW;
|
||||
pflags_enc = cc_mkenc(pflags);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
data = per_cpu(runtime_data, cpu);
|
||||
@@ -1496,6 +1499,16 @@ int __init sev_es_efi_map_ghcbs(pgd_t *pgd)
|
||||
|
||||
if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags))
|
||||
return 1;
|
||||
|
||||
if (snp_vmpl) {
|
||||
address = per_cpu(svsm_caa_pa, cpu);
|
||||
if (!address)
|
||||
return 1;
|
||||
|
||||
pfn = address >> PAGE_SHIFT;
|
||||
if (kernel_map_pages_in_pgd(pgd, pfn, address, 1, pflags_enc))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -74,6 +74,11 @@
|
||||
# define BOOT_STACK_SIZE 0x1000
|
||||
#endif
|
||||
|
||||
#define TRAMPOLINE_32BIT_SIZE (2 * PAGE_SIZE)
|
||||
|
||||
#define TRAMPOLINE_32BIT_CODE_OFFSET PAGE_SIZE
|
||||
#define TRAMPOLINE_32BIT_CODE_SIZE 0xA0
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern unsigned int output_len;
|
||||
extern const unsigned long kernel_text_size;
|
||||
@@ -83,6 +88,11 @@ unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
|
||||
void (*error)(char *x));
|
||||
|
||||
extern struct boot_params *boot_params_ptr;
|
||||
extern unsigned long *trampoline_32bit;
|
||||
extern const u16 trampoline_ljmp_imm_offset;
|
||||
|
||||
void trampoline_32bit_src(void *trampoline, bool enable_5lvl);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_BOOT_H */
|
||||
|
||||
@@ -250,6 +250,9 @@ static inline u32 efi64_convert_status(efi_status_t status)
|
||||
#define __efi64_argmap_allocate_pool(type, size, buffer) \
|
||||
((type), (size), efi64_zero_upper(buffer))
|
||||
|
||||
#define __efi64_argmap_locate_handle_buffer(type, proto, key, num, buf) \
|
||||
((type), (proto), (key), efi64_zero_upper(num), efi64_zero_upper(buf))
|
||||
|
||||
#define __efi64_argmap_create_event(type, tpl, f, c, event) \
|
||||
((type), (tpl), (f), (c), efi64_zero_upper(event))
|
||||
|
||||
|
||||
@@ -358,7 +358,7 @@ static __always_inline void sev_es_nmi_complete(void)
|
||||
cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT))
|
||||
__sev_es_nmi_complete();
|
||||
}
|
||||
extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
|
||||
extern int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd);
|
||||
extern void sev_enable(struct boot_params *bp);
|
||||
|
||||
/*
|
||||
@@ -432,7 +432,7 @@ static inline void sev_es_ist_enter(struct pt_regs *regs) { }
|
||||
static inline void sev_es_ist_exit(void) { }
|
||||
static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; }
|
||||
static inline void sev_es_nmi_complete(void) { }
|
||||
static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; }
|
||||
static inline int sev_es_efi_map_ghcbs_cas(pgd_t *pgd) { return 0; }
|
||||
static inline void sev_enable(struct boot_params *bp) { }
|
||||
static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; }
|
||||
static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; }
|
||||
|
||||
@@ -54,15 +54,11 @@
|
||||
#include <asm/uv/uv.h>
|
||||
|
||||
static unsigned long efi_systab_phys __initdata;
|
||||
static unsigned long prop_phys = EFI_INVALID_TABLE_ADDR;
|
||||
static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR;
|
||||
static unsigned long efi_runtime, efi_nr_tables;
|
||||
|
||||
unsigned long efi_fw_vendor, efi_config_table;
|
||||
|
||||
static const efi_config_table_type_t arch_tables[] __initconst = {
|
||||
{EFI_PROPERTIES_TABLE_GUID, &prop_phys, "PROP" },
|
||||
{UGA_IO_PROTOCOL_GUID, &uga_phys, "UGA" },
|
||||
#ifdef CONFIG_X86_UV
|
||||
{UV_SYSTEM_TABLE_GUID, &uv_systab_phys, "UVsystab" },
|
||||
#endif
|
||||
@@ -74,7 +70,6 @@ static const unsigned long * const efi_tables[] = {
|
||||
&efi.acpi20,
|
||||
&efi.smbios,
|
||||
&efi.smbios3,
|
||||
&uga_phys,
|
||||
#ifdef CONFIG_X86_UV
|
||||
&uv_systab_phys,
|
||||
#endif
|
||||
@@ -82,7 +77,6 @@ static const unsigned long * const efi_tables[] = {
|
||||
&efi_runtime,
|
||||
&efi_config_table,
|
||||
&efi.esrt,
|
||||
&prop_phys,
|
||||
&efi_mem_attr_table,
|
||||
#ifdef CONFIG_EFI_RCI2_TABLE
|
||||
&rci2_table_phys,
|
||||
@@ -502,22 +496,6 @@ void __init efi_init(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parse the EFI Properties table if it exists */
|
||||
if (prop_phys != EFI_INVALID_TABLE_ADDR) {
|
||||
efi_properties_table_t *tbl;
|
||||
|
||||
tbl = early_memremap_ro(prop_phys, sizeof(*tbl));
|
||||
if (tbl == NULL) {
|
||||
pr_err("Could not map Properties table!\n");
|
||||
} else {
|
||||
if (tbl->memory_protection_attribute &
|
||||
EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
|
||||
set_bit(EFI_NX_PE_DATA, &efi.flags);
|
||||
|
||||
early_memunmap(tbl, sizeof(*tbl));
|
||||
}
|
||||
}
|
||||
|
||||
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
|
||||
efi_clean_memmap();
|
||||
|
||||
@@ -784,6 +762,7 @@ static void __init kexec_enter_virtual_mode(void)
|
||||
|
||||
efi_sync_low_kernel_mappings();
|
||||
efi_native_runtime_setup();
|
||||
efi_runtime_update_mappings();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -909,13 +888,6 @@ bool efi_is_table_address(unsigned long phys_addr)
|
||||
return false;
|
||||
}
|
||||
|
||||
char *efi_systab_show_arch(char *str)
|
||||
{
|
||||
if (uga_phys != EFI_INVALID_TABLE_ADDR)
|
||||
str += sprintf(str, "UGA=0x%lx\n", uga_phys);
|
||||
return str;
|
||||
}
|
||||
|
||||
#define EFI_FIELD(var) efi_ ## var
|
||||
|
||||
#define EFI_ATTR_SHOW(name) \
|
||||
|
||||
@@ -215,8 +215,8 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
|
||||
* When SEV-ES is active, the GHCB as set by the kernel will be used
|
||||
* by firmware. Create a 1:1 unencrypted mapping for each GHCB.
|
||||
*/
|
||||
if (sev_es_efi_map_ghcbs(pgd)) {
|
||||
pr_err("Failed to create 1:1 mapping for the GHCBs!\n");
|
||||
if (sev_es_efi_map_ghcbs_cas(pgd)) {
|
||||
pr_err("Failed to create 1:1 mapping for the GHCBs and CAs!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -412,51 +412,9 @@ static int __init efi_update_mem_attr(struct mm_struct *mm, efi_memory_desc_t *m
|
||||
|
||||
void __init efi_runtime_update_mappings(void)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
|
||||
/*
|
||||
* Use the EFI Memory Attribute Table for mapping permissions if it
|
||||
* exists, since it is intended to supersede EFI_PROPERTIES_TABLE.
|
||||
*/
|
||||
if (efi_enabled(EFI_MEM_ATTR)) {
|
||||
efi_disable_ibt_for_runtime = false;
|
||||
efi_memattr_apply_permissions(NULL, efi_update_mem_attr);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* EFI_MEMORY_ATTRIBUTES_TABLE is intended to replace
|
||||
* EFI_PROPERTIES_TABLE. So, use EFI_PROPERTIES_TABLE to update
|
||||
* permissions only if EFI_MEMORY_ATTRIBUTES_TABLE is not
|
||||
* published by the firmware. Even if we find a buggy implementation of
|
||||
* EFI_MEMORY_ATTRIBUTES_TABLE, don't fall back to
|
||||
* EFI_PROPERTIES_TABLE, because of the same reason.
|
||||
*/
|
||||
|
||||
if (!efi_enabled(EFI_NX_PE_DATA))
|
||||
return;
|
||||
|
||||
for_each_efi_memory_desc(md) {
|
||||
unsigned long pf = 0;
|
||||
|
||||
if (!(md->attribute & EFI_MEMORY_RUNTIME))
|
||||
continue;
|
||||
|
||||
if (!(md->attribute & EFI_MEMORY_WB))
|
||||
pf |= _PAGE_PCD;
|
||||
|
||||
if ((md->attribute & EFI_MEMORY_XP) ||
|
||||
(md->type == EFI_RUNTIME_SERVICES_DATA))
|
||||
pf |= _PAGE_NX;
|
||||
|
||||
if (!(md->attribute & EFI_MEMORY_RO) &&
|
||||
(md->type != EFI_RUNTIME_SERVICES_CODE))
|
||||
pf |= _PAGE_RW;
|
||||
|
||||
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
|
||||
pf |= _PAGE_ENC;
|
||||
|
||||
efi_update_mappings(md, pf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -561,6 +561,11 @@ int __init efi_reuse_config(u64 tables, int nr_tables)
|
||||
|
||||
if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID))
|
||||
((efi_config_table_64_t *)p)->table = data->smbios;
|
||||
|
||||
/* Do not bother to play with mem attr table across kexec */
|
||||
if (!efi_guidcmp(guid, EFI_MEMORY_ATTRIBUTES_TABLE_GUID))
|
||||
((efi_config_table_64_t *)p)->table = EFI_INVALID_TABLE_ADDR;
|
||||
|
||||
p += sz;
|
||||
}
|
||||
early_memunmap(tablep, nr_tables * sz);
|
||||
|
||||
@@ -40,13 +40,13 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
|
||||
} while (0)
|
||||
|
||||
chkaddr(0, 0, sizeof(*mz));
|
||||
if (mz->magic != MZ_MAGIC)
|
||||
if (mz->magic != IMAGE_DOS_SIGNATURE)
|
||||
return -ELIBBAD;
|
||||
cursor = sizeof(*mz);
|
||||
|
||||
chkaddr(cursor, mz->peaddr, sizeof(*pe));
|
||||
pe = pebuf + mz->peaddr;
|
||||
if (pe->magic != PE_MAGIC)
|
||||
if (pe->magic != IMAGE_NT_SIGNATURE)
|
||||
return -ELIBBAD;
|
||||
cursor = mz->peaddr + sizeof(*pe);
|
||||
|
||||
@@ -55,7 +55,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
|
||||
pe64 = pebuf + cursor;
|
||||
|
||||
switch (pe32->magic) {
|
||||
case PE_OPT_MAGIC_PE32:
|
||||
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
|
||||
chkaddr(0, cursor, sizeof(*pe32));
|
||||
ctx->image_checksum_offset =
|
||||
(unsigned long)&pe32->csum - (unsigned long)pebuf;
|
||||
@@ -64,7 +64,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
|
||||
ctx->n_data_dirents = pe32->data_dirs;
|
||||
break;
|
||||
|
||||
case PE_OPT_MAGIC_PE32PLUS:
|
||||
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
|
||||
chkaddr(0, cursor, sizeof(*pe64));
|
||||
ctx->image_checksum_offset =
|
||||
(unsigned long)&pe64->csum - (unsigned long)pebuf;
|
||||
|
||||
@@ -76,20 +76,14 @@ config EFI_ZBOOT
|
||||
bool "Enable the generic EFI decompressor"
|
||||
depends on EFI_GENERIC_STUB && !ARM
|
||||
select HAVE_KERNEL_GZIP
|
||||
select HAVE_KERNEL_LZ4
|
||||
select HAVE_KERNEL_LZMA
|
||||
select HAVE_KERNEL_LZO
|
||||
select HAVE_KERNEL_XZ
|
||||
select HAVE_KERNEL_ZSTD
|
||||
help
|
||||
Create the bootable image as an EFI application that carries the
|
||||
actual kernel image in compressed form, and decompresses it into
|
||||
memory before executing it via LoadImage/StartImage EFI boot service
|
||||
calls. For compatibility with non-EFI loaders, the payload can be
|
||||
decompressed and executed by the loader as well, provided that the
|
||||
loader implements the decompression algorithm and that non-EFI boot
|
||||
is supported by the encapsulated image. (The compression algorithm
|
||||
used is described in the zboot image header)
|
||||
memory before executing it. For compatibility with non-EFI loaders,
|
||||
the payload can be decompressed and executed by the loader as well,
|
||||
provided that the loader implements the decompression algorithm.
|
||||
(The compression algorithm used is described in the zboot header)
|
||||
|
||||
config EFI_ARMSTUB_DTB_LOADER
|
||||
bool "Enable the DTB loader"
|
||||
|
||||
@@ -311,7 +311,7 @@ void cper_print_proc_arm(const char *pfx,
|
||||
ctx_info = (struct cper_arm_ctx_info *)err_info;
|
||||
max_ctx_type = ARRAY_SIZE(arm_reg_ctx_strs) - 1;
|
||||
for (i = 0; i < proc->context_info_num; i++) {
|
||||
int size = sizeof(*ctx_info) + ctx_info->size;
|
||||
int size = ALIGN(sizeof(*ctx_info) + ctx_info->size, 16);
|
||||
|
||||
printk("%sContext info structure %d:\n", pfx, i);
|
||||
if (len < size) {
|
||||
|
||||
@@ -325,7 +325,7 @@ void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
|
||||
|
||||
ctx_info = (struct cper_ia_proc_ctx *)err_info;
|
||||
for (i = 0; i < VALID_PROC_CXT_INFO_NUM(proc->validation_bits); i++) {
|
||||
int size = sizeof(*ctx_info) + ctx_info->reg_arr_size;
|
||||
int size = ALIGN(sizeof(*ctx_info) + ctx_info->reg_arr_size, 16);
|
||||
int groupsize = 4;
|
||||
|
||||
printk("%sContext Information Structure %d:\n", pfx, i);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <linux/bcd.h>
|
||||
#include <acpi/ghes.h>
|
||||
#include <ras/ras_event.h>
|
||||
#include "cper_cxl.h"
|
||||
#include <cxl/event.h>
|
||||
|
||||
/*
|
||||
* CPER record ID need to be unique even after reboot, because record
|
||||
@@ -624,11 +624,11 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata
|
||||
else
|
||||
goto err_section_too_small;
|
||||
} else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
|
||||
struct cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata);
|
||||
struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata);
|
||||
|
||||
printk("%ssection_type: CXL Protocol Error\n", newpfx);
|
||||
if (gdata->error_data_length >= sizeof(*prot_err))
|
||||
cper_print_prot_err(newpfx, prot_err);
|
||||
cxl_cper_print_prot_err(newpfx, prot_err);
|
||||
else
|
||||
goto err_section_too_small;
|
||||
} else {
|
||||
|
||||
@@ -8,26 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/cper.h>
|
||||
#include "cper_cxl.h"
|
||||
|
||||
#define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0)
|
||||
#define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1)
|
||||
#define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2)
|
||||
#define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3)
|
||||
#define PROT_ERR_VALID_CAPABILITY BIT_ULL(4)
|
||||
#define PROT_ERR_VALID_DVSEC BIT_ULL(5)
|
||||
#define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6)
|
||||
|
||||
/* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */
|
||||
struct cxl_ras_capability_regs {
|
||||
u32 uncor_status;
|
||||
u32 uncor_mask;
|
||||
u32 uncor_severity;
|
||||
u32 cor_status;
|
||||
u32 cor_mask;
|
||||
u32 cap_control;
|
||||
u32 header_log[16];
|
||||
};
|
||||
#include <cxl/event.h>
|
||||
|
||||
static const char * const prot_err_agent_type_strs[] = {
|
||||
"Restricted CXL Device",
|
||||
@@ -40,22 +21,8 @@ static const char * const prot_err_agent_type_strs[] = {
|
||||
"CXL Upstream Switch Port",
|
||||
};
|
||||
|
||||
/*
|
||||
* The layout of the enumeration and the values matches CXL Agent Type
|
||||
* field in the UEFI 2.10 Section N.2.13,
|
||||
*/
|
||||
enum {
|
||||
RCD, /* Restricted CXL Device */
|
||||
RCH_DP, /* Restricted CXL Host Downstream Port */
|
||||
DEVICE, /* CXL Device */
|
||||
LD, /* CXL Logical Device */
|
||||
FMLD, /* CXL Fabric Manager managed Logical Device */
|
||||
RP, /* CXL Root Port */
|
||||
DSP, /* CXL Downstream Switch Port */
|
||||
USP, /* CXL Upstream Switch Port */
|
||||
};
|
||||
|
||||
void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err)
|
||||
void cxl_cper_print_prot_err(const char *pfx,
|
||||
const struct cxl_cper_sec_prot_err *prot_err)
|
||||
{
|
||||
if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_TYPE)
|
||||
pr_info("%s agent_type: %d, %s\n", pfx, prot_err->agent_type,
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* UEFI Common Platform Error Record (CPER) support for CXL Section.
|
||||
*
|
||||
* Copyright (C) 2022 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Author: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
|
||||
*/
|
||||
|
||||
#ifndef LINUX_CPER_CXL_H
|
||||
#define LINUX_CPER_CXL_H
|
||||
|
||||
/* CXL Protocol Error Section */
|
||||
#define CPER_SEC_CXL_PROT_ERR \
|
||||
GUID_INIT(0x80B9EFB4, 0x52B5, 0x4DE3, 0xA7, 0x77, 0x68, 0x78, \
|
||||
0x4B, 0x77, 0x10, 0x48)
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */
|
||||
struct cper_sec_prot_err {
|
||||
u64 valid_bits;
|
||||
u8 agent_type;
|
||||
u8 reserved[7];
|
||||
|
||||
/*
|
||||
* Except for RCH Downstream Port, all the remaining CXL Agent
|
||||
* types are uniquely identified by the PCIe compatible SBDF number.
|
||||
*/
|
||||
union {
|
||||
u64 rcrb_base_addr;
|
||||
struct {
|
||||
u8 function;
|
||||
u8 device;
|
||||
u8 bus;
|
||||
u16 segment;
|
||||
u8 reserved_1[3];
|
||||
};
|
||||
} agent_addr;
|
||||
|
||||
struct {
|
||||
u16 vendor_id;
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_id;
|
||||
u8 class_code[2];
|
||||
u16 slot;
|
||||
u8 reserved_1[4];
|
||||
} device_id;
|
||||
|
||||
struct {
|
||||
u32 lower_dw;
|
||||
u32 upper_dw;
|
||||
} dev_serial_num;
|
||||
|
||||
u8 capability[60];
|
||||
u16 dvsec_len;
|
||||
u16 err_len;
|
||||
u8 reserved_2[4];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err);
|
||||
|
||||
#endif //__CPER_CXL_
|
||||
+33
-18
@@ -150,9 +150,6 @@ static ssize_t systab_show(struct kobject *kobj,
|
||||
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
|
||||
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86))
|
||||
str = efi_systab_show_arch(str);
|
||||
|
||||
return str - buf;
|
||||
}
|
||||
|
||||
@@ -275,6 +272,7 @@ static __init int efivar_ssdt_load(void)
|
||||
efi_char16_t *name = NULL;
|
||||
efi_status_t status;
|
||||
efi_guid_t guid;
|
||||
int ret = 0;
|
||||
|
||||
if (!efivar_ssdt[0])
|
||||
return 0;
|
||||
@@ -296,8 +294,8 @@ static __init int efivar_ssdt_load(void)
|
||||
efi_char16_t *name_tmp =
|
||||
krealloc(name, name_size, GFP_KERNEL);
|
||||
if (!name_tmp) {
|
||||
kfree(name);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
name = name_tmp;
|
||||
continue;
|
||||
@@ -311,26 +309,38 @@ static __init int efivar_ssdt_load(void)
|
||||
pr_info("loading SSDT from variable %s-%pUl\n", efivar_ssdt, &guid);
|
||||
|
||||
status = efi.get_variable(name, &guid, NULL, &data_size, NULL);
|
||||
if (status != EFI_BUFFER_TOO_SMALL || !data_size)
|
||||
return -EIO;
|
||||
if (status != EFI_BUFFER_TOO_SMALL || !data_size) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data = kmalloc(data_size, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
if (!data) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = efi.get_variable(name, &guid, NULL, &data_size, data);
|
||||
if (status == EFI_SUCCESS) {
|
||||
acpi_status ret = acpi_load_table(data, NULL);
|
||||
if (ret)
|
||||
pr_err("failed to load table: %u\n", ret);
|
||||
else
|
||||
acpi_status acpi_ret = acpi_load_table(data, NULL);
|
||||
if (ACPI_FAILURE(acpi_ret)) {
|
||||
pr_err("efivar_ssdt: failed to load table: %u\n",
|
||||
acpi_ret);
|
||||
} else {
|
||||
/*
|
||||
* The @data will be in use by ACPI engine,
|
||||
* do not free it!
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
pr_err("failed to get var data: 0x%lx\n", status);
|
||||
pr_err("efivar_ssdt: failed to get var data: 0x%lx\n", status);
|
||||
}
|
||||
kfree(data);
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
kfree(name);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline int efivar_ssdt_load(void) { return 0; }
|
||||
@@ -435,7 +445,9 @@ static int __init efisubsys_init(void)
|
||||
error = generic_ops_register();
|
||||
if (error)
|
||||
goto err_put;
|
||||
efivar_ssdt_load();
|
||||
error = efivar_ssdt_load();
|
||||
if (error)
|
||||
pr_err("efi: failed to load SSDT, error %d.\n", error);
|
||||
platform_device_register_simple("efivars", 0, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -552,6 +564,7 @@ int __efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
|
||||
|
||||
extern int efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
|
||||
__weak __alias(__efi_mem_desc_lookup);
|
||||
EXPORT_SYMBOL_GPL(efi_mem_desc_lookup);
|
||||
|
||||
/*
|
||||
* Calculate the highest address of an efi memory descriptor.
|
||||
@@ -931,13 +944,15 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
|
||||
EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
|
||||
EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
|
||||
EFI_MEMORY_NV | EFI_MEMORY_SP | EFI_MEMORY_CPU_CRYPTO |
|
||||
EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
|
||||
EFI_MEMORY_MORE_RELIABLE | EFI_MEMORY_HOT_PLUGGABLE |
|
||||
EFI_MEMORY_RUNTIME))
|
||||
snprintf(pos, size, "|attr=0x%016llx]",
|
||||
(unsigned long long)attr);
|
||||
else
|
||||
snprintf(pos, size,
|
||||
"|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
|
||||
"|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
|
||||
attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
|
||||
attr & EFI_MEMORY_HOT_PLUGGABLE ? "HP" : "",
|
||||
attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
|
||||
attr & EFI_MEMORY_CPU_CRYPTO ? "CC" : "",
|
||||
attr & EFI_MEMORY_SP ? "SP" : "",
|
||||
|
||||
@@ -47,7 +47,7 @@ static int efibc_reboot_notifier_call(struct notifier_block *notifier,
|
||||
if (ret || !data)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
wdata = kmalloc(MAX_DATA_LEN * sizeof(efi_char16_t), GFP_KERNEL);
|
||||
wdata = kmalloc_array(MAX_DATA_LEN, sizeof(efi_char16_t), GFP_KERNEL);
|
||||
if (!wdata)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
|
||||
@@ -75,8 +75,6 @@ static LIST_HEAD(entry_list);
|
||||
struct esre_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct esre_entry *entry, char *buf);
|
||||
ssize_t (*store)(struct esre_entry *entry,
|
||||
const char *buf, size_t count);
|
||||
};
|
||||
|
||||
static struct esre_entry *to_entry(struct kobject *kobj)
|
||||
|
||||
@@ -11,7 +11,7 @@ cflags-y := $(KBUILD_CFLAGS)
|
||||
|
||||
cflags-$(CONFIG_X86_32) := -march=i386
|
||||
cflags-$(CONFIG_X86_64) := -mcmodel=small
|
||||
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
|
||||
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -std=gnu11 \
|
||||
-fPIC -fno-strict-aliasing -mno-red-zone \
|
||||
-mno-mmx -mno-sse -fshort-wchar \
|
||||
-Wno-pointer-sign \
|
||||
@@ -62,6 +62,8 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS))
|
||||
# `-fdata-sections` flag from KBUILD_CFLAGS_KERNEL
|
||||
KBUILD_CFLAGS_KERNEL := $(filter-out -fdata-sections, $(KBUILD_CFLAGS_KERNEL))
|
||||
|
||||
KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__
|
||||
|
||||
lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
|
||||
file.o mem.o random.o randomalloc.o pci.o \
|
||||
skip_spaces.o lib-cmdline.o lib-ctype.o \
|
||||
@@ -89,12 +91,17 @@ lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
|
||||
|
||||
CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
|
||||
|
||||
zboot-obj-$(CONFIG_RISCV) := lib-clz_ctz.o lib-ashldi3.o
|
||||
zboot-obj-y := zboot-decompress-gzip.o
|
||||
CFLAGS_zboot-decompress-gzip.o += -I$(srctree)/lib/zlib_inflate
|
||||
zboot-obj-$(CONFIG_KERNEL_ZSTD) := zboot-decompress-zstd.o lib-xxhash.o
|
||||
CFLAGS_zboot-decompress-zstd.o += -I$(srctree)/lib/zstd
|
||||
|
||||
zboot-obj-$(CONFIG_RISCV) += lib-clz_ctz.o lib-ashldi3.o
|
||||
lib-$(CONFIG_EFI_ZBOOT) += zboot.o $(zboot-obj-y)
|
||||
|
||||
lib-$(CONFIG_UNACCEPTED_MEMORY) += unaccepted_memory.o bitmap.o find.o
|
||||
|
||||
extra-y := $(lib-y)
|
||||
targets := $(lib-y)
|
||||
lib-y := $(patsubst %.o,%.stub.o,$(lib-y))
|
||||
|
||||
# Even when -mbranch-protection=none is set, Clang will generate a
|
||||
|
||||
@@ -12,22 +12,16 @@ quiet_cmd_copy_and_pad = PAD $@
|
||||
$(obj)/vmlinux.bin: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
|
||||
$(call if_changed,copy_and_pad)
|
||||
|
||||
comp-type-$(CONFIG_KERNEL_GZIP) := gzip
|
||||
comp-type-$(CONFIG_KERNEL_LZ4) := lz4
|
||||
comp-type-$(CONFIG_KERNEL_LZMA) := lzma
|
||||
comp-type-$(CONFIG_KERNEL_LZO) := lzo
|
||||
comp-type-$(CONFIG_KERNEL_XZ) := xzkern
|
||||
comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
|
||||
|
||||
# in GZIP, the appended le32 carrying the uncompressed size is part of the
|
||||
# format, but in other cases, we just append it at the end for convenience,
|
||||
# causing the original tools to complain when checking image integrity.
|
||||
# So disregard it when calculating the payload size in the zimage header.
|
||||
zboot-method-y := $(comp-type-y)_with_size
|
||||
zboot-size-len-y := 4
|
||||
comp-type-y := gzip
|
||||
zboot-method-y := gzip
|
||||
zboot-size-len-y := 0
|
||||
|
||||
zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
|
||||
zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0
|
||||
comp-type-$(CONFIG_KERNEL_ZSTD) := zstd
|
||||
zboot-method-$(CONFIG_KERNEL_ZSTD) := zstd22_with_size
|
||||
zboot-size-len-$(CONFIG_KERNEL_ZSTD) := 4
|
||||
|
||||
$(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
|
||||
$(call if_changed,$(zboot-method-y))
|
||||
|
||||
@@ -47,9 +47,10 @@ bool __pure __efi_soft_reserve_enabled(void)
|
||||
*/
|
||||
efi_status_t efi_parse_options(char const *cmdline)
|
||||
{
|
||||
size_t len;
|
||||
char *buf __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
char *str, *buf;
|
||||
size_t len;
|
||||
char *str;
|
||||
|
||||
if (!cmdline)
|
||||
return EFI_SUCCESS;
|
||||
@@ -102,7 +103,6 @@ efi_status_t efi_parse_options(char const *cmdline)
|
||||
efi_parse_option_graphics(val + strlen("efifb:"));
|
||||
}
|
||||
}
|
||||
efi_bs_call(free_pool, buf);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
|
||||
u64, const union efistub_event *);
|
||||
struct { u32 hash_log_extend_event; } mixed_mode;
|
||||
} method;
|
||||
struct efistub_measured_event *evt;
|
||||
struct efistub_measured_event *evt __free(efi_pool) = NULL;
|
||||
int size = struct_size(evt, tagged_event.tagged_event_data,
|
||||
events[event].event_data_len);
|
||||
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
|
||||
@@ -312,7 +312,6 @@ static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
|
||||
|
||||
status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,
|
||||
load_addr, load_size, &evt->event_data);
|
||||
efi_bs_call(free_pool, evt);
|
||||
|
||||
if (status == EFI_SUCCESS)
|
||||
return EFI_SUCCESS;
|
||||
@@ -327,7 +326,7 @@ fail:
|
||||
* Size of memory allocated return in *cmd_line_len.
|
||||
* Returns NULL on error.
|
||||
*/
|
||||
char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
|
||||
char *efi_convert_cmdline(efi_loaded_image_t *image)
|
||||
{
|
||||
const efi_char16_t *options = efi_table_attr(image, load_options);
|
||||
u32 options_size = efi_table_attr(image, load_options_size);
|
||||
@@ -405,7 +404,6 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
|
||||
snprintf((char *)cmdline_addr, options_bytes, "%.*ls",
|
||||
options_bytes - 1, options);
|
||||
|
||||
*cmd_line_len = options_bytes;
|
||||
return (char *)cmdline_addr;
|
||||
}
|
||||
|
||||
@@ -603,6 +601,7 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
|
||||
* @image: EFI loaded image protocol
|
||||
* @soft_limit: preferred address for loading the initrd
|
||||
* @hard_limit: upper limit address for loading the initrd
|
||||
* @out: pointer to store the address of the initrd table
|
||||
*
|
||||
* Return: status code
|
||||
*/
|
||||
@@ -621,10 +620,6 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
|
||||
status = efi_load_initrd_dev_path(&initrd, hard_limit);
|
||||
if (status == EFI_SUCCESS) {
|
||||
efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
|
||||
if (initrd.size > 0 &&
|
||||
efi_measure_tagged_event(initrd.base, initrd.size,
|
||||
EFISTUB_EVT_INITRD) == EFI_SUCCESS)
|
||||
efi_info("Measured initrd data into PCR 9\n");
|
||||
} else if (status == EFI_NOT_FOUND) {
|
||||
status = efi_load_initrd_cmdline(image, &initrd, soft_limit,
|
||||
hard_limit);
|
||||
@@ -637,6 +632,11 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
|
||||
if (status != EFI_SUCCESS)
|
||||
goto failed;
|
||||
|
||||
if (initrd.size > 0 &&
|
||||
efi_measure_tagged_event(initrd.base, initrd.size,
|
||||
EFISTUB_EVT_INITRD) == EFI_SUCCESS)
|
||||
efi_info("Measured initrd data into PCR 9\n");
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(initrd),
|
||||
(void **)&tbl);
|
||||
if (status != EFI_SUCCESS)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/screen_info.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
@@ -53,25 +54,16 @@ void __weak free_screen_info(struct screen_info *si)
|
||||
|
||||
static struct screen_info *setup_graphics(void)
|
||||
{
|
||||
efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
void **gop_handle = NULL;
|
||||
struct screen_info *si = NULL;
|
||||
struct screen_info *si, tmp = {};
|
||||
|
||||
size = 0;
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&gop_proto, NULL, &size, gop_handle);
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
si = alloc_screen_info();
|
||||
if (!si)
|
||||
return NULL;
|
||||
status = efi_setup_gop(si, &gop_proto, size);
|
||||
if (status != EFI_SUCCESS) {
|
||||
free_screen_info(si);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (efi_setup_gop(&tmp) != EFI_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
si = alloc_screen_info();
|
||||
if (!si)
|
||||
return NULL;
|
||||
|
||||
*si = tmp;
|
||||
return si;
|
||||
}
|
||||
|
||||
@@ -112,45 +104,40 @@ static u32 get_supported_rt_services(void)
|
||||
|
||||
efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
|
||||
{
|
||||
int cmdline_size = 0;
|
||||
char *cmdline __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
char *cmdline;
|
||||
|
||||
/*
|
||||
* Get the command line from EFI, using the LOADED_IMAGE
|
||||
* protocol. We are going to copy the command line into the
|
||||
* device tree, so this can be allocated anywhere.
|
||||
*/
|
||||
cmdline = efi_convert_cmdline(image, &cmdline_size);
|
||||
cmdline = efi_convert_cmdline(image);
|
||||
if (!cmdline) {
|
||||
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
||||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
|
||||
cmdline_size == 0) {
|
||||
status = efi_parse_options(CONFIG_CMDLINE);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to parse options\n");
|
||||
goto fail_free_cmdline;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
|
||||
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
|
||||
status = efi_parse_options(cmdline);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to parse options\n");
|
||||
goto fail_free_cmdline;
|
||||
efi_err("Failed to parse EFI load options\n");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
*cmdline_ptr = cmdline;
|
||||
return EFI_SUCCESS;
|
||||
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
|
||||
IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
|
||||
cmdline[0] == 0) {
|
||||
status = efi_parse_options(CONFIG_CMDLINE);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to parse built-in command line\n");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
fail_free_cmdline:
|
||||
efi_bs_call(free_pool, cmdline_ptr);
|
||||
return status;
|
||||
*cmdline_ptr = no_free_ptr(cmdline);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
efi_status_t efi_stub_common(efi_handle_t handle,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kern_levels.h>
|
||||
@@ -122,11 +123,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
#define efi_get_handle_num(size) \
|
||||
((size) / (efi_is_native() ? sizeof(efi_handle_t) : sizeof(u32)))
|
||||
|
||||
#define for_each_efi_handle(handle, array, size, i) \
|
||||
for (i = 0; \
|
||||
i < efi_get_handle_num(size) && \
|
||||
((handle = efi_get_handle_at((array), i)) || true); \
|
||||
i++)
|
||||
#define for_each_efi_handle(handle, array, num) \
|
||||
for (int __i = 0; __i < (num) && \
|
||||
((handle = efi_get_handle_at((array), __i)) || true); \
|
||||
__i++)
|
||||
|
||||
static inline
|
||||
void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
|
||||
@@ -314,7 +314,9 @@ union efi_boot_services {
|
||||
void *close_protocol;
|
||||
void *open_protocol_information;
|
||||
void *protocols_per_handle;
|
||||
void *locate_handle_buffer;
|
||||
efi_status_t (__efiapi *locate_handle_buffer)(int, efi_guid_t *,
|
||||
void *, unsigned long *,
|
||||
efi_handle_t **);
|
||||
efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *,
|
||||
void **);
|
||||
efi_status_t (__efiapi *install_multiple_protocol_interfaces)(efi_handle_t *, ...);
|
||||
@@ -1053,10 +1055,11 @@ void efi_puts(const char *str);
|
||||
__printf(1, 2) int efi_printk(char const *fmt, ...);
|
||||
|
||||
void efi_free(unsigned long size, unsigned long addr);
|
||||
DEFINE_FREE(efi_pool, void *, if (_T) efi_bs_call(free_pool, _T));
|
||||
|
||||
void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_size);
|
||||
|
||||
char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
|
||||
char *efi_convert_cmdline(efi_loaded_image_t *image);
|
||||
|
||||
efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
|
||||
bool install_cfg_tbl);
|
||||
@@ -1082,8 +1085,7 @@ efi_status_t efi_parse_options(char const *cmdline);
|
||||
|
||||
void efi_parse_option_graphics(char *option);
|
||||
|
||||
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
unsigned long size);
|
||||
efi_status_t efi_setup_gop(struct screen_info *si);
|
||||
|
||||
efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
const efi_char16_t *optstr,
|
||||
@@ -1232,4 +1234,7 @@ void process_unaccepted_memory(u64 start, u64 end);
|
||||
void accept_memory(phys_addr_t start, unsigned long size);
|
||||
void arch_accept_memory(phys_addr_t start, phys_addr_t end);
|
||||
|
||||
efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size);
|
||||
efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -175,6 +175,12 @@ static efi_status_t efi_open_device_path(efi_file_protocol_t **volume,
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CMDLINE
|
||||
#define CONFIG_CMDLINE
|
||||
#endif
|
||||
|
||||
static const efi_char16_t builtin_cmdline[] = L"" CONFIG_CMDLINE;
|
||||
|
||||
/*
|
||||
* Check the cmdline for a LILO-style file= arguments.
|
||||
*
|
||||
@@ -189,6 +195,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
unsigned long *load_addr,
|
||||
unsigned long *load_size)
|
||||
{
|
||||
const bool ignore_load_options = IS_ENABLED(CONFIG_CMDLINE_OVERRIDE) ||
|
||||
IS_ENABLED(CONFIG_CMDLINE_FORCE);
|
||||
const efi_char16_t *cmdline = efi_table_attr(image, load_options);
|
||||
u32 cmdline_len = efi_table_attr(image, load_options_size);
|
||||
unsigned long efi_chunk_size = ULONG_MAX;
|
||||
@@ -197,6 +205,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
unsigned long alloc_addr;
|
||||
unsigned long alloc_size;
|
||||
efi_status_t status;
|
||||
bool twopass;
|
||||
int offset;
|
||||
|
||||
if (!load_addr || !load_size)
|
||||
@@ -209,6 +218,16 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
efi_chunk_size = EFI_READ_CHUNK_SIZE;
|
||||
|
||||
alloc_addr = alloc_size = 0;
|
||||
|
||||
if (!ignore_load_options && cmdline_len > 0) {
|
||||
twopass = IS_ENABLED(CONFIG_CMDLINE_BOOL) ||
|
||||
IS_ENABLED(CONFIG_CMDLINE_EXTEND);
|
||||
} else {
|
||||
do_builtin: cmdline = builtin_cmdline;
|
||||
cmdline_len = ARRAY_SIZE(builtin_cmdline) - 1;
|
||||
twopass = false;
|
||||
}
|
||||
|
||||
do {
|
||||
struct finfo fi;
|
||||
unsigned long size;
|
||||
@@ -290,6 +309,9 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
|
||||
efi_call_proto(volume, close);
|
||||
} while (offset > 0);
|
||||
|
||||
if (twopass)
|
||||
goto do_builtin;
|
||||
|
||||
*load_addr = alloc_addr;
|
||||
*load_size = alloc_size;
|
||||
|
||||
|
||||
+124
-203
@@ -133,13 +133,11 @@ void efi_parse_option_graphics(char *option)
|
||||
|
||||
static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
efi_graphics_output_mode_info_t *info __free(efi_pool) = NULL;
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
|
||||
u32 max_mode, cur_mode;
|
||||
efi_status_t status;
|
||||
int pf;
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
@@ -154,17 +152,13 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
|
||||
return cur_mode;
|
||||
}
|
||||
|
||||
status = efi_call_proto(gop, query_mode, cmdline.mode,
|
||||
&info_size, &info);
|
||||
status = efi_call_proto(gop, query_mode, cmdline.mode, &info_size, &info);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Couldn't get mode information\n");
|
||||
return cur_mode;
|
||||
}
|
||||
|
||||
pf = info->pixel_format;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) {
|
||||
efi_err("Invalid PixelFormat\n");
|
||||
return cur_mode;
|
||||
@@ -173,6 +167,28 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
|
||||
return cmdline.mode;
|
||||
}
|
||||
|
||||
static u32 choose_mode(efi_graphics_output_protocol_t *gop,
|
||||
bool (*match)(const efi_graphics_output_mode_info_t *, u32, void *),
|
||||
void *ctx)
|
||||
{
|
||||
efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode);
|
||||
u32 max_mode = efi_table_attr(mode, max_mode);
|
||||
|
||||
for (u32 m = 0; m < max_mode; m++) {
|
||||
efi_graphics_output_mode_info_t *info __free(efi_pool) = NULL;
|
||||
unsigned long info_size;
|
||||
efi_status_t status;
|
||||
|
||||
status = efi_call_proto(gop, query_mode, m, &info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (match(info, m, ctx))
|
||||
return m;
|
||||
}
|
||||
return (unsigned long)ctx;
|
||||
}
|
||||
|
||||
static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info)
|
||||
{
|
||||
if (pixel_format == PIXEL_BIT_MASK) {
|
||||
@@ -185,192 +201,117 @@ static u8 pixel_bpp(int pixel_format, efi_pixel_bitmask_t pixel_info)
|
||||
return 32;
|
||||
}
|
||||
|
||||
static bool match_res(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx)
|
||||
{
|
||||
efi_pixel_bitmask_t pi = info->pixel_information;
|
||||
int pf = info->pixel_format;
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
return false;
|
||||
|
||||
return cmdline.res.width == info->horizontal_resolution &&
|
||||
cmdline.res.height == info->vertical_resolution &&
|
||||
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
|
||||
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi));
|
||||
}
|
||||
|
||||
static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode);
|
||||
unsigned long cur_mode = efi_table_attr(mode, mode);
|
||||
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
|
||||
u32 max_mode, cur_mode;
|
||||
int pf;
|
||||
efi_pixel_bitmask_t pi;
|
||||
u32 m, w, h;
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
|
||||
cur_mode = efi_table_attr(mode, mode);
|
||||
info = efi_table_attr(mode, info);
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
if (w == cmdline.res.width && h == cmdline.res.height &&
|
||||
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
|
||||
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
|
||||
if (match_res(efi_table_attr(mode, info), cur_mode, NULL))
|
||||
return cur_mode;
|
||||
|
||||
max_mode = efi_table_attr(mode, max_mode);
|
||||
return choose_mode(gop, match_res, (void *)cur_mode);
|
||||
}
|
||||
|
||||
for (m = 0; m < max_mode; m++) {
|
||||
if (m == cur_mode)
|
||||
continue;
|
||||
struct match {
|
||||
u32 mode;
|
||||
u32 area;
|
||||
u8 depth;
|
||||
};
|
||||
|
||||
status = efi_call_proto(gop, query_mode, m,
|
||||
&info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
static bool match_auto(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx)
|
||||
{
|
||||
u32 area = info->horizontal_resolution * info->vertical_resolution;
|
||||
efi_pixel_bitmask_t pi = info->pixel_information;
|
||||
int pf = info->pixel_format;
|
||||
u8 depth = pixel_bpp(pf, pi);
|
||||
struct match *m = ctx;
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
return false;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
if (area > m->area || (area == m->area && depth > m->depth))
|
||||
*m = (struct match){ mode, area, depth };
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
continue;
|
||||
if (w == cmdline.res.width && h == cmdline.res.height &&
|
||||
(cmdline.res.format < 0 || cmdline.res.format == pf) &&
|
||||
(!cmdline.res.depth || cmdline.res.depth == pixel_bpp(pf, pi)))
|
||||
return m;
|
||||
}
|
||||
|
||||
efi_err("Couldn't find requested mode\n");
|
||||
|
||||
return cur_mode;
|
||||
return false;
|
||||
}
|
||||
|
||||
static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
struct match match = {};
|
||||
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
choose_mode(gop, match_auto, &match);
|
||||
|
||||
u32 max_mode, cur_mode, best_mode, area;
|
||||
u8 depth;
|
||||
int pf;
|
||||
efi_pixel_bitmask_t pi;
|
||||
u32 m, w, h, a;
|
||||
u8 d;
|
||||
return match.mode;
|
||||
}
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
static bool match_list(const efi_graphics_output_mode_info_t *info, u32 mode, void *ctx)
|
||||
{
|
||||
efi_pixel_bitmask_t pi = info->pixel_information;
|
||||
u32 cur_mode = (unsigned long)ctx;
|
||||
int pf = info->pixel_format;
|
||||
const char *dstr;
|
||||
u8 depth = 0;
|
||||
bool valid;
|
||||
|
||||
cur_mode = efi_table_attr(mode, mode);
|
||||
max_mode = efi_table_attr(mode, max_mode);
|
||||
valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
|
||||
|
||||
info = efi_table_attr(mode, info);
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
best_mode = cur_mode;
|
||||
area = w * h;
|
||||
depth = pixel_bpp(pf, pi);
|
||||
|
||||
for (m = 0; m < max_mode; m++) {
|
||||
if (m == cur_mode)
|
||||
continue;
|
||||
|
||||
status = efi_call_proto(gop, query_mode, m,
|
||||
&info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
continue;
|
||||
a = w * h;
|
||||
if (a < area)
|
||||
continue;
|
||||
d = pixel_bpp(pf, pi);
|
||||
if (a > area || d > depth) {
|
||||
best_mode = m;
|
||||
area = a;
|
||||
depth = d;
|
||||
}
|
||||
switch (pf) {
|
||||
case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "rgb";
|
||||
break;
|
||||
case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "bgr";
|
||||
break;
|
||||
case PIXEL_BIT_MASK:
|
||||
dstr = "";
|
||||
depth = pixel_bpp(pf, pi);
|
||||
break;
|
||||
case PIXEL_BLT_ONLY:
|
||||
dstr = "blt";
|
||||
break;
|
||||
default:
|
||||
dstr = "xxx";
|
||||
break;
|
||||
}
|
||||
|
||||
return best_mode;
|
||||
efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
|
||||
mode,
|
||||
(mode == cur_mode) ? '*' : ' ',
|
||||
!valid ? '-' : ' ',
|
||||
info->horizontal_resolution,
|
||||
info->vertical_resolution,
|
||||
dstr, depth);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static u32 choose_mode_list(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
|
||||
u32 max_mode, cur_mode;
|
||||
int pf;
|
||||
efi_pixel_bitmask_t pi;
|
||||
u32 m, w, h;
|
||||
u8 d;
|
||||
const char *dstr;
|
||||
bool valid;
|
||||
efi_graphics_output_protocol_mode_t *mode = efi_table_attr(gop, mode);
|
||||
unsigned long cur_mode = efi_table_attr(mode, mode);
|
||||
u32 max_mode = efi_table_attr(mode, max_mode);
|
||||
efi_input_key_t key;
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
|
||||
cur_mode = efi_table_attr(mode, mode);
|
||||
max_mode = efi_table_attr(mode, max_mode);
|
||||
efi_status_t status;
|
||||
|
||||
efi_printk("Available graphics modes are 0-%u\n", max_mode-1);
|
||||
efi_puts(" * = current mode\n"
|
||||
" - = unusable mode\n");
|
||||
for (m = 0; m < max_mode; m++) {
|
||||
status = efi_call_proto(gop, query_mode, m,
|
||||
&info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
|
||||
valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
|
||||
d = 0;
|
||||
switch (pf) {
|
||||
case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "rgb";
|
||||
break;
|
||||
case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
|
||||
dstr = "bgr";
|
||||
break;
|
||||
case PIXEL_BIT_MASK:
|
||||
dstr = "";
|
||||
d = pixel_bpp(pf, pi);
|
||||
break;
|
||||
case PIXEL_BLT_ONLY:
|
||||
dstr = "blt";
|
||||
break;
|
||||
default:
|
||||
dstr = "xxx";
|
||||
break;
|
||||
}
|
||||
|
||||
efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
|
||||
m,
|
||||
m == cur_mode ? '*' : ' ',
|
||||
!valid ? '-' : ' ',
|
||||
w, h, dstr, d);
|
||||
}
|
||||
choose_mode(gop, match_list, (void *)cur_mode);
|
||||
|
||||
efi_puts("\nPress any key to continue (or wait 10 seconds)\n");
|
||||
status = efi_wait_for_key(10 * EFI_USEC_PER_SEC, &key);
|
||||
@@ -461,26 +402,25 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
|
||||
}
|
||||
}
|
||||
|
||||
static efi_graphics_output_protocol_t *
|
||||
find_gop(efi_guid_t *proto, unsigned long size, void **handles)
|
||||
static efi_graphics_output_protocol_t *find_gop(unsigned long num,
|
||||
const efi_handle_t handles[])
|
||||
{
|
||||
efi_graphics_output_protocol_t *first_gop;
|
||||
efi_handle_t h;
|
||||
int i;
|
||||
|
||||
first_gop = NULL;
|
||||
|
||||
for_each_efi_handle(h, handles, size, i) {
|
||||
for_each_efi_handle(h, handles, num) {
|
||||
efi_status_t status;
|
||||
|
||||
efi_graphics_output_protocol_t *gop;
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
|
||||
efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
|
||||
void *dummy = NULL;
|
||||
|
||||
status = efi_bs_call(handle_protocol, h, proto, (void **)&gop);
|
||||
status = efi_bs_call(handle_protocol, h,
|
||||
&EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID,
|
||||
(void **)&gop);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
@@ -500,7 +440,8 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
|
||||
* Once we've found a GOP supporting ConOut,
|
||||
* don't bother looking any further.
|
||||
*/
|
||||
status = efi_bs_call(handle_protocol, h, &conout_proto, &dummy);
|
||||
status = efi_bs_call(handle_protocol, h,
|
||||
&EFI_CONSOLE_OUT_DEVICE_GUID, &dummy);
|
||||
if (status == EFI_SUCCESS)
|
||||
return gop;
|
||||
|
||||
@@ -511,16 +452,22 @@ find_gop(efi_guid_t *proto, unsigned long size, void **handles)
|
||||
return first_gop;
|
||||
}
|
||||
|
||||
static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
unsigned long size, void **handles)
|
||||
efi_status_t efi_setup_gop(struct screen_info *si)
|
||||
{
|
||||
efi_graphics_output_protocol_t *gop;
|
||||
efi_handle_t *handles __free(efi_pool) = NULL;
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
efi_graphics_output_protocol_t *gop;
|
||||
efi_status_t status;
|
||||
unsigned long num;
|
||||
|
||||
gop = find_gop(proto, size, handles);
|
||||
status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL,
|
||||
&EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, NULL, &num,
|
||||
&handles);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* Did we find any GOPs? */
|
||||
gop = find_gop(num, handles);
|
||||
if (!gop)
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
@@ -552,29 +499,3 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have Graphics Output Protocol
|
||||
*/
|
||||
efi_status_t efi_setup_gop(struct screen_info *si, efi_guid_t *proto,
|
||||
unsigned long size)
|
||||
{
|
||||
efi_status_t status;
|
||||
void **gop_handle = NULL;
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
|
||||
(void **)&gop_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, proto, NULL,
|
||||
&size, gop_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_handle;
|
||||
|
||||
status = setup_gop(si, proto, size, gop_handle);
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, gop_handle);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -15,8 +15,31 @@ void *__memmove(void *__dest, const void *__src, size_t count) __alias(memmove);
|
||||
void *__memset(void *s, int c, size_t count) __alias(memset);
|
||||
#endif
|
||||
|
||||
static void *efistub_memmove(u8 *dst, const u8 *src, size_t len)
|
||||
{
|
||||
if (src > dst || dst >= (src + len))
|
||||
for (size_t i = 0; i < len; i++)
|
||||
dst[i] = src[i];
|
||||
else
|
||||
for (ssize_t i = len - 1; i >= 0; i--)
|
||||
dst[i] = src[i];
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void *efistub_memset(void *dst, int c, size_t len)
|
||||
{
|
||||
for (u8 *d = dst; len--; d++)
|
||||
*d = c;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void *memcpy(void *dst, const void *src, size_t len)
|
||||
{
|
||||
if (efi_table_attr(efi_system_table, boottime) == NULL)
|
||||
return efistub_memmove(dst, src, len);
|
||||
|
||||
efi_bs_call(copy_mem, dst, src, len);
|
||||
return dst;
|
||||
}
|
||||
@@ -25,6 +48,9 @@ extern void *memmove(void *dst, const void *src, size_t len) __alias(memcpy);
|
||||
|
||||
void *memset(void *dst, int c, size_t len)
|
||||
{
|
||||
if (efi_table_attr(efi_system_table, boottime) == NULL)
|
||||
return efistub_memset(dst, c, len);
|
||||
|
||||
efi_bs_call(set_mem, dst, len, c & U8_MAX);
|
||||
return dst;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ u32 efi_kaslr_get_phys_seed(efi_handle_t image_handle)
|
||||
*/
|
||||
static bool check_image_region(u64 base, u64 size)
|
||||
{
|
||||
struct efi_boot_memmap *map;
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
bool ret = false;
|
||||
int map_offset;
|
||||
@@ -80,8 +80,6 @@ static bool check_image_region(u64 base, u64 size)
|
||||
}
|
||||
}
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
|
||||
bool install_cfg_tbl)
|
||||
{
|
||||
struct efi_boot_memmap tmp, *m __free(efi_pool) = NULL;
|
||||
int memtype = install_cfg_tbl ? EFI_ACPI_RECLAIM_MEMORY
|
||||
: EFI_LOADER_DATA;
|
||||
efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID;
|
||||
struct efi_boot_memmap *m, tmp;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
|
||||
@@ -48,24 +48,20 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map,
|
||||
*/
|
||||
status = efi_bs_call(install_configuration_table, &tbl_guid, m);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_map;
|
||||
return status;
|
||||
}
|
||||
|
||||
m->buff_size = m->map_size = size;
|
||||
status = efi_bs_call(get_memory_map, &m->map_size, m->map, &m->map_key,
|
||||
&m->desc_size, &m->desc_ver);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto uninstall_table;
|
||||
if (status != EFI_SUCCESS) {
|
||||
if (install_cfg_tbl)
|
||||
efi_bs_call(install_configuration_table, &tbl_guid, NULL);
|
||||
return status;
|
||||
}
|
||||
|
||||
*map = m;
|
||||
*map = no_free_ptr(m);
|
||||
return EFI_SUCCESS;
|
||||
|
||||
uninstall_table:
|
||||
if (install_cfg_tbl)
|
||||
efi_bs_call(install_configuration_table, &tbl_guid, NULL);
|
||||
free_map:
|
||||
efi_bs_call(free_pool, m);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,37 +16,20 @@
|
||||
void efi_pci_disable_bridge_busmaster(void)
|
||||
{
|
||||
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
unsigned long pci_handle_size = 0;
|
||||
efi_handle_t *pci_handle = NULL;
|
||||
efi_handle_t *pci_handle __free(efi_pool) = NULL;
|
||||
unsigned long pci_handle_num;
|
||||
efi_handle_t handle;
|
||||
efi_status_t status;
|
||||
u16 class, command;
|
||||
int i;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||
NULL, &pci_handle_size, NULL);
|
||||
|
||||
if (status != EFI_BUFFER_TOO_SMALL) {
|
||||
if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
|
||||
efi_err("Failed to locate PCI I/O handles'\n");
|
||||
status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &pci_handle_num, &pci_handle);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to locate PCI I/O handles\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, pci_handle_size,
|
||||
(void **)&pci_handle);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate memory for 'pci_handle'\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
|
||||
NULL, &pci_handle_size, pci_handle);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to locate PCI I/O handles'\n");
|
||||
goto free_handle;
|
||||
}
|
||||
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_num) {
|
||||
efi_pci_io_protocol_t *pci;
|
||||
unsigned long segment_nr, bus_nr, device_nr, func_nr;
|
||||
|
||||
@@ -82,7 +65,7 @@ void efi_pci_disable_bridge_busmaster(void)
|
||||
efi_bs_call(disconnect_controller, handle, NULL, NULL);
|
||||
}
|
||||
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_size, i) {
|
||||
for_each_efi_handle(handle, pci_handle, pci_handle_num) {
|
||||
efi_pci_io_protocol_t *pci;
|
||||
|
||||
status = efi_bs_call(handle_protocol, handle, &pci_proto,
|
||||
@@ -108,7 +91,4 @@ void efi_pci_disable_bridge_busmaster(void)
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_err("Failed to disable PCI busmastering\n");
|
||||
}
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, pci_handle);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */
|
||||
#include <linux/kern_levels.h>
|
||||
#include <asm/efi.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
|
||||
int efi_loglevel = LOGLEVEL_NOTICE;
|
||||
|
||||
/**
|
||||
* efi_char16_puts() - Write a UCS-2 encoded string to the console
|
||||
|
||||
@@ -25,6 +25,9 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
|
||||
if (md->type != EFI_CONVENTIONAL_MEMORY)
|
||||
return 0;
|
||||
|
||||
if (md->attribute & EFI_MEMORY_HOT_PLUGGABLE)
|
||||
return 0;
|
||||
|
||||
if (efi_soft_reserve_enabled() &&
|
||||
(md->attribute & EFI_MEMORY_SP))
|
||||
return 0;
|
||||
@@ -59,9 +62,9 @@ efi_status_t efi_random_alloc(unsigned long size,
|
||||
unsigned long alloc_min,
|
||||
unsigned long alloc_max)
|
||||
{
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
unsigned long total_slots = 0, target_slot;
|
||||
unsigned long total_mirrored_slots = 0;
|
||||
struct efi_boot_memmap *map;
|
||||
efi_status_t status;
|
||||
int map_offset;
|
||||
|
||||
@@ -72,6 +75,10 @@ efi_status_t efi_random_alloc(unsigned long size,
|
||||
if (align < EFI_ALLOC_ALIGN)
|
||||
align = EFI_ALLOC_ALIGN;
|
||||
|
||||
/* Avoid address 0x0, as it can be mistaken for NULL */
|
||||
if (alloc_min == 0)
|
||||
alloc_min = align;
|
||||
|
||||
size = round_up(size, EFI_ALLOC_ALIGN);
|
||||
|
||||
/* count the suitable slots in each memory map entry */
|
||||
@@ -130,7 +137,5 @@ efi_status_t efi_random_alloc(unsigned long size,
|
||||
break;
|
||||
}
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
unsigned long *addr, unsigned long min)
|
||||
{
|
||||
struct efi_boot_memmap *map;
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long nr_pages;
|
||||
int i;
|
||||
|
||||
status = efi_get_memory_map(&map, false);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto fail;
|
||||
return status;
|
||||
|
||||
/*
|
||||
* Enforce minimum alignment that EFI or Linux requires when
|
||||
@@ -53,6 +53,9 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
if (desc->type != EFI_CONVENTIONAL_MEMORY)
|
||||
continue;
|
||||
|
||||
if (desc->attribute & EFI_MEMORY_HOT_PLUGGABLE)
|
||||
continue;
|
||||
|
||||
if (efi_soft_reserve_enabled() &&
|
||||
(desc->attribute & EFI_MEMORY_SP))
|
||||
continue;
|
||||
@@ -79,11 +82,9 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
|
||||
}
|
||||
|
||||
if (i == map->map_size / map->desc_size)
|
||||
status = EFI_NOT_FOUND;
|
||||
return EFI_NOT_FOUND;
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
fail:
|
||||
return status;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,7 @@ union sev_memory_acceptance_protocol {
|
||||
static efi_status_t
|
||||
preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
|
||||
{
|
||||
struct pci_setup_rom *rom = NULL;
|
||||
struct pci_setup_rom *rom __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
uint64_t romsize;
|
||||
@@ -75,14 +75,13 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
|
||||
rom->data.len = size - sizeof(struct setup_data);
|
||||
rom->data.next = 0;
|
||||
rom->pcilen = romsize;
|
||||
*__rom = rom;
|
||||
|
||||
status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
|
||||
PCI_VENDOR_ID, 1, &rom->vendor);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to read rom->vendor\n");
|
||||
goto free_struct;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16,
|
||||
@@ -90,21 +89,18 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to read rom->devid\n");
|
||||
goto free_struct;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = efi_call_proto(pci, get_location, &rom->segment, &rom->bus,
|
||||
&rom->device, &rom->function);
|
||||
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_struct;
|
||||
return status;
|
||||
|
||||
memcpy(rom->romdata, romimage, romsize);
|
||||
return status;
|
||||
|
||||
free_struct:
|
||||
efi_bs_call(free_pool, rom);
|
||||
return status;
|
||||
*__rom = no_free_ptr(rom);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -119,38 +115,23 @@ free_struct:
|
||||
static void setup_efi_pci(struct boot_params *params)
|
||||
{
|
||||
efi_status_t status;
|
||||
void **pci_handle = NULL;
|
||||
efi_handle_t *pci_handle __free(efi_pool) = NULL;
|
||||
efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
unsigned long size = 0;
|
||||
struct setup_data *data;
|
||||
unsigned long num;
|
||||
efi_handle_t h;
|
||||
int i;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &size, pci_handle);
|
||||
|
||||
if (status == EFI_BUFFER_TOO_SMALL) {
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
|
||||
(void **)&pci_handle);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate memory for 'pci_handle'\n");
|
||||
return;
|
||||
}
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &size, pci_handle);
|
||||
}
|
||||
|
||||
status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL,
|
||||
&pci_proto, NULL, &num, &pci_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_handle;
|
||||
return;
|
||||
|
||||
data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
|
||||
|
||||
while (data && data->next)
|
||||
data = (struct setup_data *)(unsigned long)data->next;
|
||||
|
||||
for_each_efi_handle(h, pci_handle, size, i) {
|
||||
for_each_efi_handle(h, pci_handle, num) {
|
||||
efi_pci_io_protocol_t *pci = NULL;
|
||||
struct pci_setup_rom *rom;
|
||||
|
||||
@@ -170,9 +151,6 @@ static void setup_efi_pci(struct boot_params *params)
|
||||
|
||||
data = (struct setup_data *)rom;
|
||||
}
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, pci_handle);
|
||||
}
|
||||
|
||||
static void retrieve_apple_device_properties(struct boot_params *boot_params)
|
||||
@@ -407,116 +385,13 @@ static void setup_quirks(struct boot_params *boot_params)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we have Universal Graphics Adapter (UGA) protocol
|
||||
*/
|
||||
static efi_status_t
|
||||
setup_uga(struct screen_info *si, efi_guid_t *uga_proto, unsigned long size)
|
||||
{
|
||||
efi_status_t status;
|
||||
u32 width, height;
|
||||
void **uga_handle = NULL;
|
||||
efi_uga_draw_protocol_t *uga = NULL, *first_uga;
|
||||
efi_handle_t handle;
|
||||
int i;
|
||||
|
||||
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
|
||||
(void **)&uga_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
uga_proto, NULL, &size, uga_handle);
|
||||
if (status != EFI_SUCCESS)
|
||||
goto free_handle;
|
||||
|
||||
height = 0;
|
||||
width = 0;
|
||||
|
||||
first_uga = NULL;
|
||||
for_each_efi_handle(handle, uga_handle, size, i) {
|
||||
efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
u32 w, h, depth, refresh;
|
||||
void *pciio;
|
||||
|
||||
status = efi_bs_call(handle_protocol, handle, uga_proto,
|
||||
(void **)&uga);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
pciio = NULL;
|
||||
efi_bs_call(handle_protocol, handle, &pciio_proto, &pciio);
|
||||
|
||||
status = efi_call_proto(uga, get_mode, &w, &h, &depth, &refresh);
|
||||
if (status == EFI_SUCCESS && (!first_uga || pciio)) {
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
/*
|
||||
* Once we've found a UGA supporting PCIIO,
|
||||
* don't bother looking any further.
|
||||
*/
|
||||
if (pciio)
|
||||
break;
|
||||
|
||||
first_uga = uga;
|
||||
}
|
||||
}
|
||||
|
||||
if (!width && !height)
|
||||
goto free_handle;
|
||||
|
||||
/* EFI framebuffer */
|
||||
si->orig_video_isVGA = VIDEO_TYPE_EFI;
|
||||
|
||||
si->lfb_depth = 32;
|
||||
si->lfb_width = width;
|
||||
si->lfb_height = height;
|
||||
|
||||
si->red_size = 8;
|
||||
si->red_pos = 16;
|
||||
si->green_size = 8;
|
||||
si->green_pos = 8;
|
||||
si->blue_size = 8;
|
||||
si->blue_pos = 0;
|
||||
si->rsvd_size = 8;
|
||||
si->rsvd_pos = 24;
|
||||
|
||||
free_handle:
|
||||
efi_bs_call(free_pool, uga_handle);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void setup_graphics(struct boot_params *boot_params)
|
||||
{
|
||||
efi_guid_t graphics_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
struct screen_info *si;
|
||||
efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
|
||||
efi_status_t status;
|
||||
unsigned long size;
|
||||
void **gop_handle = NULL;
|
||||
void **uga_handle = NULL;
|
||||
struct screen_info *si = memset(&boot_params->screen_info, 0, sizeof(*si));
|
||||
|
||||
si = &boot_params->screen_info;
|
||||
memset(si, 0, sizeof(*si));
|
||||
|
||||
size = 0;
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&graphics_proto, NULL, &size, gop_handle);
|
||||
if (status == EFI_BUFFER_TOO_SMALL)
|
||||
status = efi_setup_gop(si, &graphics_proto, size);
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
size = 0;
|
||||
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL,
|
||||
&uga_proto, NULL, &size, uga_handle);
|
||||
if (status == EFI_BUFFER_TOO_SMALL)
|
||||
setup_uga(si, &uga_proto, size);
|
||||
}
|
||||
efi_setup_gop(si);
|
||||
}
|
||||
|
||||
|
||||
static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
|
||||
{
|
||||
efi_bs_call(exit, handle, status, 0, NULL);
|
||||
@@ -524,41 +399,30 @@ static void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
void __noreturn efi_stub_entry(efi_handle_t handle,
|
||||
efi_system_table_t *sys_table_arg,
|
||||
struct boot_params *boot_params);
|
||||
|
||||
/*
|
||||
* Because the x86 boot code expects to be passed a boot_params we
|
||||
* need to create one ourselves (usually the bootloader would create
|
||||
* one for us).
|
||||
*/
|
||||
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
efi_system_table_t *sys_table_arg)
|
||||
static efi_status_t efi_allocate_bootparams(efi_handle_t handle,
|
||||
struct boot_params **bp)
|
||||
{
|
||||
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
|
||||
struct boot_params *boot_params;
|
||||
struct setup_header *hdr;
|
||||
int options_size = 0;
|
||||
efi_status_t status;
|
||||
unsigned long alloc;
|
||||
char *cmdline_ptr;
|
||||
|
||||
efi_system_table = sys_table_arg;
|
||||
|
||||
/* Check if we were booted by the EFI firmware */
|
||||
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
|
||||
efi_exit(handle, EFI_INVALID_PARAMETER);
|
||||
|
||||
status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
|
||||
efi_exit(handle, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = efi_allocate_pages(PARAM_SIZE, &alloc, ULONG_MAX);
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_exit(handle, status);
|
||||
return status;
|
||||
|
||||
boot_params = memset((void *)alloc, 0x0, PARAM_SIZE);
|
||||
hdr = &boot_params->hdr;
|
||||
@@ -571,17 +435,17 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
hdr->initrd_addr_max = INT_MAX;
|
||||
|
||||
/* Convert unicode cmdline to ascii */
|
||||
cmdline_ptr = efi_convert_cmdline(image, &options_size);
|
||||
cmdline_ptr = efi_convert_cmdline(image);
|
||||
if (!cmdline_ptr) {
|
||||
efi_free(PARAM_SIZE, alloc);
|
||||
efi_exit(handle, EFI_OUT_OF_RESOURCES);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
|
||||
&boot_params->ext_cmd_line_ptr);
|
||||
|
||||
efi_stub_entry(handle, sys_table_arg, boot_params);
|
||||
/* not reached */
|
||||
*bp = boot_params;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
static void add_e820ext(struct boot_params *params,
|
||||
@@ -740,7 +604,7 @@ static efi_status_t allocate_e820(struct boot_params *params,
|
||||
struct setup_data **e820ext,
|
||||
u32 *e820ext_size)
|
||||
{
|
||||
struct efi_boot_memmap *map;
|
||||
struct efi_boot_memmap *map __free(efi_pool) = NULL;
|
||||
efi_status_t status;
|
||||
__u32 nr_desc;
|
||||
|
||||
@@ -754,13 +618,14 @@ static efi_status_t allocate_e820(struct boot_params *params,
|
||||
EFI_MMAP_NR_SLACK_SLOTS;
|
||||
|
||||
status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY) && status == EFI_SUCCESS)
|
||||
status = allocate_unaccepted_bitmap(nr_desc, map);
|
||||
if (IS_ENABLED(CONFIG_UNACCEPTED_MEMORY))
|
||||
return allocate_unaccepted_bitmap(nr_desc, map);
|
||||
|
||||
efi_bs_call(free_pool, map);
|
||||
return status;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
struct exit_boot_struct {
|
||||
@@ -867,13 +732,16 @@ static efi_status_t parse_options(const char *cmdline)
|
||||
return efi_parse_options(cmdline);
|
||||
}
|
||||
|
||||
static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
|
||||
static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry,
|
||||
struct boot_params *boot_params)
|
||||
{
|
||||
unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
|
||||
unsigned long addr, alloc_size, entry;
|
||||
efi_status_t status;
|
||||
u32 seed[2] = {};
|
||||
|
||||
boot_params_ptr = boot_params;
|
||||
|
||||
/* determine the required size of the allocation */
|
||||
alloc_size = ALIGN(max_t(unsigned long, output_len, kernel_total_size),
|
||||
MIN_KERNEL_ALIGN);
|
||||
@@ -904,7 +772,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
|
||||
seed[0] = 0;
|
||||
}
|
||||
|
||||
boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
|
||||
boot_params->hdr.loadflags |= KASLR_FLAG;
|
||||
}
|
||||
|
||||
status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr,
|
||||
@@ -942,20 +810,27 @@ static void __noreturn enter_kernel(unsigned long kernel_addr,
|
||||
void __noreturn efi_stub_entry(efi_handle_t handle,
|
||||
efi_system_table_t *sys_table_arg,
|
||||
struct boot_params *boot_params)
|
||||
|
||||
{
|
||||
efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID;
|
||||
struct setup_header *hdr = &boot_params->hdr;
|
||||
const struct linux_efi_initrd *initrd = NULL;
|
||||
unsigned long kernel_entry;
|
||||
struct setup_header *hdr;
|
||||
efi_status_t status;
|
||||
|
||||
boot_params_ptr = boot_params;
|
||||
|
||||
efi_system_table = sys_table_arg;
|
||||
/* Check if we were booted by the EFI firmware */
|
||||
if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
|
||||
efi_exit(handle, EFI_INVALID_PARAMETER);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL) || !boot_params) {
|
||||
status = efi_allocate_bootparams(handle, &boot_params);
|
||||
if (status != EFI_SUCCESS)
|
||||
efi_exit(handle, status);
|
||||
}
|
||||
|
||||
hdr = &boot_params->hdr;
|
||||
|
||||
if (have_unsupported_snp_features())
|
||||
efi_exit(handle, EFI_UNSUPPORTED);
|
||||
|
||||
@@ -997,7 +872,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
|
||||
if (efi_mem_encrypt > 0)
|
||||
hdr->xloadflags |= XLF_MEM_ENCRYPTION;
|
||||
|
||||
status = efi_decompress_kernel(&kernel_entry);
|
||||
status = efi_decompress_kernel(&kernel_entry, boot_params);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to decompress kernel\n");
|
||||
goto fail;
|
||||
@@ -1067,6 +942,12 @@ fail:
|
||||
efi_exit(handle, status);
|
||||
}
|
||||
|
||||
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
efi_system_table_t *sys_table_arg)
|
||||
{
|
||||
efi_stub_entry(handle, sys_table_arg, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
|
||||
void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
|
||||
struct boot_params *boot_params)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/zlib.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
#include "inftrees.c"
|
||||
#include "inffast.c"
|
||||
#include "inflate.c"
|
||||
|
||||
extern unsigned char _gzdata_start[], _gzdata_end[];
|
||||
extern u32 __aligned(1) payload_size;
|
||||
|
||||
static struct z_stream_s stream;
|
||||
|
||||
efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
|
||||
{
|
||||
efi_status_t status;
|
||||
int rc;
|
||||
|
||||
/* skip the 10 byte header, assume no recorded filename */
|
||||
stream.next_in = _gzdata_start + 10;
|
||||
stream.avail_in = _gzdata_end - stream.next_in;
|
||||
|
||||
status = efi_allocate_pages(zlib_inflate_workspacesize(),
|
||||
(unsigned long *)&stream.workspace,
|
||||
ULONG_MAX);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
rc = zlib_inflateInit2(&stream, -MAX_WBITS);
|
||||
if (rc != Z_OK) {
|
||||
efi_err("failed to initialize GZIP decompressor: %d\n", rc);
|
||||
status = EFI_LOAD_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*alloc_size = payload_size;
|
||||
return EFI_SUCCESS;
|
||||
out:
|
||||
efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
|
||||
return status;
|
||||
}
|
||||
|
||||
efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
|
||||
{
|
||||
int rc;
|
||||
|
||||
stream.next_out = out;
|
||||
stream.avail_out = outlen;
|
||||
|
||||
rc = zlib_inflate(&stream, 0);
|
||||
zlib_inflateEnd(&stream);
|
||||
|
||||
efi_free(zlib_inflate_workspacesize(), (unsigned long)stream.workspace);
|
||||
|
||||
if (rc != Z_STREAM_END) {
|
||||
efi_err("GZIP decompression failed with status %d\n", rc);
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
efi_cache_sync_image((unsigned long)out, outlen);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/zstd.h>
|
||||
|
||||
#include <asm/efi.h>
|
||||
|
||||
#include "decompress_sources.h"
|
||||
#include "efistub.h"
|
||||
|
||||
extern unsigned char _gzdata_start[], _gzdata_end[];
|
||||
extern u32 __aligned(1) payload_size;
|
||||
|
||||
static size_t wksp_size;
|
||||
static void *wksp;
|
||||
|
||||
efi_status_t efi_zboot_decompress_init(unsigned long *alloc_size)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
wksp_size = zstd_dctx_workspace_bound();
|
||||
status = efi_allocate_pages(wksp_size, (unsigned long *)&wksp, ULONG_MAX);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
*alloc_size = payload_size;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
efi_status_t efi_zboot_decompress(u8 *out, unsigned long outlen)
|
||||
{
|
||||
zstd_dctx *dctx = zstd_init_dctx(wksp, wksp_size);
|
||||
size_t ret;
|
||||
int retval;
|
||||
|
||||
ret = zstd_decompress_dctx(dctx, out, outlen, _gzdata_start,
|
||||
_gzdata_end - _gzdata_start - 4);
|
||||
efi_free(wksp_size, (unsigned long)wksp);
|
||||
|
||||
retval = zstd_get_error_code(ret);
|
||||
if (retval) {
|
||||
efi_err("ZSTD-decompression failed with status %d\n", retval);
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
efi_cache_sync_image((unsigned long)out, outlen);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
@@ -4,17 +4,17 @@
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
.set .Lextra_characteristics, 0x0
|
||||
.set .Lpe_opt_magic, PE_OPT_MAGIC_PE32PLUS
|
||||
.set .Lpe_opt_magic, IMAGE_NT_OPTIONAL_HDR64_MAGIC
|
||||
#else
|
||||
.set .Lextra_characteristics, IMAGE_FILE_32BIT_MACHINE
|
||||
.set .Lpe_opt_magic, PE_OPT_MAGIC_PE32
|
||||
.set .Lpe_opt_magic, IMAGE_NT_OPTIONAL_HDR32_MAGIC
|
||||
#endif
|
||||
|
||||
.section ".head", "a"
|
||||
.globl __efistub_efi_zboot_header
|
||||
__efistub_efi_zboot_header:
|
||||
.Ldoshdr:
|
||||
.long MZ_MAGIC
|
||||
.long IMAGE_DOS_SIGNATURE
|
||||
.ascii "zimg" // image type
|
||||
.long __efistub__gzdata_start - .Ldoshdr // payload offset
|
||||
.long __efistub__gzdata_size - ZBOOT_SIZE_LEN // payload size
|
||||
@@ -25,7 +25,7 @@ __efistub_efi_zboot_header:
|
||||
.long .Lpehdr - .Ldoshdr // PE header offset
|
||||
|
||||
.Lpehdr:
|
||||
.long PE_MAGIC
|
||||
.long IMAGE_NT_SIGNATURE
|
||||
.short MACHINE_TYPE
|
||||
.short .Lsection_count
|
||||
.long 0
|
||||
@@ -63,7 +63,7 @@ __efistub_efi_zboot_header:
|
||||
.long .Lefi_header_end - .Ldoshdr
|
||||
.long 0
|
||||
.short IMAGE_SUBSYSTEM_EFI_APPLICATION
|
||||
.short IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
|
||||
.short IMAGE_DLLCHARACTERISTICS_NX_COMPAT
|
||||
#ifdef CONFIG_64BIT
|
||||
.quad 0, 0, 0, 0
|
||||
#else
|
||||
|
||||
@@ -7,36 +7,6 @@
|
||||
|
||||
#include "efistub.h"
|
||||
|
||||
static unsigned char zboot_heap[SZ_256K] __aligned(64);
|
||||
static unsigned long free_mem_ptr, free_mem_end_ptr;
|
||||
|
||||
#define STATIC static
|
||||
#if defined(CONFIG_KERNEL_GZIP)
|
||||
#include "../../../../lib/decompress_inflate.c"
|
||||
#elif defined(CONFIG_KERNEL_LZ4)
|
||||
#include "../../../../lib/decompress_unlz4.c"
|
||||
#elif defined(CONFIG_KERNEL_LZMA)
|
||||
#include "../../../../lib/decompress_unlzma.c"
|
||||
#elif defined(CONFIG_KERNEL_LZO)
|
||||
#include "../../../../lib/decompress_unlzo.c"
|
||||
#elif defined(CONFIG_KERNEL_XZ)
|
||||
#undef memcpy
|
||||
#define memcpy memcpy
|
||||
#undef memmove
|
||||
#define memmove memmove
|
||||
#include "../../../../lib/decompress_unxz.c"
|
||||
#elif defined(CONFIG_KERNEL_ZSTD)
|
||||
#include "../../../../lib/decompress_unzstd.c"
|
||||
#endif
|
||||
|
||||
extern char efi_zboot_header[];
|
||||
extern char _gzdata_start[], _gzdata_end[];
|
||||
|
||||
static void error(char *x)
|
||||
{
|
||||
efi_err("EFI decompressor: %s\n", x);
|
||||
}
|
||||
|
||||
static unsigned long alloc_preferred_address(unsigned long alloc_size)
|
||||
{
|
||||
#ifdef EFI_KIMG_PREFERRED_ADDRESS
|
||||
@@ -64,22 +34,17 @@ struct screen_info *alloc_screen_info(void)
|
||||
asmlinkage efi_status_t __efiapi
|
||||
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
||||
{
|
||||
unsigned long compressed_size = _gzdata_end - _gzdata_start;
|
||||
char *cmdline_ptr __free(efi_pool) = NULL;
|
||||
unsigned long image_base, alloc_size;
|
||||
efi_loaded_image_t *image;
|
||||
efi_status_t status;
|
||||
char *cmdline_ptr;
|
||||
int ret;
|
||||
|
||||
WRITE_ONCE(efi_system_table, systab);
|
||||
|
||||
free_mem_ptr = (unsigned long)&zboot_heap;
|
||||
free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
|
||||
|
||||
status = efi_bs_call(handle_protocol, handle,
|
||||
&LOADED_IMAGE_PROTOCOL_GUID, (void **)&image);
|
||||
if (status != EFI_SUCCESS) {
|
||||
error("Failed to locate parent's loaded image protocol");
|
||||
efi_err("Failed to locate parent's loaded image protocol\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -89,9 +54,9 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
||||
|
||||
efi_info("Decompressing Linux Kernel...\n");
|
||||
|
||||
// SizeOfImage from the compressee's PE/COFF header
|
||||
alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
|
||||
EFI_ALLOC_ALIGN);
|
||||
status = efi_zboot_decompress_init(&alloc_size);
|
||||
if (status != EFI_SUCCESS)
|
||||
return status;
|
||||
|
||||
// If the architecture has a preferred address for the image,
|
||||
// try that first.
|
||||
@@ -122,26 +87,14 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
|
||||
seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT);
|
||||
if (status != EFI_SUCCESS) {
|
||||
efi_err("Failed to allocate memory\n");
|
||||
goto free_cmdline;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Decompress the payload into the newly allocated buffer.
|
||||
ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
|
||||
(void *)image_base, alloc_size, NULL, error);
|
||||
if (ret < 0) {
|
||||
error("Decompression failed");
|
||||
status = EFI_DEVICE_ERROR;
|
||||
goto free_image;
|
||||
}
|
||||
// Decompress the payload into the newly allocated buffer
|
||||
status = efi_zboot_decompress((void *)image_base, alloc_size) ?:
|
||||
efi_stub_common(handle, image, image_base, cmdline_ptr);
|
||||
|
||||
efi_cache_sync_image(image_base, alloc_size);
|
||||
|
||||
status = efi_stub_common(handle, image, image_base, cmdline_ptr);
|
||||
|
||||
free_image:
|
||||
efi_free(alloc_size, image_base);
|
||||
free_cmdline:
|
||||
efi_bs_call(free_pool, cmdline_ptr);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ SECTIONS
|
||||
.rodata : ALIGN(8) {
|
||||
__efistub__gzdata_start = .;
|
||||
*(.gzdata)
|
||||
__efistub_payload_size = . - 4;
|
||||
__efistub__gzdata_end = .;
|
||||
*(.rodata* .init.rodata* .srodata*)
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ unsigned long __ro_after_init efi_mem_attr_table = EFI_INVALID_TABLE_ADDR;
|
||||
int __init efi_memattr_init(void)
|
||||
{
|
||||
efi_memory_attributes_table_t *tbl;
|
||||
unsigned long size;
|
||||
|
||||
if (efi_mem_attr_table == EFI_INVALID_TABLE_ADDR)
|
||||
return 0;
|
||||
@@ -39,7 +40,22 @@ int __init efi_memattr_init(void)
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
|
||||
|
||||
/*
|
||||
* Sanity check: the Memory Attributes Table contains up to 3 entries
|
||||
* for each entry of type EfiRuntimeServicesCode in the EFI memory map.
|
||||
* So if the size of the table exceeds 3x the size of the entire EFI
|
||||
* memory map, there is clearly something wrong, and the table should
|
||||
* just be ignored altogether.
|
||||
*/
|
||||
size = tbl->num_entries * tbl->desc_size;
|
||||
if (size > 3 * efi.memmap.nr_map * efi.memmap.desc_size) {
|
||||
pr_warn(FW_BUG "Corrupted EFI Memory Attributes Table detected! (version == %u, desc_size == %u, num_entries == %u)\n",
|
||||
tbl->version, tbl->desc_size, tbl->num_entries);
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
tbl_size = sizeof(*tbl) + size;
|
||||
memblock_reserve(efi_mem_attr_table, tbl_size);
|
||||
set_bit(EFI_MEM_ATTR, &efi.flags);
|
||||
|
||||
|
||||
@@ -43,7 +43,8 @@ int __init __efi_memmap_init(struct efi_memory_map_data *data)
|
||||
map.map = early_memremap(phys_map, data->size);
|
||||
|
||||
if (!map.map) {
|
||||
pr_err("Could not map the memory map!\n");
|
||||
pr_err("Could not map the memory map! phys_map=%pa, size=0x%lx\n",
|
||||
&phys_map, data->size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,14 +99,13 @@ static struct kobject *mokvar_kobj;
|
||||
*/
|
||||
void __init efi_mokvar_table_init(void)
|
||||
{
|
||||
struct efi_mokvar_table_entry __aligned(1) *mokvar_entry, *next_entry;
|
||||
efi_memory_desc_t md;
|
||||
void *va = NULL;
|
||||
unsigned long cur_offset = 0;
|
||||
unsigned long offset_limit;
|
||||
unsigned long map_size = 0;
|
||||
unsigned long map_size_needed = 0;
|
||||
unsigned long size;
|
||||
struct efi_mokvar_table_entry *mokvar_entry;
|
||||
int err;
|
||||
|
||||
if (!efi_enabled(EFI_MEMMAP))
|
||||
@@ -134,48 +133,46 @@ void __init efi_mokvar_table_init(void)
|
||||
*/
|
||||
err = -EINVAL;
|
||||
while (cur_offset + sizeof(*mokvar_entry) <= offset_limit) {
|
||||
mokvar_entry = va + cur_offset;
|
||||
map_size_needed = cur_offset + sizeof(*mokvar_entry);
|
||||
if (map_size_needed > map_size) {
|
||||
if (va)
|
||||
early_memunmap(va, map_size);
|
||||
/*
|
||||
* Map a little more than the fixed size entry
|
||||
* header, anticipating some data. It's safe to
|
||||
* do so as long as we stay within current memory
|
||||
* descriptor.
|
||||
*/
|
||||
map_size = min(map_size_needed + 2*EFI_PAGE_SIZE,
|
||||
offset_limit);
|
||||
va = early_memremap(efi.mokvar_table, map_size);
|
||||
if (!va) {
|
||||
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n",
|
||||
efi.mokvar_table, map_size);
|
||||
return;
|
||||
}
|
||||
mokvar_entry = va + cur_offset;
|
||||
if (va)
|
||||
early_memunmap(va, sizeof(*mokvar_entry));
|
||||
va = early_memremap(efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
|
||||
if (!va) {
|
||||
pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%zu.\n",
|
||||
efi.mokvar_table + cur_offset, sizeof(*mokvar_entry));
|
||||
return;
|
||||
}
|
||||
|
||||
mokvar_entry = va;
|
||||
next:
|
||||
/* Check for last sentinel entry */
|
||||
if (mokvar_entry->name[0] == '\0') {
|
||||
if (mokvar_entry->data_size != 0)
|
||||
break;
|
||||
err = 0;
|
||||
map_size_needed = cur_offset + sizeof(*mokvar_entry);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Sanity check that the name is null terminated */
|
||||
size = strnlen(mokvar_entry->name,
|
||||
sizeof(mokvar_entry->name));
|
||||
if (size >= sizeof(mokvar_entry->name))
|
||||
break;
|
||||
/* Enforce that the name is NUL terminated */
|
||||
mokvar_entry->name[sizeof(mokvar_entry->name) - 1] = '\0';
|
||||
|
||||
/* Advance to the next entry */
|
||||
cur_offset = map_size_needed + mokvar_entry->data_size;
|
||||
size = sizeof(*mokvar_entry) + mokvar_entry->data_size;
|
||||
cur_offset += size;
|
||||
|
||||
/*
|
||||
* Don't bother remapping if the current entry header and the
|
||||
* next one end on the same page.
|
||||
*/
|
||||
next_entry = (void *)((unsigned long)mokvar_entry + size);
|
||||
if (((((unsigned long)(mokvar_entry + 1) - 1) ^
|
||||
((unsigned long)(next_entry + 1) - 1)) & PAGE_MASK) == 0) {
|
||||
mokvar_entry = next_entry;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
if (va)
|
||||
early_memunmap(va, map_size);
|
||||
early_memunmap(va, sizeof(*mokvar_entry));
|
||||
if (err) {
|
||||
pr_err("EFI MOKvar config table is not valid\n");
|
||||
return;
|
||||
|
||||
@@ -40,7 +40,7 @@ static u8 *rci2_base;
|
||||
static u32 rci2_table_len;
|
||||
unsigned long rci2_table_phys __ro_after_init = EFI_INVALID_TABLE_ADDR;
|
||||
|
||||
static BIN_ATTR_SIMPLE_ADMIN_RO(rci2);
|
||||
static __ro_after_init BIN_ATTR_SIMPLE_ADMIN_RO(rci2);
|
||||
|
||||
static u16 checksum(void)
|
||||
{
|
||||
|
||||
@@ -143,6 +143,10 @@ static efi_status_t mm_communicate(u8 *comm_buf, size_t payload_size)
|
||||
return var_hdr->ret_status;
|
||||
}
|
||||
|
||||
#define COMM_BUF_SIZE(__payload_size) (MM_COMMUNICATE_HEADER_SIZE + \
|
||||
MM_VARIABLE_COMMUNICATE_SIZE + \
|
||||
(__payload_size))
|
||||
|
||||
/**
|
||||
* setup_mm_hdr() - Allocate a buffer for StandAloneMM and initialize the
|
||||
* header data.
|
||||
@@ -150,11 +154,9 @@ static efi_status_t mm_communicate(u8 *comm_buf, size_t payload_size)
|
||||
* @dptr: pointer address to store allocated buffer
|
||||
* @payload_size: payload size
|
||||
* @func: standAloneMM function number
|
||||
* @ret: EFI return code
|
||||
* Return: pointer to corresponding StandAloneMM function buffer or NULL
|
||||
*/
|
||||
static void *setup_mm_hdr(u8 **dptr, size_t payload_size, size_t func,
|
||||
efi_status_t *ret)
|
||||
static void *setup_mm_hdr(u8 **dptr, size_t payload_size, size_t func)
|
||||
{
|
||||
const efi_guid_t mm_var_guid = EFI_MM_VARIABLE_GUID;
|
||||
struct efi_mm_communicate_header *mm_hdr;
|
||||
@@ -169,17 +171,13 @@ static void *setup_mm_hdr(u8 **dptr, size_t payload_size, size_t func,
|
||||
if (max_buffer_size &&
|
||||
max_buffer_size < (MM_COMMUNICATE_HEADER_SIZE +
|
||||
MM_VARIABLE_COMMUNICATE_SIZE + payload_size)) {
|
||||
*ret = EFI_INVALID_PARAMETER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
comm_buf = kzalloc(MM_COMMUNICATE_HEADER_SIZE +
|
||||
MM_VARIABLE_COMMUNICATE_SIZE + payload_size,
|
||||
GFP_KERNEL);
|
||||
if (!comm_buf) {
|
||||
*ret = EFI_OUT_OF_RESOURCES;
|
||||
comm_buf = alloc_pages_exact(COMM_BUF_SIZE(payload_size),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!comm_buf)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mm_hdr = (struct efi_mm_communicate_header *)comm_buf;
|
||||
memcpy(&mm_hdr->header_guid, &mm_var_guid, sizeof(mm_hdr->header_guid));
|
||||
@@ -187,9 +185,7 @@ static void *setup_mm_hdr(u8 **dptr, size_t payload_size, size_t func,
|
||||
|
||||
var_hdr = (struct smm_variable_communicate_header *)mm_hdr->data;
|
||||
var_hdr->function = func;
|
||||
if (dptr)
|
||||
*dptr = comm_buf;
|
||||
*ret = EFI_SUCCESS;
|
||||
*dptr = comm_buf;
|
||||
|
||||
return var_hdr->data;
|
||||
}
|
||||
@@ -212,10 +208,9 @@ static efi_status_t get_max_payload(size_t *size)
|
||||
|
||||
payload_size = sizeof(*var_payload);
|
||||
var_payload = setup_mm_hdr(&comm_buf, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE,
|
||||
&ret);
|
||||
SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE);
|
||||
if (!var_payload)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
ret = mm_communicate(comm_buf, payload_size);
|
||||
if (ret != EFI_SUCCESS)
|
||||
@@ -239,7 +234,7 @@ static efi_status_t get_max_payload(size_t *size)
|
||||
*/
|
||||
*size -= 2;
|
||||
out:
|
||||
kfree(comm_buf);
|
||||
free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -259,9 +254,9 @@ static efi_status_t get_property_int(u16 *name, size_t name_size,
|
||||
|
||||
smm_property = setup_mm_hdr(
|
||||
&comm_buf, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET, &ret);
|
||||
SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET);
|
||||
if (!smm_property)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
memcpy(&smm_property->guid, vendor, sizeof(smm_property->guid));
|
||||
smm_property->name_size = name_size;
|
||||
@@ -282,7 +277,7 @@ static efi_status_t get_property_int(u16 *name, size_t name_size,
|
||||
memcpy(var_property, &smm_property->property, sizeof(*var_property));
|
||||
|
||||
out:
|
||||
kfree(comm_buf);
|
||||
free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -315,9 +310,9 @@ static efi_status_t tee_get_variable(u16 *name, efi_guid_t *vendor,
|
||||
|
||||
payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + tmp_dsize;
|
||||
var_acc = setup_mm_hdr(&comm_buf, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_GET_VARIABLE, &ret);
|
||||
SMM_VARIABLE_FUNCTION_GET_VARIABLE);
|
||||
if (!var_acc)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
/* Fill in contents */
|
||||
memcpy(&var_acc->guid, vendor, sizeof(var_acc->guid));
|
||||
@@ -347,7 +342,7 @@ static efi_status_t tee_get_variable(u16 *name, efi_guid_t *vendor,
|
||||
memcpy(data, (u8 *)var_acc->name + var_acc->name_size,
|
||||
var_acc->data_size);
|
||||
out:
|
||||
kfree(comm_buf);
|
||||
free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -380,10 +375,9 @@ static efi_status_t tee_get_next_variable(unsigned long *name_size,
|
||||
|
||||
payload_size = MM_VARIABLE_GET_NEXT_HEADER_SIZE + out_name_size;
|
||||
var_getnext = setup_mm_hdr(&comm_buf, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME,
|
||||
&ret);
|
||||
SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
|
||||
if (!var_getnext)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
/* Fill in contents */
|
||||
memcpy(&var_getnext->guid, guid, sizeof(var_getnext->guid));
|
||||
@@ -404,7 +398,7 @@ static efi_status_t tee_get_next_variable(unsigned long *name_size,
|
||||
memcpy(name, var_getnext->name, var_getnext->name_size);
|
||||
|
||||
out:
|
||||
kfree(comm_buf);
|
||||
free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -437,9 +431,9 @@ static efi_status_t tee_set_variable(efi_char16_t *name, efi_guid_t *vendor,
|
||||
* the properties, if the allocation fails
|
||||
*/
|
||||
var_acc = setup_mm_hdr(&comm_buf, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_SET_VARIABLE, &ret);
|
||||
SMM_VARIABLE_FUNCTION_SET_VARIABLE);
|
||||
if (!var_acc)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
/*
|
||||
* The API has the ability to override RO flags. If no RO check was
|
||||
@@ -467,7 +461,7 @@ static efi_status_t tee_set_variable(efi_char16_t *name, efi_guid_t *vendor,
|
||||
ret = mm_communicate(comm_buf, payload_size);
|
||||
dev_dbg(pvt_data.dev, "Set Variable %s %d %lx\n", __FILE__, __LINE__, ret);
|
||||
out:
|
||||
kfree(comm_buf);
|
||||
free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -492,10 +486,9 @@ static efi_status_t tee_query_variable_info(u32 attributes,
|
||||
|
||||
payload_size = sizeof(*mm_query_info);
|
||||
mm_query_info = setup_mm_hdr(&comm_buf, payload_size,
|
||||
SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO,
|
||||
&ret);
|
||||
SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);
|
||||
if (!mm_query_info)
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
return EFI_DEVICE_ERROR;
|
||||
|
||||
mm_query_info->attr = attributes;
|
||||
ret = mm_communicate(comm_buf, payload_size);
|
||||
@@ -507,7 +500,7 @@ static efi_status_t tee_query_variable_info(u32 attributes,
|
||||
*max_variable_size = mm_query_info->max_variable_size;
|
||||
|
||||
out:
|
||||
kfree(comm_buf);
|
||||
free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
|
||||
_ret_; \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
static int __init efifb_set_system(const struct dmi_system_id *id)
|
||||
{
|
||||
struct efifb_dmi_info *info = id->driver_data;
|
||||
@@ -346,7 +347,6 @@ static const struct fwnode_operations efifb_fwnode_ops = {
|
||||
.add_links = efifb_add_links,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
static struct fwnode_handle efifb_fwnode;
|
||||
|
||||
__init void sysfb_apply_efi_quirks(void)
|
||||
|
||||
@@ -361,6 +361,10 @@ static long efi_runtime_get_waketime(unsigned long arg)
|
||||
getwakeuptime.enabled))
|
||||
return -EFAULT;
|
||||
|
||||
if (getwakeuptime.pending && put_user(pending,
|
||||
getwakeuptime.pending))
|
||||
return -EFAULT;
|
||||
|
||||
if (getwakeuptime.time) {
|
||||
if (copy_to_user(getwakeuptime.time, &efi_time,
|
||||
sizeof(efi_time_t)))
|
||||
|
||||
@@ -199,6 +199,86 @@ struct cxl_cper_work_data {
|
||||
struct cxl_cper_event_rec rec;
|
||||
};
|
||||
|
||||
#define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0)
|
||||
#define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1)
|
||||
#define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2)
|
||||
#define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3)
|
||||
#define PROT_ERR_VALID_CAPABILITY BIT_ULL(4)
|
||||
#define PROT_ERR_VALID_DVSEC BIT_ULL(5)
|
||||
#define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6)
|
||||
|
||||
/*
|
||||
* The layout of the enumeration and the values matches CXL Agent Type
|
||||
* field in the UEFI 2.10 Section N.2.13,
|
||||
*/
|
||||
enum {
|
||||
RCD, /* Restricted CXL Device */
|
||||
RCH_DP, /* Restricted CXL Host Downstream Port */
|
||||
DEVICE, /* CXL Device */
|
||||
LD, /* CXL Logical Device */
|
||||
FMLD, /* CXL Fabric Manager managed Logical Device */
|
||||
RP, /* CXL Root Port */
|
||||
DSP, /* CXL Downstream Switch Port */
|
||||
USP, /* CXL Upstream Switch Port */
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */
|
||||
struct cxl_cper_sec_prot_err {
|
||||
u64 valid_bits;
|
||||
u8 agent_type;
|
||||
u8 reserved[7];
|
||||
|
||||
/*
|
||||
* Except for RCH Downstream Port, all the remaining CXL Agent
|
||||
* types are uniquely identified by the PCIe compatible SBDF number.
|
||||
*/
|
||||
union {
|
||||
u64 rcrb_base_addr;
|
||||
struct {
|
||||
u8 function;
|
||||
u8 device;
|
||||
u8 bus;
|
||||
u16 segment;
|
||||
u8 reserved_1[3];
|
||||
};
|
||||
} agent_addr;
|
||||
|
||||
struct {
|
||||
u16 vendor_id;
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_id;
|
||||
u8 class_code[2];
|
||||
u16 slot;
|
||||
u8 reserved_1[4];
|
||||
} device_id;
|
||||
|
||||
struct {
|
||||
u32 lower_dw;
|
||||
u32 upper_dw;
|
||||
} dev_serial_num;
|
||||
|
||||
u8 capability[60];
|
||||
u16 dvsec_len;
|
||||
u16 err_len;
|
||||
u8 reserved_2[4];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/* CXL RAS Capability Structure, CXL v3.0 sec 8.2.4.16 */
|
||||
struct cxl_ras_capability_regs {
|
||||
u32 uncor_status;
|
||||
u32 uncor_mask;
|
||||
u32 uncor_severity;
|
||||
u32 cor_status;
|
||||
u32 cor_mask;
|
||||
u32 cap_control;
|
||||
u32 header_log[16];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI_APEI_GHES
|
||||
int cxl_cper_register_work(struct work_struct *work);
|
||||
int cxl_cper_unregister_work(struct work_struct *work);
|
||||
|
||||
@@ -89,6 +89,10 @@ enum {
|
||||
#define CPER_NOTIFY_DMAR \
|
||||
GUID_INIT(0x667DD791, 0xC6B3, 0x4c27, 0x8A, 0x6B, 0x0F, 0x8E, \
|
||||
0x72, 0x2D, 0xEB, 0x41)
|
||||
/* CXL Protocol Error Section */
|
||||
#define CPER_SEC_CXL_PROT_ERR \
|
||||
GUID_INIT(0x80B9EFB4, 0x52B5, 0x4DE3, 0xA7, 0x77, 0x68, 0x78, \
|
||||
0x4B, 0x77, 0x10, 0x48)
|
||||
|
||||
/* CXL Event record UUIDs are formatted as GUIDs and reported in section type */
|
||||
/*
|
||||
@@ -601,4 +605,8 @@ void cper_estatus_print(const char *pfx,
|
||||
int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus);
|
||||
int cper_estatus_check(const struct acpi_hest_generic_status *estatus);
|
||||
|
||||
struct cxl_cper_sec_prot_err;
|
||||
void cxl_cper_print_prot_err(const char *pfx,
|
||||
const struct cxl_cper_sec_prot_err *prot_err);
|
||||
|
||||
#endif
|
||||
|
||||
+19
-33
@@ -116,21 +116,22 @@ typedef struct {
|
||||
#define EFI_MAX_MEMORY_TYPE 16
|
||||
|
||||
/* Attribute values: */
|
||||
#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
|
||||
#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
|
||||
#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
|
||||
#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
|
||||
#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL) /* uncached, exported */
|
||||
#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
|
||||
#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
|
||||
#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
|
||||
#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */
|
||||
#define EFI_MEMORY_MORE_RELIABLE \
|
||||
((u64)0x0000000000010000ULL) /* higher reliability */
|
||||
#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */
|
||||
#define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */
|
||||
#define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */
|
||||
#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
|
||||
#define EFI_MEMORY_UC BIT_ULL(0) /* uncached */
|
||||
#define EFI_MEMORY_WC BIT_ULL(1) /* write-coalescing */
|
||||
#define EFI_MEMORY_WT BIT_ULL(2) /* write-through */
|
||||
#define EFI_MEMORY_WB BIT_ULL(3) /* write-back */
|
||||
#define EFI_MEMORY_UCE BIT_ULL(4) /* uncached, exported */
|
||||
#define EFI_MEMORY_WP BIT_ULL(12) /* write-protect */
|
||||
#define EFI_MEMORY_RP BIT_ULL(13) /* read-protect */
|
||||
#define EFI_MEMORY_XP BIT_ULL(14) /* execute-protect */
|
||||
#define EFI_MEMORY_NV BIT_ULL(15) /* non-volatile */
|
||||
#define EFI_MEMORY_MORE_RELIABLE BIT_ULL(16) /* higher reliability */
|
||||
#define EFI_MEMORY_RO BIT_ULL(17) /* read-only */
|
||||
#define EFI_MEMORY_SP BIT_ULL(18) /* soft reserved */
|
||||
#define EFI_MEMORY_CPU_CRYPTO BIT_ULL(19) /* supports encryption */
|
||||
#define EFI_MEMORY_HOT_PLUGGABLE BIT_ULL(20) /* supports unplugging at runtime */
|
||||
#define EFI_MEMORY_RUNTIME BIT_ULL(63) /* range requires runtime mapping */
|
||||
|
||||
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
|
||||
|
||||
#define EFI_PAGE_SHIFT 12
|
||||
@@ -365,7 +366,6 @@ void efi_native_runtime_setup(void);
|
||||
#define ACPI_20_TABLE_GUID EFI_GUID(0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81)
|
||||
#define SMBIOS_TABLE_GUID EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
|
||||
#define SMBIOS3_TABLE_GUID EFI_GUID(0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94)
|
||||
#define UGA_IO_PROTOCOL_GUID EFI_GUID(0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0x0b, 0x07, 0xa2)
|
||||
#define EFI_GLOBAL_VARIABLE_GUID EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
|
||||
#define UV_SYSTEM_TABLE_GUID EFI_GUID(0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93)
|
||||
#define LINUX_EFI_CRASH_GUID EFI_GUID(0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0)
|
||||
@@ -375,13 +375,11 @@ void efi_native_runtime_setup(void);
|
||||
#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID EFI_GUID(0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c)
|
||||
#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID EFI_GUID(0x05c99a21, 0xc70f, 0x4ad2, 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e)
|
||||
#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID EFI_GUID(0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a)
|
||||
#define EFI_UGA_PROTOCOL_GUID EFI_GUID(0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39)
|
||||
#define EFI_PCI_IO_PROTOCOL_GUID EFI_GUID(0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a)
|
||||
#define EFI_FILE_INFO_ID EFI_GUID(0x09576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
|
||||
#define EFI_SYSTEM_RESOURCE_TABLE_GUID EFI_GUID(0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80)
|
||||
#define EFI_FILE_SYSTEM_GUID EFI_GUID(0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
|
||||
#define DEVICE_TREE_GUID EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
|
||||
#define EFI_PROPERTIES_TABLE_GUID EFI_GUID(0x880aaca3, 0x4adc, 0x4a04, 0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5)
|
||||
#define EFI_RNG_PROTOCOL_GUID EFI_GUID(0x3152bca5, 0xeade, 0x433d, 0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44)
|
||||
#define EFI_RNG_ALGORITHM_RAW EFI_GUID(0xe43176d7, 0xb6e8, 0x4827, 0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61)
|
||||
#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
|
||||
@@ -583,15 +581,6 @@ struct efi_mem_range {
|
||||
u64 attribute;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u32 version;
|
||||
u32 length;
|
||||
u64 memory_protection_attribute;
|
||||
} efi_properties_table_t;
|
||||
|
||||
#define EFI_PROPERTIES_TABLE_VERSION 0x00010000
|
||||
#define EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA 0x1
|
||||
|
||||
typedef struct {
|
||||
u16 version;
|
||||
u16 length;
|
||||
@@ -875,10 +864,9 @@ static inline int efi_range_is_wc(unsigned long start, unsigned long len)
|
||||
#define EFI_PARAVIRT 6 /* Access is via a paravirt interface */
|
||||
#define EFI_ARCH_1 7 /* First arch-specific bit */
|
||||
#define EFI_DBG 8 /* Print additional debug info at runtime */
|
||||
#define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */
|
||||
#define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
|
||||
#define EFI_MEM_NO_SOFT_RESERVE 11 /* Is the kernel configured to ignore soft reservations? */
|
||||
#define EFI_PRESERVE_BS_REGIONS 12 /* Are EFI boot-services memory segments available? */
|
||||
#define EFI_MEM_ATTR 9 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
|
||||
#define EFI_MEM_NO_SOFT_RESERVE 10 /* Is the kernel configured to ignore soft reservations? */
|
||||
#define EFI_PRESERVE_BS_REGIONS 11 /* Are EFI boot-services memory segments available? */
|
||||
#define EFI_SECURE_BOOT 13 /* Are we in Secure Boot mode? */
|
||||
|
||||
enum efi_secureboot_mode {
|
||||
@@ -1307,8 +1295,6 @@ struct linux_efi_memreserve {
|
||||
|
||||
void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size);
|
||||
|
||||
char *efi_systab_show_arch(char *str);
|
||||
|
||||
/*
|
||||
* The LINUX_EFI_MOK_VARIABLE_TABLE_GUID config table can be provided
|
||||
* to the kernel by an EFI boot loader. The table contains a packed
|
||||
|
||||
+170
-101
@@ -39,113 +39,160 @@
|
||||
*/
|
||||
#define LINUX_PE_MAGIC 0x818223cd
|
||||
|
||||
#define MZ_MAGIC 0x5a4d /* "MZ" */
|
||||
#define IMAGE_DOS_SIGNATURE 0x5a4d /* "MZ" */
|
||||
|
||||
#define PE_MAGIC 0x00004550 /* "PE\0\0" */
|
||||
#define PE_OPT_MAGIC_PE32 0x010b
|
||||
#define PE_OPT_MAGIC_PE32_ROM 0x0107
|
||||
#define PE_OPT_MAGIC_PE32PLUS 0x020b
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550 /* "PE\0\0" */
|
||||
|
||||
#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x0107 /* ROM image (for R3000/R4000/R10000/ALPHA), without MZ and PE\0\0 sign */
|
||||
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x010b /* PE32 executable image */
|
||||
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x020b /* PE32+ executable image */
|
||||
|
||||
/* machine type */
|
||||
#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000
|
||||
#define IMAGE_FILE_MACHINE_AM33 0x01d3
|
||||
#define IMAGE_FILE_MACHINE_AMD64 0x8664
|
||||
#define IMAGE_FILE_MACHINE_ARM 0x01c0
|
||||
#define IMAGE_FILE_MACHINE_ARMV7 0x01c4
|
||||
#define IMAGE_FILE_MACHINE_ARM64 0xaa64
|
||||
#define IMAGE_FILE_MACHINE_EBC 0x0ebc
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||
#define IMAGE_FILE_MACHINE_IA64 0x0200
|
||||
#define IMAGE_FILE_MACHINE_M32R 0x9041
|
||||
#define IMAGE_FILE_MACHINE_MIPS16 0x0266
|
||||
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366
|
||||
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466
|
||||
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
|
||||
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1
|
||||
#define IMAGE_FILE_MACHINE_R4000 0x0166
|
||||
#define IMAGE_FILE_MACHINE_RISCV32 0x5032
|
||||
#define IMAGE_FILE_MACHINE_RISCV64 0x5064
|
||||
#define IMAGE_FILE_MACHINE_RISCV128 0x5128
|
||||
#define IMAGE_FILE_MACHINE_SH3 0x01a2
|
||||
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3
|
||||
#define IMAGE_FILE_MACHINE_SH3E 0x01a4
|
||||
#define IMAGE_FILE_MACHINE_SH4 0x01a6
|
||||
#define IMAGE_FILE_MACHINE_SH5 0x01a8
|
||||
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
|
||||
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169
|
||||
#define IMAGE_FILE_MACHINE_LOONGARCH32 0x6232
|
||||
#define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264
|
||||
#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 /* Unknown architecture */
|
||||
#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 /* Interacts with the host and not a WOW64 guest (not for file image) */
|
||||
#define IMAGE_FILE_MACHINE_ALPHA_OLD 0x0183 /* DEC Alpha AXP 32-bit (old images) */
|
||||
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 /* DEC Alpha AXP 32-bit */
|
||||
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 /* DEC Alpha AXP 64-bit (with 8kB page size) */
|
||||
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
|
||||
#define IMAGE_FILE_MACHINE_AM33 0x01d3 /* Matsushita AM33, now Panasonic MN103 */
|
||||
#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* AMD64 (x64) */
|
||||
#define IMAGE_FILE_MACHINE_ARM 0x01c0 /* ARM Little-Endian (ARMv4) */
|
||||
#define IMAGE_FILE_MACHINE_THUMB 0x01c2 /* ARM Thumb Little-Endian (ARMv4T) */
|
||||
#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 /* ARM Thumb-2 Little-Endian (ARMv7) */
|
||||
#define IMAGE_FILE_MACHINE_ARMV7 IMAGE_FILE_MACHINE_ARMNT
|
||||
#define IMAGE_FILE_MACHINE_ARM64 0xaa64 /* ARM64 Little-Endian (Classic ABI) */
|
||||
#define IMAGE_FILE_MACHINE_ARM64EC 0xa641 /* ARM64 Little-Endian (Emulation Compatible ABI for AMD64) */
|
||||
#define IMAGE_FILE_MACHINE_ARM64X 0xa64e /* ARM64 Little-Endian (fat binary with both Classic ABI and EC ABI code) */
|
||||
#define IMAGE_FILE_MACHINE_CEE 0xc0ee /* COM+ Execution Engine (CLR pure MSIL object files) */
|
||||
#define IMAGE_FILE_MACHINE_CEF 0x0cef /* Windows CE 3.0 Common Executable Format (CEF bytecode) */
|
||||
#define IMAGE_FILE_MACHINE_CHPE_X86 0x3a64 /* ARM64 Little-Endian (Compiled Hybrid PE ABI for I386) */
|
||||
#define IMAGE_FILE_MACHINE_HYBRID_X86 IMAGE_FILE_MACHINE_CHPE_X86
|
||||
#define IMAGE_FILE_MACHINE_EBC 0x0ebc /* EFI/UEFI Byte Code */
|
||||
#define IMAGE_FILE_MACHINE_I386 0x014c /* Intel 386 (x86) */
|
||||
#define IMAGE_FILE_MACHINE_I860 0x014d /* Intel 860 (N10) */
|
||||
#define IMAGE_FILE_MACHINE_IA64 0x0200 /* Intel IA-64 (with 8kB page size) */
|
||||
#define IMAGE_FILE_MACHINE_LOONGARCH32 0x6232 /* LoongArch 32-bit processor family */
|
||||
#define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 /* LoongArch 64-bit processor family */
|
||||
#define IMAGE_FILE_MACHINE_M32R 0x9041 /* Mitsubishi M32R 32-bit Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_M68K 0x0268 /* Motorola 68000 series */
|
||||
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 /* MIPS III with MIPS16 ASE Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 /* MIPS III with FPU Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 /* MIPS III with MIPS16 ASE and FPU Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_MPPC_601 0x0601 /* PowerPC 32-bit Big-Endian */
|
||||
#define IMAGE_FILE_MACHINE_OMNI 0xace1 /* Microsoft OMNI VM (omniprox.dll) */
|
||||
#define IMAGE_FILE_MACHINE_PARISC 0x0290 /* HP PA-RISC */
|
||||
#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 /* PowerPC 32-bit Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 /* PowerPC 32-bit with FPU Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_POWERPCBE 0x01f2 /* PowerPC 64-bit Big-Endian */
|
||||
#define IMAGE_FILE_MACHINE_R3000 0x0162 /* MIPS I Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_R3000_BE 0x0160 /* MIPS I Big-Endian */
|
||||
#define IMAGE_FILE_MACHINE_R4000 0x0166 /* MIPS III Little-Endian (with 1kB or 4kB page size) */
|
||||
#define IMAGE_FILE_MACHINE_R10000 0x0168 /* MIPS IV Little-Endian */
|
||||
#define IMAGE_FILE_MACHINE_RISCV32 0x5032 /* RISC-V 32-bit address space */
|
||||
#define IMAGE_FILE_MACHINE_RISCV64 0x5064 /* RISC-V 64-bit address space */
|
||||
#define IMAGE_FILE_MACHINE_RISCV128 0x5128 /* RISC-V 128-bit address space */
|
||||
#define IMAGE_FILE_MACHINE_SH3 0x01a2 /* Hitachi SH-3 32-bit Little-Endian (with 1kB page size) */
|
||||
#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 /* Hitachi SH-3 DSP 32-bit (with 1kB page size) */
|
||||
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 /* Hitachi SH-3E Little-Endian (with 1kB page size) */
|
||||
#define IMAGE_FILE_MACHINE_SH4 0x01a6 /* Hitachi SH-4 32-bit Little-Endian (with 1kB page size) */
|
||||
#define IMAGE_FILE_MACHINE_SH5 0x01a8 /* Hitachi SH-5 64-bit */
|
||||
#define IMAGE_FILE_MACHINE_TAHOE 0x07cc /* Intel EM machine */
|
||||
#define IMAGE_FILE_MACHINE_TRICORE 0x0520 /* Infineon AUDO 32-bit */
|
||||
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 /* MIPS Windows CE v2 Little-Endian */
|
||||
|
||||
/* flags */
|
||||
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
|
||||
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
|
||||
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
|
||||
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
|
||||
#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010
|
||||
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
|
||||
#define IMAGE_FILE_16BIT_MACHINE 0x0040
|
||||
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
|
||||
#define IMAGE_FILE_32BIT_MACHINE 0x0100
|
||||
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
|
||||
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
|
||||
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
|
||||
#define IMAGE_FILE_SYSTEM 0x1000
|
||||
#define IMAGE_FILE_DLL 0x2000
|
||||
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
|
||||
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
|
||||
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* Relocation info stripped from file */
|
||||
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 /* File is executable (i.e. no unresolved external references) */
|
||||
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 /* Line nunbers stripped from file */
|
||||
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 /* Local symbols stripped from file */
|
||||
#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 /* Aggressively trim working set */
|
||||
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 /* App can handle >2gb addresses (image can be loaded at address above 2GB) */
|
||||
#define IMAGE_FILE_16BIT_MACHINE 0x0040 /* 16 bit word machine */
|
||||
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 /* Bytes of machine word are reversed (should be set together with IMAGE_FILE_BYTES_REVERSED_HI) */
|
||||
#define IMAGE_FILE_32BIT_MACHINE 0x0100 /* 32 bit word machine */
|
||||
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 /* Debugging info stripped from file in .DBG file */
|
||||
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 /* If Image is on removable media, copy and run from the swap file */
|
||||
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 /* If Image is on Net, copy and run from the swap file */
|
||||
#define IMAGE_FILE_SYSTEM 0x1000 /* System kernel-mode file (can't be loaded in user-mode) */
|
||||
#define IMAGE_FILE_DLL 0x2000 /* File is a DLL */
|
||||
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 /* File should only be run on a UP (uniprocessor) machine */
|
||||
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* Bytes of machine word are reversed (should be set together with IMAGE_FILE_BYTES_REVERSED_LO) */
|
||||
|
||||
#define IMAGE_FILE_OPT_ROM_MAGIC 0x107
|
||||
#define IMAGE_FILE_OPT_PE32_MAGIC 0x10b
|
||||
#define IMAGE_FILE_OPT_PE32_PLUS_MAGIC 0x20b
|
||||
/* subsys */
|
||||
#define IMAGE_SUBSYSTEM_UNKNOWN 0 /* Unknown subsystem */
|
||||
#define IMAGE_SUBSYSTEM_NATIVE 1 /* No subsystem required (NT device drivers and NT native system processes) */
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows graphical user interface (GUI) subsystem */
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows character-mode user interface (CUI) subsystem */
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_OLD_CE_GUI 4 /* Old Windows CE subsystem */
|
||||
#define IMAGE_SUBSYSTEM_OS2_CUI 5 /* OS/2 CUI subsystem */
|
||||
#define IMAGE_SUBSYSTEM_RESERVED_6 6
|
||||
#define IMAGE_SUBSYSTEM_POSIX_CUI 7 /* POSIX CUI subsystem */
|
||||
#define IMAGE_SUBSYSTEM_MMOSA 8 /* MMOSA/Native Win32E */
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 /* Windows CE subsystem */
|
||||
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 /* Extensible Firmware Interface (EFI) application */
|
||||
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 /* EFI driver with boot services */
|
||||
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 /* EFI driver with run-time services */
|
||||
#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 /* EFI ROM image */
|
||||
#define IMAGE_SUBSYSTEM_XBOX 14 /* Xbox system */
|
||||
#define IMAGE_SUBSYSTEM_RESERVED_15 15
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 /* Windows Boot application */
|
||||
#define IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG 17 /* Xbox Code Catalog */
|
||||
|
||||
#define IMAGE_SUBSYSTEM_UNKNOWN 0
|
||||
#define IMAGE_SUBSYSTEM_NATIVE 1
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
|
||||
#define IMAGE_SUBSYSTEM_POSIX_CUI 7
|
||||
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
|
||||
#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
|
||||
#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
|
||||
#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
|
||||
#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13
|
||||
#define IMAGE_SUBSYSTEM_XBOX 14
|
||||
/* dll_flags */
|
||||
#define IMAGE_LIBRARY_PROCESS_INIT 0x0001 /* DLL initialization function called just after process initialization */
|
||||
#define IMAGE_LIBRARY_PROCESS_TERM 0x0002 /* DLL initialization function called just before process termination */
|
||||
#define IMAGE_LIBRARY_THREAD_INIT 0x0004 /* DLL initialization function called just after thread initialization */
|
||||
#define IMAGE_LIBRARY_THREAD_TERM 0x0008 /* DLL initialization function called just before thread initialization */
|
||||
#define IMAGE_DLLCHARACTERISTICS_RESERVED_4 0x0010
|
||||
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 /* ASLR with 64 bit address space (image can be loaded at address above 4GB) */
|
||||
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 /* The DLL can be relocated at load time */
|
||||
#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 /* Code integrity checks are forced */
|
||||
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 /* Image is compatible with data execution prevention */
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 /* Image is isolation aware, but should not be isolated (prevents loading of manifest file) */
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 /* Image does not use SEH, no SE handler may reside in this image */
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 /* Do not bind the image */
|
||||
#define IMAGE_DLLCHARACTERISTICS_X86_THUNK 0x1000 /* Image is a Wx86 Thunk DLL (for non-x86/risc DLL files) */
|
||||
#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 /* Image should execute in an AppContainer (for EXE Metro Apps in Windows 8) */
|
||||
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 /* A WDM driver */
|
||||
#define IMAGE_DLLCHARACTERISTICS_GUARD_CF 0x4000 /* Image supports Control Flow Guard */
|
||||
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 /* The image is terminal server (Remote Desktop Services) aware */
|
||||
|
||||
#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040
|
||||
#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080
|
||||
#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400
|
||||
#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800
|
||||
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000
|
||||
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
|
||||
/* IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS flags */
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001 /* Image is Control-flow Enforcement Technology Shadow Stack compatible */
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE 0x0002 /* CET is enforced in strict mode */
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE 0x0004 /* Relaxed mode for Context IP Validation under CET is allowed */
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC 0x0008 /* Use of dynamic APIs is restricted to processes only */
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_RESERVED_1 0x0010
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_RESERVED_2 0x0020
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040 /* All branch targets in all image code sections are annotated with forward-edge control flow integrity guard instructions */
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_HOTPATCH_COMPATIBLE 0x0080 /* Image can be modified while in use, hotpatch-compatible */
|
||||
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001
|
||||
#define IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040
|
||||
|
||||
/* they actually defined 0x00000000 as well, but I think we'll skip that one. */
|
||||
#define IMAGE_SCN_RESERVED_0 0x00000001
|
||||
#define IMAGE_SCN_RESERVED_1 0x00000002
|
||||
#define IMAGE_SCN_RESERVED_2 0x00000004
|
||||
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* don't pad - obsolete */
|
||||
#define IMAGE_SCN_RESERVED_3 0x00000010
|
||||
/* section_header flags */
|
||||
#define IMAGE_SCN_SCALE_INDEX 0x00000001 /* address of tls index is scaled = multiplied by 4 (for .tls section on MIPS only) */
|
||||
#define IMAGE_SCN_TYPE_NO_LOAD 0x00000002 /* reserved */
|
||||
#define IMAGE_SCN_TYPE_GROUPED 0x00000004 /* obsolete (used for 16-bit offset code) */
|
||||
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* .o only - don't pad - obsolete (same as IMAGE_SCN_ALIGN_1BYTES) */
|
||||
#define IMAGE_SCN_TYPE_COPY 0x00000010 /* reserved */
|
||||
#define IMAGE_SCN_CNT_CODE 0x00000020 /* .text */
|
||||
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* .data */
|
||||
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* .bss */
|
||||
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* reserved */
|
||||
#define IMAGE_SCN_LNK_INFO 0x00000200 /* .drectve comments */
|
||||
#define IMAGE_SCN_RESERVED_4 0x00000400
|
||||
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* .o only - other type than code, data or info */
|
||||
#define IMAGE_SCN_LNK_INFO 0x00000200 /* .o only - .drectve comments */
|
||||
#define IMAGE_SCN_LNK_OVERLAY 0x00000400 /* section contains overlay */
|
||||
#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* .o only - scn to be rm'd*/
|
||||
#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* .o only - COMDAT data */
|
||||
#define IMAGE_SCN_RESERVED_5 0x00002000 /* spec omits this */
|
||||
#define IMAGE_SCN_RESERVED_6 0x00004000 /* spec omits this */
|
||||
#define IMAGE_SCN_GPREL 0x00008000 /* global pointer referenced data */
|
||||
/* spec lists 0x20000 twice, I suspect they meant 0x10000 for one of them */
|
||||
#define IMAGE_SCN_MEM_PURGEABLE 0x00010000 /* reserved for "future" use */
|
||||
#define IMAGE_SCN_16BIT 0x00020000 /* reserved for "future" use */
|
||||
#define IMAGE_SCN_LOCKED 0x00040000 /* reserved for "future" use */
|
||||
#define IMAGE_SCN_PRELOAD 0x00080000 /* reserved for "future" use */
|
||||
#define IMAGE_SCN_RESERVED_13 0x00002000 /* spec omits this */
|
||||
#define IMAGE_SCN_MEM_PROTECTED 0x00004000 /* section is memory protected (for M68K) */
|
||||
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 /* reset speculative exceptions handling bits in the TLB entries (for non-M68K) */
|
||||
#define IMAGE_SCN_MEM_FARDATA 0x00008000 /* section uses FAR_EXTERNAL relocations (for M68K) */
|
||||
#define IMAGE_SCN_GPREL 0x00008000 /* global pointer referenced data (for non-M68K) */
|
||||
#define IMAGE_SCN_MEM_SYSHEAP 0x00010000 /* use system heap (for M68K) */
|
||||
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 /* section can be released from RAM (for M68K) */
|
||||
#define IMAGE_SCN_MEM_16BIT 0x00020000 /* section is 16-bit (for non-M68K where it makes sense: I386, THUMB, MIPS16, MIPSFPU16, ...) */
|
||||
#define IMAGE_SCN_MEM_LOCKED 0x00040000 /* prevent the section from being moved (for M68K and .o I386) */
|
||||
#define IMAGE_SCN_MEM_PRELOAD 0x00080000 /* section is preload to RAM (for M68K and .o I386) */
|
||||
/* and here they just stuck a 1-byte integer in the middle of a bitfield */
|
||||
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* it does what it says on the box */
|
||||
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* .o only - it does what it says on the box */
|
||||
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
|
||||
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
|
||||
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
|
||||
@@ -159,7 +206,9 @@
|
||||
#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000
|
||||
#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000
|
||||
#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000
|
||||
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* extended relocations */
|
||||
#define IMAGE_SCN_ALIGN_RESERVED 0x00f00000
|
||||
#define IMAGE_SCN_ALIGN_MASK 0x00f00000
|
||||
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* .o only - extended relocations */
|
||||
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 /* scn can be discarded */
|
||||
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* cannot be cached */
|
||||
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* not pageable */
|
||||
@@ -168,8 +217,28 @@
|
||||
#define IMAGE_SCN_MEM_READ 0x40000000 /* readable */
|
||||
#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */
|
||||
|
||||
#define IMAGE_DEBUG_TYPE_CODEVIEW 2
|
||||
#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20
|
||||
#define IMAGE_DEBUG_TYPE_UNKNOWN 0 /* Unknown value, ignored by all tools */
|
||||
#define IMAGE_DEBUG_TYPE_COFF 1 /* COFF debugging information */
|
||||
#define IMAGE_DEBUG_TYPE_CODEVIEW 2 /* CodeView debugging information or Visual C++ Program Database debugging information */
|
||||
#define IMAGE_DEBUG_TYPE_FPO 3 /* Frame pointer omission (FPO) information */
|
||||
#define IMAGE_DEBUG_TYPE_MISC 4 /* Location of DBG file with CodeView debugging information */
|
||||
#define IMAGE_DEBUG_TYPE_EXCEPTION 5 /* Exception information, copy of .pdata section */
|
||||
#define IMAGE_DEBUG_TYPE_FIXUP 6 /* Fixup information */
|
||||
#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 /* The mapping from an RVA in image to an RVA in source image */
|
||||
#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 /* The mapping from an RVA in source image to an RVA in image */
|
||||
#define IMAGE_DEBUG_TYPE_BORLAND 9 /* Borland debugging information */
|
||||
#define IMAGE_DEBUG_TYPE_RESERVED10 10 /* Coldpath / Hotpatch debug information */
|
||||
#define IMAGE_DEBUG_TYPE_CLSID 11 /* CLSID */
|
||||
#define IMAGE_DEBUG_TYPE_VC_FEATURE 12 /* Visual C++ counts / statistics */
|
||||
#define IMAGE_DEBUG_TYPE_POGO 13 /* COFF group information, data for profile-guided optimization */
|
||||
#define IMAGE_DEBUG_TYPE_ILTCG 14 /* Incremental link-time code generation */
|
||||
#define IMAGE_DEBUG_TYPE_MPX 15 /* Intel Memory Protection Extensions */
|
||||
#define IMAGE_DEBUG_TYPE_REPRO 16 /* PE determinism or reproducibility */
|
||||
#define IMAGE_DEBUG_TYPE_EMBEDDED_PORTABLE_PDB 17 /* Embedded Portable PDB debugging information */
|
||||
#define IMAGE_DEBUG_TYPE_SPGO 18 /* Sample profile-guided optimization */
|
||||
#define IMAGE_DEBUG_TYPE_PDBCHECKSUM 19 /* PDB Checksum */
|
||||
#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 /* Extended DLL characteristics bits */
|
||||
#define IMAGE_DEBUG_TYPE_PERFMAP 21 /* Location of associated Ready To Run PerfMap file */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@@ -235,7 +304,7 @@ struct pe32_opt_hdr {
|
||||
uint16_t image_minor; /* minor image version */
|
||||
uint16_t subsys_major; /* major subsystem version */
|
||||
uint16_t subsys_minor; /* minor subsystem version */
|
||||
uint32_t win32_version; /* reserved, must be 0 */
|
||||
uint32_t win32_version; /* win32 version reported at runtime */
|
||||
uint32_t image_size; /* image size */
|
||||
uint32_t header_size; /* header size rounded up to
|
||||
file_align */
|
||||
@@ -246,7 +315,7 @@ struct pe32_opt_hdr {
|
||||
uint32_t stack_size; /* amt of stack required */
|
||||
uint32_t heap_size_req; /* amt of heap requested */
|
||||
uint32_t heap_size; /* amt of heap required */
|
||||
uint32_t loader_flags; /* reserved, must be 0 */
|
||||
uint32_t loader_flags; /* loader flags */
|
||||
uint32_t data_dirs; /* number of data dir entries */
|
||||
};
|
||||
|
||||
@@ -269,7 +338,7 @@ struct pe32plus_opt_hdr {
|
||||
uint16_t image_minor; /* minor image version */
|
||||
uint16_t subsys_major; /* major subsystem version */
|
||||
uint16_t subsys_minor; /* minor subsystem version */
|
||||
uint32_t win32_version; /* reserved, must be 0 */
|
||||
uint32_t win32_version; /* win32 version reported at runtime */
|
||||
uint32_t image_size; /* image size */
|
||||
uint32_t header_size; /* header size rounded up to
|
||||
file_align */
|
||||
@@ -280,7 +349,7 @@ struct pe32plus_opt_hdr {
|
||||
uint64_t stack_size; /* amt of stack required */
|
||||
uint64_t heap_size_req; /* amt of heap requested */
|
||||
uint64_t heap_size; /* amt of heap required */
|
||||
uint32_t loader_flags; /* reserved, must be 0 */
|
||||
uint32_t loader_flags; /* loader flags */
|
||||
uint32_t data_dirs; /* number of data dir entries */
|
||||
};
|
||||
|
||||
@@ -301,10 +370,10 @@ struct data_directory {
|
||||
struct data_dirent global_ptr; /* global pointer reg. Size=0 */
|
||||
struct data_dirent tls; /* .tls */
|
||||
struct data_dirent load_config; /* load configuration structure */
|
||||
struct data_dirent bound_imports; /* no idea */
|
||||
struct data_dirent bound_imports; /* bound import table */
|
||||
struct data_dirent import_addrs; /* import address table */
|
||||
struct data_dirent delay_imports; /* delay-load import table */
|
||||
struct data_dirent clr_runtime_hdr; /* .cor (object only) */
|
||||
struct data_dirent clr_runtime_hdr; /* .cor (clr/.net executables) */
|
||||
struct data_dirent reserved;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user