From 1488219c4fa7d1780445704d7185f4a514bfc2fa Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Fri, 7 Mar 2025 23:30:19 +0800 Subject: [PATCH] Revise the link script in EFI stub --- ostd/libs/linux-bzimage/builder/src/lib.rs | 14 ++-- ostd/libs/linux-bzimage/setup/build.rs | 30 +++++--- .../setup/src/x86/amd64_efi/linker.ld | 51 ------------- .../setup/src/x86/legacy_i386/linker.ld | 36 ---------- .../setup/src/x86/legacy_i386/setup.S | 5 +- .../linux-bzimage/setup/src/x86/linker.ld | 71 +++++++++++++++++++ 6 files changed, 105 insertions(+), 102 deletions(-) delete mode 100644 ostd/libs/linux-bzimage/setup/src/x86/amd64_efi/linker.ld delete mode 100644 ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/linker.ld create mode 100644 ostd/libs/linux-bzimage/setup/src/x86/linker.ld diff --git a/ostd/libs/linux-bzimage/builder/src/lib.rs b/ostd/libs/linux-bzimage/builder/src/lib.rs index 90330729c..a010291ae 100644 --- a/ostd/libs/linux-bzimage/builder/src/lib.rs +++ b/ostd/libs/linux-bzimage/builder/src/lib.rs @@ -124,11 +124,17 @@ fn to_flat_binary(elf_file: &[u8]) -> Vec { 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); } } diff --git a/ostd/libs/linux-bzimage/setup/build.rs b/ostd/libs/linux-bzimage/setup/build.rs index 66d4b5311..22628f7dc 100644 --- a/ostd/libs/linux-bzimage/setup/build.rs +++ b/ostd/libs/linux-bzimage/setup/build.rs @@ -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()); } diff --git a/ostd/libs/linux-bzimage/setup/src/x86/amd64_efi/linker.ld b/ostd/libs/linux-bzimage/setup/src/x86/amd64_efi/linker.ld deleted file mode 100644 index 2a297b6fa..000000000 --- a/ostd/libs/linux-bzimage/setup/src/x86/amd64_efi/linker.ld +++ /dev/null @@ -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) } -} diff --git a/ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/linker.ld b/ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/linker.ld deleted file mode 100644 index 158223408..000000000 --- a/ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/linker.ld +++ /dev/null @@ -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.*) - } -} diff --git a/ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/setup.S b/ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/setup.S index c0bd10c52..628c97bed 100644 --- a/ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/setup.S +++ b/ostd/libs/linux-bzimage/setup/src/x86/legacy_i386/setup.S @@ -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: diff --git a/ostd/libs/linux-bzimage/setup/src/x86/linker.ld b/ostd/libs/linux-bzimage/setup/src/x86/linker.ld new file mode 100644 index 000000000..47d5223b6 --- /dev/null +++ b/ostd/libs/linux-bzimage/setup/src/x86/linker.ld @@ -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/ : { *(.*) } +}