commit 1233ae9e9ba4c367cb35611a66cb2878c173ac11 Author: Hydrostic Date: Wed Jan 28 16:01:38 2026 +0800 feat: add initial impl of efi-stub and kernel diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f92393 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +zig-out +.zig-cache + +yukiImage +kcapsule +*.img + + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..691fb1a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "files.associations": { + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..33aa535 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# YukiOS diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore new file mode 100644 index 0000000..c834e83 --- /dev/null +++ b/arch/x86/boot/.gitignore @@ -0,0 +1 @@ +offset.h \ No newline at end of file diff --git a/arch/x86/boot/build.zig b/arch/x86/boot/build.zig new file mode 100644 index 0000000..ec1a0c8 --- /dev/null +++ b/arch/x86/boot/build.zig @@ -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; +} diff --git a/arch/x86/boot/extractor.zig b/arch/x86/boot/extractor.zig new file mode 100644 index 0000000..e69de29 diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S new file mode 100644 index 0000000..a9ce82f --- /dev/null +++ b/arch/x86/boot/header.S @@ -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 \ No newline at end of file diff --git a/arch/x86/boot/helper.sh b/arch/x86/boot/helper.sh new file mode 100644 index 0000000..cc9deec --- /dev/null +++ b/arch/x86/boot/helper.sh @@ -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 \ No newline at end of file diff --git a/arch/x86/boot/kcapsule.ld b/arch/x86/boot/kcapsule.ld new file mode 100644 index 0000000..4604ad3 --- /dev/null +++ b/arch/x86/boot/kcapsule.ld @@ -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!") +} \ No newline at end of file diff --git a/arch/x86/boot/payload.S b/arch/x86/boot/payload.S new file mode 100644 index 0000000..e69de29 diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld new file mode 100644 index 0000000..812c50f --- /dev/null +++ b/arch/x86/boot/setup.ld @@ -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*) + } + +} \ No newline at end of file diff --git a/arch/x86/boot/setup/stage1.zig b/arch/x86/boot/setup/stage1.zig new file mode 100644 index 0000000..e69de29 diff --git a/arch/x86/kernel_bin.ld b/arch/x86/kernel_bin.ld new file mode 100644 index 0000000..0016bba --- /dev/null +++ b/arch/x86/kernel_bin.ld @@ -0,0 +1,29 @@ +OUTPUT_ARCH(i386:x86_64) +ENTRY(kernel_start) +SECTIONS { + .text : { + *(.text) + *(.text.*) + } + + .rodata : { + *(.rodata) + *(.rodata.*) + } + + .data : { + *(.data) + *(.data.*) + } + .bss : { + *(.bss) + *(.bss.*) + *(COMMON) + } + + .pgtable : { + *(.pgtable) + } + + . = ALIGN(0x1000); +} \ No newline at end of file diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..5896e3a --- /dev/null +++ b/build.zig @@ -0,0 +1,35 @@ +const std = @import("std"); +const kernel_build = @import("kernel/build.zig"); +fn buildImage(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step { + switch (target.result.cpu.arch) { + .x86_64 => { + const arch_build = @import("arch/x86/boot/build.zig"); + return arch_build.buildImage(b, optimize); + }, + else => { + @panic("target architecture unsupported"); + } + } + +} + +pub fn build(b: *std.Build) void { + const kernel_only_step = b.step("kernel", "Build the kernel only"); + const full_step = b.step("full", "Build the full OS image"); + const qemu_step = b.step("qemu", "Build and run in QEMU"); + const target = b.resolveTargetQuery(.{ + .cpu_arch = .x86_64, + .os_tag = .freestanding, + .abi = .none + }); + const optimize = b.standardOptimizeOption(.{}); + + const kernel_install = kernel_build.buildKernelBin(b, target, optimize); + kernel_only_step.dependOn(&kernel_install.step); + const image_step = buildImage(b, target, optimize); + b.getInstallStep().dependOn(image_step); + full_step.dependOn(image_step); + + qemu_step.dependOn(image_step); + +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..d174b11 --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,81 @@ +.{ + // This is the default name used by packages depending on this one. For + // example, when a user runs `zig fetch --save `, this field is used + // as the key in the `dependencies` table. Although the user can choose a + // different name, most users will stick with this provided value. + // + // It is redundant to include "zig" in this name because it is already + // within the Zig package namespace. + .name = .YukiOS, + // This is a [Semantic Version](https://semver.org/). + // In a future version of Zig it will be used for package deduplication. + .version = "0.0.0", + // Together with name, this represents a globally unique package + // identifier. This field is generated by the Zig toolchain when the + // package is first created, and then *never changes*. This allows + // unambiguous detection of one package being an updated version of + // another. + // + // When forking a Zig project, this id should be regenerated (delete the + // field and run `zig build`) if the upstream project is still maintained. + // Otherwise, the fork is *hostile*, attempting to take control over the + // original project's identity. Thus it is recommended to leave the comment + // on the following line intact, so that it shows up in code reviews that + // modify the field. + .fingerprint = 0x85d3440a21cff096, // Changing this has security and trust implications. + // Tracks the earliest Zig version that the package considers to be a + // supported use case. + .minimum_zig_version = "0.15.2", + // This field is optional. + // Each dependency must either provide a `url` and `hash`, or a `path`. + // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. + // Once all dependencies are fetched, `zig build` no longer requires + // internet connectivity. + .dependencies = .{ + // See `zig fetch --save ` for a command-line interface for adding dependencies. + //.example = .{ + // // When updating this field to a new URL, be sure to delete the corresponding + // // `hash`, otherwise you are communicating that you expect to find the old hash at + // // the new URL. If the contents of a URL change this will result in a hash mismatch + // // which will prevent zig from using it. + // .url = "https://example.com/foo.tar.gz", + // + // // This is computed from the file contents of the directory of files that is + // // obtained after fetching `url` and applying the inclusion rules given by + // // `paths`. + // // + // // This field is the source of truth; packages do not come from a `url`; they + // // come from a `hash`. `url` is just one of many possible mirrors for how to + // // obtain a package matching this `hash`. + // // + // // Uses the [multihash](https://multiformats.io/multihash/) format. + // .hash = "...", + // + // // When this is provided, the package is found in a directory relative to the + // // build root. In this case the package's hash is irrelevant and therefore not + // // computed. This field and `url` are mutually exclusive. + // .path = "foo", + // + // // When this is set to `true`, a package is declared to be lazily + // // fetched. This makes the dependency only get fetched if it is + // // actually used. + // .lazy = false, + //}, + }, + // Specifies the set of files and directories that are included in this package. + // Only files and directories listed here are included in the `hash` that + // is computed for this package. Only files listed here will remain on disk + // when using the zig package manager. As a rule of thumb, one should list + // files required for compilation plus any license(s). + // Paths are relative to the build root. Use the empty string (`""`) to refer to + // the build root itself. + // A directory listed here means that all files within, recursively, are included. + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + // For example... + //"LICENSE", + //"README.md", + }, +} diff --git a/drivers/firmware/efi/console.zig b/drivers/firmware/efi/console.zig new file mode 100644 index 0000000..4b45ee9 --- /dev/null +++ b/drivers/firmware/efi/console.zig @@ -0,0 +1,75 @@ +const std = @import("std"); +const uefi = std.os.uefi; +const unicode = std.unicode; +const SimpleTextOutput = uefi.protocol.SimpleTextOutput; + +pub const UefiConsole = struct { + console_out: ?*SimpleTextOutput = null, + pub fn init(system_table: *uefi.tables.SystemTable) UefiConsole { + var console = UefiConsole{}; + var con_out = system_table.con_out orelse return console; + con_out.clearScreen() catch return console; + con_out.setCursorPosition(0, 0) catch return console; + console.console_out = con_out; + UefiWriter.UEFI_WRITER_VTABLE = .{ + .drain = UefiWriter.drain, + }; + return console; + } + pub const UefiWriter = struct { + console: *UefiConsole, + interface: std.Io.Writer, + var UEFI_WRITER_VTABLE: std.io.Writer.VTable = .{ + .drain = undefined, + }; + pub fn drain(ptr: *std.Io.Writer, buf: []const []const u8, splat: usize) !usize { + _ = splat; + const self: *UefiWriter = @fieldParentPtr("interface", ptr); + if (self.console.console_out) |out| { + var written: usize = 0; + for (buf) |b| { + + var start: usize = 0; + var ucs2_buf = [_]u16{0} ** 65; + while (start < buf.len) { + const len = unicode.utf8ToUtf16Le(ucs2_buf[0..64], b[start..@min(start + 64, b.len)]) catch { + return error.WriteFailed; + }; + ucs2_buf[len] = 0; + _ = out.outputString(@ptrCast(&ucs2_buf)) catch { + return error.WriteFailed; + }; + start += len; + } + written += b.len; + } + return written; + } else { + return 0; + } + } + }; + pub fn writer(self: *UefiConsole) UefiWriter { + const w = UefiWriter{ + .console = self, + .interface = .{ + .vtable = @call(.never_inline, getVtable, .{}), + .buffer = &[0]u8{}, + .end = 0 + }, + }; + return w; + } + fn getVtable() *const std.Io.Writer.VTable { + return &UefiWriter.UEFI_WRITER_VTABLE; + } +}; + +pub var uc: UefiConsole = undefined; +pub fn initUefiConsole(system_table: *uefi.tables.SystemTable) void { + uc = UefiConsole.init(system_table); +} +pub fn info(comptime fmt: []const u8, args: anytype) void { + var w = uc.writer(); + w.interface.print(fmt, args) catch {}; +} \ No newline at end of file diff --git a/drivers/firmware/efi/x86.zig b/drivers/firmware/efi/x86.zig new file mode 100644 index 0000000..76838f9 --- /dev/null +++ b/drivers/firmware/efi/x86.zig @@ -0,0 +1,17 @@ +const std = @import("std"); +const console = @import("console.zig"); +const uefi = std.os.uefi; +const SystemTable = uefi.tables.SystemTable; + +export fn efi_pe_entry(image_handle: uefi.Handle, system_table: *SystemTable) callconv(.{ .x86_64_win = .{} }) uefi.Status { + const mark_ptr: *usize = @ptrFromInt(0x10000); + mark_ptr.* = 0xdeadbeef; + _ = image_handle; + if (system_table.hdr.signature != SystemTable.signature) { + return uefi.Status.invalid_parameter; + } + console.initUefiConsole(system_table); + console.info("Booting YukiOS kernel\n", .{}); + while(true) {} + return .success; +} diff --git a/include/format/pe.h b/include/format/pe.h new file mode 100644 index 0000000..a85277f --- /dev/null +++ b/include/format/pe.h @@ -0,0 +1,211 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Portable Executable (PE) format definitions. + * + * This file is derived from the Linux kernel source: + * include/linux/pe.h + * + * Copyright holders of the original Linux kernel code retain their copyright. + * See the original Linux kernel source for full copyright and licensing details. + */ + +#define IMAGE_DOS_SIGNATURE 0x5a4d /* "MZ" */ + +#define IMAGE_NT_SIGNATURE 0x00004550 /* "PE\0\0" */ + +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x0107 /* ROM image (for R3000/R4000/R10000/ALPHA), without MZ and PE\0\0 sign */ +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x010b /* PE32 executable image */ +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x020b /* PE32+ executable image */ + +/* machine type */ +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 /* Unknown architecture */ +#define IMAGE_FILE_MACHINE_TARGET_HOST 0x0001 /* Interacts with the host and not a WOW64 guest (not for file image) */ +#define IMAGE_FILE_MACHINE_ALPHA_OLD 0x0183 /* DEC Alpha AXP 32-bit (old images) */ +#define IMAGE_FILE_MACHINE_ALPHA 0x0184 /* DEC Alpha AXP 32-bit */ +#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 /* DEC Alpha AXP 64-bit (with 8kB page size) */ +#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 +#define IMAGE_FILE_MACHINE_AM33 0x01d3 /* Matsushita AM33, now Panasonic MN103 */ +#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* AMD64 (x64) */ +#define IMAGE_FILE_MACHINE_ARM 0x01c0 /* ARM Little-Endian (ARMv4) */ +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 /* ARM Thumb Little-Endian (ARMv4T) */ +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 /* ARM Thumb-2 Little-Endian (ARMv7) */ +#define IMAGE_FILE_MACHINE_ARMV7 IMAGE_FILE_MACHINE_ARMNT +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 /* ARM64 Little-Endian (Classic ABI) */ +#define IMAGE_FILE_MACHINE_ARM64EC 0xa641 /* ARM64 Little-Endian (Emulation Compatible ABI for AMD64) */ +#define IMAGE_FILE_MACHINE_ARM64X 0xa64e /* ARM64 Little-Endian (fat binary with both Classic ABI and EC ABI code) */ +#define IMAGE_FILE_MACHINE_CEE 0xc0ee /* COM+ Execution Engine (CLR pure MSIL object files) */ +#define IMAGE_FILE_MACHINE_CEF 0x0cef /* Windows CE 3.0 Common Executable Format (CEF bytecode) */ +#define IMAGE_FILE_MACHINE_CHPE_X86 0x3a64 /* ARM64 Little-Endian (Compiled Hybrid PE ABI for I386) */ +#define IMAGE_FILE_MACHINE_HYBRID_X86 IMAGE_FILE_MACHINE_CHPE_X86 +#define IMAGE_FILE_MACHINE_EBC 0x0ebc /* EFI/UEFI Byte Code */ +#define IMAGE_FILE_MACHINE_I386 0x014c /* Intel 386 (x86) */ +#define IMAGE_FILE_MACHINE_I860 0x014d /* Intel 860 (N10) */ +#define IMAGE_FILE_MACHINE_IA64 0x0200 /* Intel IA-64 (with 8kB page size) */ +#define IMAGE_FILE_MACHINE_LOONGARCH32 0x6232 /* LoongArch 32-bit processor family */ +#define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 /* LoongArch 64-bit processor family */ +#define IMAGE_FILE_MACHINE_M32R 0x9041 /* Mitsubishi M32R 32-bit Little-Endian */ +#define IMAGE_FILE_MACHINE_M68K 0x0268 /* Motorola 68000 series */ +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 /* MIPS III with MIPS16 ASE Little-Endian */ +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 /* MIPS III with FPU Little-Endian */ +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 /* MIPS III with MIPS16 ASE and FPU Little-Endian */ +#define IMAGE_FILE_MACHINE_MPPC_601 0x0601 /* PowerPC 32-bit Big-Endian */ +#define IMAGE_FILE_MACHINE_OMNI 0xace1 /* Microsoft OMNI VM (omniprox.dll) */ +#define IMAGE_FILE_MACHINE_PARISC 0x0290 /* HP PA-RISC */ +#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 /* PowerPC 32-bit Little-Endian */ +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 /* PowerPC 32-bit with FPU Little-Endian */ +#define IMAGE_FILE_MACHINE_POWERPCBE 0x01f2 /* PowerPC 64-bit Big-Endian */ +#define IMAGE_FILE_MACHINE_R3000 0x0162 /* MIPS I Little-Endian */ +#define IMAGE_FILE_MACHINE_R3000_BE 0x0160 /* MIPS I Big-Endian */ +#define IMAGE_FILE_MACHINE_R4000 0x0166 /* MIPS III Little-Endian (with 1kB or 4kB page size) */ +#define IMAGE_FILE_MACHINE_R10000 0x0168 /* MIPS IV Little-Endian */ +#define IMAGE_FILE_MACHINE_RISCV32 0x5032 /* RISC-V 32-bit address space */ +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 /* RISC-V 64-bit address space */ +#define IMAGE_FILE_MACHINE_RISCV128 0x5128 /* RISC-V 128-bit address space */ +#define IMAGE_FILE_MACHINE_SH3 0x01a2 /* Hitachi SH-3 32-bit Little-Endian (with 1kB page size) */ +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 /* Hitachi SH-3 DSP 32-bit (with 1kB page size) */ +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 /* Hitachi SH-3E Little-Endian (with 1kB page size) */ +#define IMAGE_FILE_MACHINE_SH4 0x01a6 /* Hitachi SH-4 32-bit Little-Endian (with 1kB page size) */ +#define IMAGE_FILE_MACHINE_SH5 0x01a8 /* Hitachi SH-5 64-bit */ +#define IMAGE_FILE_MACHINE_TAHOE 0x07cc /* Intel EM machine */ +#define IMAGE_FILE_MACHINE_TRICORE 0x0520 /* Infineon AUDO 32-bit */ +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 /* MIPS Windows CE v2 Little-Endian */ + +/* flags */ +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* Relocation info stripped from file */ +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 /* File is executable (i.e. no unresolved external references) */ +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 /* Line nunbers stripped from file */ +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 /* Local symbols stripped from file */ +#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 /* Aggressively trim working set */ +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 /* App can handle >2gb addresses (image can be loaded at address above 2GB) */ +#define IMAGE_FILE_16BIT_MACHINE 0x0040 /* 16 bit word machine */ +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 /* Bytes of machine word are reversed (should be set together with IMAGE_FILE_BYTES_REVERSED_HI) */ +#define IMAGE_FILE_32BIT_MACHINE 0x0100 /* 32 bit word machine */ +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 /* Debugging info stripped from file in .DBG file */ +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 /* If Image is on removable media, copy and run from the swap file */ +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 /* If Image is on Net, copy and run from the swap file */ +#define IMAGE_FILE_SYSTEM 0x1000 /* System kernel-mode file (can't be loaded in user-mode) */ +#define IMAGE_FILE_DLL 0x2000 /* File is a DLL */ +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 /* File should only be run on a UP (uniprocessor) machine */ +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 /* Bytes of machine word are reversed (should be set together with IMAGE_FILE_BYTES_REVERSED_LO) */ + +/* subsys */ +#define IMAGE_SUBSYSTEM_UNKNOWN 0 /* Unknown subsystem */ +#define IMAGE_SUBSYSTEM_NATIVE 1 /* No subsystem required (NT device drivers and NT native system processes) */ +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows graphical user interface (GUI) subsystem */ +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows character-mode user interface (CUI) subsystem */ +#define IMAGE_SUBSYSTEM_WINDOWS_OLD_CE_GUI 4 /* Old Windows CE subsystem */ +#define IMAGE_SUBSYSTEM_OS2_CUI 5 /* OS/2 CUI subsystem */ +#define IMAGE_SUBSYSTEM_RESERVED_6 6 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 /* POSIX CUI subsystem */ +#define IMAGE_SUBSYSTEM_MMOSA 8 /* MMOSA/Native Win32E */ +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 /* Windows CE subsystem */ +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 /* Extensible Firmware Interface (EFI) application */ +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 /* EFI driver with boot services */ +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 /* EFI driver with run-time services */ +#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 /* EFI ROM image */ +#define IMAGE_SUBSYSTEM_XBOX 14 /* Xbox system */ +#define IMAGE_SUBSYSTEM_RESERVED_15 15 +#define IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 /* Windows Boot application */ +#define IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG 17 /* Xbox Code Catalog */ + +/* dll_flags */ +#define IMAGE_LIBRARY_PROCESS_INIT 0x0001 /* DLL initialization function called just after process initialization */ +#define IMAGE_LIBRARY_PROCESS_TERM 0x0002 /* DLL initialization function called just before process termination */ +#define IMAGE_LIBRARY_THREAD_INIT 0x0004 /* DLL initialization function called just after thread initialization */ +#define IMAGE_LIBRARY_THREAD_TERM 0x0008 /* DLL initialization function called just before thread initialization */ +#define IMAGE_DLLCHARACTERISTICS_RESERVED_4 0x0010 +#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 /* ASLR with 64 bit address space (image can be loaded at address above 4GB) */ +#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 /* The DLL can be relocated at load time */ +#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY 0x0080 /* Code integrity checks are forced */ +#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 /* Image is compatible with data execution prevention */ +#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 /* Image is isolation aware, but should not be isolated (prevents loading of manifest file) */ +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 /* Image does not use SEH, no SE handler may reside in this image */ +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 /* Do not bind the image */ +#define IMAGE_DLLCHARACTERISTICS_X86_THUNK 0x1000 /* Image is a Wx86 Thunk DLL (for non-x86/risc DLL files) */ +#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 /* Image should execute in an AppContainer (for EXE Metro Apps in Windows 8) */ +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 /* A WDM driver */ +#define IMAGE_DLLCHARACTERISTICS_GUARD_CF 0x4000 /* Image supports Control Flow Guard */ +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 /* The image is terminal server (Remote Desktop Services) aware */ + +/* IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS flags */ +#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001 /* Image is Control-flow Enforcement Technology Shadow Stack compatible */ +#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE 0x0002 /* CET is enforced in strict mode */ +#define IMAGE_DLLCHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE 0x0004 /* Relaxed mode for Context IP Validation under CET is allowed */ +#define IMAGE_DLLCHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC 0x0008 /* Use of dynamic APIs is restricted to processes only */ +#define IMAGE_DLLCHARACTERISTICS_EX_CET_RESERVED_1 0x0010 +#define IMAGE_DLLCHARACTERISTICS_EX_CET_RESERVED_2 0x0020 +#define IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040 /* All branch targets in all image code sections are annotated with forward-edge control flow integrity guard instructions */ +#define IMAGE_DLLCHARACTERISTICS_EX_HOTPATCH_COMPATIBLE 0x0080 /* Image can be modified while in use, hotpatch-compatible */ + +/* section_header flags */ +#define IMAGE_SCN_SCALE_INDEX 0x00000001 /* address of tls index is scaled = multiplied by 4 (for .tls section on MIPS only) */ +#define IMAGE_SCN_TYPE_NO_LOAD 0x00000002 /* reserved */ +#define IMAGE_SCN_TYPE_GROUPED 0x00000004 /* obsolete (used for 16-bit offset code) */ +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* .o only - don't pad - obsolete (same as IMAGE_SCN_ALIGN_1BYTES) */ +#define IMAGE_SCN_TYPE_COPY 0x00000010 /* reserved */ +#define IMAGE_SCN_CNT_CODE 0x00000020 /* .text */ +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* .data */ +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* .bss */ +#define IMAGE_SCN_LNK_OTHER 0x00000100 /* .o only - other type than code, data or info */ +#define IMAGE_SCN_LNK_INFO 0x00000200 /* .o only - .drectve comments */ +#define IMAGE_SCN_LNK_OVERLAY 0x00000400 /* section contains overlay */ +#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* .o only - scn to be rm'd*/ +#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* .o only - COMDAT data */ +#define IMAGE_SCN_RESERVED_13 0x00002000 /* spec omits this */ +#define IMAGE_SCN_MEM_PROTECTED 0x00004000 /* section is memory protected (for M68K) */ +#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 /* reset speculative exceptions handling bits in the TLB entries (for non-M68K) */ +#define IMAGE_SCN_MEM_FARDATA 0x00008000 /* section uses FAR_EXTERNAL relocations (for M68K) */ +#define IMAGE_SCN_GPREL 0x00008000 /* global pointer referenced data (for non-M68K) */ +#define IMAGE_SCN_MEM_SYSHEAP 0x00010000 /* use system heap (for M68K) */ +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 /* section can be released from RAM (for M68K) */ +#define IMAGE_SCN_MEM_16BIT 0x00020000 /* section is 16-bit (for non-M68K where it makes sense: I386, THUMB, MIPS16, MIPSFPU16, ...) */ +#define IMAGE_SCN_MEM_LOCKED 0x00040000 /* prevent the section from being moved (for M68K and .o I386) */ +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 /* section is preload to RAM (for M68K and .o I386) */ +/* and here they just stuck a 1-byte integer in the middle of a bitfield */ +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* .o only - it does what it says on the box */ +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000 +#define IMAGE_SCN_ALIGN_RESERVED 0x00f00000 +#define IMAGE_SCN_ALIGN_MASK 0x00f00000 +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* .o only - extended relocations */ +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 /* scn can be discarded */ +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* cannot be cached */ +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* not pageable */ +#define IMAGE_SCN_MEM_SHARED 0x10000000 /* can be shared */ +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 /* can be executed as code */ +#define IMAGE_SCN_MEM_READ 0x40000000 /* readable */ +#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */ + +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 /* Unknown value, ignored by all tools */ +#define IMAGE_DEBUG_TYPE_COFF 1 /* COFF debugging information */ +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 /* CodeView debugging information or Visual C++ Program Database debugging information */ +#define IMAGE_DEBUG_TYPE_FPO 3 /* Frame pointer omission (FPO) information */ +#define IMAGE_DEBUG_TYPE_MISC 4 /* Location of DBG file with CodeView debugging information */ +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 /* Exception information, copy of .pdata section */ +#define IMAGE_DEBUG_TYPE_FIXUP 6 /* Fixup information */ +#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 /* The mapping from an RVA in image to an RVA in source image */ +#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 /* The mapping from an RVA in source image to an RVA in image */ +#define IMAGE_DEBUG_TYPE_BORLAND 9 /* Borland debugging information */ +#define IMAGE_DEBUG_TYPE_RESERVED10 10 /* Coldpath / Hotpatch debug information */ +#define IMAGE_DEBUG_TYPE_CLSID 11 /* CLSID */ +#define IMAGE_DEBUG_TYPE_VC_FEATURE 12 /* Visual C++ counts / statistics */ +#define IMAGE_DEBUG_TYPE_POGO 13 /* COFF group information, data for profile-guided optimization */ +#define IMAGE_DEBUG_TYPE_ILTCG 14 /* Incremental link-time code generation */ +#define IMAGE_DEBUG_TYPE_MPX 15 /* Intel Memory Protection Extensions */ +#define IMAGE_DEBUG_TYPE_REPRO 16 /* PE determinism or reproducibility */ +#define IMAGE_DEBUG_TYPE_EMBEDDED_PORTABLE_PDB 17 /* Embedded Portable PDB debugging information */ +#define IMAGE_DEBUG_TYPE_SPGO 18 /* Sample profile-guided optimization */ +#define IMAGE_DEBUG_TYPE_PDBCHECKSUM 19 /* PDB Checksum */ +#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 /* Extended DLL characteristics bits */ +#define IMAGE_DEBUG_TYPE_PERFMAP 21 /* Location of associated Ready To Run PerfMap file */ \ No newline at end of file diff --git a/init/main.zig b/init/main.zig new file mode 100644 index 0000000..4c04715 --- /dev/null +++ b/init/main.zig @@ -0,0 +1,4 @@ +export fn kernel_start() noreturn { + while (true) {} + +} \ No newline at end of file diff --git a/kernel/build.zig b/kernel/build.zig new file mode 100644 index 0000000..e2eeb12 --- /dev/null +++ b/kernel/build.zig @@ -0,0 +1,32 @@ +const std = @import("std"); + +pub fn buildKernelBin(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { + const kernel = b.addExecutable(.{ + .name = "kernel.bin", + .use_llvm = true, + .use_lld = true, + .root_module = b.createModule(.{ + .root_source_file = b.path("init/main.zig"), + .target = target, + .optimize = optimize, + .code_model = .kernel, + }), + }); + switch (target.result.cpu.arch) { + .x86_64 => { + kernel.setLinkerScript(b.path("arch/x86/kernel_bin.ld")); + }, + else => { + @panic("target architecture unsupported"); + } + } + kernel.entry = .{ + .symbol_name = "kernel_start", + }; + kernel.link_gc_sections = false; + return kernel; +} + +pub fn buildKernelBinInstall(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.InstallArtifact { + return b.addInstallArtifact(buildKernelBin(b, target, optimize), .{}); +} \ No newline at end of file diff --git a/tools/build_img.sh b/tools/build_img.sh new file mode 100644 index 0000000..fde120b --- /dev/null +++ b/tools/build_img.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -e + +IMG=disk.img +SIZE=256M +MNT=/tmp/$(tr -dc 'A-Za-z0-9' /dev/null << 'EOF' +timeout: 1 + +/Yuki OS + protocol: efi + path: boot():/boot/yukiImage +EOF + +echo "[*] Syncing..." +sync + +echo "[*] Unmounting..." +sudo umount "$MNT" +sudo losetup -d "$LOOP" + +echo "[+] Done: $IMG created successfully" \ No newline at end of file