45 Commits
Author SHA1 Message Date
josh c3ead56582 Add Framebuffer object 2022-03-21 16:32:11 -04:00
josh 15559b0a56 Add HULK header; map virtual memory for HULK bss section 2022-03-21 16:31:01 -04:00
josh c58284761a Comment hulk.hulk module a bit 2022-03-20 23:05:10 -04:00
josh bd99e429a9 Comment hulk.bootinfo a bit 2022-03-20 22:58:25 -04:00
josh d0acf5a718 Comment hello.hello module a bit better 2022-03-20 22:38:42 -04:00
josh b40151055c Rework scratch module and use qualified names for function calls 2022-03-20 22:21:10 -04:00
josh 1e00d7a9e9 Rename hello.output to hello.console 2022-03-20 22:12:46 -04:00
josh 79b34477ed Reorganize D modules a bit 2022-03-19 22:39:12 -04:00
josh 163ef9f79e Increase scratch buffer size 2022-03-19 22:08:35 -04:00
josh 3c549f0838 Write size file for HULK/HELLO 2022-03-19 22:07:37 -04:00
josh d8c85ad045 Map all memory regions and graphics framebuffer 2022-03-19 21:54:30 -04:00
josh 7c5af33ace Fix receiving correct argument to hulk_start() 2022-03-19 20:02:49 -04:00
josh 6f3521c576 Make sure to rebuild HELLO properly when HULK changes 2022-03-19 00:27:10 -04:00
josh 5a5d60abae Fix HULK virtual start address to be addressable 2022-03-19 00:04:59 -04:00
josh 9182a83ef2 HELLO: Make sure scratch area is page-aligned 2022-03-18 23:43:05 -04:00
josh 195b7496f4 HELLO: Include EfiLoaderCode and EfiLoaderData memory regions in memory map 2022-03-18 23:33:42 -04:00
josh b1042fd649 Jump to HULK
Unfortunately, crashes... :(
2022-03-18 23:16:07 -04:00
josh 6beb7da4cd Map HULK virtual address space 2022-03-18 23:04:09 -04:00
josh f27851def9 Bundle HULK in HELLO 2022-03-18 22:43:37 -04:00
josh 18f1bfc88f Build HELLO after HULK 2022-03-18 22:02:07 -04:00
josh cd6983e2cd Generate HULK binary 2022-03-18 22:01:27 -04:00
josh 8df1646c61 Add initial HULK source and linker script 2022-03-18 21:55:38 -04:00
josh 3e25ab6ae4 HELLO: Zero out page tables after allocating, before using 2022-03-18 21:21:00 -04:00
josh 05cc2da2e3 HULK: Add virtual start address 2022-03-18 21:19:06 -04:00
josh a54536660b HELLO: Create page tables to identity map available RAM prior to jumping to kernel 2022-03-18 21:15:58 -04:00
josh 9e3d9b18ea Add write_cr3() 2022-03-18 16:40:46 -04:00
josh ef01239468 HELLO: Add scratch module 2022-03-18 16:03:50 -04:00
josh 372b7265f1 Add src/common/hos/cpu.d 2022-03-18 10:51:35 -04:00
josh 1bc8722098 Add hos.memory module in src/common 2022-03-18 00:07:10 -04:00
josh cd2f3f9a84 Rename kernel to hulk 2022-03-17 16:57:18 -04:00
josh 08a35e40d4 Rename HEL -> HELLO 2022-03-16 16:11:26 -04:00
josh a855702214 Fix checking for EFI_INVALID_PARAMETER 2022-03-16 14:37:46 -04:00
josh 706f2c1c5d HEL: Call ExitBootServices 2022-03-16 01:12:07 -04:00
josh 704fd15f7b Get memory map; remove heap 2022-03-15 23:58:37 -04:00
josh f054bab5cc Set bootinfo framebuffer fields 2022-03-15 23:03:28 -04:00
josh 3fa8e4a24b Set maximum resolution for running in qemu 2022-03-15 22:52:56 -04:00
josh a38f95a7b8 Set graphics mode 2022-03-14 22:26:55 -04:00
josh dd57a31d38 HEL: Add heap module; locate GOP handle 2022-03-14 21:43:40 -04:00
josh 406f17c1db HEL: format hex, decimal, and CHAR16 strings in output module 2022-03-14 15:09:02 -04:00
josh 0be1b113aa Add output module for console output routines 2022-03-14 13:53:02 -04:00
josh d782b59768 Write map file 2022-03-14 01:35:28 -04:00
josh c3a6139f83 Run image from temporary copy to avoid modified disk image file 2022-03-14 00:57:24 -04:00
josh 3d3a433800 Update to rscons 3.0.2 2022-03-14 00:51:54 -04:00
josh 54451bcf5b Add initial HOS EFI Loader sources 2022-03-13 23:16:37 -04:00
josh 1fc2dd34e5 Update build system for 64-bit, EFI, and D 2022-03-13 22:46:59 -04:00
41 changed files with 976 additions and 135 deletions

No files matched your search

+1 -1
View File
@@ -1,3 +1,3 @@
.rscons* .rscons*
/i686-elf-gcc/ /x86_64-elf-gcc/
/build/ /build/
+3
View File
@@ -0,0 +1,3 @@
[submodule "uefi-d"]
path = uefi-d
url = git://github.com/kubasz/uefi-d
+84 -125
View File
@@ -1,98 +1,52 @@
path_prepend "i686-elf-gcc/bin"
configure do
rscons "i686-elf-gcc.rb", "-b", "#{build_dir}/i686-elf-gcc"
check_c_compiler "i686-elf-gcc"
check_program "genext2fs"
check_program "grub-mkstandalone"
check_program "mformat", on_fail: "Install the mtools package"
check_program "xorriso"
check_cfg package: "freetype2", on_fail: "Install libfreetype-dev", use: "freetype"
end
require "tmpdir" require "tmpdir"
# EFI (w/ GRUB) partition size (MiB) project_name "HOS"
EFI_PART_SIZE = 8 path_prepend "x86_64-elf-gcc/bin"
# HOS partition size (MiB)
HOS_PART_SIZE = 4 configure do
# Kernel default font size rscons "x86_64-elf-gcc.rb", "-b", "#{build_dir}/x86_64-elf-gcc"
check_d_compiler "ldc2", use: "ldc2"
check_c_compiler "x86_64-w64-mingw32-gcc", use: "x86_64-w64-mingw32-gcc"
check_c_compiler "x86_64-elf-gcc", use: "x86_64-elf-gcc"
check_c_compiler
check_program "mformat", on_fail: "Install the mtools package"
check_cfg package: "freetype2", on_fail: "Install libfreetype-dev", use: "freetype"
sh %w[git submodule update --init]
end
# Kernel default font size.
KFONT_SIZE = 15 KFONT_SIZE = 15
class BiosImage < Builder class HulkBinObj < Builder
def run(options) def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env) FileUtils.mkdir_p(File.dirname(@target))
print_run_message("Generating BIOS boot image #{@target}", nil) File.write(@target, <<EOF)
Dir.mktmpdir do |tmpdir| .section ".rodata"
# Create iso directory. .balign 4096
FileUtils.mkdir_p("#{tmpdir}/iso/boot/grub") .global hulk_bin_start
File.open("#{tmpdir}/iso/boot/grub/grub.cfg", "wb") do |fh| hulk_bin_start:
fh.write(<<EOF) .incbin "#{@sources.first}"
set default="0" .balign 4096
set timeout=1 .global hulk_bin_end
menuentry "HOS" { hulk_bin_end:
insmod multiboot2
multiboot2 /hos.elf
}
EOF EOF
end unless @cache.up_to_date?(@target, nil, @sources, @env)
@sources.each do |source| print_run_message("Creating HULK binary object <target>#{@target}<reset>", nil)
FileUtils.cp(source, "#{tmpdir}/iso")
end
# Build bootable GRUB image.
system(*%W[grub-mkrescue -o #{@target} #{tmpdir}/iso], err: "#{@env.build_root}/grub-mkrescue.log")
end
@cache.register_build(@target, nil, @sources, @env) @cache.register_build(@target, nil, @sources, @env)
end end
true true
end end
end end
class EfiImage < Builder class Image < Builder
def run(options) def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env) unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Generating EFI boot image #{@target}", nil) print_run_message("Creating disk image <target>#{@target}<reset>", nil)
Dir.mktmpdir do |tmpdir| File.binwrite(@target, "\0" * (1440 * 1024))
# Build a standalone GRUB. system(*%W[mformat -i #{@target} -f 1440 ::])
File.open("#{tmpdir}/grub.cfg", "wb") do |fh| system(*%W[mmd -i #{@target} ::/EFI])
fh.write(<<EOF) system(*%W[mmd -i #{@target} ::/EFI/BOOT])
insmod part_gpt system(*%W[mcopy -i #{@target} #{@sources.first} ::/EFI/BOOT])
configfile (hd0,gpt2)/grub.cfg
EOF
end
system(*%W[grub-mkstandalone -O x86_64-efi -o #{tmpdir}/BOOTX64.EFI boot/grub/grub.cfg=#{tmpdir}/grub.cfg])
# Create EFI partition.
system(*%W[dd if=/dev/zero of=#{tmpdir}/efi.part bs=1M count=#{EFI_PART_SIZE}], err: "/dev/null")
system(*%W[mformat -i #{tmpdir}/efi.part ::])
system(*%W[mmd -i #{tmpdir}/efi.part ::/EFI])
system(*%W[mmd -i #{tmpdir}/efi.part ::/EFI/BOOT])
system(*%W[mcopy -i #{tmpdir}/efi.part #{tmpdir}/BOOTX64.EFI ::/EFI/BOOT])
# Create ext2 HOS partition.
FileUtils.mkdir_p("#{tmpdir}/ext2")
@sources.each do |source|
FileUtils.cp(source, "#{tmpdir}/ext2")
end
File.open("#{tmpdir}/ext2/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
set default="0"
set timeout=1
menuentry "HOS" {
insmod part_gpt
insmod multiboot2
set root=(hd0,gpt2)
multiboot2 /hos.elf
}
EOF
end
system(*%W[genext2fs -b #{HOS_PART_SIZE * 1024} -d #{tmpdir}/ext2 #{tmpdir}/ext2.part])
# Create full disk image.
system(*%W[dd if=/dev/zero of=#{@target} bs=1M count=#{EFI_PART_SIZE + HOS_PART_SIZE + 2}], err: "/dev/null")
system(*%W[parted -s #{@target} mklabel gpt])
system(*%W[parted -s #{@target} mkpart efi 1MiB #{EFI_PART_SIZE + 1}MiB])
system(*%W[parted -s #{@target} mkpart hos #{EFI_PART_SIZE + 1}MiB #{EFI_PART_SIZE + HOS_PART_SIZE + 1}MiB])
system(*%W[dd if=#{tmpdir}/efi.part of=#{@target} bs=1M seek=1 conv=notrunc], err: "/dev/null")
system(*%W[dd if=#{tmpdir}/ext2.part of=#{@target} bs=1M seek=#{1 + EFI_PART_SIZE} conv=notrunc], err: "/dev/null")
end
@cache.register_build(@target, nil, @sources, @env) @cache.register_build(@target, nil, @sources, @env)
end end
true true
@@ -112,55 +66,60 @@ class FontGen < Builder
end end
end end
class Size < Builder fontgen_env = env "fontgen", use: "freetype" do |env|
def run(options) env.Program("^/fontgen", glob("src/fontgen/**/*.c"))
if @command end
finalize_command
else hulk_env = env "hulk", use: %w[ldc2 x86_64-elf-gcc] do |env|
@vars["_SOURCES"] = @sources env["sources"] = glob("src/hulk/**/*.d")
@vars["_TARGET"] = @target env["DFLAGS"] += %w[-mtriple=x86_64-unknown-elf --betterC -release -O3 --wi --enable-cross-module-inlining]
command = @env.build_command(%w[${SIZE} ${_SOURCES}], @vars) env["D_IMPORT_PATH"] += %w[src]
standard_command("Size <target>#{@target}<reset>", command, stdout: @target) env["LD"] = "x86_64-elf-gcc"
env["LDFLAGS"] += %w[-nostdlib -Tsrc/hulk/hulk.ld -Wl,-Map,${_TARGET}.map]
env["LDCMD"] = %w[${LD} -o ${_TARGET} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}]
env["OBJDUMP"] = "x86_64-elf-objdump"
env["OBJCOPY"] = "x86_64-elf-objcopy"
env.Program("^/hulk.elf", "${sources}")
env.depends("^/hulk.elf", "src/hulk/hulk.ld")
env["SIZE"] = "x86_64-elf-size"
env.Size("^/hulk.size", "^/hulk.elf")
env.Disassemble("^/hulk.txt", "^/hulk.elf")
env.Command("^/hulk.bin", "^/hulk.elf",
"CMD" => %W[${OBJCOPY} -O binary ${_SOURCES} ${_TARGET}],
"CMD_DESC" => "Convert ELF to binary:")
env.add_build_hook do |builder|
if builder.target.end_with?(".o")
env.Disassemble("#{builder.target}.txt", builder.target)
end end
end end
end end
# FontGen Environment hello_env = env "hello", use: %w[ldc2 x86_64-w64-mingw32-gcc] do |env|
fontgen_env = env "fontgen", use: "freetype" do |env| env.add_builder(Image)
env["CC"] = "gcc" env.add_builder(HulkBinObj)
env.Program("^/fontgen.bin", glob("fontgen/**/*.c")) env["sources"] = glob("src/hello/**/*.d")
end env["sources"] += glob("uefi-d/source/**/*.d")
env.HulkBinObj("^/hulk_bin.S", hulk_env.expand("^/hulk.bin"))
# Kernel Environment env.Object("^/hulk_bin.o", "^/hulk_bin.S")
kernel_env = env "kernel" do |env| env.depends("^/hulk_bin.o", hulk_env.expand("^/hulk.bin"))
env.add_builder(EfiImage) env["sources"] << "^/hulk_bin.o"
env.add_builder(BiosImage) env["DFLAGS"] += %w[-mtriple=x86_64-unknown-windows-coff --betterC -release -O3 --wi --enable-cross-module-inlining]
env.add_builder(FontGen) env["D_IMPORT_PATH"] += %w[src uefi-d/source]
env.add_builder(Size) env["LD"] = "x86_64-w64-mingw32-gcc"
env["OBJDUMP"] = "i686-elf-objdump" env["LDFLAGS"] += %w[-nostdlib -Wl,-dll -shared -Wl,--subsystem,10 -e efi_main -Wl,-Map,${_TARGET}.map]
env["SIZE"] = "i686-elf-size" env["LDCMD"] = %w[${LD} -o ${_TARGET} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}]
env["CCFLAGS"] += %w[-ffreestanding -Wall -O2] env["OBJDUMP"] = "x86_64-w64-mingw32-objdump"
env["LDFLAGS"] += %w[-ffreestanding -nostdlib -T src/link.ld] env.Program("^/BOOTX64.EFI", "${sources}")
env["LDFLAGS"] += %W[-Wl,-Map,${_TARGET}.map] env["SIZE"] = "x86_64-w64-mingw32-size"
env["LIBS"] += %w[gcc] env.Size("^/BOOTX64.size", "^/BOOTX64.EFI")
env.FontGen("^/kfont/kfont.c", "font/Hack-Regular.ttf", env.Disassemble("^/BOOTX64.txt", "^/BOOTX64.EFI")
"fontgen" => fontgen_env.expand("^/fontgen.bin")) env.Image("^/hos.img", "^/BOOTX64.EFI")
env.barrier
env["CPPPATH"] += ["#{env.build_root}/kfont"]
env.Program("^/hos.elf", glob("src/**/*.{S,c}") + ["^/kfont/kfont.c"])
env.depends("#{env.build_root}/hos.elf", "src/link.ld")
env.Disassemble("^/hos.elf.txt", "^/hos.elf")
env.Size("^/hos.elf.size", "^/hos.elf")
env.EfiImage("^/hos-efi.img", %w[^/hos.elf])
env.BiosImage("^/hos.img", %w[^/hos.elf])
end end
task "run", desc: "Run HOS in QEMU" do task "run", desc: "Run HOS in QEMU" do
img = kernel_env.expand("^/hos.img") Dir.mktmpdir do |tmpdir|
sh %W[qemu-system-x86_64 -hda #{img}] img = hello_env.expand("^/hos.img")
end FileUtils.cp(img, tmpdir)
sh %W[qemu-system-x86_64 -bios OVMF.fd -drive file=#{tmpdir}/hos.img,format=raw]
task "run-efi", desc: "Run HOS EFI in QEMU" do end
img = kernel_env.expand("^/hos-efi.img")
sh %W[qemu-system-x86_64 -bios OVMF.fd -hda #{img}]
end end
+6 -6
View File
@@ -1,9 +1,9 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
# Copyright (c) 2013-2022 Josh Holtrop # Copyright (c) 2013-2022 Josh Holtrop
# #
# MIT License # MIT License
# #
# Permission is hereby granted, free of charge, to any person obtaining # Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the # a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including # "Software"), to deal in the Software without restriction, including
@@ -11,10 +11,10 @@
# distribute, sublicense, and/or sell copies of the Software, and to # distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to # permit persons to whom the Software is furnished to do so, subject to
# the following conditions: # the following conditions:
# #
# The above copyright notice and this permission notice shall be # The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software. # included in all copies or substantial portions of the Software.
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -24,7 +24,7 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
script = File.join(File.dirname(__FILE__), ".rscons-3.0.0-077c0388ca4d1d902141299abcc4b8f6.rb") script = File.join(File.dirname(__FILE__), ".rscons-3.0.2-c49c635f1e4166223367979510498b28.rb")
unless File.exists?(script) unless File.exists?(script)
if File.read(__FILE__, mode: "rb") =~ /^#==>(.*)/ if File.read(__FILE__, mode: "rb") =~ /^#==>(.*)/
require "zlib" require "zlib"
@@ -43,4 +43,4 @@ load script
if __FILE__ == $0 if __FILE__ == $0
Rscons::Cli.new.run(ARGV) Rscons::Cli.new.run(ARGV)
end end
#==>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 truncated #==>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 truncated
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
+178
View File
@@ -0,0 +1,178 @@
/**
* HELLO console support.
*/
module hello.console;
import uefi;
import hello.hello;
import core.stdc.stdarg;
/**
* Format a hexadecimal value to a string.
*
* @param s String buffer.
* @param v Value to format.
* @param ptr If true, always output all 16 digits, and separate the upper and
* lower halves with an underscore.
*/
private size_t format_hex(CHAR16 * s, ulong v, bool ptr)
{
string hex_chars = "0123456789ABCDEF";
bool print = ptr;
size_t si = 0u;
for (size_t i = 0u; i < 16u; i++)
{
if (ptr && (i == 8u))
{
s[si++] = '_';
}
ulong n = (v >> (60u - 4u * i)) & 0xFu;
if (n != 0u)
{
print = true;
}
if (print || (i == 15u))
{
s[si++] = hex_chars[n];
}
}
return si;
}
/**
* Format a decimal value to a string.
*
* @param s String buffer.
* @param v Value to format.
*/
private size_t format_dec(CHAR16 * s, ulong v)
{
string dec_chars = "0123456789";
bool print;
char[20] buf;
size_t buf_i;
while ((buf_i == 0u) || (v != 0u))
{
ulong n = v % 10u;
buf[buf_i++] = dec_chars[n];
v /= 10u;
}
for (size_t si = 0u; si < buf_i; si++)
{
s[si] = buf[buf_i - si - 1u];
}
return buf_i;
}
/**
* Write a string to the console.
*
* @param s Format string.
* @param args Variable arguments structure.
*/
void write(string s, va_list args)
{
__gshared static CHAR16[256] s16;
size_t i = 0u;
bool escape = false;
foreach (char c; s)
{
if (escape)
{
if (c == '%')
{
s16[i++] = '%';
}
else if (c == 'x')
{
ulong v;
va_arg(args, v);
i += format_hex(&s16[i], v, false);
}
else if (c == 'p')
{
ulong v;
va_arg(args, v);
i += format_hex(&s16[i], v, true);
}
else if (c == 'S')
{
const(CHAR16) * s2;
va_arg(args, s2);
for (size_t s2_i = 0u; s2[s2_i] != 0; s2_i++)
{
s16[i++] = s2[s2_i];
}
}
else if (c == 'u')
{
ulong v;
va_arg(args, v);
i += format_dec(&s16[i], v);
}
else
{
s16[i++] = c;
}
escape = false;
}
else if (c == '%')
{
escape = true;
}
else
{
s16[i++] = c;
}
}
s16[i++] = 0u;
st.ConOut.OutputString(st.ConOut, &s16[0]);
}
/**
* Write a string to the console.
*
* @param s Format string.
*/
extern (C) void write(string s, ...)
{
va_list args;
va_start(args, s);
write(s, args);
va_end(args);
}
/**
* Write a string to the console.
*
* @param s Format string.
*/
extern (C) void writeln(string s, ...)
{
va_list args;
va_start(args, s);
write(s, args);
write("\r\n", args);
va_end(args);
}
/**
* Write a message to press any key and wait for a key to be pressed.
*/
void wait_key()
{
writeln("Press any key...");
st.ConIn.Reset(st.ConIn, FALSE);
EFI_INPUT_KEY key;
while (st.ConIn.ReadKeyStroke(st.ConIn, &key) == EFI_NOT_READY)
{
}
}
/**
* Clear the console.
*/
void clear()
{
st.ConOut.ClearScreen(st.ConOut);
}
+344
View File
@@ -0,0 +1,344 @@
/**
* HELLO, the HOS EFI Lightweight LOader.
*/
module hello.hello;
import uefi;
import console = hello.console;
import scratch = hello.scratch;
import hulk.bootinfo;
import hulk.header : HulkHeader = Header;
import hos.page_table;
import hos.cpu;
import hos.memory;
__gshared EFI_SYSTEM_TABLE * st;
private __gshared BootInfo bootinfo;
private __gshared UINTN memory_map_key;
extern extern(C) __gshared ubyte hulk_bin_start;
/**
* Detect if we're running in QEMU.
*/
private bool in_qemu()
{
ulong * firmware_vendor = cast(ulong *) st.FirmwareVendor;
ulong fv1 = firmware_vendor[0];
return fv1 ==
((cast(ulong)'E') |
(cast(ulong)'D' << 16) |
(cast(ulong)'K' << 32) |
(cast(ulong)' ' << 48));
}
/**
* Set a graphics mode.
*/
private bool set_graphics_mode()
{
uint max_horizontal_resolution = in_qemu() ? 1920u : 0xFFFFFFFFu;
UINTN buffer_size = scratch.free();
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
EFI_HANDLE * handles = cast(EFI_HANDLE *)scratch.current();
EFI_STATUS status = st.BootServices.LocateHandle(ByProtocol,
&gop_guid, null, &buffer_size, handles);
if (status != EFI_SUCCESS)
{
console.writeln("LocateHandle: error %x", status);
return false;
}
EFI_HANDLE gop_handle = handles[0];
EFI_HANDLE gop_interface;
status = st.BootServices.HandleProtocol(gop_handle,
&gop_guid, &gop_interface);
if (status != EFI_SUCCESS)
{
console.writeln("HandleProtocol: error %x", status);
return false;
}
if (gop_interface == null)
{
console.writeln("null interface from HandleProtocol");
return false;
}
EFI_GRAPHICS_OUTPUT_PROTOCOL * gop = cast(EFI_GRAPHICS_OUTPUT_PROTOCOL *)gop_interface;
UINTN info_size;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * info;
uint best_width;
uint best_mode_number;
for (uint mode_number = 0u;
(status = gop.QueryMode(gop, mode_number, &info_size, &info)) == EFI_SUCCESS;
mode_number++)
{
if ((info.HorizontalResolution > best_width) &&
(info.HorizontalResolution <= max_horizontal_resolution))
{
best_width = info.HorizontalResolution;
best_mode_number = mode_number;
}
st.BootServices.FreePool(info);
}
if ((status = gop.SetMode(gop, best_mode_number)) != EFI_SUCCESS)
{
console.writeln("SetMode: Error %x\n", status);
return false;
}
bootinfo.fb.buffer = cast(uint *)gop.Mode.FrameBufferBase;
bootinfo.fb.width = gop.Mode.Info.HorizontalResolution;
bootinfo.fb.height = gop.Mode.Info.VerticalResolution;
bootinfo.fb.stride = gop.Mode.Info.PixelsPerScanLine;
bootinfo.fb.format = gop.Mode.Info.PixelFormat;
return true;
}
/**
* Walk the EFI memory map and translate it to the HULK bootinfo format.
*
* @return Maximum physical address to identity map.
*/
private ulong get_memory_map()
{
UINTN memory_map_size = scratch.free();
UINTN descriptor_size;
UINT32 descriptor_version;
ubyte * scratch_base = scratch.current();
UINTN status = st.BootServices.GetMemoryMap(
&memory_map_size,
cast(EFI_MEMORY_DESCRIPTOR *)scratch_base,
&memory_map_key,
&descriptor_size,
&descriptor_version);
if (status != EFI_SUCCESS)
{
console.writeln("GetMemoryMap: Error %x", status);
return 0u;
}
ulong max_physical_address;
size_t n_entries = memory_map_size / descriptor_size;
size_t count;
for (count = 0u; count < n_entries; count++)
{
if (count > bootinfo.memory_map.length)
{
console.writeln("Memory map too large");
for (;;)
{
}
}
EFI_MEMORY_DESCRIPTOR * descriptor = cast(EFI_MEMORY_DESCRIPTOR *)&scratch_base[count * descriptor_size];
ulong end_address = descriptor.PhysicalStart + descriptor.NumberOfPages * 4096u;
if ((end_address > max_physical_address) &&
((descriptor.Type == EfiLoaderCode) ||
(descriptor.Type == EfiLoaderData) ||
(descriptor.Type == EfiBootServicesCode) ||
(descriptor.Type == EfiBootServicesData) ||
(descriptor.Type == EfiRuntimeServicesCode) ||
(descriptor.Type == EfiRuntimeServicesData) ||
(descriptor.Type == EfiConventionalMemory)))
{
max_physical_address = end_address;
}
bootinfo.memory_map[count].base = descriptor.PhysicalStart;
bootinfo.memory_map[count].size = descriptor.NumberOfPages * 4096u;
bootinfo.memory_map[count].type = cast(ubyte)descriptor.Type;
}
bootinfo.memory_map_count = count;
return max_physical_address;
}
/**
* Allocate a new page table.
*/
private PageTableEntry * new_page_table()
{
PageTableEntry * pt = cast(PageTableEntry *)scratch.alloc(1u);
memset64(pt, 0u, 512);
return pt;
}
/**
* Map a virtual address to a physical address using 4KB pages.
*
* @param source_page Source page address.
* @param dest_page Destination page address.
* @param pt_base Page table base address.
*/
private void map4k(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
{
PageTableEntry * pt = pt_base;
PageTableEntry * next_pt;
for (size_t level = 0; level < 4u; level++)
{
size_t pt_index = PageTableEntry.page_table_index(source_page, level);
if (pt[pt_index].present())
{
pt = pt[pt_index].next();
}
else
{
ulong addr;
if (level < 3u)
{
next_pt = new_page_table();
addr = cast(ulong)next_pt;
}
else
{
addr = dest_page;
}
pt[pt_index] = PageTableEntry(addr,
0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u);
pt = next_pt;
}
}
}
/**
* Map a virtual address to a physical address using 2MB pages.
*
* @param source_page Source page address.
* @param dest_page Destination page address.
* @param pt_base Page table base address.
*/
private void map2m(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
{
PageTableEntry * pt = pt_base;
PageTableEntry * next_pt;
for (size_t level = 0; level < 3u; level++)
{
size_t pt_index = PageTableEntry.page_table_index(source_page, level);
if (pt[pt_index].present())
{
pt = pt[pt_index].next();
}
else
{
if (level < 2u)
{
next_pt = new_page_table();
pt[pt_index] = PageTableEntry(cast(ulong)next_pt,
0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u);
}
else
{
pt[pt_index] = PageTableEntry(dest_page,
0u, 0u, 1u, 0u, 0u, 0u, 1u, 1u);
}
pt = next_pt;
}
}
}
/**
* Map HULK virtual addresses to physical kernel location.
*
* @param pt_base Page table base address.
*/
private void map_hulk(PageTableEntry * pt_base)
{
ulong virt = HULK_VIRTUAL_START;
ulong phys = cast(ulong)&hulk_bin_start;
HulkHeader * hulk_header = cast(HulkHeader *)&hulk_bin_start;
size_t end_phys = phys + cast(size_t)hulk_header.total_size;
while (phys < end_phys)
{
map4k(virt, phys, pt_base);
virt += 4096u;
phys += 4096u;
}
}
/**
* Build page tables in preparation to jump to HULK.
*
* @param max_physical_address Maximum physical address to identity map.
*/
private void build_page_tables(ulong max_physical_address)
{
PageTableEntry * pt_base = new_page_table();
/* Map physical RAM. */
for (size_t addr = 0u; addr < max_physical_address; addr += (2u * 1024u * 1024u))
{
map2m(addr, addr, pt_base);
}
/* Map any memory regions that are outside physical RAM. */
for (size_t i = 0u; i < bootinfo.memory_map_count; i++)
{
if (bootinfo.memory_map[i].base > max_physical_address)
{
for (size_t offset = 0u; offset < bootinfo.memory_map[i].size; offset += 4096u)
{
ulong addr = bootinfo.memory_map[i].base + offset;
map4k(addr, addr, pt_base);
}
}
}
/* Map graphics framebuffer. */
ulong framebuffer_size = bootinfo.fb.height * bootinfo.fb.stride * 4u;
for (size_t offset = 0u; offset < framebuffer_size; offset += 4096u)
{
ulong addr = cast(ulong)bootinfo.fb.buffer + offset;
map4k(addr, addr, pt_base);
}
/* Map HULK to its requested starting virtual address. */
map_hulk(pt_base);
/* Switch to the new page table. */
write_cr3(cast(ulong)pt_base);
}
/**
* Jump to HULK entry point.
*/
private void jump_to_hulk()
{
HulkHeader * hulk_header = cast(HulkHeader *)&hulk_bin_start;
void function(BootInfo *) hulk_start = cast(void function(BootInfo *))hulk_header.entry;
hulk_start(&bootinfo);
}
/**
* EFI application entry point.
*
* @param image_handle EFI application handle.
* @param st Pointer to EFI system table.
*/
extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
{
.st = st;
console.clear();
console.writeln("HELLO, HOS EFI Lightweight LOader, v0.1.0");
console.writeln("Firmware vendor: '%S', version: 0x%x", st.FirmwareVendor, st.FirmwareVendor);
if (!set_graphics_mode())
{
console.wait_key();
return EFI_SUCCESS;
}
ulong max_physical_address;
for (;;)
{
max_physical_address = get_memory_map();
EFI_STATUS status = st.BootServices.ExitBootServices(image_handle, memory_map_key);
if (status == EFI_INVALID_PARAMETER)
{
continue;
}
if (status == EFI_SUCCESS)
{
break;
}
console.writeln("ExitBootServices: Error %x", status);
console.wait_key();
return EFI_SUCCESS;
}
build_page_tables(max_physical_address);
jump_to_hulk();
return EFI_SUCCESS;
}
+36
View File
@@ -0,0 +1,36 @@
/**
* HELLO scratch buffer.
*/
module hello.scratch;
/* Scratch buffer. */
private align(4096) __gshared ubyte[1024 * 1024] scratch;
/* Number of scratch buffer bytes used. */
private __gshared size_t scratch_used;
/**
* Get the number of free bytes in the scratch buffer.
*/
size_t free()
{
return scratch.sizeof - scratch_used;
}
/**
* Get the current free scratch buffer address.
*/
ubyte * current()
{
return &scratch[scratch_used];
}
/**
* Allocate pages from the scratch buffer.
*/
ubyte * alloc(size_t n = 1)
{
ubyte * address = &scratch[scratch_used];
scratch_used += 4096u * n;
return address;
}
+26
View File
@@ -0,0 +1,26 @@
import ldc.llvmasm;
ulong read_cr0()
{
return __asm!ulong("mov %cr0, %rax", "={rax}");
}
ulong read_cr2()
{
return __asm!ulong("mov %cr2, %rax", "={rax}");
}
ulong read_cr3()
{
return __asm!ulong("mov %cr3, %rax", "={rax}");
}
void write_cr3(ulong v)
{
__asm("mov $0, %cr3", "r", v);
}
ulong read_cr4()
{
return __asm!ulong("mov %cr4, %rax", "={rax}");
}
+57
View File
@@ -0,0 +1,57 @@
import ldc.llvmasm;
void memset(void * dest, ubyte v, size_t n)
{
__asm("rep stosb",
"{al},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset16(void * dest, ushort v, size_t n)
{
__asm("rep stosw",
"{ax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset32(void * dest, uint v, size_t n)
{
__asm("rep stosl",
"{eax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset64(void * dest, ulong v, size_t n)
{
__asm("rep stosq",
"{rax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memcpy(void * dest, void * src, size_t n)
{
__asm("rep movsb",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy16(void * dest, void * src, size_t n)
{
__asm("rep movsw",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy32(void * dest, void * src, size_t n)
{
__asm("rep movsl",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy64(void * dest, void * src, size_t n)
{
__asm("rep movsq",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
+33
View File
@@ -0,0 +1,33 @@
struct PageTableEntry
{
ulong entry;
this(ulong address, ulong no_execute, ulong global,
ulong huge, ulong disable_cache, ulong write_through, ulong user,
ulong writable, ulong present)
{
entry = (present |
(writable << 1) |
(user << 2) |
(write_through << 3) |
(disable_cache << 4) |
(huge << 7) |
(global << 8) |
(no_execute << 63)) | address;
}
bool present()
{
return (entry & 0x1u) != 0u;
}
PageTableEntry * next()
{
return cast(PageTableEntry *)(entry & 0x7FFF_FFFF_FFFF_F000u);
}
static ulong page_table_index(ulong address, size_t level)
{
return ((address >> (39u - 9u * level)) & 0x1FFu);
}
}
+52
View File
@@ -0,0 +1,52 @@
/**
* HULK boot information.
*/
module hulk.bootinfo;
/**
* HULK boot information structure.
*/
struct BootInfo
{
/**
* Framebuffer description structure.
*/
struct Framebuffer
{
/** Framebuffer base address. */
uint * buffer;
/** Horizontal resolution. */
uint width;
/** Vertical resolution. */
uint height;
/** Number of pixels per scan line. */
uint stride;
/** Pixel format. */
uint format;
}
/**
* Memory map entry description structure.
*/
struct MemoryRegion
{
/** Base address of the memory region. */
ulong base;
/** Size in bytes of the memory region. */
size_t size;
/** Type of the memory region. */
ubyte type;
}
/* Framebuffer parameters. */
Framebuffer fb;
/* Memory map. */
MemoryRegion[800] memory_map;
/* Number of memory map entries. */
size_t memory_map_count;
}
/** HULK base virtual address. */
enum ulong HULK_VIRTUAL_START = 0x0000_4000_0000_0000u;
+56
View File
@@ -0,0 +1,56 @@
/**
* HULK Framebuffer support.
*/
module hulk.framebuffer;
import hos.memory;
/**
* Represent a graphical frame buffer.
*
* TODO: Handle other pixel formats. Currently only ARGB is supported.
*/
struct Framebuffer
{
/** Frame buffer base address. */
private uint * m_buffer;
/** Frame buffer width. */
private uint m_width;
/** Frame buffer height. */
private uint m_height;
/** Frame buffer stride. */
private uint m_stride;
/** Number of pixels in the frame buffer (whether visible or not). */
private uint m_buffer_size;
/**
* Initialize a frame buffer.
*
* @param buffer Frame buffer base address.
* @param width Frame buffer width.
* @param height Frame buffer height.
* @param stride Frame buffer stride.
*/
void initialize(uint * buffer, uint width, uint height, uint stride)
{
m_buffer = buffer;
m_width = width;
m_height = height;
m_stride = stride;
m_buffer_size = stride * height;
}
/**
* Clear the frame buffer to the given color.
*
* @param color Color to clear to.
*/
void clear(uint color = 0u)
{
memset32(m_buffer, color, m_buffer_size);
}
}
+23
View File
@@ -0,0 +1,23 @@
/**
* HULK image header.
*/
module hulk.header;
/**
* Header describing the HULK image.
*/
struct Header
{
/**
* Total size of memory to be mapped.
*
* The OS loader must ensure that virtual memory is mapped for this entire
* size.
* This value is really an integer, but is stored as a pointer because it
* is provided by the linker and LDC does not like us to cast it.
*/
void * total_size;
/** Entry point. */
void * entry;
}
+40
View File
@@ -0,0 +1,40 @@
/**
* HULK, the HOS Ultra Light Kernel.
*/
module hulk.hulk;
import hulk.header;
import hulk.bootinfo;
import hulk.framebuffer;
import hos.memory;
import ldc.attributes;
private __gshared Framebuffer fb;
extern extern(C) __gshared ubyte _hulk_total_size;
@(ldc.attributes.section(".hulk_header"))
private __gshared Header hulk_header = {
&_hulk_total_size,
&hulk_start,
};
/**
* HULK entry point.
*
* @param bootinfo Pointer to HULK boot information structure.
*/
extern(C) void hulk_start(ulong rdi, ulong rsi, ulong rdx, BootInfo * bootinfo)
{
fb.initialize(bootinfo.fb.buffer, bootinfo.fb.width, bootinfo.fb.height, bootinfo.fb.stride);
fb.clear(0xFF8800u);
for (size_t y = 100u; y < 120u; y++)
{
memset32(&bootinfo.fb.buffer[y * bootinfo.fb.stride + 20u], 0x001199u, 20u);
}
for (;;)
{
}
}
+32
View File
@@ -0,0 +1,32 @@
SECTIONS
{
. = 0x0000400000000000;
_hulk_mem_start = .;
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.hulk_header)
*(.rodata)
}
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)
}
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
}
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
. = ALIGN(4K);
_hulk_mem_end = .;
_hulk_total_size = _hulk_mem_end - _hulk_mem_start;
}
Submodule
+1
Submodule uefi-d added at e70959ce8a.
+4 -3
View File
@@ -1,9 +1,10 @@
project_name "x86_64-elf-gcc"
binutils_version = "2.35" binutils_version = "2.35"
binutils_checksum = "1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85" binutils_checksum = "1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85"
gcc_version = "10.2.0" gcc_version = "10.2.0"
gcc_checksum = "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c" gcc_checksum = "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
install_path = File.expand_path("i686-elf-gcc") install_path = File.expand_path("x86_64-elf-gcc")
target = "i686-elf" target = "x86_64-elf"
path_prepend "#{install_path}/bin" path_prepend "#{install_path}/bin"
configure do configure do
@@ -53,7 +54,7 @@ default do
cd "#{build_dir}/build-gcc" do cd "#{build_dir}/build-gcc" do
sh %W[../gcc-#{gcc_version}/configure sh %W[../gcc-#{gcc_version}/configure
--target=#{target} --prefix=#{install_path} --disable-nls --target=#{target} --prefix=#{install_path} --disable-nls
--enable-languages=c,c++ --without-headers] --enable-languages=c --without-headers]
sh "make all-gcc" sh "make all-gcc"
sh "make all-target-libgcc" sh "make all-target-libgcc"
sh "make install-gcc" sh "make install-gcc"