Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
97712289
Commit
97712289
authored
Nov 18, 2022
by
Ard Biesheuvel
Browse files
Options
Browse Files
Download
Plain Diff
Merge tag 'efi-zboot-direct-for-v6.2' into efi/next
parents
094226ad
c51e97e7
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
983 additions
and
854 deletions
+983
-854
MAINTAINERS
MAINTAINERS
+0
-1
arch/arm/include/asm/efi.h
arch/arm/include/asm/efi.h
+0
-3
arch/arm/kernel/efi.c
arch/arm/kernel/efi.c
+5
-26
arch/arm64/include/asm/efi.h
arch/arm64/include/asm/efi.h
+12
-3
arch/arm64/kernel/Makefile
arch/arm64/kernel/Makefile
+1
-8
arch/arm64/kernel/image-vars.h
arch/arm64/kernel/image-vars.h
+0
-8
arch/loongarch/include/asm/efi.h
arch/loongarch/include/asm/efi.h
+7
-7
arch/loongarch/kernel/efi.c
arch/loongarch/kernel/efi.c
+22
-2
arch/loongarch/kernel/image-vars.h
arch/loongarch/kernel/image-vars.h
+0
-8
arch/riscv/include/asm/efi.h
arch/riscv/include/asm/efi.h
+10
-3
arch/riscv/kernel/image-vars.h
arch/riscv/kernel/image-vars.h
+0
-6
drivers/firmware/efi/efi-init.c
drivers/firmware/efi/efi-init.c
+18
-3
drivers/firmware/efi/efi.c
drivers/firmware/efi/efi.c
+5
-0
drivers/firmware/efi/libstub/Makefile
drivers/firmware/efi/libstub/Makefile
+19
-15
drivers/firmware/efi/libstub/Makefile.zboot
drivers/firmware/efi/libstub/Makefile.zboot
+10
-12
drivers/firmware/efi/libstub/arm32-stub.c
drivers/firmware/efi/libstub/arm32-stub.c
+0
-37
drivers/firmware/efi/libstub/arm64-entry.S
drivers/firmware/efi/libstub/arm64-entry.S
+67
-0
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/arm64-stub.c
+10
-54
drivers/firmware/efi/libstub/arm64.c
drivers/firmware/efi/libstub/arm64.c
+76
-0
drivers/firmware/efi/libstub/efi-stub-entry.c
drivers/firmware/efi/libstub/efi-stub-entry.c
+65
-0
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/libstub/efi-stub-helper.c
+0
-143
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efi-stub.c
+35
-105
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/efistub.h
+15
-0
drivers/firmware/efi/libstub/file.c
drivers/firmware/efi/libstub/file.c
+0
-18
drivers/firmware/efi/libstub/intrinsics.c
drivers/firmware/efi/libstub/intrinsics.c
+18
-0
drivers/firmware/efi/libstub/loongarch-stub.c
drivers/firmware/efi/libstub/loongarch-stub.c
+20
-69
drivers/firmware/efi/libstub/loongarch.c
drivers/firmware/efi/libstub/loongarch.c
+80
-0
drivers/firmware/efi/libstub/printk.c
drivers/firmware/efi/libstub/printk.c
+154
-0
drivers/firmware/efi/libstub/riscv-stub.c
drivers/firmware/efi/libstub/riscv-stub.c
+10
-86
drivers/firmware/efi/libstub/riscv.c
drivers/firmware/efi/libstub/riscv.c
+98
-0
drivers/firmware/efi/libstub/screen_info.c
drivers/firmware/efi/libstub/screen_info.c
+56
-0
drivers/firmware/efi/libstub/string.c
drivers/firmware/efi/libstub/string.c
+92
-3
drivers/firmware/efi/libstub/zboot-header.S
drivers/firmware/efi/libstub/zboot-header.S
+1
-1
drivers/firmware/efi/libstub/zboot.c
drivers/firmware/efi/libstub/zboot.c
+76
-231
include/linux/efi.h
include/linux/efi.h
+1
-2
No files found.
MAINTAINERS
View file @
97712289
...
...
@@ -7789,7 +7789,6 @@ F: Documentation/admin-guide/efi-stub.rst
F: arch/*/include/asm/efi.h
F: arch/*/kernel/efi.c
F: arch/arm/boot/compressed/efi-header.S
F: arch/arm64/kernel/efi-entry.S
F: arch/x86/platform/efi/
F: drivers/firmware/efi/
F: include/linux/efi*.h
...
...
arch/arm/include/asm/efi.h
View file @
97712289
...
...
@@ -43,9 +43,6 @@ void efi_virtmap_unload(void);
/* arch specific definitions used by the stub code */
struct
screen_info
*
alloc_screen_info
(
void
);
void
free_screen_info
(
struct
screen_info
*
si
);
/*
* A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
* so we will reserve that amount of memory. We have no easy way to tell what
...
...
arch/arm/kernel/efi.c
View file @
97712289
...
...
@@ -75,38 +75,13 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
return
0
;
}
static
unsigned
long
__initdata
screen_info_table
=
EFI_INVALID_TABLE_ADDR
;
static
unsigned
long
__initdata
cpu_state_table
=
EFI_INVALID_TABLE_ADDR
;
const
efi_config_table_type_t
efi_arch_tables
[]
__initconst
=
{
{
LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID
,
&
screen_info_table
},
{
LINUX_EFI_ARM_CPU_STATE_TABLE_GUID
,
&
cpu_state_table
},
{}
};
static
void
__init
load_screen_info_table
(
void
)
{
struct
screen_info
*
si
;
if
(
screen_info_table
!=
EFI_INVALID_TABLE_ADDR
)
{
si
=
early_memremap_ro
(
screen_info_table
,
sizeof
(
*
si
));
if
(
!
si
)
{
pr_err
(
"Could not map screen_info config table
\n
"
);
return
;
}
screen_info
=
*
si
;
early_memunmap
(
si
,
sizeof
(
*
si
));
/* dummycon on ARM needs non-zero values for columns/lines */
screen_info
.
orig_video_cols
=
80
;
screen_info
.
orig_video_lines
=
25
;
if
(
memblock_is_map_memory
(
screen_info
.
lfb_base
))
memblock_mark_nomap
(
screen_info
.
lfb_base
,
screen_info
.
lfb_size
);
}
}
static
void
__init
load_cpu_state_table
(
void
)
{
if
(
cpu_state_table
!=
EFI_INVALID_TABLE_ADDR
)
{
...
...
@@ -145,7 +120,11 @@ void __init arm_efi_init(void)
{
efi_init
();
load_screen_info_table
();
if
(
screen_info
.
orig_video_isVGA
==
VIDEO_TYPE_EFI
)
{
/* dummycon on ARM needs non-zero values for columns/lines */
screen_info
.
orig_video_cols
=
80
;
screen_info
.
orig_video_lines
=
25
;
}
/* ARM does not permit early mappings to persist across paging_init() */
efi_memmap_unmap
();
...
...
arch/arm64/include/asm/efi.h
View file @
97712289
...
...
@@ -84,10 +84,19 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
return
(
image_addr
&
~
(
SZ_1G
-
1UL
))
+
(
1UL
<<
(
VA_BITS_MIN
-
1
));
}
#define alloc_screen_info(x...) &screen_info
static
inline
void
free_screen_info
(
struct
screen_info
*
si
)
static
inline
unsigned
long
efi_get_kimg_min_align
(
void
)
{
extern
bool
efi_nokaslr
;
/*
* Although relocatable kernels can fix up the misalignment with
* respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
* subtly out of sync with those recorded in the vmlinux when kaslr is
* disabled but the image required relocation anyway. Therefore retain
* 2M alignment if KASLR was explicitly disabled, even if it was not
* going to be activated to begin with.
*/
return
efi_nokaslr
?
MIN_KIMG_ALIGN
:
EFI_KIMG_ALIGN
;
}
#define EFI_ALLOC_ALIGN SZ_64K
...
...
arch/arm64/kernel/Makefile
View file @
97712289
...
...
@@ -36,12 +36,6 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
syscall.o proton-pack.o idreg-override.o idle.o
\
patching.o
targets
+=
efi-entry.o
OBJCOPYFLAGS
:=
--prefix-symbols
=
__efistub_
$(obj)/%.stub.o
:
$(obj)/%.o FORCE
$(
call
if_changed,objcopy
)
obj-$(CONFIG_COMPAT)
+=
sys32.o signal32.o
\
sys_compat.o
obj-$(CONFIG_COMPAT)
+=
sigreturn32.o
...
...
@@ -57,8 +51,7 @@ obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
obj-$(CONFIG_CPU_IDLE)
+=
cpuidle.o
obj-$(CONFIG_JUMP_LABEL)
+=
jump_label.o
obj-$(CONFIG_KGDB)
+=
kgdb.o
obj-$(CONFIG_EFI)
+=
efi.o efi-entry.stub.o
\
efi-rt-wrapper.o
obj-$(CONFIG_EFI)
+=
efi.o efi-rt-wrapper.o
obj-$(CONFIG_PCI)
+=
pci.o
obj-$(CONFIG_ARMV8_DEPRECATED)
+=
armv8_deprecated.o
obj-$(CONFIG_ACPI)
+=
acpi.o
...
...
arch/arm64/kernel/image-vars.h
View file @
97712289
...
...
@@ -10,7 +10,6 @@
#error This file should only be included in vmlinux.lds.S
#endif
PROVIDE
(
__efistub_kernel_size
=
_edata
-
_text
);
PROVIDE
(
__efistub_primary_entry_offset
=
primary_entry
-
_text
);
/*
...
...
@@ -22,13 +21,6 @@ PROVIDE(__efistub_primary_entry_offset = primary_entry - _text);
* linked at. The routines below are all implemented in assembler in a
* position independent manner
*/
PROVIDE
(
__efistub_memcmp
=
__pi_memcmp
);
PROVIDE
(
__efistub_memchr
=
__pi_memchr
);
PROVIDE
(
__efistub_strlen
=
__pi_strlen
);
PROVIDE
(
__efistub_strnlen
=
__pi_strnlen
);
PROVIDE
(
__efistub_strcmp
=
__pi_strcmp
);
PROVIDE
(
__efistub_strncmp
=
__pi_strncmp
);
PROVIDE
(
__efistub_strrchr
=
__pi_strrchr
);
PROVIDE
(
__efistub_dcache_clean_poc
=
__pi_dcache_clean_poc
);
PROVIDE
(
__efistub__text
=
_text
);
...
...
arch/loongarch/include/asm/efi.h
View file @
97712289
...
...
@@ -19,18 +19,18 @@ void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
#define EFI_ALLOC_ALIGN SZ_64K
#define EFI_RT_VIRTUAL_OFFSET CSR_DMW0_BASE
static
inline
struct
screen_info
*
alloc_screen_info
(
void
)
static
inline
unsigned
long
efi_get_max_initrd_addr
(
unsigned
long
image_addr
)
{
return
&
screen_info
;
return
ULONG_MAX
;
}
static
inline
void
free_screen_info
(
struct
screen_info
*
si
)
static
inline
unsigned
long
efi_get_kimg_min_align
(
void
)
{
return
SZ_2M
;
}
static
inline
unsigned
long
efi_get_max_initrd_addr
(
unsigned
long
image_addr
)
{
return
ULONG_MAX
;
}
#define EFI_KIMG_PREFERRED_ADDRESS PHYSADDR(VMLINUX_LOAD_ADDRESS)
unsigned
long
kernel_entry_address
(
void
);
#endif
/* _ASM_LOONGARCH_EFI_H */
arch/loongarch/kernel/efi.c
View file @
97712289
...
...
@@ -52,6 +52,27 @@ void __init efi_runtime_init(void)
set_bit
(
EFI_RUNTIME_SERVICES
,
&
efi
.
flags
);
}
unsigned
long
__initdata
screen_info_table
=
EFI_INVALID_TABLE_ADDR
;
static
void
__init
init_screen_info
(
void
)
{
struct
screen_info
*
si
;
if
(
screen_info_table
==
EFI_INVALID_TABLE_ADDR
)
return
;
si
=
early_memremap
(
screen_info_table
,
sizeof
(
*
si
));
if
(
!
si
)
{
pr_err
(
"Could not map screen_info config table
\n
"
);
return
;
}
screen_info
=
*
si
;
memset
(
si
,
0
,
sizeof
(
*
si
));
early_memunmap
(
si
,
sizeof
(
*
si
));
memblock_reserve
(
screen_info
.
lfb_base
,
screen_info
.
lfb_size
);
}
void
__init
efi_init
(
void
)
{
int
size
;
...
...
@@ -80,8 +101,7 @@ void __init efi_init(void)
set_bit
(
EFI_CONFIG_TABLES
,
&
efi
.
flags
);
if
(
screen_info
.
orig_video_isVGA
==
VIDEO_TYPE_EFI
)
memblock_reserve
(
screen_info
.
lfb_base
,
screen_info
.
lfb_size
);
init_screen_info
();
if
(
boot_memmap
==
EFI_INVALID_TABLE_ADDR
)
return
;
...
...
arch/loongarch/kernel/image-vars.h
View file @
97712289
...
...
@@ -7,15 +7,7 @@
#ifdef CONFIG_EFI_STUB
__efistub_memcmp
=
memcmp
;
__efistub_memchr
=
memchr
;
__efistub_strcat
=
strcat
;
__efistub_strcmp
=
strcmp
;
__efistub_strlen
=
strlen
;
__efistub_strncat
=
strncat
;
__efistub_strnstr
=
strnstr
;
__efistub_strnlen
=
strnlen
;
__efistub_strrchr
=
strrchr
;
__efistub_kernel_entry
=
kernel_entry
;
__efistub_kernel_asize
=
kernel_asize
;
__efistub_kernel_fsize
=
kernel_fsize
;
...
...
arch/riscv/include/asm/efi.h
View file @
97712289
...
...
@@ -31,13 +31,20 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
return
ULONG_MAX
;
}
#define alloc_screen_info(x...) (&screen_info)
static
inline
void
free_screen_info
(
struct
screen_info
*
si
)
static
inline
unsigned
long
efi_get_kimg_min_align
(
void
)
{
/*
* RISC-V requires the kernel image to placed 2 MB aligned base for 64
* bit and 4MB for 32 bit.
*/
return
IS_ENABLED
(
CONFIG_64BIT
)
?
SZ_2M
:
SZ_4M
;
}
#define EFI_KIMG_PREFERRED_ADDRESS efi_get_kimg_min_align()
void
efi_virtmap_load
(
void
);
void
efi_virtmap_unload
(
void
);
unsigned
long
stext_offset
(
void
);
#endif
/* _ASM_EFI_H */
arch/riscv/kernel/image-vars.h
View file @
97712289
...
...
@@ -23,13 +23,7 @@
* linked at. The routines below are all implemented in assembler in a
* position independent manner
*/
__efistub_memcmp
=
memcmp
;
__efistub_memchr
=
memchr
;
__efistub_strlen
=
strlen
;
__efistub_strnlen
=
strnlen
;
__efistub_strcmp
=
strcmp
;
__efistub_strncmp
=
strncmp
;
__efistub_strrchr
=
strrchr
;
__efistub__start
=
_start
;
__efistub__start_kernel
=
_start_kernel
;
...
...
drivers/firmware/efi/efi-init.c
View file @
97712289
...
...
@@ -22,6 +22,8 @@
#include <asm/efi.h>
unsigned
long
__initdata
screen_info_table
=
EFI_INVALID_TABLE_ADDR
;
static
int
__init
is_memory
(
efi_memory_desc_t
*
md
)
{
if
(
md
->
attribute
&
(
EFI_MEMORY_WB
|
EFI_MEMORY_WT
|
EFI_MEMORY_WC
))
...
...
@@ -55,9 +57,22 @@ extern __weak const efi_config_table_type_t efi_arch_tables[];
static
void
__init
init_screen_info
(
void
)
{
if
(
screen_info
.
orig_video_isVGA
==
VIDEO_TYPE_EFI
&&
memblock_is_map_memory
(
screen_info
.
lfb_base
))
memblock_mark_nomap
(
screen_info
.
lfb_base
,
screen_info
.
lfb_size
);
struct
screen_info
*
si
;
if
(
screen_info_table
!=
EFI_INVALID_TABLE_ADDR
)
{
si
=
early_memremap
(
screen_info_table
,
sizeof
(
*
si
));
if
(
!
si
)
{
pr_err
(
"Could not map screen_info config table
\n
"
);
return
;
}
screen_info
=
*
si
;
memset
(
si
,
0
,
sizeof
(
*
si
));
early_memunmap
(
si
,
sizeof
(
*
si
));
if
(
memblock_is_map_memory
(
screen_info
.
lfb_base
))
memblock_mark_nomap
(
screen_info
.
lfb_base
,
screen_info
.
lfb_size
);
}
}
static
int
__init
uefi_init
(
u64
efi_system_table
)
...
...
drivers/firmware/efi/efi.c
View file @
97712289
...
...
@@ -58,6 +58,8 @@ static unsigned long __initdata mem_reserve = EFI_INVALID_TABLE_ADDR;
static
unsigned
long
__initdata
rt_prop
=
EFI_INVALID_TABLE_ADDR
;
static
unsigned
long
__initdata
initrd
=
EFI_INVALID_TABLE_ADDR
;
extern
unsigned
long
screen_info_table
;
struct
mm_struct
efi_mm
=
{
.
mm_mt
=
MTREE_INIT_EXT
(
mm_mt
,
MM_MT_FLAGS
,
efi_mm
.
mmap_lock
),
.
mm_users
=
ATOMIC_INIT
(
2
),
...
...
@@ -546,6 +548,9 @@ static const efi_config_table_type_t common_tables[] __initconst = {
#endif
#ifdef CONFIG_EFI_COCO_SECRET
{
LINUX_EFI_COCO_SECRET_AREA_GUID
,
&
efi
.
coco_secret
,
"CocoSecret"
},
#endif
#ifdef CONFIG_EFI_GENERIC_STUB
{
LINUX_EFI_SCREEN_INFO_TABLE_GUID
,
&
screen_info_table
},
#endif
{},
};
...
...
drivers/firmware/efi/libstub/Makefile
View file @
97712289
...
...
@@ -5,6 +5,10 @@
# things like ftrace and stack-protector are likely to cause trouble if left
# enabled, even if doing so doesn't break the build.
#
# non-x86 reuses KBUILD_CFLAGS, x86 does not
cflags-y
:=
$(KBUILD_CFLAGS)
cflags-$(CONFIG_X86_32)
:=
-march
=
i386
cflags-$(CONFIG_X86_64)
:=
-mcmodel
=
small
cflags-$(CONFIG_X86)
+=
-m
$(BITS)
-D__KERNEL__
\
...
...
@@ -18,20 +22,19 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
# arm64 uses the full KBUILD_CFLAGS so it's necessary to explicitly
# disable the stackleak plugin
cflags-$(CONFIG_ARM64)
:=
$(
subst
$(CC_FLAGS_FTRACE)
,,
$(KBUILD_CFLAGS)
)
\
-fpie
$(DISABLE_STACKLEAK_PLUGIN)
\
cflags-$(CONFIG_ARM64)
+=
-fpie
$(DISABLE_STACKLEAK_PLUGIN)
\
$(
call
cc-option,-mbranch-protection
=
none
)
cflags-$(CONFIG_ARM)
:=
$(
subst
$(CC_FLAGS_FTRACE)
,,
$(KBUILD_CFLAGS)
)
\
-fno-builtin
-fpic
\
cflags-$(CONFIG_ARM)
+=
-DEFI_HAVE_STRLEN
-DEFI_HAVE_STRNLEN
\
-DEFI_HAVE_MEMCHR
-DEFI_HAVE_STRRCHR
\
-DEFI_HAVE_STRCMP
-fno-builtin
-fpic
\
$(
call
cc-option,-mno-single-pic-base
)
cflags-$(CONFIG_RISCV)
:=
$(
subst
$(CC_FLAGS_FTRACE)
,,
$(KBUILD_CFLAGS)
)
\
-fpic
cflags-$(CONFIG_LOONGARCH)
:=
$(
subst
$(CC_FLAGS_FTRACE)
,,
$(KBUILD_CFLAGS)
)
\
-fpie
cflags-$(CONFIG_RISCV)
+=
-fpic
cflags-$(CONFIG_LOONGARCH)
+=
-fpie
cflags-$(CONFIG_EFI_PARAMS_FROM_FDT)
+=
-I
$(srctree)
/scripts/dtc/libfdt
KBUILD_CFLAGS
:=
$
(
cflags-y
)
-Os
-DDISABLE_BRANCH_PROFILING
\
KBUILD_CFLAGS
:=
$(
subst
$(CC_FLAGS_FTRACE)
,,
$
(
cflags-y
))
\
-Os
-DDISABLE_BRANCH_PROFILING
\
-include
$(srctree)
/include/linux/hidden.h
\
-D__NO_FORTIFY
\
-ffreestanding
\
...
...
@@ -67,7 +70,7 @@ KCOV_INSTRUMENT := n
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
\
alignedmem.o relocate.o vsprintf.o
alignedmem.o relocate.o
printk.o
vsprintf.o
# include the stub's libfdt dependencies from lib/ when needed
libfdt-deps
:=
fdt_rw.c fdt_ro.c fdt_wip.c fdt.c
\
...
...
@@ -79,13 +82,14 @@ lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \
$(obj)/lib-%.o
:
$(srctree)/lib/%.c FORCE
$(
call
if_changed_rule,cc_o_c
)
lib-$(CONFIG_EFI_GENERIC_STUB)
+=
efi-stub.o string.o intrinsics.o systable.o
lib-$(CONFIG_EFI_GENERIC_STUB)
+=
efi-stub.o string.o intrinsics.o systable.o
\
screen_info.o efi-stub-entry.o
lib-$(CONFIG_ARM)
+=
arm32-stub.o
lib-$(CONFIG_ARM64)
+=
arm64
-stub
.o smbios.o
lib-$(CONFIG_ARM64)
+=
arm64
.o arm64-stub.o arm64-entry
.o smbios.o
lib-$(CONFIG_X86)
+=
x86-stub.o
lib-$(CONFIG_RISCV)
+=
riscv-stub.o
lib-$(CONFIG_LOONGARCH)
+=
loongarch-stub.o
lib-$(CONFIG_RISCV)
+=
riscv
.o riscv
-stub.o
lib-$(CONFIG_LOONGARCH)
+=
loongarch
.o loongarch
-stub.o
CFLAGS_arm32-stub.o
:=
-DTEXT_OFFSET
=
$(TEXT_OFFSET)
...
...
@@ -136,7 +140,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS
#
STUBCOPY_FLAGS-$(CONFIG_ARM64)
+=
--prefix-alloc-sections
=
.init
\
--prefix-symbols
=
__efistub_
STUBCOPY_RELOC-$(CONFIG_ARM64)
:=
R_AARCH64_ABS
STUBCOPY_RELOC-$(CONFIG_ARM64)
:=
R_AARCH64_ABS
64
# For RISC-V, we don't need anything special other than arm64. Keep all the
# symbols in .init section and make sure that no absolute symbols references
...
...
drivers/firmware/efi/libstub/Makefile.zboot
View file @
97712289
...
...
@@ -10,18 +10,17 @@ 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
zboot-method-$(CONFIG_KERNEL_GZIP)
:=
gzip
zboot-size-len-$(CONFIG_KERNEL_GZIP)
:=
0
# Copy the SizeOfHeaders, SizeOfCode and SizeOfImage fields from the payload to
# the end of the compressed image. Note that this presupposes a PE header
# offset of 64 bytes, which is what arm64, RISC-V and LoongArch use.
quiet_cmd_compwithsize
=
$
(
quiet_cmd_
$
(
comp-type-y
))
cmd_compwithsize
=
$
(
cmd_
$
(
comp-type-y
))
&&
(
\
dd
status
=
none
if
=
$<
bs
=
4
count
=
1
skip
=
37
;
\
dd
status
=
none
if
=
$<
bs
=
4
count
=
1
skip
=
23
;
\
dd
status
=
none
if
=
$<
bs
=
4
count
=
1
skip
=
36
)
>>
$@
$(obj)/vmlinuz
:
$(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
$(
call
if_changed,
$
(
zboot-method-y
)
)
$(
call
if_changed,
compwithsize
)
OBJCOPYFLAGS_vmlinuz.o
:=
-I
binary
-O
$(EFI_ZBOOT_BFD_TARGET)
\
--rename-section
.data
=
.gzdata,load,alloc,readonly,contents
...
...
@@ -30,7 +29,6 @@ $(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE
AFLAGS_zboot-header.o
+=
-DMACHINE_TYPE
=
IMAGE_FILE_MACHINE_
$(EFI_ZBOOT_MACH_TYPE)
\
-DZBOOT_EFI_PATH
=
"
\"
$(
realpath
$(obj)
/vmlinuz.efi.elf
)
\"
"
\
-DZBOOT_SIZE_LEN
=
$
(
zboot-size-len-y
)
\
-DCOMP_TYPE
=
"
\"
$
(comp-type-y)
\"
"
$(obj)/zboot-header.o
:
$(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
...
...
@@ -46,4 +44,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
$(obj)/vmlinuz.efi
:
$(obj)/vmlinuz.efi.elf FORCE
$(
call
if_changed,objcopy
)
targets
+=
zboot-header.o vmlinuz
vmlinuz
.o vmlinuz.efi.elf vmlinuz.efi
targets
+=
zboot-header.o vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
drivers/firmware/efi/libstub/arm32-stub.c
View file @
97712289
...
...
@@ -76,43 +76,6 @@ void efi_handle_post_ebs_state(void)
&
efi_entry_state
->
sctlr_after_ebs
);
}
static
efi_guid_t
screen_info_guid
=
LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID
;
struct
screen_info
*
alloc_screen_info
(
void
)
{
struct
screen_info
*
si
;
efi_status_t
status
;
/*
* Unlike on arm64, where we can directly fill out the screen_info
* structure from the stub, we need to allocate a buffer to hold
* its contents while we hand over to the kernel proper from the
* decompressor.
*/
status
=
efi_bs_call
(
allocate_pool
,
EFI_RUNTIME_SERVICES_DATA
,
sizeof
(
*
si
),
(
void
**
)
&
si
);
if
(
status
!=
EFI_SUCCESS
)
return
NULL
;
status
=
efi_bs_call
(
install_configuration_table
,
&
screen_info_guid
,
si
);
if
(
status
==
EFI_SUCCESS
)
return
si
;
efi_bs_call
(
free_pool
,
si
);
return
NULL
;
}
void
free_screen_info
(
struct
screen_info
*
si
)
{
if
(
!
si
)
return
;
efi_bs_call
(
install_configuration_table
,
&
screen_info_guid
,
NULL
);
efi_bs_call
(
free_pool
,
si
);
}
efi_status_t
handle_kernel_image
(
unsigned
long
*
image_addr
,
unsigned
long
*
image_size
,
unsigned
long
*
reserve_addr
,
...
...
arch/arm64/kernel/efi
-entry.S
→
drivers/firmware/efi/libstub/arm64
-entry.S
View file @
97712289
...
...
@@ -6,11 +6,17 @@
*
Author
:
Mark
Salter
<
msalter
@
redhat
.
com
>
*/
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>
__INIT
/
*
*
The
entrypoint
of
a
arm64
bare
metal
image
is
at
offset
#
0
of
the
*
image
,
so
this
is
a
reasonable
default
for
primary_entry_offset
.
*
Only
when
the
EFI
stub
is
integrated
into
the
core
kernel
,
it
is
not
*
guaranteed
that
the
PE
/
COFF
header
has
been
copied
to
memory
too
,
so
*
in
this
case
,
primary_entry_offset
should
be
overridden
by
the
*
linker
and
point
to
primary_entry
()
directly
.
*/
.
weak
primary_entry_offset
SYM_CODE_START
(
efi_enter_kernel
)
/
*
...
...
@@ -21,49 +27,41 @@ SYM_CODE_START(efi_enter_kernel)
*/
ldr
w2
,
=
primary_entry_offset
add
x19
,
x0
,
x2
//
relocated
Image
entrypoint
mov
x20
,
x1
//
DTB
address
/
*
*
Clean
the
copied
Image
to
the
PoC
,
and
ensure
it
is
not
shadowed
by
*
stale
icache
entries
from
before
relocation
.
*/
ldr
w1
,
=
kernel_size
add
x1
,
x0
,
x1
bl
dcache_clean_poc
ic
ialluis
mov
x0
,
x1
//
DTB
address
mov
x1
,
xzr
mov
x2
,
xzr
mov
x3
,
xzr
/
*
*
Clean
the
remainder
of
this
routine
to
the
PoC
*
so
that
we
can
safely
disable
the
MMU
and
caches
.
*/
adr
x
0
,
0
f
adr
x1
,
3
f
bl
dcache_clean_poc
0
:
adr
x
4
,
1
f
dc
civac
,
x4
dsb
sy
/
*
Turn
off
Dcache
and
MMU
*/
mrs
x0
,
CurrentEL
cmp
x0
,
#
CurrentEL_EL2
b.ne
1
f
mrs
x0
,
sctlr_el2
bic
x0
,
x0
,
#
1
<<
0
//
clear
SCTLR
.
M
bic
x0
,
x0
,
#
1
<<
2
//
clear
SCTLR
.
C
pre_disable_mmu_workaround
msr
sctlr_el2
,
x0
isb
mrs
x4
,
CurrentEL
cmp
x4
,
#
CurrentEL_EL2
mrs
x4
,
sctlr_el1
b.ne
0
f
mrs
x4
,
sctlr_el2
0
:
bic
x4
,
x4
,
#
SCTLR_ELx_M
bic
x4
,
x4
,
#
SCTLR_ELx_C
b.eq
1
f
b
2
f
1
:
mrs
x0
,
sctlr_el1
bic
x0
,
x0
,
#
1
<<
0
//
clear
SCTLR
.
M
bic
x0
,
x0
,
#
1
<<
2
//
clear
SCTLR
.
C
pre_disable_mmu_workaround
msr
sctlr_el1
,
x0
.
balign
32
1
:
pre_disable_mmu_workaround
msr
sctlr_el2
,
x4
isb
2
:
/
*
Jump
to
kernel
entry
point
*/
mov
x0
,
x20
m
ov
x1
,
xzr
mov
x2
,
xzr
mov
x3
,
xzr
br
x19
3
:
br
x19
//
jump
to
kernel
entrypoint
2
:
pre_disable_mmu_workaround
m
sr
sctlr_el1
,
x4
isb
br
x19
//
jump
to
kernel
entrypoint
.
org
1
b
+
32
SYM_CODE_END
(
efi_enter_kernel
)
drivers/firmware/efi/libstub/arm64-stub.c
View file @
97712289
...
...
@@ -11,52 +11,9 @@
#include <asm/efi.h>
#include <asm/memory.h>
#include <asm/sections.h>
#include <asm/sysreg.h>
#include "efistub.h"
static
bool
system_needs_vamap
(
void
)
{
const
u8
*
type1_family
=
efi_get_smbios_string
(
1
,
family
);
/*
* Ampere Altra machines crash in SetTime() if SetVirtualAddressMap()
* has not been called prior.
*/
if
(
!
type1_family
||
strcmp
(
type1_family
,
"Altra"
))
return
false
;
efi_warn
(
"Working around broken SetVirtualAddressMap()
\n
"
);
return
true
;
}
efi_status_t
check_platform_features
(
void
)
{
u64
tg
;
/*
* If we have 48 bits of VA space for TTBR0 mappings, we can map the
* UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
* unnecessary.
*/
if
(
VA_BITS_MIN
>=
48
&&
!
system_needs_vamap
())
efi_novamap
=
true
;
/* UEFI mandates support for 4 KB granularity, no need to check */
if
(
IS_ENABLED
(
CONFIG_ARM64_4K_PAGES
))
return
EFI_SUCCESS
;
tg
=
(
read_cpuid
(
ID_AA64MMFR0_EL1
)
>>
ID_AA64MMFR0_EL1_TGRAN_SHIFT
)
&
0xf
;
if
(
tg
<
ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN
||
tg
>
ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX
)
{
if
(
IS_ENABLED
(
CONFIG_ARM64_64K_PAGES
))
efi_err
(
"This 64 KB granular kernel is not supported by your CPU
\n
"
);
else
efi_err
(
"This 16 KB granular kernel is not supported by your CPU
\n
"
);
return
EFI_UNSUPPORTED
;
}
return
EFI_SUCCESS
;
}
/*
* Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
* to provide space, and fail to zero it). Check for this condition by double
...
...
@@ -103,16 +60,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_status_t
status
;
unsigned
long
kernel_size
,
kernel_memsize
=
0
;
u32
phys_seed
=
0
;
/*
* Although relocatable kernels can fix up the misalignment with
* respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
* subtly out of sync with those recorded in the vmlinux when kaslr is
* disabled but the image required relocation anyway. Therefore retain
* 2M alignment if KASLR was explicitly disabled, even if it was not
* going to be activated to begin with.
*/
u64
min_kimg_align
=
efi_nokaslr
?
MIN_KIMG_ALIGN
:
EFI_KIMG_ALIGN
;
u64
min_kimg_align
=
efi_get_kimg_min_align
();
if
(
IS_ENABLED
(
CONFIG_RANDOMIZE_BASE
))
{
efi_guid_t
li_fixed_proto
=
LINUX_EFI_LOADED_IMAGE_FIXED_GUID
;
...
...
@@ -171,7 +119,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
*/
*
image_addr
=
(
u64
)
_text
;
*
reserve_size
=
0
;
return
EFI_SUCCESS
;
goto
clean_image_to_poc
;
}
status
=
efi_allocate_pages_aligned
(
*
reserve_size
,
reserve_addr
,
...
...
@@ -187,5 +135,13 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
*
image_addr
=
*
reserve_addr
;
memcpy
((
void
*
)
*
image_addr
,
_text
,
kernel_size
);
clean_image_to_poc:
/*
* Clean the copied Image to the PoC, and ensure it is not shadowed by
* stale icache entries from before relocation.
*/
dcache_clean_poc
(
*
image_addr
,
*
image_addr
+
kernel_size
);
asm
(
"ic ialluis"
);
return
EFI_SUCCESS
;
}
drivers/firmware/efi/libstub/arm64.c
0 → 100644
View file @
97712289
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org>
*
* This file implements the EFI boot stub for the arm64 kernel.
* Adapted from ARM version by Mark Salter <msalter@redhat.com>
*/
#include <linux/efi.h>
#include <asm/efi.h>
#include <asm/memory.h>
#include <asm/sysreg.h>
#include "efistub.h"
static
bool
system_needs_vamap
(
void
)
{
const
u8
*
type1_family
=
efi_get_smbios_string
(
1
,
family
);
/*
* Ampere Altra machines crash in SetTime() if SetVirtualAddressMap()
* has not been called prior.
*/
if
(
!
type1_family
||
strcmp
(
type1_family
,
"Altra"
))
return
false
;
efi_warn
(
"Working around broken SetVirtualAddressMap()
\n
"
);
return
true
;
}
efi_status_t
check_platform_features
(
void
)
{
u64
tg
;
/*
* If we have 48 bits of VA space for TTBR0 mappings, we can map the
* UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
* unnecessary.
*/
if
(
VA_BITS_MIN
>=
48
&&
!
system_needs_vamap
())
efi_novamap
=
true
;
/* UEFI mandates support for 4 KB granularity, no need to check */
if
(
IS_ENABLED
(
CONFIG_ARM64_4K_PAGES
))
return
EFI_SUCCESS
;
tg
=
(
read_cpuid
(
ID_AA64MMFR0_EL1
)
>>
ID_AA64MMFR0_EL1_TGRAN_SHIFT
)
&
0xf
;
if
(
tg
<
ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN
||
tg
>
ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX
)
{
if
(
IS_ENABLED
(
CONFIG_ARM64_64K_PAGES
))
efi_err
(
"This 64 KB granular kernel is not supported by your CPU
\n
"
);
else
efi_err
(
"This 16 KB granular kernel is not supported by your CPU
\n
"
);
return
EFI_UNSUPPORTED
;
}
return
EFI_SUCCESS
;
}
void
efi_cache_sync_image
(
unsigned
long
image_base
,
unsigned
long
alloc_size
,
unsigned
long
code_size
)
{
u32
ctr
=
read_cpuid_effective_cachetype
();
u64
lsize
=
4
<<
cpuid_feature_extract_unsigned_field
(
ctr
,
CTR_EL0_DminLine_SHIFT
);
do
{
asm
(
"dc civac, %0"
::
"r"
(
image_base
));
image_base
+=
lsize
;
alloc_size
-=
lsize
;
}
while
(
alloc_size
>=
lsize
);
asm
(
"ic ialluis"
);
dsb
(
ish
);
isb
();
}
drivers/firmware/efi/libstub/efi-stub-entry.c
0 → 100644
View file @
97712289
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/efi.h>
#include <asm/efi.h>
#include "efistub.h"
/*
* EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
* LoongArch. This is the entrypoint that is described in the PE/COFF header
* of the core kernel.
*/
efi_status_t
__efiapi
efi_pe_entry
(
efi_handle_t
handle
,
efi_system_table_t
*
systab
)
{
efi_loaded_image_t
*
image
;
efi_status_t
status
;
unsigned
long
image_addr
;
unsigned
long
image_size
=
0
;
/* addr/point and size pairs for memory management*/
char
*
cmdline_ptr
=
NULL
;
efi_guid_t
loaded_image_proto
=
LOADED_IMAGE_PROTOCOL_GUID
;
unsigned
long
reserve_addr
=
0
;
unsigned
long
reserve_size
=
0
;
WRITE_ONCE
(
efi_system_table
,
systab
);
/* Check if we were booted by the EFI firmware */
if
(
efi_system_table
->
hdr
.
signature
!=
EFI_SYSTEM_TABLE_SIGNATURE
)
return
EFI_INVALID_PARAMETER
;
/*
* Get a handle to the loaded image protocol. This is used to get
* information about the running image, such as size and the command
* line.
*/
status
=
efi_bs_call
(
handle_protocol
,
handle
,
&
loaded_image_proto
,
(
void
*
)
&
image
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to get loaded image protocol
\n
"
);
return
status
;
}
status
=
efi_handle_cmdline
(
image
,
&
cmdline_ptr
);
if
(
status
!=
EFI_SUCCESS
)
return
status
;
efi_info
(
"Booting Linux Kernel...
\n
"
);
status
=
handle_kernel_image
(
&
image_addr
,
&
image_size
,
&
reserve_addr
,
&
reserve_size
,
image
,
handle
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to relocate kernel
\n
"
);
return
status
;
}
status
=
efi_stub_common
(
handle
,
image
,
image_addr
,
cmdline_ptr
);
efi_free
(
image_size
,
image_addr
);
efi_free
(
reserve_size
,
reserve_addr
);
return
status
;
}
drivers/firmware/efi/libstub/efi-stub-helper.c
View file @
97712289
...
...
@@ -9,10 +9,8 @@
#include <linux/stdarg.h>
#include <linux/ctype.h>
#include <linux/efi.h>
#include <linux/kernel.h>
#include <linux/printk.h>
/* For CONSOLE_LOGLEVEL_* */
#include <asm/efi.h>
#include <asm/setup.h>
...
...
@@ -20,7 +18,6 @@
bool
efi_nochunk
;
bool
efi_nokaslr
=
!
IS_ENABLED
(
CONFIG_RANDOMIZE_BASE
);
int
efi_loglevel
=
CONSOLE_LOGLEVEL_DEFAULT
;
bool
efi_novamap
;
static
bool
efi_noinitrd
;
...
...
@@ -32,146 +29,6 @@ bool __pure __efi_soft_reserve_enabled(void)
return
!
efi_nosoftreserve
;
}
/**
* efi_char16_puts() - Write a UCS-2 encoded string to the console
* @str: UCS-2 encoded string
*/
void
efi_char16_puts
(
efi_char16_t
*
str
)
{
efi_call_proto
(
efi_table_attr
(
efi_system_table
,
con_out
),
output_string
,
str
);
}
static
u32
utf8_to_utf32
(
const
u8
**
s8
)
{
u32
c32
;
u8
c0
,
cx
;
size_t
clen
,
i
;
c0
=
cx
=
*
(
*
s8
)
++
;
/*
* The position of the most-significant 0 bit gives us the length of
* a multi-octet encoding.
*/
for
(
clen
=
0
;
cx
&
0x80
;
++
clen
)
cx
<<=
1
;
/*
* If the 0 bit is in position 8, this is a valid single-octet
* encoding. If the 0 bit is in position 7 or positions 1-3, the
* encoding is invalid.
* In either case, we just return the first octet.
*/
if
(
clen
<
2
||
clen
>
4
)
return
c0
;
/* Get the bits from the first octet. */
c32
=
cx
>>
clen
--
;
for
(
i
=
0
;
i
<
clen
;
++
i
)
{
/* Trailing octets must have 10 in most significant bits. */
cx
=
(
*
s8
)[
i
]
^
0x80
;
if
(
cx
&
0xc0
)
return
c0
;
c32
=
(
c32
<<
6
)
|
cx
;
}
/*
* Check for validity:
* - The character must be in the Unicode range.
* - It must not be a surrogate.
* - It must be encoded using the correct number of octets.
*/
if
(
c32
>
0x10ffff
||
(
c32
&
0xf800
)
==
0xd800
||
clen
!=
(
c32
>=
0x80
)
+
(
c32
>=
0x800
)
+
(
c32
>=
0x10000
))
return
c0
;
*
s8
+=
clen
;
return
c32
;
}
/**
* efi_puts() - Write a UTF-8 encoded string to the console
* @str: UTF-8 encoded string
*/
void
efi_puts
(
const
char
*
str
)
{
efi_char16_t
buf
[
128
];
size_t
pos
=
0
,
lim
=
ARRAY_SIZE
(
buf
);
const
u8
*
s8
=
(
const
u8
*
)
str
;
u32
c32
;
while
(
*
s8
)
{
if
(
*
s8
==
'\n'
)
buf
[
pos
++
]
=
L'\r'
;
c32
=
utf8_to_utf32
(
&
s8
);
if
(
c32
<
0x10000
)
{
/* Characters in plane 0 use a single word. */
buf
[
pos
++
]
=
c32
;
}
else
{
/*
* Characters in other planes encode into a surrogate
* pair.
*/
buf
[
pos
++
]
=
(
0xd800
-
(
0x10000
>>
10
))
+
(
c32
>>
10
);
buf
[
pos
++
]
=
0xdc00
+
(
c32
&
0x3ff
);
}
if
(
*
s8
==
'\0'
||
pos
>=
lim
-
2
)
{
buf
[
pos
]
=
L'\0'
;
efi_char16_puts
(
buf
);
pos
=
0
;
}
}
}
/**
* efi_printk() - Print a kernel message
* @fmt: format string
*
* The first letter of the format string is used to determine the logging level
* of the message. If the level is less then the current EFI logging level, the
* message is suppressed. The message will be truncated to 255 bytes.
*
* Return: number of printed characters
*/
int
efi_printk
(
const
char
*
fmt
,
...)
{
char
printf_buf
[
256
];
va_list
args
;
int
printed
;
int
loglevel
=
printk_get_level
(
fmt
);
switch
(
loglevel
)
{
case
'0'
...
'9'
:
loglevel
-=
'0'
;
break
;
default:
/*
* Use loglevel -1 for cases where we just want to print to
* the screen.
*/
loglevel
=
-
1
;
break
;
}
if
(
loglevel
>=
efi_loglevel
)
return
0
;
if
(
loglevel
>=
0
)
efi_puts
(
"EFI stub: "
);
fmt
=
printk_skip_level
(
fmt
);
va_start
(
args
,
fmt
);
printed
=
vsnprintf
(
printf_buf
,
sizeof
(
printf_buf
),
fmt
,
args
);
va_end
(
args
);
efi_puts
(
printf_buf
);
if
(
printed
>=
sizeof
(
printf_buf
))
{
efi_puts
(
"[Message truncated]
\n
"
);
return
-
1
;
}
return
printed
;
}
/**
* efi_parse_options() - Parse EFI command line options
* @cmdline: kernel command line
...
...
drivers/firmware/efi/libstub/efi-stub.c
View file @
97712289
...
...
@@ -35,15 +35,6 @@
* as well to minimize the code churn.
*/
#define EFI_RT_VIRTUAL_BASE SZ_512M
#define EFI_RT_VIRTUAL_SIZE SZ_512M
#ifdef CONFIG_ARM64
# define EFI_RT_VIRTUAL_LIMIT DEFAULT_MAP_WINDOW_64
#elif defined(CONFIG_RISCV) || defined(CONFIG_LOONGARCH)
# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE_MIN
#else
/* Only if TASK_SIZE is a constant */
# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE
#endif
/*
* Some architectures map the EFI regions into the kernel's linear map using a
...
...
@@ -56,6 +47,15 @@
static
u64
virtmap_base
=
EFI_RT_VIRTUAL_BASE
;
static
bool
flat_va_mapping
=
(
EFI_RT_VIRTUAL_OFFSET
!=
0
);
struct
screen_info
*
__weak
alloc_screen_info
(
void
)
{
return
&
screen_info
;
}
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
;
...
...
@@ -115,62 +115,21 @@ static u32 get_supported_rt_services(void)
return
supported
;
}
/*
* EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
* that is described in the PE/COFF header. Most of the code is the same
* for both archictectures, with the arch-specific code provided in the
* handle_kernel_image() function.
*/
efi_status_t
__efiapi
efi_pe_entry
(
efi_handle_t
handle
,
efi_system_table_t
*
sys_table_arg
)
efi_status_t
efi_handle_cmdline
(
efi_loaded_image_t
*
image
,
char
**
cmdline_ptr
)
{
efi_loaded_image_t
*
image
;
efi_status_t
status
;
unsigned
long
image_addr
;
unsigned
long
image_size
=
0
;
/* addr/point and size pairs for memory management*/
char
*
cmdline_ptr
=
NULL
;
int
cmdline_size
=
0
;
efi_guid_t
loaded_image_proto
=
LOADED_IMAGE_PROTOCOL_GUID
;
unsigned
long
reserve_addr
=
0
;
unsigned
long
reserve_size
=
0
;
struct
screen_info
*
si
;
efi_properties_table_t
*
prop_tbl
;
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
)
{
status
=
EFI_INVALID_PARAMETER
;
goto
fail
;
}
status
=
check_platform_features
();
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
/*
* Get a handle to the loaded image protocol. This is used to get
* information about the running image, such as size and the command
* line.
*/
status
=
efi_bs_call
(
handle_protocol
,
handle
,
&
loaded_image_proto
,
(
void
*
)
&
image
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to get loaded image protocol
\n
"
);
goto
fail
;
}
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
_ptr
=
efi_convert_cmdline
(
image
,
&
cmdline_size
);
if
(
!
cmdline
_ptr
)
{
cmdline
=
efi_convert_cmdline
(
image
,
&
cmdline_size
);
if
(
!
cmdline
)
{
efi_err
(
"getting command line via LOADED_IMAGE_PROTOCOL
\n
"
);
status
=
EFI_OUT_OF_RESOURCES
;
goto
fail
;
return
EFI_OUT_OF_RESOURCES
;
}
if
(
IS_ENABLED
(
CONFIG_CMDLINE_EXTEND
)
||
...
...
@@ -184,25 +143,34 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
}
if
(
!
IS_ENABLED
(
CONFIG_CMDLINE_FORCE
)
&&
cmdline_size
>
0
)
{
status
=
efi_parse_options
(
cmdline
_ptr
);
status
=
efi_parse_options
(
cmdline
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to parse options
\n
"
);
goto
fail_free_cmdline
;
}
}
efi_info
(
"Booting Linux Kernel...
\n
"
);
*
cmdline_ptr
=
cmdline
;
return
EFI_SUCCESS
;
si
=
setup_graphics
();
fail_free_cmdline:
efi_bs_call
(
free_pool
,
cmdline_ptr
);
return
status
;
}
status
=
handle_kernel_image
(
&
image_addr
,
&
image_size
,
&
reserve_addr
,
&
reserve_size
,
image
,
handle
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to relocate kernel
\n
"
);
goto
fail_free_screeninfo
;
}
efi_status_t
efi_stub_common
(
efi_handle_t
handle
,
efi_loaded_image_t
*
image
,
unsigned
long
image_addr
,
char
*
cmdline_ptr
)
{
struct
screen_info
*
si
;
efi_status_t
status
;
status
=
check_platform_features
();
if
(
status
!=
EFI_SUCCESS
)
return
status
;
si
=
setup_graphics
();
efi_retrieve_tpm2_eventlog
();
...
...
@@ -214,53 +182,15 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_random_get_seed
();
/*
* If the NX PE data feature is enabled in the properties table, we
* should take care not to create a virtual mapping that changes the
* relative placement of runtime services code and data regions, as
* they may belong to the same PE/COFF executable image in memory.
* The easiest way to achieve that is to simply use a 1:1 mapping.
*/
prop_tbl
=
get_efi_config_table
(
EFI_PROPERTIES_TABLE_GUID
);
flat_va_mapping
|=
prop_tbl
&&
(
prop_tbl
->
memory_protection_attribute
&
EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
/* force efi_novamap if SetVirtualAddressMap() is unsupported */
efi_novamap
|=
!
(
get_supported_rt_services
()
&
EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP
);
/* hibernation expects the runtime regions to stay in the same place */
if
(
!
IS_ENABLED
(
CONFIG_HIBERNATION
)
&&
!
efi_nokaslr
&&
!
flat_va_mapping
)
{
/*
* Randomize the base of the UEFI runtime services region.
* Preserve the 2 MB alignment of the region by taking a
* shift of 21 bit positions into account when scaling
* the headroom value using a 32-bit random value.
*/
static
const
u64
headroom
=
EFI_RT_VIRTUAL_LIMIT
-
EFI_RT_VIRTUAL_BASE
-
EFI_RT_VIRTUAL_SIZE
;
u32
rnd
;
status
=
efi_get_random_bytes
(
sizeof
(
rnd
),
(
u8
*
)
&
rnd
);
if
(
status
==
EFI_SUCCESS
)
{
virtmap_base
=
EFI_RT_VIRTUAL_BASE
+
(((
headroom
>>
21
)
*
rnd
)
>>
(
32
-
21
));
}
}
install_memreserve_table
();
status
=
efi_boot_kernel
(
handle
,
image
,
image_addr
,
cmdline_ptr
);
efi_free
(
image_size
,
image_addr
);
efi_free
(
reserve_size
,
reserve_addr
);
fail_free_screeninfo:
free_screen_info
(
si
);
fail_free_cmdline:
efi_bs_call
(
free_pool
,
cmdline_ptr
);
fail:
return
status
;
}
...
...
drivers/firmware/efi/libstub/efistub.h
View file @
97712289
...
...
@@ -958,6 +958,14 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_loaded_image_t
*
image
,
efi_handle_t
image_handle
);
/* shared entrypoint between the normal stub and the zboot stub */
efi_status_t
efi_stub_common
(
efi_handle_t
handle
,
efi_loaded_image_t
*
image
,
unsigned
long
image_addr
,
char
*
cmdline_ptr
);
efi_status_t
efi_handle_cmdline
(
efi_loaded_image_t
*
image
,
char
**
cmdline_ptr
);
asmlinkage
void
__noreturn
efi_enter_kernel
(
unsigned
long
entrypoint
,
unsigned
long
fdt_addr
,
unsigned
long
fdt_size
);
...
...
@@ -975,6 +983,13 @@ efi_enable_reset_attack_mitigation(void) { }
void
efi_retrieve_tpm2_eventlog
(
void
);
struct
screen_info
*
alloc_screen_info
(
void
);
void
free_screen_info
(
struct
screen_info
*
si
);
void
efi_cache_sync_image
(
unsigned
long
image_base
,
unsigned
long
alloc_size
,
unsigned
long
code_size
);
struct
efi_smbios_record
{
u8
type
;
u8
length
;
...
...
drivers/firmware/efi/libstub/file.c
View file @
97712289
...
...
@@ -66,28 +66,10 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
static
efi_status_t
efi_open_volume
(
efi_loaded_image_t
*
image
,
efi_file_protocol_t
**
fh
)
{
struct
efi_vendor_dev_path
*
dp
=
image
->
file_path
;
efi_guid_t
li_proto
=
LOADED_IMAGE_PROTOCOL_GUID
;
efi_guid_t
fs_proto
=
EFI_FILE_SYSTEM_GUID
;
efi_simple_file_system_protocol_t
*
io
;
efi_status_t
status
;
// If we are using EFI zboot, we should look for the file system
// protocol on the parent image's handle instead
if
(
IS_ENABLED
(
CONFIG_EFI_ZBOOT
)
&&
image
->
parent_handle
!=
NULL
&&
dp
!=
NULL
&&
dp
->
header
.
type
==
EFI_DEV_MEDIA
&&
dp
->
header
.
sub_type
==
EFI_DEV_MEDIA_VENDOR
&&
!
efi_guidcmp
(
dp
->
vendorguid
,
LINUX_EFI_ZBOOT_MEDIA_GUID
))
{
status
=
efi_bs_call
(
handle_protocol
,
image
->
parent_handle
,
&
li_proto
,
(
void
*
)
&
image
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to locate parent image handle
\n
"
);
return
status
;
}
}
status
=
efi_bs_call
(
handle_protocol
,
image
->
device_handle
,
&
fs_proto
,
(
void
**
)
&
io
);
if
(
status
!=
EFI_SUCCESS
)
{
...
...
drivers/firmware/efi/libstub/intrinsics.c
View file @
97712289
...
...
@@ -28,3 +28,21 @@ void *memset(void *dst, int c, size_t len)
efi_bs_call
(
set_mem
,
dst
,
len
,
c
&
U8_MAX
);
return
dst
;
}
/**
* memcmp - Compare two areas of memory
* @cs: One area of memory
* @ct: Another area of memory
* @count: The size of the area.
*/
#undef memcmp
int
memcmp
(
const
void
*
cs
,
const
void
*
ct
,
size_t
count
)
{
const
unsigned
char
*
su1
,
*
su2
;
int
res
=
0
;
for
(
su1
=
cs
,
su2
=
ct
;
0
<
count
;
++
su1
,
++
su2
,
count
--
)
if
((
res
=
*
su1
-
*
su2
)
!=
0
)
break
;
return
res
;
}
drivers/firmware/efi/libstub/loongarch-stub.c
View file @
97712289
...
...
@@ -9,18 +9,10 @@
#include <asm/addrspace.h>
#include "efistub.h"
typedef
void
__noreturn
(
*
kernel_entry_t
)(
bool
efi
,
unsigned
long
cmdline
,
unsigned
long
systab
);
extern
int
kernel_asize
;
extern
int
kernel_fsize
;
extern
int
kernel_offset
;
extern
kernel_entry_t
kernel_entry
;
efi_status_t
check_platform_features
(
void
)
{
return
EFI_SUCCESS
;
}
extern
int
kernel_entry
;
efi_status_t
handle_kernel_image
(
unsigned
long
*
image_addr
,
unsigned
long
*
image_size
,
...
...
@@ -29,74 +21,33 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_loaded_image_t
*
image
,
efi_handle_t
image_handle
)
{
int
nr_pages
=
round_up
(
kernel_asize
,
EFI_ALLOC_ALIGN
)
/
EFI_PAGE_SIZE
;
efi_physical_addr_t
kernel_addr
=
EFI_KIMG_PREFERRED_ADDRESS
;
efi_status_t
status
;
unsigned
long
kernel_addr
=
0
;
kernel_addr
=
(
unsigned
long
)
&
kernel_offset
-
kernel_offset
;
status
=
efi_relocate_kernel
(
&
kernel_addr
,
kernel_fsize
,
kernel_asize
,
PHYSADDR
(
VMLINUX_LOAD_ADDRESS
),
SZ_2M
,
0x0
);
*
image_addr
=
kernel_addr
;
*
image_size
=
kernel_asize
;
return
status
;
}
struct
exit_boot_struct
{
efi_memory_desc_t
*
runtime_map
;
int
runtime_entry_count
;
};
static
efi_status_t
exit_boot_func
(
struct
efi_boot_memmap
*
map
,
void
*
priv
)
{
struct
exit_boot_struct
*
p
=
priv
;
/*
*
Update the memory map with virtual addresses. The function will also
*
populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
*
entries so that we can pass it straight to SetVirtualAddressMap()
*
Allocate space for the kernel image at the preferred offset. This is
*
the only location in memory from where we can execute the image, so
*
no point in falling back to another allocation.
*/
efi_get_virtmap
(
map
->
map
,
map
->
map_size
,
map
->
desc_size
,
p
->
runtime_map
,
&
p
->
runtime_entry_count
);
return
EFI_SUCCESS
;
}
efi_status_t
efi_boot_kernel
(
void
*
handle
,
efi_loaded_image_t
*
image
,
unsigned
long
kernel_addr
,
char
*
cmdline_ptr
)
{
kernel_entry_t
real_kernel_entry
;
struct
exit_boot_struct
priv
;
unsigned
long
desc_size
;
efi_status_t
status
;
u32
desc_ver
;
status
=
efi_alloc_virtmap
(
&
priv
.
runtime_map
,
&
desc_size
,
&
desc_ver
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Unable to retrieve UEFI memory map.
\n
"
);
return
status
;
}
efi_info
(
"Exiting boot services
\n
"
);
efi_novamap
=
false
;
status
=
efi_exit_boot_services
(
handle
,
&
priv
,
exit_boot_func
);
status
=
efi_bs_call
(
allocate_pages
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
kernel_addr
);
if
(
status
!=
EFI_SUCCESS
)
return
status
;
/* Install the new virtual address map */
efi_rt_call
(
set_virtual_address_map
,
priv
.
runtime_entry_count
*
desc_size
,
desc_size
,
desc_ver
,
priv
.
runtime_map
);
*
image_addr
=
EFI_KIMG_PREFERRED_ADDRESS
;
*
image_size
=
kernel_asize
;
/* Config Direct Mapping */
csr_write64
(
CSR_DMW0_INIT
,
LOONGARCH_CSR_DMWIN0
);
csr_write64
(
CSR_DMW1_INIT
,
LOONGARCH_CSR_DMWIN1
);
memcpy
((
void
*
)
EFI_KIMG_PREFERRED_ADDRESS
,
(
void
*
)
&
kernel_offset
-
kernel_offset
,
kernel_fsize
);
real_kernel_entry
=
(
kernel_entry_t
)
((
unsigned
long
)
&
kernel_entry
-
kernel_addr
+
VMLINUX_LOAD_ADDRESS
);
return
status
;
}
unsigned
long
kernel_entry_address
(
void
)
{
unsigned
long
base
=
(
unsigned
long
)
&
kernel_offset
-
kernel_offset
;
real_kernel_entry
(
true
,
(
unsigned
long
)
cmdline_ptr
,
(
unsigned
long
)
efi_system_table
);
return
(
unsigned
long
)
&
kernel_entry
-
base
+
VMLINUX_LOAD_ADDRESS
;
}
drivers/firmware/efi/libstub/loongarch.c
0 → 100644
View file @
97712289
// SPDX-License-Identifier: GPL-2.0
/*
* Author: Yun Liu <liuyun@loongson.cn>
* Huacai Chen <chenhuacai@loongson.cn>
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
*/
#include <asm/efi.h>
#include <asm/addrspace.h>
#include "efistub.h"
typedef
void
__noreturn
(
*
kernel_entry_t
)(
bool
efi
,
unsigned
long
cmdline
,
unsigned
long
systab
);
efi_status_t
check_platform_features
(
void
)
{
return
EFI_SUCCESS
;
}
struct
exit_boot_struct
{
efi_memory_desc_t
*
runtime_map
;
int
runtime_entry_count
;
};
static
efi_status_t
exit_boot_func
(
struct
efi_boot_memmap
*
map
,
void
*
priv
)
{
struct
exit_boot_struct
*
p
=
priv
;
/*
* Update the memory map with virtual addresses. The function will also
* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
* entries so that we can pass it straight to SetVirtualAddressMap()
*/
efi_get_virtmap
(
map
->
map
,
map
->
map_size
,
map
->
desc_size
,
p
->
runtime_map
,
&
p
->
runtime_entry_count
);
return
EFI_SUCCESS
;
}
unsigned
long
__weak
kernel_entry_address
(
void
)
{
return
*
(
unsigned
long
*
)(
PHYSADDR
(
VMLINUX_LOAD_ADDRESS
)
+
8
);
}
efi_status_t
efi_boot_kernel
(
void
*
handle
,
efi_loaded_image_t
*
image
,
unsigned
long
kernel_addr
,
char
*
cmdline_ptr
)
{
kernel_entry_t
real_kernel_entry
;
struct
exit_boot_struct
priv
;
unsigned
long
desc_size
;
efi_status_t
status
;
u32
desc_ver
;
status
=
efi_alloc_virtmap
(
&
priv
.
runtime_map
,
&
desc_size
,
&
desc_ver
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Unable to retrieve UEFI memory map.
\n
"
);
return
status
;
}
efi_info
(
"Exiting boot services
\n
"
);
efi_novamap
=
false
;
status
=
efi_exit_boot_services
(
handle
,
&
priv
,
exit_boot_func
);
if
(
status
!=
EFI_SUCCESS
)
return
status
;
/* Install the new virtual address map */
efi_rt_call
(
set_virtual_address_map
,
priv
.
runtime_entry_count
*
desc_size
,
desc_size
,
desc_ver
,
priv
.
runtime_map
);
/* Config Direct Mapping */
csr_write64
(
CSR_DMW0_INIT
,
LOONGARCH_CSR_DMWIN0
);
csr_write64
(
CSR_DMW1_INIT
,
LOONGARCH_CSR_DMWIN1
);
real_kernel_entry
=
(
void
*
)
kernel_entry_address
();
real_kernel_entry
(
true
,
(
unsigned
long
)
cmdline_ptr
,
(
unsigned
long
)
efi_system_table
);
}
drivers/firmware/efi/libstub/printk.c
0 → 100644
View file @
97712289
// SPDX-License-Identifier: GPL-2.0
#include <linux/stdarg.h>
#include <linux/ctype.h>
#include <linux/efi.h>
#include <linux/kernel.h>
#include <linux/printk.h>
/* For CONSOLE_LOGLEVEL_* */
#include <asm/efi.h>
#include <asm/setup.h>
#include "efistub.h"
int
efi_loglevel
=
CONSOLE_LOGLEVEL_DEFAULT
;
/**
* efi_char16_puts() - Write a UCS-2 encoded string to the console
* @str: UCS-2 encoded string
*/
void
efi_char16_puts
(
efi_char16_t
*
str
)
{
efi_call_proto
(
efi_table_attr
(
efi_system_table
,
con_out
),
output_string
,
str
);
}
static
u32
utf8_to_utf32
(
const
u8
**
s8
)
{
u32
c32
;
u8
c0
,
cx
;
size_t
clen
,
i
;
c0
=
cx
=
*
(
*
s8
)
++
;
/*
* The position of the most-significant 0 bit gives us the length of
* a multi-octet encoding.
*/
for
(
clen
=
0
;
cx
&
0x80
;
++
clen
)
cx
<<=
1
;
/*
* If the 0 bit is in position 8, this is a valid single-octet
* encoding. If the 0 bit is in position 7 or positions 1-3, the
* encoding is invalid.
* In either case, we just return the first octet.
*/
if
(
clen
<
2
||
clen
>
4
)
return
c0
;
/* Get the bits from the first octet. */
c32
=
cx
>>
clen
--
;
for
(
i
=
0
;
i
<
clen
;
++
i
)
{
/* Trailing octets must have 10 in most significant bits. */
cx
=
(
*
s8
)[
i
]
^
0x80
;
if
(
cx
&
0xc0
)
return
c0
;
c32
=
(
c32
<<
6
)
|
cx
;
}
/*
* Check for validity:
* - The character must be in the Unicode range.
* - It must not be a surrogate.
* - It must be encoded using the correct number of octets.
*/
if
(
c32
>
0x10ffff
||
(
c32
&
0xf800
)
==
0xd800
||
clen
!=
(
c32
>=
0x80
)
+
(
c32
>=
0x800
)
+
(
c32
>=
0x10000
))
return
c0
;
*
s8
+=
clen
;
return
c32
;
}
/**
* efi_puts() - Write a UTF-8 encoded string to the console
* @str: UTF-8 encoded string
*/
void
efi_puts
(
const
char
*
str
)
{
efi_char16_t
buf
[
128
];
size_t
pos
=
0
,
lim
=
ARRAY_SIZE
(
buf
);
const
u8
*
s8
=
(
const
u8
*
)
str
;
u32
c32
;
while
(
*
s8
)
{
if
(
*
s8
==
'\n'
)
buf
[
pos
++
]
=
L'\r'
;
c32
=
utf8_to_utf32
(
&
s8
);
if
(
c32
<
0x10000
)
{
/* Characters in plane 0 use a single word. */
buf
[
pos
++
]
=
c32
;
}
else
{
/*
* Characters in other planes encode into a surrogate
* pair.
*/
buf
[
pos
++
]
=
(
0xd800
-
(
0x10000
>>
10
))
+
(
c32
>>
10
);
buf
[
pos
++
]
=
0xdc00
+
(
c32
&
0x3ff
);
}
if
(
*
s8
==
'\0'
||
pos
>=
lim
-
2
)
{
buf
[
pos
]
=
L'\0'
;
efi_char16_puts
(
buf
);
pos
=
0
;
}
}
}
/**
* efi_printk() - Print a kernel message
* @fmt: format string
*
* The first letter of the format string is used to determine the logging level
* of the message. If the level is less then the current EFI logging level, the
* message is suppressed. The message will be truncated to 255 bytes.
*
* Return: number of printed characters
*/
int
efi_printk
(
const
char
*
fmt
,
...)
{
char
printf_buf
[
256
];
va_list
args
;
int
printed
;
int
loglevel
=
printk_get_level
(
fmt
);
switch
(
loglevel
)
{
case
'0'
...
'9'
:
loglevel
-=
'0'
;
break
;
default:
/*
* Use loglevel -1 for cases where we just want to print to
* the screen.
*/
loglevel
=
-
1
;
break
;
}
if
(
loglevel
>=
efi_loglevel
)
return
0
;
if
(
loglevel
>=
0
)
efi_puts
(
"EFI stub: "
);
fmt
=
printk_skip_level
(
fmt
);
va_start
(
args
,
fmt
);
printed
=
vsnprintf
(
printf_buf
,
sizeof
(
printf_buf
),
fmt
,
args
);
va_end
(
args
);
efi_puts
(
printf_buf
);
if
(
printed
>=
sizeof
(
printf_buf
))
{
efi_puts
(
"[Message truncated]
\n
"
);
return
-
1
;
}
return
printed
;
}
drivers/firmware/efi/libstub/riscv-stub.c
View file @
97712289
...
...
@@ -4,7 +4,6 @@
*/
#include <linux/efi.h>
#include <linux/libfdt.h>
#include <asm/efi.h>
#include <asm/sections.h>
...
...
@@ -12,92 +11,16 @@
#include "efistub.h"
/*
* RISC-V requires the kernel image to placed 2 MB aligned base for 64 bit and
* 4MB for 32 bit.
*/
#ifdef CONFIG_64BIT
#define MIN_KIMG_ALIGN SZ_2M
#else
#define MIN_KIMG_ALIGN SZ_4M
#endif
typedef
void
__noreturn
(
*
jump_kernel_func
)(
unsigned
long
,
unsigned
long
);
static
unsigned
long
hartid
;
static
int
get_boot_hartid_from_fdt
(
void
)
{
const
void
*
fdt
;
int
chosen_node
,
len
;
const
void
*
prop
;
fdt
=
get_efi_config_table
(
DEVICE_TREE_GUID
);
if
(
!
fdt
)
return
-
EINVAL
;
chosen_node
=
fdt_path_offset
(
fdt
,
"/chosen"
);
if
(
chosen_node
<
0
)
return
-
EINVAL
;
prop
=
fdt_getprop
((
void
*
)
fdt
,
chosen_node
,
"boot-hartid"
,
&
len
);
if
(
!
prop
)
return
-
EINVAL
;
if
(
len
==
sizeof
(
u32
))
hartid
=
(
unsigned
long
)
fdt32_to_cpu
(
*
(
fdt32_t
*
)
prop
);
else
if
(
len
==
sizeof
(
u64
))
hartid
=
(
unsigned
long
)
fdt64_to_cpu
(
__get_unaligned_t
(
fdt64_t
,
prop
));
else
return
-
EINVAL
;
return
0
;
}
static
efi_status_t
get_boot_hartid_from_efi
(
void
)
unsigned
long
stext_offset
(
void
)
{
efi_guid_t
boot_protocol_guid
=
RISCV_EFI_BOOT_PROTOCOL_GUID
;
struct
riscv_efi_boot_protocol
*
boot_protocol
;
efi_status_t
status
;
status
=
efi_bs_call
(
locate_protocol
,
&
boot_protocol_guid
,
NULL
,
(
void
**
)
&
boot_protocol
);
if
(
status
!=
EFI_SUCCESS
)
return
status
;
return
efi_call_proto
(
boot_protocol
,
get_boot_hartid
,
&
hartid
);
}
efi_status_t
check_platform_features
(
void
)
{
efi_status_t
status
;
int
ret
;
status
=
get_boot_hartid_from_efi
();
if
(
status
!=
EFI_SUCCESS
)
{
ret
=
get_boot_hartid_from_fdt
();
if
(
ret
)
{
efi_err
(
"Failed to get boot hartid!
\n
"
);
return
EFI_UNSUPPORTED
;
}
}
return
EFI_SUCCESS
;
}
void
__noreturn
efi_enter_kernel
(
unsigned
long
entrypoint
,
unsigned
long
fdt
,
unsigned
long
fdt_size
)
{
unsigned
long
stext_offset
=
_start_kernel
-
_start
;
unsigned
long
kernel_entry
=
entrypoint
+
stext_offset
;
jump_kernel_func
jump_kernel
=
(
jump_kernel_func
)
kernel_entry
;
/*
* Jump to real kernel here with following constraints.
* 1. MMU should be disabled.
* 2. a0 should contain hartid
* 3. a1 should DT address
* When built as part of the kernel, the EFI stub cannot branch to the
* kernel proper via the image header, as the PE/COFF header is
* strictly not part of the in-memory presentation of the image, only
* of the file representation. So instead, we need to jump to the
* actual entrypoint in the .text region of the image.
*/
csr_write
(
CSR_SATP
,
0
);
jump_kernel
(
hartid
,
fdt
);
return
_start_kernel
-
_start
;
}
efi_status_t
handle_kernel_image
(
unsigned
long
*
image_addr
,
...
...
@@ -125,9 +48,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
* lowest possible memory region as long as the address and size meets
* the alignment constraints.
*/
preferred_addr
=
MIN_KIMG_ALIGN
;
preferred_addr
=
EFI_KIMG_PREFERRED_ADDRESS
;
status
=
efi_relocate_kernel
(
image_addr
,
kernel_size
,
*
image_size
,
preferred_addr
,
MIN_KIMG_ALIGN
,
0x0
);
preferred_addr
,
efi_get_kimg_min_align
(),
0x0
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to relocate kernel
\n
"
);
...
...
drivers/firmware/efi/libstub/riscv.c
0 → 100644
View file @
97712289
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 Western Digital Corporation or its affiliates.
*/
#include <linux/efi.h>
#include <linux/libfdt.h>
#include <asm/efi.h>
#include <asm/unaligned.h>
#include "efistub.h"
typedef
void
__noreturn
(
*
jump_kernel_func
)(
unsigned
long
,
unsigned
long
);
static
unsigned
long
hartid
;
static
int
get_boot_hartid_from_fdt
(
void
)
{
const
void
*
fdt
;
int
chosen_node
,
len
;
const
void
*
prop
;
fdt
=
get_efi_config_table
(
DEVICE_TREE_GUID
);
if
(
!
fdt
)
return
-
EINVAL
;
chosen_node
=
fdt_path_offset
(
fdt
,
"/chosen"
);
if
(
chosen_node
<
0
)
return
-
EINVAL
;
prop
=
fdt_getprop
((
void
*
)
fdt
,
chosen_node
,
"boot-hartid"
,
&
len
);
if
(
!
prop
)
return
-
EINVAL
;
if
(
len
==
sizeof
(
u32
))
hartid
=
(
unsigned
long
)
fdt32_to_cpu
(
*
(
fdt32_t
*
)
prop
);
else
if
(
len
==
sizeof
(
u64
))
hartid
=
(
unsigned
long
)
fdt64_to_cpu
(
__get_unaligned_t
(
fdt64_t
,
prop
));
else
return
-
EINVAL
;
return
0
;
}
static
efi_status_t
get_boot_hartid_from_efi
(
void
)
{
efi_guid_t
boot_protocol_guid
=
RISCV_EFI_BOOT_PROTOCOL_GUID
;
struct
riscv_efi_boot_protocol
*
boot_protocol
;
efi_status_t
status
;
status
=
efi_bs_call
(
locate_protocol
,
&
boot_protocol_guid
,
NULL
,
(
void
**
)
&
boot_protocol
);
if
(
status
!=
EFI_SUCCESS
)
return
status
;
return
efi_call_proto
(
boot_protocol
,
get_boot_hartid
,
&
hartid
);
}
efi_status_t
check_platform_features
(
void
)
{
efi_status_t
status
;
int
ret
;
status
=
get_boot_hartid_from_efi
();
if
(
status
!=
EFI_SUCCESS
)
{
ret
=
get_boot_hartid_from_fdt
();
if
(
ret
)
{
efi_err
(
"Failed to get boot hartid!
\n
"
);
return
EFI_UNSUPPORTED
;
}
}
return
EFI_SUCCESS
;
}
unsigned
long
__weak
stext_offset
(
void
)
{
/*
* This fallback definition is used by the EFI zboot stub, which loads
* the entire image so it can branch via the image header at offset #0.
*/
return
0
;
}
void
__noreturn
efi_enter_kernel
(
unsigned
long
entrypoint
,
unsigned
long
fdt
,
unsigned
long
fdt_size
)
{
unsigned
long
kernel_entry
=
entrypoint
+
stext_offset
();
jump_kernel_func
jump_kernel
=
(
jump_kernel_func
)
kernel_entry
;
/*
* Jump to real kernel here with following constraints.
* 1. MMU should be disabled.
* 2. a0 should contain hartid
* 3. a1 should DT address
*/
csr_write
(
CSR_SATP
,
0
);
jump_kernel
(
hartid
,
fdt
);
}
drivers/firmware/efi/libstub/screen_info.c
0 → 100644
View file @
97712289
// SPDX-License-Identifier: GPL-2.0
#include <linux/efi.h>
#include <asm/efi.h>
#include "efistub.h"
/*
* There are two ways of populating the core kernel's struct screen_info via the stub:
* - using a configuration table, like below, which relies on the EFI init code
* to locate the table and copy the contents;
* - by linking directly to the core kernel's copy of the global symbol.
*
* The latter is preferred because it makes the EFIFB earlycon available very
* early, but it only works if the EFI stub is part of the core kernel image
* itself. The zboot decompressor can only use the configuration table
* approach.
*
* In order to support both methods from the same build of the EFI stub
* library, provide this dummy global definition of struct screen_info. If it
* is required to satisfy a link dependency, it means we need to override the
* __weak alloc and free methods with the ones below, and those will be pulled
* in as well.
*/
struct
screen_info
screen_info
;
static
efi_guid_t
screen_info_guid
=
LINUX_EFI_SCREEN_INFO_TABLE_GUID
;
struct
screen_info
*
alloc_screen_info
(
void
)
{
struct
screen_info
*
si
;
efi_status_t
status
;
status
=
efi_bs_call
(
allocate_pool
,
EFI_ACPI_RECLAIM_MEMORY
,
sizeof
(
*
si
),
(
void
**
)
&
si
);
if
(
status
!=
EFI_SUCCESS
)
return
NULL
;
status
=
efi_bs_call
(
install_configuration_table
,
&
screen_info_guid
,
si
);
if
(
status
==
EFI_SUCCESS
)
return
si
;
efi_bs_call
(
free_pool
,
si
);
return
NULL
;
}
void
free_screen_info
(
struct
screen_info
*
si
)
{
if
(
!
si
)
return
;
efi_bs_call
(
install_configuration_table
,
&
screen_info_guid
,
NULL
);
efi_bs_call
(
free_pool
,
si
);
}
drivers/firmware/efi/libstub/string.c
View file @
97712289
...
...
@@ -11,7 +11,37 @@
#include <linux/types.h>
#include <linux/string.h>
#ifndef __HAVE_ARCH_STRSTR
#ifndef EFI_HAVE_STRLEN
/**
* strlen - Find the length of a string
* @s: The string to be sized
*/
size_t
strlen
(
const
char
*
s
)
{
const
char
*
sc
;
for
(
sc
=
s
;
*
sc
!=
'\0'
;
++
sc
)
/* nothing */
;
return
sc
-
s
;
}
#endif
#ifndef EFI_HAVE_STRNLEN
/**
* strnlen - Find the length of a length-limited string
* @s: The string to be sized
* @count: The maximum number of bytes to search
*/
size_t
strnlen
(
const
char
*
s
,
size_t
count
)
{
const
char
*
sc
;
for
(
sc
=
s
;
count
--
&&
*
sc
!=
'\0'
;
++
sc
)
/* nothing */
;
return
sc
-
s
;
}
#endif
/**
* strstr - Find the first substring in a %NUL terminated string
* @s1: The string to be searched
...
...
@@ -33,9 +63,29 @@ char *strstr(const char *s1, const char *s2)
}
return
NULL
;
}
#ifndef EFI_HAVE_STRCMP
/**
* strcmp - Compare two strings
* @cs: One string
* @ct: Another string
*/
int
strcmp
(
const
char
*
cs
,
const
char
*
ct
)
{
unsigned
char
c1
,
c2
;
while
(
1
)
{
c1
=
*
cs
++
;
c2
=
*
ct
++
;
if
(
c1
!=
c2
)
return
c1
<
c2
?
-
1
:
1
;
if
(
!
c1
)
break
;
}
return
0
;
}
#endif
#ifndef __HAVE_ARCH_STRNCMP
/**
* strncmp - Compare two length-limited strings
* @cs: One string
...
...
@@ -57,7 +107,6 @@ int strncmp(const char *cs, const char *ct, size_t count)
}
return
0
;
}
#endif
/* Works only for digits and letters, but small and fast */
#define TOLOWER(x) ((x) | 0x20)
...
...
@@ -113,3 +162,43 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
return
simple_strtoull
(
cp
,
endp
,
base
);
}
#ifdef CONFIG_EFI_PARAMS_FROM_FDT
#ifndef EFI_HAVE_STRRCHR
/**
* strrchr - Find the last occurrence of a character in a string
* @s: The string to be searched
* @c: The character to search for
*/
char
*
strrchr
(
const
char
*
s
,
int
c
)
{
const
char
*
last
=
NULL
;
do
{
if
(
*
s
==
(
char
)
c
)
last
=
s
;
}
while
(
*
s
++
);
return
(
char
*
)
last
;
}
#endif
#ifndef EFI_HAVE_MEMCHR
/**
* memchr - Find a character in an area of memory.
* @s: The memory area
* @c: The byte to search for
* @n: The size of the area.
*
* returns the address of the first occurrence of @c, or %NULL
* if @c is not found
*/
void
*
memchr
(
const
void
*
s
,
int
c
,
size_t
n
)
{
const
unsigned
char
*
p
=
s
;
while
(
n
--
!=
0
)
{
if
((
unsigned
char
)
c
==
*
p
++
)
{
return
(
void
*
)(
p
-
1
);
}
}
return
NULL
;
}
#endif
#endif
drivers/firmware/efi/libstub/zboot-header.S
View file @
97712289
...
...
@@ -17,7 +17,7 @@ __efistub_efi_zboot_header:
.
long
MZ_MAGIC
.
ascii
"zimg"
//
image
type
.
long
__efistub__gzdata_start
-
.
Ldoshdr
//
payload
offset
.
long
__efistub__gzdata_size
-
ZBOOT_SIZE_LEN
//
payload
size
.
long
__efistub__gzdata_size
-
12
//
payload
size
.
long
0
,
0
//
reserved
.
asciz
COMP_TYPE
//
compression
type
.
org
.
Ldoshdr
+
0x3c
...
...
drivers/firmware/efi/libstub/zboot.c
View file @
97712289
...
...
@@ -32,271 +32,116 @@ static unsigned long free_mem_ptr, free_mem_end_ptr;
extern
char
efi_zboot_header
[];
extern
char
_gzdata_start
[],
_gzdata_end
[];
static
void
log
(
efi_char16_t
str
[])
{
efi_call_proto
(
efi_table_attr
(
efi_system_table
,
con_out
),
output_string
,
L"EFI decompressor: "
);
efi_call_proto
(
efi_table_attr
(
efi_system_table
,
con_out
),
output_string
,
str
);
efi_call_proto
(
efi_table_attr
(
efi_system_table
,
con_out
),
output_string
,
L"
\n
"
);
}
static
void
error
(
char
*
x
)
{
log
(
L"error() called from decompressor library
\n
"
);
}
// Local version to avoid pulling in memcmp()
static
bool
guids_eq
(
const
efi_guid_t
*
a
,
const
efi_guid_t
*
b
)
{
const
u32
*
l
=
(
u32
*
)
a
;
const
u32
*
r
=
(
u32
*
)
b
;
return
l
[
0
]
==
r
[
0
]
&&
l
[
1
]
==
r
[
1
]
&&
l
[
2
]
==
r
[
2
]
&&
l
[
3
]
==
r
[
3
];
}
static
efi_status_t
__efiapi
load_file
(
efi_load_file_protocol_t
*
this
,
efi_device_path_protocol_t
*
rem
,
bool
boot_policy
,
unsigned
long
*
bufsize
,
void
*
buffer
)
{
unsigned
long
compressed_size
=
_gzdata_end
-
_gzdata_start
;
struct
efi_vendor_dev_path
*
vendor_dp
;
bool
decompress
=
false
;
unsigned
long
size
;
int
ret
;
if
(
rem
==
NULL
||
bufsize
==
NULL
)
return
EFI_INVALID_PARAMETER
;
if
(
boot_policy
)
return
EFI_UNSUPPORTED
;
// Look for our vendor media device node in the remaining file path
if
(
rem
->
type
==
EFI_DEV_MEDIA
&&
rem
->
sub_type
==
EFI_DEV_MEDIA_VENDOR
)
{
vendor_dp
=
container_of
(
rem
,
struct
efi_vendor_dev_path
,
header
);
if
(
!
guids_eq
(
&
vendor_dp
->
vendorguid
,
&
LINUX_EFI_ZBOOT_MEDIA_GUID
))
return
EFI_NOT_FOUND
;
decompress
=
true
;
rem
=
(
void
*
)(
vendor_dp
+
1
);
}
if
(
rem
->
type
!=
EFI_DEV_END_PATH
||
rem
->
sub_type
!=
EFI_DEV_END_ENTIRE
)
return
EFI_NOT_FOUND
;
// The uncompressed size of the payload is appended to the raw bit
// stream, and may therefore appear misaligned in memory
size
=
decompress
?
get_unaligned_le32
(
_gzdata_end
-
4
)
:
compressed_size
;
if
(
buffer
==
NULL
||
*
bufsize
<
size
)
{
*
bufsize
=
size
;
return
EFI_BUFFER_TOO_SMALL
;
}
if
(
decompress
)
{
ret
=
__decompress
(
_gzdata_start
,
compressed_size
,
NULL
,
NULL
,
buffer
,
size
,
NULL
,
error
);
if
(
ret
<
0
)
{
log
(
L"Decompression failed"
);
return
EFI_DEVICE_ERROR
;
}
}
else
{
memcpy
(
buffer
,
_gzdata_start
,
compressed_size
);
}
return
EFI_SUCCESS
;
}
// Return the length in bytes of the device path up to the first end node.
static
int
device_path_length
(
const
efi_device_path_protocol_t
*
dp
)
{
int
len
=
0
;
while
(
dp
->
type
!=
EFI_DEV_END_PATH
)
{
len
+=
dp
->
length
;
dp
=
(
void
*
)((
u8
*
)
dp
+
dp
->
length
);
}
return
len
;
efi_err
(
"EFI decompressor: %s
\n
"
,
x
);
}
static
void
append_rel_offset_node
(
efi_device_path_protocol_t
**
dp
,
unsigned
long
start
,
unsigned
long
end
)
static
unsigned
long
alloc_preferred_address
(
unsigned
long
alloc_size
)
{
struct
efi_rel_offset_dev_path
*
rodp
=
(
void
*
)
*
dp
;
rodp
->
header
.
type
=
EFI_DEV_MEDIA
;
rodp
->
header
.
sub_type
=
EFI_DEV_MEDIA_REL_OFFSET
;
rodp
->
header
.
length
=
sizeof
(
struct
efi_rel_offset_dev_path
);
rodp
->
reserved
=
0
;
rodp
->
starting_offset
=
start
;
rodp
->
ending_offset
=
end
;
#ifdef EFI_KIMG_PREFERRED_ADDRESS
efi_physical_addr_t
efi_addr
=
EFI_KIMG_PREFERRED_ADDRESS
;
*
dp
=
(
void
*
)(
rodp
+
1
);
}
static
void
append_ven_media_node
(
efi_device_path_protocol_t
**
dp
,
efi_guid_t
*
guid
)
{
struct
efi_vendor_dev_path
*
vmdp
=
(
void
*
)
*
dp
;
vmdp
->
header
.
type
=
EFI_DEV_MEDIA
;
vmdp
->
header
.
sub_type
=
EFI_DEV_MEDIA_VENDOR
;
vmdp
->
header
.
length
=
sizeof
(
struct
efi_vendor_dev_path
);
vmdp
->
vendorguid
=
*
guid
;
*
dp
=
(
void
*
)(
vmdp
+
1
);
if
(
efi_bs_call
(
allocate_pages
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
alloc_size
/
EFI_PAGE_SIZE
,
&
efi_addr
)
==
EFI_SUCCESS
)
return
efi_addr
;
#endif
return
ULONG_MAX
;
}
static
void
append_end_node
(
efi_device_path_protocol_t
**
dp
)
void
__weak
efi_cache_sync_image
(
unsigned
long
image_base
,
unsigned
long
alloc_size
,
unsigned
long
code_size
)
{
(
*
dp
)
->
type
=
EFI_DEV_END_PATH
;
(
*
dp
)
->
sub_type
=
EFI_DEV_END_ENTIRE
;
(
*
dp
)
->
length
=
sizeof
(
struct
efi_generic_dev_path
);
++*
dp
;
// Provided by the arch to perform the cache maintenance necessary for
// executable code loaded into memory to be safe for execution.
}
asmlinkage
efi_status_t
__efiapi
efi_zboot_entry
(
efi_handle_t
handle
,
efi_system_table_t
*
systab
)
{
struct
efi_mem_mapped_dev_path
mmdp
=
{
.
header
.
type
=
EFI_DEV_HW
,
.
header
.
sub_type
=
EFI_DEV_MEM_MAPPED
,
.
header
.
length
=
sizeof
(
struct
efi_mem_mapped_dev_path
)
};
efi_device_path_protocol_t
*
parent_dp
,
*
dpp
,
*
lf2_dp
,
*
li_dp
;
efi_load_file2_protocol_t
zboot_load_file2
;
efi_loaded_image_t
*
parent
,
*
child
;
unsigned
long
exit_data_size
;
efi_handle_t
child_handle
;
efi_handle_t
zboot_handle
;
efi_char16_t
*
exit_data
;
unsigned
long
compressed_size
=
_gzdata_end
-
_gzdata_start
;
unsigned
long
image_base
,
alloc_size
,
code_size
;
efi_loaded_image_t
*
image
;
efi_status_t
status
;
void
*
dp_alloc
;
int
dp_len
;
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
);
exit_data
=
NULL
;
exit_data_size
=
0
;
status
=
efi_bs_call
(
handle_protocol
,
handle
,
&
LOADED_IMAGE_PROTOCOL_GUID
,
(
void
**
)
&
parent
);
&
LOADED_IMAGE_PROTOCOL_GUID
,
(
void
**
)
&
image
);
if
(
status
!=
EFI_SUCCESS
)
{
log
(
L
"Failed to locate parent's loaded image protocol"
);
error
(
"Failed to locate parent's loaded image protocol"
);
return
status
;
}
status
=
efi_bs_call
(
handle_protocol
,
handle
,
&
LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID
,
(
void
**
)
&
parent_dp
);
if
(
status
!=
EFI_SUCCESS
||
parent_dp
==
NULL
)
{
// Create a MemoryMapped() device path node to describe
// the parent image if no device path was provided.
mmdp
.
memory_type
=
parent
->
image_code_type
;
mmdp
.
starting_addr
=
(
unsigned
long
)
parent
->
image_base
;
mmdp
.
ending_addr
=
(
unsigned
long
)
parent
->
image_base
+
parent
->
image_size
-
1
;
parent_dp
=
&
mmdp
.
header
;
dp_len
=
sizeof
(
mmdp
);
}
else
{
dp_len
=
device_path_length
(
parent_dp
);
}
// Allocate some pool memory for device path protocol data
status
=
efi_bs_call
(
allocate_pool
,
EFI_LOADER_DATA
,
2
*
(
dp_len
+
sizeof
(
struct
efi_rel_offset_dev_path
)
+
sizeof
(
struct
efi_generic_dev_path
))
+
sizeof
(
struct
efi_vendor_dev_path
),
(
void
**
)
&
dp_alloc
);
if
(
status
!=
EFI_SUCCESS
)
{
log
(
L"Failed to allocate device path pool memory"
);
status
=
efi_handle_cmdline
(
image
,
&
cmdline_ptr
);
if
(
status
!=
EFI_SUCCESS
)
return
status
;
}
// Create a device path describing the compressed payload in this image
// <...parent_dp...>/Offset(<start>, <end>)
lf2_dp
=
memcpy
(
dp_alloc
,
parent_dp
,
dp_len
);
dpp
=
(
void
*
)((
u8
*
)
lf2_dp
+
dp_len
);
append_rel_offset_node
(
&
dpp
,
(
unsigned
long
)(
_gzdata_start
-
efi_zboot_header
),
(
unsigned
long
)(
_gzdata_end
-
efi_zboot_header
-
1
));
append_end_node
(
&
dpp
);
// Create a device path describing the decompressed payload in this image
// <...parent_dp...>/Offset(<start>, <end>)/VenMedia(ZBOOT_MEDIA_GUID)
dp_len
+=
sizeof
(
struct
efi_rel_offset_dev_path
);
li_dp
=
memcpy
(
dpp
,
lf2_dp
,
dp_len
);
dpp
=
(
void
*
)((
u8
*
)
li_dp
+
dp_len
);
append_ven_media_node
(
&
dpp
,
&
LINUX_EFI_ZBOOT_MEDIA_GUID
);
append_end_node
(
&
dpp
);
zboot_handle
=
NULL
;
zboot_load_file2
.
load_file
=
load_file
;
status
=
efi_bs_call
(
install_multiple_protocol_interfaces
,
&
zboot_handle
,
&
EFI_DEVICE_PATH_PROTOCOL_GUID
,
lf2_dp
,
&
EFI_LOAD_FILE2_PROTOCOL_GUID
,
&
zboot_load_file2
,
NULL
);
if
(
status
!=
EFI_SUCCESS
)
{
log
(
L"Failed to install LoadFile2 protocol and device path"
);
goto
free_dpalloc
;
}
status
=
efi_bs_call
(
load_image
,
false
,
handle
,
li_dp
,
NULL
,
0
,
&
child_handle
);
if
(
status
!=
EFI_SUCCESS
)
{
log
(
L"Failed to load image"
);
goto
uninstall_lf2
;
}
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
);
// SizeOfHeaders and SizeOfCode from the compressee's PE/COFF header
code_size
=
get_unaligned_le32
(
_gzdata_end
-
8
)
+
get_unaligned_le32
(
_gzdata_end
-
12
);
// If the architecture has a preferred address for the image,
// try that first.
image_base
=
alloc_preferred_address
(
alloc_size
);
if
(
image_base
==
ULONG_MAX
)
{
unsigned
long
min_kimg_align
=
efi_get_kimg_min_align
();
u32
seed
=
U32_MAX
;
if
(
!
IS_ENABLED
(
CONFIG_RANDOMIZE_BASE
))
{
// Setting the random seed to 0x0 is the same as
// allocating as low as possible
seed
=
0
;
}
else
if
(
efi_nokaslr
)
{
efi_info
(
"KASLR disabled on kernel command line
\n
"
);
}
else
{
status
=
efi_get_random_bytes
(
sizeof
(
seed
),
(
u8
*
)
&
seed
);
if
(
status
==
EFI_NOT_FOUND
)
{
efi_info
(
"EFI_RNG_PROTOCOL unavailable
\n
"
);
efi_nokaslr
=
true
;
}
else
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"efi_get_random_bytes() failed (0x%lx)
\n
"
,
status
);
efi_nokaslr
=
true
;
}
}
status
=
efi_bs_call
(
handle_protocol
,
child_handle
,
&
LOADED_IMAGE_PROTOCOL_GUID
,
(
void
**
)
&
child
);
if
(
status
!=
EFI_SUCCESS
)
{
log
(
L"Failed to locate child's loaded image protocol"
);
goto
unload_image
;
status
=
efi_random_alloc
(
alloc_size
,
min_kimg_align
,
&
image_base
,
seed
,
EFI_LOADER_CODE
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_err
(
"Failed to allocate memory
\n
"
);
goto
free_cmdline
;
}
}
// Copy the kernel command line
child
->
load_options
=
parent
->
load_options
;
child
->
load_options_size
=
parent
->
load_options_size
;
status
=
efi_bs_call
(
start_image
,
child_handle
,
&
exit_data_size
,
&
exit_data
);
if
(
status
!=
EFI_SUCCESS
)
{
log
(
L"StartImage() returned with error"
);
if
(
exit_data_size
>
0
)
log
(
exit_data
);
// If StartImage() returns EFI_SECURITY_VIOLATION, the image is
// not unloaded so we need to do it by hand.
if
(
status
==
EFI_SECURITY_VIOLATION
)
unload_image:
efi_bs_call
(
unload_image
,
child_handle
);
// 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
;
}
uninstall_lf2:
efi_bs_call
(
uninstall_multiple_protocol_interfaces
,
zboot_handle
,
&
EFI_DEVICE_PATH_PROTOCOL_GUID
,
lf2_dp
,
&
EFI_LOAD_FILE2_PROTOCOL_GUID
,
&
zboot_load_file2
,
NULL
);
free_dpalloc:
efi_bs_call
(
free_pool
,
dp_alloc
);
efi_cache_sync_image
(
image_base
,
alloc_size
,
code_size
);
efi_bs_call
(
exit
,
handle
,
status
,
exit_data_size
,
exit_data
);
status
=
efi_stub_common
(
handle
,
image
,
image_base
,
cmdline_ptr
);
// Free ExitData in case Exit() returned with a failure code,
// but return the original status code.
log
(
L"Exit() returned with failure code"
);
if
(
exit_data
!=
NULL
)
efi_bs_call
(
free_pool
,
exit_data
);
free_image:
efi_free
(
alloc_size
,
image_base
);
free_cmdline:
efi_bs_call
(
free_pool
,
cmdline_ptr
);
return
status
;
}
include/linux/efi.h
View file @
97712289
...
...
@@ -404,7 +404,7 @@ void efi_native_runtime_setup(void);
* structure that was populated by the stub based on the GOP protocol instance
* associated with ConOut
*/
#define LINUX_EFI_
ARM_
SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
#define LINUX_EFI_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
#define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989, 0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2)
#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
...
...
@@ -412,7 +412,6 @@ void efi_native_runtime_setup(void);
#define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25)
#define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2)
#define LINUX_EFI_INITRD_MEDIA_GUID EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
#define LINUX_EFI_ZBOOT_MEDIA_GUID EFI_GUID(0xe565a30d, 0x47da, 0x4dbd, 0xb3, 0x54, 0x9b, 0xb5, 0xc8, 0x4f, 0x8b, 0xe2)
#define LINUX_EFI_MOK_VARIABLE_TABLE_GUID EFI_GUID(0xc451ed2b, 0x9694, 0x45d3, 0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89)
#define LINUX_EFI_COCO_SECRET_AREA_GUID EFI_GUID(0xadf956ad, 0xe98c, 0x484c, 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47)
#define LINUX_EFI_BOOT_MEMMAP_GUID EFI_GUID(0x800f683f, 0xd08b, 0x423a, 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment