258 Commits
Author SHA1 Message Date
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
josh 872d562d6a Import backup from 2004-07-10 2017-07-25 22:23:47 -04:00
josh 0729754659 Import backup from 2004-07-09 2017-07-25 22:23:47 -04:00
josh f3fe4ef3b8 Import backup from 2004-06-16 2017-07-25 22:23:47 -04:00
josh c76725eac3 Import backup from 2004-06-12 2017-07-25 22:23:47 -04:00
josh 9a8d2c29cb Import backup from 2004-06-10 2017-07-25 22:23:47 -04:00
josh b54b8191c4 Import backup from 2004-06-09 2017-07-25 22:23:47 -04:00
josh fdf6b71a91 Import backup from 2004-06-08 2017-07-25 22:23:47 -04:00
josh 802a07ebfe Import backup from 2004-06-07 2017-07-25 22:23:46 -04:00
josh b5ba5b63fe Import backup from 2004-06-03 2017-07-25 22:23:46 -04:00
josh b4aca026d4 Import backup from 2004-06-01 2017-07-25 22:23:46 -04:00
josh 6d941b7b16 Import backup from 2004-05-23 2017-07-25 22:23:46 -04:00
josh a982312d2c Import backup from 2004-05-22 2017-07-25 22:23:46 -04:00
josh 6b6e19effd Import backup from 2004-05-21 2017-07-25 22:23:46 -04:00
josh 38f009f2ca Import backup from 2004-04-05 2017-07-25 22:23:46 -04:00
josh 6236c341dd Import backup from 2004-04-03 2017-07-25 22:23:46 -04:00
josh 7110307896 Import backup from 2004-03-15 2017-07-25 22:23:46 -04:00
josh ab576bf18f Import backup from 2004-03-12 2017-07-25 22:23:46 -04:00
josh 302538b8ff Import backup from 2004-03-10 2017-07-25 22:23:46 -04:00
josh 7f886e44e1 Import backup from 2004-03-09 2017-07-25 22:23:46 -04:00
josh 8d0e6de040 Import backup from 2004-03-08 2017-07-25 22:23:46 -04:00
josh 0b9d7fde22 Import backup from 2004-03-02 2017-07-25 22:23:46 -04:00
josh 48f4046e79 Import backup from 2004-02-13 2017-07-25 22:23:46 -04:00
josh 2cd08dee70 Import backup from 2004-02-11 2017-07-25 22:23:46 -04:00
josh 311b8afc83 Import backup from 2004-01-26 2017-07-25 22:23:46 -04:00
josh 21e3943b5e Import backup from 2004-01-20 2017-07-25 22:23:46 -04:00
josh 10fd7102ca Import backup from 2004-01-18 2017-07-25 22:23:46 -04:00
josh 7de4f94423 Import backup from 2004-01-15 2017-07-25 22:23:46 -04:00
josh 0a546f1467 Import backup from 2004-01-07 2017-07-25 22:23:45 -04:00
josh af6087ecec Import backup from 2004-01-04 2017-07-25 22:23:45 -04:00
josh c613002307 Import backup from 2003-12-31 2017-07-25 22:23:45 -04:00
josh 76398df125 Import backup from 2003-12-30 2017-07-25 22:23:45 -04:00
josh e83408ce83 Import backup from 2003-12-29 2017-07-25 22:23:45 -04:00
josh 715bb9341a Import backup from 2003-12-28 2017-07-25 22:23:45 -04:00
josh e82bf2ecdf Import backup from 2003-12-25 2017-07-25 22:23:45 -04:00
josh 528527a7ed Import backup from 2003-12-23_2 2017-07-25 22:23:45 -04:00
josh 71aaa7a598 Import backup from 2003-12-23 2017-07-25 22:23:45 -04:00
josh 9070a76b18 Import backup from 2003-12-22_2 2017-07-25 22:23:45 -04:00
josh 5048a93ff7 Import backup from 2003-12-22 2017-07-25 22:23:45 -04:00
josh 282b856e24 Import backup from 2003-12-21 2017-07-25 22:23:45 -04:00
josh 3bb1e5fffc Import backup from 2003-12-20 2017-07-25 22:23:45 -04:00
josh 5ccfd0fc74 Import backup from 2003-11-13 2017-07-25 22:23:45 -04:00
josh 70d6bb1eb3 Import backup from 2003-11-12 2017-07-25 22:23:45 -04:00
josh 294b4b0e27 Import backup from 2003-11-11 2017-07-25 22:23:45 -04:00
josh 57980293e6 Import backup from 2003-11-03 2017-07-25 22:23:45 -04:00
josh ba97e8a7f0 Import backup from 2003-10-30 2017-07-25 22:23:45 -04:00
josh 36b025ccb4 Import backup from 2003-10-27 2017-07-25 22:23:45 -04:00
josh aab5ff3c90 Import backup from 2003-10-23 2017-07-25 22:23:45 -04:00
josh 8bf6e65a95 Import backup from 2003-10-16 2017-07-25 22:23:45 -04:00
josh 5da602b162 Import backup from 2003-10-06 2017-07-25 22:23:45 -04:00
josh 7a0351e123 Import backup from 2003-10-03 2017-07-25 22:23:45 -04:00
josh 3dc0fe5e2b Import backup from 2003-09-30 2017-07-25 22:23:45 -04:00
josh 82da40c9f0 Import backup from 2003-09-29 2017-07-25 22:23:45 -04:00
josh 8d5b28f823 Import backup from 2003-09-28 2017-07-25 22:23:45 -04:00
josh 68fd6cad70 Import backup from 2003-09-26 2017-07-25 22:23:45 -04:00
josh c3309d4e5d Import backup from 2003-09-23 2017-07-25 22:23:45 -04:00
josh 06d7cbef47 Import backup from 2003-09-13 2017-07-25 22:23:44 -04:00
josh e8b1abb265 Import backup from 2003-09-12 2017-07-25 22:23:44 -04:00
josh a40131b163 Import backup from 2003-09-11 2017-07-25 22:23:44 -04:00
josh fdfeb94ae3 Import backup from 2003-09-09 2017-07-25 22:23:44 -04:00
josh 3f4c7ff32f Import backup from 2003-09-08 2017-07-25 22:23:44 -04:00
josh 02d7fc9a69 Import backup from 2003-09-07 2017-07-25 22:23:44 -04:00
josh e147635333 Import backup from 2003-09-03 2017-07-25 22:23:44 -04:00
josh 5ffee3c2d8 Import backup from 2003-09-02 2017-07-25 22:23:44 -04:00
josh 9076a15f08 Import backup from 2003-09-01_2 2017-07-25 22:23:44 -04:00
josh dae5569216 Import backup from 2003-09-01 2017-07-25 22:23:44 -04:00
josh 594502f824 Import backup from 2003-08-31 2017-07-25 22:23:44 -04:00
josh c968aa28ac Import backup from 2003-08-26 2017-07-25 22:23:44 -04:00
josh 449917d434 Import backup from 2003-08-24 2017-07-25 22:23:44 -04:00
josh 8efede851c Import backup from 2003-08-19 2017-07-25 22:23:44 -04:00
josh 82cf9a9de4 Import backup from 2003-08-18_2 2017-07-25 22:23:44 -04:00
josh b0c1c492b2 Import backup from 2003-08-18 2017-07-25 22:23:44 -04:00
josh 162e52b121 Import backup from 2003-08-17_3 2017-07-25 22:23:44 -04:00
josh 9ee980bc94 Import backup from 2003-08-17_2 2017-07-25 22:23:44 -04:00
josh 43f3ea24f8 Import backup from 2003-08-17 2017-07-25 22:23:44 -04:00
josh 149541fbf1 Import backup from 2003-08-16 2017-07-25 22:23:44 -04:00
josh 588b3f06ba Import backup from 2003-08-13_2 2017-07-25 22:23:44 -04:00
josh 75c132cbd4 Import backup from 2003-08-13 2017-07-25 22:23:44 -04:00
josh 4e4baeba63 Import backup from 2003-08-12 2017-07-25 22:23:44 -04:00
josh 1c3e9ebdc4 Import backup from 2003-08-11 2017-07-25 22:23:44 -04:00
josh 9035beda29 Import backup from 2003-08-10 2017-07-25 22:23:44 -04:00
josh ff819331cf Import backup from 2003-08-09 2017-07-25 22:23:44 -04:00
josh 06fbbb1c87 Import backup from 2003-08-06 2017-07-25 22:23:44 -04:00
josh 2ada7fd5df Import backup from 2003-08-05 2017-07-25 22:23:44 -04:00
josh e6805ee94c Import backup from 2003-08-04 2017-07-25 22:23:44 -04:00
josh 7a4586bb06 Import backup from 2003-08-03 2017-07-25 22:23:44 -04:00
83 changed files with 2556 additions and 2155 deletions

No files matched your search

