feat: add initial impl of efi-stub and kernel
This commit is contained in:
1
arch/x86/boot/.gitignore
vendored
Normal file
1
arch/x86/boot/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
offset.h
|
||||
86
arch/x86/boot/build.zig
Normal file
86
arch/x86/boot/build.zig
Normal file
@@ -0,0 +1,86 @@
|
||||
const std = @import("std");
|
||||
const kernel_build = @import("../../../kernel/build.zig");
|
||||
const Step = std.Build.Step;
|
||||
|
||||
pub fn buildSetup(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, kcapsule: *Step.Compile) *Step.Compile {
|
||||
const offset_generate = b.addSystemCommand(&[_][]const u8{
|
||||
"sh",
|
||||
"arch/x86/boot/helper.sh",
|
||||
"generate_offset_header",
|
||||
});
|
||||
offset_generate.addFileArg(kcapsule.getEmittedBin());
|
||||
offset_generate.step.dependOn(&kcapsule.step);
|
||||
const setup = b.addExecutable(.{
|
||||
.name = "setup",
|
||||
.use_lld = true,
|
||||
.use_llvm = true,
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("arch/x86/boot/setup/stage1.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}),
|
||||
});
|
||||
setup.step.dependOn(&offset_generate.step);
|
||||
setup.step.addWatchInput(b.path("arch/x86/boot/offset.h")) catch {};
|
||||
setup.addAssemblyFile(b.path("arch/x86/boot/header.S"));
|
||||
setup.addIncludePath(b.path("include"));
|
||||
setup.addIncludePath(b.path("arch/x86/boot"));
|
||||
setup.setLinkerScript(b.path("arch/x86/boot/setup.ld"));
|
||||
return setup;
|
||||
}
|
||||
pub fn buildKcapsule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *Step.Compile {
|
||||
const kernel = kernel_build.buildKernelBin(b, target, optimize);
|
||||
const kcapsule = b.addExecutable(.{
|
||||
.name = "kcapsule",
|
||||
.use_lld = true,
|
||||
.use_llvm = true,
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("arch/x86/boot/extractor.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.pic = true,
|
||||
}),
|
||||
});
|
||||
const efi_target = b.resolveTargetQuery(.{
|
||||
.cpu_arch = .x86_64,
|
||||
.os_tag = .freestanding,
|
||||
.abi = .msvc,
|
||||
});
|
||||
const efi_loader = b.addObject(.{
|
||||
.name = "efi_loader",
|
||||
.use_lld = true,
|
||||
.use_llvm = true,
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("drivers/firmware/efi/x86.zig"),
|
||||
.target = efi_target,
|
||||
.optimize = optimize,
|
||||
.pic = true,
|
||||
}),
|
||||
});
|
||||
kcapsule.pie = true;
|
||||
kcapsule.entry = .{ .symbol_name = "efi_pe_entry" };
|
||||
kcapsule.addObject(efi_loader);
|
||||
kcapsule.addAssemblyFile(b.path("arch/x86/boot/payload.S"));
|
||||
kcapsule.setLinkerScript(b.path("arch/x86/boot/kcapsule.ld"));
|
||||
kcapsule.step.dependOn(&kernel.step);
|
||||
|
||||
return kcapsule;
|
||||
}
|
||||
pub fn buildImage(b: *std.Build, optimize: std.builtin.OptimizeMode) *Step {
|
||||
const target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .freestanding, .abi = .none });
|
||||
|
||||
const kcapsule = buildKcapsule(b, target, optimize);
|
||||
const setup = buildSetup(b, target, optimize, kcapsule);
|
||||
const image = b.addSystemCommand(&[_][]const u8{
|
||||
"sh",
|
||||
"arch/x86/boot/helper.sh",
|
||||
"build_image",
|
||||
});
|
||||
|
||||
image.addFileArg(setup.getEmittedBin());
|
||||
image.addFileArg(kcapsule.getEmittedBin());
|
||||
image.step.dependOn(&setup.step);
|
||||
image.step.dependOn(&kcapsule.step);
|
||||
|
||||
return &image.step;
|
||||
}
|
||||
0
arch/x86/boot/extractor.zig
Normal file
0
arch/x86/boot/extractor.zig
Normal file
86
arch/x86/boot/header.S
Normal file
86
arch/x86/boot/header.S
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "format/pe.h"
|
||||
#include "offset.h"
|
||||
.set salign, 0x1000
|
||||
.set falign, 0x200
|
||||
.section ".bstext", "ax" // allocatable, executable
|
||||
.word IMAGE_DOS_SIGNATURE
|
||||
.org 0x3c
|
||||
.long pe_header
|
||||
.global pe_header
|
||||
pe_header:
|
||||
.long IMAGE_NT_SIGNATURE
|
||||
coff_header:
|
||||
.word IMAGE_FILE_MACHINE_AMD64
|
||||
.word section_count
|
||||
.long 0 /* TimeDateStamp */
|
||||
.long 0 /* PointerToSymbolTable */
|
||||
.long 0 /* NumberOfSymbols */
|
||||
.word section_table - optional_header /* SizeOfOptionalHeader */
|
||||
.word IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED /* Characteristics */
|
||||
optional_header:
|
||||
.word IMAGE_NT_OPTIONAL_HDR64_MAGIC /* Magic */
|
||||
.byte 0 /* MajorLinkerVersion */
|
||||
.byte 0 /* MinorLinkerVersion */
|
||||
.long CAP__data /* SizeOfCode */
|
||||
.long CAP__end - CAP__data /* SizeOfInitializedData */
|
||||
.long 0 /* SizeOfUninitializedData */
|
||||
.long setup_size + efi_pe_entry /* AddressOfEntryPoint */
|
||||
.long setup_size /* BaseOfCode */
|
||||
extra_header_fields:
|
||||
.quad 0 /* ImageBase */
|
||||
.long salign /* SectionAlignment */
|
||||
.long falign /* FileAlignment */
|
||||
.word 0 /* MajorOperatingSystemVersion */
|
||||
.word 0 /* MinorOperatingSystemVersion */
|
||||
.word 0 /* MajorImageVersion */
|
||||
.word 0 /* MinorImageVersion */
|
||||
.word 0 /* MajorSubsystemVersion */
|
||||
.word 0 /* MinorSubsystemVersion */
|
||||
.long 0 /* Win32VersionValue */
|
||||
|
||||
.long setup_size + CAP__end /* SizeOfImage */
|
||||
|
||||
.long salign /* SizeOfHeaders */
|
||||
.long 0 /* CheckSum */
|
||||
.word IMAGE_SUBSYSTEM_EFI_APPLICATION /* Subsystem */
|
||||
.word IMAGE_DLLCHARACTERISTICS_NX_COMPAT /* DllCharacteristics */
|
||||
.quad 0 /* SizeOfStackReserve */
|
||||
.quad 0 /* SizeOfStackCommit */
|
||||
.quad 0 /* SizeOfHeapReserve */
|
||||
.quad 0 /* SizeOfHeapCommit */
|
||||
.long 0 /* LoaderFlags */
|
||||
.long (section_table - .) / 8 /* NumberOfRvaAndSizes */
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
|
||||
section_table:
|
||||
# .ascii ".setup\0\0"
|
||||
# .long setup_size - salign /* VirtualSize */
|
||||
# .long salign /* VirtualAddress */
|
||||
# .long setup_size - salign /* SizeOfRawData */
|
||||
# .long salign /* PointerToRawData */
|
||||
# .long 0,0,0
|
||||
# .long IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
|
||||
|
||||
.ascii ".text\0\0\0"
|
||||
.long text_size /* VirtualSize */
|
||||
.long setup_size /* VirtualAddress */
|
||||
.long text_size /* SizeOfRawData */
|
||||
.long setup_size /* PointerToRawData */
|
||||
.long 0,0,0
|
||||
.long IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE
|
||||
|
||||
.ascii ".data\0\0\0"
|
||||
.long CAP__end - CAP__data /* VirtualSize */
|
||||
.long setup_size + CAP__data /* VirtualAddress */
|
||||
.long CAP__edata - CAP__data /* SizeOfRawData */
|
||||
.long setup_size + CAP__data /* PointerToRawData */
|
||||
.long 0,0,0
|
||||
.long IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
|
||||
|
||||
.set text_size, CAP__data
|
||||
.set section_count, (. - section_table) / 40
|
||||
30
arch/x86/boot/helper.sh
Normal file
30
arch/x86/boot/helper.sh
Normal file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
generate_offset_header() {
|
||||
echo "processing $1"
|
||||
nm -n "$1" \
|
||||
| grep -e ' _\(end\|edata\|data\)$' \
|
||||
| awk '{print "#define CAP_" $3 " 0x" $1}' \
|
||||
> arch/x86/boot/offset.h
|
||||
nm -n "$1" \
|
||||
| grep -e ' efi_pe_entry$' \
|
||||
| awk '{print "#define efi_pe_entry 0x" $1}' \
|
||||
>> arch/x86/boot/offset.h
|
||||
}
|
||||
build_image() {
|
||||
echo "building image from $1 and $2"
|
||||
(dd if=$1 bs=4k conv=sync; cat $2) > yukiImage
|
||||
}
|
||||
# Main dispatcher
|
||||
case "$1" in
|
||||
generate_offset_header)
|
||||
generate_offset_header "$2"
|
||||
;;
|
||||
build_image)
|
||||
build_image "$2" "$3"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {generate_offset_header|build_image} [args...]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
60
arch/x86/boot/kcapsule.ld
Normal file
60
arch/x86/boot/kcapsule.ld
Normal file
@@ -0,0 +1,60 @@
|
||||
OUTPUT_ARCH(i386:x86_64)
|
||||
SECTIONS {
|
||||
. = 0x1000;
|
||||
.text : {
|
||||
_text = .;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
_etext = .;
|
||||
}
|
||||
.rodata : {
|
||||
_rodata = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
_erodata = .;
|
||||
}
|
||||
. = ALIGN(0x1000);
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
. = ALIGN(0x1000);
|
||||
_edata = .;
|
||||
}
|
||||
.bss : {
|
||||
_bss = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
_ebss = .;
|
||||
}
|
||||
|
||||
.pgtable : {
|
||||
_pgtable = .;
|
||||
*(.pgtable)
|
||||
_epgtable = .;
|
||||
}
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
_end = .;
|
||||
.got.plt (INFO) : {
|
||||
*(.got.plt)
|
||||
}
|
||||
ASSERT(SIZEOF(.got.plt) == 0 ||
|
||||
SIZEOF(.got.plt) == 0x18,
|
||||
"Unexpected GOT/PLT entries detected!")
|
||||
|
||||
/*
|
||||
* Sections that should stay zero sized, which is safer to
|
||||
* explicitly check instead of blindly discarding.
|
||||
*/
|
||||
.got : {
|
||||
*(.got)
|
||||
}
|
||||
ASSERT(SIZEOF(.got) == 0, "Unexpected GOT entries detected!")
|
||||
|
||||
.plt : {
|
||||
*(.plt) *(.plt.*)
|
||||
}
|
||||
ASSERT(SIZEOF(.plt) == 0, "Unexpected run-time procedure linkages detected!")
|
||||
}
|
||||
0
arch/x86/boot/payload.S
Normal file
0
arch/x86/boot/payload.S
Normal file
28
arch/x86/boot/setup.ld
Normal file
28
arch/x86/boot/setup.ld
Normal file
@@ -0,0 +1,28 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0;
|
||||
|
||||
.bstext : {
|
||||
*(.bstext)
|
||||
. = 495;
|
||||
} =0xffffffff
|
||||
.text : {*(.text .text.*)}
|
||||
. = ALIGN(16);
|
||||
.rodata : {*(.rodata .rodata.*)}
|
||||
. = ALIGN(16);
|
||||
.data : {*(.data .data.*)}
|
||||
|
||||
setup_size = ALIGN(ABSOLUTE(.), 4096);
|
||||
|
||||
. = ALIGN(16);
|
||||
.bss : {*(.bss) }
|
||||
. = ALIGN(16);
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.note*)
|
||||
}
|
||||
|
||||
}
|
||||
0
arch/x86/boot/setup/stage1.zig
Normal file
0
arch/x86/boot/setup/stage1.zig
Normal file
Reference in New Issue
Block a user