mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-25 02:13:24 +00:00
Revise headers and entry points in EFI stub
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
fbb8ea6ad1
commit
81bfa6ed6e
@ -27,15 +27,14 @@ use linux_boot_params::BootParams;
|
|||||||
mod console;
|
mod console;
|
||||||
mod loader;
|
mod loader;
|
||||||
|
|
||||||
// Unfortunately, the entrypoint is not defined here in the main.rs file.
|
// The entry points are defined in `x86/*/setup.S`.
|
||||||
// See the exported functions in the x86 module for details.
|
|
||||||
mod x86;
|
mod x86;
|
||||||
|
|
||||||
fn get_payload(boot_params: &BootParams) -> &'static [u8] {
|
fn get_payload(boot_params: &BootParams) -> &'static [u8] {
|
||||||
let hdr = &boot_params.hdr;
|
let hdr = &boot_params.hdr;
|
||||||
// The payload_offset field is not recorded in the relocation table, so we need to
|
// The payload_offset field is not recorded in the relocation table, so we need to
|
||||||
// calculate the loaded offset manually.
|
// calculate the loaded offset manually.
|
||||||
let loaded_offset = x86::get_image_loaded_offset();
|
let loaded_offset = x86::image_load_offset();
|
||||||
let payload_offset = (loaded_offset + hdr.payload_offset as isize) as usize;
|
let payload_offset = (loaded_offset + hdr.payload_offset as isize) as usize;
|
||||||
let payload_length = hdr.payload_length as usize;
|
let payload_length = hdr.payload_length as usize;
|
||||||
// SAFETY: the payload_offset and payload_length is valid if we assume that the
|
// SAFETY: the payload_offset and payload_length is valid if we assume that the
|
||||||
|
@ -13,24 +13,8 @@ use super::{decoder::decode_payload, relocation::apply_rela_relocations};
|
|||||||
|
|
||||||
const PAGE_SIZE: u64 = 4096;
|
const PAGE_SIZE: u64 = 4096;
|
||||||
|
|
||||||
// Suppress warnings since using todo!.
|
#[export_name = "main_efi_handover64"]
|
||||||
#[expect(unreachable_code)]
|
extern "sysv64" fn main_efi_handover64(
|
||||||
#[expect(unused_variables)]
|
|
||||||
#[expect(clippy::diverging_sub_expression)]
|
|
||||||
#[export_name = "efi_stub_entry"]
|
|
||||||
extern "sysv64" fn efi_stub_entry(handle: Handle, system_table: *const SystemTable) -> ! {
|
|
||||||
// SAFETY: handle and system_table are valid pointers. It is only called once.
|
|
||||||
unsafe { system_init(handle, system_table) };
|
|
||||||
|
|
||||||
uefi::helpers::init().unwrap();
|
|
||||||
|
|
||||||
let boot_params = todo!("Use EFI boot services to fill boot params");
|
|
||||||
|
|
||||||
efi_phase_boot(boot_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[export_name = "efi_handover_entry"]
|
|
||||||
extern "sysv64" fn efi_handover_entry(
|
|
||||||
handle: Handle,
|
handle: Handle,
|
||||||
system_table: *const SystemTable,
|
system_table: *const SystemTable,
|
||||||
boot_params_ptr: *mut BootParams,
|
boot_params_ptr: *mut BootParams,
|
||||||
@ -74,7 +58,7 @@ fn efi_phase_boot(boot_params: &mut BootParams) -> ! {
|
|||||||
uefi::println!("[EFI stub] Relocations applied.");
|
uefi::println!("[EFI stub] Relocations applied.");
|
||||||
uefi::println!(
|
uefi::println!(
|
||||||
"[EFI stub] Stub loaded at {:#x?}",
|
"[EFI stub] Stub loaded at {:#x?}",
|
||||||
crate::x86::get_image_loaded_offset()
|
crate::x86::image_load_offset()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fill the boot params with the RSDP address if it is not provided.
|
// Fill the boot params with the RSDP address if it is not provided.
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: MPL-2.0 */
|
|
||||||
|
|
||||||
// The compatibility file for the Linux x86 Boot Protocol.
|
|
||||||
// See https://www.kernel.org/doc/html/v5.6/x86/boot.html for
|
|
||||||
// more information on the Linux x86 Boot Protocol.
|
|
||||||
|
|
||||||
// Some of the fields filled with a 0xab* values should be filled
|
|
||||||
// by the torjan builder.
|
|
||||||
// Asterinas will use only a few of these fields, and some of them
|
|
||||||
// are filled by the loader and will be read by Asterinas.
|
|
||||||
|
|
||||||
.section ".header", "a"
|
|
||||||
CODE32_START = 0x100000
|
|
||||||
SETUP_SECTS = 7 # so that the legacy setup could occupy a page
|
|
||||||
SETUP_SECTS_SIZE = 0x200 * (SETUP_SECTS + 1)
|
|
||||||
.code16
|
|
||||||
.org 0x01f1
|
|
||||||
hdr_start:
|
|
||||||
setup_sects: .byte SETUP_SECTS
|
|
||||||
root_flags: .word 1
|
|
||||||
syssize: .long 0
|
|
||||||
ram_size: .word 0
|
|
||||||
vid_mode: .word 0xfffd
|
|
||||||
root_dev: .word 0
|
|
||||||
boot_flag: .word 0xAA55
|
|
||||||
jump: .byte 0xeb
|
|
||||||
jump_addr: .byte hdr_end-jump_addr
|
|
||||||
magic: .ascii "HdrS"
|
|
||||||
.word 0x020f
|
|
||||||
realmode_swtch: .word 0, 0
|
|
||||||
start_sys_seg: .word 0
|
|
||||||
.word 0
|
|
||||||
type_of_loader: .byte 0
|
|
||||||
loadflags: .byte (1 << 0)
|
|
||||||
setup_move_size: .word 0
|
|
||||||
code32_start: .long CODE32_START
|
|
||||||
ramdisk_image: .long 0
|
|
||||||
ramdisk_size: .long 0
|
|
||||||
bootsect_kludge: .long 0
|
|
||||||
heap_end_ptr: .word 65535
|
|
||||||
ext_loader_ver: .byte 0
|
|
||||||
ext_loader_type: .byte 0
|
|
||||||
cmd_line_ptr: .long 0
|
|
||||||
initrd_addr_max: .long 0x7fffffff
|
|
||||||
kernel_alignment: .long 0x1000000
|
|
||||||
relocatable_kernel: .byte 0
|
|
||||||
min_alignment: .byte 0x10
|
|
||||||
xloadflags: .word 0b01111 # all handover protocols except kexec
|
|
||||||
cmdline_size: .long 4096-1
|
|
||||||
hardware_subarch: .long 0
|
|
||||||
hardware_subarch_data: .quad 0
|
|
||||||
payload_offset: .long 0xabababab # at 0x248/4, to be filled by the builder
|
|
||||||
payload_length: .long 0xabababab # at 0x24c/4, to be filled by the builder
|
|
||||||
setup_data: .quad 0
|
|
||||||
pref_address: .quad CODE32_START - SETUP_SECTS_SIZE
|
|
||||||
init_size: .long 0xabababab # at 0x260/4, to be filled by the builder
|
|
||||||
# The handover_offset should be efi_handover_setup_entry - CODE32_START - 0x200
|
|
||||||
# But we use ABI workaround to avoid the relocation of efi_handover_setup_entry
|
|
||||||
handover_offset: .long 0x10
|
|
||||||
kernel_info_offset: .long 0
|
|
||||||
hdr_end:
|
|
@ -1,4 +1,4 @@
|
|||||||
ENTRY(efi_handover_setup_entry)
|
ENTRY(entry_efi_pe64)
|
||||||
OUTPUT_ARCH(i386:x86-64)
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
OUTPUT_FORMAT(elf64-x86-64)
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
|
||||||
|
@ -6,8 +6,6 @@ mod relocation;
|
|||||||
|
|
||||||
use core::arch::{asm, global_asm};
|
use core::arch::{asm, global_asm};
|
||||||
|
|
||||||
global_asm!(include_str!("header.S"));
|
|
||||||
|
|
||||||
global_asm!(include_str!("setup.S"));
|
global_asm!(include_str!("setup.S"));
|
||||||
|
|
||||||
pub const ASTER_ENTRY_POINT: u32 = 0x8001200;
|
pub const ASTER_ENTRY_POINT: u32 = 0x8001200;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use crate::x86::get_image_loaded_offset;
|
use crate::x86::image_load_offset;
|
||||||
|
|
||||||
/// Apply the relocations in the `.rela.*` sections.
|
/// Apply the relocations in the `.rela.*` sections.
|
||||||
///
|
///
|
||||||
@ -18,7 +18,7 @@ use crate::x86::get_image_loaded_offset;
|
|||||||
/// Failure to do relocations will cause `dyn Trait` objects to break.
|
/// Failure to do relocations will cause `dyn Trait` objects to break.
|
||||||
pub unsafe fn apply_rela_relocations() {
|
pub unsafe fn apply_rela_relocations() {
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
let image_loaded_offset = get_image_loaded_offset();
|
let image_loaded_offset = image_load_offset();
|
||||||
|
|
||||||
let mut start: usize;
|
let mut start: usize;
|
||||||
let end: usize;
|
let end: usize;
|
||||||
|
@ -1,43 +1,74 @@
|
|||||||
/* SPDX-License-Identifier: MPL-2.0 */
|
/* SPDX-License-Identifier: MPL-2.0 */
|
||||||
|
|
||||||
|
// The load address of the setup section is CODE32_START (0x100000).
|
||||||
|
// See the linker script.
|
||||||
.section ".setup", "ax"
|
.section ".setup", "ax"
|
||||||
|
|
||||||
|
.code32
|
||||||
|
.global entry_legacy32
|
||||||
|
entry_legacy32:
|
||||||
|
// This is the 32-bit Linux legacy entry point.
|
||||||
|
|
||||||
|
// Not supported. However, there doesn't seem to be a way to disable this
|
||||||
|
// entry point in the header, so provide a dummy implementation here.
|
||||||
|
hlt
|
||||||
|
jmp entry_legacy32
|
||||||
|
|
||||||
|
.global entry_efi_handover32
|
||||||
|
entry_efi_handover32:
|
||||||
|
// This is the 32-bit EFI handover entry point.
|
||||||
|
|
||||||
|
// Not supported. This entry point is not enabled in the header, so it
|
||||||
|
// should not be reachable. We declare the entry point anyway, because
|
||||||
|
// its offset is needed in the header. We provide a dummy implementation
|
||||||
|
// just in case.
|
||||||
|
jmp entry_legacy32
|
||||||
|
|
||||||
|
// The 64-bit Linux legacy entry point must be 0x200 bytes after the 32-bit
|
||||||
|
// one. This is required by the x86 Linux boot protocol.
|
||||||
|
.skip 0x200 - (. - entry_legacy32)
|
||||||
|
|
||||||
.code64
|
.code64
|
||||||
// start_of_setup32 should be loaded at CODE32_START, which is our base.
|
entry_legacy64:
|
||||||
.global start_of_setup32
|
// This is the 64-bit Linux legacy entry point.
|
||||||
start_of_setup32:
|
|
||||||
|
|
||||||
// `efi_handover_setup_entry64` should be at efi_handover_setup_entry32 + 0x200, but
|
// Not supported. We need to enable this entry point in the header,
|
||||||
// we could provide the 32 bit dummy entry point as the 64 bit entry point - 0x200
|
// otherwise the boot loader will think the kernel does not support
|
||||||
// since we do not provide 32-bit entry point in the x86_64 specific implementation.
|
// 64-bit.
|
||||||
.org 0x210
|
jmp halt
|
||||||
.global efi_handover_setup_entry
|
|
||||||
efi_handover_setup_entry:
|
|
||||||
// The 3 parameters of is stored in rdi, rsi and rdx (sysv64).
|
|
||||||
// Do not use them.
|
|
||||||
|
|
||||||
// Setup the stack.
|
// The 64-bit EFI handover entry point must be 0x200 bytes after the 32-bit
|
||||||
lea rsp, [rip + setup_stack_top]
|
// one. This is required by the x86 Linux boot protocol.
|
||||||
lea rax, [rip + halt]
|
.skip 0x200 - (. - entry_efi_handover32)
|
||||||
push rax # the return address
|
|
||||||
mov rbp, rsp
|
|
||||||
add rbp, -4
|
|
||||||
push rbp
|
|
||||||
mov rbp, rsp
|
|
||||||
|
|
||||||
.extern efi_handover_entry
|
entry_efi_handover64:
|
||||||
lea rax, [rip + efi_handover_entry]
|
// This is the 64-bit EFI handover entry point.
|
||||||
call rax
|
//
|
||||||
|
// Arguments:
|
||||||
|
// RDI: void *handle
|
||||||
|
// RSI: efi_system_table_t *table
|
||||||
|
// RDX: struct boot_params *bp
|
||||||
|
|
||||||
|
// We can reuse the stack provided by the UEFI firmware until a short time
|
||||||
|
// after exiting the UEFI boot services. So we don't build our own stack.
|
||||||
|
//
|
||||||
|
// But the stack must be 16-byte aligned! So we drop the return address.
|
||||||
|
add rsp, 8
|
||||||
|
|
||||||
|
// Call the Rust main routine.
|
||||||
|
call main_efi_handover64
|
||||||
|
|
||||||
|
// The main routine should not return. If it does, there is nothing we can
|
||||||
|
// do but stop the machine.
|
||||||
|
jmp halt
|
||||||
|
|
||||||
|
.global entry_efi_pe64
|
||||||
|
entry_efi_pe64:
|
||||||
|
// This is the 64-bit EFI PE/COFF entry point.
|
||||||
|
|
||||||
|
// Not supported yet. Just stop the machine.
|
||||||
|
jmp halt
|
||||||
|
|
||||||
// Unreachable here.
|
|
||||||
halt:
|
halt:
|
||||||
hlt
|
hlt
|
||||||
jmp halt
|
jmp halt
|
||||||
|
|
||||||
// A small stack for the setup code.
|
|
||||||
.section .data
|
|
||||||
.align 0x1000 / 8
|
|
||||||
.global setup_stack
|
|
||||||
setup_stack:
|
|
||||||
.skip 0x1000
|
|
||||||
.global setup_stack_top
|
|
||||||
setup_stack_top:
|
|
@ -10,9 +10,13 @@
|
|||||||
// are filled by the loader and will be read by Asterinas.
|
// are filled by the loader and will be read by Asterinas.
|
||||||
|
|
||||||
.section ".header", "a"
|
.section ".header", "a"
|
||||||
|
|
||||||
CODE32_START = 0x100000
|
CODE32_START = 0x100000
|
||||||
SETUP_SECTS = 7 # so that the legacy setup could occupy a page
|
|
||||||
.code16
|
# Real-mode setup sectors. We don't use them. Their size is set to one page.
|
||||||
|
SETUP_SECTS = 7
|
||||||
|
SETUP_SECTS_SIZE = 0x200 * (SETUP_SECTS + 1)
|
||||||
|
|
||||||
.org 0x01f1
|
.org 0x01f1
|
||||||
hdr_start:
|
hdr_start:
|
||||||
setup_sects: .byte SETUP_SECTS
|
setup_sects: .byte SETUP_SECTS
|
||||||
@ -30,7 +34,7 @@ realmode_swtch: .word 0, 0
|
|||||||
start_sys_seg: .word 0
|
start_sys_seg: .word 0
|
||||||
.word 0
|
.word 0
|
||||||
type_of_loader: .byte 0
|
type_of_loader: .byte 0
|
||||||
loadflags: .byte (1 << 0)
|
loadflags: .byte (1 << 0) # LOADED_HIGH
|
||||||
setup_move_size: .word 0
|
setup_move_size: .word 0
|
||||||
code32_start: .long CODE32_START
|
code32_start: .long CODE32_START
|
||||||
ramdisk_image: .long 0
|
ramdisk_image: .long 0
|
||||||
@ -44,15 +48,32 @@ initrd_addr_max: .long 0x7fffffff
|
|||||||
kernel_alignment: .long 0x1000000
|
kernel_alignment: .long 0x1000000
|
||||||
relocatable_kernel: .byte 0
|
relocatable_kernel: .byte 0
|
||||||
min_alignment: .byte 0x10
|
min_alignment: .byte 0x10
|
||||||
|
|
||||||
|
.if {CFG_TARGET_ARCH_X86_64}
|
||||||
|
# Note that we don't actually support the legacy 64-bit entry point
|
||||||
|
# (XLF_KERNEL_64). But we have to specify it, otherwise the boot loader
|
||||||
|
# will think this kernel does not have 64-bit support.
|
||||||
|
xloadflags: .word 0b01011 # Bit 0: XLF_KERNEL_64
|
||||||
|
# Bit 1: XLF_CAN_BE_LOADED_ABOVE_4G
|
||||||
|
# Bit 3: XLF_EFI_HANDOVER_64
|
||||||
|
.else
|
||||||
xloadflags: .word 0
|
xloadflags: .word 0
|
||||||
|
.endif
|
||||||
|
|
||||||
cmdline_size: .long 4096 - 1
|
cmdline_size: .long 4096 - 1
|
||||||
hardware_subarch: .long 0
|
hardware_subarch: .long 0
|
||||||
hardware_subarch_data: .quad 0
|
hardware_subarch_data: .quad 0
|
||||||
payload_offset: .long 0xabababab # at 0x248/4, to be filled by the builder
|
payload_offset: .long 0xabababab # at 0x248/4, to be filled by the builder
|
||||||
payload_length: .long 0xabababab # at 0x24c/4, to be filled by the builder
|
payload_length: .long 0xabababab # at 0x24c/4, to be filled by the builder
|
||||||
setup_data: .quad 0
|
setup_data: .quad 0
|
||||||
pref_address: .quad CODE32_START - 0x200 * (SETUP_SECTS + 1);
|
pref_address: .quad CODE32_START
|
||||||
init_size: .long 0xabababab # at 0x260/4, to be filled by the builder
|
init_size: .long 0xabababab # at 0x260/4, to be filled by the builder
|
||||||
|
|
||||||
|
.if {CFG_TARGET_ARCH_X86_64}
|
||||||
|
handover_offset: .long (entry_efi_handover32 - entry_legacy32)
|
||||||
|
.else
|
||||||
handover_offset: .long 0
|
handover_offset: .long 0
|
||||||
|
.endif
|
||||||
|
|
||||||
kernel_info_offset: .long 0
|
kernel_info_offset: .long 0
|
||||||
hdr_end:
|
hdr_end:
|
@ -4,23 +4,21 @@ use core::arch::{asm, global_asm};
|
|||||||
|
|
||||||
use linux_boot_params::BootParams;
|
use linux_boot_params::BootParams;
|
||||||
|
|
||||||
global_asm!(include_str!("header.S"));
|
|
||||||
|
|
||||||
global_asm!(include_str!("setup.S"));
|
global_asm!(include_str!("setup.S"));
|
||||||
|
|
||||||
use crate::console::{print_hex, print_str};
|
use crate::console::{print_hex, print_str};
|
||||||
|
|
||||||
pub const ASTER_ENTRY_POINT: u32 = 0x8001000;
|
pub const ASTER_ENTRY_POINT: u32 = 0x8001000;
|
||||||
|
|
||||||
#[export_name = "_bzimage_entry_32"]
|
#[export_name = "main_legacy32"]
|
||||||
extern "cdecl" fn bzimage_entry(boot_params_ptr: u32) -> ! {
|
extern "cdecl" fn main_legacy32(boot_params_ptr: u32) -> ! {
|
||||||
// SAFETY: this init function is only called once.
|
// SAFETY: this init function is only called once.
|
||||||
unsafe { crate::console::init() };
|
unsafe { crate::console::init() };
|
||||||
|
|
||||||
// println!("[setup] bzImage loaded at {:#x}", x86::relocation::get_image_loaded_offset());
|
// println!("[setup] bzImage loaded at {:#x}", x86::relocation::image_load_offset());
|
||||||
unsafe {
|
unsafe {
|
||||||
print_str("[setup] bzImage loaded offset: ");
|
print_str("[setup] bzImage loaded offset: ");
|
||||||
print_hex(crate::x86::get_image_loaded_offset() as u64);
|
print_hex(crate::x86::image_load_offset() as u64);
|
||||||
print_str("\n");
|
print_str("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,31 @@
|
|||||||
/* SPDX-License-Identifier: MPL-2.0 */
|
/* SPDX-License-Identifier: MPL-2.0 */
|
||||||
|
|
||||||
// 32-bit setup code starts here, and will be loaded at CODE32_START.
|
// The load address of the setup section is CODE32_START (0x100000).
|
||||||
|
// See the linker script.
|
||||||
.section ".setup", "ax"
|
.section ".setup", "ax"
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
.global start_of_setup32
|
.global entry_legacy32
|
||||||
start_of_setup32:
|
entry_legacy32:
|
||||||
mov eax, offset __stack_top
|
// This is the 32-bit Linux legacy entry point.
|
||||||
mov esp, eax
|
//
|
||||||
mov eax, offset halt
|
// Arguments:
|
||||||
push eax # the return address
|
// RSI: struct boot_params *bp
|
||||||
mov ebp, esp
|
|
||||||
add ebp, -4
|
|
||||||
push ebp
|
|
||||||
mov ebp, esp
|
|
||||||
|
|
||||||
// The rust entrypoint of the bzImage
|
// Set up the stack.
|
||||||
.extern _bzimage_entry_32
|
mov esp, offset __stack_top
|
||||||
push esi # the boot_params pointer
|
|
||||||
call _bzimage_entry_32
|
// Call the Rust main routine.
|
||||||
|
push esi
|
||||||
|
call main_legacy32
|
||||||
|
|
||||||
|
// The main routine should not return. If it does, there is nothing we can
|
||||||
|
// do but stop the machine.
|
||||||
|
jmp halt
|
||||||
|
|
||||||
|
// All other types of entry points are not enabled in the header.
|
||||||
|
// So we don't care about them.
|
||||||
|
|
||||||
// Unreachable here.
|
|
||||||
halt:
|
halt:
|
||||||
hlt
|
hlt
|
||||||
jmp halt
|
jmp halt
|
||||||
|
@ -1,38 +1,34 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use core::arch::global_asm;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(target_arch = "x86_64")] {
|
if #[cfg(target_arch = "x86_64")] {
|
||||||
mod amd64_efi;
|
mod amd64_efi;
|
||||||
|
|
||||||
|
const CFG_TARGET_ARCH_X86_64: usize = 1;
|
||||||
} else if #[cfg(target_arch = "x86")] {
|
} else if #[cfg(target_arch = "x86")] {
|
||||||
mod legacy_i386;
|
mod legacy_i386;
|
||||||
|
|
||||||
|
const CFG_TARGET_ARCH_X86_64: usize = 0;
|
||||||
} else {
|
} else {
|
||||||
compile_error!("Unsupported target_arch");
|
compile_error!("unsupported target architecture");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is enforced in the linker script of the setup.
|
global_asm!(
|
||||||
const START_OF_SETUP32_VA: usize = 0x100000;
|
include_str!("header.S"),
|
||||||
|
CFG_TARGET_ARCH_X86_64 = const CFG_TARGET_ARCH_X86_64,
|
||||||
|
);
|
||||||
|
|
||||||
/// The setup is a position-independent executable. We can get the loaded base
|
/// Returns the difference between the real load address and the one in the linker script.
|
||||||
/// address from the symbol.
|
pub fn image_load_offset() -> isize {
|
||||||
#[inline]
|
/// The load address of the `entry_legacy32` symbol specified in the linker script.
|
||||||
pub fn get_image_loaded_offset() -> isize {
|
const CODE32_START: isize = 0x100000;
|
||||||
let address_of_start: usize;
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
extern "C" {
|
||||||
unsafe {
|
fn entry_legacy32();
|
||||||
core::arch::asm!(
|
|
||||||
"lea {}, [rip + start_of_setup32]",
|
|
||||||
out(reg) address_of_start,
|
|
||||||
options(pure, nomem, nostack)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "x86")]
|
|
||||||
unsafe {
|
(entry_legacy32 as usize as isize) - CODE32_START
|
||||||
core::arch::asm!(
|
|
||||||
"lea {}, [start_of_setup32]",
|
|
||||||
out(reg) address_of_start,
|
|
||||||
options(pure, nomem, nostack)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
address_of_start as isize - START_OF_SETUP32_VA as isize
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user