From 33e59feaf42745de6e246007bd5b0d0005004e00 Mon Sep 17 00:00:00 2001 From: Binary Craft Date: Thu, 12 Jan 2023 09:55:11 +0800 Subject: [PATCH 1/2] Zig kernel example --- mykernel/README.md | 2 +- mykernel/zig/Makefile | 36 ++++++++ mykernel/zig/build.zig | 18 ++++ mykernel/zig/src/bootboot.zig | 123 ++++++++++++++++++++++++++++ mykernel/zig/src/font.psf | Bin 0 -> 2080 bytes mykernel/zig/src/link.ld | 57 +++++++++++++ mykernel/zig/src/main.zig | 149 ++++++++++++++++++++++++++++++++++ 7 files changed, 384 insertions(+), 1 deletion(-) create mode 100644 mykernel/zig/Makefile create mode 100644 mykernel/zig/build.zig create mode 100644 mykernel/zig/src/bootboot.zig create mode 100644 mykernel/zig/src/font.psf create mode 100644 mykernel/zig/src/link.ld create mode 100644 mykernel/zig/src/main.zig diff --git a/mykernel/README.md b/mykernel/README.md index 14bec04..186ea35 100644 --- a/mykernel/README.md +++ b/mykernel/README.md @@ -13,4 +13,4 @@ Compilation ----------- In the language's directory, just run `make`. You'll need `gcc`, `g++`, `gnat` (GNU Ada), `fpc` (FreePascal -Compiler), `cargo` + `rust`, and `gccgo` (GNU go-lang compiler, NOT the official go-lang compiler!). +Compiler), `cargo` + `rust` + `gccgo` (GNU go-lang compiler, NOT the official go-lang compiler!), and `zig`. diff --git a/mykernel/zig/Makefile b/mykernel/zig/Makefile new file mode 100644 index 0000000..658d272 --- /dev/null +++ b/mykernel/zig/Makefile @@ -0,0 +1,36 @@ +# +# mykernel/zig/Makefile +# +# Copyright (C) 2022 binarycraft +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, copy, +# modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# This file is part of the BOOTBOOT Protocol package. +# @brief An example Makefile for sample kernel +# +# + +all: mykernel.x86_64.elf + +# Kernel build +mykernel.x86_64.elf: src/** + zig build -Drelease-fast + cp ./zig-out/bin/mykernel.x86_64.elf mykernel.x86_64.elf diff --git a/mykernel/zig/build.zig b/mykernel/zig/build.zig new file mode 100644 index 0000000..db615e3 --- /dev/null +++ b/mykernel/zig/build.zig @@ -0,0 +1,18 @@ +const std = @import("std"); + +pub fn build(b: *std.build.Builder) void { + var target = std.zig.CrossTarget{ + .os_tag = .freestanding, + .cpu_arch = .x86_64, + .abi = .none, + }; + + const mode = b.standardReleaseOptions(); + const kernel = b.addExecutable("mykernel.x86_64.elf", "src/main.zig"); + kernel.setLinkerScriptPath(.{ .path = "src/link.ld" }); + kernel.code_model = .kernel; + kernel.setTarget(target); + kernel.setBuildMode(mode); + kernel.install(); + kernel.strip = true; +} diff --git a/mykernel/zig/src/bootboot.zig b/mykernel/zig/src/bootboot.zig new file mode 100644 index 0000000..f0cb4ae --- /dev/null +++ b/mykernel/zig/src/bootboot.zig @@ -0,0 +1,123 @@ +pub const BOOTBOOT_MAGIC = "BOOT"; + +// default virtual addresses for level 0 and 1 static loaders +pub const BOOTBOOT_MMIO = 0xfffffffff8000000; // memory mapped IO virtual address +pub const BOOTBOOT_FB = 0xfffffffffc000000; // frame buffer virtual address +pub const BOOTBOOT_INFO = 0xffffffffffe00000; // bootboot struct virtual address +pub const BOOTBOOT_ENV = 0xffffffffffe01000; // environment string virtual address +pub const BOOTBOOT_CORE = 0xffffffffffe02000; // core loadable segment start + +// minimum protocol level: +// hardcoded kernel name, static kernel memory addresses +pub const PROTOCOL_MINIMAL = 0; +// static protocol level: +// kernel name parsed from environment, static kernel memory addresses +pub const PROTOCOL_STATIC = 1; +// dynamic protocol level: +// kernel name parsed, kernel memory addresses from ELF or PE symbols +pub const PROTOCOL_DYNAMIC = 2; +// big-endian flag +pub const PROTOCOL_BIGENDIAN = 0x80; + +// loader types, just informational +pub const LOADER_BIOS = 0 << 2; +pub const LOADER_UEFI = 1 << 2; +pub const LOADER_RPI = 2 << 2; +pub const LOADER_COREBOOT = 3 << 2; + +// framebuffer pixel format, only 32 bits supported +pub const FramebufferFormat = enum(u8) { + ARGB = 0, + RGBA = 1, + ABGR = 2, + BGRA = 3, +}; + +// mmap entry, type is stored in least significant tetrad (half byte) of size +// this means size described in 16 byte units (not a problem, most modern +// firmware report memory in pages, 4096 byte units anyway). +pub const MMapEnt = extern struct { + ptr: u64 align(1), + size: u64 align(1), + + const Self = @This(); + + pub inline fn getPtr(self: *Self) u64 { + return self.ptr; + } + + pub inline fn getSizeInBytes(self: *Self) u64 { + return self.size & 0xFFFFFFFFFFFFFFF0; + } + + pub inline fn getSizeIn4KiBPages(self: *Self) u64 { + return self.getSizeInBytes() / 4096; + } + + pub inline fn getType(self: *Self) MMapType { + return @intToEnum(MMapType, @truncate(u4, self.size)); + } + + pub inline fn isFree(self: *Self) bool { + return (self.size & 0xF) == 1; + } +}; + +pub const MMapType = enum(u4) { + /// don't use. Reserved or unknown regions + MMAP_USED = 0, + + /// usable memory + MMAP_FREE = 1, + + /// acpi memory, volatile and non-volatile as well + MMAP_ACPI = 2, + + /// memory mapped IO region + MMAP_MMIO = 3, +}; + +pub const INITRD_MAXSIZE = 16; // Mb + +pub const BOOTBOOT = extern struct { + magic: [4]u8 align(1), + size: u32 align(1), + protocol: u8 align(1), + fb_type: u8 align(1), + numcores: u16 align(1), + bspid: u16 align(1), + timezone: i16 align(1), + datetime: [8]u8 align(1), + initrd_ptr: u64 align(1), + initrd_size: u64 align(1), + fb_ptr: u64 align(1), + fb_size: u32 align(1), + fb_width: u32 align(1), + fb_height: u32 align(1), + fb_scanline: u32 align(1), + + arch: extern union { + x86_64: extern struct { + acpi_ptr: u64, + smbi_ptr: u64, + efi_ptr: u64, + mp_ptr: u64, + unused0: u64, + unused1: u64, + unused2: u64, + unused3: u64, + }, + aarch64: extern struct { + acpi_ptr: u64, + mmio_ptr: u64, + efi_ptr: u64, + unused0: u64, + unused1: u64, + unused2: u64, + unused3: u64, + unused4: u64, + }, + } align(1), + + mmap: MMapEnt align(1), +}; diff --git a/mykernel/zig/src/font.psf b/mykernel/zig/src/font.psf new file mode 100644 index 0000000000000000000000000000000000000000..3e67693f59d769c6453826ed9012a09818a9b9af GIT binary patch literal 2080 zcmZuyJ!>0D7#>_KR}4bsa4{l9ij>P897`AyNSU9IYDvN-#T4cWA-F-duJC{G54fL@ zbcRKSsZ2^0kr1w|CInT73$wcC{TS^A?#0^Ocb@nAWBljmHB10uHuk&-tTrh=e)ws&!OD& zIEIK5^uV;cAqPZ!>YLZE8&T)Oo2%>Vs~g29qhEiU-GXLf!8ai9;6V6SzrQL$XZt(h z&)=WF2YuY#w{qaz+VA{Y-GAtCq&H0R97LTP}vkkfS*({VNnjTr}Y#bM;bqUfqI81m+h>gY@@8Zx*QlcZQH7K zK7Ag#@Vv*zRTX1)k7G11R(<<=LH8K`*G8P>6EwU3UbcBQLcDrdc zzA+V~qku&I5fcz;;va?g%@P^5OI=X&5D09V@E~~Cy!$l!RKIJqUdq??exScisd*th zd180!kA{!Q3qIj#==c2|u4Xehy%&66Gadb4RA`6UDj_MD1UD@KOKcBz-DPA(or1q5ydEtm(tybNSpz)=EZHy?o@Kj5#f#%<( zOKRRS&!3ldDNDr-Zm_fJ^mt!+Ss!Z|r*4Yf|9RrJEz9A>qB1iZkNaxw>YA#JAvjuy z2?LPpcM4Ad;=11?6cd&p<5l=jbC0yXz^5dB8!cbqupg#mU+as}tcLwB3NykwfKV4G zLtX|z 0 and char < font.numglyph) blk: { + break :blk font.headersize + (char * font.bytesperglyph); + } else blk: { + break :blk font.headersize + (0 * font.bytesperglyph); + }; + + { + var y: usize = 0; + while (y < font.height) : (y += 1) { + var line = offs; + var mask = @as(u32, 1) << @intCast(u5, font.width - 1); + + { + var x: usize = 0; + while (x < font.width) : (x += 1) { + if ((fontEmbedded[idx] & mask) == 0) { + framebuffer[line / @sizeOf(u32)] = 0x000000; + } else { + framebuffer[line / @sizeOf(u32)] = 0xFFFFFF; + } + mask >>= 1; + line += 4; + } + } + + framebuffer[line / @sizeOf(u32)] = 0; + idx += bytesperline; + offs += bootboot.fb_scanline; + } + } + } +} + +// Entry point, called by BOOTBOOT Loader +export fn _start() callconv(.Naked) noreturn { + // NOTE: this code runs on all cores in parallel + var s = bootboot.fb_scanline; + var w = bootboot.fb_width; + var h = bootboot.fb_height; + var framebuffer = @intToPtr([*]u32, @ptrToInt(&fb)); + + if (s > 0) { + // cross-hair to see screen dimension detected correctly + { + var y: usize = 0; + while (y < h) : (y += 1) { + framebuffer[(s * y + w * 2) / @sizeOf(u32)] = 0x00FFFFFF; + } + } + + { + var x: usize = 0; + while (x < w) : (x += 1) { + framebuffer[(s * (h / 2) + x * 4) / @sizeOf(u32)] = 0x00FFFFFF; + } + } + + // red, green, blue boxes in order + { + var y: usize = 0; + while (y < 20) : (y += 1) { + var x: usize = 0; + while (x < 20) : (x += 1) { + framebuffer[(s * (y + 20) + (x + 20) * 4) / @sizeOf(u32)] = 0x00FF0000; + } + } + } + + { + var y: usize = 0; + while (y < 20) : (y += 1) { + var x: usize = 0; + while (x < 20) : (x += 1) { + framebuffer[(s * (y + 20) + (x + 50) * 4) / @sizeOf(u32)] = 0x0000FF00; + } + } + } + + { + var y: usize = 0; + while (y < 20) : (y += 1) { + var x: usize = 0; + while (x < 20) : (x += 1) { + framebuffer[(s * (y + 20) + (x + 80) * 4) / @sizeOf(u32)] = 0x000000FF; + } + } + } + + // say hello + puts("Hello from a simple BOOTBOOT kernel"); + } + // hang for now + while (true) {} +} From d6845611e003a5b6324a0b0c4e3a2b011cf4bbe8 Mon Sep 17 00:00:00 2001 From: Binary Craft Date: Thu, 12 Jan 2023 10:05:58 +0800 Subject: [PATCH 2/2] fixed readme formating --- mykernel/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mykernel/README.md b/mykernel/README.md index 186ea35..286bebf 100644 --- a/mykernel/README.md +++ b/mykernel/README.md @@ -13,4 +13,4 @@ Compilation ----------- In the language's directory, just run `make`. You'll need `gcc`, `g++`, `gnat` (GNU Ada), `fpc` (FreePascal -Compiler), `cargo` + `rust` + `gccgo` (GNU go-lang compiler, NOT the official go-lang compiler!), and `zig`. +Compiler), `cargo` + `rust`, `gccgo` (GNU go-lang compiler, NOT the official go-lang compiler!), and `zig`.