Changes to the x86 boot code in v6.7:
- 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 Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmU9B6ERHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1jXOg/+NAOQKhIYK0uFqAM+CEhZX4cqsJ9Ck0ze bqQ8pf5iCkbVZ+6ByiMSOszScTgVTSalRfKMYR+Fa9PVkLK4SNAeYPnGYugmLRoj U3lZYFpNDEwsZOmFwvqn7p+bGBQcBYKZuVI6bQh5U7Go4v6ujPjK4zTAK8SWDdTp DtEzhj9tELcYlm1NSV2OYu/k0IWAFV3Fc++G3WAm85xOK7oXVOYeMIlaVkpOyAXu th3yCw+Q0u1tuBS++77FwsEPt1KTzKGcTL7HpPrb4e4e4snOhmri+KAM/Noef7Vm lWqo8fTAeYwpYQ80oFsXVDhuI5LsfsuQgQid20sy1cWwswe1o1A73/AeP4pRogWl zLJuRcuNg2/VhPvMLdBWn5QdgJjH7CngeH+r/YkZPssPo6tfwa5UW7HOTCQvLsO9 a+xy098qkk9d+8Za0sYMuv8/4+Ev5II2haP8edLgNWQ8S5qKIUQaY+r6268pIN/F 0fGP9B3wblBjiNWCnd8UBh6T271g1O4vaMUt2URdcW3QObEq2EGnNiTc5tx9OPnP ZxQdAIl6pB0H0HIe9/7PABF40biKn84zmSl+KuXrhvh1f5FjYjJWVNyKlAKdSpSR wjvzg1KbhLiAHV05oQSHR7txMHJxfjpxAKmus0Hpqo6qVQ9FgrKiru9VHKocIpKU z66g+wEKUuY= =sxZJ -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
2b95bb0526
@ -43,7 +43,7 @@ endif
|
||||
|
||||
# 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.
|
||||
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 \
|
||||
-fno-strict-aliasing -fomit-frame-pointer -fno-pic \
|
||||
-mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
|
||||
|
@ -89,7 +89,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
|
||||
|
||||
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 $@
|
||||
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)
|
||||
* Search EFI system tables for RSDP. Preferred is ACPI_20_TABLE_GUID to
|
||||
* 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);
|
||||
if (rsdp_addr)
|
||||
return (acpi_physical_address)rsdp_addr;
|
||||
|
||||
/* 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);
|
||||
if (rsdp_addr)
|
||||
return (acpi_physical_address)rsdp_addr;
|
||||
@ -56,15 +56,15 @@ static acpi_physical_address efi_get_rsdp_addr(void)
|
||||
enum efi_type et;
|
||||
int ret;
|
||||
|
||||
et = efi_get_type(boot_params);
|
||||
et = efi_get_type(boot_params_ptr);
|
||||
if (et == EFI_TYPE_NONE)
|
||||
return 0;
|
||||
|
||||
systab_pa = efi_get_system_table(boot_params);
|
||||
systab_pa = efi_get_system_table(boot_params_ptr);
|
||||
if (!systab_pa)
|
||||
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)
|
||||
error("EFI config table not found.");
|
||||
|
||||
@ -156,7 +156,7 @@ acpi_physical_address get_rsdp_addr(void)
|
||||
{
|
||||
acpi_physical_address pa;
|
||||
|
||||
pa = boot_params->acpi_rsdp_addr;
|
||||
pa = boot_params_ptr->acpi_rsdp_addr;
|
||||
|
||||
if (!pa)
|
||||
pa = efi_get_rsdp_addr();
|
||||
@ -210,7 +210,7 @@ static unsigned long get_acpi_srat_table(void)
|
||||
rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
|
||||
if (!rsdp)
|
||||
rsdp = (struct acpi_table_rsdp *)(long)
|
||||
boot_params->acpi_rsdp_addr;
|
||||
boot_params_ptr->acpi_rsdp_addr;
|
||||
|
||||
if (!rsdp)
|
||||
return 0;
|
||||
|
@ -14,9 +14,9 @@ static inline char rdfs8(addr_t addr)
|
||||
#include "../cmdline.c"
|
||||
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;
|
||||
}
|
||||
|
@ -159,8 +159,9 @@ void initialize_identity_maps(void *rmode)
|
||||
* or does not touch all the pages covering them.
|
||||
*/
|
||||
kernel_add_identity_map((unsigned long)_head, (unsigned long)_end);
|
||||
boot_params = rmode;
|
||||
kernel_add_identity_map((unsigned long)boot_params, (unsigned long)(boot_params + 1));
|
||||
boot_params_ptr = rmode;
|
||||
kernel_add_identity_map((unsigned long)boot_params_ptr,
|
||||
(unsigned long)(boot_params_ptr + 1));
|
||||
cmdline = get_cmd_line_ptr();
|
||||
kernel_add_identity_map(cmdline, cmdline + COMMAND_LINE_SIZE);
|
||||
|
||||
@ -168,7 +169,7 @@ void initialize_identity_maps(void *rmode)
|
||||
* Also map the setup_data entries passed via boot_params in case they
|
||||
* 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) {
|
||||
unsigned long sd_addr = (unsigned long)sd;
|
||||
|
||||
|
@ -63,7 +63,7 @@ static unsigned long get_boot_seed(void)
|
||||
unsigned long hash = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -383,7 +383,7 @@ static void handle_mem_options(void)
|
||||
static void mem_avoid_init(unsigned long input, unsigned long input_size,
|
||||
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;
|
||||
unsigned long cmd_line, cmd_line_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;
|
||||
|
||||
/* Avoid initrd. */
|
||||
initrd_start = (u64)boot_params->ext_ramdisk_image << 32;
|
||||
initrd_start |= boot_params->hdr.ramdisk_image;
|
||||
initrd_size = (u64)boot_params->ext_ramdisk_size << 32;
|
||||
initrd_size |= boot_params->hdr.ramdisk_size;
|
||||
initrd_start = (u64)boot_params_ptr->ext_ramdisk_image << 32;
|
||||
initrd_start |= boot_params_ptr->hdr.ramdisk_image;
|
||||
initrd_size = (u64)boot_params_ptr->ext_ramdisk_size << 32;
|
||||
initrd_size |= boot_params_ptr->hdr.ramdisk_size;
|
||||
mem_avoid[MEM_AVOID_INITRD].start = initrd_start;
|
||||
mem_avoid[MEM_AVOID_INITRD].size = initrd_size;
|
||||
/* 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,
|
||||
}
|
||||
|
||||
/* Avoid boot parameters. */
|
||||
mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params;
|
||||
mem_avoid[MEM_AVOID_BOOTPARAMS].size = sizeof(*boot_params);
|
||||
mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params_ptr;
|
||||
mem_avoid[MEM_AVOID_BOOTPARAMS].size = sizeof(*boot_params_ptr);
|
||||
|
||||
/* We don't need to set a mapping for setup_data. */
|
||||
|
||||
@ -447,7 +447,7 @@ static bool mem_avoid_overlap(struct mem_vector *img,
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
struct mem_vector avoid;
|
||||
|
||||
@ -706,7 +706,7 @@ static inline bool memory_type_is_free(efi_memory_desc_t *md)
|
||||
static bool
|
||||
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;
|
||||
struct mem_vector region;
|
||||
efi_memory_desc_t *md;
|
||||
@ -777,8 +777,8 @@ static void process_e820_entries(unsigned long minimum,
|
||||
struct boot_e820_entry *entry;
|
||||
|
||||
/* Verify potential e820 positions, appending to slots list. */
|
||||
for (i = 0; i < boot_params->e820_entries; i++) {
|
||||
entry = &boot_params->e820_table[i];
|
||||
for (i = 0; i < boot_params_ptr->e820_entries; i++) {
|
||||
entry = &boot_params_ptr->e820_table[i];
|
||||
/* Skip non-RAM entries. */
|
||||
if (entry->type != E820_TYPE_RAM)
|
||||
continue;
|
||||
@ -852,7 +852,7 @@ void choose_random_location(unsigned long input,
|
||||
return;
|
||||
}
|
||||
|
||||
boot_params->hdr.loadflags |= KASLR_FLAG;
|
||||
boot_params_ptr->hdr.loadflags |= KASLR_FLAG;
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86_32))
|
||||
mem_limit = KERNEL_IMAGE_SIZE;
|
||||
|
@ -54,17 +54,17 @@ bool init_unaccepted_memory(void)
|
||||
enum efi_type et;
|
||||
int ret;
|
||||
|
||||
et = efi_get_type(boot_params);
|
||||
et = efi_get_type(boot_params_ptr);
|
||||
if (et == EFI_TYPE_NONE)
|
||||
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) {
|
||||
warn("EFI config table not found.");
|
||||
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);
|
||||
if (!table)
|
||||
return false;
|
||||
|
@ -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
|
||||
*/
|
||||
struct boot_params *boot_params;
|
||||
struct boot_params *boot_params_ptr;
|
||||
|
||||
struct port_io_ops pio_ops;
|
||||
|
||||
@ -132,8 +132,8 @@ void __putstr(const char *s)
|
||||
if (lines == 0 || cols == 0)
|
||||
return;
|
||||
|
||||
x = boot_params->screen_info.orig_x;
|
||||
y = boot_params->screen_info.orig_y;
|
||||
x = boot_params_ptr->screen_info.orig_x;
|
||||
y = boot_params_ptr->screen_info.orig_y;
|
||||
|
||||
while ((c = *s++) != '\0') {
|
||||
if (c == '\n') {
|
||||
@ -154,8 +154,8 @@ void __putstr(const char *s)
|
||||
}
|
||||
}
|
||||
|
||||
boot_params->screen_info.orig_x = x;
|
||||
boot_params->screen_info.orig_y = y;
|
||||
boot_params_ptr->screen_info.orig_x = x;
|
||||
boot_params_ptr->screen_info.orig_y = y;
|
||||
|
||||
pos = (x + cols * y) * 2; /* Update cursor position */
|
||||
outb(14, vidport);
|
||||
@ -382,14 +382,14 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
|
||||
size_t entry_offset;
|
||||
|
||||
/* 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. */
|
||||
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;
|
||||
vidport = 0x3b4;
|
||||
} else {
|
||||
@ -397,8 +397,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
|
||||
vidport = 0x3d4;
|
||||
}
|
||||
|
||||
lines = boot_params->screen_info.orig_video_lines;
|
||||
cols = boot_params->screen_info.orig_video_cols;
|
||||
lines = boot_params_ptr->screen_info.orig_video_lines;
|
||||
cols = boot_params_ptr->screen_info.orig_video_cols;
|
||||
|
||||
init_default_io_ops();
|
||||
|
||||
@ -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
|
||||
* 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");
|
||||
|
||||
|
@ -61,7 +61,6 @@ extern memptr free_mem_ptr;
|
||||
extern memptr free_mem_end_ptr;
|
||||
void *malloc(int size);
|
||||
void free(void *where);
|
||||
extern struct boot_params *boot_params;
|
||||
void __putstr(const char *s);
|
||||
void __puthex(unsigned long value);
|
||||
#define error_putstr(__x) __putstr(__x)
|
||||
|
@ -28,7 +28,6 @@ static char trampoline_save[TRAMPOLINE_32BIT_SIZE];
|
||||
*/
|
||||
unsigned long *trampoline_32bit __section(".data");
|
||||
|
||||
extern struct boot_params *boot_params;
|
||||
int cmdline_find_option_bool(const char *option);
|
||||
|
||||
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.
|
||||
*/
|
||||
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) &&
|
||||
strncmp(signature, EFI64_LOADER_SIGNATURE, 4)) {
|
||||
ebda_start = *(unsigned short *)0x40e << 4;
|
||||
@ -65,10 +64,10 @@ static unsigned long find_trampoline_placement(void)
|
||||
bios_start = round_down(bios_start, PAGE_SIZE);
|
||||
|
||||
/* 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;
|
||||
|
||||
entry = &boot_params->e820_table[i];
|
||||
entry = &boot_params_ptr->e820_table[i];
|
||||
|
||||
/* Skip all entries above bios_start. */
|
||||
if (bios_start <= entry->addr)
|
||||
@ -107,7 +106,7 @@ asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable)
|
||||
bool l5_required = false;
|
||||
|
||||
/* Initialize boot_params. Required for cmdline_find_option_bool(). */
|
||||
boot_params = bp;
|
||||
boot_params_ptr = bp;
|
||||
|
||||
/*
|
||||
* Check if LA57 is desired and supported.
|
||||
|
@ -615,7 +615,7 @@ void sev_prep_identity_maps(unsigned long top_level_pgt)
|
||||
* accessed after switchover.
|
||||
*/
|
||||
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;
|
||||
|
||||
kernel_add_identity_map(cc_info_pa, cc_info_pa + sizeof(*cc_info));
|
||||
|
@ -43,11 +43,13 @@ SECTIONS
|
||||
*(.rodata.*)
|
||||
_erodata = . ;
|
||||
}
|
||||
.data : {
|
||||
.data : ALIGN(0x1000) {
|
||||
_data = . ;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.bss.efistub)
|
||||
|
||||
/* Add 4 bytes of extra space for a CRC-32 checksum */
|
||||
. = ALIGN(. + 4, 0x200);
|
||||
_edata = . ;
|
||||
}
|
||||
. = ALIGN(L1_CACHE_BYTES);
|
||||
|
@ -36,66 +36,20 @@ SYSSEG = 0x1000 /* historical load address >> 4 */
|
||||
#define ROOT_RDONLY 1
|
||||
#endif
|
||||
|
||||
.set salign, 0x1000
|
||||
.set falign, 0x200
|
||||
|
||||
.code16
|
||||
.section ".bstext", "ax"
|
||||
|
||||
.global bootsect_start
|
||||
bootsect_start:
|
||||
#ifdef CONFIG_EFI_STUB
|
||||
# "MZ", MS-DOS header
|
||||
.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
|
||||
#
|
||||
# Offset to the PE header.
|
||||
#
|
||||
.long LINUX_PE_MAGIC
|
||||
.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:
|
||||
.long PE_MAGIC
|
||||
|
||||
@ -124,30 +78,26 @@ optional_header:
|
||||
.byte 0x02 # MajorLinkerVersion
|
||||
.byte 0x14 # MinorLinkerVersion
|
||||
|
||||
# Filled in by build.c
|
||||
.long 0 # SizeOfCode
|
||||
.long ZO__data # SizeOfCode
|
||||
|
||||
.long 0 # SizeOfInitializedData
|
||||
.long ZO__end - ZO__data # SizeOfInitializedData
|
||||
.long 0 # SizeOfUninitializedData
|
||||
|
||||
# Filled in by build.c
|
||||
.long 0x0000 # AddressOfEntryPoint
|
||||
.long setup_size + ZO_efi_pe_entry # AddressOfEntryPoint
|
||||
|
||||
.long 0x0200 # BaseOfCode
|
||||
.long setup_size # BaseOfCode
|
||||
#ifdef CONFIG_X86_32
|
||||
.long 0 # data
|
||||
#endif
|
||||
|
||||
extra_header_fields:
|
||||
# PE specification requires ImageBase to be 64k aligned
|
||||
.set image_base, (LOAD_PHYSICAL_ADDR + 0xffff) & ~0xffff
|
||||
#ifdef CONFIG_X86_32
|
||||
.long image_base # ImageBase
|
||||
.long 0 # ImageBase
|
||||
#else
|
||||
.quad image_base # ImageBase
|
||||
.quad 0 # ImageBase
|
||||
#endif
|
||||
.long 0x20 # SectionAlignment
|
||||
.long 0x20 # FileAlignment
|
||||
.long salign # SectionAlignment
|
||||
.long falign # FileAlignment
|
||||
.word 0 # MajorOperatingSystemVersion
|
||||
.word 0 # MinorOperatingSystemVersion
|
||||
.word LINUX_EFISTUB_MAJOR_VERSION # MajorImageVersion
|
||||
@ -156,12 +106,10 @@ extra_header_fields:
|
||||
.word 0 # MinorSubsystemVersion
|
||||
.long 0 # Win32VersionValue
|
||||
|
||||
#
|
||||
# The size of the bzImage is written in tools/build.c
|
||||
#
|
||||
.long 0 # SizeOfImage
|
||||
.long setup_size + ZO__end + pecompat_vsize
|
||||
# SizeOfImage
|
||||
|
||||
.long 0x200 # SizeOfHeaders
|
||||
.long salign # SizeOfHeaders
|
||||
.long 0 # CheckSum
|
||||
.word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application)
|
||||
#ifdef CONFIG_EFI_DXE_MEM_ATTRIBUTES
|
||||
@ -192,87 +140,78 @@ extra_header_fields:
|
||||
|
||||
# Section table
|
||||
section_table:
|
||||
#
|
||||
# The offset & size fields are filled in by build.c.
|
||||
#
|
||||
.ascii ".setup"
|
||||
.byte 0
|
||||
.byte 0
|
||||
.long 0
|
||||
.long 0x0 # startup_{32,64}
|
||||
.long 0 # Size of initialized data
|
||||
# on disk
|
||||
.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 setup_size - salign # VirtualSize
|
||||
.long salign # VirtualAddress
|
||||
.long pecompat_fstart - salign # SizeOfRawData
|
||||
.long salign # PointerToRawData
|
||||
|
||||
#
|
||||
# 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 0, 0, 0
|
||||
.long IMAGE_SCN_CNT_INITIALIZED_DATA | \
|
||||
IMAGE_SCN_MEM_READ | \
|
||||
IMAGE_SCN_MEM_DISCARDABLE | \
|
||||
IMAGE_SCN_ALIGN_1BYTES # Characteristics
|
||||
IMAGE_SCN_MEM_DISCARDABLE # Characteristics
|
||||
|
||||
#ifdef CONFIG_EFI_MIXED
|
||||
#
|
||||
# The offset & size fields are filled in by build.c.
|
||||
#
|
||||
.asciz ".compat"
|
||||
.long 0
|
||||
.long 0x0
|
||||
.long 0 # Size of initialized data
|
||||
# on disk
|
||||
.long 0x0
|
||||
.long 0 # PointerToRelocations
|
||||
.long 0 # PointerToLineNumbers
|
||||
.word 0 # NumberOfRelocations
|
||||
.word 0 # NumberOfLineNumbers
|
||||
|
||||
.long 8 # VirtualSize
|
||||
.long setup_size + ZO__end # VirtualAddress
|
||||
.long pecompat_fsize # SizeOfRawData
|
||||
.long pecompat_fstart # PointerToRawData
|
||||
|
||||
.long 0, 0, 0
|
||||
.long IMAGE_SCN_CNT_INITIALIZED_DATA | \
|
||||
IMAGE_SCN_MEM_READ | \
|
||||
IMAGE_SCN_MEM_DISCARDABLE | \
|
||||
IMAGE_SCN_ALIGN_1BYTES # Characteristics
|
||||
#endif
|
||||
IMAGE_SCN_MEM_DISCARDABLE # Characteristics
|
||||
|
||||
#
|
||||
# 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"
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
.long 0
|
||||
.long 0x0 # startup_{32,64}
|
||||
.long 0 # Size of initialized data
|
||||
.long ZO__data
|
||||
.long setup_size
|
||||
.long ZO__data # Size of initialized data
|
||||
# on disk
|
||||
.long 0x0 # startup_{32,64}
|
||||
.long setup_size
|
||||
.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
|
||||
IMAGE_SCN_MEM_EXECUTE # 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
|
||||
#endif /* CONFIG_EFI_STUB */
|
||||
@ -286,12 +225,12 @@ sentinel: .byte 0xff, 0xff /* Used to detect broken loaders */
|
||||
|
||||
.globl hdr
|
||||
hdr:
|
||||
setup_sects: .byte 0 /* Filled in by build.c */
|
||||
.byte setup_sects - 1
|
||||
root_flags: .word ROOT_RDONLY
|
||||
syssize: .long 0 /* Filled in by build.c */
|
||||
syssize: .long ZO__edata / 16
|
||||
ram_size: .word 0 /* Obsolete */
|
||||
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
|
||||
|
||||
# offset 512, entry point
|
||||
@ -579,9 +518,25 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
|
||||
# define INIT_SIZE VO_INIT_SIZE
|
||||
#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
|
||||
handover_offset: .long 0 # Filled in by build.c
|
||||
kernel_info_offset: .long 0 # Filled in by build.c
|
||||
handover_offset: __handover_offset
|
||||
kernel_info_offset: .long ZO_kernel_info
|
||||
|
||||
# End of setup header #####################################################
|
||||
|
||||
|
@ -10,10 +10,11 @@ ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
.bstext : { *(.bstext) }
|
||||
.bsdata : { *(.bsdata) }
|
||||
.bstext : {
|
||||
*(.bstext)
|
||||
. = 495;
|
||||
} =0xffffffff
|
||||
|
||||
. = 495;
|
||||
.header : { *(.header) }
|
||||
.entrytext : { *(.entrytext) }
|
||||
.inittext : { *(.inittext) }
|
||||
@ -35,11 +36,16 @@ SECTIONS
|
||||
. = ALIGN(16);
|
||||
.data : { *(.data*) }
|
||||
|
||||
.pecompat : { *(.pecompat) }
|
||||
PROVIDE(pecompat_fsize = setup_size - pecompat_fstart);
|
||||
|
||||
.signature : {
|
||||
setup_sig = .;
|
||||
LONG(0x5a5aaa55)
|
||||
}
|
||||
|
||||
setup_size = ALIGN(ABSOLUTE(.), 4096);
|
||||
setup_sects = ABSOLUTE(setup_size / 512);
|
||||
}
|
||||
|
||||
. = ALIGN(16);
|
||||
.bss :
|
||||
|
@ -40,10 +40,6 @@ typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
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 */
|
||||
#define SETUP_SECT_MIN 5
|
||||
#define SETUP_SECT_MAX 64
|
||||
@ -51,22 +47,7 @@ typedef unsigned int u32;
|
||||
/* This must be large enough to hold the entire setup */
|
||||
u8 buf[SETUP_SECT_MAX*512];
|
||||
|
||||
#define PECOFF_RELOC_RESERVE 0x20
|
||||
|
||||
#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;
|
||||
static unsigned long _edata;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
@ -152,180 +133,6 @@ static void usage(void)
|
||||
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
|
||||
* 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)
|
||||
p = (char *)buf;
|
||||
|
||||
while (p && *p) {
|
||||
PARSE_ZOFS(p, efi32_stub_entry);
|
||||
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);
|
||||
PARSE_ZOFS(p, _edata);
|
||||
|
||||
p = strchr(p, '\n');
|
||||
while (p && (*p == '\r' || *p == '\n'))
|
||||
@ -371,17 +171,14 @@ static void parse_zoffset(char *fname)
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
unsigned int i, sz, setup_sectors, init_sz;
|
||||
unsigned int i, sz, setup_sectors;
|
||||
int c;
|
||||
u32 sys_size;
|
||||
struct stat sb;
|
||||
FILE *file, *dest;
|
||||
int fd;
|
||||
void *kernel;
|
||||
u32 crc = 0xffffffffUL;
|
||||
|
||||
efi_stub_defaults();
|
||||
|
||||
if (argc != 5)
|
||||
usage();
|
||||
parse_zoffset(argv[3]);
|
||||
@ -403,72 +200,27 @@ int main(int argc, char ** argv)
|
||||
die("Boot block hasn't got boot flag (0xAA55)");
|
||||
fclose(file);
|
||||
|
||||
c += reserve_pecoff_compat_section(c);
|
||||
c += reserve_pecoff_reloc_section(c);
|
||||
|
||||
/* Pad unused space with zeros */
|
||||
setup_sectors = (c + 511) / 512;
|
||||
setup_sectors = (c + 4095) / 4096;
|
||||
setup_sectors *= 8;
|
||||
if (setup_sectors < SETUP_SECT_MIN)
|
||||
setup_sectors = SETUP_SECT_MIN;
|
||||
i = setup_sectors*512;
|
||||
memset(buf+c, 0, i-c);
|
||||
|
||||
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 */
|
||||
fd = open(argv[2], O_RDONLY);
|
||||
if (fd < 0)
|
||||
die("Unable to open `%s': %m", argv[2]);
|
||||
if (fstat(fd, &sb))
|
||||
die("Unable to stat `%s': %m", argv[2]);
|
||||
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);
|
||||
if (kernel == MAP_FAILED)
|
||||
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);
|
||||
if (fwrite(buf, 1, i, dest) != i)
|
||||
@ -479,13 +231,6 @@ int main(int argc, char ** argv)
|
||||
if (fwrite(kernel, 1, sz, dest) != sz)
|
||||
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 */
|
||||
put_unaligned_le32(crc, buf);
|
||||
if (fwrite(buf, 1, 4, dest) != 4)
|
||||
|
@ -85,6 +85,8 @@ extern const unsigned long kernel_total_size;
|
||||
|
||||
unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
|
||||
void (*error)(char *x));
|
||||
|
||||
extern struct boot_params *boot_params_ptr;
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_BOOT_H */
|
||||
|
@ -2,6 +2,8 @@
|
||||
#ifndef _ASM_X86_INIT_H
|
||||
#define _ASM_X86_INIT_H
|
||||
|
||||
#define __head __section(".head.text")
|
||||
|
||||
struct x86_mapping_info {
|
||||
void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
|
||||
void *context; /* context for alloc_pgt_page */
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <asm/trapnr.h>
|
||||
#include <asm/sev.h>
|
||||
#include <asm/tdx.h>
|
||||
#include <asm/init.h>
|
||||
|
||||
/*
|
||||
* Manage page tables very early on.
|
||||
@ -69,7 +70,7 @@ EXPORT_SYMBOL(vmemmap_base);
|
||||
/*
|
||||
* 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_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff),
|
||||
[GDT_ENTRY_KERNEL_DS] = GDT_ENTRY_INIT(0xc093, 0, 0xfffff),
|
||||
@ -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
|
||||
* while the kernel still uses a direct mapping.
|
||||
*/
|
||||
static struct desc_ptr startup_gdt_descr = {
|
||||
.size = sizeof(startup_gdt),
|
||||
static struct desc_ptr startup_gdt_descr __initdata = {
|
||||
.size = sizeof(startup_gdt)-1,
|
||||
.address = 0,
|
||||
};
|
||||
|
||||
#define __head __section(".head.text")
|
||||
|
||||
static void __head *fixup_pointer(void *ptr, unsigned long physaddr)
|
||||
{
|
||||
return ptr - (void *)_text + (void *)physaddr;
|
||||
@ -211,7 +210,7 @@ unsigned long __head __startup_64(unsigned long physaddr,
|
||||
|
||||
/* 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);
|
||||
if (la57)
|
||||
*p = (unsigned long)level4_kernel_pgt;
|
||||
@ -220,11 +219,11 @@ unsigned long __head __startup_64(unsigned long physaddr,
|
||||
*p += _PAGE_TABLE_NOENC - __START_KERNEL_map + load_delta;
|
||||
|
||||
if (la57) {
|
||||
p4d = fixup_pointer(&level4_kernel_pgt, physaddr);
|
||||
p4d = fixup_pointer(level4_kernel_pgt, physaddr);
|
||||
p4d[511] += load_delta;
|
||||
}
|
||||
|
||||
pud = fixup_pointer(&level3_kernel_pgt, physaddr);
|
||||
pud = fixup_pointer(level3_kernel_pgt, physaddr);
|
||||
pud[510] += load_delta;
|
||||
pud[511] += load_delta;
|
||||
|
||||
@ -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 */
|
||||
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);
|
||||
gate_desc *idt = fixup_pointer(bringup_idt_table, physbase);
|
||||
|
@ -108,13 +108,6 @@ lib-y := $(patsubst %.o,%.stub.o,$(lib-y))
|
||||
# https://bugs.llvm.org/show_bug.cgi?id=46480
|
||||
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_64) := R_X86_64_64
|
||||
|
||||
|
@ -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_system_table_t *sys_table_arg)
|
||||
{
|
||||
struct boot_params *boot_params;
|
||||
struct setup_header *hdr;
|
||||
void *image_base;
|
||||
static struct boot_params boot_params __page_aligned_bss;
|
||||
struct setup_header *hdr = &boot_params.hdr;
|
||||
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
|
||||
int options_size = 0;
|
||||
efi_status_t status;
|
||||
@ -469,30 +468,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
efi_exit(handle, status);
|
||||
}
|
||||
|
||||
image_base = efi_table_attr(image, image_base);
|
||||
|
||||
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.
|
||||
*/
|
||||
/* Assign the setup_header fields that the kernel actually cares about */
|
||||
hdr->root_flags = 1;
|
||||
hdr->vid_mode = 0xffff;
|
||||
hdr->boot_flag = 0xAA55;
|
||||
|
||||
hdr->type_of_loader = 0x21;
|
||||
|
||||
@ -501,25 +479,13 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
|
||||
if (!cmdline_ptr)
|
||||
goto fail;
|
||||
|
||||
efi_set_u64_split((unsigned long)cmdline_ptr,
|
||||
&hdr->cmd_line_ptr, &boot_params->ext_cmd_line_ptr);
|
||||
efi_set_u64_split((unsigned long)cmdline_ptr, &hdr->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 */
|
||||
|
||||
fail:
|
||||
efi_free(sizeof(struct boot_params), (unsigned long)boot_params);
|
||||
|
||||
efi_exit(handle, status);
|
||||
}
|
||||
|
||||
@ -849,7 +815,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
|
||||
unsigned long kernel_entry;
|
||||
efi_status_t status;
|
||||
|
||||
boot_params_pointer = boot_params;
|
||||
boot_params_ptr = boot_params;
|
||||
|
||||
efi_system_table = sys_table_arg;
|
||||
/* Check if we were booted by the EFI firmware */
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include <linux/efi.h>
|
||||
|
||||
extern struct boot_params *boot_params_pointer asm("boot_params");
|
||||
|
||||
extern void trampoline_32bit_src(void *, bool);
|
||||
extern const u16 trampoline_ljmp_imm_offset;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user