mirror of
https://gitlab.com/bztsrc/bootboot.git
synced 2023-02-13 20:54:32 -05:00
Merge branch 'master' into 'master'
Zig kernel example See merge request bztsrc/bootboot!14
This commit is contained in:
commit
6ce3a4a2a8
7 changed files with 384 additions and 1 deletions
|
@ -13,4 +13,4 @@ Compilation
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
In the language's directory, just run `make`. You'll need `gcc`, `g++`, `gnat` (GNU Ada), `fpc` (FreePascal
|
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`.
|
||||||
|
|
36
mykernel/zig/Makefile
Normal file
36
mykernel/zig/Makefile
Normal file
|
@ -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
|
18
mykernel/zig/build.zig
Normal file
18
mykernel/zig/build.zig
Normal file
|
@ -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;
|
||||||
|
}
|
123
mykernel/zig/src/bootboot.zig
Normal file
123
mykernel/zig/src/bootboot.zig
Normal file
|
@ -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),
|
||||||
|
};
|
BIN
mykernel/zig/src/font.psf
Normal file
BIN
mykernel/zig/src/font.psf
Normal file
Binary file not shown.
57
mykernel/zig/src/link.ld
Normal file
57
mykernel/zig/src/link.ld
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* mykernel/c/link.ld
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
|
||||||
|
*
|
||||||
|
* 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 linker script for sample kernel
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
mmio = 0xfffffffff8000000; /* these are configurable for level 2 loaders */
|
||||||
|
fb = 0xfffffffffc000000;
|
||||||
|
bootboot = 0xffffffffffe00000;
|
||||||
|
environment = 0xffffffffffe01000;
|
||||||
|
/* initstack = 1024; */
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
boot PT_LOAD; /* one single loadable segment */
|
||||||
|
}
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0xffffffffffe02000;
|
||||||
|
.text : {
|
||||||
|
KEEP(*(.text.boot)) *(.text .text.*) /* code */
|
||||||
|
*(.rodata .rodata.*) /* data */
|
||||||
|
*(.data .data.*)
|
||||||
|
} :boot
|
||||||
|
.bss (NOLOAD) : { /* bss */
|
||||||
|
. = ALIGN(16);
|
||||||
|
*(.bss .bss.*)
|
||||||
|
*(COMMON)
|
||||||
|
} :boot
|
||||||
|
|
||||||
|
/DISCARD/ : { *(.eh_frame) *(.comment) }
|
||||||
|
}
|
149
mykernel/zig/src/main.zig
Normal file
149
mykernel/zig/src/main.zig
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/// mykernel/zig/src/main.zig
|
||||||
|
///
|
||||||
|
/// 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 A sample BOOTBOOT compatible kernel
|
||||||
|
const std = @import("std");
|
||||||
|
const BOOTBOOT = @import("bootboot.zig").BOOTBOOT;
|
||||||
|
|
||||||
|
const fontEmbedded = @embedFile("font.psf");
|
||||||
|
|
||||||
|
// imported virtual addresses, see linker script
|
||||||
|
extern var bootboot: BOOTBOOT; // see bootboot.zig
|
||||||
|
extern var environment: [4096]u8; // configuration, UTF-8 text key=value pairs
|
||||||
|
extern var fb: u8; // linear framebuffer mapped
|
||||||
|
|
||||||
|
// Display text on screen
|
||||||
|
const PsfFont = packed struct {
|
||||||
|
magic: u32, // magic bytes to identify PSF
|
||||||
|
version: u32, // zero
|
||||||
|
headersize: u32, // offset of bitmaps in file, 32
|
||||||
|
flags: u32, // 0 if there's no unicode table
|
||||||
|
numglyph: u32, // number of glyphs
|
||||||
|
bytesperglyph: u32, // size of each glyph
|
||||||
|
height: u32, // height in pixels
|
||||||
|
width: u32, // width in pixels
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to display a string
|
||||||
|
pub fn puts(string: []const u8) void {
|
||||||
|
const font = @bitCast(PsfFont, fontEmbedded[0..@sizeOf(PsfFont)].*);
|
||||||
|
var bytesperline = (font.width + 7) / 8;
|
||||||
|
var framebuffer = @intToPtr([*]u32, @ptrToInt(&fb));
|
||||||
|
for (string) |char, i| {
|
||||||
|
var offs = i * (font.width + 1) * 4;
|
||||||
|
var idx = if (char > 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) {}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue