65 Commits
Author SHA1 Message Date
josh c6ae200a54 Update to rscons 2.3.0
Move cross compiler to i686-elf-gcc directory.
Automatically build cross compiler using rscons subsidiary script.
2021-12-08 11:33:03 -05:00
josh 6b1de7c9d4 Explicitly check page boundaries when adding bootloader-provided memory regions 2021-08-16 17:35:11 -04:00
josh ebfeca47b5 Use size_t rather than uint32_t 2021-08-16 14:01:39 -04:00
josh 43f4a1f4b1 Show kernel size/address 2021-08-16 13:59:39 -04:00
josh 0f73efbdc3 add mm module to manage free physical page regions 2020-10-26 20:17:08 -04:00
josh a084ab296c define _hos_mem_start and _hos_mem_end symbols 2020-10-25 17:08:07 -04:00
josh aa28284187 build kernel .size file on build 2020-10-25 17:06:56 -04:00
josh 87c135b010 set up a GDT to stop using the one GRUB set up 2020-10-25 16:49:09 -04:00
josh 3d30025d3b write a map file when linking 2020-10-25 16:48:42 -04:00
josh 556b0f0c4d add gdt.h 2020-10-23 00:48:40 -04:00
josh bffd652c16 walk multiboot2 memory map 2020-10-23 00:47:19 -04:00
josh cbd427b14b add 64-bit formatting support 2020-10-23 00:46:40 -04:00
josh fa4ff5facf load some multiboot2 info after the framebuffer is initialized 2020-10-22 22:03:43 -04:00
josh db16e69d5d add klog module to print kernel messages 2020-10-20 21:44:21 -04:00
josh 1d3b0a5621 make fb_clear() public 2020-10-20 20:24:48 -04:00
josh d03a34ab3e fb: store fb.pitch in words, not bytes 2020-10-20 20:07:51 -04:00
josh 494ef6de81 add fb_width(), fb_height() 2020-10-20 20:06:54 -04:00
josh 784009ba6c hos_printf: handle field width, zero-padding, and left-justifiying conversion specifiers 2020-10-20 19:56:30 -04:00
josh 9bddf11ee4 stream: use char instead of uint8_t 2020-10-20 19:47:15 -04:00
josh 313b86fdc7 provide an implementation for memcpy() 2020-10-20 19:31:26 -04:00
josh 75491dd36b add hos_printf and stream modules 2020-10-20 19:30:23 -04:00
josh c8db9fe905 add string.h 2020-10-20 17:55:31 -04:00
josh d0cbaba4d1 add memcpy(), memmove(), memset() 2020-10-20 17:47:40 -04:00
josh 1f22d0c900 add a few multiboot2 info structures 2020-10-20 17:34:08 -04:00
josh a474368435 increase kernel font size a little 2020-10-20 17:28:43 -04:00
josh fb88595dec add fb_clear(), just clear to solid bluish color for now 2020-10-20 17:28:16 -04:00
josh 70b4db9dbb fix fb_text_render_char() to use given color 2020-10-20 17:23:51 -04:00
josh 9fde638b6e build with -O2 2020-10-20 15:09:00 -04:00
josh b4b77dd52c add mem.h and memset32() 2020-10-20 15:08:12 -04:00
josh 79951bd0f1 add cross/clean.sh 2020-10-20 14:15:28 -04:00
josh 41152cb4ca add fb_fill() 2020-10-20 14:01:14 -04:00
josh dba3d28bbf draw a character 2020-10-20 13:34:02 -04:00
josh 610f30fae9 generate a built-in kernel font 2020-10-20 00:34:53 -04:00
josh e22b90b768 configure GRUB to boot HOS automatically after 1s 2020-10-20 00:17:05 -04:00
josh 08fc9a5445 rename target run-bios -> run 2020-10-20 00:11:12 -04:00
josh a66df19edc add fb_ready() 2020-10-20 00:09:09 -04:00
josh 5bc844649b set desired framebuffer size to 1600x900x32 2020-10-19 23:57:54 -04:00
josh 0d390465f6 simplify boot.S 2020-10-19 23:42:02 -04:00
josh 04d29fdb71 add mbinfo module to parse multiboot2 boot info 2020-10-19 23:34:42 -04:00
josh e9f426894c rename kernel_main.c -> hos_main.c 2020-10-19 22:40:55 -04:00
josh c8810e4701 rename _start -> hos_start 2020-10-19 22:26:12 -04:00
josh b202eca0cc define startup stack in linker script, not assembly 2020-10-19 22:23:39 -04:00
josh 05de14800b remove hard tabs! 2020-10-19 22:12:34 -04:00
josh 8ae84716d6 rename kernel_main() to hos_main() 2020-10-19 22:12:17 -04:00
josh bb495eceec add "fb" module for framebuffer control 2020-10-19 22:09:33 -04:00
josh 67b90a482f add "clean" target 2020-10-19 21:59:54 -04:00
josh 85e5b76aa3 Move multiboot2 header from assembly to C. 2020-10-19 21:44:27 -04:00
josh 412925a790 switch from multiboot to multiboot2 2020-10-18 14:25:06 -04:00
josh 21afa93c4b fill in framebuffer with more exciting pattern - working in qemu BIOS but lost graphics in qemu EFI 2020-10-18 13:47:35 -04:00
josh d08d54ecbf make run tasks depend on all 2020-10-18 13:29:56 -04:00
josh 06644a02f9 draw pixels to screen to verify framebuffer access and multiboot info 2020-10-18 13:25:26 -04:00
josh 8f9881889b build both BIOS and EFI images 2020-10-18 13:16:02 -04:00
josh a91ea8d620 update Makefile to wrap rscons and add run target 2020-10-15 20:05:58 -04:00
josh a9a2f6dcaf fix GRUB config to add a HOS menu entry 2020-10-15 20:01:40 -04:00
josh 9befd553eb always disassemble kernel when building 2020-10-15 19:47:20 -04:00
josh 6053745ee9 build kernel as 32-bit ELF for now so GRUB can recognize it as multiboot 2020-10-15 19:46:53 -04:00
josh 0adc6e395c Add more modern build script for kernel and disk image based on osdev Bare Bones template
GRUB is not identifying the kernel as multiboot compatible. Possibly
because I am using x86_64 instead of i686. Need to investigate further.
2020-10-14 21:20:41 -04:00
josh bbf212d5a2 add configure script 2020-10-13 19:53:14 -04:00
josh 94ed9078df update rscons 2020-10-13 19:20:19 -04:00
josh e97e76da7b add cross compiler build script and configure script 2020-10-06 20:06:19 -04:00
josh 1f5e3507ba change nasm output format to elf32 2020-10-02 10:21:10 -04:00
josh a9a6f6f4d4 avoid make jobserver warnings 2020-10-02 10:17:32 -04:00
josh 2d009273a1 add readme.txt 2017-07-26 13:51:58 -04:00
josh 2b936758ff add .gitignore 2017-07-26 13:42:21 -04:00
josh 509009d134 get HOS building again on Ubuntu 17.04 with GCC 6 2017-07-26 13:41:23 -04:00
45 changed files with 1925 additions and 271 deletions

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
/hos.flp
/hos_initrd
/hos_initrd.gz
*.lst
*.map
*.bin
.rscons*
/i686-elf-gcc/build*/
/i686-elf-gcc/*.xz
/i686-elf-gcc/binutils-*/
/i686-elf-gcc/gcc-*/
/i686-elf-gcc/i686-elf-gcc/
/build/
+12 -85
View File
@@ -1,88 +1,15 @@
# Makefile for HOS
# Josh Holtrop
# Created: 07/09/04
FLOPPY=/dev/fd0
FLOPPY_IMAGE=hos.flp
FLOPPY_MOUNT=./mnt_flp
GRUB_IMAGE=grub.flp
INITRD=hos_initrd
INITRD_DIR=initrd
INITRD_MOUNT=./mnt_initrd
INITRD_SIZE=100 #initrd size in kb
MOUNT=sudo mount
UMOUNT=sudo umount
# Do not print "Entering directory ..."
MAKEFLAGS += --no-print-directory
.PHONY: all clean initrd apps grub_image install install_img depend copy_image bochs bochsq
.PHONY: all
all:
make -C kernel
make -C rmmod
./rscons build
.PHONY: run-efi
run-efi: all
qemu-system-x86_64 -bios OVMF.fd -hda build/hos-efi.img
.PHONY: run
run: all
qemu-system-x86_64 -hda build/hos.img
.PHONY: clean
clean:
-make -C kernel clean
-make -C rmmod clean
-rm -f *~ *.out hos.flp \#* hos_initrd hos_initrd.gz
apps:
make -C apps
grub_image:
dd if=/dev/zero of=$(GRUB_IMAGE) bs=1024 seek=1440 count=0
-mkdir $(FLOPPY_MOUNT)
mke2fs -F $(GRUB_IMAGE)
$(MOUNT) -t ext2 -o loop $(GRUB_IMAGE) $(FLOPPY_MOUNT)
-mkdir -p $(FLOPPY_MOUNT)/boot/grub
-cp /boot/grub/stage1 /boot/grub/stage2 /boot/grub/e2fs_stage1_5 $(FLOPPY_MOUNT)/boot/grub
$(UMOUNT) $(FLOPPY_MOUNT)
-rmdir $(FLOPPY_MOUNT)
echo "(fd0) $(GRUB_IMAGE)" > grub_image_device.map.tmp
echo "root (fd0)" > grub_commands.tmp
echo "setup (fd0)" >> grub_commands.tmp
echo "quit" >> grub_commands.tmp
grub --device-map grub_image_device.map.tmp < grub_commands.tmp
rm grub_commands.tmp
rm grub_image_device.map.tmp
copy_image:
cp $(GRUB_IMAGE) $(FLOPPY_IMAGE)
install: FDEV=$(FLOPPY)
install_img: FDEV=$(FLOPPY_IMAGE)
install_img: MOUNT_FLAGS=-o loop
install_img: copy_image
install install_img:
-mkdir $(FLOPPY_MOUNT)
$(MOUNT) -t ext2 $(MOUNT_FLAGS) $(FDEV) $(FLOPPY_MOUNT)
-cp kernel/kernel.bin $(FLOPPY_MOUNT)
-cp rmmod/rmmod.bin $(FLOPPY_MOUNT)
-cp menu.lst $(FLOPPY_MOUNT)/boot/grub
-cp $(INITRD).gz $(FLOPPY_MOUNT)/$(INITRD).gz
$(UMOUNT) $(FLOPPY_MOUNT)
-rmdir $(FLOPPY_MOUNT)
initrd:
dd if=/dev/zero of=$(INITRD) bs=1024 count=$(INITRD_SIZE)
mke2fs -Fv -m0 -r0 -i1024 $(INITRD)
-mkdir $(INITRD_MOUNT)
$(MOUNT) -t ext2 -o loop $(INITRD) $(INITRD_MOUNT)
cp -Pr $(INITRD_DIR)/* $(INITRD_MOUNT)
$(UMOUNT) $(INITRD_MOUNT)
rm -rf $(INITRD_MOUNT)
gzip -c $(INITRD) > $(INITRD).gz
depend:
make -C kernel depend
bochs:
bochs
bochsq:
echo 'c' | bochs -q
wordcount:
find . -regex '\(.*\.[ch]\)\|\(.*\.asm\)\|\(.*\.inc\)\|\(.*\.cpp\)' | xargs cat | wc
./rscons clean
+155
View File
@@ -0,0 +1,155 @@
path_prepend "i686-elf-gcc/i686-elf-gcc/bin"
configure do
rscons "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
build do
require "tmpdir"
# EFI (w/ GRUB) partition size (MiB)
EFI_PART_SIZE = 8
# HOS partition size (MiB)
HOS_PART_SIZE = 4
# Kernel default font size
KFONT_SIZE = 15
class BiosImage < Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Generating BIOS boot image #{@target}", nil)
Dir.mktmpdir do |tmpdir|
# Create iso directory.
FileUtils.mkdir_p("#{tmpdir}/iso/boot/grub")
File.open("#{tmpdir}/iso/boot/grub/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
set default="0"
set timeout=1
menuentry "HOS" {
insmod multiboot2
multiboot2 /hos.elf
}
EOF
end
@sources.each do |source|
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)
end
true
end
end
class EfiImage < Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Generating EFI boot image #{@target}", nil)
Dir.mktmpdir do |tmpdir|
# Build a standalone GRUB.
File.open("#{tmpdir}/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
insmod part_gpt
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)
end
true
end
end
class FontGen < Builder
def run(options)
if @command
finalize_command
else
@sources += ["build/fontgen"]
command = %W[build/fontgen #{@sources.first} #{KFONT_SIZE} #{@target}]
standard_command("FontGen <target>#{@target}<reset>", command, {})
end
end
end
class Size < Builder
def run(options)
if @command
finalize_command
else
@vars["_SOURCES"] = @sources
@vars["_TARGET"] = @target
command = @env.build_command(%w[${SIZE} ${_SOURCES}], @vars)
standard_command("Size <target>#{@target}<reset>", command, stdout: @target)
end
end
end
# FontGen Environment
Environment.new(use: "freetype") do |env|
env["CC"] = "gcc"
env.Program("build/fontgen", glob("fontgen/**/*.c"))
end
# Kernel Environment
Environment.new do |env|
env.add_builder(EfiImage)
env.add_builder(BiosImage)
env.add_builder(FontGen)
env.add_builder(Size)
env["OBJDUMP"] = "i686-elf-objdump"
env["SIZE"] = "i686-elf-size"
env["CCFLAGS"] += %w[-ffreestanding -Wall -O2]
env["LDFLAGS"] += %w[-ffreestanding -nostdlib -T src/link.ld]
env["LDFLAGS"] += %W[-Wl,-Map,${_TARGET}.map]
env["LIBS"] += %w[gcc]
env.FontGen("^/kfont/kfont.c", "font/Hack-Regular.ttf")
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("build/hos-efi.img", %w[^/hos.elf])
env.BiosImage("build/hos.img", %w[^/hos.elf])
end
end
Vendored Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exec ./rscons configure "$@"
Binary file not shown.
+224
View File
@@ -0,0 +1,224 @@
#include <stdlib.h>
#include <stdint.h>
#include <ft2build.h>
#include <stdio.h>
#include FT_FREETYPE_H
#include <string.h>
#include <strings.h>
#include <ctype.h>
#define N_CHARS 128
#define round_up_26_6(val) (((val) + 63) >> 6u)
int max_advance;
int max_top = -9999;
int min_bottom = 9999;
int line_height;
int baseline_offset;
typedef struct {
int width;
int height;
int top;
int left;
uint8_t * bitmap;
} char_info_t;
static char_info_t char_infos[N_CHARS];
static void load_char(FT_Face face, int char_code)
{
if (FT_Load_Char(face, char_code, FT_LOAD_RENDER) != 0)
{
return;
}
int advance = round_up_26_6(face->glyph->advance.x);
if (advance > max_advance)
{
max_advance = advance;
}
if ((face->glyph->bitmap.width == 0) ||
(face->glyph->bitmap.rows == 0))
{
return;
}
char_infos[char_code].width = face->glyph->bitmap.width;
char_infos[char_code].height = face->glyph->bitmap.rows;
char_infos[char_code].top = face->glyph->bitmap_top;
if (char_infos[char_code].top > max_top)
{
max_top = char_infos[char_code].top;
}
int bottom = char_infos[char_code].top - char_infos[char_code].height;
if (bottom < min_bottom)
{
min_bottom = bottom;
}
char_infos[char_code].left = face->glyph->bitmap_left;
char_infos[char_code].bitmap = malloc(char_infos[char_code].width * char_infos[char_code].height);
memcpy(char_infos[char_code].bitmap,
face->glyph->bitmap.buffer,
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)
{
for (int i = 0; i < count; i++)
{
if (i % 8 == 0)
{
fprintf(file, " ");
}
fprintf(file, "0x%02xu,", bytes[i]);
if ((i + 1) % 8 == 0)
{
fprintf(file, "\n");
}
else if (i < (count - 1))
{
fprintf(file, " ");
}
}
if (count % 8 != 0)
{
fprintf(file, "\n");
}
}
static void generate(const char * c_file_name)
{
char * h_file_name = malloc(strlen(c_file_name) + 1);
strcpy(h_file_name, c_file_name);
h_file_name[strlen(h_file_name) - 1] = 'h';
char * guard = include_guard_name(h_file_name);
FILE * h_file = fopen(h_file_name, "wb");
fprintf(h_file, "#ifndef %s\n", guard);
fprintf(h_file, "#define %s\n\n", guard);
fprintf(h_file, "#include <stdint.h>\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(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(h_file, "extern const fontgen_font_t kfont;\n");
fprintf(h_file, "#endif\n");
fclose(h_file);
FILE * c_file = fopen(c_file_name, "wb");
fprintf(c_file, "#include \"%s\"\n", bare_header_name(h_file_name));
fprintf(c_file, "#include <stddef.h>\n");
for (int i = 0; i < N_CHARS; i++)
{
if (char_infos[i].width > 0)
{
fprintf(c_file, "static const uint8_t char_bitmap_%d[] = {\n", i);
generate_bytes(c_file, char_infos[i].bitmap, char_infos[i].width * char_infos[i].height);
fprintf(c_file, "};\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
{
fprintf(c_file, " NULL,\n");
}
fprintf(c_file, "};\n\n");
}
fprintf(c_file, "const fontgen_char_info_t * char_infos[] = {\n");
for (int i = 0; i < N_CHARS; i++)
{
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[])
{
/* Expect: font file, size, out file */
if (argc != 4)
{
fprintf(stderr, "Incorrect arguments\n");
return 1;
}
const char * font_file = argv[1];
int size = atoi(argv[2]);
const char * out_file = argv[3];
FT_Library ft_library;
if (FT_Init_FreeType(&ft_library) != 0)
{
fprintf(stderr, "Could not initialize freetype\n");
return 2;
}
FT_Face face;
if (FT_New_Face(ft_library, font_file, 0, &face) != 0)
{
fprintf(stderr, "Could not open %s\n", font_file);
return 3;
}
FT_Set_Pixel_Sizes(face, 0, size);
for (int i = 0; i < N_CHARS; i++)
{
load_char(face, i);
}
line_height = round_up_26_6(face->size->metrics.height);
baseline_offset = (line_height - (max_top - min_bottom)) / 2 - min_bottom;
generate(out_file);
return 0;
}
+17
View File
@@ -0,0 +1,17 @@
configure do
check_c_compiler "gcc"
check_program "make"
check_program "bison"
check_program "flex"
check_program "texi2any", on_fail: "Install the texinfo package"
check_program "wget"
check_lib "gmp", on_fail: "Install the libgmp-dev package"
check_lib "mpc", on_fail: "Install the libmpc-dev package"
check_lib "mpfr", on_fail: "Install the libmpfr-dev package"
end
build do
unless File.exist?("i686-elf-gcc")
system("./build.sh")
end
end
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
BINUTILS_VERSION="2.35"
BINUTILS_CHECKSUM="1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85"
GCC_VERSION="10.2.0"
GCC_CHECKSUM="b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
if [ ! -e binutils-${BINUTILS_VERSION}.tar.xz ]; then
wget -O binutils-${BINUTILS_VERSION}.tar.xz https://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VERSION}.tar.xz
fi
if [[ ! `sha256sum binutils-${BINUTILS_VERSION}.tar.xz` =~ $BINUTILS_CHECKSUM ]]; then
echo "Invalid binutils-${BINUTILS_VERSION}.tar.xz checksum"
exit
fi
if [ ! -d binutils-${BINUTILS_VERSION} ]; then
tar xJf binutils-${BINUTILS_VERSION}.tar.xz
fi
if [ ! -e gcc-${GCC_VERSION}.tar.xz ]; then
wget -O gcc-${GCC_VERSION}.tar.xz https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.xz
fi
if [[ ! `sha256sum gcc-${GCC_VERSION}.tar.xz` =~ $GCC_CHECKSUM ]]; then
echo "Invalid gcc-${GCC_VERSION}.tar.xz checksum"
exit
fi
if [ ! -d gcc-${GCC_VERSION} ]; then
tar xJf gcc-${GCC_VERSION}.tar.xz
fi
export PREFIX="$PWD/i686-elf-gcc"
export TARGET="i686-elf"
export PATH="$PREFIX/bin:$PATH"
function build_binutils()
{
rm -rf build-binutils
mkdir -p build-binutils
(
cd build-binutils
../binutils-${BINUTILS_VERSION}/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror && \
make && \
make install
)
}
function build_gcc()
{
rm -rf build-gcc
mkdir -p build-gcc
(
cd build-gcc
../gcc-${GCC_VERSION}/configure --target="$TARGET" --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers && \
make all-gcc && \
make all-target-libgcc && \
make install-gcc && \
make install-target-libgcc
)
}
build_binutils && build_gcc
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
rm -rf build build-* binutils* gcc-*
Vendored Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exec ../rscons configure
+7 -6
View File
@@ -5,18 +5,19 @@
# Assembler Information:
NASM=nasm
NASM_FLAGS=-f aout
NASM_FLAGS=-f elf32
# C/C++ Information:
CPPFLAGS=-fleading-underscore -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -I. -Wall
CPPFLAGS=-ffreestanding -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -I. -Wall -m32 -fno-pic
# -S -masm=intel
CC=gcc
CXX=g++
CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_
CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_ -std=gnu++98
# Linker Information:
LD=ld
LDFLAGS=-nodefaultlibs -nostdlib --no-demangle -T link.ld
LD=gcc
LDFLAGS=-ffreestanding -fno-builtin -nostartfiles -nodefaultlibs -nostdlib -Wl,--no-demangle -T link.ld -m32
LIBS=-static-libgcc
# Files
OBJS=boot.o lang/lang_a.o \
@@ -43,7 +44,7 @@ CXXSRC=lang/string.cpp lang/new.cpp char/misc_char.cpp char/vconsole.cpp \
.PHONY: all depend clean html
all: $(OBJS)
$(LD) $(LDFLAGS) -Map kernel.map $(OBJS) -o kernel.bin
$(LD) $(LDFLAGS) -Wl,-Map -Wl,kernel.map $(OBJS) -o kernel.bin $(LIBS)
@echo ' Kernel built: ' `ls -sk kernel.bin | cut -d' ' -f1`kb
depend:
+14 -14
View File
@@ -25,23 +25,23 @@
%define KERNEL_P PHYS_START+0x8000 ;1mb+32kb - the kernel's physical address
%define KERNEL_V KERNEL_P+VIRT_OFFSET ;3gb+1mb+32kb, the virtual address of the kernel
extern _k_init, _isr, _k_mbsave, _end, _rm_params, _initrd, _tss0
extern k_init, isr, k_mbsave, end, rm_params, initrd, tss0
[bits 32]
[global _start]
_start:
[global start]
start:
multiboot_header:
dd MULTIBOOT_MAGIC ;magic
dd MULTIBOOT_FLAGS ;flags
dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) ;checksum
dd multiboot_header-VIRT_OFFSET ;header_addr
dd _start-VIRT_OFFSET ;load_addr
dd 0x100000000+multiboot_header-VIRT_OFFSET ;header_addr
dd 0x100000000+start-VIRT_OFFSET ;load_addr
dd 0 ;load_end_addr
dd _end-VIRT_OFFSET ;bss_end_addr
dd multiboot_entry-VIRT_OFFSET ;entry_addr
dd 0x100000000+end-VIRT_OFFSET ;bss_end_addr
dd 0x100000000+multiboot_entry-VIRT_OFFSET ;entry_addr
; dd 1 ;mode_type
; dd 80 ;width
@@ -53,7 +53,7 @@ multiboot_entry:
;This is where the kernel begins execution from the bootloader.
;At this point, a temporary gdt is set up to "map" 0xC000_0000 to 0x0.
cli ;should already be off...
lgdt [gdtrbs32-VIRT_OFFSET]
lgdt [0x100000000+gdtrbs32-VIRT_OFFSET]
jmp KERNEL_CODE_BS32:segmented_start
segmented_start:
mov cx, KERNEL_DATA_BS32
@@ -68,7 +68,7 @@ segmented_start:
add ebx, VIRT_OFFSET
push eax
push ebx ;pointer to multiboot info structure
call _k_mbsave ;save multiboot info structures
call k_mbsave ;save multiboot info structures
add esp, 8
cmp eax, 0 ; eax = pointer to mb_module_t struct for rmmod
@@ -86,7 +86,7 @@ segmented_start:
rep movsd ; copy rmmod to first 1mb
mov ebx, pm_return ; return address
mov ecx, _rm_params ; put real mode params here (video mode etc...)
mov ecx, rm_params ; put real mode params here (video mode etc...)
sub ecx, VIRT_OFFSET
jmp 0xC0005010 ; jump to rmmod
@@ -161,8 +161,8 @@ newgdtcontinue:
lidt [idtr] ;load idt
mov [PDBR_V], dword 0 ;unmap 0x0, we are running completely paged at 0xC000_0000
mov edi, GDT_V + TSS0_SEG + 2 ; copy _tss0 base address
mov eax, _tss0 ; into the GDT descrtiptor
mov edi, GDT_V + TSS0_SEG + 2 ; copy tss0 base address
mov eax, tss0 ; into the GDT descrtiptor
stosw ; for TSS0
shr eax, 16
stosb
@@ -170,7 +170,7 @@ newgdtcontinue:
shr eax, 8
stosb
call _k_init ;C kernel initialization
call k_init ;C kernel initialization
mov ax, TSS0_SEG
ltr ax
@@ -187,7 +187,7 @@ idle_loop: ; system idle loop
;-------------------------------------------------------
gdtrbs32:
dw gdt_endbs32-gdtbs32-1
dd gdtbs32-VIRT_OFFSET
dd 0x100000000+gdtbs32-VIRT_OFFSET
gdtbs32: ; 0 = null descriptor
dd 0
dd 0
+2 -2
View File
@@ -29,7 +29,7 @@ Ext2OpenFile::Ext2OpenFile(Ext2fs *fs, u32_t inum, int mode)
myBlockCacheStatus = 0; /* 0: invalid; 1: valid; 2: dirty */
fs->readInode(inum, &myInode);
myCache = new Ext2BlockCache(fs, inum, &myInode);
lock(&Ext2OpenFileListLock);
lockit(&Ext2OpenFileListLock);
if ((mode & VFS_MODE_RW_MASK) == VFS_MODE_WRITE)
{
if ((mode & VFS_MODE_WRITE_MASK) == VFS_MODE_TRUNCATE)
@@ -62,7 +62,7 @@ Ext2OpenFile::Ext2OpenFile(Ext2fs *fs, u32_t inum, int mode)
Ext2OpenFile::~Ext2OpenFile()
{
/* remove ourselves from the open file list */
lock(&Ext2OpenFileListLock);
lockit(&Ext2OpenFileListLock);
u32_t size = Ext2OpenFileList->size();
for (u32_t i = 0; i < size; i++)
{
+6
View File
@@ -9,9 +9,15 @@
#include "hos_defines.h"
#include "sys/io.h"
#ifdef __cplusplus
extern "C" {
#endif
extern u32_t _code;
extern u32_t _bss;
extern u32_t _end;
#ifdef __cplusplus
}
#endif
//Enables (SeTs) Interrupt Flag on the processor
static inline void enable_ints()
+6
View File
@@ -44,9 +44,15 @@ typedef unsigned char u8_t;
typedef unsigned char byte;
typedef int lock_t;
#ifdef __cplusplus
extern "C" {
#endif
extern u32_t _end;
extern u32_t _bss;
extern u32_t start;
#ifdef __cplusplus
}
#endif
#endif
+1 -1
View File
@@ -97,7 +97,7 @@ isr_main_nodup:
push esp
push eax ;interrupt number
call _isr
call isr
add esp, 8
pop gs
+38 -38
View File
@@ -13,8 +13,8 @@
%endmacro
;implements a lock
[global _lock]
_lock:
[global lockit]
lockit:
push ebp
mov ebp, esp
push eax
@@ -35,8 +35,8 @@ _lock_loop0:
ret
;releases a lock
[global _unlock]
_unlock:
[global unlock]
unlock:
push ebp
mov ebp, esp
push esi
@@ -50,15 +50,15 @@ _unlock:
;returns the value in the CR0 register
;extern dword read_cr0();
[global _read_cr0]
_read_cr0:
[global read_cr0]
read_cr0:
mov eax, cr0;
ret
;stores the parameter to the CR0 register
;extern dword write_cr0(dword cr0);
[global _write_cr0]
_write_cr0:
[global write_cr0]
write_cr0:
push ebp
mov ebp, esp
mov eax, [ebp+8]
@@ -68,8 +68,8 @@ _write_cr0:
;returns the value in the CR2 register
;extern dword read_cr2();
[global _read_cr2]
_read_cr2:
[global read_cr2]
read_cr2:
mov eax, cr2;
ret
@@ -77,16 +77,16 @@ _read_cr2:
;returns the value in the CR3 register
;extern dword read_cr3();
[global _read_cr3]
_read_cr3:
[global read_cr3]
read_cr3:
mov eax, cr3;
ret
;stores the parameter to the CR3 register
;extern dword write_cr3(dword cr3);
[global _write_cr3]
_write_cr3:
[global write_cr3]
write_cr3:
push ebp
mov ebp, esp
mov eax, [ebp+8]
@@ -96,16 +96,16 @@ _write_cr3:
; read ss register
[global _read_ss]
_read_ss:
[global read_ss]
read_ss:
mov ax, ss
ret
;copies a string from the source to the destination parameter
;extern void strcpy(char *dest, char *src);
[global _strcpy]
_strcpy:
[global strcpy]
strcpy:
push ebp
mov ebp, esp
push esi
@@ -124,8 +124,8 @@ strcpyloop:
;copies memory of n bytes from src to destination
;void memcpy(void *dest, void *src, dword n);
[global _memcpy]
_memcpy:
[global memcpy]
memcpy:
push ebp
mov ebp, esp
push esi
@@ -147,8 +147,8 @@ _memcpy:
;copies memory of n words (n*2 bytes) from src to destination
;void memcpyw(void *dest, void *src, dword n);
[global _memcpyw]
_memcpyw:
[global memcpyw]
memcpyw:
push ebp
mov ebp, esp
push esi
@@ -170,8 +170,8 @@ _memcpyw:
;copies memory of n dwords (n*4 bytes) from src to destination
;void memcpyd(void *dest, void *src, dword n);
[global _memcpyd]
_memcpyd:
[global memcpyd]
memcpyd:
push ebp
mov ebp, esp
push esi
@@ -193,8 +193,8 @@ _memcpyd:
;sets num bytes at buffer to the value of c
;void *memset(void *buffer, int c, int num);
[global _memset]
_memset:
[global memset]
memset:
push ebp
mov ebp, esp
push edi
@@ -215,8 +215,8 @@ _memset:
;sets num words at buffer to the value of c
;void *memsetw(void *buffer, int c, int num);
[global _memsetw]
_memsetw:
[global memsetw]
memsetw:
push ebp
mov ebp, esp
push edi
@@ -237,8 +237,8 @@ _memsetw:
;sets num dwords at buffer to the value of c
;void *memsetd(void *buffer, int c, int num);
[global _memsetd]
_memsetd:
[global memsetd]
memsetd:
push ebp
mov ebp, esp
push edi
@@ -259,8 +259,8 @@ _memsetd:
;returns the number of characters in a string
;extern dword strlen(char *str);
[global _strlen]
_strlen:
[global strlen]
strlen:
push ebp
mov ebp, esp
push esi
@@ -284,8 +284,8 @@ strlendone:
;this function invalidates the page directory/table entry that
; would be used to access the memory address given in the parameter
;extern void invlpg_(dword addr);
[global _invlpg_]
_invlpg_:
[global invlpg_]
invlpg_:
mov eax, [esp+4]
invlpg [eax]
ret
@@ -294,8 +294,8 @@ _invlpg_:
;
;void writeCursorPosition(word pos)
;
[global _writeCursorPosition]
_writeCursorPosition:
[global writeCursorPosition]
writeCursorPosition:
push ebp
mov ebp, esp
@@ -333,8 +333,8 @@ _writeCursorPosition:
;
;word getCursorPosition()
;
[global _getCursorPosition]
_getCursorPosition:
[global getCursorPosition]
getCursorPosition:
push ebx
push edx
+1 -1
View File
@@ -9,7 +9,7 @@
#include "hos_defines.h"
/* lang.asm */
void lock(lock_t *addr);
void lockit(lock_t *addr);
void unlock(lock_t *addr);
u32_t read_cr0();
u32_t write_cr0(u32_t cr0);
+87 -121
View File
@@ -15,6 +15,8 @@ template<typename type>
class vector
{
protected:
typedef type * type_ptr_t;
/* Pointers to vector elements */
type **myData;
@@ -25,127 +27,80 @@ protected:
unsigned int myAllocated;
/* Causes the vector to double in its allocated size */
void grow();
public:
/* Constructors/Destructor */
vector<type>();
vector<type>(unsigned int size);
vector<type>(const vector<type> & v1);
~vector<type>();
/* Assignment operator */
vector<type> & operator=(const vector<type> & v1);
/* Returns the size of the vector */
unsigned int size() const;
/* Add an element to the end of the vector */
vector<type> & add(type elem);
/* Remove an element from the vector */
vector<type> & remove(unsigned int index);
/* Insert an element into a position in the vector */
vector<type> & insert(type elem, unsigned int position);
/* Direct access operators */
const type & operator[](unsigned int index) const;
type & operator[](unsigned int index);
/* Returns pointer to data */
type **data();
};
template<typename type>
vector<type>::vector<type>()
{
myData = NULL;
mySize = 0;
myAllocated = 0;
}
template<typename type>
vector<type>::vector<type>(unsigned int size)
{
myData = new (type *)[size];
mySize = 0;
myAllocated = size;
}
template<typename type>
vector<type>::vector<type>(const vector<type> & v1)
{
mySize = v1.mySize;
myAllocated = v1.myAllocated;
myData = new (type *)[myAllocated];
for (u32_t i = 0; i < mySize; i++)
myData[i] = new type(*v1.myData[i]);
}
template<typename type>
vector<type>::~vector<type>()
{
for (unsigned int i = 0; i < mySize; i++)
delete myData[i];
delete[] myData;
}
template<typename type>
vector<type> & vector<type>::operator=(const vector<type> & v1)
{
mySize = v1.mySize;
myAllocated = v1.myAllocated;
myData = new (type *)[myAllocated];
for (u32_t i = 0; i < mySize; i++)
myData[i] = new type(*v1.myData[i]);
return *this;
}
template<typename type>
u32_t vector<type>::size() const
{
return mySize;
}
template<typename type>
const type & vector<type>::operator[](unsigned int index) const
{
return *myData[index];
}
template<typename type>
type & vector<type>::operator[](unsigned int index)
{
return *myData[index];
}
template<typename type>
vector<type> & vector<type>::add(type elem)
{
while (mySize >= myAllocated)
grow();
myData[mySize++] = new type(elem);
return *this;
}
template<typename type>
void vector<type>::grow()
{
void grow()
{
myAllocated <<= 1;
if (myAllocated == 0)
myAllocated = 1;
type **data_new = new (type *)[myAllocated];
type **data_new = new type_ptr_t[myAllocated];
for (unsigned int i = 0; i < mySize; i++)
data_new[i] = myData[i];
if (myData)
delete[] myData;
myData = data_new;
}
}
template<typename type>
vector<type> & vector<type>::remove(unsigned int index)
{
public:
/* Constructors/Destructor */
vector<type>()
{
myData = NULL;
mySize = 0;
myAllocated = 0;
}
vector<type>(unsigned int size)
{
myData = new type_ptr_t[size];
mySize = 0;
myAllocated = size;
}
vector<type>(const vector<type> & v1)
{
mySize = v1.mySize;
myAllocated = v1.myAllocated;
myData = new type_ptr_t[myAllocated];
for (u32_t i = 0; i < mySize; i++)
myData[i] = new type(*v1.myData[i]);
}
~vector<type>()
{
for (unsigned int i = 0; i < mySize; i++)
delete myData[i];
delete[] myData;
}
/* Assignment operator */
vector<type> & operator=(const vector<type> & v1)
{
mySize = v1.mySize;
myAllocated = v1.myAllocated;
myData = new type_ptr_t[myAllocated];
for (u32_t i = 0; i < mySize; i++)
myData[i] = new type(*v1.myData[i]);
return *this;
}
/* Returns the size of the vector */
unsigned int size() const
{
return mySize;
}
/* Add an element to the end of the vector */
vector<type> & add(type elem)
{
while (mySize >= myAllocated)
grow();
myData[mySize++] = new type(elem);
return *this;
}
/* Remove an element from the vector */
vector<type> & remove(unsigned int index)
{
if (index < mySize)
{
delete myData[index];
@@ -154,11 +109,11 @@ vector<type> & vector<type>::remove(unsigned int index)
mySize--;
}
return *this;
}
}
template<typename type>
vector<type> & vector<type>::insert(type elem, unsigned int position)
{
/* Insert an element into a position in the vector */
vector<type> & insert(type elem, unsigned int position)
{
if (position <= mySize)
{
if (mySize >= myAllocated)
@@ -169,13 +124,24 @@ vector<type> & vector<type>::insert(type elem, unsigned int position)
mySize++;
}
return *this;
}
}
/* Direct access operators */
const type & operator[](unsigned int index) const
{
return *myData[index];
}
template<typename type>
type **vector<type>::data()
{
type & operator[](unsigned int index)
{
return *myData[index];
}
/* Returns pointer to data */
type **data()
{
return myData;
}
}
};
#endif
+4 -3
View File
@@ -1,10 +1,11 @@
OUTPUT_FORMAT("binary")
ENTRY(_start)
ENTRY(start)
SECTIONS
{
.text 0xC0108000 : {
code = .; _code = .; __code = .;
*(.text)
*(.eh_frame*)
}
.gnulinkonce : {
*(.gnu.linkonce*)
@@ -12,8 +13,8 @@ SECTIONS
}
.data : {
data = .; _data = .; __data = .;
*(.data)
*(.rodata)
*(.data*)
*(.rodata*)
. = ALIGN(4096);
}
.bss : {
+89
View File
@@ -0,0 +1,89 @@
HOS - Holtrop's Operating System
--------------------------------
HOS is (in the process of becoming) a 32-bit, protected mode, graphical, multitasking operating system.
It was written by me, Josh Holtrop, with help from a few others along the way.
Goals: (A = accomplished, P = in progress, T = todo)
----------------------------------------------------
(A) Custom bootloader to load kernel from FAT-formatted boot media, options for video mode/ram disk
(A) Multiboot compliance - kernel can be loaded by GRUB
(A) 32-bit protected mode environment
(A) VESA Support for graphics modes
(A) PS/2 keyboard & mouse drivers
(A) Utilize x86's paging architecture for virtual memory management
(P) Console Manager
(P) VFS abstraction layer for a single file system
(P) ram disk driver
(P) devfs file system driver
(P) ext2 file system support
(T) vfat file system support
(T) Multitasking support
(T) HASH command shell
(T) Window Manager
(T) Various other utilities/applications
(T) Hard Drive (ATA) driver
(T) cdrom (ATAPI) driver
Change Log
----------
0.16
12/16/04 - initrd going to be loaded as a gzipped ext2 image (kernel module) - faster loading!
0.15
07/10/04 - Multiboot support added, loadable by GRUB
0.14
05/21/04 - C++ support in kernel, can use classes & templates
04/04/04 - video_line function for diagonal lines
03/16/04 - new VFS design with support for a loop device
03/01/04 - Thanks to Ben Meyer for helping me get a Makefile working and building on linux to work!
0.13
01/26/04 - functions added to read/write CMOS clock date and time
01/19/04 - fixed bug GDTR/IDTR pointing to physical rather than linear table base address
01/07/04 - fixed bug not reading sectors correctly from floppy
12/28/03 - fixed bug not storing eax on interrupt
12/25/03 - fixed bug in mm_palloc()
12/25/03 - incorporated output functions as regular functions rather than as part of a linked library
12/23/03 - re-written physical memory manager using bitmap instead of stack
12/22/03 - kernel relocated to 3gb linear / 1mb+24kb physical to allow for app. address space
0.12
12/21/03 - sample bmp loader tested, works (tests loading a kernel of size ~ 932kb)
12/20/03 - GDT/IDT now located at 1mb physical, before kernel
10/30/03 - turns floppy motor off
10/30/03 - keyboard LEDs working
10/29/03 - paging functions working
10/15/03 - physical memory management page allocators working
0.11
10/09/03 - PS/2 mouse driver
0.10
09/11/03 - Rewritten C and assembly kernel with VESA GUI mode support, keyboard driver
0.05
05/14/03 - HGUI24/HGUI32 commands finished for testing GUI on both 24bpp and 32bpp graphics cards
05/14/03 - first web release!
0.04
03/09/03 - added VM shortcut command
03/09/03 - press up to fill retrieve last inputted command for Nate Scholten
03/08/03 - press clear to clear console input
03/07/03 - added "shortcut" commands PC, IC, ? for Nate Scholten
03/06/03 - added PROMPTC, INPUTC commands
0.03
12/30/02 - Command Line Interface working, accepting basic commands
0.02
12/11/02 - Assembly bootsector can load stage2 ("console")
0.01
12/01/02 - Real mode assembly bootsector boots from floppy disk successfully
Executable
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env ruby
script = File.join(File.dirname(__FILE__), ".rscons-2.3.0-272f26340e9affa341050e282d22641f.rb")
unless File.exists?(script)
if File.read(__FILE__, mode: "rb") =~ /^#==>(.*)/
require "zlib"
require "base64"
encoded_compressed = $1
unescaped_compressed = Base64.decode64(encoded_compressed)
inflated = Zlib::Inflate.inflate(unescaped_compressed)
File.open(script, "wb") do |fh|
fh.write(inflated)
end
else
raise "Could not decompress."
end
end
load script
if __FILE__ == $0
Rscons::Cli.run(ARGV)
end
#==>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 truncated
+18
View File
@@ -0,0 +1,18 @@
.global hos_start
.type hos_start, @function
hos_start:
/* Set stack pointer. */
mov $_stack_end, %esp
/* Jump to C. */
push $0
push $0
push $0
push %ebx
call hos_main
cli
1: hlt
jmp 1b
.size hos_start, . - hos_start
+116
View File
@@ -0,0 +1,116 @@
#include "fb.h"
#include <stddef.h>
#include "mem.h"
static struct {
uint32_t * addr;
uint32_t width;
uint32_t height;
uint32_t pitch;
} fb;
static inline uint32_t build_pixel(uint8_t r, uint8_t g, uint8_t b)
{
return (r << 16u) | (g << 8u) | b;
}
static inline void fb_set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b)
{
fb.addr[fb.pitch * y + x] = build_pixel(r, g, b);
}
void fb_clear(void)
{
memset32(fb.addr, 0u, fb.pitch * fb.height);
}
void fb_init(uint32_t * addr, uint32_t width, uint32_t height, uint32_t pitch)
{
fb.addr = addr;
fb.width = width;
fb.height = height;
fb.pitch = pitch / 4u;
fb_clear();
}
uint32_t * fb_addr(void)
{
return fb.addr;
}
bool fb_ready(void)
{
return fb.addr != NULL;
}
uint32_t fb_width(void)
{
return fb.width;
}
uint32_t fb_height(void)
{
return fb.height;
}
void fb_blend_alpha8(const uint8_t * bitmap, int width, int height, int pitch, int x, int y, uint8_t r, uint8_t g, uint8_t b)
{
if (((x + width) <= 0) || (x >= (int)fb.width) || ((y + height) <= 0) || (y >= (int)fb.height))
{
return;
}
if (x < 0)
{
width += x;
bitmap += (-x);
x = 0;
}
if (y < 0)
{
height += y;
bitmap += ((-y) * pitch);
y = 0;
}
if ((x + width) > (int)fb.width)
{
width = (int)fb.width - x;
}
if ((y + height) > (int)fb.height)
{
height = (int)fb.height - y;
}
uint32_t * target = &fb.addr[fb.pitch * y + x];
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
uint32_t alpha = bitmap[col];
uint32_t current_pixel = target[col];
uint8_t cr = (current_pixel >> 16u) & 0xFFu;
uint8_t cg = (current_pixel >> 8u) & 0xFFu;
uint8_t cb = current_pixel & 0xFFu;
uint8_t pr = alpha * r / 255u;
uint8_t pg = alpha * g / 255u;
uint8_t pb = alpha * b / 255u;
uint32_t current_alpha = 255u - alpha;
uint32_t pixel = build_pixel(
pr + current_alpha * cr / 255u,
pg + current_alpha * cg / 255u,
pb + current_alpha * cb / 255u);
target[col] = pixel;
}
bitmap += pitch;
target += fb.pitch;
}
}
void fb_fill(int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b)
{
uint32_t * target = &fb.addr[fb.pitch * y + x];
uint32_t pixel = build_pixel(r, g, b);
for (int row = 0; row < height; row++)
{
memset32(target, pixel, width);
target += fb.pitch;
}
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef FB_H
#define FB_H
#include <stdint.h>
#include <stdbool.h>
void fb_init(uint32_t * addr, uint32_t width, uint32_t height, uint32_t pitch);
bool fb_ready(void);
uint32_t * fb_addr(void);
uint32_t fb_width(void);
uint32_t fb_height(void);
void fb_blend_alpha8(const uint8_t * bitmap, int width, int height, int pitch, int x, int y, uint8_t r, uint8_t g, uint8_t b);
void fb_fill(int x, int y, int width, int height, uint8_t r, uint8_t g, uint8_t b);
void fb_clear(void);
#endif
+11
View File
@@ -0,0 +1,11 @@
#include "fb_text.h"
#include "kfont.h"
#include "fb.h"
void fb_text_render_char(int c, int x, int y, uint8_t r, uint8_t g, uint8_t b)
{
const fontgen_char_info_t * char_info = kfont.char_infos[c];
y += kfont.line_height - kfont.baseline_offset - char_info->top;
x += char_info->left;
fb_blend_alpha8(char_info->bitmap, char_info->width, char_info->height, char_info->width, x, y, r, g, b);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef FB_TEXT_H
#define FB_TEXT_H
#include <stdint.h>
void fb_text_render_char(int c, int x, int y, uint8_t r, uint8_t g, uint8_t b);
#endif
+16
View File
@@ -0,0 +1,16 @@
.global gdt_set
.extern gdtr
.type gdt_set, @function
gdt_set:
lgdt gdtr
jmp $0x8, $gdt_set_reload
gdt_set_reload:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
ret
.size gdt_set, . - gdt_set
+20
View File
@@ -0,0 +1,20 @@
#include "gdt.h"
static const gdt_entry_t gdt_entries[] = {
/* Null descriptor */
0u,
/* Code segment for kernel */
gdt_build_entry(0u, 0xFFFFFu, 1u, 0u, 1u, 1u, 0u, 1u, 0u, 1u, 1u, 0u),
/* Data segment for kernel */
gdt_build_entry(0u, 0xFFFFFu, 1u, 0u, 1u, 0u, 0u, 1u, 0u, 1u, 1u, 0u),
};
gdtr_t gdtr;
void gdt_init(void)
{
gdtr.size = sizeof(gdt_entries);
gdtr.offset_lower = (uintptr_t)gdt_entries & 0xFFFFu;
gdtr.offset_upper = (uintptr_t)gdt_entries >> 16u;
gdt_set();
}
+34
View File
@@ -0,0 +1,34 @@
#ifndef GDT_H
#define GDT_H
#include <stdint.h>
typedef struct {
uint16_t size;
uint16_t offset_lower;
uint16_t offset_upper;
uint16_t _reserved;
} gdtr_t;
typedef uint64_t gdt_entry_t;
#define gdt_build_entry(base, limit, pr, privl, s, ex, dc, rw, ac, gr, sz, l) \
(gdt_entry_t)( \
(((gdt_entry_t)base << 32) & 0xFF00000000000000ull) | /* Base 0:15 */ \
(((gdt_entry_t)gr & 0x1u) << 55) | /* Granularity (0 = bytes, 1 = blocks) */ \
(((gdt_entry_t)sz & 0x1u) << 54) | /* Size (0 = 16-bit, 1 = 32-bit) */ \
(((gdt_entry_t)l & 0x1u) << 53) | /* L flag (x86_64 code) */ \
(((gdt_entry_t)limit << 32) & 0x000F000000000000ull) | /* Limit 16:19 */ \
(((gdt_entry_t)pr & 0x1u) << 47) | /* Present flag */ \
(((gdt_entry_t)privl & 0x3u) << 45) | /* Privilege (ring level) */ \
(((gdt_entry_t)s & 0x1u) << 44) | /* Type (0 = system, 1 = code/data) */ \
(((gdt_entry_t)ex & 0x1u) << 43) | /* Executable flag */ \
(((gdt_entry_t)dc & 0x1u) << 42) | /* Direction/Conforming */ \
(((gdt_entry_t)rw & 0x1u) << 41) | /* Readable/Writable */ \
(((gdt_entry_t)ac & 0x1u) << 40) | /* Accessed flag */ \
(((gdt_entry_t)base << 16) & 0x000000FFFFFF0000ull) | /* Base 0:23 */ \
((gdt_entry_t)limit & 0x000000000000FFFFull)) /* Limit 0:15 */
void gdt_init(void);
void gdt_set(void);
#endif
+25
View File
@@ -0,0 +1,25 @@
#include <stdint.h>
#include "fb.h"
#include "mbinfo.h"
#include "klog.h"
#include "gdt.h"
#include "mm.h"
void hos_main(uint32_t mbinfo_addr)
{
gdt_init();
if (!mbinfo_init(mbinfo_addr))
{
return;
}
if (!fb_ready())
{
return;
}
klog_init();
klog_printf("Welcome to HOS!\n");
mm_init();
mbinfo_load();
klog_printf("Found %dKB of usable RAM\n", mm_get_total_ram() / 1024u);
klog_printf("Kernel is %dKB at 0x%x\n", mm_get_kernel_size() / 1024u, mm_get_kernel_address());
}
+281
View File
@@ -0,0 +1,281 @@
#include "hos_printf.h"
#include <stdint.h>
#include <stdbool.h>
#include "string.h"
static size_t format_dec(char * buffer, int32_t v)
{
size_t sz = 0u;
bool printing = false;
if (v < 0)
{
buffer[sz++] = '-';
v = -v;
}
for (int32_t div = 1000000000; div >= 1; div /= 10)
{
int32_t digit = v / div;
v %= div;
if ((digit != 0) || (div == 1))
{
printing = true;
}
if (printing)
{
buffer[sz++] = digit + '0';
}
}
return sz;
}
static size_t format_dec64(char * buffer, int64_t v)
{
size_t sz = 0u;
bool printing = false;
if (v < 0)
{
buffer[sz++] = '-';
v = -v;
}
for (int64_t div = 1000000000000000000; div >= 1; div /= 10)
{
int64_t digit = v / div;
v %= div;
if ((digit != 0) || (div == 1))
{
printing = true;
}
if (printing)
{
buffer[sz++] = digit + '0';
}
}
return sz;
}
static size_t format_udec(char * buffer, int32_t v)
{
size_t sz = 0u;
for (int32_t div = 1000000000u; div >= 1u; div /= 10u)
{
int32_t digit = v / div;
v %= div;
if ((digit != 0) || (sz > 0u) || (div == 1))
{
buffer[sz++] = digit + '0';
}
}
return sz;
}
static size_t format_udec64(char * buffer, uint64_t v)
{
size_t sz = 0u;
for (uint64_t div = 10000000000000000000u; div >= 1u; div /= 10u)
{
uint64_t digit = v / div;
v %= div;
if ((digit != 0) || (sz > 0u) || (div == 1))
{
buffer[sz++] = digit + '0';
}
}
return sz;
}
static size_t format_hex(char * buffer, uint32_t v, bool upper)
{
const char upper_hex[] = "0123456789ABCDEF";
const char lower_hex[] = "0123456789abcdef";
size_t sz = 0u;
for (int i = 28; i >= 0; i -= 4)
{
uint8_t n = (v >> i) & 0xFu;
if ((sz > 0u) || (n != 0u) || (i == 0))
{
buffer[sz] = upper ? upper_hex[n] : lower_hex[n];
sz++;
}
}
return sz;
}
static size_t format_hex64(char * buffer, uint64_t v, bool upper)
{
const char upper_hex[] = "0123456789ABCDEF";
const char lower_hex[] = "0123456789abcdef";
size_t sz = 0u;
for (int i = 60; i >= 0; i -= 4)
{
uint8_t n = (v >> i) & 0xFu;
if ((sz > 0u) || (n != 0u) || (i == 0))
{
buffer[sz] = upper ? upper_hex[n] : lower_hex[n];
sz++;
}
}
return sz;
}
static void pad_write(const stream_t * stream, const char * data, size_t length, bool leading_zero, bool left_just, size_t width)
{
if (left_just)
{
stream->write(data, length);
while (length < width)
{
stream->write1(' ');
length++;
}
}
else
{
char fill = leading_zero ? '0' : ' ';
size_t l = length;
while (l < width)
{
stream->write1(fill);
l++;
}
stream->write(data, length);
}
}
void hos_vprintf(const stream_t * stream, const char * fmt, va_list va)
{
bool in_conv = false;
char c;
char buffer[22];
size_t width;
bool leading_zero;
bool left_just;
bool long_flag;
size_t length;
while ((c = *fmt))
{
if (in_conv)
{
switch (c)
{
case '%':
stream->write1('%');
break;
case 'X':
{
if (long_flag)
{
uint64_t v = va_arg(va, uint64_t);
length = format_hex(buffer, v, true);
}
else
{
uint32_t v = va_arg(va, uint32_t);
length = format_hex(buffer, v, true);
}
pad_write(stream, buffer, length, leading_zero, left_just, width);
}
break;
case 'c':
{
char ch = va_arg(va, int);
pad_write(stream, &ch, 1u, leading_zero, left_just, width);
}
break;
case 'd':
{
if (long_flag)
{
int64_t v = va_arg(va, int64_t);
length = format_dec64(buffer, v);
}
else
{
int32_t v = va_arg(va, int32_t);
length = format_dec(buffer, v);
}
pad_write(stream, buffer, length, leading_zero, left_just, width);
}
break;
case 's':
{
const char * s = va_arg(va, const char *);
pad_write(stream, s, strlen(s), leading_zero, left_just, width);
}
break;
case 'u':
{
if (long_flag)
{
uint64_t v = va_arg(va, uint64_t);
length = format_udec64(buffer, v);
}
else
{
uint32_t v = va_arg(va, uint32_t);
length = format_udec(buffer, v);
}
pad_write(stream, buffer, length, leading_zero, left_just, width);
}
break;
case 'x':
{
if (long_flag)
{
uint64_t v = va_arg(va, uint64_t);
length = format_hex64(buffer, v, false);
}
else
{
uint32_t v = va_arg(va, uint32_t);
length = format_hex(buffer, v, false);
}
pad_write(stream, buffer, length, leading_zero, left_just, width);
}
break;
}
in_conv = false;
}
else if (c == '%')
{
in_conv = true;
width = 0u;
leading_zero = false;
left_just = false;
long_flag = false;
if (fmt[1] == '-')
{
left_just = true;
fmt++;
}
if (fmt[1] == '0')
{
leading_zero = true;
fmt++;
}
while (('0' <= fmt[1]) && (fmt[1] <= '9'))
{
width *= 10u;
width += (fmt[1] - '0');
fmt++;
}
if (fmt[1] == 'l')
{
long_flag = true;
fmt++;
}
}
else
{
stream->write1(c);
}
fmt++;
}
}
void hos_printf(const stream_t * stream, const char * fmt, ...)
{
va_list va;
va_start(va, fmt);
hos_vprintf(stream, fmt, va);
va_end(va);
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef HOS_PRINTF_H
#define HOS_PRINTF_H
#include "stream.h"
#include <stdarg.h>
void hos_vprintf(const stream_t * stream, const char * fmt, va_list va);
void hos_printf(const stream_t * stream, const char * fmt, ...);
#endif
+103
View File
@@ -0,0 +1,103 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdarg.h>
#include "klog.h"
#include "kfont.h"
#include "fb.h"
#include "fb_text.h"
#include "stream.h"
#include "hos_printf.h"
#include "mem.h"
static struct {
size_t console_width;
size_t console_height;
size_t x;
size_t y;
bool need_shift;
} klog;
static void shift_line(void)
{
uint32_t * fb = fb_addr();
uint32_t w = fb_width();
size_t console_fb_line_words = w * kfont.line_height;
for (size_t row = 0u; row < klog.console_height; row++)
{
memcpy32(fb, fb + console_fb_line_words, console_fb_line_words);
fb += console_fb_line_words;
}
fb_fill(0, kfont.line_height * (klog.console_height - 1u), w, kfont.line_height, 0u, 0x2Cu, 0x55u);
}
static void klog_fb_write1(char c)
{
if (klog.need_shift)
{
shift_line();
klog.need_shift = false;
}
if (c == '\n')
{
if (klog.y == (klog.console_height - 1u))
{
klog.need_shift = true;
}
else
{
klog.y++;
}
klog.x = 0u;
}
else
{
int px = klog.x * kfont.advance;
int py = klog.y * kfont.line_height;
fb_text_render_char(c, px, py, 0xFFu, 0x80u, 0u);
klog.x++;
if (klog.x == klog.console_width)
{
if (klog.y == (klog.console_height - 1u))
{
klog.need_shift = true;
}
else
{
klog.y++;
}
klog.x = 0u;
}
}
}
static void klog_fb_write(const char * src, size_t length)
{
for (size_t i = 0u; i < length; i++)
{
klog_fb_write1(src[i]);
}
}
static const stream_t klog_fb_stream = {
klog_fb_write,
klog_fb_write1,
};
void klog_init(void)
{
klog.console_width = fb_width() / kfont.advance;
klog.console_height = fb_height() / kfont.line_height;
klog.x = 0u;
klog.y = 0u;
klog.need_shift = false;
fb_fill(0, 0, fb_width(), fb_height(), 0u, 0x2Cu, 0x55u);
}
void klog_printf(const char * fmt, ...)
{
va_list va;
va_start(va, fmt);
hos_vprintf(&klog_fb_stream, fmt, va);
va_end(va);
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef KLOG_H
#define KLOG_H
void klog_init(void);
void klog_printf(const char * fmt, ...);
#endif
+41
View File
@@ -0,0 +1,41 @@
ENTRY(hos_start)
SECTIONS
{
. = 1M;
_hos_mem_start = .;
.text BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
*(.text)
}
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.rodata)
}
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
}
_stack_size = 16K;
.stack (NOLOAD) : ALIGN(4K)
{
_stack_start = .;
. = . + _stack_size;
_stack_end = .;
}
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
. = ALIGN(4K);
_hos_mem_end = .;
}
+100
View File
@@ -0,0 +1,100 @@
#include "multiboot2.h"
#include "fb.h"
#include "mem.h"
#include <stdint.h>
#include "klog.h"
#include "mm.h"
static uint32_t mbinfo[2048];
static void mbinfo_process_tag(const multiboot2_info_tag_t * tag)
{
switch (tag->type)
{
case MULTIBOOT2_INFO_BOOT_COMMAND_LINE:
{
multiboot2_info_boot_command_line_t * cl =
(multiboot2_info_boot_command_line_t *)tag;
klog_printf("Kernel boot command line: '%s'\n", cl->string);
}
break;
case MULTIBOOT2_INFO_BOOT_LOADER_NAME:
{
multiboot2_info_boot_loader_name_t * bln =
(multiboot2_info_boot_loader_name_t *)tag;
klog_printf("Boot loader: '%s'\n", bln->string);
}
break;
case MULTIBOOT2_INFO_MEMORY_MAP:
{
multiboot2_info_memory_map_t * mmap_info =
(multiboot2_info_memory_map_t *)tag;
size_t sz = sizeof(mmap_info->header) +
sizeof(mmap_info->entry_size) +
sizeof(mmap_info->entry_version);
multiboot2_info_memory_map_entry_t * entry = &mmap_info->entries[0];
for (;;)
{
sz += mmap_info->entry_size;
if (sz > mmap_info->header.size)
{
break;
}
if (entry->type == MULTIBOOT2_MEMORY_MAP_TYPE_RAM)
{
klog_printf("Memory region %16lx : %16lx\n",
entry->base_addr,
entry->length);
mm_register_ram_region(entry->base_addr, entry->length);
}
entry = (multiboot2_info_memory_map_entry_t *)((uintptr_t)entry + mmap_info->entry_size);
}
}
break;
case MULTIBOOT2_INFO_FRAMEBUFFER_INFO:
{
multiboot2_info_framebuffer_info_t * fbinfo =
(multiboot2_info_framebuffer_info_t *)tag;
fb_init((uint32_t *)(uintptr_t)fbinfo->framebuffer_addr,
fbinfo->framebuffer_width,
fbinfo->framebuffer_height,
fbinfo->framebuffer_pitch);
}
break;
}
}
static void process_tags(const multiboot2_info_tag_t * tag, bool init)
{
while (tag->type != 0u)
{
if ((init && (tag->type == MULTIBOOT2_INFO_FRAMEBUFFER_INFO)) ||
(!init && (tag->type != MULTIBOOT2_INFO_FRAMEBUFFER_INFO)))
{
mbinfo_process_tag(tag);
}
tag = multiboot2_info_next_tag(tag);
}
}
bool mbinfo_init(uint32_t mbinfo_addr)
{
multiboot2_info_header_t * mbinfo_header = (multiboot2_info_header_t *)mbinfo_addr;
if (mbinfo_header->total_size <= sizeof(mbinfo))
{
memcpy32(mbinfo, mbinfo_header, mbinfo_header->total_size / 4u);
multiboot2_info_tag_t * tag = (multiboot2_info_tag_t *)(mbinfo + sizeof(multiboot2_info_header_t) / 4u);
process_tags(tag, true);
return true;
}
return false;
}
void mbinfo_load(void)
{
multiboot2_info_tag_t * tag = (multiboot2_info_tag_t *)(mbinfo + sizeof(multiboot2_info_header_t) / 4u);
process_tags(tag, false);
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef MBINFO_H
#define MBINFO_H
#include <stdint.h>
#include <stdbool.h>
bool mbinfo_init(uint32_t mbinfo_addr);
void mbinfo_load(void);
#endif
+49
View File
@@ -0,0 +1,49 @@
#ifndef MEM_H
#define MEM_H
#include <stddef.h>
static inline void memcpy(void * dest, const void * src, size_t n)
{
uint32_t r0, r1, r2;
__asm__ __volatile__ (
"cld\n\t"
"rep movsb"
: "=&c" (r0), "=&S" (r1), "=&D" (r2)
: "2" (dest), "1" (src), "0" (n)
: "memory");
}
static inline void memcpy32(void * dest, const void * src, size_t count)
{
uint32_t r0, r1, r2;
__asm__ __volatile__ (
"cld\n\t"
"rep movsd"
: "=&c" (r0), "=&S" (r1), "=&D" (r2)
: "2" (dest), "1" (src), "0" (count)
: "memory");
}
static inline void * memmove(void * dest, const void * src, size_t count)
{
return __builtin_memmove(dest, src, count);
}
static inline void * memset(void * dest, int val, size_t count)
{
return __builtin_memset(dest, val, count);
}
static inline void memset32(void * dest, uint32_t val, size_t count)
{
uint32_t r0, r1;
__asm__ __volatile__ (
"cld\n\t"
"rep stosl"
: "=&c" (r0), "=&D" (r1)
: "a" (val), "1" (dest), "0" (count)
: "memory");
}
#endif
+91
View File
@@ -0,0 +1,91 @@
#include "mm.h"
typedef struct mm_page_entry_s {
size_t count;
struct mm_page_entry_s * next;
} mm_region_entry_t;
static mm_region_entry_t * mm_next_free_region;
static size_t mm_free_pages;
static size_t mm_total_ram;
static size_t kernel_start_address;
static size_t kernel_size;
extern uint8_t _hos_mem_start;
extern uint8_t _hos_mem_end;
static void mm_add_ram_region(size_t base, size_t size)
{
mm_region_entry_t * region = (mm_region_entry_t *)base;
size_t pages = size / PAGE_SIZE;
region->count = pages;
region->next = mm_next_free_region;
mm_next_free_region = region;
mm_total_ram += size;
mm_free_pages = pages;
}
void mm_register_ram_region(uint64_t base, size_t size)
{
/* Ignore any RAM region above 4GB. */
if (base >= 0x100000000ull)
{
return;
}
if ((base + size) > 0x100000000ull)
{
size = (size_t)(0x100000000ull - base);
}
size_t end_address = mm_page_floor((size_t)base + size);
size_t start_address = mm_page_ceil(base);
size = end_address - start_address;
if (size < PAGE_SIZE)
{
return;
}
size_t kernel_end_address = kernel_start_address + kernel_size;
/* Add regions before and after kernel RAM. */
if (start_address < kernel_start_address)
{
/* RAM region begins before kernel RAM. */
size_t this_sz = size;
if ((start_address + this_sz) > kernel_start_address)
{
this_sz = kernel_start_address - start_address;
}
mm_add_ram_region(start_address, this_sz);
}
if ((start_address + size) > kernel_end_address)
{
/* RAM region ends after kernel RAM. */
size_t this_sz = size;
if (start_address < kernel_end_address)
{
this_sz = (start_address + size) - kernel_end_address;
start_address = kernel_end_address;
}
mm_add_ram_region(start_address, this_sz);
}
}
void mm_init(void)
{
kernel_start_address = mm_page_floor((size_t)&_hos_mem_start);
kernel_size = mm_page_ceil((size_t)&_hos_mem_end - kernel_start_address);
mm_total_ram = kernel_size;
}
size_t mm_get_total_ram(void)
{
return mm_total_ram;
}
size_t mm_get_kernel_address(void)
{
return kernel_start_address;
}
size_t mm_get_kernel_size(void)
{
return kernel_size;
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef MM_H
#define MM_H
#include <stdint.h>
#include <stddef.h>
#define PAGE_SIZE 4096u
static inline size_t mm_page_floor(size_t bytes)
{
return bytes & ~(PAGE_SIZE - 1u);
}
static inline size_t mm_page_ceil(size_t bytes)
{
return (bytes + PAGE_SIZE - 1u) & ~(PAGE_SIZE - 1u);
}
void mm_init(void);
void mm_register_ram_region(uint64_t base, size_t size);
size_t mm_get_total_ram(void);
size_t mm_get_kernel_address(void);
size_t mm_get_kernel_size(void);
#endif
+127
View File
@@ -0,0 +1,127 @@
#ifndef MULTIBOOT2_H
#define MULTIBOOT2_H
#include <stdint.h>
#define MULTIBOOT2_MAGIC 0xE85250D6u
#define MULTIBOOT2_ARCHITECTURE_I386 0u
typedef struct {
uint32_t magic;
uint32_t architecture;
uint32_t header_length;
uint32_t checksum;
} multiboot2_header_t;
#define multiboot2_header(magic, architecture, header_length) \
{(magic), (architecture), (header_length), (uint32_t)(0x100000000u - (magic) - (architecture) - (header_length))}
#define multiboot2_header_default() \
multiboot2_header(MULTIBOOT2_MAGIC, MULTIBOOT2_ARCHITECTURE_I386, sizeof(multiboot2_header_t))
typedef struct {
uint16_t type;
uint16_t flags;
uint32_t size;
} multiboot2_tag_t;
#define multiboot2_end_tag() {0u, 0u, 8u}
typedef struct {
multiboot2_tag_t header;
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t _padding;
} multiboot2_framebuffer_tag_t;
#define multiboot2_framebuffer_tag(width, height, depth) \
{{5u, 0u, 20u}, width, height, depth}
#define MULTIBOOT2_INFO_TAG_ALIGNMENT 8u
#define MULTIBOOT2_INFO_BOOT_COMMAND_LINE 1u
#define MULTIBOOT2_INFO_BOOT_LOADER_NAME 2u
#define MULTIBOOT2_INFO_MODULES 3u
#define MULTIBOOT2_INFO_BASIC_MEMORY_INFO 4u
#define MULTIBOOT2_INFO_BIOS_BOOT_DEVICE 5u
#define MULTIBOOT2_INFO_MEMORY_MAP 6u
#define MULTIBOOT2_INFO_VBE_INFO 7u
#define MULTIBOOT2_INFO_FRAMEBUFFER_INFO 8u
#define MULTIBOOT2_INFO_ELF_SYMBOLS 9u
#define MULTIBOOT2_INFO_APM_TABLE 10u
#define MULTIBOOT2_INFO_EFI_32BIT_SYSTEM_TABLE_POINTER 11u
#define MULTIBOOT2_INFO_EFI_64BIT_SYSTEM_TABLE_POINTER 12u
#define MULTIBOOT2_INFO_SMBIOS_TABLES 13u
#define MULTIBOOT2_INFO_ACPI_OLD_RSDP 14u
#define MULTIBOOT2_INFO_NETWORKING_INFO 16u
#define MULTIBOOT2_INFO_EFI_MEMORY_MAP 17u
#define MULTIBOOT2_INFO_EFI_BOOT_SERVICES_NOT_TERMINATED 18u
#define MULTIBOOT2_INFO_EFI_32BIT_IMAGE_HANDLE_POINTER 19u
#define MULTIBOOT2_INFO_EFI_64BIT_IMAGE_HANDLE_POINTER 20u
#define MULTIBOOT2_INFO_IMAGE_LOAD_BASE_PHYSICAL_ADDRESS 21u
typedef struct {
uint32_t total_size;
uint32_t _reserved;
} multiboot2_info_header_t;
typedef struct {
uint32_t type;
uint32_t size;
} multiboot2_info_tag_t;
#define multiboot2_info_next_tag(current_tag) \
(multiboot2_info_tag_t *)(((uintptr_t)current_tag + current_tag->size + MULTIBOOT2_INFO_TAG_ALIGNMENT - 1u) & ~(MULTIBOOT2_INFO_TAG_ALIGNMENT - 1u))
typedef struct {
multiboot2_info_tag_t header;
char string[];
} multiboot2_info_boot_command_line_t;
typedef struct {
multiboot2_info_tag_t header;
char string[];
} multiboot2_info_boot_loader_name_t;
typedef struct {
multiboot2_info_tag_t header;
uint32_t mem_lower;
uint32_t mem_upper;
} multiboot2_info_basic_memory_info_t;
#define MULTIBOOT2_MEMORY_MAP_TYPE_RAM 1u
#define MULTIBOOT2_MEMORY_MAP_TYPE_ACPI 3u
#define MULTIBOOT2_MEMORY_MAP_TYPE_PRESERVE 4u
#define MULTIBOOT2_MEMORY_MAP_TYPE_DEFECTIVE 5u
typedef struct {
uint64_t base_addr;
uint64_t length;
uint32_t type;
uint32_t _reserved;
} multiboot2_info_memory_map_entry_t;
typedef struct {
multiboot2_info_tag_t header;
uint32_t entry_size;
uint32_t entry_version;
multiboot2_info_memory_map_entry_t entries[];
} multiboot2_info_memory_map_t;
typedef struct {
multiboot2_info_tag_t header;
uint16_t vbe_mode;
uint16_t vbe_interface_set;
uint16_t vbe_interface_off;
uint16_t vbe_interface_len;
uint8_t vbe_control_info[512];
uint8_t vbe_mode_info[256];
} multiboot2_info_vbe_info_t;
typedef struct {
multiboot2_info_tag_t header;
uint64_t framebuffer_addr;
uint32_t framebuffer_pitch;
uint32_t framebuffer_width;
uint32_t framebuffer_height;
uint8_t framebuffer_bpp;
uint8_t framebuffer_type;
uint8_t _reserved;
} multiboot2_info_framebuffer_info_t;
#endif
+12
View File
@@ -0,0 +1,12 @@
#include "multiboot2.h"
/* Multiboot2 Header. */
struct {
multiboot2_header_t header;
multiboot2_framebuffer_tag_t framebuffer_tag;
multiboot2_tag_t end_tag;
} multiboot_header __attribute__((section(".multiboot"))) = {
multiboot2_header_default(),
multiboot2_framebuffer_tag(1600u, 900u, 32u),
multiboot2_end_tag(),
};
+12
View File
@@ -0,0 +1,12 @@
#ifndef STREAM_H
#define STREAM_H
#include <stddef.h>
#include <stdint.h>
typedef struct {
void (*write)(const char * src, size_t length);
void (*write1)(char c);
} stream_t;
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef STRING_H
#define STRING_H
#include <stddef.h>
static inline size_t strlen(const char * s)
{
size_t r = 0u;
while (*s++ != (char)0)
{
r++;
}
return r;
}
static inline char * strcpy(char * dest, const char * src)
{
return __builtin_strcpy(dest, src);
}
static inline char * strncpy(char * dest, const char * src, size_t n)
{
return __builtin_strncpy(dest, src, n);
}
#endif