mirror of
https://github.com/rdmsr/zag.git
synced 2026-11-01 07:48:20 +00:00
loader: initial loader code
This commit is contained in:
+1
-2
@@ -9,8 +9,7 @@ pub const Bootloader = enum {
|
||||
pub const Platform = struct {
|
||||
arch: std.Target.Cpu.Arch,
|
||||
os: std.Target.Os.Tag,
|
||||
|
||||
bootloader: ?Bootloader = null,
|
||||
bootloader: Bootloader = .Limine,
|
||||
};
|
||||
|
||||
const ArchEnum = enum {
|
||||
|
||||
+9
-4
@@ -21,20 +21,24 @@ pub fn addIso(
|
||||
arch: Arch,
|
||||
image_name: []const u8,
|
||||
kernel: *std.Build.Step.Compile,
|
||||
loader: *std.Build.Step.Compile,
|
||||
limine: *std.Build.Dependency,
|
||||
) IsoResult {
|
||||
const limine_tool = addLimineTool(b, limine);
|
||||
const kernel_bin = kernel.getEmittedBin();
|
||||
const loader_bin = loader.getEmittedBin();
|
||||
|
||||
const prep_script =
|
||||
\\set -euo pipefail
|
||||
\\kernel="$1"
|
||||
\\iso_root="$2"
|
||||
\\limine_conf="$3"
|
||||
\\limine_dir="$4"
|
||||
\\arch="$5"
|
||||
\\loader="$2"
|
||||
\\iso_root="$3"
|
||||
\\limine_conf="$4"
|
||||
\\limine_dir="$5"
|
||||
\\arch="$6"
|
||||
\\rm -rf "$iso_root"
|
||||
\\mkdir -p "$iso_root/boot/limine" "$iso_root/EFI/BOOT"
|
||||
\\cp "$loader" "$iso_root/boot/loader"
|
||||
\\cp "$kernel" "$iso_root/boot/kernel"
|
||||
\\cp "$limine_conf" "$iso_root/boot/limine/limine.conf"
|
||||
\\case "$arch" in
|
||||
@@ -62,6 +66,7 @@ pub fn addIso(
|
||||
const prep = b.addSystemCommand(&.{ "bash", "-ceu", prep_script, "--" });
|
||||
|
||||
prep.addFileArg(kernel_bin);
|
||||
prep.addFileArg(loader_bin);
|
||||
prep.addDirectoryArg(iso_root.getDirectory());
|
||||
prep.addFileArg(b.path("build/limine.conf"));
|
||||
prep.addDirectoryArg(limine.path("."));
|
||||
|
||||
+4
-1
@@ -7,5 +7,8 @@ timeout: 3
|
||||
protocol: limine
|
||||
|
||||
# Path to the kernel to boot. boot():/ represents the partition on which limine.conf is located.
|
||||
path: boot():/boot/kernel
|
||||
path: boot():/boot/loader
|
||||
|
||||
module_path: boot():/boot/kernel
|
||||
module_string: kernel
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* Tell the linker that we want an aarch64 ELF64 output file */
|
||||
OUTPUT_FORMAT(elf64-littleaarch64)
|
||||
|
||||
/* We want the symbol kmain to be our entry point */
|
||||
ENTRY(kmain)
|
||||
|
||||
/* Define the program headers we want so the bootloader gives us the right */
|
||||
/* MMU permissions; this also allows us to exert more control over the linking */
|
||||
/* process. */
|
||||
PHDRS
|
||||
{
|
||||
limine_requests PT_LOAD;
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
|
||||
/* and because that is what the Limine spec mandates. */
|
||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||
.limine_requests : {
|
||||
KEEP(*(.limine_requests_start))
|
||||
KEEP(*(.limine_requests))
|
||||
KEEP(*(.limine_requests_end))
|
||||
} :limine_requests
|
||||
|
||||
/* Move to the next memory page for .text */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */
|
||||
/* linker command. */
|
||||
.note.gnu.build-id : {
|
||||
*(.note.gnu.build-id)
|
||||
} :rodata
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||
/* unnecessary zeros will be written to the binary. */
|
||||
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||
/* above this. */
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
} :data
|
||||
|
||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
/* Tell the linker that we want an x86_64 ELF64 output file */
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
|
||||
/* We want the symbol kmain to be our entry point */
|
||||
ENTRY(kmain)
|
||||
|
||||
/* Define the program headers we want so the bootloader gives us the right */
|
||||
/* MMU permissions; this also allows us to exert more control over the linking */
|
||||
/* process. */
|
||||
PHDRS
|
||||
{
|
||||
limine_requests PT_LOAD;
|
||||
@@ -17,22 +12,20 @@ PHDRS
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
|
||||
/* and because that is what the Limine spec mandates. */
|
||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||
|
||||
.limine_requests : {
|
||||
KEEP(*(.limine_requests_start))
|
||||
KEEP(*(.limine_requests))
|
||||
KEEP(*(.limine_requests_end))
|
||||
} :limine_requests
|
||||
|
||||
/* Move to the next memory page for .text */
|
||||
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
|
||||
|
||||
text_start_addr = .;
|
||||
|
||||
.text : {
|
||||
@@ -40,11 +33,9 @@ SECTIONS
|
||||
} :text
|
||||
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
text_end_addr = .;
|
||||
|
||||
rodata_start_addr = .;
|
||||
|
||||
.rodata : {
|
||||
@@ -52,14 +43,11 @@ SECTIONS
|
||||
} :rodata
|
||||
|
||||
|
||||
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */
|
||||
/* linker command. */
|
||||
.note.gnu.build-id : {
|
||||
*(.note.gnu.build-id)
|
||||
} :rodata
|
||||
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
rodata_end_addr = .;
|
||||
|
||||
@@ -83,10 +71,7 @@ SECTIONS
|
||||
} :data
|
||||
|
||||
|
||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||
/* unnecessary zeros will be written to the binary. */
|
||||
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||
/* above this. */
|
||||
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
@@ -97,7 +82,6 @@ SECTIONS
|
||||
|
||||
data_end_addr = .;
|
||||
|
||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
@@ -0,0 +1,68 @@
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
ENTRY(loader_entry)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
limine_requests PT_LOAD;
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xffffffffe0000000;
|
||||
|
||||
.limine_requests : {
|
||||
KEEP(*(.limine_requests_start))
|
||||
KEEP(*(.limine_requests))
|
||||
KEEP(*(.limine_requests_end))
|
||||
} :limine_requests
|
||||
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
text_start_addr = .;
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
text_end_addr = .;
|
||||
|
||||
rodata_start_addr = .;
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
.note.gnu.build-id : {
|
||||
*(.note.gnu.build-id)
|
||||
} :rodata
|
||||
|
||||
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
rodata_end_addr = .;
|
||||
data_start_addr = .;
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
} :data
|
||||
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
data_end_addr = .;
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/* Tell the linker that we want a loongarch64 ELF64 output file */
|
||||
OUTPUT_FORMAT(elf64-loongarch)
|
||||
|
||||
/* We want the symbol kmain to be our entry point */
|
||||
ENTRY(kmain)
|
||||
|
||||
/* Define the program headers we want so the bootloader gives us the right */
|
||||
/* MMU permissions; this also allows us to exert more control over the linking */
|
||||
/* process. */
|
||||
PHDRS
|
||||
{
|
||||
limine_requests PT_LOAD;
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
|
||||
/* and because that is what the Limine spec mandates. */
|
||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||
.limine_requests : {
|
||||
KEEP(*(.limine_requests_start))
|
||||
KEEP(*(.limine_requests))
|
||||
KEEP(*(.limine_requests_end))
|
||||
} :limine_requests
|
||||
|
||||
/* Move to the next memory page for .text */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */
|
||||
/* linker command. */
|
||||
.note.gnu.build-id : {
|
||||
*(.note.gnu.build-id)
|
||||
} :rodata
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||
/* unnecessary zeros will be written to the binary. */
|
||||
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||
/* above this. */
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
} :data
|
||||
|
||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/* Tell the linker that we want a riscv64 ELF64 output file */
|
||||
OUTPUT_FORMAT(elf64-littleriscv)
|
||||
|
||||
/* We want the symbol kmain to be our entry point */
|
||||
ENTRY(kmain)
|
||||
|
||||
/* Define the program headers we want so the bootloader gives us the right */
|
||||
/* MMU permissions; this also allows us to exert more control over the linking */
|
||||
/* process. */
|
||||
PHDRS
|
||||
{
|
||||
limine_requests PT_LOAD;
|
||||
text PT_LOAD;
|
||||
rodata PT_LOAD;
|
||||
data PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
|
||||
/* and because that is what the Limine spec mandates. */
|
||||
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||
/* that is the beginning of the region. */
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
/* Define a section to contain the Limine requests and assign it to its own PHDR */
|
||||
.limine_requests : {
|
||||
KEEP(*(.limine_requests_start))
|
||||
KEEP(*(.limine_requests))
|
||||
KEEP(*(.limine_requests_end))
|
||||
} :limine_requests
|
||||
|
||||
/* Move to the next memory page for .text */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.text : {
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
|
||||
/* Move to the next memory page for .rodata */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.rodata : {
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
/* Add a .note.gnu.build-id output section in case a build ID flag is added to the */
|
||||
/* linker command. */
|
||||
.note.gnu.build-id : {
|
||||
*(.note.gnu.build-id)
|
||||
} :rodata
|
||||
|
||||
/* Move to the next memory page for .data */
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||
/* unnecessary zeros will be written to the binary. */
|
||||
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||
/* above this. */
|
||||
.bss : {
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
} :data
|
||||
|
||||
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame*)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
SECTIONS {
|
||||
.data.percpu : {
|
||||
__percpu_start = .;
|
||||
*(.data.percpu)
|
||||
__percpu_end = .;
|
||||
}
|
||||
|
||||
.percpu_init_array : {
|
||||
__init_array_percpu_start = .;
|
||||
KEEP(*(.percpu_init_array))
|
||||
__init_array_percpu_end = .;
|
||||
}
|
||||
|
||||
} INSERT AFTER .data;
|
||||
|
||||
PROVIDE(text_start_addr = ADDR(.text));
|
||||
PROVIDE(text_end_addr = ADDR(.text) + SIZEOF(.text));
|
||||
+4
-4
@@ -8,7 +8,7 @@ const QemuArgs = struct {
|
||||
args: [][]u8,
|
||||
};
|
||||
|
||||
pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, plat: config.Platform) void {
|
||||
pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, loader: *std.Build.Step.Compile, plat: config.Platform) void {
|
||||
const run_step = b.step("run", "Run the kernel");
|
||||
const uefi = b.option(bool, "uefi", "Boot with UEFI firmware") orelse false;
|
||||
const debug = b.option(bool, "debug", "Boot in debug mode") orelse false;
|
||||
@@ -17,7 +17,7 @@ pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, plat: config.Platf
|
||||
if (plat.os == .freestanding) {
|
||||
const limine = b.dependency("limine", .{});
|
||||
const ovmf = b.dependency("ovmf", .{});
|
||||
const iso_out = image.addIso(b, plat.arch, "myos", kernel, limine);
|
||||
const iso_out = image.addIso(b, plat.arch, "myos", kernel, loader, limine);
|
||||
|
||||
const qemu_bin = switch (plat.arch) {
|
||||
.x86_64 => "qemu-system-x86_64",
|
||||
@@ -47,8 +47,8 @@ pub fn addRun(b: *std.Build, kernel: *std.Build.Step.Compile, plat: config.Platf
|
||||
qemu.addArgs(&.{
|
||||
"-d",
|
||||
"int",
|
||||
"-s",
|
||||
"-S",
|
||||
//"-s",
|
||||
//"-S",
|
||||
"-D",
|
||||
"qemu.log",
|
||||
"-no-reboot",
|
||||
|
||||
Reference in New Issue
Block a user