use core::arch::naked_asm;

use super::addrspace::KERNEL_BASE;
use crate::efi_stub::{
    __x86_64_efi_pe_entry,
    pe::{
        IMAGE_DOS_SIGNATURE, IMAGE_FILE_DEBUG_STRIPPED, IMAGE_FILE_EXECUTABLE_IMAGE,
        IMAGE_FILE_LINE_NUMS_STRIPPED, IMAGE_FILE_MACHINE_AMD64, IMAGE_NT_SIGNATURE,
        IMAGE_SUBSYSTEM_EFI_APPLICATION, LINUX_EFISTUB_MAJOR_VERSION, LINUX_EFISTUB_MINOR_VERSION,
        LINUX_PE_MAGIC,
    },
};

#[unsafe(naked)]
#[unsafe(no_mangle)]
#[unsafe(link_section = ".head.text")]
pub unsafe extern "C" fn _head() {
    naked_asm!(
        ".word {dos_signature}",
        ".org 0x8",
        ".quad _kernel_entry",
        ".quad _kernel_asize",
        ".quad {phys_link_kaddr}",
        ".org 0x38",
        ".long {linux_pe_magic}",
        ".long 4f - _head",
        "4:",
        ".long {image_nt_signature}",
        ".short {file_machine}",
        ".short 2",
        ".long 0",
        ".long 0",
        ".long 0",
        ".short 2f - 1f",
        ".short {flags}",
        "1:",
        ".short 0x20b",
        ".byte 0x02",
        ".byte 0x14",
        ".long _kernel_code_size",
        ".long _kernel_rsize",
        ".long _kernel_bss_size",
        ".long {efi_pe_entry} - _head",
        ".long _kernel_text_offset",
        ".quad 0",
        ".long PAGE_SIZE",
        ".long PECOFF_FILE_ALIGN",
        ".short 0",
        ".short 0",
        ".short {major_image_version}",
        ".short {minor_image_version}",
        ".short 0",
        ".short 0",
        ".long 0",
        ".long _kernel_image_size",
        ".long _kernel_text_offset",
        ".long 0",
        ".short {image_subsystem}",
        ".short 0",
        ".quad 0",
        ".quad 0",
        ".quad 0",
        ".quad 0",
        ".long 0",
        ".long (2f - .) / 8",
        ".quad 0",
        ".quad 0",
        ".quad 0",
        ".quad 0",
        ".quad 0",
        ".quad 0",
        "2:",
        ".ascii \".text\\0\\0\\0\"",
        ".long _kernel_code_size",
        ".long _kernel_text_offset",
        ".long _kernel_code_size",
        ".long _kernel_text_offset",
        ".long 0",
        ".long 0",
        ".short 0",
        ".short 0",
        ".long 0x60000020",
        ".ascii \".data\\0\\0\\0\"",
        ".long _kernel_vsize",
        ".long _etext - _head",
        ".long _kernel_rsize",
        ".long _etext - _head",
        ".long 0",
        ".long 0",
        ".short 0",
        ".short 0",
        ".long 0xc0000040",
        dos_signature = const IMAGE_DOS_SIGNATURE,
        phys_link_kaddr = const KERNEL_BASE,
        linux_pe_magic = const LINUX_PE_MAGIC,
        image_nt_signature = const IMAGE_NT_SIGNATURE,
        file_machine = const IMAGE_FILE_MACHINE_AMD64,
        flags = const IMAGE_FILE_DEBUG_STRIPPED
            | IMAGE_FILE_EXECUTABLE_IMAGE
            | IMAGE_FILE_LINE_NUMS_STRIPPED,
        major_image_version = const LINUX_EFISTUB_MAJOR_VERSION,
        minor_image_version = const LINUX_EFISTUB_MINOR_VERSION,
        efi_pe_entry = sym __x86_64_efi_pe_entry,
        image_subsystem = const IMAGE_SUBSYSTEM_EFI_APPLICATION,
    )
}