+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
-37
View File
@@ -1,37 +0,0 @@
KERNEL_FILE := hos.gz
MKISOFS := genisoimage
ISO := hos.iso
QEMU := qemu-system-x86_64
BOCHS := bochs
# default target: build the kernel and ISO image
all: kernel iso
# build the kernel
.PHONY: kernel
kernel:
$(MAKE) -C $@
# build the ISO image
.PHONY: iso
iso: $(ISO) kernel
$(ISO): kernel
cp kernel/$(KERNEL_FILE) iso/boot
-rm -f $(ISO)
$(MKISOFS) -R -b boot/grub/stage2_eltorito -no-emul-boot \
-boot-load-size 4 -boot-info-table -o $(ISO) iso
.PHONY: qemu
qemu: iso
$(QEMU) -cdrom $(ISO) -boot d -m 384 -localtime
.PHONY: bochs
bochs: iso
-$(BOCHS)
.PHONY: clean
clean:
$(MAKE) -C kernel clean
-rm -f $(ISO) iso/boot/$(KERNEL_FILE)
+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 = 15
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]
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]
end
end
-52
View File
@@ -1,52 +0,0 @@
# configuration file generated by Bochs
plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, gameport=1, pci_ide=1, acpi=1, ioapic=1
config_interface: textconfig
display_library: sdl
megs: 32
romimage: file="/usr/share/bochs/BIOS-bochs-latest"
vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest"
boot: cdrom
floppy_bootsig_check: disabled=0
# no floppya
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=cdrom, path="hos.iso", status=inserted, biosdetect=auto, model="Generic 1234"
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0
ata3: enabled=0
parport1: enabled=1, file=""
parport2: enabled=0
com1: enabled=1, mode=null, dev=""
com2: enabled=0
com3: enabled=0
com4: enabled=0
usb_uhci: enabled=0
usb_ohci: enabled=0
i440fxsupport: enabled=1
vga_update_interval: 50000
vga: extension=vbe
cpu: count=1, ips=4000000, reset_on_triple_fault=1, cpuid_limit_winnt=0
print_timestamps: enabled=0
# no gdb stub
port_e9_hack: enabled=0
text_snapshot_check: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local
# no cmosimage
ne2k: enabled=0
pnic: enabled=0
sb16: enabled=0
# no loader
log: -
logprefix: %t%e%d
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
pass: action=fatal
keyboard_type: mf
keyboard_serial_delay: 250
keyboard_paste_delay: 100000
keyboard_mapping: enabled=0, map=
user_shortcut: keys=none
mouse: enabled=0, type=ps2
Binary file not shown.
-6
View File
@@ -1,6 +0,0 @@
timeout 2
default 0
title HOS
kernel /boot/hos.gz
Binary file not shown.
-45
View File
@@ -1,45 +0,0 @@
CROSS_COMPILE := i586-elf-
export LD := $(CROSS_COMPILE)ld
export CC := $(CROSS_COMPILE)gcc
export CXX := $(CROSS_COMPILE)g++
export OBJDUMP := $(CROSS_COMPILE)objdump
export NASM := nasm
export HOS_TOPLEVEL := $(shell pwd)
LDSCRIPT := link.ld
KERNEL := hos
export CPPFLAGS := -I$(HOS_TOPLEVEL) -I$(HOS_TOPLEVEL)/include
export CFLAGS := -Wall -O2 -g
export CXXFLAGS := -Wall -O2 -fno-rtti -fno-exceptions -g
export LDFLAGS := -T $(LDSCRIPT) -Map $(KERNEL).map
export LDLIBS := `$(CC) -print-libgcc-file-name`
SUBDIRS := boot mm lang isr sys
SUBDIRS_clean := $(SUBDIRS:%=%.clean)
.PHONY: all
all: $(KERNEL).gz
$(KERNEL).gz: $(KERNEL)
gzip -c $< > $@
$(KERNEL): $(KERNEL).o
$(LD) $(LDFLAGS) -o $@ $<
$(OBJDUMP) --disassemble --source $@ > $@.dump
# strip $@
$(KERNEL).o: $(SUBDIRS)
$(LD) -r -o $@ $(foreach subdir,$(SUBDIRS),$(subdir)/$(subdir)_all.o) $(LDLIBS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@ SUBDIR=$@
.PHONY: clean
clean: $(SUBDIRS_clean)
-rm -f *~ $(KERNEL) $(KERNEL).{gz,o,elf,dump,map}
%.clean:
$(MAKE) -C $* clean clean=1
-2
View File
@@ -1,2 +0,0 @@
include $(HOS_TOPLEVEL)/subdir.mak
-23
View File
@@ -1,23 +0,0 @@
; boot.asm
; Author: Josh Holtrop
; Date: 2009-06-25
; Adapted from HOS 0.16 source
%define CONSOLE_MEMORY 0xB8000
; Symbols from C
extern k_bootstrap, bootstrap_stack
;**************************************************************************
;* This is the entry point for the kernel. *
;**************************************************************************
[global start]
start:
mov cx, 0x0700 + 'a'
mov [CONSOLE_MEMORY+160*8+0*2], cx
mov esp, bootstrap_stack+4096 ; set up temporary stack space
push eax ; multiboot bootloader magic value
push ebx ; pointer to multiboot info struct
call k_bootstrap
-85
View File
@@ -1,85 +0,0 @@
#include "k_bootstrap.h"
#include "k_main.h"
#include "hos_types.h"
#include "hos_defines.h"
#include "multiboot.h"
#include "sys/cpu.h"
#include "k_early_panic.h"
#include "mm/mm.h"
#include "mm/stack.h"
#include "lang/kio.h"
#include "isr/interrupts.h"
#define DEBUG_LETTER(col,chr) *(u16_t *)(KERNEL_OFFSET + CONSOLE_MEMORY \
+ 160 * 8 + (col) * 2) \
= 0x0700 | (chr)
extern "C" {
u8_t bootstrap_stack[4096];
/**************************************************************************
* Multiboot header data block *
*************************************************************************/
u32_t mb_header[] __attribute__ ((section (".multiboot_header") )) = {
MB_HEADER_MAGIC, /* magic */
MB_HEADER_FLAGS, /* flags */
-(MB_HEADER_MAGIC + MB_HEADER_FLAGS) /* checksum */
};
/**************************************************************************
* This function is invoked to bootstrap the kernel. *
*************************************************************************/
void k_bootstrap(mb_info_t * mb_info, u32_t mb_magic)
{
DEBUG_LETTER(1, 'b');
if (mb_magic != MB_BOOTLOADER_MAGIC)
{
k_early_panic("Bad multiboot magic identifier!");
}
if ( ! (mb_info->flags & MB_BOOTLOADER_MMAP) )
{
k_early_panic("No memory map provided by bootloader!");
}
for (mb_mmap_t * mmap = (mb_mmap_t *) (mb_info->mmap_addr + KERNEL_OFFSET),
* end = (mb_mmap_t *) ((u32_t)mmap + mb_info->mmap_length);
mmap < end;
mmap = (mb_mmap_t *) (((u32_t)mmap) + mmap->size + 4))
{
// kprintf(" ** size: %d, type: %d ", mmap->size, mmap->type);
mm_record_mmap_entry(mmap);
}
DEBUG_LETTER(2, 'c');
/*
* These functions could destroy the multiboot information block and
* associated structures, so we must be finished reading those structures
* before calling them.
*/
mm_bootstrap();
DEBUG_LETTER(3, 'd');
interrupts_bootstrap();
DEBUG_LETTER(4, 'e');
kio_bootstrap();
DEBUG_LETTER(5, 'f');
/* begin using the permanent stack */
write_esp(KERNEL_STACK_TOP);
k_main();
idle_loop();
}
void idle_loop()
{
for (;;)
{
__asm__ __volatile__ ("hlt");
}
}
} /* extern "C" */
-17
View File
@@ -1,17 +0,0 @@
#ifndef K_BOOTSTRAP_H
#define K_BOOTSTRAP_H
#include "hos_types.h"
#include "multiboot.h"
extern "C" {
void k_bootstrap(mb_info_t * mb_info, u32_t mb_magic)
__attribute__ ((noreturn));
void idle_loop()
__attribute__ ((noreturn));
}
#endif
-18
View File
@@ -1,18 +0,0 @@
#include "hos_types.h"
#include "hos_defines.h"
#include "k_early_panic.h"
void k_early_panic(const char * msg)
{
char * dest = (char *) (CONSOLE_MEMORY + KERNEL_OFFSET);
while (*msg)
{
*dest++ = *msg++;
*dest++ = 0x04; /* red error message */
}
/* infinite loop */
for (;;)
;
}
-15
View File
@@ -1,15 +0,0 @@
#ifndef K_EARLY_PANIC_H
#define K_EARLY_PANIC_H
#ifdef __cplusplus
extern "C" {
#endif
void k_early_panic(const char * msg);
#ifdef __cplusplus
}
#endif
#endif
-28
View File
@@ -1,28 +0,0 @@
#include "k_main.h"
#include "lang/kio.h"
#include "mm/mm.h"
#include "sys/timer.h"
#include "sys/pic.h"
#include "isr/interrupts.h"
extern "C" {
void k_main()
{
kprintf("Kernel load address: 0x%08x\n", KERNEL_CODE);
kprintf("Kernel code size: %d KB (%d bytes)\n",
(KERNEL_DATA - KERNEL_CODE) >> 10, KERNEL_DATA - KERNEL_CODE);
kprintf("Kernel data size: %d KB (%d bytes)\n",
(KERNEL_BSS - KERNEL_DATA) >> 10, KERNEL_BSS - KERNEL_DATA);
kprintf("Kernel bss size: %d KB (%d bytes)\n",
(KERNEL_END - KERNEL_BSS) >> 10, KERNEL_END - KERNEL_BSS);
mm_print_memory_map();
timer_init(KERNEL_TIMER_FREQ);
pic_remap(0x20, 0x28);
pic_mask1(0x0);
pic_mask2(0x0);
interrupts_enable();
}
} /* extern "C" */
-11
View File
@@ -1,11 +0,0 @@
#ifndef K_MAIN_H
#define K_MAIN_H
extern "C" {
void k_main();
}
#endif
-47
View File
@@ -1,47 +0,0 @@
#ifndef HOS_DEFINES_H
#define HOS_DEFINES_H
#include "hos_types.h"
#define KERNEL_OFFSET 0x00000000
#define PAGE_LOG_SIZE 12u
#define PAGE_SIZE (1 << PAGE_LOG_SIZE)
#define PAGE_HIGH_MASK (0xFFFFFFFFu << PAGE_LOG_SIZE)
#define PAGE_LOW_MASK (0xFFFFFFFFu >> (32 - PAGE_LOG_SIZE))
#define CONSOLE_MEMORY 0xB8000
#define KERNEL_CODE (&_code)
#define KERNEL_DATA (&_data)
#define KERNEL_BSS (&_bss)
#define KERNEL_END (&_end)
#define KERNEL_PHYSICAL_ADDRESS ((u32_t)(KERNEL_CODE - KERNEL_OFFSET))
#define KERNEL_VIRTUAL_ADDRESS ((u32_t)KERNEL_CODE)
#define KERNEL_SIZE ((u32_t)(KERNEL_END - KERNEL_CODE))
#define KERNEL_TIMER_FREQ 1000
#define BUILD_BUG_ON(condition) \
do { \
typedef struct { int negative_width_test : ((condition)?-1:1); } \
BUILD_BUG_ON_DUMMY_STRUCT; \
} \
while(0)
#ifdef __cplusplus
extern "C" {
#endif
extern u8_t _code;
extern u8_t _data;
extern u8_t _bss;
extern u8_t _end;
#ifdef __cplusplus
}
#endif
#endif
-55
View File
@@ -1,55 +0,0 @@
#ifndef HOS_TYPES_H
#define HOS_TYPES_H
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned char u8_t;
typedef signed char s8_t;
typedef unsigned short u16_t;
typedef signed short s16_t;
typedef unsigned int u32_t;
typedef signed int s32_t;
typedef unsigned long long u64_t;
typedef signed long long s64_t;
typedef struct
{
u32_t gs;
u32_t fs;
u32_t es;
u32_t ds;
u32_t edi;
u32_t esi;
u32_t ebp;
u32_t esp_junk; /* the esp value saved by 'pusha' */
u32_t ebx;
u32_t edx;
u32_t ecx;
u32_t eax;
u32_t error; /* valid on exceptions 8, 10-14 */
u32_t eip;
u32_t cs;
u32_t eflags;
u32_t esp; /* present if privilege transition */
u32_t ss;
} int_stack_t;
typedef struct
{
u16_t limit;
u32_t base;
} __attribute__ ((packed)) gdtr_t;
typedef gdtr_t idtr_t;
#ifdef __cplusplus
}
#endif
#endif
-154
View File
@@ -1,154 +0,0 @@
#ifndef MULTIBOOT_H
#define MULTIBOOT_H
#include "hos_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* The magic number for the Multiboot header. */
#define MB_HEADER_MAGIC 0x1BADB002
#define MB_HEADER_FLAGS 0x00000003
#define MB_HEADER_ALIGN_MODULES (1 << 0)
#define MB_HEADER_MEM_INFO (1 << 1)
#define MB_HEADER_VIDEO_INFO (1 << 2)
#define MB_HEADER_KLUDGE_OFFSETS (1 << 16)
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MB_BOOTLOADER_MAGIC 0x2BADB002
#define MB_BOOTLOADER_MEM_INFO (1 << 0)
#define MB_BOOTLOADER_BOOT_DEVICE (1 << 1)
#define MB_BOOTLOADER_COMMAND_LINE (1 << 2)
#define MB_BOOTLOADER_MODS (1 << 3)
#define MB_BOOTLOADER_AOUT (1 << 4)
#define MB_BOOTLOADER_ELF (1 << 5)
#define MB_BOOTLOADER_MMAP (1 << 6)
#define MB_BOOTLOADER_DRIVES (1 << 7)
#define MB_BOOTLOADER_CONFIG (1 << 8)
#define MB_BOOTLOADER_APM (1 << 9)
#define MB_BOOTLOADER_GRAPHICS (1 << 10)
#define MB_DRIVE_MODE_CHS 0
#define MB_DRIVE_MODE_LBA 1
#define MB_MMAP_TYPE_RAM 1
/* The Multiboot header. */
typedef struct
{
u32_t magic;
u32_t flags;
u32_t checksum;
u32_t header_addr; // if flags[16]
u32_t load_addr; // if flags[16]
u32_t load_end_addr; // if flags[16]
u32_t bss_end_addr; // if flags[16]
u32_t entry_addr; // if flags[16]
u32_t mode_type; // if flags[2]
u32_t width; // if flags[2]
u32_t height; // if flags[2]
u32_t depth; // if flags[2]
} mb_header_t;
/* The symbol table for a.out. */
typedef struct
{
u32_t tabsize;
u32_t strsize;
u32_t addr;
u32_t reserved;
} mb_aout_symbol_table_t;
/* The section header table for ELF. */
typedef struct
{
u32_t num;
u32_t size;
u32_t addr;
u32_t shndx;
} mb_elf_section_header_table_t;
/* The Multiboot information. */
typedef struct
{
u32_t flags;
u32_t mem_lower; // present if flags[0] is set
u32_t mem_upper;
u32_t boot_device; // 1
u32_t cmdline; // 2
u32_t mods_count; // 3
u32_t mods_addr; // 3
union
{
mb_aout_symbol_table_t aout_sym; // 4
mb_elf_section_header_table_t elf_sec; // 5
};
u32_t mmap_length; // 6
u32_t mmap_addr; // 6
u32_t drives_length; // 7
u32_t drives_addr; // 7
u32_t config_table; // 8
u32_t bootloader_name; // 9
u32_t apm_table; // 10
u32_t vbe_control_info; // 11
u32_t vbe_mode_info; // 11
u16_t vbe_mode; // 11
u16_t vbe_interface_seg; // 11
u16_t vbe_interface_off; // 11
u16_t vbe_interface_len; // 11
} mb_info_t;
/* The module structure. */
typedef struct
{
u32_t mod_start;
u32_t mod_end;
u32_t string;
u32_t reserved;
} mb_module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low, not size. */
typedef struct
{
u32_t size; // offset -4
u64_t base; // offset 0
u64_t length;
u32_t type;
} mb_mmap_t;
/* The drive structure */
typedef struct
{
u32_t size;
u8_t drive_number;
u8_t drive_mode;
u8_t drive_cylinders;
u8_t drive_heads;
u8_t drive_sectors;
u16_t drive_ports[1];
} mb_drive_t;
/* APM table structure */
typedef struct
{
u16_t version;
u16_t cseg;
u32_t offset;
u16_t cseg_16;
u16_t dseg;
u16_t flags;
u16_t cseg_len;
u16_t cseg_16_len;
u16_t dseg_len;
} mb_apm_t;
#ifdef __cplusplus
}
#endif
#endif
-37
View File
@@ -1,37 +0,0 @@
#ifndef PORTIO_H
#define PORTIO_H
#include "hos_types.h"
#define outportb(port, val) \
__asm__ __volatile__ ("outb %%al, %%dx" : : "a" (val), "d" (port));
#define outportw(port, val) \
__asm__ __volatile__ ("outw %%ax, %%dx" : : "a" (val), "d" (port));
#define outportd(port, val) \
__asm__ __volatile__ ("outl %%eax, %%dx" : : "a" (val), "d" (port));
static inline u8_t inportb(u16_t port)
{
u8_t val;
__asm__ __volatile__ ("inb %%dx, %%al" : "=a" (val) : "d" (port));
return val;
}
static inline u16_t inportw(u16_t port)
{
u16_t val;
__asm__ __volatile__ ("inw %%dx, %%al" : "=a" (val) : "d" (port));
return val;
}
static inline u32_t inportd(u16_t port)
{
u32_t val;
__asm__ __volatile__ ("inl %%dx, %%al" : "=a" (val) : "d" (port));
return val;
}
#endif
-2
View File
@@ -1,2 +0,0 @@
include $(HOS_TOPLEVEL)/subdir.mak
-110
View File
@@ -1,110 +0,0 @@
#include "hos_types.h"
#include "interrupts.h"
#include "mm/mm.h"
#include "lang/kio.h"
#include "sys/pic.h"
#include "sys/cpu.h"
extern "C" {
idtr_t idtr;
void isr(u8_t int_num, int_stack_t * istack)
{
switch (int_num)
{
case 0x20: /* timer interrupt */
(*(u16_t *)CONSOLE_MEMORY)++;
pic_eoi();
break;
case 0x21:
/* TODO: keyboard hook */
pic_eoi();
break;
default:
kputs("--------------------------------------------------------------------------------");
kprintf("Unhandled Interrupt #%d\n", int_num);
kprintf(" ds: 0x%08x es: 0x%08x fs: 0x%08x gs: 0x%08x\n",
istack->ds, istack->es, istack->fs, istack->gs);
kprintf(" eax: 0x%08x ebx: 0x%08x ecx: 0x%08x edx: 0x%08x\n",
istack->eax, istack->ebx, istack->ecx, istack->edx);
kprintf(" ebp: 0x%08x esi: 0x%08x edi: 0x%08x eflags: 0x%08x\n",
istack->ebp, istack->esi, istack->edi, istack->eflags);
kprintf(" cs: 0x%08x eip: 0x%08x ss: 0x%08x esp: 0x%08x\n",
istack->cs, istack->eip, istack->ss, istack->esp);
kprintf(" cr0: 0x%08x cr2: 0x%08x cr3: 0x%08x\n",
read_cr0(), read_cr2(), read_cr3());
kprintf(" Error: 0x%08x (%d)\n", istack->error, istack->error);
kputs("--------------------------------------------------------------------------------");
kprintf("Halting!\n");
for (;;)
;
break;
}
}
} /* extern "C" */
void interrupts_bootstrap()
{
u32_t idt_phys = mm_page_alloc();
u32_t idt_virt = mm_early_vpage_alloc();
mm_map(idt_virt, idt_phys, 0, 1);
u64_t * idt = (u64_t *) idt_virt;
idt[0] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_0, 0);
idt[1] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_1, 0);
idt[2] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_2, 0);
idt[3] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_3, 0);
idt[4] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_4, 0);
idt[5] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_5, 0);
idt[6] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_6, 0);
idt[7] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_7, 0);
idt[8] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_8, 0);
idt[9] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_9, 0);
idt[10] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_10, 0);
idt[11] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_11, 0);
idt[12] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_12, 0);
idt[13] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_13, 0);
idt[14] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_14, 0);
idt[15] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_15, 0);
idt[16] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_16, 0);
idt[17] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_17, 0);
idt[18] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_18, 0);
idt[19] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_19, 0);
idt[20] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_20, 0);
idt[21] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_21, 0);
idt[22] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_22, 0);
idt[23] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_23, 0);
idt[24] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_24, 0);
idt[25] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_25, 0);
idt[26] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_26, 0);
idt[27] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_27, 0);
idt[28] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_28, 0);
idt[29] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_29, 0);
idt[30] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_30, 0);
idt[31] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_31, 0);
idt[32] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_32, 0);
idt[33] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_33, 0);
idt[34] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_34, 0);
idt[35] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_35, 0);
idt[36] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_36, 0);
idt[37] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_37, 0);
idt[38] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_38, 0);
idt[39] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_39, 0);
idt[40] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_40, 0);
idt[41] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_41, 0);
idt[42] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_42, 0);
idt[43] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_43, 0);
idt[44] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_44, 0);
idt[45] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_45, 0);
idt[46] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_46, 0);
idt[47] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_47, 0);
idt[48] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_48, 0);
idt[49] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_49, 0);
idtr.base = idt_phys;
idtr.limit = 49 * sizeof(idt[0]) - 1;
__asm__ __volatile__ ("lidt (idtr)" : : : "memory");
}
-79
View File
@@ -1,79 +0,0 @@
#ifndef INTERRUPTS_H
#define INTERRUPTS_H
#ifdef __cplusplus
extern "C" {
#endif
void isr(u8_t int_num, int_stack_t * int_stack);
extern void isr_0();
extern void isr_1();
extern void isr_2();
extern void isr_3();
extern void isr_4();
extern void isr_5();
extern void isr_6();
extern void isr_7();
extern void isr_8();
extern void isr_9();
extern void isr_10();
extern void isr_11();
extern void isr_12();
extern void isr_13();
extern void isr_14();
extern void isr_15();
extern void isr_16();
extern void isr_17();
extern void isr_18();
extern void isr_19();
extern void isr_20();
extern void isr_21();
extern void isr_22();
extern void isr_23();
extern void isr_24();
extern void isr_25();
extern void isr_26();
extern void isr_27();
extern void isr_28();
extern void isr_29();
extern void isr_30();
extern void isr_31();
extern void isr_32();
extern void isr_33();
extern void isr_34();
extern void isr_35();
extern void isr_36();
extern void isr_37();
extern void isr_38();
extern void isr_39();
extern void isr_40();
extern void isr_41();
extern void isr_42();
extern void isr_43();
extern void isr_44();
extern void isr_45();
extern void isr_46();
extern void isr_47();
extern void isr_48();
extern void isr_49();
#ifdef __cplusplus
}
#endif
#define MAKE_IDT_DESCRIPTOR(selector, offset, dpl) \
(u64_t) ( ( (((u64_t) offset) & 0xFFFF0000ull) << 32 ) /* offset 31:16 */ \
| ( ( (u64_t) 0x1ull) << 47 ) /* present */ \
| ( (((u64_t) dpl) & 0x3) << 45 ) /* DPL */ \
| ( ( (u64_t) 0xEull) << 40 ) /* TODO: gate? */ \
| ( (((u64_t) selector) & 0xFFFFull) << 16 ) /* selector */ \
| ( (((u64_t) offset) & 0x0000FFFFull) ) ) /* offset 15:0 */
void interrupts_bootstrap();
#define interrupts_enable() __asm__ __volatile__ ("sti");
#define interrupts_disable() __asm__ __volatile__ ("cli");
#endif
-56
View File
@@ -1,56 +0,0 @@
; C ISR routine
[extern isr]
; Macro for creating a single ISR label
; We need to push a junk value on the stack first
; if the interrupt number is not 8 or 10-14.
; This is to properly align the stack for both exceptions
; having and not having error codes.
%macro isr_label 1
[global isr_%1]
isr_%1:
%if ( (%1 != 8) && (%1 < 10 || %1 > 14) )
push eax ; junk value to take error code stack space
%endif
pusha ; eax, ecx, edx, ebx, esp, ebp, esi, edi
mov al, %1 ; save interrupt number in al
%if ($ - isr_common) < 127 ; do a short jump and save 3 bytes if we can
jmp short isr_common
%else
jmp isr_common
%endif
%endmacro
; The common ISR routine
isr_common:
push ds
push es
push fs
push gs
push esp ; pointer to interrupt stack
push eax ; interrupt number
call isr
pop eax ; restore stack pointer (this is shorter
pop eax ; than "add esp, 8" and "lea esp, [esp+8]")
pop gs
pop fs
pop es
pop ds
popa ; edi, esi, ebp, <null>, ebx, edx, ecx, eax
lea esp, [esp+4] ; bypass error code
iret
; Loop to create all of our ISR entry points
%assign i 0
%rep 50
isr_label i
%assign i i+1
%endrep
-2
View File
@@ -1,2 +0,0 @@
include $(HOS_TOPLEVEL)/subdir.mak
-317
View File
@@ -1,317 +0,0 @@
#include "hos_types.h"
#include "hos_defines.h"
#include "kio.h"
#include "string.h"
#include "portio.h"
#include <limits.h>
#include <stdarg.h> /* va_*() */
static void fmt_d2a(char * buf, int val);
static void fmt_u2a(char * buf, unsigned int val);
static void fmt_ll2a(char * buf, long long val);
static void fmt_ull2a(char * buf, unsigned long long val);
static void fmt_x2a(char * buf, unsigned int val);
static void fmt_xl2a(char * buf, unsigned long long val);
static void fmt_o2a(char * buf, unsigned int val);
static int cursor_x, cursor_y;
static void writeCursorPosition(int x, int y)
{
u16_t pos = 80 * y + x;
outportb(0x3D4, 0x0E);
outportb(0x3D5, pos >> 8);
outportb(0x3D4, 0x0F);
outportb(0x3D5, pos);
}
extern "C" {
void kio_bootstrap()
{
cursor_x = 0;
cursor_y = 9;
writeCursorPosition(cursor_x, cursor_y);
}
void kprintf(const char * fmt, ...)
{
va_list args;
va_start(args, fmt);
kvprintf(fmt, args);
va_end(args);
}
void kvprintf(const char * fmt, va_list args)
{
char tmpbuf[25];
for ( ; *fmt; fmt++)
{
if (*fmt == '%')
{
fmt++;
if (*fmt)
{
int width = 0;
char pad_char = ' ';
bool pad_right = false;
if (*fmt == '0')
{
pad_char = '0';
fmt++;
}
else if (*fmt == '-')
{
pad_right = true;
fmt++;
}
for ( ; '0' <= *fmt && *fmt <= '9'; fmt++)
{
if (width == 0)
{
width = *fmt - '0';
}
else
{
width *= 10;
width += *fmt - '0';
}
}
switch (*fmt)
{
case 'c':
kputc(va_arg(args, int));
break;
case 'd':
fmt_d2a(tmpbuf, va_arg(args, int));
kputs_pad(tmpbuf, width, pad_char, pad_right);
break;
case 'l':
fmt_ll2a(tmpbuf, va_arg(args, long long));
kputs_pad(tmpbuf, width, pad_char, pad_right);
break;
case 'L':
fmt_ull2a(tmpbuf, va_arg(args, unsigned long long));
kputs_pad(tmpbuf, width, pad_char, pad_right);
break;
case 'o':
fmt_o2a(tmpbuf, va_arg(args, unsigned int));
kputs_pad(tmpbuf, width, pad_char, pad_right);
break;
case 's':
kputs_pad(va_arg(args, char *),
width, pad_char, pad_right);
break;
case 'u':
fmt_u2a(tmpbuf, va_arg(args, unsigned int));
kputs_pad(tmpbuf, width, pad_char, pad_right);
break;
case 'x':
fmt_x2a(tmpbuf, va_arg(args, unsigned int));
kputs_pad(tmpbuf, width, pad_char, pad_right);
break;
case 'X':
fmt_xl2a(tmpbuf, va_arg(args, unsigned long long));
kputs_pad(tmpbuf, width, pad_char, pad_right);
break;
case '%':
kputc('%');
break;
}
}
}
else
{
kputc(*fmt);
}
if (!*fmt)
{
break;
}
}
}
void kputc(char c)
{
u16_t * console_memory = (u16_t *) CONSOLE_MEMORY;
console_memory += 80 * cursor_y + cursor_x;
switch (c)
{
case '\t':
{
int to_advance = 8 - (cursor_x & 0x3);
while (to_advance--)
{
*console_memory++ = 0x0720;
}
}
break;
case '\n':
cursor_x = 0;
cursor_y++;
break;
default:
*console_memory = 0x0700 | (c & 0xFF);
cursor_x++;
break;
}
if (cursor_x >= 80)
{
cursor_x = 0;
cursor_y++;
}
if (cursor_y >= 25)
{
memcpy((u8_t *) CONSOLE_MEMORY,
(u8_t *) (CONSOLE_MEMORY + 80 * 2),
2 * 80 * 24);
memsetw((u16_t *) (CONSOLE_MEMORY + 2 * 80 * 24), 0x0720, 80);
cursor_y = 24;
}
writeCursorPosition(cursor_x, cursor_y);
}
void kputs(const char * s)
{
while (*s)
{
kputc(*s);
s++;
}
}
void kputs_pad(const char * s, int width, char pad_char, bool pad_right)
{
int len = strlen(s);
if (pad_right)
{
kputs(s);
}
int num_pad_chars = width - len;
for (int i = 0; i < num_pad_chars; i++)
{
kputc(pad_char);
}
if (!pad_right)
{
kputs(s);
}
}
} /* extern "C" */
static void fmt_d2a(char * buf, int val)
{
if (val < 0)
{
*buf++ = '-';
val = -val;
}
fmt_u2a(buf, (unsigned int) val);
}
static void fmt_u2a(char * buf, unsigned int val)
{
bool printing = false;
for (unsigned int div = 1000000000; div >= 1; div /= 10)
{
unsigned int n = val / div;
if (n || div == 1)
{
printing = true;
}
if (printing)
{
*buf++ = '0' + n;
}
val -= n * div;
}
*buf = '\0';
}
static void fmt_ll2a(char * buf, long long val)
{
if (val < 0)
{
*buf++ = '-';
val = -val;
}
fmt_ull2a(buf, (unsigned long long) val);
}
static void fmt_ull2a(char * buf, unsigned long long val)
{
bool printing = false;
for (unsigned long long div = 10000000000000000000ull; div >= 1; div /= 10)
{
unsigned long long n = val / div;
if (n || div == 1)
{
printing = true;
}
if (printing)
{
*buf++ = '0' + n;
}
val -= n * div;
}
*buf = '\0';
}
static void fmt_x2a(char * buf, unsigned int val)
{
bool printing = false;
for (int s = 28; s >= 0; s -= 4)
{
unsigned int n = (val >> s) & 0xF;
if (n || s == 0)
{
printing = true;
}
if (printing)
{
*buf++ = "0123456789abcdef"[n];
}
}
*buf = '\0';
}
static void fmt_xl2a(char * buf, unsigned long long val)
{
bool printing = false;
for (int s = 60; s >= 0; s -= 4)
{
unsigned int n = (val >> s) & 0xF;
if (n || s == 0)
{
printing = true;
}
if (printing)
{
*buf++ = "0123456789abcdef"[n];
}
}
*buf = '\0';
}
static void fmt_o2a(char * buf, unsigned int val)
{
bool printing = false;
for (int s = 30; s >= 0; s -= 3)
{
unsigned int n = (val >> s) & 0x7;
if (n || s == 0)
{
printing = true;
}
if (printing)
{
*buf++ = "01234567"[n];
}
}
*buf = '\0';
}
-27
View File
@@ -1,27 +0,0 @@
#ifndef KIO_H
#define KIO_H
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
void kio_bootstrap();
void kprintf(const char * fmt, ...);
void kvprintf(const char * fmt, va_list args);
void kputc(char c);
void kputs(const char * s);
void kputs_pad(const char * s, int width, char pad_char, bool pad_right);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
-73
View File
@@ -1,73 +0,0 @@
#include "string.h"
extern "C" {
void strcpy(char * dst, const char * src)
{
while (*src)
{
*dst++ = *src++;
}
*dst = '\0';
}
u32_t strlen(const char * s)
{
u32_t len = 0;
while (*s++)
{
len++;
}
return len;
}
void memcpy(u8_t * dst, u8_t * src, u32_t size)
{
for (u32_t n = 0; n < size; n++)
{
*dst++ = *src++;
}
}
void memcpyw(u16_t * dst, u16_t * src, u32_t size)
{
for (u32_t n = 0; n < size; n++)
{
*dst++ = *src++;
}
}
void memcpyd(u32_t * dst, u32_t * src, u32_t size)
{
for (u32_t n = 0; n < size; n++)
{
*dst++ = *src++;
}
}
void memset(u8_t * dst, u8_t val, u32_t size)
{
for (u32_t n = 0; n < size; n++)
{
*dst++ = val;
}
}
void memsetw(u16_t * dst, u16_t val, u32_t size)
{
for (u32_t n = 0; n < size; n++)
{
*dst++ = val;
}
}
void memsetd(u32_t * dst, u32_t val, u32_t size)
{
for (u32_t n = 0; n < size; n++)
{
*dst++ = val;
}
}
} /* extern "C" */
-27
View File
@@ -1,27 +0,0 @@
#ifndef STRING_H
#define STRING_H
#include "hos_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
void strcpy(char * dst, const char * src);
u32_t strlen(const char * s);
void memcpy(u8_t * dst, u8_t * src, u32_t size);
void memcpyw(u16_t * dst, u16_t * src, u32_t size);
void memcpyd(u32_t * dst, u32_t * src, u32_t size);
void memset(u8_t * dst, u8_t val, u32_t size);
void memsetw(u16_t * dst, u16_t val, u32_t size);
void memsetd(u32_t * dst, u32_t val, u32_t size);
#ifdef __cplusplus
}
#endif
#endif
-34
View File
@@ -1,34 +0,0 @@
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
virt = 0x00100000;
phys = 0x00100000;
SECTIONS
{
.text virt : AT(phys) {
code = .; _code = .; __code = .;
*(.multiboot_header*)
*(.text*)
*(.gnu.linkonce*)
. = ALIGN(4096);
}
.rodata : {
*(.rodata*)
. = ALIGN(4096);
}
.other : {
*(.eh_*)
*(.rel*)
. = ALIGN(4096);
}
.data : {
data = .; _data = .; __data = .;
*(.data*)
. = ALIGN(4096);
}
.bss : {
bss = .; _bss = .; __bss = .;
*(.bss*)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
-2
View File
@@ -1,2 +0,0 @@
include $(HOS_TOPLEVEL)/subdir.mak
-405
View File
@@ -1,405 +0,0 @@
#include <stddef.h>
#include "mm.h"
#include "stack.h"
#include "boot/k_early_panic.h"
#include "lang/string.h"
#include "lang/kio.h"
#include "sys/cpu.h"
#define MM_MAX_MMAP_ENTRIES 64
/* mmap management */
static mm_mem_range_t mm_mmap_entries[MM_MAX_MMAP_ENTRIES];
static int mm_mmap_num_entries = 0;
/* free/total page statistics */
static int mm_num_free_pages = 0;
static int mm_num_total_pages = 0;
gdtr_t mm_gdtr;
static u64_t * mm_gdt; /* NOT mapped into virtual address space */
static u32_t mm_heap_base; /* virtual address of start of heap */
static pagedirectory_t * early_page_directory_ptr;
/* physical addresses of page allocation pages to map in before the heap */
static u32_t page_alloc_page_numbers[1025]; /* supports 4GB physical memory */
static int last_page_alloc_page = -1; /* index of last valid page alloc page */
static int page_alloc_page_index = -1;
static mm_page_alloc_page_t * page_alloc_pages;
static int page_alloc_pages_index = -1;
/**************************************************************************
* Internal Functions *
*************************************************************************/
static void record_phys_page(u32_t base_address);
/**************************************************************************
* Compile-time tests *
*************************************************************************/
static void build_tests()
{
/* check that a mm_page_alloc_page_t fits exactly in a page */
BUILD_BUG_ON(sizeof(mm_page_alloc_page_t) != PAGE_SIZE);
}
/**************************************************************************
* This function is run in segmented memory before paging is in effect. *
* Record an mmap entry from the bootloader into our kernel space. *
*************************************************************************/
void mm_record_mmap_entry(mb_mmap_t * mmap)
{
if (mm_mmap_num_entries < MM_MAX_MMAP_ENTRIES)
{
if (mmap->type == MB_MMAP_TYPE_RAM)
{
mm_mmap_entries[mm_mmap_num_entries].base = mmap->base;
mm_mmap_entries[mm_mmap_num_entries].length = mmap->length;
mm_mmap_num_entries++;
}
}
else
{
k_early_panic("Too many mmap_entries!");
}
}
/**************************************************************************
* This function is run in segmented memory before paging is in effect. *
* It is run after the bootloader information has been read, so we can *
* overwrite that memory now. *
*************************************************************************/
void mm_bootstrap()
{
u32_t max_ram_address = KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE - 1;
if (mm_mmap_num_entries < 1)
{
k_early_panic("No mmap entries read from bootloader!");
}
mm_heap_base = (u32_t) KERNEL_END;
page_alloc_pages = (mm_page_alloc_page_t *) mm_heap_base;
for (int mmap_idx = 0; mmap_idx < mm_mmap_num_entries; mmap_idx++)
{
u32_t base_address = mm_mmap_entries[mmap_idx].base;
u32_t address_limit = base_address + mm_mmap_entries[mmap_idx].length;
if (base_address & PAGE_LOW_MASK)
{
/* start of this mmap range is not page-aligned */
base_address = (base_address & PAGE_HIGH_MASK) + PAGE_SIZE;
}
if (address_limit & PAGE_LOW_MASK)
{
/* end of this mmap range is not page-aligned */
address_limit &= PAGE_HIGH_MASK;
}
/* record the highest RAM address found */
if ((address_limit - 1) > max_ram_address)
{
max_ram_address = (address_limit - 1);
}
/*
* loop through every page in the mmap range and add
* pages into the free page linked list
*/
for (; base_address < address_limit; base_address += PAGE_SIZE)
{
/* check to make sure the page doesn't overlap the kernel */
if ( base_address + PAGE_SIZE <= KERNEL_PHYSICAL_ADDRESS
|| base_address >= KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE )
{
record_phys_page(base_address);
mm_num_free_pages++;
}
mm_num_total_pages++;
}
}
if (mm_num_free_pages < 10)
{
k_early_panic("Not enough free pages of RAM!");
}
/* ok, now mm_early_page_alloc() should be functional */
/* move the heap back to after the page allocation pages */
mm_heap_base = (u32_t) &page_alloc_pages[last_page_alloc_page + 1];
/* ok, now mm_early_vpage_alloc() should be functional */
/* allocate the page directory */
u32_t page_directory_phys = mm_early_page_alloc();
early_page_directory_ptr = (pagedirectory_t *)
(page_directory_phys + KERNEL_OFFSET);
/* Clear the page directory */
for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++)
{
(*early_page_directory_ptr)[i] = 0;
}
/* ok, now mm_early_map() should be functional */
/* map in the page directory itself so we can modify it once paging is on */
(*early_page_directory_ptr)[PAGE_DIR_SELF_REF_INDEX] =
(page_directory_phys) | (0x1 << 1) | (0x1);
/* map in the physical page allocator pages */
for (int i = 0; i <= last_page_alloc_page; i++)
{
mm_early_map((u32_t) &page_alloc_pages[i],
page_alloc_page_numbers[i], 0, 1);
}
/* map the kernel's virtual address space into RAM */
for (u32_t page_base = KERNEL_VIRTUAL_ADDRESS;
page_base < KERNEL_VIRTUAL_ADDRESS + KERNEL_SIZE;
page_base += PAGE_SIZE)
{
/* map page_base to page_base - KERNEL_OFFSET */
mm_early_map(page_base, page_base - KERNEL_OFFSET, 0, 1);
}
/* map console memory */
mm_early_map(CONSOLE_MEMORY, CONSOLE_MEMORY, 0, 1);
/* set up the global descriptor table */
u32_t gdt_base = mm_early_page_alloc();
mm_gdt = (u64_t *) ((u32_t) gdt_base + (u32_t) KERNEL_OFFSET);
mm_gdt[0] = 0x0ull;
mm_gdt[1] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 1); /* kernel code */
mm_gdt[2] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 0); /* kernel data */
mm_gdtr.limit = 3 * sizeof(mm_gdt[0]) - 1;
mm_gdtr.base = gdt_base;
__asm__ __volatile__ (
"lgdt (mm_gdtr);\n"
"jmp $0x08, $42f;\n"
"42:\n"
"mov $0x10, %%cx\n"
"mov %%cx, %%ss\n"
"mov %%cx, %%ds\n"
"mov %%cx, %%es\n"
"mov %%cx, %%fs\n"
"mov %%cx, %%gs\n"
: /* no outputs */
: /* no inputs */
: "ecx");
/* set the page directory base register */
write_cr3(page_directory_phys);
/* set up permanent stack before enabling paging */
stack_bootstrap();
/* turn on paging */
write_cr0(read_cr0() | (1 << 31));
}
/**************************************************************************
* This function is run in segmented memory before paging is in effect. *
* Record a physical page in the page allocation pages. *
*************************************************************************/
static void record_phys_page(u32_t base_address)
{
if (page_alloc_page_index < 0)
{
/* allocate a new page alloc page */
last_page_alloc_page++;
page_alloc_pages_index++;
page_alloc_page_numbers[last_page_alloc_page] = base_address;
page_alloc_page_index = 0;
}
else
{
mm_page_alloc_page_t * current_page_alloc_page =
(mm_page_alloc_page_t *)
(page_alloc_page_numbers[page_alloc_pages_index] + KERNEL_OFFSET);
page_alloc_page_index++;
(*current_page_alloc_page)[page_alloc_page_index] = base_address;
if (page_alloc_page_index == NUM_PAGETABLE_ENTRIES - 1)
{
page_alloc_page_index = -1;
}
}
}
/**************************************************************************
* Map virtual_address to physical_address. *
* Both addresses should be page-aligned. *
* This 'early' version can be used during segmented bootstrapping *
*************************************************************************/
int mm_early_map(u32_t virtual_address, u32_t physical_address,
u32_t user_mode, u32_t writable)
{
u32_t directory_index = (virtual_address >> 22) & 0x3FF;
u32_t table_index = (virtual_address >> 12) & 0x3FF;
if ((*early_page_directory_ptr)[directory_index] == 0)
{
/* allocate a new page table */
u32_t page_table_phys = mm_early_page_alloc();
if (page_table_phys == 0)
{
return 0;
}
pagedirectory_entry_t * page_table_virt = (pagedirectory_entry_t *)
(page_table_phys + KERNEL_OFFSET);
for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++)
{
page_table_virt[i] = 0;
}
(*early_page_directory_ptr)[directory_index] = page_table_phys
| (0x1 << 2) /* PTs can be user mode */
| (0x1 << 1) /* writable */
| (0x1); /* present */
}
u32_t page_table_phys =
(*early_page_directory_ptr)[directory_index] & PAGE_HIGH_MASK;
pagedirectory_entry_t * page_table =
(pagedirectory_entry_t *) (page_table_phys + KERNEL_OFFSET);
page_table[table_index] = (physical_address & PAGE_HIGH_MASK)
| ((user_mode & 0x1) << 2)
| ((writable & 0x1) << 1)
| 0x1; /* present */
return 1;
}
/**************************************************************************
* Map virtual_address to physical_address. *
* Both addresses should be page-aligned. *
*************************************************************************/
int mm_map(u32_t virtual_address, u32_t physical_address,
u32_t user_mode, u32_t writable)
{
u32_t directory_index = (virtual_address >> 22) & 0x3FF;
u32_t table_index = (virtual_address >> 12) & 0x3FF;
pagedirectory_entry_t * page_dir_entry = (pagedirectory_entry_t *)
(PAGE_DIR_SELF_REF2 | (directory_index << 2));
if (*page_dir_entry == 0)
{
/* allocate a new page table */
u32_t page_table_phys = mm_page_alloc();
if (page_table_phys == 0)
{
return 0;
}
*page_dir_entry = page_table_phys
| (0x1 << 2) /* PTs can be user mode */
| (0x1 << 1) /* writable */
| (0x1); /* present */
pagedirectory_entry_t * page_table = (pagedirectory_entry_t *)
(PAGE_DIR_SELF_REF | (directory_index << 12));
for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++)
{
page_table[i] = 0;
}
}
pagedirectory_entry_t * page_table_entry = (pagedirectory_entry_t *)
(PAGE_DIR_SELF_REF | (directory_index << 12) | (table_index << 2));
*page_table_entry = (physical_address & PAGE_HIGH_MASK)
| ((user_mode & 0x1) << 2)
| ((writable & 0x1) << 1)
| 0x1; /* present */
return 1;
}
/**************************************************************************
* Returns the physical base address of a page in RAM *
* or 0 if no pages were available *
* This 'early' version can be used during segmented bootstrapping *
*************************************************************************/
u32_t mm_early_page_alloc()
{
u32_t page_address = 0;
if (page_alloc_pages_index >= 0)
{
if (page_alloc_page_index >= 0)
{
mm_page_alloc_page_t * current_pap = (mm_page_alloc_page_t *)
(page_alloc_page_numbers[page_alloc_pages_index]
+ KERNEL_OFFSET);
page_address = (*current_pap)[page_alloc_page_index];
page_alloc_page_index--;
}
else
{
/* return the page allocation page itself */
page_address = page_alloc_page_numbers[page_alloc_pages_index];
page_alloc_pages_index--;
page_alloc_page_index = NUM_PAGETABLE_ENTRIES - 1;
}
mm_num_free_pages--;
}
return page_address;
}
/**************************************************************************
* Returns the physical base address of a page in RAM *
* or 0 if no pages were available *
*************************************************************************/
u32_t mm_page_alloc()
{
u32_t page_address = 0;
if (page_alloc_pages_index >= 0)
{
if (page_alloc_page_index >= 0)
{
page_address =
page_alloc_pages[page_alloc_pages_index][page_alloc_page_index];
page_alloc_page_index--;
}
else
{
/* return the page allocation page itself */
page_address = page_alloc_page_numbers[page_alloc_pages_index];
page_alloc_pages_index--;
page_alloc_page_index = NUM_PAGETABLE_ENTRIES - 1;
}
mm_num_free_pages--;
}
return page_address;
}
/**************************************************************************
* This function allocates a virtual page. It should only be called *
* during the bootstrap process, before the kernel begins its normal *
* operation. It adjusts the heap pointer to push it back beyond any *
* bootstrap pages allocated. *
*************************************************************************/
u32_t mm_early_vpage_alloc()
{
u32_t vaddress = mm_heap_base;
mm_heap_base += PAGE_SIZE;
return vaddress;
}
void mm_print_memory_map()
{
kprintf("Bootloader provided memory map:\n");
kprintf(" Base Address Length\n");
for (int i = 0; i < mm_mmap_num_entries; i++)
{
kprintf(" 0x%016X 0x%016X (%l bytes / %l KB / %l MB)\n",
mm_mmap_entries[i].base,
mm_mmap_entries[i].length,
mm_mmap_entries[i].length,
mm_mmap_entries[i].length >> 10,
mm_mmap_entries[i].length >> 20);
}
kprintf("Used pages: %d\n", mm_num_total_pages - mm_num_free_pages);
kprintf("Free pages: %d\n", mm_num_free_pages);
}
-65
View File
@@ -1,65 +0,0 @@
#ifndef MM_H
#define MM_H MM_H
#include "hos_types.h"
#include "hos_defines.h"
#include "multiboot.h"
#define KERNEL_CODE_SEGMENT 0x08
#define KERNEL_DATA_SEGMENT 0x10
typedef u32_t pagedirectory_entry_t;
#define NUM_PAGETABLE_ENTRIES (PAGE_SIZE / sizeof(pagedirectory_entry_t))
#define PAGE_DIR_SELF_REF (0x20000000u - (PAGE_SIZE * NUM_PAGETABLE_ENTRIES))
#define PAGE_DIR_SELF_REF_INDEX ((PAGE_DIR_SELF_REF >> 22) & 0x3FF)
#define PAGE_DIR_SELF_REF2 (PAGE_DIR_SELF_REF | (PAGE_DIR_SELF_REF_INDEX << 12))
typedef pagedirectory_entry_t pagedirectory_t[NUM_PAGETABLE_ENTRIES];
typedef struct
{
u64_t base;
u64_t length;
} mm_mem_range_t;
typedef u32_t mm_page_alloc_page_t[NUM_PAGETABLE_ENTRIES];
/* http://courses.ece.illinois.edu/ece391/references/descriptors.pdf */
/* granularity: 0: limit in bytes; 1: limit in pages */
/* dpl: 0: system mode; 3: user mode */
/* normal: 0: TSS/LDT/call gate; 1: code/data segment */
/* code_seg: 0: data segment; 1: code segment */
#define MAKE_DESCRIPTOR(base, limit, granularity, dpl, normal, code_seg) \
(u64_t) ( ( (((u64_t) base) & 0xFF000000ull) << 32 ) /* base 31:24 */ \
| ( (((u64_t) granularity) & 0x1ull) << 55 ) /* granularity */ \
| ( ( (u64_t) 0x1ull) << 54 ) /* 32-bit */ \
| ( (((u64_t) limit) & 0xF0000ull) << 32 ) /* limit 19:16 */ \
| ( ( (u64_t) 0x1ull) << 47 ) /* present */ \
| ( (((u64_t) dpl) & 0x3ull) << 45 ) /* dpl */ \
| ( (((u64_t) normal) & 0x1ull) << 44 ) /* normal */ \
| ( (((u64_t) code_seg) & 0x1ull) << 43 ) /* code seg */ \
| ( ( (u64_t) 0x2ull) << 40 ) /* ? */ \
| ( (((u64_t) base) & 0x00FFFFFFull) << 16) /* base 23:00 */ \
| ( (((u64_t) limit) & 0x0000FFFFull) ) ) /* limit 15:00 */
typedef u64_t descriptor_t;
void mm_record_mmap_entry(mb_mmap_t * mmap);
void mm_bootstrap();
int mm_early_map(u32_t virtual_address, u32_t physical_address,
u32_t user_mode, u32_t writable);
int mm_map(u32_t virtual_address, u32_t physical_address,
u32_t user_mode, u32_t writable);
u32_t mm_early_page_alloc();
u32_t mm_page_alloc();
u32_t mm_early_vpage_alloc();
void mm_print_memory_map();
#endif
-19
View File
@@ -1,19 +0,0 @@
#include "stack.h"
#include "mm.h"
#include "hos_defines.h"
void stack_bootstrap()
{
/*
* running from our temporary stack while segmentation is enabled,
* set up the "permanent" stack for use while paging
*/
u32_t stack_page_virt = KERNEL_STACK_TOP - PAGE_SIZE;
for (int i = 0; i < STACK_INITIAL_SIZE; i++)
{
u32_t stack_page_phys = mm_early_page_alloc();
mm_early_map(stack_page_virt, stack_page_phys, 0, 1);
stack_page_virt -= PAGE_SIZE;
}
}
-13
View File
@@ -1,13 +0,0 @@
#ifndef STACK_H
#define STACK_H
#include "mm/mm.h"
#define KERNEL_STACK_TOP PAGE_DIR_SELF_REF
#define STACK_INITIAL_SIZE 2 /* number of initial stack pages */
void stack_bootstrap();
#endif
-54
View File
@@ -1,54 +0,0 @@
ASMOBJS := $(patsubst %.asm,%.o,$(wildcard *.asm))
COBJS := $(patsubst %.c,%.o,$(wildcard *.c))
CXXOBJS := $(patsubst %.cc,%.o,$(wildcard *.cc))
CDEPS := $(COBJS:.o=.dep)
CXXDEPS := $(CXXOBJS:.o=.dep)
DEPS := $(CDEPS) $(CXXDEPS)
OUTPUT_FILE := $(SUBDIR)_all.o
ifdef SUBDIRS
SUBDIRS_clean := $(SUBDIRS:%=%.clean)
endif
all: $(OUTPUT_FILE)
$(OUTPUT_FILE): $(ASMOBJS) $(COBJS) $(CXXOBJS) $(SUBDIRS)
$(LD) -r -o $@ $(ASMOBJS) $(COBJS) $(CXXOBJS) $(foreach subdir,$(SUBDIRS),$(subdir)/$(subdir)_all.o)
%.o: %.asm
$(NASM) -f elf -o $@ -l $<.lst $<
%.o: %.c
$(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
%.o: %.cc
$(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $<
ifdef SUBDIRS
.PHONY: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@ SUBDIR=$@
endif
# Make dependency files
%.dep: %.c
@set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@
%.dep: %.cc
@set -e; rm -f $@; \
$(CXX) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@
clean: $(SUBDIRS_clean)
-rm -f *.o *.dep *.lst *~
ifdef SUBDIRS
%.clean:
$(MAKE) -C $* clean clean=1
endif
# Include dependency files
ifndef clean
-include $(DEPS)
endif
-2
View File
@@ -1,2 +0,0 @@
include $(HOS_TOPLEVEL)/subdir.mak
-40
View File
@@ -1,40 +0,0 @@
#ifndef CPU_H
#define CPU_H
#include "hos_types.h"
static u32_t read_cr0() __attribute__ ((unused));
static u32_t read_cr0()
{
u32_t val;
__asm__ __volatile__ ("movl %%cr0, %0" : "=r" (val));
return val;
}
static u32_t read_cr2() __attribute__ ((unused));
static u32_t read_cr2()
{
u32_t val;
__asm__ __volatile__ ("movl %%cr2, %0" : "=r" (val));
return val;
}
static u32_t read_cr3() __attribute__ ((unused));
static u32_t read_cr3()
{
u32_t val;
__asm__ __volatile__ ("movl %%cr3, %0" : "=r" (val));
return val;
}
#define write_cr0(val) \
__asm__ __volatile__ ("movl %0, %%cr0" : : "r" (val));
#define write_cr3(val) \
__asm__ __volatile__ ("movl %0, %%cr3" : : "r" (val));
#define write_esp(val) \
__asm__ __volatile__ ("movl %0, %%esp" : : "r" (val));
#endif
-29
View File
@@ -1,29 +0,0 @@
#include "pic.h"
#include "portio.h"
/*
* Re-maps the Programmable Interrupr Controllers
* so IRQ0->pic1 base address, IRG8->pic2 base address
*/
void pic_remap(u8_t base1, u8_t base2)
{
u8_t a1, a2;
a1 = inportb(PIC1_DATA); /* 0x21 */
a2 = inportb(PIC2_DATA); /* 0xA1 */
outportb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); /* 0x20, 0x10+0x01 00010001b */
outportb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); /* 0xA0, 0x10+0x01 00010001b */
outportb(PIC1_DATA, base1); /* 0x21, pic1 */
outportb(PIC2_DATA, base2); /* 0xA1, pic2 */
outportb(PIC1_DATA, 4); /* 0x21, 0x04 00000100b */
outportb(PIC2_DATA, 2); /* 0xA1, 0x02 00000010b */
outportb(PIC1_DATA, ICW4_8086); /* 0x21, 0x01 00000001b */
outportb(PIC2_DATA, ICW4_8086); /* 0xA1, 0x01 00000001b */
outportb(PIC1_DATA, a1); /* 0x21 */
outportb(PIC2_DATA, a2); /* 0xA1 */
}
-46
View File
@@ -1,46 +0,0 @@
#ifndef PIC_H
#define PIC_H
#include "hos_types.h"
#include "portio.h"
#define PIC1 0x20
#define PIC2 0xA0
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define PIC_EOI 0x20
#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
#define ICW1_INIT 0x10 /* Initialization - required! */
#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
void pic_remap(u8_t base1, u8_t base2);
/* Masks interrupts on first Programmable Interrupt Controller */
#define pic_mask1(mask) outportb(PIC1_DATA, mask) /* 0x21, maskfield *OCW1* */
/* Masks interrupts on second Programmable Interrupt Controller */
#define pic_mask2(mask) outportb(PIC2_DATA, mask) /* 0xA1, maskfield *OCW1* */
/* Signals an End Of Interrupt signal to the first PIC */
#define pic_eoi() outportb(0x20, 0x20)
/* Signals an End Of Interrupt signal to both the second and first PIC unit */
static inline void pic_eoi2()
{
outportb(0xA0, 0x20);
outportb(0x20, 0x20);
}
#endif
-12
View File
@@ -1,12 +0,0 @@
#include "timer.h"
#include "portio.h"
void timer_init(u32_t freq)
{
/* how many ticks the PIT must wait before issuing an interrupt */
u32_t wait = 1193180 / freq;
outportb(0x43, 0x34);
outportb(0x40, wait); /* LSB */
outportb(0x40, wait >> 8); /* MSB */
}
-9
View File
@@ -1,9 +0,0 @@
#ifndef TIMER_H
#define TIMER_H
#include "hos_types.h"
void timer_init(u32_t freq);
#endif
+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
+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
#==>eJztfWt3GzeS6Pf8inbbiUmZouzMndlzGCuSLMmJ9sqWryRnPUszHIpsSj0mu7ndpGStzP3tF1V4VQHoJuVHbnbP9ZyJ2HgUgEKhUCgUqh4+2FqUxdZFmm0l2XVULC5uvyuS/1ikRRLFWTLfuprPZ7FNGqWXSTmPv5vmo8UkiU7LYZ6V30WR+t7LylR8RdFwMijL6PnzqEwmY0yJotPDs8PzaDuK3yfdp9NYpY6ScXRTpPOkkeataGOalOXgMmmqXJGf94f5JC9ERdlaezCbTdLhYJ7mWVvkDkSbsoipk45NtXaWTnZMBgOn6u6Ihm1zSTYyv/PFHLobh+ASkMNFUSTZ3HYTxkmbTEqBu1FlvhpyOxkMrwT86NP0E8nFVqfttOwPdhpn8yLNLpssO4omaZaUAvC0XQrMzBvx+yxuRZvPguWwmf5NOr/qp9ko+YgtQk4rSj85FbBtyIseMDywfD58UZCNN1BHIvbJOgVd1K6qQWfPaw4G4uWGaohBpdFzha4y/c8k2oyerTl4d3K9XlQXWEVHaw0S5n6NQbopyaR0cTMclEk0dRJvrpIs6ogp+ImmuhSOK/ynvzybul2R1S+LJMl+Wln9x4rqt8lkkt/8tKr6XyqqX0wWCe19RfX/VVF9KpZqNh/8tKL6XyuqD28H2Rqt/62i+s2V4JSrUfcvVWPPJyM6eaHqz6onDqrTyauoXjVxUJ1OXkX1yokT1enkVVSvmjioTievonrVxEF1OnkV1asmDqrTyauoXjdxq8imataKpEzmNTQT4jMef2Df/Gs9NljB/igohwl98b6ompyuORL6O83bUigRMDRYmz8r0uvBXPcVJJigLCE6ePr2xd/7b473zl+enL6Ktv8r2pqKjt58mpa35RbpR+Pw9W/d+Pzw9FXci7bFfH6cJ8U0bkY//BB9f9Mdp+M8Gl4NisFQpJ/NkmE6mPTaaTacLEYJtNou54N5ezy/nRHZyUGoKDWf3+4EBqx/yb/wX/i/kfoE/fginxTx9qwwhhAG83nRL5LBKCmijuhtep30rwdFOsjmpS0wGA7F5ApS6Vws0smoP0qLUKYv3TkFsv78Chor/bbLYZHO5qFKZTqRtJqN08tFkYTKXCfFRa6QB/MrZKV0LnAuhAGFsl0XjFhJ82Jhss3ARDpO7unZ/snrs/6Lt0fHB/2Do1Mx0Z8+RTGW0wtXFGyPkkkiCM8vr+d114xagH47TyeiClCLEFf6HCGirMJ9/7LIFzOo0O2RmZaDmw/KD/3kYzJcwDT2Z1di59dUshvK9CAUi6xRIGEg1lsIUqzMbNSfCaKdlq2ovMpv+pjcigaTif6ZZIOLiWBGmkb0IPfFok8EgQuyzoZJNx4P0gnyrOlUQC1hleihqE7S5mAunCRd1G1QFHWTvjPL1y8McjAsygcufLsYY0MSMeMFQxhSP9C+O1ZdH1dVfzSYD+JeN3Yrxj2ytEPDCrdXs/qBqHH+ROUz/NHOkhuLDTGFC0HTk3ww6pPlRSq2IY9SAj1YQT/cbtimJXxFIqYWJklQMqdhaMeCLpL5osiipx5MOCneYmk1SY3xQLDEZh1t82Wcjj1CaifTGeWiAslDAb/IgXcIdF+nRZ5NE4pqAeVcQGkjqG4sVsxgMZmzCYR8ktOWUGXfktCcUdbud1FvmTjCbDAVpzuZ9clt05RYo03z66nHAcLTu8gmAinRrknX5EhR49Oue9pMPoqdREzMg0aAzsWe+nvj/ZNPm80tKgAEFoRXWZ+XWzGtWcL2Ok553btlDWyLb44GLq/wPNrxnUZ7o/loK1R6lJbwtxVpRg5TJfrz6FkrevQjq+H3u0sr9Qyn00ARz5sM0Vw4Ak2B7i6MLjgsWLhey5YbqpRuB/vgimgmV6EUOlk9DgWkxxE1KYFTA4msARwZwGcIhD4Jc0Zhy6pVFGK7dMEgZ4NdTUsgUeTscYGdwdsFwzWDOh6VydQ8oK9Tgu6jcj4Swm4LT/etKH6JICNVK2o8vEujJ9Gz5dbDO7c1UJEsm524pc4aLdRC2KlWoNuzhVhKKLCoqv153i8b6sMVsymyhpNkkGn8Ak483NBMwWeLy2SuuT3lhpBuhy9LF8k0F1KqzGzIP7bzL8VYoc9lu5j2x042mXUEJcS9ZDjPizQxjQtxch7dfRq0ootP0YVUJz3f/jkaSLTZzum6txX9M/kN88v2Mks+zjW3hR6bntzuhIqLBdM4SIu22KWwr7ZItBl1H7cft6LH7fbjXtPd7KIIqhVTUYFWEtM+XCRRlk5qtw05HqQ3b4oFT5qvP81uwTakaI0gm7Ji3LCyeNOnLFyt/CwQEhxgqdtZr9nr1hPmTIMjIgXAXqjkqMFinkMZgni3j9XnNzqyGrnEbM6qjFjSQenl0CZ2e3Sru6YbgfhsK0AVDDTcTJiNsoE4Azf9tkgkrdhEDhkQCOSks09mINw2dl059SK5TDMyLj0jBq7gV1T0RMKXh+LDogCFys9RwqZN0KY4SnLRE+sOUiFuhqbTP/6seyQISTnfeV3hxOxjfJFhyxO9mu/BchH0l3Fcj5clHwVvKHe8grifxKcALM0uo4d3ssAyhpVET/Dw77P5uBzR/zQ27uHO1A2j79sxfkWmDXlKyWdA4VLi1gMFvhhSJcG/Bw/crPZYyDxiqrSwGnHhEY7w8EPL8+wgBS1xjYmPOZYfXLx2DOpXe0RKqjTTHeyNn0tkVg1lnMyHV42OOiS2IrqMSc0PyW2glkhtYVO2hjvUyaAUWNJ47MH1rQJSwys0DNVfI/D3aVurTxLpODBPFBRlnPK874n3tSRoBf9Q7xEDjQ3BFMpW9MPFJB9+INQHyYKsinJeoW9WhzIsV07SYfKg8dTnLZYuLEDQAZqzpautsxPQniaCX+Ea6URypeh56kTdHukr9t3uZvBl9GSh+cNTgobV8IZeufDk7hWz6mKdZ1k+F3uo+DWB4wNkp1k0EKlXScEbk52LPTStXoTrtx1luUEUDDfNklGgxXlS9K8vYWYmg+nFaIA0KlNVZUapLEfuBYJa3U6XVlmMk+tgUjTG4Yhz0IwfYvnsVQBhvJcfbp0edf1+98h6t3tY1Tm/esVxPPKGxLFRH+Ddo/saR29/lrrdHtdh0+sYK/lWiEEeaTmDlumfSE8kmGG+AKUN5xgUe7JABfrW4VVM46ya2zZaTfinbsTgvu81oWutkBgL6VMzWeweVe2kY7fryGbZfGj4YEcgRIJQeZD+ZmL3X1arjeTqJCIxCtqeYU/96YXuGJ85c5UzVUfnt2kyGUW84VV9XUNJLcUtULiWHY05VL/2ULIMKmzhJ2M7kNAeJbIlsSvA3mFacmW777uRmMJSrI1sPm7E32/++C9lLIHKrXmJAjOHuKT0gJmuQhm/qUaZMwmxsfXnIMSCZnHz4Z0tvuSX02I4mCcODh8SsacWlw4vMZCAGLcppPZiBrYpDkD3xtogwUXDXwEN8cM73cAyRlTI3lThYhVv0mfS+n3rvhSs6eZ99htd1uGVGe2IRfs4nLd8HEedKI6XHYq0z1oguk+RZRC6EZJgpFfoVEN9NVUnqlhH/SrzdTJ5JhLMuZzd6qy8DSFw7OjULHK4cNtnKqLK3N7vOavFa9BbLYKlTRaJt7Finlgz7o2MhNe1YNwd161QJvM+aahR0QGuhg8Yf4V5ePw2+5DlN5kEBZfOEVuYem/AnQh6pViMYgDNmgW7Ph1U3kKqYwGcilCGrL+4c0p/ttpOwcHjBR7I/XbF0asUB/Lvb7pGySk1mFbR4h7RjeKKW2SEbTBeDMp0SLR0BlXWaKEROlcDOxIEI9IEezlL8La3IWF3OgeHL/feHp/3wQjh/PTt/vnRyev+b3unR3svjg/PNAicBR9XD3R7rJxdInJnFzyhfODNb7fXEAhz+tiFQ61X9FJQu8gPlG97WbyJ7Qaeh8ViCDWEYt4kxIHEZwNXUOk2GMhk8szHGVCEKFwk44b80xKp82IAiUqQ10BlCpMLTUnXoll1oO4MAP2TB0gLJiSIycMPbMZoKZJk1x004MbDpjhown97pIvt8KgIGI4IQYqDsi8Yx1U+0qY/5lqqw4AZxM2g+/3xZHBZNvC/5HCK3/Ii9YFzhaqyBLdIJpPGo2f+aby4pte6N3mBN25nUB4/1OUwa7P8kM6cS0RZNnThBjnstg1uSgUAMjkBePAP1IDBA4IkMn5MFfhCQqabSnENJy4wMCJWMjTjiaVwt40rMQmTZHUbeKCYIDVGePCY+LoyIJOJAIVI6uIFIt/BFAKYnj5gXwhQ4BYSDvgVDUnUdLGn4r+T3mrxDUFD19CsZ3NQDK+8E1Nt71Wb8f7+y+O9X86EXNlVYBBbvXDp44PVpTkGQliS196y97AAHt5plhfvv3kjuPeb08OXR++EcOsZF8gZ7qpyR68PoS+PyNgobMCMusz/CsjRkL50xNir8rYs8nz+NbqlQa09bzU1vmjujl7vrzVxb/bOf62ZNQfq8dGL46PX/3s1ZFGwjhh8sAdHp2tBXdFfmM9plm8Oby9vUvaCITBfUIVhPDBDThmvLdHKKL8pQy2tD2UmjS2/bXcB55v/Nmh52NVg9s40mEfPiEVTHbRJNTTbqbWhzaqhCUpdGxyYMBdz3EV3GvEmOy6sRmsVnCf3hLPm9CShCnLxeKUD+oLi2pMQiaDzgEsdWpapFIVQtgtl4IfXUn1xKcvMBmmBW7+Wk7kYI4RCJmKre5G9ohjcNnGrhm2aJlKWKGpLOdsVQzhebbkqaSV0PhwtplrEkqJv/2pQXkXbRhKe5/0rvwCe0lAZ17+4bfzQAdOkJtOEMM1iv5wXUhusr4Rupxf5pBntyDR5Eo5QZjb1guZW8KikpUESEyowJECNiu4hSm7mjE0srEJYWPdgJtXC61shQ2FusqKuI/UpBv50475OjZ2VRTQrtFcUSPgxpmjJ3HAuSqYIQQJrsFwyc+LT07eINNZfB2B9X3Xlr6POqG6HtpHqVcuwjEkLine 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
+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, " uint top;\n");
fprintf(fh, " uint 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, " uint 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, " %du,\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, " %du,\n", char_infos[i].top);
fprintf(fh, " %du,\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;
}
+178
View File
@@ -0,0 +1,178 @@
/**
* HELLO console support.
*/
module hello.console;
import uefi;
import hello.hello;
import core.stdc.stdarg;
/**
* Format a hexadecimal value to a string.
*
* @param s String buffer.
* @param v Value to format.
* @param ptr If true, always output all 16 digits, and separate the upper and
* lower halves with an underscore.
*/
private size_t format_hex(CHAR16 * s, ulong v, bool ptr)
{
string hex_chars = "0123456789ABCDEF";
bool print = ptr;
size_t si = 0u;
for (size_t i = 0u; i < 16u; i++)
{
if (ptr && (i == 8u))
{
s[si++] = '_';
}
ulong n = (v >> (60u - 4u * i)) & 0xFu;
if (n != 0u)
{
print = true;
}
if (print || (i == 15u))
{
s[si++] = hex_chars[n];
}
}
return si;
}
/**
* Format a decimal value to a string.
*
* @param s String buffer.
* @param v Value to format.
*/
private size_t format_dec(CHAR16 * s, ulong v)
{
string dec_chars = "0123456789";
bool print;
char[20] buf;
size_t buf_i;
while ((buf_i == 0u) || (v != 0u))
{
ulong n = v % 10u;
buf[buf_i++] = dec_chars[n];
v /= 10u;
}
for (size_t si = 0u; si < buf_i; si++)
{
s[si] = buf[buf_i - si - 1u];
}
return buf_i;
}
/**
* Write a string to the console.
*
* @param s Format string.
* @param args Variable arguments structure.
*/
void write(string s, va_list args)
{
__gshared static CHAR16[256] s16;
size_t i = 0u;
bool escape = false;
foreach (char c; s)
{
if (escape)
{
if (c == '%')
{
s16[i++] = '%';
}
else if (c == 'x')
{
ulong v;
va_arg(args, v);
i += format_hex(&s16[i], v, false);
}
else if (c == 'p')
{
ulong v;
va_arg(args, v);
i += format_hex(&s16[i], v, true);
}
else if (c == 'S')
{
const(CHAR16) * s2;
va_arg(args, s2);
for (size_t s2_i = 0u; s2[s2_i] != 0; s2_i++)
{
s16[i++] = s2[s2_i];
}
}
else if (c == 'u')
{
ulong v;
va_arg(args, v);
i += format_dec(&s16[i], v);
}
else
{
s16[i++] = c;
}
escape = false;
}
else if (c == '%')
{
escape = true;
}
else
{
s16[i++] = c;
}
}
s16[i++] = 0u;
st.ConOut.OutputString(st.ConOut, &s16[0]);
}
/**
* Write a string to the console.
*
* @param s Format string.
*/
extern (C) void write(string s, ...)
{
va_list args;
va_start(args, s);
write(s, args);
va_end(args);
}
/**
* Write a string to the console.
*
* @param s Format string.
*/
extern (C) void writeln(string s, ...)
{
va_list args;
va_start(args, s);
write(s, args);
write("\r\n", args);
va_end(args);
}
/**
* Write a message to press any key and wait for a key to be pressed.
*/
void wait_key()
{
writeln("Press any key...");
st.ConIn.Reset(st.ConIn, FALSE);
EFI_INPUT_KEY key;
while (st.ConIn.ReadKeyStroke(st.ConIn, &key) == EFI_NOT_READY)
{
}
}
/**
* Clear the console.
*/
void clear()
{
st.ConOut.ClearScreen(st.ConOut);
}
+344
View File
@@ -0,0 +1,344 @@
/**
* HELLO, the HOS EFI Lightweight LOader.
*/
module hello.hello;
import uefi;
import console = hello.console;
import scratch = hello.scratch;
import hulk.bootinfo;
import hulk.header : HulkHeader = Header;
import hos.page_table;
import hos.cpu;
import hos.memory;
__gshared EFI_SYSTEM_TABLE * st;
private __gshared BootInfo bootinfo;
private __gshared UINTN memory_map_key;
extern extern(C) __gshared ubyte hulk_bin_start;
/**
* Detect if we're running in QEMU.
*/
private bool in_qemu()
{
ulong * firmware_vendor = cast(ulong *) st.FirmwareVendor;
ulong fv1 = firmware_vendor[0];
return fv1 ==
((cast(ulong)'E') |
(cast(ulong)'D' << 16) |
(cast(ulong)'K' << 32) |
(cast(ulong)' ' << 48));
}
/**
* Set a graphics mode.
*/
private bool set_graphics_mode()
{
uint max_horizontal_resolution = in_qemu() ? 1920u : 0xFFFFFFFFu;
UINTN buffer_size = scratch.free();
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
EFI_HANDLE * handles = cast(EFI_HANDLE *)scratch.current();
EFI_STATUS status = st.BootServices.LocateHandle(ByProtocol,
&gop_guid, null, &buffer_size, handles);
if (status != EFI_SUCCESS)
{
console.writeln("LocateHandle: error %x", status);
return false;
}
EFI_HANDLE gop_handle = handles[0];
EFI_HANDLE gop_interface;
status = st.BootServices.HandleProtocol(gop_handle,
&gop_guid, &gop_interface);
if (status != EFI_SUCCESS)
{
console.writeln("HandleProtocol: error %x", status);
return false;
}
if (gop_interface == null)
{
console.writeln("null interface from HandleProtocol");
return false;
}
EFI_GRAPHICS_OUTPUT_PROTOCOL * gop = cast(EFI_GRAPHICS_OUTPUT_PROTOCOL *)gop_interface;
UINTN info_size;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * info;
uint best_width;
uint best_mode_number;
for (uint mode_number = 0u;
(status = gop.QueryMode(gop, mode_number, &info_size, &info)) == EFI_SUCCESS;
mode_number++)
{
if ((info.HorizontalResolution > best_width) &&
(info.HorizontalResolution <= max_horizontal_resolution))
{
best_width = info.HorizontalResolution;
best_mode_number = mode_number;
}
st.BootServices.FreePool(info);
}
if ((status = gop.SetMode(gop, best_mode_number)) != EFI_SUCCESS)
{
console.writeln("SetMode: Error %x\n", status);
return false;
}
bootinfo.fb.buffer = cast(uint *)gop.Mode.FrameBufferBase;
bootinfo.fb.width = gop.Mode.Info.HorizontalResolution;
bootinfo.fb.height = gop.Mode.Info.VerticalResolution;
bootinfo.fb.stride = gop.Mode.Info.PixelsPerScanLine;
bootinfo.fb.format = gop.Mode.Info.PixelFormat;
return true;
}
/**
* Walk the EFI memory map and translate it to the HULK bootinfo format.
*
* @return Maximum physical address to identity map.
*/
private ulong get_memory_map()
{
UINTN memory_map_size = scratch.free();
UINTN descriptor_size;
UINT32 descriptor_version;
ubyte * scratch_base = scratch.current();
UINTN status = st.BootServices.GetMemoryMap(
&memory_map_size,
cast(EFI_MEMORY_DESCRIPTOR *)scratch_base,
&memory_map_key,
&descriptor_size,
&descriptor_version);
if (status != EFI_SUCCESS)
{
console.writeln("GetMemoryMap: Error %x", status);
return 0u;
}
ulong max_physical_address;
size_t n_entries = memory_map_size / descriptor_size;
size_t count;
for (count = 0u; count < n_entries; count++)
{
if (count > bootinfo.memory_map.length)
{
console.writeln("Memory map too large");
for (;;)
{
}
}
EFI_MEMORY_DESCRIPTOR * descriptor = cast(EFI_MEMORY_DESCRIPTOR *)&scratch_base[count * descriptor_size];
ulong end_address = descriptor.PhysicalStart + descriptor.NumberOfPages * 4096u;
if ((end_address > max_physical_address) &&
((descriptor.Type == EfiLoaderCode) ||
(descriptor.Type == EfiLoaderData) ||
(descriptor.Type == EfiBootServicesCode) ||
(descriptor.Type == EfiBootServicesData) ||
(descriptor.Type == EfiRuntimeServicesCode) ||
(descriptor.Type == EfiRuntimeServicesData) ||
(descriptor.Type == EfiConventionalMemory)))
{
max_physical_address = end_address;
}
bootinfo.memory_map[count].base = descriptor.PhysicalStart;
bootinfo.memory_map[count].size = descriptor.NumberOfPages * 4096u;
bootinfo.memory_map[count].type = cast(ubyte)descriptor.Type;
}
bootinfo.memory_map_count = count;
return max_physical_address;
}
/**
* Allocate a new page table.
*/
private PageTableEntry * new_page_table()
{
PageTableEntry * pt = cast(PageTableEntry *)scratch.alloc(1u);
memset64(pt, 0u, 512);
return pt;
}
/**
* Map a virtual address to a physical address using 4KB pages.
*
* @param source_page Source page address.
* @param dest_page Destination page address.
* @param pt_base Page table base address.
*/
private void map4k(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
{
PageTableEntry * pt = pt_base;
PageTableEntry * next_pt;
for (size_t level = 0; level < 4u; level++)
{
size_t pt_index = PageTableEntry.page_table_index(source_page, level);
if (pt[pt_index].present())
{
pt = pt[pt_index].next();
}
else
{
ulong addr;
if (level < 3u)
{
next_pt = new_page_table();
addr = cast(ulong)next_pt;
}
else
{
addr = dest_page;
}
pt[pt_index] = PageTableEntry(addr,
0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u);
pt = next_pt;
}
}
}
/**
* Map a virtual address to a physical address using 2MB pages.
*
* @param source_page Source page address.
* @param dest_page Destination page address.
* @param pt_base Page table base address.
*/
private void map2m(ulong source_page, ulong dest_page, PageTableEntry * pt_base)
{
PageTableEntry * pt = pt_base;
PageTableEntry * next_pt;
for (size_t level = 0; level < 3u; level++)
{
size_t pt_index = PageTableEntry.page_table_index(source_page, level);
if (pt[pt_index].present())
{
pt = pt[pt_index].next();
}
else
{
if (level < 2u)
{
next_pt = new_page_table();
pt[pt_index] = PageTableEntry(cast(ulong)next_pt,
0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u);
}
else
{
pt[pt_index] = PageTableEntry(dest_page,
0u, 0u, 1u, 0u, 0u, 0u, 1u, 1u);
}
pt = next_pt;
}
}
}
/**
* Map HULK virtual addresses to physical kernel location.
*
* @param pt_base Page table base address.
*/
private void map_hulk(PageTableEntry * pt_base)
{
ulong virt = HULK_VIRTUAL_START;
ulong phys = cast(ulong)&hulk_bin_start;
HulkHeader * hulk_header = cast(HulkHeader *)&hulk_bin_start;
size_t end_phys = phys + cast(size_t)hulk_header.total_size;
while (phys < end_phys)
{
map4k(virt, phys, pt_base);
virt += 4096u;
phys += 4096u;
}
}
/**
* Build page tables in preparation to jump to HULK.
*
* @param max_physical_address Maximum physical address to identity map.
*/
private void build_page_tables(ulong max_physical_address)
{
PageTableEntry * pt_base = new_page_table();
/* Map physical RAM. */
for (size_t addr = 0u; addr < max_physical_address; addr += (2u * 1024u * 1024u))
{
map2m(addr, addr, pt_base);
}
/* Map any memory regions that are outside physical RAM. */
for (size_t i = 0u; i < bootinfo.memory_map_count; i++)
{
if (bootinfo.memory_map[i].base > max_physical_address)
{
for (size_t offset = 0u; offset < bootinfo.memory_map[i].size; offset += 4096u)
{
ulong addr = bootinfo.memory_map[i].base + offset;
map4k(addr, addr, pt_base);
}
}
}
/* Map graphics framebuffer. */
ulong framebuffer_size = bootinfo.fb.height * bootinfo.fb.stride * 4u;
for (size_t offset = 0u; offset < framebuffer_size; offset += 4096u)
{
ulong addr = cast(ulong)bootinfo.fb.buffer + offset;
map4k(addr, addr, pt_base);
}
/* Map HULK to its requested starting virtual address. */
map_hulk(pt_base);
/* Switch to the new page table. */
write_cr3(cast(ulong)pt_base);
}
/**
* Jump to HULK entry point.
*/
private void jump_to_hulk()
{
HulkHeader * hulk_header = cast(HulkHeader *)&hulk_bin_start;
void function(BootInfo *) hulk_start = cast(void function(BootInfo *))hulk_header.entry;
hulk_start(&bootinfo);
}
/**
* EFI application entry point.
*
* @param image_handle EFI application handle.
* @param st Pointer to EFI system table.
*/
extern (C) EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * st)
{
.st = st;
console.clear();
console.writeln("HELLO, HOS EFI Lightweight LOader, v0.1.0");
console.writeln("Firmware vendor: '%S', version: 0x%x", st.FirmwareVendor, st.FirmwareVendor);
if (!set_graphics_mode())
{
console.wait_key();
return EFI_SUCCESS;
}
ulong max_physical_address;
for (;;)
{
max_physical_address = get_memory_map();
EFI_STATUS status = st.BootServices.ExitBootServices(image_handle, memory_map_key);
if (status == EFI_INVALID_PARAMETER)
{
continue;
}
if (status == EFI_SUCCESS)
{
break;
}
console.writeln("ExitBootServices: Error %x", status);
console.wait_key();
return EFI_SUCCESS;
}
build_page_tables(max_physical_address);
jump_to_hulk();
return EFI_SUCCESS;
}
+36
View File
@@ -0,0 +1,36 @@
/**
* HELLO scratch buffer.
*/
module hello.scratch;
/* Scratch buffer. */
private align(4096) __gshared ubyte[1024 * 1024] scratch;
/* Number of scratch buffer bytes used. */
private __gshared size_t scratch_used;
/**
* Get the number of free bytes in the scratch buffer.
*/
size_t free()
{
return scratch.sizeof - scratch_used;
}
/**
* Get the current free scratch buffer address.
*/
ubyte * current()
{
return &scratch[scratch_used];
}
/**
* Allocate pages from the scratch buffer.
*/
ubyte * alloc(size_t n = 1)
{
ubyte * address = &scratch[scratch_used];
scratch_used += 4096u * n;
return address;
}
+26
View File
@@ -0,0 +1,26 @@
import ldc.llvmasm;
ulong read_cr0()
{
return __asm!ulong("mov %cr0, %rax", "={rax}");
}
ulong read_cr2()
{
return __asm!ulong("mov %cr2, %rax", "={rax}");
}
ulong read_cr3()
{
return __asm!ulong("mov %cr3, %rax", "={rax}");
}
void write_cr3(ulong v)
{
__asm("mov $0, %cr3", "r", v);
}
ulong read_cr4()
{
return __asm!ulong("mov %cr4, %rax", "={rax}");
}
+57
View File
@@ -0,0 +1,57 @@
import ldc.llvmasm;
void memset(void * dest, ubyte v, size_t n)
{
__asm("rep stosb",
"{al},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset16(void * dest, ushort v, size_t n)
{
__asm("rep stosw",
"{ax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset32(void * dest, uint v, size_t n)
{
__asm("rep stosl",
"{eax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memset64(void * dest, ulong v, size_t n)
{
__asm("rep stosq",
"{rax},{rcx},{rdi},~{rcx},~{rdi},~{memory}",
v, n, dest);
}
void memcpy(void * dest, void * src, size_t n)
{
__asm("rep movsb",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy16(void * dest, void * src, size_t n)
{
__asm("rep movsw",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy32(void * dest, void * src, size_t n)
{
__asm("rep movsl",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
void memcpy64(void * dest, void * src, size_t n)
{
__asm("rep movsq",
"{rcx},{rsi},{rdi},~{rcx},~{rsi},~{rdi},~{memory}",
n, src, dest);
}
+33
View File
@@ -0,0 +1,33 @@
struct PageTableEntry
{
ulong entry;
this(ulong address, ulong no_execute, ulong global,
ulong huge, ulong disable_cache, ulong write_through, ulong user,
ulong writable, ulong present)
{
entry = (present |
(writable << 1) |
(user << 2) |
(write_through << 3) |
(disable_cache << 4) |
(huge << 7) |
(global << 8) |
(no_execute << 63)) | address;
}
bool present()
{
return (entry & 0x1u) != 0u;
}
PageTableEntry * next()
{
return cast(PageTableEntry *)(entry & 0x7FFF_FFFF_FFFF_F000u);
}
static ulong page_table_index(ulong address, size_t level)
{
return ((address >> (39u - 9u * level)) & 0x1FFu);
}
}
+52
View File
@@ -0,0 +1,52 @@
/**
* HULK boot information.
*/
module hulk.bootinfo;
/**
* HULK boot information structure.
*/
struct BootInfo
{
/**
* Framebuffer description structure.
*/
struct Framebuffer
{
/** Framebuffer base address. */
uint * buffer;
/** Horizontal resolution. */
uint width;
/** Vertical resolution. */
uint height;
/** Number of pixels per scan line. */
uint stride;
/** Pixel format. */
uint format;
}
/**
* Memory map entry description structure.
*/
struct MemoryRegion
{
/** Base address of the memory region. */
ulong base;
/** Size in bytes of the memory region. */
size_t size;
/** Type of the memory region. */
ubyte type;
}
/* Framebuffer parameters. */
Framebuffer fb;
/* Memory map. */
MemoryRegion[800] memory_map;
/* Number of memory map entries. */
size_t memory_map_count;
}
/** HULK base virtual address. */
enum ulong HULK_VIRTUAL_START = 0x0000_4000_0000_0000u;
+56
View File
@@ -0,0 +1,56 @@
/**
* HULK Framebuffer support.
*/
module hulk.framebuffer;
import hos.memory;
/**
* Represent a graphical frame buffer.
*
* TODO: Handle other pixel formats. Currently only ARGB is supported.
*/
struct Framebuffer
{
/** Frame buffer base address. */
private uint * m_buffer;
/** Frame buffer width. */
private uint m_width;
/** Frame buffer height. */
private uint m_height;
/** Frame buffer stride. */
private uint m_stride;
/** Number of pixels in the frame buffer (whether visible or not). */
private uint m_buffer_size;
/**
* Initialize a frame buffer.
*
* @param buffer Frame buffer base address.
* @param width Frame buffer width.
* @param height Frame buffer height.
* @param stride Frame buffer stride.
*/
void initialize(uint * buffer, uint width, uint height, uint stride)
{
m_buffer = buffer;
m_width = width;
m_height = height;
m_stride = stride;
m_buffer_size = stride * height;
}
/**
* Clear the frame buffer to the given color.
*
* @param color Color to clear to.
*/
void clear(uint color = 0u)
{
memset32(m_buffer, color, m_buffer_size);
}
}
+23
View File
@@ -0,0 +1,23 @@
/**
* HULK image header.
*/
module hulk.header;
/**
* Header describing the HULK image.
*/
struct Header
{
/**
* Total size of memory to be mapped.
*
* The OS loader must ensure that virtual memory is mapped for this entire
* size.
* This value is really an integer, but is stored as a pointer because it
* is provided by the linker and LDC does not like us to cast it.
*/
void * total_size;
/** Entry point. */
void * entry;
}
+40
View File
@@ -0,0 +1,40 @@
/**
* HULK, the HOS Ultra Light Kernel.
*/
module hulk.hulk;
import hulk.header;
import hulk.bootinfo;
import hulk.framebuffer;
import hos.memory;
import ldc.attributes;
private __gshared Framebuffer fb;
extern extern(C) __gshared ubyte _hulk_total_size;
@(ldc.attributes.section(".hulk_header"))
private __gshared Header hulk_header = {
&_hulk_total_size,
&hulk_start,
};
/**
* HULK entry point.
*
* @param bootinfo Pointer to HULK boot information structure.
*/
extern(C) void hulk_start(ulong rdi, ulong rsi, ulong rdx, BootInfo * bootinfo)
{
fb.initialize(bootinfo.fb.buffer, bootinfo.fb.width, bootinfo.fb.height, bootinfo.fb.stride);
fb.clear(0xFF8800u);
for (size_t y = 100u; y < 120u; y++)
{
memset32(&bootinfo.fb.buffer[y * bootinfo.fb.stride + 20u], 0x001199u, 20u);
}
for (;;)
{
}
}
+32
View File
@@ -0,0 +1,32 @@
SECTIONS
{
. = 0x0000400000000000;
_hulk_mem_start = .;
.rodata BLOCK(4K) : ALIGN(4K)
{
*(.hulk_header)
*(.rodata)
}
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)
}
.data BLOCK(4K) : ALIGN(4K)
{
*(.data)
}
.bss BLOCK(4K) : ALIGN(4K)
{
*(COMMON)
*(.bss)
}
. = ALIGN(4K);
_hulk_mem_end = .;
_hulk_total_size = _hulk_mem_end - _hulk_mem_start;
}
Submodule
+1
Submodule uefi-d added at e70959ce8a.
-100
View File
@@ -1,100 +0,0 @@
#!/bin/bash -x
BINUTILS_VERSION=${BINUTILS_VERSION:-"2.20"}
GCC_VERSION=${GCC_VERSION:-"4.4.2"}
TARGET=${TARGET:-"i586-elf"}
PREFIX=${PREFIX:-"$HOME/local/$TARGET"}
GNUFTP=ftp://ftp.gnu.org/gnu
export PATH=$PREFIX/bin:$PATH
mkdir -p build-binutils build-gcc
if [ ! -f "binutils-$BINUTILS_VERSION.tar.bz2" ]; then
wget "$GNUFTP/binutils/binutils-$BINUTILS_VERSION.tar.bz2"
if [ $? != 0 ]; then
echo "Error downloading binutils"
exit 1
fi
fi
if [ ! -f "gcc-$GCC_VERSION.tar.bz2" ]; then
wget "$GNUFTP/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.bz2"
if [ $? != 0 ]; then
echo "Error downloading gcc"
exit 1
fi
fi
if [ ! -d "binutils-$BINUTILS_VERSION" ]; then
tar xvjf "binutils-$BINUTILS_VERSION.tar.bz2"
if [ $? != 0 ]; then
echo "Error extracting binutils"
exit 1
fi
fi
if [ ! -d "gcc-$GCC_VERSION" ]; then
tar xvjf "gcc-$GCC_VERSION.tar.bz2"
if [ $? != 0 ]; then
echo "Error extracting gcc"
exit 1
fi
fi
# build binutils
dum=`which $TARGET-ar`
if [ $? != 0 ]; then
pushd build-binutils
../binutils-$BINUTILS_VERSION/configure --target=$TARGET --prefix=$PREFIX --disable-nls
if [ $? != 0 ]; then
echo "Error configuring binutils"
exit 1
fi
make all
if [ $? != 0 ]; then
echo "Error building binutils"
exit 1
fi
make install
if [ $? != 0 ]; then
echo "Error installing binutils"
exit 1
fi
popd
fi
# build gcc
dum=`which $TARGET-gcc`
if [ $? != 0 ]; then
pushd build-gcc
../gcc-$GCC_VERSION/configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-languages=c,c++ --without-headers
if [ $? != 0 ]; then
echo "Error configuring gcc"
exit 1
fi
make all-gcc
if [ $? != 0 ]; then
echo "Error building gcc"
exit 1
fi
make install-gcc
if [ $? != 0 ]; then
echo "Error installing gcc"
exit 1
fi
make all-target-libgcc
if [ $? != 0 ]; then
echo "Error building libgcc"
exit 1
fi
make install-target-libgcc
if [ $? != 0 ]; then
echo "Error installing libgcc"
exit 1
fi
popd
fi
exit 0
+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