Commit 2b95bb05 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86-boot-2023-10-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 boot updates from Ingo Molnar:

 - Rework PE header generation, primarily to generate a modern, 4k
   aligned kernel image view with narrower W^X permissions.

 - Further refine init-lifetime annotations

 - Misc cleanups & fixes

* tag 'x86-boot-2023-10-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
  x86/boot: efistub: Assign global boot_params variable
  x86/boot: Rename conflicting 'boot_params' pointer to 'boot_params_ptr'
  x86/head/64: Move the __head definition to <asm/init.h>
  x86/head/64: Add missing __head annotation to startup_64_load_idt()
  x86/head/64: Mark 'startup_gdt[]' and 'startup_gdt_descr' as __initdata
  x86/boot: Harmonize the style of array-type parameter for fixup_pointer() calls
  x86/boot: Fix incorrect startup_gdt_descr.size
  x86/boot: Compile boot code with -std=gnu11 too
  x86/boot: Increase section and file alignment to 4k/512
  x86/boot: Split off PE/COFF .data section
  x86/boot: Drop PE/COFF .reloc section
  x86/boot: Construct PE/COFF .text section from assembler
  x86/boot: Derive file size from _edata symbol
  x86/boot: Define setup size in linker script
  x86/boot: Set EFI handover offset directly in header asm
  x86/boot: Grab kernel_info offset from zoffset header directly
  x86/boot: Drop references to startup_64
  x86/boot: Drop redundant code setting the root device
  x86/boot: Omit compression buffer from PE/COFF image memory footprint
  x86/boot: Remove the 'bugger off' message
  ...
