202 Commits
Author SHA1 Message Date
josh b0e59b3e26 Add hippo.allocate_page() 2022-04-26 21:45:17 -04:00
josh 153a8d43f1 Add hulk.linker_addresses module 2022-04-26 19:37:05 -04:00
josh bf9a005dbc Launch qemu with a USB XHCI controller and USB tablet device 2022-04-13 21:55:06 -04:00
josh 53e2e52bbe Scan for PCI devices 2022-04-13 21:54:28 -04:00
josh 12067b8e1a Remove src-old 2022-04-13 17:12:16 -04:00
josh 8278c4211b Add HIPPO module and starting tracking free physical pages 2022-03-29 22:24:14 -04:00
josh 3bdc5bccdd Pass page table address range to HULK on boot 2022-03-28 21:22:10 -04:00
josh f904ec2b48 Convert hello.console to use a namespacing struct 2022-03-28 15:18:31 -04:00
josh bcec23ef89 Update hello.scratch to use namespacing struct 2022-03-28 15:17:07 -04:00
josh d86745d91d Move bootinfo into HULK header 2022-03-27 16:14:54 -04:00
josh cf5956dcd3 Rename Header to HulkHeader 2022-03-27 09:45:09 -04:00
josh 8498de6b62 Add HURL; relocate kernel virtual regions 2022-03-26 10:41:53 -04:00
josh f761d0a445 Jump to HULK from assembly 2022-03-26 00:36:23 -04:00
josh f29bd9d00c Allocate HULK stack region from HELLO, translate memory region types 2022-03-26 00:29:19 -04:00
josh f236a64b21 HELLO: Be more welcoming 2022-03-25 13:17:22 -04:00
josh 1225e98276 Pass HULK physical memory info to kernel from HELLO 2022-03-25 13:16:36 -04:00
josh cb31e36e90 Clean up console 2022-03-25 12:37:18 -04:00
josh 0568a813f2 HELLO: Zero out HULK bss section 2022-03-25 11:53:01 -04:00
josh 37d5621e41 HULK console: clear last row when shifting rows up 2022-03-25 10:51:52 -04:00
josh 98e992aad0 Convert fb, console, klog to "static instance" namespacing structs 2022-03-25 10:48:32 -04:00
josh 06242a0c9f Add console, klog, and writef modules.
They are not complete, but adding to checkpoint progress.
2022-03-24 17:52:39 -04:00
josh e214a9c3de Fix call to fb.blend_alpha_bitmap() 2022-03-24 09:52:26 -04:00
josh c259ae4cee Add Framebuffer.copy_rows_up() 2022-03-23 22:12:38 -04:00
josh b4d8707243 Rename blending blit methods to blend 2022-03-22 22:32:45 -04:00
josh 6b7b14d954 Add Framebuffer.character() 2022-03-22 22:11:12 -04:00
josh 9e7c3ee676 Add Framebuffer.rect(), .hline(), .vline() 2022-03-22 21:55:25 -04:00
josh 2d7bf5197f Drawing text working using Framebuffer.blit_alpha_bitmap() 2022-03-22 20:01:08 -04:00
josh 7562be585f Add Framebuffer.blit_alpha_bitmap() 2022-03-22 20:00:32 -04:00
josh 3d04eec427 Compile HULK with large code model 2022-03-22 19:29:30 -04:00
josh 5c97acba5f Update fontgen to output D instead of C 2022-03-22 13:01:20 -04:00
josh c3ead56582 Add Framebuffer object 2022-03-21 16:32:11 -04:00
josh 15559b0a56 Add HULK header; map virtual memory for HULK bss section 2022-03-21 16:31:01 -04:00
josh c58284761a Comment hulk.hulk module a bit 2022-03-20 23:05:10 -04:00
josh bd99e429a9 Comment hulk.bootinfo a bit 2022-03-20 22:58:25 -04:00
josh d0acf5a718 Comment hello.hello module a bit better 2022-03-20 22:38:42 -04:00
josh b40151055c Rework scratch module and use qualified names for function calls 2022-03-20 22:21:10 -04:00
josh 1e00d7a9e9 Rename hello.output to hello.console 2022-03-20 22:12:46 -04:00
josh 79b34477ed Reorganize D modules a bit 2022-03-19 22:39:12 -04:00
josh 163ef9f79e Increase scratch buffer size 2022-03-19 22:08:35 -04:00
josh 3c549f0838 Write size file for HULK/HELLO 2022-03-19 22:07:37 -04:00
josh d8c85ad045 Map all memory regions and graphics framebuffer 2022-03-19 21:54:30 -04:00
josh 7c5af33ace Fix receiving correct argument to hulk_start() 2022-03-19 20:02:49 -04:00
josh 6f3521c576 Make sure to rebuild HELLO properly when HULK changes 2022-03-19 00:27:10 -04:00
josh 5a5d60abae Fix HULK virtual start address to be addressable 2022-03-19 00:04:59 -04:00
josh 9182a83ef2 HELLO: Make sure scratch area is page-aligned 2022-03-18 23:43:05 -04:00
josh 195b7496f4 HELLO: Include EfiLoaderCode and EfiLoaderData memory regions in memory map 2022-03-18 23:33:42 -04:00
josh b1042fd649 Jump to HULK
Unfortunately, crashes... :(
2022-03-18 23:16:07 -04:00
josh 6beb7da4cd Map HULK virtual address space 2022-03-18 23:04:09 -04:00
josh f27851def9 Bundle HULK in HELLO 2022-03-18 22:43:37 -04:00
josh 18f1bfc88f Build HELLO after HULK 2022-03-18 22:02:07 -04:00
josh cd6983e2cd Generate HULK binary 2022-03-18 22:01:27 -04:00
josh 8df1646c61 Add initial HULK source and linker script 2022-03-18 21:55:38 -04:00
josh 3e25ab6ae4 HELLO: Zero out page tables after allocating, before using 2022-03-18 21:21:00 -04:00
josh 05cc2da2e3 HULK: Add virtual start address 2022-03-18 21:19:06 -04:00
josh a54536660b HELLO: Create page tables to identity map available RAM prior to jumping to kernel 2022-03-18 21:15:58 -04:00
josh 9e3d9b18ea Add write_cr3() 2022-03-18 16:40:46 -04:00
josh ef01239468 HELLO: Add scratch module 2022-03-18 16:03:50 -04:00
josh 372b7265f1 Add src/common/hos/cpu.d 2022-03-18 10:51:35 -04:00
josh 1bc8722098 Add hos.memory module in src/common 2022-03-18 00:07:10 -04:00
josh cd2f3f9a84 Rename kernel to hulk 2022-03-17 16:57:18 -04:00
josh 08a35e40d4 Rename HEL -> HELLO 2022-03-16 16:11:26 -04:00
josh a855702214 Fix checking for EFI_INVALID_PARAMETER 2022-03-16 14:37:46 -04:00
josh 706f2c1c5d HEL: Call ExitBootServices 2022-03-16 01:12:07 -04:00
josh 704fd15f7b Get memory map; remove heap 2022-03-15 23:58:37 -04:00
josh f054bab5cc Set bootinfo framebuffer fields 2022-03-15 23:03:28 -04:00
josh 3fa8e4a24b Set maximum resolution for running in qemu 2022-03-15 22:52:56 -04:00
josh a38f95a7b8 Set graphics mode 2022-03-14 22:26:55 -04:00
josh dd57a31d38 HEL: Add heap module; locate GOP handle 2022-03-14 21:43:40 -04:00
josh 406f17c1db HEL: format hex, decimal, and CHAR16 strings in output module 2022-03-14 15:09:02 -04:00
josh 0be1b113aa Add output module for console output routines 2022-03-14 13:53:02 -04:00
josh d782b59768 Write map file 2022-03-14 01:35:28 -04:00
josh c3a6139f83 Run image from temporary copy to avoid modified disk image file 2022-03-14 00:57:24 -04:00
josh 3d3a433800 Update to rscons 3.0.2 2022-03-14 00:51:54 -04:00
josh 54451bcf5b Add initial HOS EFI Loader sources 2022-03-13 23:16:37 -04:00
josh 1fc2dd34e5 Update build system for 64-bit, EFI, and D 2022-03-13 22:46:59 -04:00
josh cb6bd3914c Remove HOS v0.16 sources 2022-02-28 15:10:25 -05:00
josh 56c3be9207 Update to rscons 3.0.0 2022-02-28 13:40:08 -05:00
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
josh 0aaf5db5ad Import backup from 2006-01-02 2017-07-25 22:23:52 -04:00
josh 89d962e33a Import backup from 2005-12-31 2017-07-25 22:23:52 -04:00
josh 712337c485 Import backup from 2005-12-30 2017-07-25 22:23:52 -04:00
josh 761e3f0483 Import backup from 2005-12-26 2017-07-25 22:23:51 -04:00
josh 98abfc2af0 Import backup from 2005-12-19 2017-07-25 22:23:51 -04:00
josh 677551fba5 Import backup from 2005-11-03 2017-07-25 22:23:51 -04:00
josh 7daa1c5336 Import backup from 2005-11-01 2017-07-25 22:23:51 -04:00
josh 79ca453f66 Import backup from 2005-09-13 2017-07-25 22:23:51 -04:00
josh 0521733e20 Import backup from 2005-09-11 2017-07-25 22:23:51 -04:00
josh 396c5f3452 Import backup from 2005-09-01 2017-07-25 22:23:51 -04:00
josh 9e03bfc8b6 Import backup from 2005-08-30 2017-07-25 22:23:51 -04:00
josh 2b67ff6f49 Import backup from 2005-08-29 2017-07-25 22:23:51 -04:00
josh daa29212d0 Import backup from 2005-08-27 2017-07-25 22:23:50 -04:00
josh 83a5b032f8 Import backup from 2005-08-25 2017-07-25 22:23:50 -04:00
josh 345ef6c9f3 Import backup from 2005-08-18 2017-07-25 22:23:50 -04:00
josh e1682a2fe7 Import backup from 2005-08-17 2017-07-25 22:23:50 -04:00
josh 2cefd9441c Import backup from 2005-06-21 2017-07-25 22:23:50 -04:00
josh da90bcc164 Import backup from 2005-06-20 2017-07-25 22:23:50 -04:00
josh 4689c11cc8 Import backup from 2005-06-13 2017-07-25 22:23:50 -04:00
josh 692cf2fc08 Import backup from 2005-06-02 2017-07-25 22:23:50 -04:00
josh b0132c866e Import backup from 2005-05-12 2017-07-25 22:23:50 -04:00
josh 14792ef954 Import backup from 2005-03-21 2017-07-25 22:23:50 -04:00
josh bb8ff09e3f Import backup from 2005-03-11 2017-07-25 22:23:50 -04:00
josh dfeabc39aa Import backup from 2005-02-23 2017-07-25 22:23:50 -04:00
josh 14148e4d80 Import backup from 2005-02-15 2017-07-25 22:23:49 -04:00
josh 80774c48fe Import backup from 2005-02-07 2017-07-25 22:23:49 -04:00
josh 862b36b37b Import backup from 2005-02-01 2017-07-25 22:23:49 -04:00
josh 4638656aaf Import backup from 2005-01-31 2017-07-25 22:23:49 -04:00
josh 3381041a8f Import backup from 2005-01-26 2017-07-25 22:23:49 -04:00
josh f09ed66826 Import backup from 2005-01-18 2017-07-25 22:23:49 -04:00
josh ba5906c7a3 Import backup from 2005-01-14 2017-07-25 22:23:49 -04:00
josh 05183a3949 Import backup from 2005-01-05 2017-07-25 22:23:49 -04:00
josh d8580a9393 Import backup from 2005-01-04 2017-07-25 22:23:49 -04:00
josh 50285aa33b Import backup from 2005-01-01 2017-07-25 22:23:49 -04:00
josh ee63a84c0e Import backup from 2004-12-31 2017-07-25 22:23:49 -04:00
josh 76a243d894 Import backup from 2004-12-30 2017-07-25 22:23:49 -04:00
josh 6bad3f2b96 Import backup from 2004-12-29 2017-07-25 22:23:49 -04:00
josh 51948ce081 Import backup from 2004-12-24 2017-07-25 22:23:49 -04:00
josh b40a68f581 Import backup from 2004-12-23 2017-07-25 22:23:49 -04:00
josh 55b7429d4e Import backup from 2004-12-22 2017-07-25 22:23:49 -04:00
josh 7b805f2495 Import backup from 2004-12-21 2017-07-25 22:23:48 -04:00
josh 2445034e43 Import backup from 2004-12-20 2017-07-25 22:23:48 -04:00
josh 3c531f3b7b Import backup from 2004-12-17 2017-07-25 22:23:48 -04:00
josh 11cc0c87f3 Import backup from 2004-12-16 2017-07-25 22:23:48 -04:00
josh bad7f79ed1 Import backup from 2004-09-21 2017-07-25 22:23:48 -04:00
josh 78272f6bc3 Import backup from 2004-08-20 2017-07-25 22:23:48 -04:00
josh 396d5015d2 Import backup from 2004-08-19 2017-07-25 22:23:48 -04:00
josh 1bf14ddefa Import backup from 2004-08-17 2017-07-25 22:23:48 -04:00
josh c0dd3b529e Import backup from 2004-08-16 2017-07-25 22:23:48 -04:00
josh 8a8f56decb Import backup from 2004-08-15 2017-07-25 22:23:48 -04:00
josh b9c77827bd Import backup from 2004-08-06 2017-07-25 22:23:48 -04:00
josh cd02211b21 Import backup from 2004-08-03 2017-07-25 22:23:48 -04:00
josh a50c2a1233 Import backup from 2004-08-02 2017-07-25 22:23:48 -04:00
josh 07e8a0f4cf Import backup from 2004-07-31 2017-07-25 22:23:48 -04:00
josh 6d23c76e84 Import backup from 2004-07-29 2017-07-25 22:23:48 -04:00
josh 11da8cb162 Import backup from 2004-07-25 2017-07-25 22:23:48 -04:00
josh 1063a68a21 Import backup from 2004-07-20 2017-07-25 22:23:47 -04:00
josh 286b5e9ae1 Import backup from 2004-07-17 2017-07-25 22:23:47 -04:00
josh d4aadbea38 Import backup from 2004-07-15 2017-07-25 22:23:47 -04:00
josh dfb71cc759 Import backup from 2004-07-12 2017-07-25 22:23:47 -04:00
43 changed files with 2369 additions and 779 deletions

No files matched your search

-43
View File
@@ -1,43 +0,0 @@
# configuration file generated by Bochs
config_interface: textconfig
display_library: x
megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latest
boot: floppy
floppya: 1_44="hos.flp", status=inserted
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=0
ata2: enabled=0
ata3: enabled=0
parport1: enabled=1, file=""
com1: enabled=1, dev=""
usb1: enabled=1, ioaddr=0xff80, irq=10
# no sb16
floppy_bootsig_check: disabled=0
vga_update_interval: 30000
keyboard_serial_delay: 20000
keyboard_paste_delay: 100000
floppy_command_delay: 50000
ips: 500000
text_snapshot_check: 0
mouse: enabled=0
private_colormap: enabled=0
i440fxsupport: enabled=0
clock: sync=none, time0=local
# no ne2k
newharddrivesupport: enabled=1
# no loader
log: -
logprefix: %t%e%d
debugger_log: -
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
pass: action=fatal
keyboard_mapping: enabled=0, map=
keyboard_type: mf
user_shortcut: keys=none
# no cmosimage
+3
View File
@@ -0,0 +1,3 @@
.rscons*
/x86_64-elf-gcc/
/build/
+3
View File
@@ -0,0 +1,3 @@
[submodule "uefi-d"]
path = uefi-d
url = git://github.com/kubasz/uefi-d
-48
View File
@@ -1,48 +0,0 @@
# Makefile for HOS
# Josh Holtrop
# Created: 07/09/04
FLOPPY=/dev/fd0
FLOPPY_MOUNT=./mnt_flp
FLOPPY_IMAGE=hos.flp
GRUB_IMAGE=grub.flp
all:
make -C kernel
# make -C rmmod
clean:
make -C kernel clean
make -C include clean
# make -C rmmod clean
- rm *~ hos.flp
grub:
- mkdir $(FLOPPY_MOUNT)
mke2fs $(FLOPPY)
mount -t ext2 $(FLOPPY) $(FLOPPY_MOUNT)
grub-install --root-directory=$(FLOPPY_MOUNT) fd0
umount $(FLOPPY_MOUNT)
- rmdir $(FLOPPY_MOUNT)
grub_image:
dd if=$(FLOPPY) of=$(GRUB_IMAGE)
install:
- mkdir $(FLOPPY_MOUNT)
mount -t ext2 $(FLOPPY) $(FLOPPY_MOUNT)
cp kernel/kernel.bin $(FLOPPY_MOUNT)
cp menu.lst $(FLOPPY_MOUNT)/boot/grub
umount $(FLOPPY_MOUNT)
- rmdir $(FLOPPY_MOUNT)
install_img:
- mkdir $(FLOPPY_MOUNT)
cp grub.flp $(FLOPPY_IMAGE)
mount -t ext2 -o loop $(FLOPPY_IMAGE) $(FLOPPY_MOUNT)
cp kernel/kernel.bin $(FLOPPY_MOUNT)
cp menu.lst $(FLOPPY_MOUNT)/boot/grub
umount $(FLOPPY_MOUNT)
- rmdir $(FLOPPY_MOUNT)
+130
View File
@@ -0,0 +1,130 @@
require "tmpdir"
project_name "HOS"
path_prepend "x86_64-elf-gcc/bin"
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)
FileUtils.mkdir_p(File.dirname(@target))
File.write(@target, <<EOF)
.section ".rodata"
.balign 4096
.global _hulk_bin_start
_hulk_bin_start:
.incbin "#{@sources.first}"
.balign 4096
.global _hulk_bin_end
_hulk_bin_end:
EOF
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Creating HULK binary object <target>#{@target}<reset>", nil)
@cache.register_build(@target, nil, @sources, @env)
end
true
end
end
class Image < Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Creating disk image <target>#{@target}<reset>", nil)
File.binwrite(@target, "\0" * (1440 * 1024))
system(*%W[mformat -i #{@target} -f 1440 ::])
system(*%W[mmd -i #{@target} ::/EFI])
system(*%W[mmd -i #{@target} ::/EFI/BOOT])
system(*%W[mcopy -i #{@target} #{@sources.first} ::/EFI/BOOT])
@cache.register_build(@target, nil, @sources, @env)
end
true
end
end
class FontGen < Builder
def run(options)
if @command
finalize_command
else
fontgen = @vars["fontgen"]
@sources += [fontgen]
command = %W[#{fontgen} #{@sources.first} #{KFONT_SIZE} #{@target}]
standard_command("FontGen <target>#{@target}<reset>", command, {})
end
end
end
fontgen_env = env "fontgen", use: "freetype" do |env|
env.Program("^/fontgen", glob("src/fontgen/**/*.c"))
end
hulk_env = env "hulk", use: %w[ldc2 x86_64-elf-gcc] do |env|
env.add_builder(FontGen)
env.FontGen("^/src/hulk/kfont.d", "font/Hack-Regular.ttf",
"fontgen" => fontgen_env.expand("^/fontgen"))
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
hello_env = env "hello", use: %w[ldc2 x86_64-w64-mingw32-gcc] do |env|
env.add_builder(Image)
env.add_builder(HulkBinObj)
env["sources"] = glob("src/hello/**/*.d")
env["sources"] += glob("uefi-d/source/**/*.d")
env.HulkBinObj("^/hulk_bin.S", hulk_env.expand("^/hulk.bin"))
env.Object("^/hulk_bin.o", "^/hulk_bin.S")
env.depends("^/hulk_bin.o", hulk_env.expand("^/hulk.bin"))
env["sources"] << "^/hulk_bin.o"
env["DFLAGS"] += %w[-mtriple=x86_64-unknown-windows-coff --betterC -release -O3 --wi --enable-cross-module-inlining]
env["D_IMPORT_PATH"] += %w[src uefi-d/source]
env["LD"] = "x86_64-w64-mingw32-gcc"
env["LDFLAGS"] += %w[-nostdlib -Wl,-dll -shared -Wl,--subsystem,10 -e efi_main -Wl,-Map,${_TARGET}.map]
env["LDCMD"] = %w[${LD} -o ${_TARGET} ${LDFLAGS} ${_SOURCES} ${LIBDIRPREFIX}${LIBPATH} ${LIBLINKPREFIX}${LIBS}]
env["OBJDUMP"] = "x86_64-w64-mingw32-objdump"
env.Program("^/BOOTX64.EFI", "${sources}")
env["SIZE"] = "x86_64-w64-mingw32-size"
env.Size("^/BOOTX64.size", "^/BOOTX64.EFI")
env.Disassemble("^/BOOTX64.txt", "^/BOOTX64.EFI")
env.Image("^/hos.img", "^/BOOTX64.EFI")
end
task "run", desc: "Run HOS in QEMU" do
Dir.mktmpdir do |tmpdir|
img = hello_env.expand("^/hos.img")
FileUtils.cp(img, tmpdir)
sh %W[qemu-system-x86_64 -bios OVMF.fd -drive file=#{tmpdir}/hos.img,format=raw -device qemu-xhci -device usb-tablet]
end
end
Binary file not shown.
BIN
View File
Binary file not shown.
-2
View File
@@ -1,2 +0,0 @@
clean:
- rm *~
-23
View File
@@ -1,23 +0,0 @@
#ifndef __HOS_KERNEL_H__
#define __HOS_KERNEL_H__ __HOS_KERNEL_H__
#include "multiboot.h"
#define VIRT_OFFSET 0xC0000000
#define MAX_MODULES 16
#define MAX_MMAP 16
typedef unsigned int u32_t;
typedef unsigned short u16_t;
typedef unsigned char u8_t;
/* returns true to callee if we should jump to a real mode module */
int k_mbsave(mb_info_t *mbinfo, unsigned int mb_magic);
void k_init();
void isr();
#endif
-16
View File
@@ -1,16 +0,0 @@
#ifndef __HOS_MODULE_H__
#define __HOS_MODULE_H__ __HOS_MODULE_H__
#define MOD_REAL_MODE 1
#define MOD_KERNEL 2
typedef struct {
unsigned int mod_magic; // "HOSM" = 0x484F534D
unsigned int mod_type; // module type
void (*init) (); // address of void initialization function
unsigned int reserved;
} hos_module_header_t;
#endif
-144
View File
@@ -1,144 +0,0 @@
#ifndef __HOS_MULTIBOOT_H__
#define __HOS_MULTIBOOT_H__ __HOS_MULTIBOOT_H__
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
#define MB_HEADER_ALIGN_MODULES 0x01
#define MB_HEADER_MEM_INFO 0x02
#define MB_HEADER_VIDEO_INFO 0x04
#define MB_HEADER_KLUDGE_OFFSETS 0x10000
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#define MB_BOOTLOADER_MEM_INFO 0x01
#define MB_BOOTLOADER_BOOT_DEVICE 0x02
#define MB_BOOTLOADER_COMMAND_LINE 0x04
#define MB_BOOTLOADER_MODS 0x08
#define MB_BOOTLOADER_AOUT 0x10
#define MB_BOOTLOADER_ELF 0x20
#define MB_BOOTLOADER_MMAP 0x40
#define MB_BOOTLOADER_DRIVES 0x80
#define MB_BOOTLOADER_CONFIG 0x0100
#define MB_BOOTLOADER_APM 0x0200
#define MB_BOOTLOADER_GRAPHICS 0x0400
#define MB_DRIVE_MODE_CHS 0
#define MB_DRIVE_MODE_LBA 1
/* The Multiboot header. */
typedef struct
{
unsigned int magic;
unsigned int flags;
unsigned int checksum;
unsigned int header_addr;
unsigned int load_addr;
unsigned int load_end_addr;
unsigned int bss_end_addr;
unsigned int entry_addr;
} mb_header_t;
/* The symbol table for a.out. */
typedef struct
{
unsigned int tabsize;
unsigned int strsize;
unsigned int addr;
unsigned int reserved;
} mb_aout_symbol_table_t;
/* The section header table for ELF. */
typedef struct
{
unsigned int num;
unsigned int size;
unsigned int addr;
unsigned int shndx;
} mb_elf_section_header_table_t;
/* The Multiboot information. */
typedef struct
{
unsigned int flags;
unsigned int mem_lower; // present if flags[0] is set
unsigned int mem_upper;
unsigned int boot_device; // 1
unsigned int cmdline; // 2
unsigned int mods_count; // 3
unsigned int mods_addr;
union
{
mb_aout_symbol_table_t aout_sym; // 4
mb_elf_section_header_table_t elf_sec; // 5
};
unsigned int mmap_length; // 6
unsigned int mmap_addr;
unsigned int drives_length; // 7
unsigned int drives_addr;
unsigned int config_table; // 8
unsigned int bootloader_name; // 9
unsigned int apm_table; // 10
unsigned int vbe_control_info; // 11
unsigned int vbe_mode_info;
unsigned short vbe_mode;
unsigned short vbe_interface_seg;
unsigned short vbe_interface_off;
unsigned short vbe_interface_len;
} mb_info_t;
/* The module structure. */
typedef struct
{
unsigned int mod_start;
unsigned int mod_end;
unsigned int string;
unsigned int reserved;
} mb_module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low, not size. */
typedef struct
{
unsigned int size; //offset -4
unsigned int base_addr_low; //offset 0
unsigned int base_addr_high;
unsigned int length_low;
unsigned int length_high;
unsigned int type;
} mb_mmap_t;
/* The drive structure */
typedef struct
{
unsigned int size;
unsigned char drive_number;
unsigned char drive_mode;
unsigned char drive_cylinders;
unsigned char drive_heads;
unsigned char drive_sectors;
unsigned short drive_ports[1];
} mb_drive_t;
/* APM table structure */
typedef struct
{
unsigned short version;
unsigned short cseg;
unsigned int offset;
unsigned short cseg_16;
unsigned short dseg;
unsigned short flags;
unsigned short cseg_len;
unsigned short cseg_16_len;
unsigned short dseg_len;
} mb_apm_t;
#endif
-33
View File
@@ -1,33 +0,0 @@
# Makefile for HOS
# Josh Holtrop
# Created: 07/08/04
# Modified: 07/09/04
# Assembler Information:
NASM=nasm
NASM_FLAGS=-f aout
# C Information:
CC=gcc
CC_FLAGS=-fleading-underscore -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -I. -I../include -Wall
# Linker Information:
LD=ld
LD_FLAGS=-nodefaultlibs -nostdlib --no-demangle -T link.ld
all: Asm_Kernel C_Kernel
$(LD) $(LD_FLAGS) -Map boot.map boot.o kernel.o -o kernel.bin
Asm_Kernel:
$(NASM) $(NASM_FLAGS) -l boot.lst boot.asm -o boot.o
C_Kernel:
$(CC) $(CC_FLAGS) -c kernel.c -o kernel.o
#################################################
# Clean up the source directory of any binaries #
#################################################
clean:
- rm *.s *.S *.o *.bin *~ *.map *.lst
-196
View File
@@ -1,196 +0,0 @@
;boot.asm
;Author: Josh Holtrop
;Date: 07/08/04
;Modified: 07/10/04
%define MULTIBOOT_MAGIC 0x1BADB002
%define MULTIBOOT_FLAGS 0x00010003
%define VIRT_OFFSET 0xC0000000 ;3gb virtual address
%define PHYS_START 0x00100000 ;1mb physical address
%define VIRT_STACK_TOP 0xCFFFFFFC ;3gb+256mb virtual address
%define GDT_P PHYS_START ;1mb physical - Global Descriptor Table space
%define GDT_V GDT_P+VIRT_OFFSET
%define IDT_P PHYS_START+0x2000 ;1mb+8kb - Interrupt Descriptor Table space
%define IDT_V IDT_P+VIRT_OFFSET
%define PDBR_P PHYS_START+0x4000 ;1mb+16kb - Page Directory Base Register (first PD)
%define PDBR_V PDBR_P+VIRT_OFFSET
%define LOPT_P PHYS_START+0x5000 ;1mb+20kb - LOw Page Table for mapping first 4mb
%define LOPT_V LOPT_P+VIRT_OFFSET
%define PT_STACK_P PHYS_START+0x6000 ;1mb+24kb - page table for initial kernel stack pages (under 0xD0000000)
%define PT_STACK_V PT_STACK_P+VIRT_OFFSET
%define STACK_P PHYS_START+0x7000 ;1mb+28kb - initial 4kb kernel stack page
%define STACK_V STACK_P+VIRT_OFFSET
%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
[bits 32]
[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 0 ;load_end_addr
dd _end-VIRT_OFFSET ;bss_end_addr
dd multiboot_entry-VIRT_OFFSET ;entry_addr
; dd 1 ;mode_type
; dd 80 ;width
; dd 25 ;height
; dd 0 ;depth
[global multiboot_entry]
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]
jmp KERNEL_CODE_BS32:segmented_start
segmented_start:
mov ax, KERNEL_DATA_BS32
mov ss, ax
mov ds, ax
mov es, ax
mov gs, ax
mov fs, ax
mov esp, STACK_V+0x1000 ;ok, now we can access our data
;aloop:
; inc dword [0xC00B8000]
; jmp aloop
;Then the multiboot info structures are saved to local data variables.
add ebx, VIRT_OFFSET
push eax
push ebx ;pointer to multiboot info structure
call _k_mbsave ;save multiboot info structures
add esp, 8
cmp eax, 0
jz pm_return
;go back to real mode to initialize video mode
mov ebx, pm_return
;Next we enable paging with the first 4mb mapped 1:1 virtual:physical
; and with the 4mb starting at 0xC000_0000 mapped to the first 4mb physical.
pm_return:
xor eax, eax
mov edi, PDBR_V
mov ecx, 1024 ;clear the PDBR
rep stosd
mov edi, PT_STACK_V
mov ecx, 1024 ;clear the PT_STACK
rep stosd
mov [PDBR_V], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table | (read/write, present)
mov [PDBR_V+0xC00], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table | (read/write, present)
mov [PDBR_V+0xCFC], dword PT_STACK_P|0x03 ;store the physical address of the initial stack page page table | (read/write, present)
mov [PT_STACK_V+0xFFC], dword STACK_P|0x03 ;store the physical address of the initial stack page | (read/write, present)
mov edi, LOPT_V
mov ecx, 1024
mov eax, 0x03 ;starting physical address = 0x0 | (read/write, present flags)
fill_lopt_loop: ;fill the page table
stosd
add eax, 4096 ;increment next phsyical address by 4kb
loop fill_lopt_loop
mov eax, PDBR_P
mov cr3, eax ;store the Page Directory Base Address
mov eax, cr0
or eax, 0x80000000 ;set Page Enable bit
mov cr0, eax ;now paging is active!
mov edi, GDT_V
mov esi, gdt
mov ecx, gdt_end-gdt
rep movsb
mov edi, IDT_V ;destination
mov esi, isr_0 ;address of isr0
mov edx, isr_1-isr_0 ;distance between isr labels
mov ecx, 50 ;number of isrlabels
fill_idt:
mov ebx, esi
mov ax, si
stosw ;0 offset 15:0
mov ax, KERNEL_CODE
stosw ;2 selector 15:0
mov ax, 0x8E00
stosw ;4 [P][DPL][0][TYPE][0][0][0][0][0][0][0][0]
shr esi, 16
mov ax, si
stosw ;6 offset 31:16
mov esi, ebx
add esi, edx
loop fill_idt
mov word [IDT_V+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
;Then we can start using our "real" gdt, then unmap the lower 4mb.
lgdt [gdtr] ;load gdt
jmp KERNEL_CODE:newgdtcontinue
newgdtcontinue:
mov ax, KERNEL_DATA
mov es, ax
mov ds, ax
mov gs, ax
mov fs, ax
mov ss, ax
mov esp, VIRT_STACK_TOP ;stack just under 3gb+256mb, moves downward
lidt [idtr] ;load idt
mov [PDBR_V], dword 0 ;unmap 0x0, we are running completely paged at 0xC000_0000
call _k_init ;C kernel initialization
idle_loop:
; sti
hlt
jmp idle_loop
;-------------------------------------------------------
gdtrbs32:
dw gdt_endbs32-gdtbs32-1
dd gdtbs32-VIRT_OFFSET
gdtbs32: ;null descriptor
dd 0
dd 0
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
KERNEL_CODE_BS32 equ $-gdtbs32
db 0xff ;limit 7:0
db 0xff ;limit 15:8
db 0x00 ;base 7:0
db 0x00 ;base 15:8
db 0x00 ;base 23:16
db 0x9a ;access
db 0xcf ;flags / limit 19:16
db 0x40 ;base 31:24
KERNEL_DATA_BS32 equ $-gdtbs32
db 0xff ;limit 7:0
db 0xff ;limit 15:8
db 0x00 ;base 7:0
db 0x00 ;base 15:8
db 0x00 ;base 23:16
db 0x92 ;access
db 0xcf ;flags / limit 19:16
db 0x40 ;base 31:24
gdt_endbs32:
%include "gdt.inc"
%include "idt.inc"
-71
View File
@@ -1,71 +0,0 @@
;gdt.inc
;Author: Josh Holtrop
;Date: 10/30/03
;Modified: 03/02/04
gdtr:
dw gdt_end-gdt-1
dd GDT_V
gdt:
dd 0
dd 0
KERNEL_CODE equ $-gdt
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x9A ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
KERNEL_DATA equ $-gdt
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
USER_CODE equ $-gdt
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0xFA ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
USER_DATA equ $-gdt
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0xF2 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
VESA_CODE equ $-gdt
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x9A ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
VESA_DATA equ $-gdt
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
VIDEO_TEXT equ $-gdt
dw 0x7FFF ;limit 15:0
dw 0x8000 ;base 15:0
db 0x0B ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
VIDEO_GRAPHICS equ $-gdt
dw 0xFFFF ;limit 15:0
dw 0x0000 ;base 15:0
db 0x0A ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
gdt_end:
-92
View File
@@ -1,92 +0,0 @@
;idt.inc
;Author: Josh Holtrop
;Date: 10/30/03
;Modified: 07/06/04
idtr:
dw 50*8-1 ;size of idt
dd IDT_V ;address of idt
%macro isr_label 1
isr_%1:
push eax
mov eax, %1
jmp isr_main
%endmacro
isr_label 0
isr_label 1
isr_label 2
isr_label 3
isr_label 4
isr_label 5
isr_label 6
isr_label 7
isr_label 8
isr_label 9
isr_label 10
isr_label 11
isr_label 12
isr_label 13
isr_label 14
isr_label 15
isr_label 16
isr_label 17
isr_label 18
isr_label 19
isr_label 20
isr_label 21
isr_label 22
isr_label 23
isr_label 24
isr_label 25
isr_label 26
isr_label 27
isr_label 28
isr_label 29
isr_label 30
isr_label 31
isr_label 32
isr_label 33
isr_label 34
isr_label 35
isr_label 36
isr_label 37
isr_label 38
isr_label 39
isr_label 40
isr_label 41
isr_label 42
isr_label 43
isr_label 44
isr_label 45
isr_label 46
isr_label 47
isr_label 48
isr_label 49
isr_main:
pusha
push ds
push es
push eax ;interrupt number
call _isr
add esp, 4
pop es
pop ds
popa
pop eax ;original saved eax
iret
-76
View File
@@ -1,76 +0,0 @@
#include "kernel.h"
#include "multiboot.h"
#include "module.h"
mb_info_t mb_info_block;
mb_mmap_t mb_mmap[MAX_MMAP];
mb_module_t mb_modules[MAX_MODULES];
mb_apm_t mb_apm_table;
char mb_cmdline[256];
/* This function runs in segmented memory - 0xC000_0000 is mapped to 0x0 but 0x0
itself is an invalid linear address. Therefore, the multiboot information addresses
must be manually adjusted by VIRT_OFFSET to become valid linear addresses. */
int k_mbsave(mb_info_t *mbinfo, unsigned int mb_magic)
{
if (mb_magic != MULTIBOOT_BOOTLOADER_MAGIC)
{
char *msg = "Bad multiboot magic identifier!";
char *dest = (char *) 0xC00B8000;
while (*msg)
{
*dest++ = *msg++;
*dest++ = 0x04; //red error message
}
for (;;) ;
}
mb_info_block = *mbinfo;
if (mb_info_block.flags & MB_BOOTLOADER_COMMAND_LINE)
{
mb_info_block.cmdline += VIRT_OFFSET;
memcpy(mb_cmdline, mb_info_block.cmdline, 256);
mb_cmdline[255] = 0;
}
if (mb_info_block.flags & MB_BOOTLOADER_MODS)
{
mb_info_block.mods_addr += VIRT_OFFSET;
int i;
for (i = 0; i < mb_info_block.mods_count && i < MAX_MODULES; i++)
{
mb_modules[i] = ((mb_module_t *)mb_info_block.mods_addr)[i];
}
}
if (mb_info_block.flags & MB_BOOTLOADER_MMAP)
{
mb_info_block.mmap_addr += VIRT_OFFSET - 4; //-4 to get to size field, not base_addr_low field
mb_mmap_t *mmap = (mb_mmap_t *)mb_info_block.mmap_addr;
int i, sz = 0;
for (i = 0; sz < mb_info_block.mmap_length && i < MAX_MMAP; i++)
{
sz += mmap->size;
mb_mmap[i] = *mmap;
mmap = (mb_mmap_t *)(((u32_t) mmap) + mmap->size);
}
}
if (mb_info_block.flags & MB_BOOTLOADER_APM)
{
mb_info_block.apm_table += VIRT_OFFSET;
mb_apm_table = *(mb_apm_t *)mb_info_block.apm_table;
}
return 0;
}
void k_init()
{
for (;;)
{
(*(char*)0xC00B8000)++;
}
}
void isr()
{
for (;;) ;
}
-26
View File
@@ -1,26 +0,0 @@
OUTPUT_FORMAT("binary")
ENTRY(_start)
SECTIONS
{
.text 0xC0108000 : {
code = .; _code = .; __code = .;
*(.text)
. = ALIGN(4096);
}
.data : {
data = .; _data = .; __data = .;
*(.data)
/* . = ALIGN(4096); */
}
.rodata : {
rodata = .; _rodata = .; __rodata = .;
*(.rodata)
. = ALIGN(4096);
}
.bss : {
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
-9
View File
@@ -1,9 +0,0 @@
timeout 10
default 0
title HOS 0.15
root (fd0)
kernel /kernel.bin
+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
View File
Whitespace-only changes.
View File
Whitespace-only changes.
Executable
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env ruby
# Copyright (c) 2013-2022 Josh Holtrop
#
# MIT License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
script = File.join(File.dirname(__FILE__), ".rscons-3.0.2-c49c635f1e4166223367979510498b28.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.new.run(ARGV)
end
#==>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 truncated
+173
View File
@@ -0,0 +1,173 @@
#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 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 * d_file_name)
{
FILE * fh = fopen(d_file_name, "wb");
fprintf(fh, "module hulk.kfont;\n");
fprintf(fh, "struct CharInfo {\n");
fprintf(fh, " uint width;\n");
fprintf(fh, " uint height;\n");
fprintf(fh, " int top;\n");
fprintf(fh, " int left;\n");
fprintf(fh, " const ubyte[] bitmap;\n");
fprintf(fh, "};\n");
fprintf(fh, "struct FontInfo {\n");
fprintf(fh, " uint line_height;\n");
fprintf(fh, " uint advance;\n");
fprintf(fh, " int baseline_offset;\n");
fprintf(fh, " const CharInfo[] chars;\n");
fprintf(fh, "};\n");
fprintf(fh, "__gshared const FontInfo kfont = {\n");
fprintf(fh, " %du,\n", line_height);
fprintf(fh, " %du,\n", max_advance);
fprintf(fh, " %d,\n", baseline_offset);
fprintf(fh, " [\n");
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)
{
fprintf(fh, " [\n");
generate_bytes(fh, char_infos[i].bitmap, char_infos[i].width * char_infos[i].height);
fprintf(fh, " ]\n");
}
else
{
fprintf(fh, " []\n");
}
fprintf(fh, " ),\n");
}
fprintf(fh, " ],\n");
fprintf(fh, "};\n");
fclose(fh);
}
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;
}
+181
View File
@@ -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);
}
}
+457
View File
@@ -0,0 +1,457 @@
/**
* 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);
bootinfo().pt_phys = cast(ulong)scratch.current();
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;
bootinfo().pt_size = cast(ulong)scratch.current() - bootinfo().pt_phys;
jump_to_hulk();
return EFI_SUCCESS;
}
+39
View File
@@ -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;
}
}
+46
View File
@@ -0,0 +1,46 @@
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}");
}
ushort in16(ushort ioaddr)
{
return __asm!ushort("inw %dx, %ax", "={ax},{dx}", ioaddr);
}
ulong in32(ushort ioaddr)
{
return __asm!ulong("inl %dx, %eax", "={eax},{dx}", ioaddr);
}
void out16(ushort ioaddr, ushort v)
{
__asm("outw %ax, %dx", "{dx},{ax}", ioaddr, v);
}
void out32(ushort ioaddr, ulong v)
{
__asm("outl %eax, %dx", "{dx},{eax}", ioaddr, v);
}
+57
View File
@@ -0,0 +1,57 @@
import ldc.llvmasm;
void memset(void * dest, ubyte v, size_t n)
{
__asm("rep stosb",
"{al},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset16(void * dest, ushort v, size_t n)
{
__asm("rep stosw",
"{ax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset32(void * dest, uint v, size_t n)
{
__asm("rep stosl",
"{eax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset64(void * dest, ulong v, size_t n)
{
__asm("rep stosq",
"{rax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memcpy(void * dest, void * src, size_t n)
{
__asm("rep movsb",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy16(void * dest, void * src, size_t n)
{
__asm("rep movsw",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy32(void * dest, void * src, size_t n)
{
__asm("rep movsl",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy64(void * dest, void * src, size_t n)
{
__asm("rep movsq",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
+33
View File
@@ -0,0 +1,33 @@
struct PageTableEntry
{
ulong entry;
this(ulong address, ulong no_execute, ulong global,
ulong huge, ulong disable_cache, ulong write_through, ulong user,
ulong writable, ulong present)
{
entry = (present |
(writable << 1) |
(user << 2) |
(write_through << 3) |
(disable_cache << 4) |
(huge << 7) |
(global << 8) |
(no_execute << 63)) | address;
}
bool present()
{
return (entry & 0x1u) != 0u;
}
PageTableEntry * next()
{
return cast(PageTableEntry *)(entry & 0x7FFF_FFFF_FFFF_F000u);
}
static ulong page_table_index(ulong address, size_t level)
{
return ((address >> (39u - 9u * level)) & 0x1FFu);
}
}
+76
View File
@@ -0,0 +1,76 @@
/**
* 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;
/* Physical address of page tables while jumping to HULK. */
ulong pt_phys;
/* Size of page tables while jumping to HULK. */
ulong pt_size;
}
+102
View File
@@ -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
View File
@@ -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;
}
}
+40
View File
@@ -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;
}
+121
View File
@@ -0,0 +1,121 @@
/**
* HIPPO, the HOS In-place Physical Page Organizer.
*/
module hulk.hippo;
import hulk.header;
import hulk.bootinfo;
import hulk.klog;
import hulk.linker_addresses;
struct hippo
{
/**
* Linked list node entry for a physical page.
*/
private struct PhysicalPage
{
PhysicalPage * next;
}
/**
* Linked list of free physical pages.
*/
private static __gshared PhysicalPage * free_pages;
/**
* Number of free physical pages.
*/
private static __gshared size_t n_free_pages;
/**
* Initialize HIPPO.
*
* Ok, what we do here is iterate through all of the memory map regions in
* the bootinfo memory_map array, and create a linked list of all free
* physical pages that are available. Within the available memory regions,
* we have to watch out for the following items:
* 1) HULK binary (text + data)
* - This includes the HULK header and bootinfo structures
* 2) HULK bss
* 3) HULK stack
* 4) Framebuffer
* 5) Page tables
*
* @param bootinfo HULK boot information structure.
*/
public static void initialize(HulkHeader * header)
{
size_t usable_memory;
ulong[2][5] reserved = [
[header.bootinfo.hulk_phys, cast(ulong)header.total_size],
[header.bootinfo.bss_phys, LinkerAddresses.hulk_bss_size],
[header.bootinfo.stack_phys, header.stack_size],
[cast(ulong)header.bootinfo.fb.buffer, header.bootinfo.fb.height * header.bootinfo.fb.stride],
[header.bootinfo.pt_phys, header.bootinfo.pt_size],
];
for (size_t ri = 0u; ri < reserved.length; ri++)
{
reserved[ri][1] += reserved[ri][0];
}
for (size_t bii = 0u; bii < header.bootinfo.memory_map_count; bii++)
{
if (header.bootinfo.memory_map[bii].type == BootInfo.MemoryRegion.Type.Conventional)
{
ulong phys = header.bootinfo.memory_map[bii].base;
ulong phys_end = phys + header.bootinfo.memory_map[bii].size;
usable_memory += header.bootinfo.memory_map[bii].size;
phys_loop: while (phys < phys_end)
{
bool is_reserved = false;
for (size_t ri = 0u; ri < reserved.length; ri++)
{
if ((reserved[ri][0] <= phys) && (phys < reserved[ri][1]))
{
is_reserved = true;
break;
}
}
if (!is_reserved)
{
free_page(phys);
}
phys += 4096u;
}
}
}
size_t usable_kb = usable_memory >> 10u;
size_t usable_mb = usable_kb >> 10u;
size_t frac_mb = ((1000u * (usable_kb & 0x3FFu)) + 512u) >> 10u;
klog.writefln("Found %u.%03uMB of usable RAM", usable_mb, frac_mb);
}
/**
* Free a physical page.
*
* @param phys Physical page address.
*/
private static void free_page(ulong phys)
{
PhysicalPage * pp = cast(PhysicalPage *)phys;
pp.next = free_pages;
free_pages = pp;
n_free_pages++;
}
/**
* Allocate a physical page.
*
* @return Page address, or null if none available.
*/
public static void * allocate_page()
{
PhysicalPage * pp;
if (pp != null)
{
pp = free_pages;
free_pages = free_pages.next;
}
return cast(void *)pp;
}
}
+47
View File
@@ -0,0 +1,47 @@
/**
* 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;
import hulk.hippo;
import hulk.pci;
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!");
hippo.initialize(&hulk_header);
pci.initialize();
for (;;)
{
}
}
+47
View File
@@ -0,0 +1,47 @@
SECTIONS
{
. = 0xFFFF800000000000;
_hulk_mem_start = .;
.hulk_header :
{
*(.hulk_header)
}
. = ALIGN(4K);
_hulk_text_start = .;
.text :
{
*(.text)
}
. = ALIGN(4K);
_hulk_text_end = .;
.rodata :
{
*(.rodata)
}
. = ALIGN(4K);
.data :
{
*(.data)
}
. = ALIGN(4K);
_hulk_bss_start = .;
.bss :
{
*(COMMON)
*(.bss)
}
. = ALIGN(4K);
_hulk_bss_size = . - _hulk_bss_start;
_hulk_mem_end = .;
_hulk_total_size = _hulk_mem_end - _hulk_mem_start;
}
+15
View File
@@ -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;
+73
View File
@@ -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);
}
}
+41
View File
@@ -0,0 +1,41 @@
/**
* This module provides access to linker-defined symbols.
*/
module hulk.linker_addresses;
private extern extern(C) __gshared ubyte _hulk_mem_start;
private extern extern(C) __gshared ubyte _hulk_bss_start;
private extern extern(C) __gshared ubyte _hulk_bss_size;
private extern extern(C) __gshared ubyte _hulk_mem_end;
private extern extern(C) __gshared ubyte _hulk_total_size;
/**
* This struct provides access to linker-defined symbols.
*/
public struct LinkerAddresses
{
public static @property ulong hulk_mem_start()
{
return cast(ulong)&_hulk_mem_start;
}
public static @property ulong hulk_bss_start()
{
return cast(ulong)&_hulk_bss_start;
}
public static @property ulong hulk_bss_size()
{
return cast(ulong)&_hulk_bss_size;
}
public static @property ulong hulk_mem_end()
{
return cast(ulong)&_hulk_mem_end;
}
public static @property ulong hulk_total_size()
{
return cast(ulong)&_hulk_total_size;
}
}
+48
View File
@@ -0,0 +1,48 @@
module hulk.pci;
import hos.cpu;
import hulk.klog;
struct pci
{
/* IO address for PCI configuration address. */
enum IO_ADDR_CONFIG_ADDRESS = 0xCF8u;
/* IO address for PCI configuration data. */
enum IO_ADDR_CONFIG_DATA = 0xCFCu;
private static ulong read_config_register(ulong bus_id, ulong device_id, ulong register_id)
{
ulong addr = 0x8000_0000u | (bus_id << 16u) | (device_id << 11u) | (register_id << 2u);
out32(IO_ADDR_CONFIG_ADDRESS, addr);
return in32(IO_ADDR_CONFIG_DATA);
}
private static void scan(ulong bus_id, ulong device_id)
{
ulong reg0 = read_config_register(bus_id, device_id, 0u);
if (reg0 != 0xFFFFFFFFu)
{
ulong reg2 = read_config_register(bus_id, device_id, 2u);
klog.writefln("Found PCI device %04x:%04x (%02x:%02x:%02x) at %02u:%02u",
(reg0 & 0xFFFFu), (reg0 >> 16u),
(reg2 >> 24u) & 0xFFu,
(reg2 >> 16u) & 0xFFu,
(reg2 >> 8u) & 0xFFu,
bus_id, device_id);
}
}
public static void initialize()
{
klog.writefln("Scanning PCI devices...");
for (ulong bus_id = 0u; bus_id < 256u; bus_id++)
{
for (ulong device_id = 0u; device_id < 32u; device_id++)
{
scan(bus_id, device_id);
}
}
klog.writefln("PCI scan complete.");
}
}
+151
View File
@@ -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.
+76
View File
@@ -0,0 +1,76 @@
project_name "x86_64-elf-gcc"
binutils_version = "2.35"
binutils_checksum = "1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85"
gcc_version = "10.2.0"
gcc_checksum = "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
install_path = File.expand_path("x86_64-elf-gcc")
target = "x86_64-elf"
path_prepend "#{install_path}/bin"
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
default do
unless Dir.exist?(install_path)
# Download archives.
download "https://ftp.gnu.org/gnu/binutils/binutils-#{binutils_version}.tar.xz",
"#{build_dir}/binutils-#{binutils_version}.tar.xz",
sha256sum: binutils_checksum
download "https://ftp.gnu.org/gnu/gcc/gcc-#{gcc_version}/gcc-#{gcc_version}.tar.xz",
"#{build_dir}/gcc-#{gcc_version}.tar.xz",
sha256sum: gcc_checksum
# Extract archives.
sh "tar", "xJf", "binutils-#{binutils_version}.tar.xz",
chdir: build_dir
sh "tar", "xJf", "gcc-#{gcc_version}.tar.xz",
chdir: build_dir
# Build binutils.
rm_rf "#{build_dir}/build-binutils"
mkdir_p "#{build_dir}/build-binutils"
cd "#{build_dir}/build-binutils" do
sh %W[../binutils-#{binutils_version}/configure
--target=#{target} --prefix=#{install_path} --with-sysroot --disable-nls
--disable-werror]
sh "make"
sh "make install"
end
# Build gcc.
rm_rf "#{build_dir}/build-gcc"
mkdir_p "#{build_dir}/build-gcc"
cd "#{build_dir}/build-gcc" do
sh %W[../gcc-#{gcc_version}/configure
--target=#{target} --prefix=#{install_path} --disable-nls
--enable-languages=c --without-headers]
sh "make all-gcc"
sh "make all-target-libgcc"
sh "make install-gcc"
sh "make install-target-libgcc"
end
# Remove archives and build directories if everything succeeded.
rm_f "#{build_dir}/binutils-#{binutils_version}.tar.xz"
rm_rf "#{build_dir}/binutils-#{binutils_version}"
rm_rf "#{build_dir}/build-binutils"
rm_f "#{build_dir}/gcc-#{gcc_version}.tar.xz"
rm_rf "#{build_dir}/gcc-#{gcc_version}"
rm_rf "#{build_dir}/build-gcc"
end
end
distclean do
rm_rf install_path
end