Revise the link script in EFI stub

This commit is contained in:
Ruihan Li 2025-03-07 23:30:19 +08:00 committed by Tate, Hongliang Tian
parent 81bfa6ed6e
commit 1488219c4f
6 changed files with 105 additions and 102 deletions

View File

@ -124,11 +124,17 @@ fn to_flat_binary(elf_file: &[u8]) -> Vec<u8> {
let dst_file_offset = usize::from(SetupFileOffset::from(SetupVA::from(
program.virtual_addr() as usize,
)));
let dst_file_length = program.file_size() as usize;
if bin.len() < dst_file_offset + dst_file_length {
bin.resize(dst_file_offset + dst_file_length, 0);
// Note that `mem_size` can be greater than `file_size`. The remaining part must be
// filled with zeros.
let mem_length = program.mem_size() as usize;
if bin.len() < dst_file_offset + mem_length {
bin.resize(dst_file_offset + mem_length, 0);
}
let dest_slice = bin[dst_file_offset..dst_file_offset + dst_file_length].as_mut();
// Copy the bytes in the `file_size` part.
let file_length = program.file_size() as usize;
let dest_slice = bin[dst_file_offset..dst_file_offset + file_length].as_mut();
dest_slice.copy_from_slice(header_data);
}
}

View File

@ -1,17 +1,29 @@
// SPDX-License-Identifier: MPL-2.0
use std::path::PathBuf;
use std::{path::PathBuf, process::Command};
fn main() {
let source_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
let target_arch = std::env::var("TARGET").unwrap();
let linker_script = if target_arch == "x86_64-unknown-none" {
source_dir.join("src/x86/amd64_efi/linker.ld")
} else if target_arch == "x86_64-i386_pm-none" {
source_dir.join("src/x86/legacy_i386/linker.ld")
} else {
panic!("Unsupported target_arch: {}", target_arch);
let lds = source_dir.join("src/x86/linker.ld");
let def = match target_arch.as_str() {
"x86_64-unknown-none" => "-DCFG_TARGET_ARCH_X86_64=1",
"x86_64-i386_pm-none" => "-DCFG_TARGET_ARCH_X86_64=0",
other => panic!("unsupported target: {}", other),
};
println!("cargo:rerun-if-changed={}", linker_script.display());
println!("cargo:rustc-link-arg=-T{}", linker_script.display());
let out_lds = out_dir.join("linker.ld");
let status = Command::new("cpp")
.arg("-o")
.arg(&out_lds)
.arg(def)
.arg(&lds)
.status()
.expect("failed to run the preprocessor");
assert!(status.success(), "the preprocessor exits with failure");
println!("cargo:rerun-if-changed={}", lds.display());
println!("cargo:rustc-link-arg=-T{}", out_lds.display());
}

View File

@ -1,51 +0,0 @@
ENTRY(entry_efi_pe64)
OUTPUT_ARCH(i386:x86-64)
OUTPUT_FORMAT(elf64-x86-64)
SETUP32_LMA = 0x100000;
BOOTSECT_SIZE = 0x1000;
BOOTSECT_START = SETUP32_LMA - BOOTSECT_SIZE;
LEGACY_STACK_SIZE = 0x1000;
SECTIONS
{
. = BOOTSECT_START;
.header : { KEEP(*(.header)) }
. = SETUP32_LMA;
.setup : { KEEP(*(.setup)) }
.text : { *(.text .text.*) }
.data : { *(.data .data.*) }
.bss : {
PROVIDE(__bss_start = .);
*(.bss .bss.*) *(COMMON)
PROVIDE(__bss_end = .);
}
.got.plt : {
*(.got.plt .got.plt.*)
}
.dynamic : {
*(.dynamic .dynamic.*)
}
.rodata : { *(.rodata .rodata.*) }
.eh_frame : {
*(.eh_frame .eh_frame.*)
}
.eh_frame_hdr : {
*(.eh_frame_hdr .eh_frame_hdr.*)
}
.rela : {
PROVIDE(__rela_start = .);
*(.rela .rela.*)
PROVIDE(__rela_end = .);
}
.comment : { *(.comment) }
}

View File

@ -1,36 +0,0 @@
ENTRY(start_of_setup32)
OUTPUT_ARCH(i386:x86)
OUTPUT_FORMAT(elf32-i386)
SETUP32_LMA = 0x100000;
BOOTSECT_SIZE = 0x1000;
BOOTSECT_START = SETUP32_LMA - BOOTSECT_SIZE;
LEGACY_STACK_SIZE = 0x1000;
SECTIONS
{
. = BOOTSECT_START;
.header : { KEEP(*(.header)) }
. = SETUP32_LMA;
.setup : { KEEP(*(.setup)) }
.stack : { *(.stack) }
.text : { *(.text .text.*) }
.rodata : { *(.rodata .rodata.*) }
.data : { *(.data .data.*) }
.bss : {
PROVIDE(__bss_start = .);
*(.bss .bss.*) *(COMMON)
PROVIDE(__bss_end = .);
}
.eh_frame : {
*(.eh_frame .eh_frame.*)
}
.eh_frame_hdr : {
*(.eh_frame_hdr .eh_frame_hdr.*)
}
}

View File

@ -30,8 +30,9 @@ halt:
hlt
jmp halt
// A small stack for the 32-bit code.
.section ".stack", "aw"
// A small stack for the setup code.
.bss
.align 8
__stack_bottom:
.space 0x1000
__stack_top:

View File

@ -0,0 +1,71 @@
#if CFG_TARGET_ARCH_X86_64
ENTRY(entry_efi_pe64) // This need to be the PE/COFF entry point.
OUTPUT_ARCH(i386:x86-64)
OUTPUT_FORMAT(elf64-x86-64)
#else
ENTRY(entry_legacy32) // This does not matter. No one will use it.
OUTPUT_ARCH(i386:x86)
OUTPUT_FORMAT(elf32-i386)
#endif
SETUP32_LMA = 0x100000;
BOOTSECT_SIZE = 0x1000;
BOOTSECT_LMA = SETUP32_LMA - BOOTSECT_SIZE;
PHDRS
{
// Note that this segment cannot actually be loaded because:
// (1) In the legacy case, the memory area below SETUP32_LMA is typically
// reserved by the BIOS.
// (2) In the EFI case, the PE/COFF format prohibits us from having a
// segment with a zero file offset.
// We have this segment only for communication with the builder.
header PT_LOAD FLAGS(4); // R__
// There are loadable segments. They must be aligned to the page boundaries
// because the PE/COFF format requires all segments to be page-aligned.
text PT_LOAD FLAGS(5); // R_E
rodata PT_LOAD FLAGS(4); // R__
data PT_LOAD FLAGS(6); // RW_
}
SECTIONS
{
// Header segment.
. = BOOTSECT_LMA;
.header : { KEEP(*(.header)) } : header
// Text segment.
. = SETUP32_LMA;
.setup : { KEEP(*(.setup)) } : text
.text : { *(.text .text.*) } : text
// Rodata segment.
. = ALIGN(4096);
.rodata : { *(.rodata .rodata.*) } : rodata
.rela : {
PROVIDE(__rela_start = .);
*(.rela .rela.*)
PROVIDE(__rela_end = .);
} : rodata
// Data segment.
. = ALIGN(4096);
.got : { *(.got .got.*) } : data
.data : { *(.data .data.*) } : data
.bss : {
PROVIDE(__bss_start = .);
*(.bss .bss.*) *(COMMON)
PROVIDE(__bss_end = .);
} : data
. = ALIGN(4096);
// Section names. ELF files must have them.
.shstrtab : { *(.shstrtab) } : NONE
// Symbols and their names. They are useful when debugging.
.symtab : { *(.symtab) } : NONE
.strtab : { *(.strtab) } : NONE
/DISCARD/ : { *(.*) }
}