parents 3b8b4b4f 50dcc2e0
...@@ -43,7 +43,7 @@ endif ...@@ -43,7 +43,7 @@ endif
# How to compile the 16-bit code. Note we always compile for -march=i386; # How to compile the 16-bit code. Note we always compile for -march=i386;
# that way we can complain to the user if the CPU is insufficient. # that way we can complain to the user if the CPU is insufficient.
REALMODE_CFLAGS := -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \ REALMODE_CFLAGS := -std=gnu11 -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \
-Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \ -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
-mno-mmx -mno-sse $(call cc-option,-fcf-protection=none) -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
......
...@@ -89,7 +89,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE ...@@ -89,7 +89,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|efi32_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p' sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|efi.._stub_entry\|efi\(32\)\?_pe_entry\|input_data\|kernel_info\|_end\|_ehead\|_text\|_e\?data\|z_.*\)$$/\#define ZO_\2 0x\1/p'
quiet_cmd_zoffset = ZOFFSET $@ quiet_cmd_zoffset = ZOFFSET $@
cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@ cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
......
...@@ -30,13 +30,13 @@ __efi_get_rsdp_addr(unsigned long cfg_tbl_pa, unsigned int cfg_tbl_len) ...@@ -30,13 +30,13 @@ __efi_get_rsdp_addr(unsigned long cfg_tbl_pa, unsigned int cfg_tbl_len)
* Search EFI system tables for RSDP. Preferred is ACPI_20_TABLE_GUID to * Search EFI system tables for RSDP. Preferred is ACPI_20_TABLE_GUID to
* ACPI_TABLE_GUID because it has more features. * ACPI_TABLE_GUID because it has more features.
*/ */
rsdp_addr = efi_find_vendor_table(boot_params, cfg_tbl_pa, cfg_tbl_len, rsdp_addr = efi_find_vendor_table(boot_params_ptr, cfg_tbl_pa, cfg_tbl_len,
ACPI_20_TABLE_GUID); ACPI_20_TABLE_GUID);
if (rsdp_addr) if (rsdp_addr)
return (acpi_physical_address)rsdp_addr; return (acpi_physical_address)rsdp_addr;
/* No ACPI_20_TABLE_GUID found, fallback to ACPI_TABLE_GUID. */ /* No ACPI_20_TABLE_GUID found, fallback to ACPI_TABLE_GUID. */
rsdp_addr = efi_find_vendor_table(boot_params, cfg_tbl_pa, cfg_tbl_len, rsdp_addr = efi_find_vendor_table(boot_params_ptr, cfg_tbl_pa, cfg_tbl_len,
ACPI_TABLE_GUID); ACPI_TABLE_GUID);
if (rsdp_addr) if (rsdp_addr)
return (acpi_physical_address)rsdp_addr; return (acpi_physical_address)rsdp_addr;
...@@ -56,15 +56,15 @@ static acpi_physical_address efi_get_rsdp_addr(void) ...@@ -56,15 +56,15 @@ static acpi_physical_address efi_get_rsdp_addr(void)
enum efi_type et; enum efi_type et;
int ret; int ret;
et = efi_get_type(boot_params); et = efi_get_type(boot_params_ptr);
if (et == EFI_TYPE_NONE) if (et == EFI_TYPE_NONE)
return 0; return 0;
systab_pa = efi_get_system_table(boot_params); systab_pa = efi_get_system_table(boot_params_ptr);
if (!systab_pa) if (!systab_pa)
error("EFI support advertised, but unable to locate system table."); error("EFI support advertised, but unable to locate system table.");
ret = efi_get_conf_table(boot_params, &cfg_tbl_pa, &cfg_tbl_len); ret = efi_get_conf_table(boot_params_ptr, &cfg_tbl_pa, &cfg_tbl_len);
if (ret || !cfg_tbl_pa) if (ret || !cfg_tbl_pa)
error("EFI config table not found."); error("EFI config table not found.");
...@@ -156,7 +156,7 @@ acpi_physical_address get_rsdp_addr(void) ...@@ -156,7 +156,7 @@ acpi_physical_address get_rsdp_addr(void)
{ {
acpi_physical_address pa; acpi_physical_address pa;
pa = boot_params->acpi_rsdp_addr; pa = boot_params_ptr->acpi_rsdp_addr;
if (!pa) if (!pa)
pa = efi_get_rsdp_addr(); pa = efi_get_rsdp_addr();
...@@ -210,7 +210,7 @@ static unsigned long get_acpi_srat_table(void) ...@@ -210,7 +210,7 @@ static unsigned long get_acpi_srat_table(void)
rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp(); rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
if (!rsdp) if (!rsdp)
rsdp = (struct acpi_table_rsdp *)(long) rsdp = (struct acpi_table_rsdp *)(long)
boot_params->acpi_rsdp_addr; boot_params_ptr->acpi_rsdp_addr;
if (!rsdp) if (!rsdp)
return 0; return 0;
......
...@@ -14,9 +14,9 @@ static inline char rdfs8(addr_t addr) ...@@ -14,9 +14,9 @@ static inline char rdfs8(addr_t addr)
#include "../cmdline.c" #include "../cmdline.c"
unsigned long get_cmd_line_ptr(void) unsigned long get_cmd_line_ptr(void)
{ {
unsigned long cmd_line_ptr = boot_params->hdr.cmd_line_ptr; unsigned long cmd_line_ptr = boot_params_ptr->hdr.cmd_line_ptr;
cmd_line_ptr |= (u64)boot_params->ext_cmd_line_ptr << 32; cmd_line_ptr |= (u64)boot_params_ptr->ext_cmd_line_ptr << 32;
return cmd_line_ptr; return cmd_line_ptr;
} }
......
...@@ -159,8 +159,9 @@ void initialize_identity_maps(void *rmode) ...@@ -159,8 +159,9 @@ void initialize_identity_maps(void *rmode)
* or does not touch all the pages covering them. * or does not touch all the pages covering them.
*/ */
kernel_add_identity_map((unsigned long)_head, (unsigned long)_end); kernel_add_identity_map((unsigned long)_head, (unsigned long)_end);
boot_params = rmode; boot_params_ptr = rmode;
kernel_add_identity_map((unsigned long)boot_params, (unsigned long)(boot_params + 1)); kernel_add_identity_map((unsigned long)boot_params_ptr,
(unsigned long)(boot_params_ptr + 1));
cmdline = get_cmd_line_ptr(); cmdline = get_cmd_line_ptr();
kernel_add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE); kernel_add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
...@@ -168,7 +169,7 @@ void initialize_identity_maps(void *rmode) ...@@ -168,7 +169,7 @@ void initialize_identity_maps(void *rmode)
* Also map the setup_data entries passed via boot_params in case they * Also map the setup_data entries passed via boot_params in case they
* need to be accessed by uncompressed kernel via the identity mapping. * need to be accessed by uncompressed kernel via the identity mapping.
*/ */
sd = (struct setup_data *)boot_params->hdr.setup_data; sd = (struct setup_data *)boot_params_ptr->hdr.setup_data;
while (sd) { while (sd) {
unsigned long sd_addr = (unsigned long)sd; unsigned long sd_addr = (unsigned long)sd;
......
...@@ -63,7 +63,7 @@ static unsigned long get_boot_seed(void) ...@@ -63,7 +63,7 @@ static unsigned long get_boot_seed(void)
unsigned long hash = 0; unsigned long hash = 0;
hash = rotate_xor(hash, build_str, sizeof(build_str)); hash = rotate_xor(hash, build_str, sizeof(build_str));
hash = rotate_xor(hash, boot_params, sizeof(*boot_params)); hash = rotate_xor(hash, boot_params_ptr, sizeof(*boot_params_ptr));
return hash; return hash;
} }
...@@ -383,7 +383,7 @@ static void handle_mem_options(void) ...@@ -383,7 +383,7 @@ static void handle_mem_options(void)
static void mem_avoid_init(unsigned long input, unsigned long input_size, static void mem_avoid_init(unsigned long input, unsigned long input_size,
unsigned long output) unsigned long output)
{ {
unsigned long init_size = boot_params->hdr.init_size; unsigned long init_size = boot_params_ptr->hdr.init_size;
u64 initrd_start, initrd_size; u64 initrd_start, initrd_size;
unsigned long cmd_line, cmd_line_size; unsigned long cmd_line, cmd_line_size;
...@@ -395,10 +395,10 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, ...@@ -395,10 +395,10 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
mem_avoid[MEM_AVOID_ZO_RANGE].size = (output + init_size) - input; mem_avoid[MEM_AVOID_ZO_RANGE].size = (output + init_size) - input;
/* Avoid initrd. */ /* Avoid initrd. */
initrd_start = (u64)boot_params->ext_ramdisk_image << 32; initrd_start = (u64)boot_params_ptr->ext_ramdisk_image << 32;
initrd_start |= boot_params->hdr.ramdisk_image; initrd_start |= boot_params_ptr->hdr.ramdisk_image;
initrd_size = (u64)boot_params->ext_ramdisk_size << 32; initrd_size = (u64)boot_params_ptr->ext_ramdisk_size << 32;
initrd_size |= boot_params->hdr.ramdisk_size; initrd_size |= boot_params_ptr->hdr.ramdisk_size;
mem_avoid[MEM_AVOID_INITRD].start = initrd_start; mem_avoid[MEM_AVOID_INITRD].start = initrd_start;
mem_avoid[MEM_AVOID_INITRD].size = initrd_size; mem_avoid[MEM_AVOID_INITRD].size = initrd_size;
/* No need to set mapping for initrd, it will be handled in VO. */ /* No need to set mapping for initrd, it will be handled in VO. */
...@@ -413,8 +413,8 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size, ...@@ -413,8 +413,8 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
} }
/* Avoid boot parameters. */ /* Avoid boot parameters. */
mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params; mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params_ptr;
mem_avoid[MEM_AVOID_BOOTPARAMS].size = sizeof(*boot_params); mem_avoid[MEM_AVOID_BOOTPARAMS].size = sizeof(*boot_params_ptr);
/* We don't need to set a mapping for setup_data. */ /* We don't need to set a mapping for setup_data. */
...@@ -447,7 +447,7 @@ static bool mem_avoid_overlap(struct mem_vector *img, ...@@ -447,7 +447,7 @@ static bool mem_avoid_overlap(struct mem_vector *img,
} }
/* Avoid all entries in the setup_data linked list. */ /* Avoid all entries in the setup_data linked list. */
ptr = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data; ptr = (struct setup_data *)(unsigned long)boot_params_ptr->hdr.setup_data;
while (ptr) { while (ptr) {
struct mem_vector avoid; struct mem_vector avoid;
...@@ -706,7 +706,7 @@ static inline bool memory_type_is_free(efi_memory_desc_t *md) ...@@ -706,7 +706,7 @@ static inline bool memory_type_is_free(efi_memory_desc_t *md)
static bool static bool
process_efi_entries(unsigned long minimum, unsigned long image_size) process_efi_entries(unsigned long minimum, unsigned long image_size)
{ {
struct efi_info *e = &boot_params->efi_info; struct efi_info *e = &boot_params_ptr->efi_info;
bool efi_mirror_found = false; bool efi_mirror_found = false;
struct mem_vector region; struct mem_vector region;
efi_memory_desc_t *md; efi_memory_desc_t *md;
...@@ -777,8 +777,8 @@ static void process_e820_entries(unsigned long minimum, ...@@ -777,8 +777,8 @@ static void process_e820_entries(unsigned long minimum,
struct boot_e820_entry *entry; struct boot_e820_entry *entry;
/* Verify potential e820 positions, appending to slots list. */ /* Verify potential e820 positions, appending to slots list. */
for (i = 0; i < boot_params->e820_entries; i++) { for (i = 0; i < boot_params_ptr->e820_entries; i++) {
entry = &boot_params->e820_table[i]; entry = &boot_params_ptr->e820_table[i];
/* Skip non-RAM entries. */ /* Skip non-RAM entries. */
if (entry->type != E820_TYPE_RAM) if (entry->type != E820_TYPE_RAM)
continue; continue;
...@@ -852,7 +852,7 @@ void choose_random_location(unsigned long input, ...@@ -852,7 +852,7 @@ void choose_random_location(unsigned long input,
return; return;
} }
boot_params->hdr.loadflags |= KASLR_FLAG; boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
if (IS_ENABLED(CONFIG_X86_32)) if (IS_ENABLED(CONFIG_X86_32))
mem_limit = KERNEL_IMAGE_SIZE; mem_limit = KERNEL_IMAGE_SIZE;
......
...@@ -54,17 +54,17 @@ bool init_unaccepted_memory(void) ...@@ -54,17 +54,17 @@ bool init_unaccepted_memory(void)
enum efi_type et; enum efi_type et;
int ret; int ret;
et = efi_get_type(boot_params); et = efi_get_type(boot_params_ptr);
if (et == EFI_TYPE_NONE) if (et == EFI_TYPE_NONE)
return false; return false;
ret = efi_get_conf_table(boot_params, &cfg_table_pa, &cfg_table_len); ret = efi_get_conf_table(boot_params_ptr, &cfg_table_pa, &cfg_table_len);
if (ret) { if (ret) {
warn("EFI config table not found."); warn("EFI config table not found.");
return false; return false;
} }
table = (void *)efi_find_vendor_table(boot_params, cfg_table_pa, table = (void *)efi_find_vendor_table(boot_params_ptr, cfg_table_pa,
cfg_table_len, guid); cfg_table_len, guid);
if (!table) if (!table)
return false; return false;
......
...@@ -46,7 +46,7 @@ void *memmove(void *dest, const void *src, size_t n); ...@@ -46,7 +46,7 @@ void *memmove(void *dest, const void *src, size_t n);
/* /*
* This is set up by the setup-routine at boot-time * This is set up by the setup-routine at boot-time
*/ */
struct boot_params *boot_params; struct boot_params *boot_params_ptr;
struct port_io_ops pio_ops; struct port_io_ops pio_ops;
...@@ -132,8 +132,8 @@ void __putstr(const char *s) ...@@ -132,8 +132,8 @@ void __putstr(const char *s)
if (lines == 0 || cols == 0) if (lines == 0 || cols == 0)
return; return;
x = boot_params->screen_info.orig_x; x = boot_params_ptr->screen_info.orig_x;
y = boot_params->screen_info.orig_y; y = boot_params_ptr->screen_info.orig_y;
while ((c = *s++) != '\0') { while ((c = *s++) != '\0') {
if (c == '\n') { if (c == '\n') {
...@@ -154,8 +154,8 @@ void __putstr(const char *s) ...@@ -154,8 +154,8 @@ void __putstr(const char *s)
} }
} }
boot_params->screen_info.orig_x = x; boot_params_ptr->screen_info.orig_x = x;
boot_params->screen_info.orig_y = y; boot_params_ptr->screen_info.orig_y = y;
pos = (x + cols * y) * 2; /* Update cursor position */ pos = (x + cols * y) * 2; /* Update cursor position */
outb(14, vidport); outb(14, vidport);
...@@ -382,14 +382,14 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output) ...@@ -382,14 +382,14 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
size_t entry_offset; size_t entry_offset;
/* Retain x86 boot parameters pointer passed from startup_32/64. */ /* Retain x86 boot parameters pointer passed from startup_32/64. */
boot_params = rmode; boot_params_ptr = rmode;
/* Clear flags intended for solely in-kernel use. */ /* Clear flags intended for solely in-kernel use. */
boot_params->hdr.loadflags &= ~KASLR_FLAG; boot_params_ptr->hdr.loadflags &= ~KASLR_FLAG;
sanitize_boot_params(boot_params); sanitize_boot_params(boot_params_ptr);
if (boot_params->screen_info.orig_video_mode == 7) { if (boot_params_ptr->screen_info.orig_video_mode == 7) {
vidmem = (char *) 0xb0000; vidmem = (char *) 0xb0000;
vidport = 0x3b4; vidport = 0x3b4;
} else { } else {
...@@ -397,8 +397,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output) ...@@ -397,8 +397,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
vidport = 0x3d4; vidport = 0x3d4;
} }
lines = boot_params->screen_info.orig_video_lines; lines = boot_params_ptr->screen_info.orig_video_lines;
cols = boot_params->screen_info.orig_video_cols; cols = boot_params_ptr->screen_info.orig_video_cols;
init_default_io_ops(); init_default_io_ops();
...@@ -417,7 +417,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output) ...@@ -417,7 +417,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
* so that early debugging output from the RSDP parsing code can be * so that early debugging output from the RSDP parsing code can be
* collected. * collected.
*/ */
boot_params->acpi_rsdp_addr = get_rsdp_addr(); boot_params_ptr->acpi_rsdp_addr = get_rsdp_addr();
debug_putstr("early console in extract_kernel\n"); debug_putstr("early console in extract_kernel\n");
......
...@@ -61,7 +61,6 @@ extern memptr free_mem_ptr; ...@@ -61,7 +61,6 @@ extern memptr free_mem_ptr;
extern memptr free_mem_end_ptr; extern memptr free_mem_end_ptr;
void *malloc(int size); void *malloc(int size);
void free(void *where); void free(void *where);
extern struct boot_params *boot_params;
void __putstr(const char *s); void __putstr(const char *s);
void __puthex(unsigned long value); void __puthex(unsigned long value);
#define error_putstr(__x) __putstr(__x) #define error_putstr(__x) __putstr(__x)
......
...@@ -28,7 +28,6 @@ static char trampoline_save[TRAMPOLINE_32BIT_SIZE]; ...@@ -28,7 +28,6 @@ static char trampoline_save[TRAMPOLINE_32BIT_SIZE];
*/ */
unsigned long *trampoline_32bit __section(".data"); unsigned long *trampoline_32bit __section(".data");
extern struct boot_params *boot_params;
int cmdline_find_option_bool(const char *option); int cmdline_find_option_bool(const char *option);
static unsigned long find_trampoline_placement(void) static unsigned long find_trampoline_placement(void)
...@@ -49,7 +48,7 @@ static unsigned long find_trampoline_placement(void) ...@@ -49,7 +48,7 @@ static unsigned long find_trampoline_placement(void)
* *
* Only look for values in the legacy ROM for non-EFI system. * Only look for values in the legacy ROM for non-EFI system.
*/ */
signature = (char *)&boot_params->efi_info.efi_loader_signature; signature = (char *)&boot_params_ptr->efi_info.efi_loader_signature;
if (strncmp(signature, EFI32_LOADER_SIGNATURE, 4) && if (strncmp(signature, EFI32_LOADER_SIGNATURE, 4) &&
strncmp(signature, EFI64_LOADER_SIGNATURE, 4)) { strncmp(signature, EFI64_LOADER_SIGNATURE, 4)) {
ebda_start = *(unsigned short *)0x40e << 4; ebda_start = *(unsigned short *)0x40e << 4;
...@@ -65,10 +64,10 @@ static unsigned long find_trampoline_placement(void) ...@@ -65,10 +64,10 @@ static unsigned long find_trampoline_placement(void)
bios_start = round_down(bios_start, PAGE_SIZE); bios_start = round_down(bios_start, PAGE_SIZE);
/* Find the first usable memory region under bios_start. */ /* Find the first usable memory region under bios_start. */
for (i = boot_params->e820_entries - 1; i >= 0; i--) { for (i = boot_params_ptr->e820_entries - 1; i >= 0; i--) {
unsigned long new = bios_start; unsigned long new = bios_start;
entry = &boot_params->e820_table[i]; entry = &boot_params_ptr->e820_table[i];
/* Skip all entries above bios_start. */ /* Skip all entries above bios_start. */
if (bios_start <= entry->addr) if (bios_start <= entry->addr)
...@@ -107,7 +106,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable) ...@@ -107,7 +106,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable)
bool l5_required = false; bool l5_required = false;
/* Initialize boot_params. Required for cmdline_find_option_bool(). */ /* Initialize boot_params. Required for cmdline_find_option_bool(). */
boot_params = bp; boot_params_ptr = bp;
/* /*
* Check if LA57 is desired and supported. * Check if LA57 is desired and supported.
......
...@@ -615,7 +615,7 @@ void sev_prep_identity_maps(unsigned long top_level_pgt) ...@@ -615,7 +615,7 @@ void sev_prep_identity_maps(unsigned long top_level_pgt)
* accessed after switchover. * accessed after switchover.
*/ */
if (sev_snp_enabled()) { if (sev_snp_enabled()) {
unsigned long cc_info_pa = boot_params->cc_blob_address; unsigned long cc_info_pa = boot_params_ptr->cc_blob_address;
struct cc_blob_sev_info *cc_info; struct cc_blob_sev_info *cc_info;
kernel_add_identity_map(cc_info_pa, cc_info_pa + sizeof(*cc_info)); kernel_add_identity_map(cc_info_pa, cc_info_pa + sizeof(*cc_info));
......
...@@ -43,11 +43,13 @@ SECTIONS ...@@ -43,11 +43,13 @@ SECTIONS
*(.rodata.*) *(.rodata.*)
_erodata = . ; _erodata = . ;
} }
.data : { .data : ALIGN(0x1000) {
_data = . ; _data = . ;
*(.data) *(.data)
*(.data.*) *(.data.*)
*(.bss.efistub)
/* Add 4 bytes of extra space for a CRC-32 checksum */
. = ALIGN(. + 4, 0x200);
_edata = . ; _edata = . ;
} }
. = ALIGN(L1_CACHE_BYTES); . = ALIGN(L1_CACHE_BYTES);
......
...@@ -36,66 +36,20 @@ SYSSEG = 0x1000 /* historical load address >> 4 */ ...@@ -36,66 +36,20 @@ SYSSEG = 0x1000 /* historical load address >> 4 */
#define ROOT_RDONLY 1 #define ROOT_RDONLY 1
#endif #endif
.set salign, 0x1000
.set falign, 0x200
.code16 .code16
.section ".bstext", "ax" .section ".bstext", "ax"
.global bootsect_start
bootsect_start:
#ifdef CONFIG_EFI_STUB #ifdef CONFIG_EFI_STUB
# "MZ", MS-DOS header # "MZ", MS-DOS header
.word MZ_MAGIC .word MZ_MAGIC
#endif
# Normalize the start address
ljmp $BOOTSEG, $start2
start2:
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
xorw %sp, %sp
sti
cld
movw $bugger_off_msg, %si
msg_loop:
lodsb
andb %al, %al
jz bs_die
movb $0xe, %ah
movw $7, %bx
int $0x10
jmp msg_loop
bs_die:
# Allow the user to press a key, then reboot
xorw %ax, %ax
int $0x16
int $0x19
# int 0x19 should never return. In case it does anyway,
# invoke the BIOS reset code...
ljmp $0xf000,$0xfff0
#ifdef CONFIG_EFI_STUB
.org 0x38 .org 0x38
# #
# Offset to the PE header. # Offset to the PE header.
# #
.long LINUX_PE_MAGIC .long LINUX_PE_MAGIC
.long pe_header .long pe_header
#endif /* CONFIG_EFI_STUB */
.section ".bsdata", "a"
bugger_off_msg:
.ascii "Use a boot loader.\r\n"
.ascii "\n"
.ascii "Remove disk and press any key to reboot...\r\n"
.byte 0
#ifdef CONFIG_EFI_STUB
pe_header: pe_header:
.long PE_MAGIC .long PE_MAGIC
...@@ -124,30 +78,26 @@ optional_header: ...@@ -124,30 +78,26 @@ optional_header:
.byte 0x02 # MajorLinkerVersion .byte 0x02 # MajorLinkerVersion
.byte 0x14 # MinorLinkerVersion .byte 0x14 # MinorLinkerVersion
# Filled in by build.c .long ZO__data # SizeOfCode
.long 0 # SizeOfCode
.long 0 # SizeOfInitializedData .long ZO__end - ZO__data # SizeOfInitializedData
.long 0 # SizeOfUninitializedData .long 0 # SizeOfUninitializedData
# Filled in by build.c .long setup_size + ZO_efi_pe_entry # AddressOfEntryPoint
.long 0x0000 # AddressOfEntryPoint
.long 0x0200 # BaseOfCode .long setup_size # BaseOfCode
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
.long 0 # data .long 0 # data
#endif #endif
extra_header_fields: extra_header_fields:
# PE specification requires ImageBase to be 64k aligned
.set image_base, (LOAD_PHYSICAL_ADDR + 0xffff) & ~0xffff
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
.long image_base # ImageBase .long 0 # ImageBase
#else #else
.quad image_base # ImageBase .quad 0 # ImageBase
#endif #endif
.long 0x20 # SectionAlignment .long salign # SectionAlignment
.long 0x20 # FileAlignment .long falign # FileAlignment
.word 0 # MajorOperatingSystemVersion .word 0 # MajorOperatingSystemVersion
.word 0 # MinorOperatingSystemVersion .word 0 # MinorOperatingSystemVersion
.word LINUX_EFISTUB_MAJOR_VERSION # MajorImageVersion .word LINUX_EFISTUB_MAJOR_VERSION # MajorImageVersion
...@@ -156,12 +106,10 @@ extra_header_fields: ...@@ -156,12 +106,10 @@ extra_header_fields:
.word 0 # MinorSubsystemVersion .word 0 # MinorSubsystemVersion
.long 0 # Win32VersionValue .long 0 # Win32VersionValue
# .long setup_size + ZO__end + pecompat_vsize
# The size of the bzImage is written in tools/build.c # SizeOfImage
#
.long 0 # SizeOfImage
.long 0x200 # SizeOfHeaders .long salign # SizeOfHeaders
.long 0 # CheckSum .long 0 # CheckSum
.word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application) .word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application)
#ifdef CONFIG_EFI_DXE_MEM_ATTRIBUTES #ifdef CONFIG_EFI_DXE_MEM_ATTRIBUTES
...@@ -192,87 +140,78 @@ extra_header_fields: ...@@ -192,87 +140,78 @@ extra_header_fields:
# Section table # Section table
section_table: section_table:
#
# The offset & size fields are filled in by build.c.
#
.ascii ".setup" .ascii ".setup"
.byte 0 .byte 0
.byte 0 .byte 0
.long 0 .long setup_size - salign # VirtualSize
.long 0x0 # startup_{32,64} .long salign # VirtualAddress
.long 0 # Size of initialized data .long pecompat_fstart - salign # SizeOfRawData
# on disk .long salign # PointerToRawData
.long 0x0 # startup_{32,64}
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_CNT_CODE | \
IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_EXECUTE | \
IMAGE_SCN_ALIGN_16BYTES # Characteristics
# .long 0, 0, 0
# The EFI application loader requires a relocation section
# because EFI applications must be relocatable. The .reloc
# offset & size fields are filled in by build.c.
#
.ascii ".reloc"
.byte 0
.byte 0
.long 0
.long 0
.long 0 # SizeOfRawData
.long 0 # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_CNT_INITIALIZED_DATA | \ .long IMAGE_SCN_CNT_INITIALIZED_DATA | \
IMAGE_SCN_MEM_READ | \ IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_DISCARDABLE | \ IMAGE_SCN_MEM_DISCARDABLE # Characteristics
IMAGE_SCN_ALIGN_1BYTES # Characteristics
#ifdef CONFIG_EFI_MIXED #ifdef CONFIG_EFI_MIXED
#
# The offset & size fields are filled in by build.c.
#
.asciz ".compat" .asciz ".compat"
.long 0
.long 0x0 .long 8 # VirtualSize
.long 0 # Size of initialized data .long setup_size + ZO__end # VirtualAddress
# on disk .long pecompat_fsize # SizeOfRawData
.long 0x0 .long pecompat_fstart # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers .long 0, 0, 0
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_CNT_INITIALIZED_DATA | \ .long IMAGE_SCN_CNT_INITIALIZED_DATA | \
IMAGE_SCN_MEM_READ | \ IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_DISCARDABLE | \ IMAGE_SCN_MEM_DISCARDABLE # Characteristics
IMAGE_SCN_ALIGN_1BYTES # Characteristics
#endif
# /*
# The offset & size fields are filled in by build.c. * Put the IA-32 machine type and the associated entry point address in
# * the .compat section, so loaders can figure out which other execution
* modes this image supports.
*/
.pushsection ".pecompat", "a", @progbits
.balign falign
.set pecompat_vsize, salign
.globl pecompat_fstart
pecompat_fstart:
.byte 0x1 # Version
.byte 8 # Size
.word IMAGE_FILE_MACHINE_I386 # PE machine type
.long setup_size + ZO_efi32_pe_entry # Entrypoint
.popsection
#else
.set pecompat_vsize, 0
.set pecompat_fstart, setup_size
#endif
.ascii ".text" .ascii ".text"
.byte 0 .byte 0
.byte 0 .byte 0
.byte 0 .byte 0
.long 0 .long ZO__data
.long 0x0 # startup_{32,64} .long setup_size
.long 0 # Size of initialized data .long ZO__data # Size of initialized data
# on disk # on disk
.long 0x0 # startup_{32,64} .long setup_size
.long 0 # PointerToRelocations .long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers .long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations .word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers .word 0 # NumberOfLineNumbers
.long IMAGE_SCN_CNT_CODE | \ .long IMAGE_SCN_CNT_CODE | \
IMAGE_SCN_MEM_READ | \ IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_EXECUTE | \ IMAGE_SCN_MEM_EXECUTE # Characteristics
IMAGE_SCN_ALIGN_16BYTES # Characteristics
.ascii ".data\0\0\0"
.long ZO__end - ZO__data # VirtualSize
.long setup_size + ZO__data # VirtualAddress
.long ZO__edata - ZO__data # SizeOfRawData
.long setup_size + ZO__data # PointerToRawData
.long 0, 0, 0
.long IMAGE_SCN_CNT_INITIALIZED_DATA | \
IMAGE_SCN_MEM_READ | \
IMAGE_SCN_MEM_WRITE # Characteristics
.set section_count, (. - section_table) / 40 .set section_count, (. - section_table) / 40
#endif /* CONFIG_EFI_STUB */ #endif /* CONFIG_EFI_STUB */
...@@ -286,12 +225,12 @@ sentinel: .byte 0xff, 0xff /* Used to detect broken loaders */ ...@@ -286,12 +225,12 @@ sentinel: .byte 0xff, 0xff /* Used to detect broken loaders */
.globl hdr .globl hdr
hdr: hdr:
setup_sects: .byte 0 /* Filled in by build.c */ .byte setup_sects - 1
root_flags: .word ROOT_RDONLY root_flags: .word ROOT_RDONLY
syssize: .long 0 /* Filled in by build.c */ syssize: .long ZO__edata / 16
ram_size: .word 0 /* Obsolete */ ram_size: .word 0 /* Obsolete */
vid_mode: .word SVGA_MODE vid_mode: .word SVGA_MODE
root_dev: .word 0 /* Filled in by build.c */ root_dev: .word 0 /* Default to major/minor 0/0 */
boot_flag: .word 0xAA55 boot_flag: .word 0xAA55
# offset 512, entry point # offset 512, entry point
...@@ -579,9 +518,25 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr ...@@ -579,9 +518,25 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
# define INIT_SIZE VO_INIT_SIZE # define INIT_SIZE VO_INIT_SIZE
#endif #endif
.macro __handover_offset
#ifndef CONFIG_EFI_HANDOVER_PROTOCOL
.long 0
#elif !defined(CONFIG_X86_64)
.long ZO_efi32_stub_entry
#else
/* Yes, this is really how we defined it :( */
.long ZO_efi64_stub_entry - 0x200
#ifdef CONFIG_EFI_MIXED
.if ZO_efi32_stub_entry != ZO_efi64_stub_entry - 0x200
.error "32-bit and 64-bit EFI entry points do not match"
.endif
#endif
#endif
.endm
init_size: .long INIT_SIZE # kernel initialization size init_size: .long INIT_SIZE # kernel initialization size
handover_offset: .long 0 # Filled in by build.c handover_offset: __handover_offset
kernel_info_offset: .long 0 # Filled in by build.c kernel_info_offset: .long ZO_kernel_info
# End of setup header ##################################################### # End of setup header #####################################################
......
...@@ -10,10 +10,11 @@ ENTRY(_start) ...@@ -10,10 +10,11 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0; . = 0;
.bstext : { *(.bstext) } .bstext : {
.bsdata : { *(.bsdata) } *(.bstext)
. = 495; . = 495;
} =0xffffffff
.header : { *(.header) } .header : { *(.header) }
.entrytext : { *(.entrytext) } .entrytext : { *(.entrytext) }
.inittext : { *(.inittext) } .inittext : { *(.inittext) }
...@@ -35,11 +36,16 @@ SECTIONS ...@@ -35,11 +36,16 @@ SECTIONS
. = ALIGN(16); . = ALIGN(16);
.data : { *(.data*) } .data : { *(.data*) }
.pecompat : { *(.pecompat) }
PROVIDE(pecompat_fsize = setup_size - pecompat_fstart);
.signature : { .signature : {
setup_sig = .; setup_sig = .;
LONG(0x5a5aaa55) LONG(0x5a5aaa55)
}
setup_size = ALIGN(ABSOLUTE(.), 4096);
setup_sects = ABSOLUTE(setup_size / 512);
}
. = ALIGN(16); . = ALIGN(16);
.bss : .bss :
......
...@@ -40,10 +40,6 @@ typedef unsigned char u8; ...@@ -40,10 +40,6 @@ typedef unsigned char u8;
typedef unsigned short u16; typedef unsigned short u16;
typedef unsigned int u32; typedef unsigned int u32;
#define DEFAULT_MAJOR_ROOT 0
#define DEFAULT_MINOR_ROOT 0
#define DEFAULT_ROOT_DEV (DEFAULT_MAJOR_ROOT << 8 | DEFAULT_MINOR_ROOT)
/* Minimal number of setup sectors */ /* Minimal number of setup sectors */
#define SETUP_SECT_MIN 5 #define SETUP_SECT_MIN 5
#define SETUP_SECT_MAX 64 #define SETUP_SECT_MAX 64
...@@ -51,22 +47,7 @@ typedef unsigned int u32; ...@@ -51,22 +47,7 @@ typedef unsigned int u32;
/* This must be large enough to hold the entire setup */ /* This must be large enough to hold the entire setup */
u8 buf[SETUP_SECT_MAX*512]; u8 buf[SETUP_SECT_MAX*512];
#define PECOFF_RELOC_RESERVE 0x20 static unsigned long _edata;
#ifdef CONFIG_EFI_MIXED
#define PECOFF_COMPAT_RESERVE 0x20
#else
#define PECOFF_COMPAT_RESERVE 0x0
#endif
static unsigned long efi32_stub_entry;
static unsigned long efi64_stub_entry;
static unsigned long efi_pe_entry;
static unsigned long efi32_pe_entry;
static unsigned long kernel_info;
static unsigned long startup_64;
static unsigned long _ehead;
static unsigned long _end;
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
...@@ -152,180 +133,6 @@ static void usage(void) ...@@ -152,180 +133,6 @@ static void usage(void)
die("Usage: build setup system zoffset.h image"); die("Usage: build setup system zoffset.h image");
} }
#ifdef CONFIG_EFI_STUB
static void update_pecoff_section_header_fields(char *section_name, u32 vma, u32 size, u32 datasz, u32 offset)
{
unsigned int pe_header;
unsigned short num_sections;
u8 *section;
pe_header = get_unaligned_le32(&buf[0x3c]);
num_sections = get_unaligned_le16(&buf[pe_header + 6]);
#ifdef CONFIG_X86_32
section = &buf[pe_header + 0xa8];
#else
section = &buf[pe_header + 0xb8];
#endif
while (num_sections > 0) {
if (strncmp((char*)section, section_name, 8) == 0) {
/* section header size field */
put_unaligned_le32(size, section + 0x8);
/* section header vma field */
put_unaligned_le32(vma, section + 0xc);
/* section header 'size of initialised data' field */
put_unaligned_le32(datasz, section + 0x10);
/* section header 'file offset' field */
put_unaligned_le32(offset, section + 0x14);
break;
}
section += 0x28;
num_sections--;
}
}
static void update_pecoff_section_header(char *section_name, u32 offset, u32 size)
{
update_pecoff_section_header_fields(section_name, offset, size, size, offset);
}
static void update_pecoff_setup_and_reloc(unsigned int size)
{
u32 setup_offset = 0x200;
u32 reloc_offset = size - PECOFF_RELOC_RESERVE - PECOFF_COMPAT_RESERVE;
#ifdef CONFIG_EFI_MIXED
u32 compat_offset = reloc_offset + PECOFF_RELOC_RESERVE;
#endif
u32 setup_size = reloc_offset - setup_offset;
update_pecoff_section_header(".setup", setup_offset, setup_size);
update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE);
/*
* Modify .reloc section contents with a single entry. The
* relocation is applied to offset 10 of the relocation section.
*/
put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]);
put_unaligned_le32(10, &buf[reloc_offset + 4]);
#ifdef CONFIG_EFI_MIXED
update_pecoff_section_header(".compat", compat_offset, PECOFF_COMPAT_RESERVE);
/*
* Put the IA-32 machine type (0x14c) and the associated entry point
* address in the .compat section, so loaders can figure out which other
* execution modes this image supports.
*/
buf[compat_offset] = 0x1;
buf[compat_offset + 1] = 0x8;
put_unaligned_le16(0x14c, &buf[compat_offset + 2]);
put_unaligned_le32(efi32_pe_entry + size, &buf[compat_offset + 4]);
#endif
}
static void update_pecoff_text(unsigned int text_start, unsigned int file_sz,
unsigned int init_sz)
{
unsigned int pe_header;
unsigned int text_sz = file_sz - text_start;
unsigned int bss_sz = init_sz - file_sz;
pe_header = get_unaligned_le32(&buf[0x3c]);
/*
* The PE/COFF loader may load the image at an address which is
* misaligned with respect to the kernel_alignment field in the setup
* header.
*
* In order to avoid relocating the kernel to correct the misalignment,
* add slack to allow the buffer to be aligned within the declared size
* of the image.
*/
bss_sz += CONFIG_PHYSICAL_ALIGN;
init_sz += CONFIG_PHYSICAL_ALIGN;
/*
* Size of code: Subtract the size of the first sector (512 bytes)
* which includes the header.
*/
put_unaligned_le32(file_sz - 512 + bss_sz, &buf[pe_header + 0x1c]);
/* Size of image */
put_unaligned_le32(init_sz, &buf[pe_header + 0x50]);
/*
* Address of entry point for PE/COFF executable
*/
put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
update_pecoff_section_header_fields(".text", text_start, text_sz + bss_sz,
text_sz, text_start);
}
static int reserve_pecoff_reloc_section(int c)
{
/* Reserve 0x20 bytes for .reloc section */
memset(buf+c, 0, PECOFF_RELOC_RESERVE);
return PECOFF_RELOC_RESERVE;
}
static void efi_stub_defaults(void)
{
/* Defaults for old kernel */
#ifdef CONFIG_X86_32
efi_pe_entry = 0x10;
#else
efi_pe_entry = 0x210;
startup_64 = 0x200;
#endif
}
static void efi_stub_entry_update(void)
{
unsigned long addr = efi32_stub_entry;
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
#ifdef CONFIG_X86_64
/* Yes, this is really how we defined it :( */
addr = efi64_stub_entry - 0x200;
#endif
#ifdef CONFIG_EFI_MIXED
if (efi32_stub_entry != addr)
die("32-bit and 64-bit EFI entry points do not match\n");
#endif
#endif
put_unaligned_le32(addr, &buf[0x264]);
}
#else
static inline void update_pecoff_setup_and_reloc(unsigned int size) {}
static inline void update_pecoff_text(unsigned int text_start,
unsigned int file_sz,
unsigned int init_sz) {}
static inline void efi_stub_defaults(void) {}
static inline void efi_stub_entry_update(void) {}
static inline int reserve_pecoff_reloc_section(int c)
{
return 0;
}
#endif /* CONFIG_EFI_STUB */
static int reserve_pecoff_compat_section(int c)
{
/* Reserve 0x20 bytes for .compat section */
memset(buf+c, 0, PECOFF_COMPAT_RESERVE);
return PECOFF_COMPAT_RESERVE;
}
/* /*
* Parse zoffset.h and find the entry points. We could just #include zoffset.h * 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 * but that would mean tools/build would have to be rebuilt every time. It's
...@@ -354,14 +161,7 @@ static void parse_zoffset(char *fname) ...@@ -354,14 +161,7 @@ static void parse_zoffset(char *fname)
p = (char *)buf; p = (char *)buf;
while (p && *p) { while (p && *p) {
PARSE_ZOFS(p, efi32_stub_entry); PARSE_ZOFS(p, _edata);
PARSE_ZOFS(p, efi64_stub_entry);
PARSE_ZOFS(p, efi_pe_entry);
PARSE_ZOFS(p, efi32_pe_entry);
PARSE_ZOFS(p, kernel_info);
PARSE_ZOFS(p, startup_64);
PARSE_ZOFS(p, _ehead);
PARSE_ZOFS(p, _end);
p = strchr(p, '\n'); p = strchr(p, '\n');
while (p && (*p == '\r' || *p == '\n')) while (p && (*p == '\r' || *p == '\n'))
...@@ -371,17 +171,14 @@ static void parse_zoffset(char *fname) ...@@ -371,17 +171,14 @@ static void parse_zoffset(char *fname)
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
unsigned int i, sz, setup_sectors, init_sz; unsigned int i, sz, setup_sectors;
int c; int c;
u32 sys_size;
struct stat sb; struct stat sb;
FILE *file, *dest; FILE *file, *dest;
int fd; int fd;
void *kernel; void *kernel;
u32 crc = 0xffffffffUL; u32 crc = 0xffffffffUL;
efi_stub_defaults();
if (argc != 5) if (argc != 5)
usage(); usage();
parse_zoffset(argv[3]); parse_zoffset(argv[3]);
...@@ -403,72 +200,27 @@ int main(int argc, char ** argv) ...@@ -403,72 +200,27 @@ int main(int argc, char ** argv)
die("Boot block hasn't got boot flag (0xAA55)"); die("Boot block hasn't got boot flag (0xAA55)");
fclose(file); fclose(file);
c += reserve_pecoff_compat_section(c);
c += reserve_pecoff_reloc_section(c);
/* Pad unused space with zeros */ /* Pad unused space with zeros */
setup_sectors = (c + 511) / 512; setup_sectors = (c + 4095) / 4096;
setup_sectors *= 8;
if (setup_sectors < SETUP_SECT_MIN) if (setup_sectors < SETUP_SECT_MIN)
setup_sectors = SETUP_SECT_MIN; setup_sectors = SETUP_SECT_MIN;
i = setup_sectors*512; i = setup_sectors*512;
memset(buf+c, 0, i-c); memset(buf+c, 0, i-c);
update_pecoff_setup_and_reloc(i);
/* Set the default root device */
put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]);
/* Open and stat the kernel file */ /* Open and stat the kernel file */
fd = open(argv[2], O_RDONLY); fd = open(argv[2], O_RDONLY);
if (fd < 0) if (fd < 0)
die("Unable to open `%s': %m", argv[2]); die("Unable to open `%s': %m", argv[2]);
if (fstat(fd, &sb)) if (fstat(fd, &sb))
die("Unable to stat `%s': %m", argv[2]); die("Unable to stat `%s': %m", argv[2]);
sz = sb.st_size; 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); kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
if (kernel == MAP_FAILED) if (kernel == MAP_FAILED)
die("Unable to mmap '%s': %m", argv[2]); die("Unable to mmap '%s': %m", argv[2]);
/* Number of 16-byte paragraphs, including space for a 4-byte CRC */
sys_size = (sz + 15 + 4) / 16;
#ifdef CONFIG_EFI_STUB
/*
* COFF requires minimum 32-byte alignment of sections, and
* adding a signature is problematic without that alignment.
*/
sys_size = (sys_size + 1) & ~1;
#endif
/* Patch the setup code with the appropriate size parameters */
buf[0x1f1] = setup_sectors-1;
put_unaligned_le32(sys_size, &buf[0x1f4]);
init_sz = get_unaligned_le32(&buf[0x260]);
#ifdef CONFIG_EFI_STUB
/*
* The decompression buffer will start at ImageBase. When relocating
* the compressed kernel to its end, we must ensure that the head
* section does not get overwritten. The head section occupies
* [i, i + _ehead), and the destination is [init_sz - _end, init_sz).
*
* At present these should never overlap, because 'i' is at most 32k
* because of SETUP_SECT_MAX, '_ehead' is less than 1k, and the
* calculation of INIT_SIZE in boot/header.S ensures that
* 'init_sz - _end' is at least 64k.
*
* For future-proofing, increase init_sz if necessary.
*/
if (init_sz - _end < i + _ehead) {
init_sz = (i + _ehead + _end + 4095) & ~4095;
put_unaligned_le32(init_sz, &buf[0x260]);
}
#endif
update_pecoff_text(setup_sectors * 512, i + (sys_size * 16), init_sz);
efi_stub_entry_update();
/* Update kernel_info offset. */
put_unaligned_le32(kernel_info, &buf[0x268]);
crc = partial_crc32(buf, i, crc); crc = partial_crc32(buf, i, crc);
if (fwrite(buf, 1, i, dest) != i) if (fwrite(buf, 1, i, dest) != i)
...@@ -479,13 +231,6 @@ int main(int argc, char ** argv) ...@@ -479,13 +231,6 @@ int main(int argc, char ** argv)
if (fwrite(kernel, 1, sz, dest) != sz) if (fwrite(kernel, 1, sz, dest) != sz)
die("Writing kernel failed"); die("Writing kernel failed");
/* Add padding leaving 4 bytes for the checksum */
while (sz++ < (sys_size*16) - 4) {
crc = partial_crc32_one('\0', crc);
if (fwrite("\0", 1, 1, dest) != 1)
die("Writing padding failed");
}
/* Write the CRC */ /* Write the CRC */
put_unaligned_le32(crc, buf); put_unaligned_le32(crc, buf);
if (fwrite(buf, 1, 4, dest) != 4) if (fwrite(buf, 1, 4, dest) != 4)
......
...@@ -85,6 +85,8 @@ extern const unsigned long kernel_total_size; ...@@ -85,6 +85,8 @@ extern const unsigned long kernel_total_size;
unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr, unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
void (*error)(char *x)); void (*error)(char *x));
extern struct boot_params *boot_params_ptr;
#endif #endif
#endif /* _ASM_X86_BOOT_H */ #endif /* _ASM_X86_BOOT_H */
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#ifndef _ASM_X86_INIT_H #ifndef _ASM_X86_INIT_H
#define _ASM_X86_INIT_H #define _ASM_X86_INIT_H
#define __head __section(".head.text")
struct x86_mapping_info { struct x86_mapping_info {
void *(*alloc_pgt_page)(void *); /* allocate buf for page table */ void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
void *context; /* context for alloc_pgt_page */ void *context; /* context for alloc_pgt_page */
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <asm/trapnr.h> #include <asm/trapnr.h>
#include <asm/sev.h> #include <asm/sev.h>
#include <asm/tdx.h> #include <asm/tdx.h>
#include <asm/init.h>
/* /*
* Manage page tables very early on. * Manage page tables very early on.
...@@ -69,7 +70,7 @@ EXPORT_SYMBOL(vmemmap_base); ...@@ -69,7 +70,7 @@ EXPORT_SYMBOL(vmemmap_base);
/* /*
* GDT used on the boot CPU before switching to virtual addresses. * GDT used on the boot CPU before switching to virtual addresses.
*/ */
static struct desc_struct startup_gdt[GDT_ENTRIES] = { static struct desc_struct startup_gdt[GDT_ENTRIES] __initdata = {
[GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff), [GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff),
[GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff), [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
[GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff), [GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
...@@ -79,13 +80,11 @@ static struct desc_struct startup_gdt[GDT_ENTRIES] = { ...@@ -79,13 +80,11 @@ static struct desc_struct startup_gdt[GDT_ENTRIES] = {
* Address needs to be set at runtime because it references the startup_gdt * Address needs to be set at runtime because it references the startup_gdt
* while the kernel still uses a direct mapping. * while the kernel still uses a direct mapping.
*/ */
static struct desc_ptr startup_gdt_descr = { static struct desc_ptr startup_gdt_descr __initdata = {
.size = sizeof(startup_gdt), .size = sizeof(startup_gdt)-1,
.address = 0, .address = 0,
}; };
#define __head __section(".head.text")
static void __head *fixup_pointer(void *ptr, unsigned long physaddr) static void __head *fixup_pointer(void *ptr, unsigned long physaddr)
{ {
return ptr - (void *)_text + (void *)physaddr; return ptr - (void *)_text + (void *)physaddr;
...@@ -211,7 +210,7 @@ unsigned long __head __startup_64(unsigned long physaddr, ...@@ -211,7 +210,7 @@ unsigned long __head __startup_64(unsigned long physaddr,
/* Fixup the physical addresses in the page table */ /* Fixup the physical addresses in the page table */
pgd = fixup_pointer(&early_top_pgt, physaddr); pgd = fixup_pointer(early_top_pgt, physaddr);
p = pgd + pgd_index(__START_KERNEL_map); p = pgd + pgd_index(__START_KERNEL_map);
if (la57) if (la57)
*p = (unsigned long)level4_kernel_pgt; *p = (unsigned long)level4_kernel_pgt;
...@@ -220,11 +219,11 @@ unsigned long __head __startup_64(unsigned long physaddr, ...@@ -220,11 +219,11 @@ unsigned long __head __startup_64(unsigned long physaddr,
*p += _PAGE_TABLE_NOENC - __START_KERNEL_map + load_delta; *p += _PAGE_TABLE_NOENC - __START_KERNEL_map + load_delta;
if (la57) { if (la57) {
p4d = fixup_pointer(&level4_kernel_pgt, physaddr); p4d = fixup_pointer(level4_kernel_pgt, physaddr);
p4d[511] += load_delta; p4d[511] += load_delta;
} }
pud = fixup_pointer(&level3_kernel_pgt, physaddr); pud = fixup_pointer(level3_kernel_pgt, physaddr);
pud[510] += load_delta; pud[510] += load_delta;
pud[511] += load_delta; pud[511] += load_delta;
...@@ -588,7 +587,7 @@ static void set_bringup_idt_handler(gate_desc *idt, int n, void *handler) ...@@ -588,7 +587,7 @@ static void set_bringup_idt_handler(gate_desc *idt, int n, void *handler)
} }
/* This runs while still in the direct mapping */ /* This runs while still in the direct mapping */
static void startup_64_load_idt(unsigned long physbase) static void __head startup_64_load_idt(unsigned long physbase)
{ {
struct desc_ptr *desc = fixup_pointer(&bringup_idt_descr, physbase); struct desc_ptr *desc = fixup_pointer(&bringup_idt_descr, physbase);
gate_desc *idt = fixup_pointer(bringup_idt_table, physbase); gate_desc *idt = fixup_pointer(bringup_idt_table, physbase);
......
...@@ -108,13 +108,6 @@ lib-y := $(patsubst %.o,%.stub.o,$(lib-y)) ...@@ -108,13 +108,6 @@ lib-y := $(patsubst %.o,%.stub.o,$(lib-y))
# https://bugs.llvm.org/show_bug.cgi?id=46480 # https://bugs.llvm.org/show_bug.cgi?id=46480
STUBCOPY_FLAGS-y += --remove-section=.note.gnu.property STUBCOPY_FLAGS-y += --remove-section=.note.gnu.property
#
# For x86, bootloaders like systemd-boot or grub-efi do not zero-initialize the
# .bss section, so the .bss section of the EFI stub needs to be included in the
# .data section of the compressed kernel to ensure initialization. Rename the
# .bss section here so it's easy to pick out in the linker script.
#
STUBCOPY_FLAGS-$(CONFIG_X86) += --rename-section .bss=.bss.efistub,load,alloc
STUBCOPY_RELOC-$(CONFIG_X86_32) := R_386_32 STUBCOPY_RELOC-$(CONFIG_X86_32) := R_386_32
STUBCOPY_RELOC-$(CONFIG_X86_64) := R_X86_64_64 STUBCOPY_RELOC-$(CONFIG_X86_64) := R_X86_64_64
......
...@@ -449,9 +449,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle, ...@@ -449,9 +449,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_system_table_t *sys_table_arg) efi_system_table_t *sys_table_arg)
{ {
struct boot_params *boot_params; static struct boot_params boot_params __page_aligned_bss;
struct setup_header *hdr; struct setup_header *hdr = &boot_params.hdr;
void *image_base;
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
int options_size = 0; int options_size = 0;
efi_status_t status; efi_status_t status;
...@@ -469,30 +468,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -469,30 +468,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_exit(handle, status); efi_exit(handle, status);
} }
image_base = efi_table_attr(image, image_base); /* Assign the setup_header fields that the kernel actually cares about */
status = efi_allocate_pages(sizeof(struct boot_params),
(unsigned long *)&boot_params, ULONG_MAX);
if (status != EFI_SUCCESS) {
efi_err("Failed to allocate lowmem for boot params\n");
efi_exit(handle, status);
}
memset(boot_params, 0x0, sizeof(struct boot_params));
hdr = &boot_params->hdr;
/* Copy the setup header from the second sector to boot_params */
memcpy(&hdr->jump, image_base + 512,
sizeof(struct setup_header) - offsetof(struct setup_header, jump));
/*
* Fill out some of the header fields ourselves because the
* EFI firmware loader doesn't load the first sector.
*/
hdr->root_flags = 1; hdr->root_flags = 1;
hdr->vid_mode = 0xffff; hdr->vid_mode = 0xffff;
hdr->boot_flag = 0xAA55;
hdr->type_of_loader = 0x21; hdr->type_of_loader = 0x21;
...@@ -501,25 +479,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -501,25 +479,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
if (!cmdline_ptr) if (!cmdline_ptr)
goto fail; goto fail;
efi_set_u64_split((unsigned long)cmdline_ptr, efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->cmd_line_ptr,
&hdr->cmd_line_ptr, &boot_params->ext_cmd_line_ptr); &boot_params.ext_cmd_line_ptr);
hdr->ramdisk_image = 0;
hdr->ramdisk_size = 0;
/*
* Disregard any setup data that was provided by the bootloader:
* setup_data could be pointing anywhere, and we have no way of
* authenticating or validating the payload.
*/
hdr->setup_data = 0;
efi_stub_entry(handle, sys_table_arg, boot_params); efi_stub_entry(handle, sys_table_arg, &boot_params);
/* not reached */ /* not reached */
fail: fail:
efi_free(sizeof(struct boot_params), (unsigned long)boot_params);
efi_exit(handle, status); efi_exit(handle, status);
} }
...@@ -849,7 +815,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle, ...@@ -849,7 +815,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
unsigned long kernel_entry; unsigned long kernel_entry;
efi_status_t status; efi_status_t status;
boot_params_pointer = boot_params; boot_params_ptr = boot_params;
efi_system_table = sys_table_arg; efi_system_table = sys_table_arg;
/* Check if we were booted by the EFI firmware */ /* Check if we were booted by the EFI firmware */
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
#include <linux/efi.h> #include <linux/efi.h>
extern struct boot_params *boot_params_pointer asm("boot_params");
extern void trampoline_32bit_src(void *, bool); extern void trampoline_32bit_src(void *, bool);
extern const u16 trampoline_ljmp_imm_offset; extern const u16 trampoline_ljmp_imm_offset;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment