Compare commits

..

93 Commits

Author SHA1 Message Date
josh
f51426f73f fixed memory barrier bug in IDT initialization -- kernel still crashing when interrupts enabled but i think the memory management initialization is correct
git-svn-id: svn://anubis/hos/trunk@102 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-02-01 05:24:40 +00:00
josh
4b688a3ce0 fixed bug that mapping PAGE_DIR_SELF_REF would incorrectly allocate a new physical page
git-svn-id: svn://anubis/hos/trunk@101 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-02-01 05:04:39 +00:00
josh
563758b1bd added PAGE_DIR_SELF_REF2 to fix bug in page directory self-referencing
git-svn-id: svn://anubis/hos/trunk@100 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-02-01 04:21:29 +00:00
josh
ae5dc7df6f in the middle of clearing page tables allocated during mm_map() and mm_early_map()
git-svn-id: svn://anubis/hos/trunk@99 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-02-01 01:47:19 +00:00
josh
d41ffbbedc added mm_early_vpage_alloc(); kernel still crashing...
git-svn-id: svn://anubis/hos/trunk@98 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-28 04:22:02 +00:00
josh
5ac343a2e8 fixed mm bug, now crashing because IDT isn't mapped via paging
git-svn-id: svn://anubis/hos/trunk@97 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-27 05:25:05 +00:00
josh
1027b8c346 compiling again after updating mm_early_map() and mm_map() for new page allocation scheme
git-svn-id: svn://anubis/hos/trunk@96 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-27 05:06:12 +00:00
josh
08491bace9 still reworking physical page allocator
git-svn-id: svn://anubis/hos/trunk@95 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-26 05:25:46 +00:00
josh
96ba9fabb1 reworking memory management... again
git-svn-id: svn://anubis/hos/trunk@94 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-25 23:03:23 +00:00
josh
24485b8143 fixed line endings on text files
git-svn-id: svn://anubis/hos/trunk@93 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-25 16:04:08 +00:00
josh
ca82cc32ac cleaned up a few page allocation page issues, still crashing
git-svn-id: svn://anubis/hos/trunk@92 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-25 15:59:27 +00:00
josh
4816102139 kernel compiling with new page allocation mechanism but crashing
git-svn-id: svn://anubis/hos/trunk@91 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-25 05:56:40 +00:00
josh
0bc304328d kernel now keeping track of total/free number of physical pages instead of free/used
git-svn-id: svn://anubis/hos/trunk@90 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-22 20:51:34 +00:00
josh
dccecb054b fixed BUILD_BUG_ON() to work in C++
git-svn-id: svn://anubis/hos/trunk@89 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-22 20:48:41 +00:00
josh
0c78e21e14 added STACK_INITIAL_SIZE to control the number of initial stack pages; added BUILD_BUG_ON() macro to catch compile-time errors
git-svn-id: svn://anubis/hos/trunk@88 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-22 19:35:43 +00:00
josh
53407d7b59 rearranged slightly
git-svn-id: svn://anubis/hos/trunk@87 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-22 18:19:20 +00:00
josh
cdea1602d5 added bochs target to Makefile
git-svn-id: svn://anubis/hos/trunk@86 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-22 18:19:17 +00:00
josh
b6bebfd9b4 removed debug print
git-svn-id: svn://anubis/hos/trunk@85 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-14 15:54:16 +00:00
josh
1be6e37961 thanks to bug found by Nick - fixed mmap traversal and size calculation
git-svn-id: svn://anubis/hos/trunk@84 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-14 15:43:49 +00:00
josh
85c5a26631 removed erroneous offset by four when calculating address of mmap structure from bootloader
git-svn-id: svn://anubis/hos/trunk@83 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-14 04:23:26 +00:00
josh
eb2dd3b1ad updated start symbol comment
git-svn-id: svn://anubis/hos/trunk@82 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-07 19:14:34 +00:00
josh
6cd78f195f changed kernel stack top to 0x40000000 (1GB) virtual
git-svn-id: svn://anubis/hos/trunk@81 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-07 15:56:53 +00:00
josh
e4701b8d96 merged in removing-assembly branch to do more in C
git-svn-id: svn://anubis/hos/trunk@80 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-07 15:38:15 +00:00
josh
76ac4f88a4 set virtual offset to 0x0, kernel now runs in qemu / VirtualBox
git-svn-id: svn://anubis/hos/trunk@73 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-06 05:37:04 +00:00
josh
f6e71b9891 minor Makefile improvements
git-svn-id: svn://anubis/hos/trunk@72 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-06 05:04:59 +00:00
josh
cf7287d368 removed multiboot kludge; using ELF kernel with different virtual and load addresses
git-svn-id: svn://anubis/hos/trunk@71 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-06 05:02:32 +00:00
josh
44c6bac2af added util folder with build script for i586-elf target cross-compiler
git-svn-id: svn://anubis/hos/trunk@70 5b3e749e-e535-0410-8002-a9bb6afbdfca
2010-01-02 02:10:20 +00:00
josh
bc7064e92a got interrupts working, added sys/{pic,timer,cpu} modules, ready to work on multitasking
git-svn-id: svn://anubis/hos/trunk@69 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-29 22:30:52 +00:00
josh
2c5a5d7093 moved gdtr_t definition from mm.h to hos_types.h
git-svn-id: svn://anubis/hos/trunk@68 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-24 17:05:11 +00:00
josh
ddd8c9fd71 split mm_map() and mm_page_alloc() into regular and "early" versions (mm_early_map() and mm_early_page_alloc()); removed mm_use_virtual_offset flag
git-svn-id: svn://anubis/hos/trunk@67 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-24 14:51:23 +00:00
josh
d7be0159c9 created /kernel/isr subdir, moved isr.asm from boot to isr module, added interrupts.cc for isr() main function and isr_bootstrap() routine
git-svn-id: svn://anubis/hos/trunk@66 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-24 14:19:31 +00:00
josh
d352afd079 added int_stack_t type in hos_types.h for interrupt stack access
git-svn-id: svn://anubis/hos/trunk@65 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-24 14:02:11 +00:00
josh
1105e6e203 optimized isr.asm a bit
git-svn-id: svn://anubis/hos/trunk@64 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-24 13:50:29 +00:00
josh
339eef5976 build process generating assembly list files for .asm sources; ignoring .lst files in /kernel/boot
git-svn-id: svn://anubis/hos/trunk@63 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-23 22:03:57 +00:00
josh
6a75fdfc10 Added isr.asm with 50 isr_%d labels defined, ready to call isr()
git-svn-id: svn://anubis/hos/trunk@62 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-23 22:02:11 +00:00
josh
2f810cc2ec Reduced grub timeout in menu.lst
git-svn-id: svn://anubis/hos/trunk@61 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-22 21:00:18 +00:00
josh
63289deade updated include/portio.h to not use gcc-specific "statement blocks" but instead have inportX() be static inline functions. Verified that the compiler does in fact inline them
git-svn-id: svn://anubis/hos/trunk@60 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-20 19:21:20 +00:00
josh
e70b1a5213 removed special cases for formatting of lowest signed values due to Corrin' rationale; fixed formatting routines to handle formatting "0" values
git-svn-id: svn://anubis/hos/trunk@59 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-20 19:10:54 +00:00
josh
c21caccb1f printing memory map, used pages, and free pages on boot
git-svn-id: svn://anubis/hos/trunk@58 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-16 00:05:44 +00:00
josh
fd02ee26e1 added kputs_pad(); implemented padding in kprintf(); put some padding tests in k_main()
git-svn-id: svn://anubis/hos/trunk@57 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-15 14:53:58 +00:00
josh
ecd74fe35b starting kio change
git-svn-id: svn://anubis/hos/trunk@56 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-15 02:47:46 +00:00
josh
08af04897c added include/portio.h; using it to update cursor position in kputc()
git-svn-id: svn://anubis/hos/trunk@55 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-14 20:37:10 +00:00
josh
1dd8250048 moved call to stack_bootstrap() into mm_bootstrap() since stack_bootstrap() relies on calling mm_map() and mm_use_virtual_offset was getting unset at the end of mm_bootstrap(); calling k_main() now works!
git-svn-id: svn://anubis/hos/trunk@54 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-14 16:08:06 +00:00
josh
118021a0f6 added Makefile commands to build a binary and an ELF kernel and do disassemble the ELF version
git-svn-id: svn://anubis/hos/trunk@53 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-14 13:50:29 +00:00
josh
bf9c7d74eb added mm/stack module; initializing "permanent" stack for kernel use while paging, crashing when calling k_main() though...
git-svn-id: svn://anubis/hos/trunk@52 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-14 13:31:08 +00:00
josh
cf2d28f5ce added k_main.cc, need to set up a stack before calling k_main()
git-svn-id: svn://anubis/hos/trunk@51 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-14 03:34:16 +00:00
josh
594625b0fa changed lgdt instruction to load from linear address instead of physical address for [mm_gdtr]
git-svn-id: svn://anubis/hos/trunk@50 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-14 00:26:40 +00:00
josh
df719b4281 added code to reset segmentation and enable paging; added fmt_xl2a() in kio; added debug prints in k_bootstrap() since kernel is crashing when trying to enable paging
git-svn-id: svn://anubis/hos/trunk@49 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 22:58:48 +00:00
josh
0fb590a407 changed kio routines to accept const char *; added MAKE_DESCRIPTOR() macro to mm
git-svn-id: svn://anubis/hos/trunk@48 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 22:38:53 +00:00
josh
5b9651299e fixed a few formatting and string bugs, kprintf() working when called during bootstrapping!
git-svn-id: svn://anubis/hos/trunk@47 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 21:54:27 +00:00
josh
a4d497544e added memcpy{,w,d}(), memset{,w,d}(); filled in kputc()
git-svn-id: svn://anubis/hos/trunk@46 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 21:42:18 +00:00
josh
6a69fd06ec filled in a few more formatting routines; linking with libgcc.a to work with 64-bit unsigned integer division/modulus
git-svn-id: svn://anubis/hos/trunk@45 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 20:08:16 +00:00
josh
6a8c7431ff hos_defines.h should include hos_types.h first
git-svn-id: svn://anubis/hos/trunk@44 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 17:15:39 +00:00
josh
be17cde305 added devices and lang directories, added skeleton kio and string modules
git-svn-id: svn://anubis/hos/trunk@43 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-13 15:34:39 +00:00
josh
1aace858da Moved page_directory from an allocated object to a pointer to a run-time allocated page of RAM
git-svn-id: svn://anubis/hos/trunk@42 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-06 21:48:04 +00:00
josh
784978b131 boot.asm comments
git-svn-id: svn://anubis/hos/trunk@41 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-05 16:38:47 +00:00
josh
54b42c0226 added set_cr3() macro and called it to set the PDBR
git-svn-id: svn://anubis/hos/trunk@40 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-04 00:22:18 +00:00
josh
e55f2cdfc4 mapping in kernel virtual address space
git-svn-id: svn://anubis/hos/trunk@39 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-03 20:48:51 +00:00
josh
edb1a6426d minor mm.cc comment changes
git-svn-id: svn://anubis/hos/trunk@38 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-02 19:26:52 +00:00
josh
f07e34c849 updated link script to pack things better
git-svn-id: svn://anubis/hos/trunk@37 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-02 03:43:44 +00:00
josh
e907902ca0 changed mm functions to C++ linkage
git-svn-id: svn://anubis/hos/trunk@36 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-02 03:35:24 +00:00
josh
a8947f8aa3 added mm_map() to map addresses and mm_page_alloc() to allocate physical pages
git-svn-id: svn://anubis/hos/trunk@35 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-02 03:28:25 +00:00
josh
2bddc1d428 filled out more of mm_bootstrap() including initializing the free page linked list
git-svn-id: svn://anubis/hos/trunk@34 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-02 01:09:09 +00:00
josh
bfb4f3bdd0 changed k_bootstrap from C to C++ source file
git-svn-id: svn://anubis/hos/trunk@33 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-01 21:17:24 +00:00
josh
db192f6d36 added CXXFLAGS to disable rtti and exceptions; added C++ support to header files; moved mm.c to mm.cc to use C++ functionality
git-svn-id: svn://anubis/hos/trunk@32 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-01 19:52:18 +00:00
josh
2faa2cc8d6 added mm_bootstrap() skeleton function
git-svn-id: svn://anubis/hos/trunk@31 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-01 17:34:52 +00:00
josh
02c2b25ded added DEPS definition in subdir.mak so dependency files are automatically generated again
git-svn-id: svn://anubis/hos/trunk@30 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-01 12:39:43 +00:00
josh
39ea3f231b added bootstrap_stack so the temporary stack is not in the same place as the page directory
git-svn-id: svn://anubis/hos/trunk@29 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-01 01:53:43 +00:00
josh
981a01ba9b added linker script symbols and address macros to hos_defines.h
git-svn-id: svn://anubis/hos/trunk@28 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-07-01 01:51:02 +00:00
josh
3eea1b4fd3 building in linux with i586-elf cross-compiler as well
git-svn-id: svn://anubis/hos/trunk@27 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-30 23:31:30 +00:00
josh
be8d6015ff Added mm_record_mmap_entry() and calls to it in k_bootstrap().
git-svn-id: svn://anubis/hos/trunk@26 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-30 21:29:44 +00:00
josh
6ea8fe1a27 Added k_bootstrap.c, k_early_panic.[ch]
Calling k_bootstrap() from boot.asm in segmented mode

git-svn-id: svn://anubis/hos/trunk@25 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-30 20:12:39 +00:00
josh
d4f5a0b244 Added multiboot.h
git-svn-id: svn://anubis/hos/trunk@24 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-30 18:17:20 +00:00
josh
1548e7327a added SUBDIRS support to subdir.mak for recursive building
git-svn-id: svn://anubis/hos/trunk@23 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-30 17:54:09 +00:00
josh
90e03d4f95 Added include folder with hos_types.h and hos_defines.h
Added mm build subdir with mm.c
Updated subdir.mak to build $(subdir)_all.o instead of $(subdir).o
Updated main Makefile to pass SUBDIR in to subdirectory builds, add $(HOS_TOPLEVEL)/include to compiler include path, and made the linker write a map file
Updated boot.asm to use the page_directory symbol from the .bss section defined in mm.o as its temporary stack area

git-svn-id: svn://anubis/hos/trunk@22 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-29 19:55:50 +00:00
josh
fb807847bf fixed SUBDIRS_clean definition in Makefile
git-svn-id: svn://anubis/hos/trunk@21 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-29 13:40:33 +00:00
josh
d8f7e731e1 moved boot.asm into kernel/boot, added kernel/boot/Makefile using new subdir.mak
git-svn-id: svn://anubis/hos/trunk@20 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 21:57:50 +00:00
josh
a5ca4348d9 changing Makefile system a bit, again
git-svn-id: svn://anubis/hos/trunk@19 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 19:46:49 +00:00
josh
8fe8d78051 realigned assembly a bit
git-svn-id: svn://anubis/hos/trunk@18 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 19:12:25 +00:00
josh
1b0da72e5a moved PLATFORM and associated definitions from Makefile to kernel/Makefile so the kernel can be built by itself
git-svn-id: svn://anubis/hos/trunk@17 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 18:03:39 +00:00
josh
8493002072 removed jump at start symbol since the bootloader starts after the multiboot header anyway; added diagnostic characters "a", "b"
git-svn-id: svn://anubis/hos/trunk@16 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 15:16:01 +00:00
josh
1ba82ac77f added svn:ignore to a few directories; kernel linked to virtual address 0xE000_0000 and running there in segmented mode
git-svn-id: svn://anubis/hos/trunk@15 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 15:02:46 +00:00
josh
13f467ca47 i guess genisoimage likes to modify iso/boot/grub/stage2_eltorito
git-svn-id: svn://anubis/hos/trunk@14 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 13:17:48 +00:00
josh
81a56c9fcf build system works using i586-elf cross-compiler in cygwin
git-svn-id: svn://anubis/hos/trunk@13 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-25 13:16:22 +00:00
josh
788597b6f4 added linker script
git-svn-id: svn://anubis/hos/trunk@12 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-24 21:53:32 +00:00
josh
09fb19df15 little Makefile change
git-svn-id: svn://anubis/hos/trunk@11 5b3e749e-e535-0410-8002-a9bb6afbdfca
2009-06-24 18:30:57 +00:00
josh
af529606e9 load address changed to 1MB
git-svn-id: svn://anubis/hos/trunk@7 5b3e749e-e535-0410-8002-a9bb6afbdfca
2007-07-25 03:30:16 +00:00
josh
f58228c559 fixed sample boot.asm, changed Makefile target to $(ISO)
git-svn-id: svn://anubis/hos/trunk@6 5b3e749e-e535-0410-8002-a9bb6afbdfca
2007-07-25 03:16:59 +00:00
josh
8f00324b30 bootable with small multiboot kernel
git-svn-id: svn://anubis/hos/trunk@5 5b3e749e-e535-0410-8002-a9bb6afbdfca
2007-07-25 03:00:58 +00:00
josh
bdf4ce8ae8 added clean target
git-svn-id: svn://anubis/hos/trunk@4 5b3e749e-e535-0410-8002-a9bb6afbdfca
2007-07-25 01:18:24 +00:00
josh
e124ac5b1b Makefiles created, added initial iso directory
git-svn-id: svn://anubis/hos/trunk@3 5b3e749e-e535-0410-8002-a9bb6afbdfca
2007-07-25 01:08:19 +00:00
josh
fba9e3ea54 created kernel directory
git-svn-id: svn://anubis/hos/trunk@2 5b3e749e-e535-0410-8002-a9bb6afbdfca
2007-07-23 03:32:19 +00:00
josh
43d1ca0e18 initial creation of trunk directory
git-svn-id: svn://anubis/hos/trunk@1 5b3e749e-e535-0410-8002-a9bb6afbdfca
2007-07-23 03:11:24 +00:00
70 changed files with 2155 additions and 1761 deletions

3
.gitignore vendored
View File

@ -1,3 +0,0 @@
.rscons*
/i686-elf-gcc/
/build/

37
Makefile Normal file
View File

@ -0,0 +1,37 @@
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)

View File

@ -1,166 +0,0 @@
path_prepend "i686-elf-gcc/bin"
configure do
rscons "i686-elf-gcc.rb", "-b", "#{build_dir}/i686-elf-gcc"
check_c_compiler "i686-elf-gcc"
check_program "genext2fs"
check_program "grub-mkstandalone"
check_program "mformat", on_fail: "Install the mtools package"
check_program "xorriso"
check_cfg package: "freetype2", on_fail: "Install libfreetype-dev", use: "freetype"
end
require "tmpdir"
# EFI (w/ GRUB) partition size (MiB)
EFI_PART_SIZE = 8
# HOS partition size (MiB)
HOS_PART_SIZE = 4
# Kernel default font size
KFONT_SIZE = 15
class BiosImage < Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Generating BIOS boot image #{@target}", nil)
Dir.mktmpdir do |tmpdir|
# Create iso directory.
FileUtils.mkdir_p("#{tmpdir}/iso/boot/grub")
File.open("#{tmpdir}/iso/boot/grub/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
set default="0"
set timeout=1
menuentry "HOS" {
insmod multiboot2
multiboot2 /hos.elf
}
EOF
end
@sources.each do |source|
FileUtils.cp(source, "#{tmpdir}/iso")
end
# Build bootable GRUB image.
system(*%W[grub-mkrescue -o #{@target} #{tmpdir}/iso], err: "#{@env.build_root}/grub-mkrescue.log")
end
@cache.register_build(@target, nil, @sources, @env)
end
true
end
end
class EfiImage < Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Generating EFI boot image #{@target}", nil)
Dir.mktmpdir do |tmpdir|
# Build a standalone GRUB.
File.open("#{tmpdir}/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
insmod part_gpt
configfile (hd0,gpt2)/grub.cfg
EOF
end
system(*%W[grub-mkstandalone -O x86_64-efi -o #{tmpdir}/BOOTX64.EFI boot/grub/grub.cfg=#{tmpdir}/grub.cfg])
# Create EFI partition.
system(*%W[dd if=/dev/zero of=#{tmpdir}/efi.part bs=1M count=#{EFI_PART_SIZE}], err: "/dev/null")
system(*%W[mformat -i #{tmpdir}/efi.part ::])
system(*%W[mmd -i #{tmpdir}/efi.part ::/EFI])
system(*%W[mmd -i #{tmpdir}/efi.part ::/EFI/BOOT])
system(*%W[mcopy -i #{tmpdir}/efi.part #{tmpdir}/BOOTX64.EFI ::/EFI/BOOT])
# Create ext2 HOS partition.
FileUtils.mkdir_p("#{tmpdir}/ext2")
@sources.each do |source|
FileUtils.cp(source, "#{tmpdir}/ext2")
end
File.open("#{tmpdir}/ext2/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
set default="0"
set timeout=1
menuentry "HOS" {
insmod part_gpt
insmod multiboot2
set root=(hd0,gpt2)
multiboot2 /hos.elf
}
EOF
end
system(*%W[genext2fs -b #{HOS_PART_SIZE * 1024} -d #{tmpdir}/ext2 #{tmpdir}/ext2.part])
# Create full disk image.
system(*%W[dd if=/dev/zero of=#{@target} bs=1M count=#{EFI_PART_SIZE + HOS_PART_SIZE + 2}], err: "/dev/null")
system(*%W[parted -s #{@target} mklabel gpt])
system(*%W[parted -s #{@target} mkpart efi 1MiB #{EFI_PART_SIZE + 1}MiB])
system(*%W[parted -s #{@target} mkpart hos #{EFI_PART_SIZE + 1}MiB #{EFI_PART_SIZE + HOS_PART_SIZE + 1}MiB])
system(*%W[dd if=#{tmpdir}/efi.part of=#{@target} bs=1M seek=1 conv=notrunc], err: "/dev/null")
system(*%W[dd if=#{tmpdir}/ext2.part of=#{@target} bs=1M seek=#{1 + EFI_PART_SIZE} conv=notrunc], err: "/dev/null")
end
@cache.register_build(@target, nil, @sources, @env)
end
true
end
end
class FontGen < Builder
def run(options)
if @command
finalize_command
else
fontgen = @vars["fontgen"]
@sources += [fontgen]
command = %W[#{fontgen} #{@sources.first} #{KFONT_SIZE} #{@target}]
standard_command("FontGen <target>#{@target}<reset>", command, {})
end
end
end
class Size < Builder
def run(options)
if @command
finalize_command
else
@vars["_SOURCES"] = @sources
@vars["_TARGET"] = @target
command = @env.build_command(%w[${SIZE} ${_SOURCES}], @vars)
standard_command("Size <target>#{@target}<reset>", command, stdout: @target)
end
end
end
# FontGen Environment
fontgen_env = env "fontgen", use: "freetype" do |env|
env["CC"] = "gcc"
env.Program("^/fontgen.bin", glob("fontgen/**/*.c"))
end
# Kernel Environment
kernel_env = env "kernel" do |env|
env.add_builder(EfiImage)
env.add_builder(BiosImage)
env.add_builder(FontGen)
env.add_builder(Size)
env["OBJDUMP"] = "i686-elf-objdump"
env["SIZE"] = "i686-elf-size"
env["CCFLAGS"] += %w[-ffreestanding -Wall -O2]
env["LDFLAGS"] += %w[-ffreestanding -nostdlib -T src/link.ld]
env["LDFLAGS"] += %W[-Wl,-Map,${_TARGET}.map]
env["LIBS"] += %w[gcc]
env.FontGen("^/kfont/kfont.c", "font/Hack-Regular.ttf",
"fontgen" => fontgen_env.expand("^/fontgen.bin"))
env.barrier
env["CPPPATH"] += ["#{env.build_root}/kfont"]
env.Program("^/hos.elf", glob("src/**/*.{S,c}") + ["^/kfont/kfont.c"])
env.depends("#{env.build_root}/hos.elf", "src/link.ld")
env.Disassemble("^/hos.elf.txt", "^/hos.elf")
env.Size("^/hos.elf.size", "^/hos.elf")
env.EfiImage("^/hos-efi.img", %w[^/hos.elf])
env.BiosImage("^/hos.img", %w[^/hos.elf])
end
task "run", desc: "Run HOS in QEMU" do
img = kernel_env.expand("^/hos.img")
sh %W[qemu-system-x86_64 -hda #{img}]
end
task "run-efi", desc: "Run HOS EFI in QEMU" do
img = kernel_env.expand("^/hos-efi.img")
sh %W[qemu-system-x86_64 -bios OVMF.fd -hda #{img}]
end

52
bochsrc Normal file
View File

@ -0,0 +1,52 @@
# 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.

View File

@ -1,224 +0,0 @@
#include <stdlib.h>
#include <stdint.h>
#include <ft2build.h>
#include <stdio.h>
#include FT_FREETYPE_H
#include <string.h>
#include <strings.h>
#include <ctype.h>
#define N_CHARS 128
#define round_up_26_6(val) (((val) + 63) >> 6u)
int max_advance;
int max_top = -9999;
int min_bottom = 9999;
int line_height;
int baseline_offset;
typedef struct {
int width;
int height;
int top;
int left;
uint8_t * bitmap;
} char_info_t;
static char_info_t char_infos[N_CHARS];
static void load_char(FT_Face face, int char_code)
{
if (FT_Load_Char(face, char_code, FT_LOAD_RENDER) != 0)
{
return;
}
int advance = round_up_26_6(face->glyph->advance.x);
if (advance > max_advance)
{
max_advance = advance;
}
if ((face->glyph->bitmap.width == 0) ||
(face->glyph->bitmap.rows == 0))
{
return;
}
char_infos[char_code].width = face->glyph->bitmap.width;
char_infos[char_code].height = face->glyph->bitmap.rows;
char_infos[char_code].top = face->glyph->bitmap_top;
if (char_infos[char_code].top > max_top)
{
max_top = char_infos[char_code].top;
}
int bottom = char_infos[char_code].top - char_infos[char_code].height;
if (bottom < min_bottom)
{
min_bottom = bottom;
}
char_infos[char_code].left = face->glyph->bitmap_left;
char_infos[char_code].bitmap = malloc(char_infos[char_code].width * char_infos[char_code].height);
memcpy(char_infos[char_code].bitmap,
face->glyph->bitmap.buffer,
char_infos[char_code].width * char_infos[char_code].height);
}
static const char * bare_header_name(const char * h_file_name)
{
const char * p = rindex(h_file_name, '/');
if (p == NULL)
{
p = h_file_name;
}
else
{
p++;
}
return p;
}
static char * include_guard_name(const char * h_file_name)
{
const char * p = bare_header_name(h_file_name);
char * guard_name = malloc(strlen(p) + 1);
strcpy(guard_name, p);
char * m = guard_name;
while (*m != '\0')
{
if ('a' <= *m && *m <= 'z')
{
*m = toupper(*m);
}
else if (('0' <= *m && *m <= '9') || ('A' <= *m && *m <= 'Z'))
{
/* no change */
}
else
{
*m = '_';
}
m++;
}
return guard_name;
}
static void generate_bytes(FILE * file, const uint8_t * bytes, int count)
{
for (int i = 0; i < count; i++)
{
if (i % 8 == 0)
{
fprintf(file, " ");
}
fprintf(file, "0x%02xu,", bytes[i]);
if ((i + 1) % 8 == 0)
{
fprintf(file, "\n");
}
else if (i < (count - 1))
{
fprintf(file, " ");
}
}
if (count % 8 != 0)
{
fprintf(file, "\n");
}
}
static void generate(const char * c_file_name)
{
char * h_file_name = malloc(strlen(c_file_name) + 1);
strcpy(h_file_name, c_file_name);
h_file_name[strlen(h_file_name) - 1] = 'h';
char * guard = include_guard_name(h_file_name);
FILE * h_file = fopen(h_file_name, "wb");
fprintf(h_file, "#ifndef %s\n", guard);
fprintf(h_file, "#define %s\n\n", guard);
fprintf(h_file, "#include <stdint.h>\n");
fprintf(h_file, "typedef struct {\n int width;\n int height;\n int top;\n int left;\n const uint8_t * bitmap;\n} fontgen_char_info_t;\n");
fprintf(h_file, "typedef struct {\n int line_height;\n int advance;\n int baseline_offset;\n const fontgen_char_info_t ** char_infos;\n} fontgen_font_t;\n");
fprintf(h_file, "extern const fontgen_font_t kfont;\n");
fprintf(h_file, "#endif\n");
fclose(h_file);
FILE * c_file = fopen(c_file_name, "wb");
fprintf(c_file, "#include \"%s\"\n", bare_header_name(h_file_name));
fprintf(c_file, "#include <stddef.h>\n");
for (int i = 0; i < N_CHARS; i++)
{
if (char_infos[i].width > 0)
{
fprintf(c_file, "static const uint8_t char_bitmap_%d[] = {\n", i);
generate_bytes(c_file, char_infos[i].bitmap, char_infos[i].width * char_infos[i].height);
fprintf(c_file, "};\n");
}
fprintf(c_file, "static const fontgen_char_info_t char_%d = {\n", i);
fprintf(c_file, " %d,\n", char_infos[i].width);
fprintf(c_file, " %d,\n", char_infos[i].height);
fprintf(c_file, " %d,\n", char_infos[i].top);
fprintf(c_file, " %d,\n", char_infos[i].left);
if (char_infos[i].width > 0)
{
fprintf(c_file, " char_bitmap_%d,\n", i);
}
else
{
fprintf(c_file, " NULL,\n");
}
fprintf(c_file, "};\n\n");
}
fprintf(c_file, "const fontgen_char_info_t * char_infos[] = {\n");
for (int i = 0; i < N_CHARS; i++)
{
fprintf(c_file, " &char_%d,\n", i);
}
fprintf(c_file, "};\n");
fprintf(c_file, "const fontgen_font_t kfont = {\n");
fprintf(c_file, " %d,\n", line_height);
fprintf(c_file, " %d,\n", max_advance);
fprintf(c_file, " %d,\n", baseline_offset);
fprintf(c_file, " char_infos,\n");
fprintf(c_file, "};\n");
fclose(c_file);
}
int main(int argc, char * argv[])
{
/* Expect: font file, size, out file */
if (argc != 4)
{
fprintf(stderr, "Incorrect arguments\n");
return 1;
}
const char * font_file = argv[1];
int size = atoi(argv[2]);
const char * out_file = argv[3];
FT_Library ft_library;
if (FT_Init_FreeType(&ft_library) != 0)
{
fprintf(stderr, "Could not initialize freetype\n");
return 2;
}
FT_Face face;
if (FT_New_Face(ft_library, font_file, 0, &face) != 0)
{
fprintf(stderr, "Could not open %s\n", font_file);
return 3;
}
FT_Set_Pixel_Sizes(face, 0, size);
for (int i = 0; i < N_CHARS; i++)
{
load_char(face, i);
}
line_height = round_up_26_6(face->size->metrics.height);
baseline_offset = (line_height - (max_top - min_bottom)) / 2 - min_bottom;
generate(out_file);
return 0;
}

View File

@ -1,75 +0,0 @@
binutils_version = "2.35"
binutils_checksum = "1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85"
gcc_version = "10.2.0"
gcc_checksum = "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
install_path = File.expand_path("i686-elf-gcc")
target = "i686-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,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

6
iso/boot/grub/menu.lst Normal file
View File

@ -0,0 +1,6 @@
timeout 2
default 0
title HOS
kernel /boot/hos.gz

Binary file not shown.

45
kernel/Makefile Normal file
View File

@ -0,0 +1,45 @@
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
kernel/boot/Makefile Normal file
View File

@ -0,0 +1,2 @@
include $(HOS_TOPLEVEL)/subdir.mak

23
kernel/boot/boot.asm Normal file
View File

@ -0,0 +1,23 @@
; 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

View File

@ -0,0 +1,85 @@
#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
kernel/boot/k_bootstrap.h Normal file
View File

@ -0,0 +1,17 @@
#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

View File

@ -0,0 +1,18 @@
#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 (;;)
;
}

View File

@ -0,0 +1,15 @@
#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
kernel/boot/k_main.cc Normal file
View File

@ -0,0 +1,28 @@
#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
kernel/boot/k_main.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef K_MAIN_H
#define K_MAIN_H
extern "C" {
void k_main();
}
#endif

View File

@ -0,0 +1,47 @@
#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

View File

@ -0,0 +1,55 @@
#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
kernel/include/multiboot.h Normal file
View File

@ -0,0 +1,154 @@
#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
kernel/include/portio.h Normal file
View File

@ -0,0 +1,37 @@
#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
kernel/isr/Makefile Normal file
View File

@ -0,0 +1,2 @@
include $(HOS_TOPLEVEL)/subdir.mak

110
kernel/isr/interrupts.cc Normal file
View File

@ -0,0 +1,110 @@
#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
kernel/isr/interrupts.h Normal file
View File

@ -0,0 +1,79 @@
#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
kernel/isr/isr.asm Normal file
View File

@ -0,0 +1,56 @@
; 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
kernel/lang/Makefile Normal file
View File

@ -0,0 +1,2 @@
include $(HOS_TOPLEVEL)/subdir.mak

317
kernel/lang/kio.cc Normal file
View File

@ -0,0 +1,317 @@
#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
kernel/lang/kio.h Normal file
View File

@ -0,0 +1,27 @@
#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
kernel/lang/string.cc Normal file
View File

@ -0,0 +1,73 @@
#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
kernel/lang/string.h Normal file
View File

@ -0,0 +1,27 @@
#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
kernel/link.ld Normal file
View File

@ -0,0 +1,34 @@
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
kernel/mm/Makefile Normal file
View File

@ -0,0 +1,2 @@
include $(HOS_TOPLEVEL)/subdir.mak

405
kernel/mm/mm.cc Normal file
View File

@ -0,0 +1,405 @@
#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
kernel/mm/mm.h Normal file
View File

@ -0,0 +1,65 @@
#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
kernel/mm/stack.cc Normal file
View File

@ -0,0 +1,19 @@
#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
kernel/mm/stack.h Normal file
View File

@ -0,0 +1,13 @@
#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
kernel/subdir.mak Normal file
View File

@ -0,0 +1,54 @@
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
kernel/sys/Makefile Normal file
View File

@ -0,0 +1,2 @@
include $(HOS_TOPLEVEL)/subdir.mak

40
kernel/sys/cpu.h Normal file
View File

@ -0,0 +1,40 @@
#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
kernel/sys/pic.cc Normal file
View File

@ -0,0 +1,29 @@
#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
kernel/sys/pic.h Normal file
View File

@ -0,0 +1,46 @@
#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
kernel/sys/timer.cc Normal file
View File

@ -0,0 +1,12 @@
#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
kernel/sys/timer.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef TIMER_H
#define TIMER_H
#include "hos_types.h"
void timer_init(u32_t freq);
#endif

View File

@ -1,89 +0,0 @@
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

46
rscons

File diff suppressed because one or more lines are too long

View File

@ -1,18 +0,0 @@
.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
src/fb.c
View File

@ -1,116 +0,0 @@
#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;
}
}

View File

@ -1,16 +0,0 @@
#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

View File

@ -1,11 +0,0 @@
#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);
}

View File

@ -1,8 +0,0 @@
#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

View File

@ -1,16 +0,0 @@
.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

View File

@ -1,20 +0,0 @@
#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();
}

View File

@ -1,34 +0,0 @@
#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

View File

@ -1,25 +0,0 @@
#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());
}

View File

@ -1,281 +0,0 @@
#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);
}

View File

@ -1,10 +0,0 @@
#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

View File

@ -1,103 +0,0 @@
#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);
}

View File

@ -1,7 +0,0 @@
#ifndef KLOG_H
#define KLOG_H
void klog_init(void);
void klog_printf(const char * fmt, ...);
#endif

View File

@ -1,41 +0,0 @@
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 = .;
}

View File

@ -1,100 +0,0 @@
#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);
}

View File

@ -1,10 +0,0 @@
#ifndef MBINFO_H
#define MBINFO_H
#include <stdint.h>
#include <stdbool.h>
bool mbinfo_init(uint32_t mbinfo_addr);
void mbinfo_load(void);
#endif

View File

@ -1,49 +0,0 @@
#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

View File

@ -1,91 +0,0 @@
#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;
}

View File

@ -1,25 +0,0 @@
#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

View File

@ -1,127 +0,0 @@
#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

View File

@ -1,12 +0,0 @@
#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(),
};

View File

@ -1,12 +0,0 @@
#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

View File

@ -1,26 +0,0 @@
#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

100
util/build-i586-elf-gcc.sh Executable file
View File

@ -0,0 +1,100 @@
#!/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