Compare commits
68
Commits
master
...
f904ec2b48
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f904ec2b48 | ||
|
|
bcec23ef89 | ||
|
|
d86745d91d | ||
|
|
cf5956dcd3 | ||
|
|
8498de6b62 | ||
|
|
f761d0a445 | ||
|
|
f29bd9d00c | ||
|
|
f236a64b21 | ||
|
|
1225e98276 | ||
|
|
cb31e36e90 | ||
|
|
0568a813f2 | ||
|
|
37d5621e41 | ||
|
|
98e992aad0 | ||
|
|
06242a0c9f | ||
|
|
e214a9c3de | ||
|
|
c259ae4cee | ||
|
|
b4d8707243 | ||
|
|
6b7b14d954 | ||
|
|
9e7c3ee676 | ||
|
|
2d7bf5197f | ||
|
|
7562be585f | ||
|
|
3d04eec427 | ||
|
|
5c97acba5f | ||
|
|
c3ead56582 | ||
|
|
15559b0a56 | ||
|
|
c58284761a | ||
|
|
bd99e429a9 | ||
|
|
d0acf5a718 | ||
|
|
b40151055c | ||
|
|
1e00d7a9e9 | ||
|
|
79b34477ed | ||
|
|
163ef9f79e | ||
|
|
3c549f0838 | ||
|
|
d8c85ad045 | ||
|
|
7c5af33ace | ||
|
|
6f3521c576 | ||
|
|
5a5d60abae | ||
|
|
9182a83ef2 | ||
|
|
195b7496f4 | ||
|
|
b1042fd649 | ||
|
|
6beb7da4cd | ||
|
|
f27851def9 | ||
|
|
18f1bfc88f | ||
|
|
cd6983e2cd | ||
|
|
8df1646c61 | ||
|
|
3e25ab6ae4 | ||
|
|
05cc2da2e3 | ||
|
|
a54536660b | ||
|
|
9e3d9b18ea | ||
|
|
ef01239468 | ||
|
|
372b7265f1 | ||
|
|
1bc8722098 | ||
|
|
cd2f3f9a84 | ||
|
|
08a35e40d4 | ||
|
|
a855702214 | ||
|
|
706f2c1c5d | ||
|
|
704fd15f7b | ||
|
|
f054bab5cc | ||
|
|
3fa8e4a24b | ||
|
|
a38f95a7b8 | ||
|
|
dd57a31d38 | ||
|
|
406f17c1db | ||
|
|
0be1b113aa | ||
|
|
d782b59768 | ||
|
|
c3a6139f83 | ||
|
|
3d3a433800 | ||
|
|
54451bcf5b | ||
|
|
1fc2dd34e5 |
No files matched your search
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
.rscons*
|
.rscons*
|
||||||
/i686-elf-gcc/
|
/x86_64-elf-gcc/
|
||||||
/build/
|
/build/
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "uefi-d"]
|
||||||
|
path = uefi-d
|
||||||
|
url = git://github.com/kubasz/uefi-d
|
||||||
+90
-126
@@ -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
|
|
||||||
# Kernel default font size
|
|
||||||
KFONT_SIZE = 15
|
|
||||||
|
|
||||||
class BiosImage < Builder
|
configure do
|
||||||
|
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 = 18
|
||||||
|
|
||||||
|
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,65 @@ 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.add_builder(FontGen)
|
||||||
@vars["_TARGET"] = @target
|
env.FontGen("^/src/hulk/kfont.d", "font/Hack-Regular.ttf",
|
||||||
command = @env.build_command(%w[${SIZE} ${_SOURCES}], @vars)
|
"fontgen" => fontgen_env.expand("^/fontgen"))
|
||||||
standard_command("Size <target>#{@target}<reset>", command, stdout: @target)
|
env["sources"] = glob("src/hulk/**/*.d")
|
||||||
|
env["sources"] << "^/src/hulk/kfont.d"
|
||||||
|
env["DFLAGS"] += %w[-mtriple=x86_64-unknown-elf --betterC -release -O3 --wi --enable-cross-module-inlining -code-model=large]
|
||||||
|
env["D_IMPORT_PATH"] += %w[src]
|
||||||
|
env["D_IMPORT_PATH"] << env.expand("^/src")
|
||||||
|
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
|
||||||
@@ -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
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -62,52 +62,13 @@ static void load_char(FT_Face face, int char_code)
|
|||||||
char_infos[char_code].width * char_infos[char_code].height);
|
char_infos[char_code].width * char_infos[char_code].height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * bare_header_name(const char * h_file_name)
|
|
||||||
{
|
|
||||||
const char * p = rindex(h_file_name, '/');
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
p = h_file_name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char * include_guard_name(const char * h_file_name)
|
|
||||||
{
|
|
||||||
const char * p = bare_header_name(h_file_name);
|
|
||||||
char * guard_name = malloc(strlen(p) + 1);
|
|
||||||
strcpy(guard_name, p);
|
|
||||||
char * m = guard_name;
|
|
||||||
while (*m != '\0')
|
|
||||||
{
|
|
||||||
if ('a' <= *m && *m <= 'z')
|
|
||||||
{
|
|
||||||
*m = toupper(*m);
|
|
||||||
}
|
|
||||||
else if (('0' <= *m && *m <= '9') || ('A' <= *m && *m <= 'Z'))
|
|
||||||
{
|
|
||||||
/* no change */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*m = '_';
|
|
||||||
}
|
|
||||||
m++;
|
|
||||||
}
|
|
||||||
return guard_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void generate_bytes(FILE * file, const uint8_t * bytes, int count)
|
static void generate_bytes(FILE * file, const uint8_t * bytes, int count)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (i % 8 == 0)
|
if (i % 8 == 0)
|
||||||
{
|
{
|
||||||
fprintf(file, " ");
|
fprintf(file, " ");
|
||||||
}
|
}
|
||||||
fprintf(file, "0x%02xu,", bytes[i]);
|
fprintf(file, "0x%02xu,", bytes[i]);
|
||||||
if ((i + 1) % 8 == 0)
|
if ((i + 1) % 8 == 0)
|
||||||
@@ -125,62 +86,50 @@ static void generate_bytes(FILE * file, const uint8_t * bytes, int count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generate(const char * c_file_name)
|
static void generate(const char * d_file_name)
|
||||||
{
|
{
|
||||||
char * h_file_name = malloc(strlen(c_file_name) + 1);
|
FILE * fh = fopen(d_file_name, "wb");
|
||||||
strcpy(h_file_name, c_file_name);
|
fprintf(fh, "module hulk.kfont;\n");
|
||||||
h_file_name[strlen(h_file_name) - 1] = 'h';
|
fprintf(fh, "struct CharInfo {\n");
|
||||||
char * guard = include_guard_name(h_file_name);
|
fprintf(fh, " uint width;\n");
|
||||||
|
fprintf(fh, " uint height;\n");
|
||||||
FILE * h_file = fopen(h_file_name, "wb");
|
fprintf(fh, " int top;\n");
|
||||||
fprintf(h_file, "#ifndef %s\n", guard);
|
fprintf(fh, " int left;\n");
|
||||||
fprintf(h_file, "#define %s\n\n", guard);
|
fprintf(fh, " const ubyte[] bitmap;\n");
|
||||||
fprintf(h_file, "#include <stdint.h>\n");
|
fprintf(fh, "};\n");
|
||||||
fprintf(h_file, "typedef struct {\n int width;\n int height;\n int top;\n int left;\n const uint8_t * bitmap;\n} fontgen_char_info_t;\n");
|
fprintf(fh, "struct FontInfo {\n");
|
||||||
fprintf(h_file, "typedef struct {\n int line_height;\n int advance;\n int baseline_offset;\n const fontgen_char_info_t ** char_infos;\n} fontgen_font_t;\n");
|
fprintf(fh, " uint line_height;\n");
|
||||||
fprintf(h_file, "extern const fontgen_font_t kfont;\n");
|
fprintf(fh, " uint advance;\n");
|
||||||
fprintf(h_file, "#endif\n");
|
fprintf(fh, " int baseline_offset;\n");
|
||||||
fclose(h_file);
|
fprintf(fh, " const CharInfo[] chars;\n");
|
||||||
|
fprintf(fh, "};\n");
|
||||||
FILE * c_file = fopen(c_file_name, "wb");
|
fprintf(fh, "__gshared const FontInfo kfont = {\n");
|
||||||
fprintf(c_file, "#include \"%s\"\n", bare_header_name(h_file_name));
|
fprintf(fh, " %du,\n", line_height);
|
||||||
fprintf(c_file, "#include <stddef.h>\n");
|
fprintf(fh, " %du,\n", max_advance);
|
||||||
|
fprintf(fh, " %d,\n", baseline_offset);
|
||||||
|
fprintf(fh, " [\n");
|
||||||
for (int i = 0; i < N_CHARS; i++)
|
for (int i = 0; i < N_CHARS; i++)
|
||||||
{
|
{
|
||||||
|
fprintf(fh, " CharInfo(\n");
|
||||||
|
fprintf(fh, " %du,\n", char_infos[i].width);
|
||||||
|
fprintf(fh, " %du,\n", char_infos[i].height);
|
||||||
|
fprintf(fh, " %d,\n", char_infos[i].top);
|
||||||
|
fprintf(fh, " %d,\n", char_infos[i].left);
|
||||||
if (char_infos[i].width > 0)
|
if (char_infos[i].width > 0)
|
||||||
{
|
{
|
||||||
fprintf(c_file, "static const uint8_t char_bitmap_%d[] = {\n", i);
|
fprintf(fh, " [\n");
|
||||||
generate_bytes(c_file, char_infos[i].bitmap, char_infos[i].width * char_infos[i].height);
|
generate_bytes(fh, char_infos[i].bitmap, char_infos[i].width * char_infos[i].height);
|
||||||
fprintf(c_file, "};\n");
|
fprintf(fh, " ]\n");
|
||||||
}
|
|
||||||
fprintf(c_file, "static const fontgen_char_info_t char_%d = {\n", i);
|
|
||||||
fprintf(c_file, " %d,\n", char_infos[i].width);
|
|
||||||
fprintf(c_file, " %d,\n", char_infos[i].height);
|
|
||||||
fprintf(c_file, " %d,\n", char_infos[i].top);
|
|
||||||
fprintf(c_file, " %d,\n", char_infos[i].left);
|
|
||||||
if (char_infos[i].width > 0)
|
|
||||||
{
|
|
||||||
fprintf(c_file, " char_bitmap_%d,\n", i);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(c_file, " NULL,\n");
|
fprintf(fh, " []\n");
|
||||||
}
|
}
|
||||||
fprintf(c_file, "};\n\n");
|
fprintf(fh, " ),\n");
|
||||||
}
|
}
|
||||||
fprintf(c_file, "const fontgen_char_info_t * char_infos[] = {\n");
|
fprintf(fh, " ],\n");
|
||||||
for (int i = 0; i < N_CHARS; i++)
|
fprintf(fh, "};\n");
|
||||||
{
|
fclose(fh);
|
||||||
fprintf(c_file, " &char_%d,\n", i);
|
|
||||||
}
|
|
||||||
fprintf(c_file, "};\n");
|
|
||||||
fprintf(c_file, "const fontgen_font_t kfont = {\n");
|
|
||||||
fprintf(c_file, " %d,\n", line_height);
|
|
||||||
fprintf(c_file, " %d,\n", max_advance);
|
|
||||||
fprintf(c_file, " %d,\n", baseline_offset);
|
|
||||||
fprintf(c_file, " char_infos,\n");
|
|
||||||
fprintf(c_file, "};\n");
|
|
||||||
fclose(c_file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
/**
|
||||||
|
* HELLO console support.
|
||||||
|
*/
|
||||||
|
module hello.console;
|
||||||
|
|
||||||
|
import uefi;
|
||||||
|
import hello.hello;
|
||||||
|
import core.stdc.stdarg;
|
||||||
|
|
||||||
|
struct console
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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 static 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 static 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.
|
||||||
|
*/
|
||||||
|
public static 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.
|
||||||
|
*/
|
||||||
|
public static 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.
|
||||||
|
*/
|
||||||
|
public static 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.
|
||||||
|
*/
|
||||||
|
public static 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.
|
||||||
|
*/
|
||||||
|
public static void clear()
|
||||||
|
{
|
||||||
|
st.ConOut.ClearScreen(st.ConOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,454 @@
|
|||||||
|
/**
|
||||||
|
* HELLO, the HOS EFI Lightweight LOader.
|
||||||
|
*/
|
||||||
|
module hello.hello;
|
||||||
|
|
||||||
|
import uefi;
|
||||||
|
import hello.console;
|
||||||
|
import hello.scratch;
|
||||||
|
import hulk.bootinfo;
|
||||||
|
import hulk.header;
|
||||||
|
import hos.page_table;
|
||||||
|
import hos.cpu;
|
||||||
|
import hos.memory;
|
||||||
|
import ldc.llvmasm;
|
||||||
|
|
||||||
|
__gshared EFI_SYSTEM_TABLE * st;
|
||||||
|
extern extern(C) __gshared ubyte _hulk_bin_start;
|
||||||
|
extern extern(C) __gshared ubyte _hulk_bin_end;
|
||||||
|
|
||||||
|
private HulkHeader * hulk_header()
|
||||||
|
{
|
||||||
|
return cast(HulkHeader *)&_hulk_bin_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BootInfo * bootinfo()
|
||||||
|
{
|
||||||
|
return &hulk_header().bootinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_bin_phys()
|
||||||
|
{
|
||||||
|
return cast(ulong)&_hulk_bin_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_bin_size()
|
||||||
|
{
|
||||||
|
return cast(ulong)&_hulk_bin_end - cast(ulong)&_hulk_bin_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_total_size()
|
||||||
|
{
|
||||||
|
return cast(ulong)hulk_header().total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_bss_size()
|
||||||
|
{
|
||||||
|
return hulk_total_size() - hulk_bin_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_stack_size()
|
||||||
|
{
|
||||||
|
return hulk_header().stack_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_virt_base_address()
|
||||||
|
{
|
||||||
|
return hulk_header().virt_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_virt_stack_top()
|
||||||
|
{
|
||||||
|
return hulk_header().virt_stack_top;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong hulk_virt_framebuffer_address()
|
||||||
|
{
|
||||||
|
return hulk_header().virt_fb_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
private void get_memory_map(ulong * bss_phys, ulong * stack_phys, ulong * max_physical_address, UINTN * memory_map_key)
|
||||||
|
{
|
||||||
|
immutable static ubyte[] efi_to_hulk_memory_map_type = [
|
||||||
|
BootInfo.MemoryRegion.Type.Reserved, // EfiReservedMemoryType
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiLoaderCode
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiLoaderData
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiBootServicesCode
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiBootServicesData
|
||||||
|
BootInfo.MemoryRegion.Type.Reserved, // EfiRuntimeServicesCode
|
||||||
|
BootInfo.MemoryRegion.Type.Reserved, // EfiRuntimeServicesData
|
||||||
|
BootInfo.MemoryRegion.Type.Conventional, // EfiConventionalMemory
|
||||||
|
BootInfo.MemoryRegion.Type.Unusable, // EfiUnusableMemory
|
||||||
|
BootInfo.MemoryRegion.Type.ACPIReclaim, // EfiACPIReclaimMemory
|
||||||
|
BootInfo.MemoryRegion.Type.ACPINVS, // EfiACPIMemoryNVS
|
||||||
|
BootInfo.MemoryRegion.Type.MemoryMappedIO, // EfiMemoryMappedIO
|
||||||
|
BootInfo.MemoryRegion.Type.MemoryMappedIOPortSpace, // EfiMemoryMappedIOPortSpace
|
||||||
|
BootInfo.MemoryRegion.Type.PalCode, // EfiPalCode
|
||||||
|
];
|
||||||
|
*max_physical_address = 0u;
|
||||||
|
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);
|
||||||
|
for (;;) {}
|
||||||
|
}
|
||||||
|
size_t n_entries = memory_map_size / descriptor_size;
|
||||||
|
size_t count;
|
||||||
|
bool found_bss;
|
||||||
|
bool found_stack;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (descriptor.Type >= efi_to_hulk_memory_map_type.length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bootinfo().memory_map[count].base = descriptor.PhysicalStart;
|
||||||
|
bootinfo().memory_map[count].size = descriptor.NumberOfPages * 4096u;
|
||||||
|
bootinfo().memory_map[count].type = efi_to_hulk_memory_map_type[descriptor.Type];
|
||||||
|
if ((!found_bss) &&
|
||||||
|
(descriptor.Type == EfiConventionalMemory) &&
|
||||||
|
(bootinfo().memory_map[count].size >= hulk_bss_size()))
|
||||||
|
{
|
||||||
|
*bss_phys = bootinfo().memory_map[count].base;
|
||||||
|
bootinfo().memory_map[count].base += hulk_bss_size();
|
||||||
|
bootinfo().memory_map[count].size -= hulk_bss_size();
|
||||||
|
found_bss = true;
|
||||||
|
}
|
||||||
|
if ((!found_stack) &&
|
||||||
|
(descriptor.Type == EfiConventionalMemory) &&
|
||||||
|
(bootinfo().memory_map[count].size >= hulk_stack_size()))
|
||||||
|
{
|
||||||
|
*stack_phys = bootinfo().memory_map[count].base;
|
||||||
|
bootinfo().memory_map[count].base += hulk_stack_size();
|
||||||
|
bootinfo().memory_map[count].size -= hulk_stack_size();
|
||||||
|
found_stack = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bootinfo().memory_map_count = count;
|
||||||
|
if ((!found_bss) && (!found_stack))
|
||||||
|
{
|
||||||
|
for (;;) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 region to a physical region using 4KB pages.
|
||||||
|
*
|
||||||
|
* @param source Source address.
|
||||||
|
* @param dest Destination address.
|
||||||
|
* @param size Region size.
|
||||||
|
* @param pt_base Page table base address.
|
||||||
|
*/
|
||||||
|
private void map4kregion(ulong source, ulong dest, size_t size, PageTableEntry * pt_base)
|
||||||
|
{
|
||||||
|
ulong end = source + size;
|
||||||
|
while (source < end)
|
||||||
|
{
|
||||||
|
map4k(source, dest, pt_base);
|
||||||
|
source += 4096u;
|
||||||
|
dest += 4096u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 bss_phys, ulong stack_phys)
|
||||||
|
{
|
||||||
|
/* Map HULK bin region. */
|
||||||
|
ulong virt = hulk_virt_base_address();
|
||||||
|
map4kregion(virt, hulk_bin_phys(), hulk_bin_size(), pt_base);
|
||||||
|
/* Map HULK bss region. */
|
||||||
|
virt += hulk_bin_size();
|
||||||
|
map4kregion(virt, bss_phys, hulk_bss_size(), pt_base);
|
||||||
|
/* Map HULK stack. */
|
||||||
|
virt = hulk_virt_stack_top() - hulk_stack_size();
|
||||||
|
map4kregion(virt, stack_phys, hulk_stack_size(), pt_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, ulong bss_phys, ulong stack_phys)
|
||||||
|
{
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
ulong addr = bootinfo().memory_map[i].base;
|
||||||
|
if (addr >= max_physical_address)
|
||||||
|
{
|
||||||
|
map4kregion(addr, addr, bootinfo().memory_map[i].size, pt_base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Map graphics framebuffer. */
|
||||||
|
ulong framebuffer_size = bootinfo().fb.height * bootinfo().fb.stride * 4u;
|
||||||
|
ulong fb_phys = cast(ulong)bootinfo().fb.buffer;
|
||||||
|
ulong fb_virt = hulk_virt_framebuffer_address();
|
||||||
|
map4kregion(fb_virt, fb_phys, framebuffer_size, pt_base);
|
||||||
|
/* Map HULK regions. */
|
||||||
|
map_hulk(pt_base, bss_phys, stack_phys);
|
||||||
|
/* Switch to the new page table. */
|
||||||
|
write_cr3(cast(ulong)pt_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jump to HULK entry point.
|
||||||
|
*/
|
||||||
|
private void jump_to_hulk()
|
||||||
|
{
|
||||||
|
__asm(
|
||||||
|
"jmpq *$0",
|
||||||
|
"r,{rsp}",
|
||||||
|
hulk_header().entry, hulk_virt_stack_top());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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("Welcome to 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 bss_phys;
|
||||||
|
ulong stack_phys;
|
||||||
|
ulong max_physical_address;
|
||||||
|
UINTN memory_map_key;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
get_memory_map(&bss_phys, &stack_phys, &max_physical_address, &memory_map_key);
|
||||||
|
|
||||||
|
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, bss_phys, stack_phys);
|
||||||
|
|
||||||
|
bootinfo().hulk_phys = hulk_bin_phys();
|
||||||
|
bootinfo().bss_phys = bss_phys;
|
||||||
|
bootinfo().stack_phys = stack_phys;
|
||||||
|
|
||||||
|
jump_to_hulk();
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* HELLO scratch buffer.
|
||||||
|
*/
|
||||||
|
module hello.scratch;
|
||||||
|
|
||||||
|
struct scratch
|
||||||
|
{
|
||||||
|
/* Scratch buffer. */
|
||||||
|
private static align(4096) __gshared ubyte[1024 * 1024] scratch;
|
||||||
|
|
||||||
|
/* Number of scratch buffer bytes used. */
|
||||||
|
private static __gshared size_t scratch_used;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of free bytes in the scratch buffer.
|
||||||
|
*/
|
||||||
|
public static size_t free()
|
||||||
|
{
|
||||||
|
return scratch.sizeof - scratch_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current free scratch buffer address.
|
||||||
|
*/
|
||||||
|
public static ubyte * current()
|
||||||
|
{
|
||||||
|
return &scratch[scratch_used];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate pages from the scratch buffer.
|
||||||
|
*/
|
||||||
|
public static ubyte * alloc(size_t n = 1)
|
||||||
|
{
|
||||||
|
ubyte * address = &scratch[scratch_used];
|
||||||
|
scratch_used += 4096u * n;
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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}");
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* HULK boot information.
|
||||||
|
*/
|
||||||
|
module hulk.bootinfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HULK boot information structure.
|
||||||
|
*/
|
||||||
|
struct BootInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Framebuffer description structure.
|
||||||
|
*/
|
||||||
|
struct Framebuffer
|
||||||
|
{
|
||||||
|
/** Framebuffer physical 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
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
Reserved,
|
||||||
|
Conventional,
|
||||||
|
Unusable,
|
||||||
|
ACPIReclaim,
|
||||||
|
ACPINVS,
|
||||||
|
MemoryMappedIO,
|
||||||
|
MemoryMappedIOPortSpace,
|
||||||
|
PalCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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[1000] memory_map;
|
||||||
|
|
||||||
|
/* Number of memory map entries. */
|
||||||
|
size_t memory_map_count;
|
||||||
|
|
||||||
|
/* Physical address of HULK. */
|
||||||
|
ulong hulk_phys;
|
||||||
|
|
||||||
|
/* Physical address used for HULK bss section. */
|
||||||
|
ulong bss_phys;
|
||||||
|
|
||||||
|
/* Physical address of stack while jumping to HULK. */
|
||||||
|
ulong stack_phys;
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* HULK Console functionality.
|
||||||
|
*/
|
||||||
|
module hulk.console;
|
||||||
|
|
||||||
|
import hulk.fb;
|
||||||
|
import hulk.kfont;
|
||||||
|
|
||||||
|
struct console
|
||||||
|
{
|
||||||
|
/** Console width in text columns. */
|
||||||
|
private static __gshared size_t m_width;
|
||||||
|
|
||||||
|
/** Console height in text rows. */
|
||||||
|
private static __gshared size_t m_height;
|
||||||
|
|
||||||
|
/** Current console cursor X position. */
|
||||||
|
private static __gshared size_t m_x;
|
||||||
|
|
||||||
|
/** Current console cursor Y position. */
|
||||||
|
private static __gshared size_t m_y;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the console.
|
||||||
|
*/
|
||||||
|
public static void initialize()
|
||||||
|
{
|
||||||
|
m_width = fb.width / kfont.advance;
|
||||||
|
m_height = fb.height / kfont.line_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the console.
|
||||||
|
*/
|
||||||
|
public static void clear()
|
||||||
|
{
|
||||||
|
fb.clear();
|
||||||
|
m_x = 0u;
|
||||||
|
m_y = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a character to the console.
|
||||||
|
*
|
||||||
|
* @param ch Character to write.
|
||||||
|
*/
|
||||||
|
public static void write(char ch)
|
||||||
|
{
|
||||||
|
if (ch == '\n')
|
||||||
|
{
|
||||||
|
m_x = 0u;
|
||||||
|
m_y++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
render_char(m_x, m_y, ch);
|
||||||
|
m_x++;
|
||||||
|
if (m_x == m_width)
|
||||||
|
{
|
||||||
|
m_x = 0u;
|
||||||
|
m_y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_y == m_height)
|
||||||
|
{
|
||||||
|
m_y--;
|
||||||
|
fb.copy_rows_up(fb_y(m_height - 1u),
|
||||||
|
(m_height - 1u) * kfont.line_height,
|
||||||
|
kfont.line_height);
|
||||||
|
fb.rect(0u, fb_y(m_height - 1u), fb_x(m_width), kfont.line_height, 0u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render a character.
|
||||||
|
*
|
||||||
|
* @param x X position.
|
||||||
|
* @param y Y position.
|
||||||
|
* @param ch Character to render.
|
||||||
|
*/
|
||||||
|
private static void render_char(size_t x, size_t y, char ch)
|
||||||
|
{
|
||||||
|
const(CharInfo) * ci = &kfont.chars[ch];
|
||||||
|
fb.blit_alpha_bitmap(fb_x(x) + ci.left, fb_y(y) + ci.top - ci.height, ci.bitmap, ci.width, ci.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the framebuffer X coordinate corresponding to the console X position.
|
||||||
|
*/
|
||||||
|
private static size_t fb_x(size_t x)
|
||||||
|
{
|
||||||
|
return x * kfont.advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the framebuffer Y coordinate corresponding to the console Y position.
|
||||||
|
*/
|
||||||
|
private static size_t fb_y(size_t y)
|
||||||
|
{
|
||||||
|
return fb.height - ((y + 1u) * kfont.line_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
+274
@@ -0,0 +1,274 @@
|
|||||||
|
/**
|
||||||
|
* HULK Framebuffer support.
|
||||||
|
*/
|
||||||
|
module hulk.fb;
|
||||||
|
|
||||||
|
import hos.memory;
|
||||||
|
import hulk.kfont;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a graphical frame buffer.
|
||||||
|
*
|
||||||
|
* TODO: Handle other pixel formats. Currently only BGRx is supported.
|
||||||
|
*/
|
||||||
|
struct fb
|
||||||
|
{
|
||||||
|
/** Frame buffer base address. */
|
||||||
|
private __gshared static uint * m_buffer;
|
||||||
|
|
||||||
|
/** Frame buffer width. */
|
||||||
|
private __gshared static uint m_width;
|
||||||
|
|
||||||
|
/** Frame buffer height. */
|
||||||
|
private __gshared static uint m_height;
|
||||||
|
|
||||||
|
/** Frame buffer stride. */
|
||||||
|
private __gshared static uint m_stride;
|
||||||
|
|
||||||
|
/** Number of pixels in the frame buffer (whether visible or not). */
|
||||||
|
private __gshared static uint m_buffer_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the framebuffer width.
|
||||||
|
*/
|
||||||
|
public static @property uint width()
|
||||||
|
{
|
||||||
|
return m_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the framebuffer height.
|
||||||
|
*/
|
||||||
|
public static @property uint height()
|
||||||
|
{
|
||||||
|
return m_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static 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.
|
||||||
|
*/
|
||||||
|
static void clear(uint color = 0u)
|
||||||
|
{
|
||||||
|
memset32(m_buffer, color, m_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a solid rectangle on the framebuffer.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of rectangle.
|
||||||
|
* @param y Y coordinate of bottom side of rectangle.
|
||||||
|
* @param width Width of rectangle.
|
||||||
|
* @param height Height of rectangle.
|
||||||
|
* @param color Color of rectangle.
|
||||||
|
*/
|
||||||
|
static void rect(size_t x, size_t y, size_t width, size_t height, uint color)
|
||||||
|
{
|
||||||
|
for (size_t iy = 0u; iy < height; iy++)
|
||||||
|
{
|
||||||
|
size_t buffer_index = buffer_index(x, y);
|
||||||
|
memset32(&m_buffer[buffer_index], color, width);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a horizontal line.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of line.
|
||||||
|
* @param y Y coordinate of line.
|
||||||
|
* @param width Width of line.
|
||||||
|
* @param color Color of line.
|
||||||
|
*/
|
||||||
|
static void hline(size_t x, size_t y, size_t width, uint color)
|
||||||
|
{
|
||||||
|
size_t buffer_index = buffer_index(x, y);
|
||||||
|
memset32(&m_buffer[buffer_index], color, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a vertical line.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of line.
|
||||||
|
* @param y Y coordinate of bottom of line.
|
||||||
|
* @param height Height of line.
|
||||||
|
* @param color Color of line.
|
||||||
|
*/
|
||||||
|
static void vline(size_t x, size_t y, size_t height, uint color)
|
||||||
|
{
|
||||||
|
size_t buffer_index = buffer_index(x, y);
|
||||||
|
for (size_t iy = 0u; iy < height; iy++)
|
||||||
|
{
|
||||||
|
m_buffer[buffer_index] = color;
|
||||||
|
buffer_index -= m_stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a character.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of character.
|
||||||
|
* @param y Y coordinate of bottom side of character.
|
||||||
|
* @param ch Character to draw.
|
||||||
|
* @param color Color of character.
|
||||||
|
*/
|
||||||
|
static void character(int x, int y, char ch, uint color)
|
||||||
|
{
|
||||||
|
const(CharInfo) * ci = &kfont.chars[ch];
|
||||||
|
blend_alpha_bitmap(x + ci.left, y + kfont.baseline_offset + ci.top - ci.height, ci.bitmap, ci.width, ci.height, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blend an 8-bit alpha bitmap to the framebuffer.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of target location.
|
||||||
|
* @param y Y coordinate of bottom side of target location.
|
||||||
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
||||||
|
* @param width Bitmap width.
|
||||||
|
* @param height Bitmap height.
|
||||||
|
* @param color Color to blend with alpha value.
|
||||||
|
*/
|
||||||
|
static void blend_alpha_bitmap(size_t x, size_t y, const(ubyte) * alpha_bitmap,
|
||||||
|
size_t width, size_t height, uint color)
|
||||||
|
{
|
||||||
|
y += height - 1u;
|
||||||
|
size_t bitmap_index;
|
||||||
|
for (size_t iy = 0u; iy < height; iy++)
|
||||||
|
{
|
||||||
|
for (size_t ix = 0u; ix < width; ix++)
|
||||||
|
{
|
||||||
|
size_t buffer_index = buffer_index(x + ix, y);
|
||||||
|
ubyte alpha = alpha_bitmap[bitmap_index];
|
||||||
|
uint current_color = m_buffer[buffer_index];
|
||||||
|
uint in_color_scaled = scale_color(color, alpha);
|
||||||
|
uint old_color_scaled = scale_color(current_color, 255u - alpha);
|
||||||
|
uint new_color = old_color_scaled + in_color_scaled;
|
||||||
|
m_buffer[buffer_index] = new_color;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
|
y--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blend an 8-bit alpha bitmap to the framebuffer.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of target location.
|
||||||
|
* @param y Y coordinate of bottom side of target location.
|
||||||
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
||||||
|
* @param width Bitmap width.
|
||||||
|
* @param height Bitmap height.
|
||||||
|
* @param color Color to blend with alpha value.
|
||||||
|
*/
|
||||||
|
static void blend_alpha_bitmap(size_t x, size_t y, const(ubyte)[] alpha_bitmap,
|
||||||
|
size_t width, size_t height, uint color)
|
||||||
|
{
|
||||||
|
blend_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blit an 8-bit alpha bitmap to the framebuffer.
|
||||||
|
* The foreground will be white (based on the alpha value), and the
|
||||||
|
* background black.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of target location.
|
||||||
|
* @param y Y coordinate of bottom side of target location.
|
||||||
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
||||||
|
* @param width Bitmap width.
|
||||||
|
* @param height Bitmap height.
|
||||||
|
*/
|
||||||
|
static void blit_alpha_bitmap(size_t x, size_t y, const(ubyte) * alpha_bitmap,
|
||||||
|
size_t width, size_t height)
|
||||||
|
{
|
||||||
|
y += height - 1u;
|
||||||
|
size_t bitmap_index;
|
||||||
|
for (size_t iy = 0u; iy < height; iy++)
|
||||||
|
{
|
||||||
|
for (size_t ix = 0u; ix < width; ix++)
|
||||||
|
{
|
||||||
|
size_t buffer_index = buffer_index(x + ix, y);
|
||||||
|
ubyte alpha = alpha_bitmap[bitmap_index];
|
||||||
|
m_buffer[buffer_index] = (alpha << 16u) | (alpha << 8u) | alpha;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
|
y--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blit an 8-bit alpha bitmap to the framebuffer.
|
||||||
|
* The foreground will be white (based on the alpha value), and the
|
||||||
|
* background black.
|
||||||
|
*
|
||||||
|
* @param x X coordinate of left side of target location.
|
||||||
|
* @param y Y coordinate of bottom side of target location.
|
||||||
|
* @param alpha_bitmap 8-bit alpha-channel bitmap.
|
||||||
|
* @param width Bitmap width.
|
||||||
|
* @param height Bitmap height.
|
||||||
|
*/
|
||||||
|
static void blit_alpha_bitmap(size_t x, size_t y, const(ubyte)[] alpha_bitmap,
|
||||||
|
size_t width, size_t height)
|
||||||
|
{
|
||||||
|
blit_alpha_bitmap(x, y, alpha_bitmap.ptr, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy framebuffer rows up in the framebuffer.
|
||||||
|
*
|
||||||
|
* @param y Y coordinate of bottom side of region to copy up.
|
||||||
|
* @param height Height of region to copy up.
|
||||||
|
* @param offset Number of rows to copy region up by.
|
||||||
|
*/
|
||||||
|
static void copy_rows_up(size_t y, size_t height, size_t offset)
|
||||||
|
{
|
||||||
|
memcpy32(&m_buffer[buffer_index(0u, y + height + offset - 1u)],
|
||||||
|
&m_buffer[buffer_index(0u, y + height - 1u)],
|
||||||
|
(m_stride * height));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale a color value by an alpha amount.
|
||||||
|
*
|
||||||
|
* @param color Color value.
|
||||||
|
* @param alpha Alpha amount.
|
||||||
|
*
|
||||||
|
* @return Scaled color value.
|
||||||
|
*/
|
||||||
|
private static uint scale_color(uint color, ubyte alpha)
|
||||||
|
{
|
||||||
|
return ((((color & 0xFFu) * alpha) >> 8u) & 0xFFu) |
|
||||||
|
((((color & 0xFF00u) * alpha) >> 8u) & 0xFF00u) |
|
||||||
|
((((color & 0xFF0000u) * alpha) >> 8u) & 0xFF0000u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the buffer index for the given X and Y coordinates.
|
||||||
|
*
|
||||||
|
* @param x X coordinate from left side of framebuffer.
|
||||||
|
* @param y Y coordinate from bottom side of framebuffer.
|
||||||
|
*
|
||||||
|
* @return Buffer index for the given X and Y coordinates.
|
||||||
|
*/
|
||||||
|
private static size_t buffer_index(size_t x, size_t y)
|
||||||
|
{
|
||||||
|
return (m_height - y - 1u) * m_stride + x;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* HULK image header.
|
||||||
|
*/
|
||||||
|
module hulk.header;
|
||||||
|
|
||||||
|
import hulk.bootinfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header describing the HULK image.
|
||||||
|
*/
|
||||||
|
struct HulkHeader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/** Stack size. */
|
||||||
|
ulong stack_size;
|
||||||
|
|
||||||
|
/** Virtual base address. */
|
||||||
|
ulong virt_base;
|
||||||
|
|
||||||
|
/** Stack top virtual address. */
|
||||||
|
ulong virt_stack_top;
|
||||||
|
|
||||||
|
/** Framebuffer virtual address. */
|
||||||
|
ulong virt_fb_buffer;
|
||||||
|
|
||||||
|
/** HULK boot information. */
|
||||||
|
BootInfo bootinfo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* HULK, the HOS Ultra Light Kernel.
|
||||||
|
*/
|
||||||
|
module hulk.hulk;
|
||||||
|
|
||||||
|
import hulk.header;
|
||||||
|
import hulk.fb;
|
||||||
|
import hulk.console;
|
||||||
|
import hos.memory;
|
||||||
|
import ldc.attributes;
|
||||||
|
import hulk.kfont;
|
||||||
|
import hulk.klog;
|
||||||
|
import hulk.hurl;
|
||||||
|
|
||||||
|
extern extern(C) __gshared ubyte _hulk_total_size;
|
||||||
|
|
||||||
|
@(ldc.attributes.section(".hulk_header"))
|
||||||
|
private __gshared HulkHeader hulk_header = {
|
||||||
|
&_hulk_total_size, /* total_size */
|
||||||
|
&hulk_start, /* entry */
|
||||||
|
16u * 1024u, /* stack_size */
|
||||||
|
HULK_VIRTUAL_BASE_ADDRESS, /* virt_base */
|
||||||
|
HULK_VIRTUAL_STACK_TOP_ADDRESS, /* virt_stack_top */
|
||||||
|
HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, /* virt_fb_buffer */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HULK entry point.
|
||||||
|
*/
|
||||||
|
void hulk_start()
|
||||||
|
{
|
||||||
|
fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, hulk_header.bootinfo.fb.width, hulk_header.bootinfo.fb.height, hulk_header.bootinfo.fb.stride);
|
||||||
|
console.initialize();
|
||||||
|
console.clear();
|
||||||
|
klog.initialize();
|
||||||
|
|
||||||
|
klog.writefln("Welcome to HULK, the HOS UltraLight Kernel!");
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0xFFFF800000000000;
|
||||||
|
_hulk_mem_start = .;
|
||||||
|
|
||||||
|
.hulk_header BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.hulk_header)
|
||||||
|
}
|
||||||
|
_hulk_header_size = . - _hulk_mem_start;
|
||||||
|
|
||||||
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* HURL, the HOS Unreal Region Locator.
|
||||||
|
*
|
||||||
|
* HURL provides virtual memory management for HULK.
|
||||||
|
*/
|
||||||
|
module hulk.hurl;
|
||||||
|
|
||||||
|
/** HULK virtual base address. */
|
||||||
|
enum ulong HULK_VIRTUAL_BASE_ADDRESS = 0xFFFF_8000_0000_0000u;
|
||||||
|
|
||||||
|
/** HULK virtual stack top address. */
|
||||||
|
enum ulong HULK_VIRTUAL_STACK_TOP_ADDRESS = 0xFFFF_A000_0000_0000u;
|
||||||
|
|
||||||
|
/** HULK virtual framebuffer address. */
|
||||||
|
enum ulong HULK_VIRTUAL_FRAMEBUFFER_ADDRESS = 0xFFFF_A000_0000_0000u;
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* HULK Kernel Log buffer.
|
||||||
|
*/
|
||||||
|
module hulk.klog;
|
||||||
|
|
||||||
|
import core.stdc.stdarg;
|
||||||
|
import hulk.console;
|
||||||
|
static import hulk.writef;
|
||||||
|
|
||||||
|
struct klog
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Kernel buffer size log.
|
||||||
|
* 16 gives a kernel buffer size of 64KB.
|
||||||
|
*/
|
||||||
|
private enum size_t KLOG_SIZE_LOG = 16u;
|
||||||
|
|
||||||
|
/** Kernel buffer size. */
|
||||||
|
private enum size_t KLOG_SIZE = 1u << KLOG_SIZE_LOG;
|
||||||
|
|
||||||
|
/** Kernel log buffer. */
|
||||||
|
private static __gshared align(4096) char[KLOG_SIZE] klog_buffer;
|
||||||
|
|
||||||
|
/** Write index in the kernel log buffer. */
|
||||||
|
private static __gshared size_t klog_index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the klog module.
|
||||||
|
*/
|
||||||
|
public static void initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a formatted string to the kernel log.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
* @param args Variable arguments structure.
|
||||||
|
*/
|
||||||
|
public static void writef(string s, va_list args)
|
||||||
|
{
|
||||||
|
hulk.writef.writef(s, args, function void(ubyte ch) {
|
||||||
|
console.write(ch);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a formatted string to the kernel log.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
*/
|
||||||
|
public static extern (C) void writef(string s, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, s);
|
||||||
|
writef(s, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a formatted string and newline to the console.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
*/
|
||||||
|
public static extern (C) void writefln(string s, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, s);
|
||||||
|
writef(s, args);
|
||||||
|
writef("\n", args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/**
|
||||||
|
* HULK Formatted stream writing support.
|
||||||
|
*/
|
||||||
|
module hulk.writef;
|
||||||
|
|
||||||
|
import core.stdc.stdarg;
|
||||||
|
|
||||||
|
alias ch_out_fn = void function(ubyte);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a string and write characters to the given output function.
|
||||||
|
*
|
||||||
|
* @param s Format string.
|
||||||
|
* @param args Variable arguments structure.
|
||||||
|
* @param ch_out Character output function.
|
||||||
|
*
|
||||||
|
* @return Number of characters written.
|
||||||
|
*/
|
||||||
|
size_t writef(string s, va_list args, ch_out_fn ch_out)
|
||||||
|
{
|
||||||
|
size_t length_written;
|
||||||
|
bool escape = false;
|
||||||
|
char pad = ' ';
|
||||||
|
size_t width;
|
||||||
|
foreach (char c; s)
|
||||||
|
{
|
||||||
|
if (escape)
|
||||||
|
{
|
||||||
|
if (c == 'x')
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
va_arg(args, v);
|
||||||
|
length_written += write_hex(v, false, pad, width, ch_out);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
else if (c == 'X')
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
va_arg(args, v);
|
||||||
|
length_written += write_hex(v, true, pad, width, ch_out);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
else if (c == 'u')
|
||||||
|
{
|
||||||
|
ulong v;
|
||||||
|
va_arg(args, v);
|
||||||
|
length_written += write_udec(v, pad, width, ch_out);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
else if ((c == '0') && (width == 0u))
|
||||||
|
{
|
||||||
|
pad = '0';
|
||||||
|
}
|
||||||
|
else if (('0' <= c) && (c <= '9'))
|
||||||
|
{
|
||||||
|
width = (width * 10u) + (c - '0');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch_out(c);
|
||||||
|
escape = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '%')
|
||||||
|
{
|
||||||
|
escape = true;
|
||||||
|
pad = ' ';
|
||||||
|
width = 0u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch_out(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return length_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a value in hexadecimal to the given output function.
|
||||||
|
*
|
||||||
|
* @param v Value to format.
|
||||||
|
* @param upper Whether to use uppercase letters.
|
||||||
|
* @param pad Pad character to use.
|
||||||
|
* @param width Field width.
|
||||||
|
* @param ch_out Character output function.
|
||||||
|
*
|
||||||
|
* @return Number of characters written.
|
||||||
|
*/
|
||||||
|
private size_t write_hex(ulong v, bool upper, char pad, size_t width, ch_out_fn ch_out)
|
||||||
|
{
|
||||||
|
string hex_chars_lower = "0123456789abcdef";
|
||||||
|
string hex_chars_upper = "0123456789ABCDEF";
|
||||||
|
char[16] buf;
|
||||||
|
size_t i;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ulong n = v & 0xFu;
|
||||||
|
buf[i] = upper ? hex_chars_upper[n] : hex_chars_lower[n];
|
||||||
|
v >>= 4u;
|
||||||
|
i++;
|
||||||
|
} while (v != 0u);
|
||||||
|
size_t length_written = i;
|
||||||
|
while (width > i)
|
||||||
|
{
|
||||||
|
ch_out(pad);
|
||||||
|
width--;
|
||||||
|
length_written++;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
ch_out(buf[i]);
|
||||||
|
} while (i != 0u);
|
||||||
|
return length_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a value in decimal to the given output function.
|
||||||
|
*
|
||||||
|
* @param v Value to format.
|
||||||
|
* @param pad Pad character to use.
|
||||||
|
* @param width Field width.
|
||||||
|
* @param ch_out Character output function.
|
||||||
|
*
|
||||||
|
* @return Number of characters written.
|
||||||
|
*/
|
||||||
|
private size_t write_udec(ulong v, char pad, size_t width, ch_out_fn ch_out)
|
||||||
|
{
|
||||||
|
char[20] buf;
|
||||||
|
size_t i;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ulong d = v % 10u;
|
||||||
|
buf[i] = cast(char)(d + '0');
|
||||||
|
v /= 10u;
|
||||||
|
i++;
|
||||||
|
} while (v != 0u);
|
||||||
|
size_t length_written = i;
|
||||||
|
while (width > i)
|
||||||
|
{
|
||||||
|
ch_out(pad);
|
||||||
|
width--;
|
||||||
|
length_written++;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
ch_out(buf[i]);
|
||||||
|
} while (i != 0u);
|
||||||
|
return length_written;
|
||||||
|
}
|
||||||
Submodule
+1
Submodule uefi-d added at e70959ce8a.
@@ -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"
|
||||||
Reference in new issue
Block a user