1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
const std = @import("std");
// the gils coreutils
const gils_tools = .{ "gils", "ls", "tree", "cat", "rm", "mkdir", "touch", "cp", "mv", "wc", "head", "tail", "ed" };
pub fn build(b: *std.Build) void {
// Default to ReleaseSafe because Debug pulls Zig's UBSan runtime and other
// sanitization, which needs f128/SSE ops, which i don't provide.
const optimize = b.option(std.builtin.OptimizeMode, "optimize", "optimize mode") orelse .safe;
// The kernel must NOT touch SSE/MMX/AVX until it has enabled them itself, so
// I strip those features and let the compiler use a soft-float ABI
// `code_model = .kernel` keeps relocations valid for the higher-half load
// address in boot/linker.ld.
//
// In other words. Going raw baby
var query: std.Target.Query = .{
.cpu_arch = .x86_64,
.os_tag = .freestanding,
.abi = .none,
};
const Feature = std.Target.x86.Feature;
query.cpu_features_sub.addFeature(@backingInt(Feature.mmx));
query.cpu_features_sub.addFeature(@backingInt(Feature.avx));
query.cpu_features_sub.addFeature(@backingInt(Feature.avx2));
const target = b.resolveTargetQuery(query);
const kernel = b.addExecutable(.{
.name = "revel",
.root_module = b.createModule(.{
.root_source_file = b.path("boot/boot.zig"),
.target = target,
.optimize = optimize,
.code_model = .kernel,
.red_zone = false,
.single_threaded = true,
.link_libc = false,
}),
});
kernel.entry = .{ .symbol_name = "_start" };
kernel.pie = false;
kernel.setLinkerScript(b.path("boot/linker.ld"));
// the big guns
const revo_dep = b.dependency("revo", .{
.target = target,
.optimize = optimize,
.features = "regex",
});
const revo_mod = revo_dep.module("revo");
var visited: std.AutoHashMap(*std.Build.Module, void) = .init(b.allocator);
defer visited.deinit();
kernelize(revo_mod, &visited);
// the thin guns
const bridge_mod = b.createModule(.{
.root_source_file = b.path("bridge/bridge.zig"),
.target = target,
.optimize = optimize,
.code_model = .kernel,
.red_zone = false,
.single_threaded = true,
.link_libc = false,
});
bridge_mod.addImport("revo", revo_mod);
inline for (.{
.{ "k_font", "kernel/font.rv" },
.{ "k_console", "kernel/console.rv" },
.{ "k_vmm", "kernel/vmm.rv" },
.{ "k_fs", "kernel/fs.rv" },
.{ "k_io", "kernel/io.rv" },
.{ "k_vfs", "kernel/vfs.rv" },
.{ "k_seed", "kernel/seed.rv" },
.{ "k_proc", "kernel/proc.rv" },
.{ "k_ttf", "kernel/ttf.rv" },
.{ "k_shell", "kernel/shell.rv" },
.{ "k_tty", "kernel/tty.rv" },
.{ "k_input", "kernel/input.rv" },
.{ "k_main", "kernel/main.rv" },
}) |e| {
bridge_mod.addAnonymousImport(e[0], .{ .root_source_file = b.path(e[1]) });
}
// load gils
inline for (gils_tools) |g| {
bridge_mod.addAnonymousImport("k_gils_" ++ g, .{ .root_source_file = b.path("gils/" ++ g ++ ".rv") });
}
// /etc/ bullshit
inline for (.{ "motd", "profile", "lung" }) |name| {
bridge_mod.addAnonymousImport("k_etc_" ++ name, .{ .root_source_file = b.path("etc/" ++ name) });
}
kernel.root_module.addImport("bridge", bridge_mod);
inline for (.{
.{ "font_vga16", "fonts/vga16.psf" },
.{ "font_vga8", "fonts/vga8.psf" },
.{ "font_sun16", "fonts/sun16.psf" },
.{ "font_acorn8", "fonts/acorn8.psf" },
.{ "font_pearl8", "fonts/pearl8.psf" },
.{ "font_dejavu", "fonts/dejavu.ttf" },
.{ "font_terminess", "fonts/terminess.ttf" },
}) |e| {
kernel.root_module.addAnonymousImport(e[0], .{ .root_source_file = b.path(e[1]) });
}
inline for (.{ "hexview", "calc", "primes", "save", "chat", "membrk" }) |prog| {
const cc = b.addSystemCommand(&.{
"zig", "cc",
"-target", "x86_64-freestanding",
"-ffreestanding", "-nostdlib",
"-static", "-no-pie",
"-fno-stack-protector", "-fno-sanitize=all",
"-Wall", "-Wextra",
"-Werror", "-Wpedantic",
"-Wl,-T,user/link.ld", "-Wl,--build-id=none",
"-o",
});
const prog_elf = cc.addOutputFileArg(prog ++ ".elf");
cc.addFileArg(b.path("user/" ++ prog ++ ".c"));
cc.addFileInput(b.path("user/user.h"));
cc.addFileInput(b.path("user/link.ld"));
kernel.root_module.addAnonymousImport("user_" ++ prog, .{ .root_source_file = prog_elf });
}
b.installArtifact(kernel);
}
// force a module and everything it imports to the kernel's codegen settings
fn kernelize(mod: *std.Build.Module, visited: *std.AutoHashMap(*std.Build.Module, void)) void {
if (visited.contains(mod)) return;
visited.put(mod, {}) catch @panic("OOM building module graph");
mod.code_model = .kernel;
mod.red_zone = false;
mod.single_threaded = true;
var it = mod.import_table.iterator();
while (it.next()) |entry| kernelize(entry.value_ptr.*, visited);
}
|