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
147 changed files with 2111 additions and 12627 deletions

View File

@ -1,43 +0,0 @@
# configuration file generated by Bochs
config_interface: textconfig
display_library: x
megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latest
boot: floppy
floppya: 1_44="hos.flp", status=inserted
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=0
ata2: enabled=0
ata3: enabled=0
parport1: enabled=1, file="parallel.out"
com1: enabled=1, dev=""
usb1: enabled=1, ioaddr=0xff80, irq=10
# no sb16
floppy_bootsig_check: disabled=0
vga_update_interval: 30000
keyboard_serial_delay: 20000
keyboard_paste_delay: 100000
floppy_command_delay: 50000
ips: 500000
text_snapshot_check: 0
mouse: enabled=0
private_colormap: enabled=0
i440fxsupport: enabled=1
clock: sync=realtime, time0=local
# no ne2k
#newharddrivesupport: enabled=1
# no loader
log: -
logprefix: %t%e%d
debugger_log: -
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
pass: action=fatal
keyboard_mapping: enabled=0, map=
keyboard_type: mf
user_shortcut: keys=ctrlaltdel
# no cmosimage

113
Makefile
View File

@ -1,88 +1,37 @@
# Makefile for HOS
# Josh Holtrop
# Created: 07/09/04
FLOPPY=/dev/fd0
FLOPPY_IMAGE=hos.flp
FLOPPY_MOUNT=./mnt_flp
GRUB_IMAGE=grub.flp
INITRD=hos_initrd
INITRD_DIR=initrd
INITRD_MOUNT=./mnt_initrd
INITRD_SIZE=100 #initrd size in kb
MOUNT=sudo mount
UMOUNT=sudo umount
KERNEL_FILE := hos.gz
MKISOFS := genisoimage
ISO := hos.iso
QEMU := qemu-system-x86_64
BOCHS := bochs
# Do not print "Entering directory ..."
MAKEFLAGS += --no-print-directory
# default target: build the kernel and ISO image
all: kernel iso
.PHONY: all clean initrd apps grub_image install install_img depend copy_image bochs bochsq
# build the kernel
.PHONY: kernel
kernel:
$(MAKE) -C $@
all:
make -C kernel
make -C rmmod
# 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
-make -C rmmod clean
-rm -f *~ *.out hos.flp \#* hos_initrd hos_initrd.gz
apps:
make -C apps
grub_image:
dd if=/dev/zero of=$(GRUB_IMAGE) bs=1024 seek=1440 count=0
-mkdir $(FLOPPY_MOUNT)
mke2fs -F $(GRUB_IMAGE)
$(MOUNT) -t ext2 -o loop $(GRUB_IMAGE) $(FLOPPY_MOUNT)
-mkdir -p $(FLOPPY_MOUNT)/boot/grub
-cp /boot/grub/stage1 /boot/grub/stage2 /boot/grub/e2fs_stage1_5 $(FLOPPY_MOUNT)/boot/grub
$(UMOUNT) $(FLOPPY_MOUNT)
-rmdir $(FLOPPY_MOUNT)
echo "(fd0) $(GRUB_IMAGE)" > grub_image_device.map.tmp
echo "root (fd0)" > grub_commands.tmp
echo "setup (fd0)" >> grub_commands.tmp
echo "quit" >> grub_commands.tmp
grub --device-map grub_image_device.map.tmp < grub_commands.tmp
rm grub_commands.tmp
rm grub_image_device.map.tmp
copy_image:
cp $(GRUB_IMAGE) $(FLOPPY_IMAGE)
install: FDEV=$(FLOPPY)
install_img: FDEV=$(FLOPPY_IMAGE)
install_img: MOUNT_FLAGS=-o loop
install_img: copy_image
install install_img:
-mkdir $(FLOPPY_MOUNT)
$(MOUNT) -t ext2 $(MOUNT_FLAGS) $(FDEV) $(FLOPPY_MOUNT)
-cp kernel/kernel.bin $(FLOPPY_MOUNT)
-cp rmmod/rmmod.bin $(FLOPPY_MOUNT)
-cp menu.lst $(FLOPPY_MOUNT)/boot/grub
-cp $(INITRD).gz $(FLOPPY_MOUNT)/$(INITRD).gz
$(UMOUNT) $(FLOPPY_MOUNT)
-rmdir $(FLOPPY_MOUNT)
initrd:
dd if=/dev/zero of=$(INITRD) bs=1024 count=$(INITRD_SIZE)
mke2fs -Fv -m0 -r0 -i1024 $(INITRD)
-mkdir $(INITRD_MOUNT)
$(MOUNT) -t ext2 -o loop $(INITRD) $(INITRD_MOUNT)
cp -Pr $(INITRD_DIR)/* $(INITRD_MOUNT)
$(UMOUNT) $(INITRD_MOUNT)
rm -rf $(INITRD_MOUNT)
gzip -c $(INITRD) > $(INITRD).gz
depend:
make -C kernel depend
bochs:
bochs
bochsq:
echo 'c' | bochs -q
wordcount:
find . -regex '\(.*\.[ch]\)\|\(.*\.asm\)\|\(.*\.inc\)\|\(.*\.cpp\)' | xargs cat | wc
$(MAKE) -C kernel clean
-rm -f $(ISO) iso/boot/$(KERNEL_FILE)

View File

@ -1,5 +0,0 @@
all:
make -C hash
nasm -f bin -l test1.lst test1.asm -o test1.app
nasm -f bin test2.asm -o test2.app

View File

@ -1,3 +0,0 @@
all:
nasm -f bin hash.asm -o hash

View File

@ -1 +0,0 @@
<EFBFBD>0<EFBFBD>

View File

@ -1,6 +0,0 @@
[bits 32]
begin:
int 0x30
ret

Binary file not shown.

View File

@ -1,20 +0,0 @@
; test app 1
[bits 32]
org 0x0
;header:
; dd 0x4D534F48 ; magic identifier "HOSM"
; dd 2 ; test app
; dd start ; start address
; dd 0 ; reserved
start:
mov ebx, astring
mov eax, 2
int 0x30
jmp start
ret
astring:
db "Hello there from test1!", 10, 0

View File

@ -1,22 +0,0 @@
1 ; test app 1
2
3 [bits 32]
4 org 0x0
5
6 ;header:
7 ; dd 0x4D534F48 ; magic identifier "HOSM"
8 ; dd 2 ; test app
9 ; dd start ; start address
10 ; dd 0 ; reserved
11
12 start:
13 00000000 BB[0F000000] mov ebx, astring
14 00000005 B802000000 mov eax, 2
15 0000000A CD30 int 0x30
16 0000000C EBF2 jmp start
17 0000000E C3 ret
18
19 astring:
20 0000000F 48656C6C6F20746865- db "Hello there from test1!", 10, 0
21 00000018 72652066726F6D2074-
22 00000021 65737431210A00

Binary file not shown.

View File

@ -1,17 +0,0 @@
; test app 1
[bits 32]
org 0x0
;header:
; dd 0x4D534F48 ; magic identifier "HOSM"
; dd 2 ; test app
; dd start ; start address
; dd 0 ; reserved
start:
mov eax, 1
mov ebx, 'i'
int 0x30
jmp start
ret

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

View File

@ -1,2 +0,0 @@
To build the HOS kernel, just run 'make'
To build a HOS floppy image for bochs, run 'make initrd' and 'make install_img' as root (root permissions needed to mount floppy image)

BIN
e2fs

Binary file not shown.

BIN
grub.flp

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
test_file

View File

@ -1,46 +0,0 @@
# Change this file to contain the machines that you want to use
# to run MPI jobs on. The format is one host name per line, with either
# hostname
# or
# hostname:n
# where n is the number of processors in an SMP. The hostname should
# be the same as the result from the command "hostname"
#
#non-functional machines
#stallman.cs.calvin.edu
#zuse.cs.calvin.edu
#knuth.cs.calvin.edu
stroustrup.cs.calvin.edu
kernighan.cs.calvin.edu
ritchie.cs.calvin.edu
aiken.cs.calvin.edu
backus-naur.cs.calvin.edu
codd.cs.calvin.edu
eckert-mauchly.cs.calvin.edu
atanasoff.cs.calvin.edu
thompson.cs.calvin.edu
augusta.cs.calvin.edu
babbage.cs.calvin.edu
turing.cs.calvin.edu
hoare.cs.calvin.edu
wall.cs.calvin.edu
englebart.cs.calvin.edu
vonneuman.cs.calvin.edu
hopper.cs.calvin.edu
dijkstra.cs.calvin.edu
chomsky.cs.calvin.edu
leibniz.cs.calvin.edu
schreyer.cs.calvin.edu
wirth.cs.calvin.edu
cray.cs.calvin.edu
hillis.cs.calvin.edu
taylor.cs.calvin.edu
goldberg.cs.calvin.edu
kay.cs.calvin.edu
boole.cs.calvin.edu
church.cs.calvin.edu
sutherland.cs.calvin.edu
noyce-kilby.cs.calvin.edu
hollerith.cs.calvin.edu

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.

View File

@ -1,128 +1,45 @@
# Makefile for HOS
# Josh Holtrop
# Created: 07/08/04
# Modified: 06/13/05
# Assembler Information:
NASM=nasm
NASM_FLAGS=-f aout
CROSS_COMPILE := i586-elf-
# C/C++ Information:
CPPFLAGS=-fleading-underscore -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -I. -Wall
# -S -masm=intel
CC=gcc
CXX=g++
CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_
export LD := $(CROSS_COMPILE)ld
export CC := $(CROSS_COMPILE)gcc
export CXX := $(CROSS_COMPILE)g++
export OBJDUMP := $(CROSS_COMPILE)objdump
export NASM := nasm
# Linker Information:
LD=ld
LDFLAGS=-nodefaultlibs -nostdlib --no-demangle -T link.ld
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`
# Files
OBJS=boot.o lang/lang_a.o \
kernel.o mm/mm.o mm/vmm.o lang/conv.o display/kout.o \
display/display.o sys/pic.o char/keyboard.o lang/lang.o \
sys/pci_classes.o syscall.o \
proc/proc.o proc/hash.o \
lang/string.o lang/new.o char/misc_char.o char/vconsole.o \
devices.o block/ramdisk.o fs/vfs.o fs/FileSystem.o fs/VFSMount.o \
fs/ext2/ext2.o fs/sysfs/sysfs.o fs/sysfs/sysfs_entry.o \
sys/pci.o fs/OpenFile.o fs/OpenDirectory.o \
fs/ext2/Ext2OpenDirectory.o fs/ext2/Ext2OpenFile.o \
fs/ext2/Ext2BlockCache.o
CSRC=kernel.c mm/mm.c mm/vmm.c lang/conv.c display/kout.c \
display/display.c sys/pic.c char/keyboard.c lang/lang.c \
sys/pci_classes.c syscall.c
CXXSRC=lang/string.cpp lang/new.cpp char/misc_char.cpp char/vconsole.cpp \
block/ramdisk.cpp devices.cpp fs/vfs.cpp fs/FileSystem.o fs/VFSMount.o\
fs/ext2/ext2.cpp fs/sysfs/sysfs.cpp fs/sysfs/sysfs_entry.cpp \
sys/pci.cpp proc/proc.cpp proc/hash.cpp fs/OpenFile.cpp \
fs/OpenDirectory.cpp fs/ext2/Ext2OpenDirectory.cpp \
fs/ext2/Ext2OpenFile.cpp fs/ext2/Ext2BlockCache.cpp
SUBDIRS := boot mm lang isr sys
SUBDIRS_clean := $(SUBDIRS:%=%.clean)
.PHONY: all depend clean html
.PHONY: all
all: $(KERNEL).gz
all: $(OBJS)
$(LD) $(LDFLAGS) -Map kernel.map $(OBJS) -o kernel.bin
@echo ' Kernel built: ' `ls -sk kernel.bin | cut -d' ' -f1`kb
$(KERNEL).gz: $(KERNEL)
gzip -c $< > $@
depend:
makedepend -- $(CPPFLAGS) -- $(CSRC) $(CXXSRC)
$(KERNEL): $(KERNEL).o
$(LD) $(LDFLAGS) -o $@ $<
$(OBJDUMP) --disassemble --source $@ > $@.dump
# strip $@
boot.o: boot.asm idt.inc gdt.inc
$(NASM) $(NASM_FLAGS) -l boot.lst boot.asm -o boot.o
$(KERNEL).o: $(SUBDIRS)
$(LD) -r -o $@ $(foreach subdir,$(SUBDIRS),$(subdir)/$(subdir)_all.o) $(LDLIBS)
lang/lang_a.o: lang/lang.asm
$(NASM) $(NASM_FLAGS) -l lang.lst lang/lang.asm -o lang/lang_a.o
.PHONY: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@ SUBDIR=$@
clean:
-rm -f $(OBJS) *.bin *.map *.lst *.out
-find . -name '*~' | xargs rm -f
.PHONY: clean
clean: $(SUBDIRS_clean)
-rm -f *~ $(KERNEL) $(KERNEL).{gz,o,elf,dump,map}
html:
-rm -rf html
-mkdir html
source-highlight --output-dir=html -f xhtml -n $(CSRC) $(CXXSRC)
# The following is used by 'make' to automatically
# generate dependency information
# DO NOT DELETE
kernel.o: kernel.h hos_defines.h multiboot.h module.h lang/lang.h functions.h
kernel.o: sys/io.h mm/mm.h mm/vmm.h lang/conv.h devices.h display/display.h
kernel.o: display/kout.h sys/pic.h char/keyboard.h block/ramdisk.h fs/vfs.h
kernel.o: fs/ext2/ext2.h sys/pci.h proc/proc.h
mm/mm.o: kernel.h hos_defines.h multiboot.h mm/mm.h
mm/vmm.o: hos_defines.h kernel.h multiboot.h mm/vmm.h lang/lang.h mm/mm.h
lang/conv.o: lang/conv.h hos_defines.h
display/kout.o: hos_defines.h display/kout.h lang/conv.h devices.h
display/kout.o: char/misc_char.h char/misc_char.h functions.h sys/io.h
display/display.o: devices.h hos_defines.h char/vconsole.h display/display.h
display/display.o: lang/lang.h kernel.h multiboot.h char/keyboard.h
display/display.o: display/kout.h
sys/pic.o: hos_defines.h sys/pic.h sys/io.h
char/keyboard.o: hos_defines.h char/keyboard.h sys/io.h functions.h
char/keyboard.o: lang/conv.h display/kout.h display/display.h devices.h
lang/lang.o: lang/lang.h hos_defines.h
sys/pci_classes.o: hos_defines.h sys/pci.h
lang/string.o: lang/string.h lang/lang.h hos_defines.h
lang/new.o: hos_defines.h mm/vmm.h multiboot.h
char/misc_char.o: hos_defines.h devices.h char/misc_char.h sys/io.h
char/vconsole.o: hos_defines.h mm/vmm.h multiboot.h lang/lang.h
char/vconsole.o: display/display.h devices.h functions.h sys/io.h
char/vconsole.o: char/vconsole.h
block/ramdisk.o: functions.h hos_defines.h sys/io.h mm/vmm.h multiboot.h
block/ramdisk.o: lang/lang.h block/ramdisk.h devices.h
devices.o: hos_defines.h devices.h char/misc_char.h char/misc_char.h
devices.o: char/vconsole.h block/ramdisk.h
fs/vfs.o: hos_defines.h display/kout.h functions.h sys/io.h lang/lang.h
fs/vfs.o: fs/vfs.h devices.h fs/FileSystem.h fs/OpenDirectory.h lang/string.h
fs/vfs.o: fs/OpenFile.h fs/VFSMount.h fs/FileSystem.h fs/ext2/ext2.h fs/vfs.h
fs/vfs.o: lang/vector.h
fs/ext2/ext2.o: display/kout.h hos_defines.h mm/vmm.h multiboot.h lang/lang.h
fs/ext2/ext2.o: fs/ext2/ext2.h fs/vfs.h devices.h fs/ext2/Ext2OpenDirectory.h
fs/ext2/ext2.o: fs/ext2/Ext2BlockCache.h fs/ext2/Ext2OpenFile.h fs/OpenFile.h
fs/sysfs/sysfs.o: display/kout.h hos_defines.h fs/vfs.h devices.h
fs/sysfs/sysfs.o: fs/sysfs/sysfs.h fs/sysfs/sysfs_entry.h lang/vector.h
fs/sysfs/sysfs.o: lang/string.h
fs/sysfs/sysfs_entry.o: fs/sysfs/sysfs_entry.h lang/vector.h hos_defines.h
fs/sysfs/sysfs_entry.o: lang/string.h
sys/pci.o: hos_defines.h display/kout.h sys/io.h sys/pci.h lang/vector.h
proc/proc.o: hos_defines.h mm/mm.h kernel.h multiboot.h mm/vmm.h lang/lang.h
proc/proc.o: functions.h sys/io.h display/kout.h proc/proc.h proc/hash.h
proc/proc.o: lang/vector.h
proc/hash.o: hos_defines.h proc/hash.h lang/vector.h display/kout.h mm/vmm.h
proc/hash.o: multiboot.h
fs/OpenFile.o: fs/OpenFile.h hos_defines.h
fs/OpenDirectory.o: fs/vfs.h hos_defines.h devices.h fs/OpenDirectory.h
fs/OpenDirectory.o: lang/string.h
fs/ext2/Ext2OpenDirectory.o: lang/lang.h hos_defines.h fs/vfs.h devices.h
fs/ext2/Ext2OpenDirectory.o: fs/ext2/Ext2OpenDirectory.h fs/ext2/ext2.h
fs/ext2/Ext2OpenDirectory.o: fs/ext2/Ext2BlockCache.h fs/ext2/Ext2OpenFile.h
fs/ext2/Ext2OpenDirectory.o: fs/OpenFile.h
fs/ext2/Ext2OpenFile.o: fs/ext2/Ext2OpenFile.h fs/ext2/ext2.h fs/vfs.h
fs/ext2/Ext2OpenFile.o: hos_defines.h devices.h fs/OpenFile.h
fs/ext2/Ext2OpenFile.o: fs/ext2/Ext2BlockCache.h lang/lang.h functions.h
fs/ext2/Ext2OpenFile.o: sys/io.h
fs/ext2/Ext2BlockCache.o: fs/vfs.h hos_defines.h devices.h
fs/ext2/Ext2BlockCache.o: fs/ext2/Ext2BlockCache.h fs/ext2/ext2.h
%.clean:
$(MAKE) -C $* clean clean=1

View File

@ -1,123 +0,0 @@
# Makefile for HOS
# Josh Holtrop
# Created: 07/08/04
# Modified: 06/13/05
# Assembler Information:
NASM=nasm
NASM_FLAGS=-f aout
# C/C++ Information:
CPPFLAGS=-fleading-underscore -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -I. -Wall
# -S -masm=intel
CC=gcc
CXX=g++
CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_
# Linker Information:
LD=ld
LDFLAGS=-nodefaultlibs -nostdlib --no-demangle -T link.ld
# Files
OBJS=boot.o lang/lang_a.o \
kernel.o mm/mm.o mm/vmm.o lang/conv.o display/kout.o \
display/display.o sys/pic.o char/keyboard.o lang/lang.o \
sys/pci_classes.o syscall.o \
proc/proc.o proc/hash.o \
lang/string.o lang/new.o char/misc_char.o char/vconsole.o \
devices.o block/ramdisk.o fs/vfs.o fs/FileSystem.o fs/VFSMount.o \
fs/ext2/ext2.o fs/sysfs/sysfs.o fs/sysfs/sysfs_entry.o \
sys/pci.o fs/OpenFile.o fs/OpenDirectory.o \
fs/ext2/Ext2OpenDirectory.o fs/ext2/Ext2OpenFile.o \
fs/ext2/Ext2BlockCache.o
CSRC=kernel.c mm/mm.c mm/vmm.c lang/conv.c display/kout.c \
display/display.c sys/pic.c char/keyboard.c lang/lang.c \
sys/pci_classes.c syscall.c
CXXSRC=lang/string.cpp lang/new.cpp char/misc_char.cpp char/vconsole.cpp \
block/ramdisk.cpp devices.cpp fs/vfs.cpp fs/FileSystem.o fs/VFSMount.o\
fs/ext2/ext2.cpp fs/sysfs/sysfs.cpp fs/sysfs/sysfs_entry.cpp \
sys/pci.cpp proc/proc.cpp proc/hash.cpp fs/OpenFile.cpp \
fs/OpenDirectory.cpp fs/ext2/Ext2OpenDirectory.cpp \
fs/ext2/Ext2OpenFile.cpp fs/ext2/Ext2BlockCache.cpp
.PHONY: all depend clean html
all: $(OBJS)
$(LD) $(LDFLAGS) -Map kernel.map $(OBJS) -o kernel.bin
@echo ' Kernel built: ' `ls -sk kernel.bin | cut -d' ' -f1`kb
depend:
makedepend -- $(CPPFLAGS) -- $(CSRC) $(CXXSRC)
boot.o: boot.asm idt.inc gdt.inc
$(NASM) $(NASM_FLAGS) -l boot.lst boot.asm -o boot.o
lang/lang_a.o: lang/lang.asm
$(NASM) $(NASM_FLAGS) -l lang.lst lang/lang.asm -o lang/lang_a.o
clean:
-rm -f $(OBJS) *.bin *.map *.lst *.out
-find . -name '*~' | xargs rm -f
html:
-rm -rf html
-mkdir html
source-highlight --output-dir=html -f xhtml -n $(CSRC) $(CXXSRC)
# The following is used by 'make' to automatically
# generate dependency information
# DO NOT DELETE
kernel.o: kernel.h hos_defines.h multiboot.h module.h lang/lang.h functions.h
kernel.o: sys/io.h mm/mm.h mm/vmm.h lang/conv.h devices.h display/display.h
kernel.o: display/kout.h sys/pic.h char/keyboard.h block/ramdisk.h fs/vfs.h
kernel.o: fs/ext2/ext2.h sys/pci.h proc/proc.h
mm/mm.o: kernel.h hos_defines.h multiboot.h mm/mm.h
mm/vmm.o: hos_defines.h kernel.h multiboot.h mm/vmm.h lang/lang.h mm/mm.h
lang/conv.o: lang/conv.h hos_defines.h
display/kout.o: hos_defines.h display/kout.h lang/conv.h devices.h
display/kout.o: char/misc_char.h char/misc_char.h functions.h sys/io.h
display/display.o: devices.h hos_defines.h char/vconsole.h display/display.h
display/display.o: lang/lang.h kernel.h multiboot.h char/keyboard.h
display/display.o: display/kout.h
sys/pic.o: hos_defines.h sys/pic.h sys/io.h
char/keyboard.o: hos_defines.h char/keyboard.h sys/io.h functions.h
char/keyboard.o: lang/conv.h display/kout.h display/display.h devices.h
lang/lang.o: lang/lang.h hos_defines.h
sys/pci_classes.o: hos_defines.h sys/pci.h
lang/string.o: lang/string.h lang/lang.h hos_defines.h
lang/new.o: hos_defines.h mm/vmm.h multiboot.h
char/misc_char.o: hos_defines.h devices.h char/misc_char.h sys/io.h
char/vconsole.o: hos_defines.h mm/vmm.h multiboot.h lang/lang.h
char/vconsole.o: display/display.h devices.h functions.h sys/io.h
char/vconsole.o: char/vconsole.h
block/ramdisk.o: functions.h hos_defines.h sys/io.h mm/vmm.h multiboot.h
block/ramdisk.o: lang/lang.h block/ramdisk.h devices.h
devices.o: hos_defines.h devices.h char/misc_char.h char/misc_char.h
devices.o: char/vconsole.h block/ramdisk.h
fs/vfs.o: hos_defines.h display/kout.h functions.h sys/io.h lang/lang.h
fs/vfs.o: fs/vfs.h devices.h fs/FileSystem.h fs/OpenDirectory.h fs/OpenFile.h
fs/vfs.o: lang/string.h fs/VFSMount.h fs/FileSystem.h fs/ext2/ext2.h fs/vfs.h
fs/vfs.o: lang/vector.h
fs/ext2/ext2.o: display/kout.h hos_defines.h mm/vmm.h multiboot.h lang/lang.h
fs/ext2/ext2.o: fs/ext2/ext2.h fs/vfs.h devices.h fs/ext2/Ext2OpenDirectory.h
fs/ext2/ext2.o: fs/OpenDirectory.h fs/vfs.h fs/OpenFile.h lang/string.h
fs/ext2/ext2.o: fs/ext2/Ext2OpenFile.h fs/OpenFile.h
fs/sysfs/sysfs.o: display/kout.h hos_defines.h fs/vfs.h devices.h
fs/sysfs/sysfs.o: fs/sysfs/sysfs.h fs/sysfs/sysfs_entry.h lang/vector.h
fs/sysfs/sysfs.o: lang/string.h
fs/sysfs/sysfs_entry.o: fs/sysfs/sysfs_entry.h lang/vector.h hos_defines.h
fs/sysfs/sysfs_entry.o: lang/string.h
sys/pci.o: hos_defines.h display/kout.h sys/io.h sys/pci.h lang/vector.h
proc/proc.o: hos_defines.h mm/mm.h kernel.h multiboot.h mm/vmm.h lang/lang.h
proc/proc.o: functions.h sys/io.h display/kout.h proc/proc.h proc/hash.h
proc/proc.o: lang/vector.h
proc/hash.o: hos_defines.h proc/hash.h lang/vector.h display/kout.h mm/vmm.h
proc/hash.o: multiboot.h
fs/OpenFile.o: fs/OpenFile.h hos_defines.h
fs/OpenDirectory.o: fs/vfs.h hos_defines.h devices.h fs/OpenDirectory.h
fs/OpenDirectory.o: fs/OpenFile.h lang/string.h
fs/ext2/Ext2OpenDirectory.o: display/kout.h hos_defines.h lang/lang.h
fs/ext2/Ext2OpenDirectory.o: fs/vfs.h devices.h fs/ext2/Ext2OpenDirectory.h
fs/ext2/Ext2OpenDirectory.o: fs/OpenDirectory.h fs/vfs.h fs/OpenFile.h
fs/ext2/Ext2OpenDirectory.o: lang/string.h fs/ext2/ext2.h

View File

@ -1,91 +0,0 @@
// ramdisk.cpp
// Author: Josh Holtrop
// Date: 08/20/04
// Modified: 05/11/05
extern "C"
{
#include "functions.h"
#include "mm/vmm.h"
#include "lang/lang.h"
}
#include "block/ramdisk.h"
#include "devices.h"
ramdisk_t *ramdisks[256];
minor_t ramdisk_new(u32_t size)
{
int i;
for (i = 0; i < 256; i++)
{
if (!ramdisks[i])
{
void *start;
if (( start = kmalloc(size) ))
{
ramdisks[i] = (ramdisk_t *)New(ramdisk_t);
ramdisks[i]->start = start;
ramdisks[i]->size = size;
return i;
}
return -2;
}
}
return -1;
}
minor_t ramdisk_register(void *ramdisk, u32_t size)
{
int i;
for (i = 0; i < 256; i++)
{
if (!ramdisks[i])
{
ramdisks[i] = (ramdisk_t *)New(ramdisk_t);
ramdisks[i]->start = ramdisk;
ramdisks[i]->size = size;
return i;
}
}
return -1;
}
int ramdisk_remove(minor_t minor)
{
if (ramdisks[minor])
{
kfree(ramdisks[minor]->start);
kfree(ramdisks[minor]);
ramdisks[minor] = NULL;
return 0;
}
return -1;
}
int Ramdisk::block_read(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer)
{
if (!ramdisks[minor])
return -1;
if ((blockStart << BLOCK_SIZE_LOG) >= ramdisks[minor]->size)
return -2;
void *rdAddr = (void *)((u32_t)ramdisks[minor]->start + (blockStart << BLOCK_SIZE_LOG));
u32_t copyLen = min(blocks << BLOCK_SIZE_LOG, ramdisks[minor]->size + (u32_t)ramdisks[minor]->start - (u32_t)rdAddr);
memcpyd(buffer, rdAddr, copyLen >> 2);
return copyLen;
}
int Ramdisk::block_write(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer)
{
if (!ramdisks[minor])
return -1;
if ((blockStart << BLOCK_SIZE_LOG) >= ramdisks[minor]->size)
return -2;
void *rdAddr = (void *)((u32_t)ramdisks[minor]->start + (blockStart << BLOCK_SIZE_LOG));
u32_t copyLen = min(blocks << BLOCK_SIZE_LOG, ramdisks[minor]->size + (u32_t)ramdisks[minor]->start - (u32_t)rdAddr);
memcpyd(rdAddr, buffer, copyLen >> 2);
return copyLen;
}

View File

@ -1,38 +0,0 @@
// ramdisk.h
// Author: Josh Holtrop
// Date: 08/20/04
// Modified: 08/22/04
#ifndef __HOS_RD_H__
#define __HOS_RD_H__ __HOS_RD_H__
#ifdef _HOS_CPP_
extern "C" {
#endif
#include "hos_defines.h"
#include "devices.h"
typedef struct {
void *start;
u32_t size;
} ramdisk_t;
minor_t ramdisk_new(u32_t size);
minor_t ramdisk_register(void *ramdisk, u32_t size);
int ramdisk_remove(minor_t minor);
#ifdef _HOS_CPP_
}
class Ramdisk : public DeviceDriver
{
public:
int block_read(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer);
int block_write(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer);
};
#endif
#endif

View File

@ -1,100 +0,0 @@
// ramdisk.c
// Author: Josh Holtrop
// Date: 08/20/04
// Modified: 08/22/04
#include "block/ramdisk.h"
#include "fs/devices.h"
#include "functions.h"
#include "mm/vmm.h"
#include "lang/lang.h"
ramdisk_t *ramdisks[256];
int ramdisk_init(major_t major)
{
dev_driver_t *ramdisk_driver;
if (( ramdisk_driver = New(dev_driver_t) ))
{
ramdisk_driver->block_read = ramdisk_block_read;
ramdisk_driver->block_write = ramdisk_block_write;
devices_register_major('b', major, ramdisk_driver);
return 0;
}
return -1;
}
minor_t ramdisk_new(u32_t size)
{
int i;
for (i = 0; i < 256; i++)
{
if (!ramdisks[i])
{
void *start;
if (( start = kmalloc(size) ))
{
ramdisks[i] = New(ramdisk_t);
ramdisks[i]->start = start;
ramdisks[i]->size = size;
return i;
}
return -2;
}
}
return -1;
}
minor_t ramdisk_register(void *ramdisk, u32_t size)
{
int i;
for (i = 0; i < 256; i++)
{
if (!ramdisks[i])
{
ramdisks[i] = New(ramdisk_t);
ramdisks[i]->start = ramdisk;
ramdisks[i]->size = size;
return i;
}
}
return -1;
}
int ramdisk_remove(minor_t minor)
{
if (ramdisks[minor])
{
kfree(ramdisks[minor]->start);
kfree(ramdisks[minor]);
ramdisks[minor] = NULL;
return 0;
}
return -1;
}
int ramdisk_block_read(minor_t minor, u32_t blockNum, u32_t count, void *buffer)
{
if (!ramdisks[minor])
return -1;
if ((blockNum << BLOCK_SIZE_LOG) >= ramdisks[minor]->size)
return -2;
void *rdAddr = ramdisks[minor]->start + (blockNum << BLOCK_SIZE_LOG);
u32_t copyLen = min(count << BLOCK_SIZE_LOG, ramdisks[minor]->size + (u32_t)ramdisks[minor]->start - (u32_t)rdAddr);
memcpyd(buffer, rdAddr, copyLen >> 2);
return copyLen;
}
int ramdisk_block_write(minor_t minor, u32_t blockNum, u32_t count, void *buffer)
{
if (!ramdisks[minor])
return -1;
if ((blockNum << BLOCK_SIZE_LOG) >= ramdisks[minor]->size)
return -2;
void *rdAddr = ramdisks[minor]->start + (blockNum << BLOCK_SIZE_LOG);
u32_t copyLen = min(count << BLOCK_SIZE_LOG, ramdisks[minor]->size + (u32_t)ramdisks[minor]->start - (u32_t)rdAddr);
memcpyd(rdAddr, buffer, copyLen >> 2);
return copyLen;
}

View File

@ -1,25 +0,0 @@
// ramdisk.h
// Author: Josh Holtrop
// Date: 08/20/04
// Modified: 08/22/04
#ifndef __HOS_RD_H__
#define __HOS_RD_H__ __HOS_RD_H__
#include "hos_defines.h"
#include "fs/devices.h"
typedef struct {
void *start;
u32_t size;
} ramdisk_t;
int ramdisk_init(major_t major);
minor_t ramdisk_new(u32_t size);
minor_t ramdisk_register(void *ramdisk, u32_t size);
int ramdisk_remove(minor_t minor);
int ramdisk_block_read(minor_t minor, u32_t blockNum, u32_t count, void *buffer);
int ramdisk_block_write(minor_t minor, u32_t blockNum, u32_t count, void *buffer);
#endif

View File

@ -1,236 +0,0 @@
;boot.asm
;Author: Josh Holtrop
;Date: 07/08/04
;Modified: 11/01/05
%define MULTIBOOT_MAGIC 0x1BADB002
%define MULTIBOOT_FLAGS 0x00010003
%define VIRT_OFFSET 0xC0000000 ;3gb virtual address
%define PHYS_START 0x00100000 ;1mb physical address
%define VIRT_STACK_TOP 0xD0000000 ;3gb+256mb virtual address
%define GDT_P PHYS_START ;1mb physical - Global Descriptor Table space
%define GDT_V GDT_P+VIRT_OFFSET
%define IDT_P PHYS_START+0x2000 ;1mb+8kb - Interrupt Descriptor Table space
%define IDT_V IDT_P+VIRT_OFFSET
%define PDBR_P PHYS_START+0x4000 ;1mb+16kb - Page Directory Base Register (first PD)
%define PDBR_V PDBR_P+VIRT_OFFSET
%define LOPT_P PHYS_START+0x5000 ;1mb+20kb - LOw Page Table for mapping first 4mb
%define LOPT_V LOPT_P+VIRT_OFFSET
%define PT_STACK_P PHYS_START+0x6000 ;1mb+24kb - page table for initial kernel stack pages (under 0xD0000000)
%define PT_STACK_V PT_STACK_P+VIRT_OFFSET
%define STACK_P PHYS_START+0x7000 ;1mb+28kb - initial 4kb kernel stack page
%define STACK_V STACK_P+VIRT_OFFSET
%define KERNEL_P PHYS_START+0x8000 ;1mb+32kb - the kernel's physical address
%define KERNEL_V KERNEL_P+VIRT_OFFSET ;3gb+1mb+32kb, the virtual address of the kernel
extern _k_init, _isr, _k_mbsave, _end, _rm_params, _initrd, _tss0
[bits 32]
[global _start]
_start:
multiboot_header:
dd MULTIBOOT_MAGIC ;magic
dd MULTIBOOT_FLAGS ;flags
dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) ;checksum
dd multiboot_header-VIRT_OFFSET ;header_addr
dd _start-VIRT_OFFSET ;load_addr
dd 0 ;load_end_addr
dd _end-VIRT_OFFSET ;bss_end_addr
dd multiboot_entry-VIRT_OFFSET ;entry_addr
; dd 1 ;mode_type
; dd 80 ;width
; dd 25 ;height
; dd 0 ;depth
[global multiboot_entry]
multiboot_entry:
;This is where the kernel begins execution from the bootloader.
;At this point, a temporary gdt is set up to "map" 0xC000_0000 to 0x0.
cli ;should already be off...
lgdt [gdtrbs32-VIRT_OFFSET]
jmp KERNEL_CODE_BS32:segmented_start
segmented_start:
mov cx, KERNEL_DATA_BS32
mov ss, cx
mov ds, cx
mov es, cx
mov gs, cx
mov fs, cx
mov esp, STACK_V+0x1000 ;ok, now we can access our data
;Then the multiboot info structures are saved to local data variables.
add ebx, VIRT_OFFSET
push eax
push ebx ;pointer to multiboot info structure
call _k_mbsave ;save multiboot info structures
add esp, 8
cmp eax, 0 ; eax = pointer to mb_module_t struct for rmmod
jz pm_return
;go back to real mode to initialize video mode
mov ebx, eax ; pointer to mb_module_t
mov ecx, [ebx+4] ; end of module
mov eax, [ebx] ; start of module
mov esi, eax ; start of module
sub ecx, eax ; ecx = length of rmmod
shr ecx, 2 ; ecx = length of rmmod in dwords
mov edi, 0xC0005000 ; where to copy rmmod to (0x5000 physical)
rep movsd ; copy rmmod to first 1mb
mov ebx, pm_return ; return address
mov ecx, _rm_params ; put real mode params here (video mode etc...)
sub ecx, VIRT_OFFSET
jmp 0xC0005010 ; jump to rmmod
;Next we enable paging with the first 4mb mapped 1:1 virtual:physical
; and with the 4mb starting at 0xC000_0000 mapped to the first 4mb physical.
pm_return:
mov esp, STACK_V+0x1000 ;ok, now we can access our data again
xor eax, eax
mov edi, PDBR_V
mov ecx, 1024 ;clear the PDBR
rep stosd
mov edi, PT_STACK_V
mov ecx, 1024 ;clear the PT_STACK
rep stosd
mov [PDBR_V], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table | (read/write, present)
mov [PDBR_V+0xC00], dword LOPT_P|0x03 ;store the physical address of the LOw Page Table | (read/write, present)
mov [PDBR_V+0xCFC], dword PT_STACK_P|0x03 ;store the physical address of the initial stack page page table | (read/write, present)
mov [PDBR_V+0xFFC], dword PDBR_P|0x03 ;store the physical address of the page directory (identity map) | (read/write, present)
mov [PT_STACK_V+0xFFC], dword STACK_P|0x03 ;store the physical address of the initial stack page | (read/write, present)
mov edi, LOPT_V
mov ecx, 1024
mov eax, 0x03 ;starting physical address = 0x0 | (read/write, present flags)
fill_lopt_loop: ;fill the page table
stosd
add eax, 4096 ;increment next phsyical address by 4kb
loop fill_lopt_loop
mov eax, PDBR_P
mov cr3, eax ;store the Page Directory Base Address
mov eax, cr0
or eax, 0x80000000 ;set Page Enable bit
mov cr0, eax ;now paging is active!
mov edi, GDT_V
mov esi, gdt
mov ecx, gdt_end-gdt
rep movsb
mov edi, IDT_V ;destination
mov esi, isr_0 ;address of isr0
mov edx, isr_1-isr_0 ;distance between isr labels
mov ecx, 50 ;number of isrlabels
fill_idt:
mov ebx, esi
mov ax, si
stosw ;0 offset 15:0
mov ax, KERNEL_CODE
stosw ;2 selector 15:0
mov ax, 0x8E00
stosw ;4 [P][DPL][0][TYPE][0][0][0][0][0][0][0][0]
shr esi, 16
mov ax, si
stosw ;6 offset 31:16
mov esi, ebx
add esi, edx
loop fill_idt
mov word [IDT_V+0x30*8+4], 0xEE00 ;interrupt 0x30 has user priviledges
;Then we can start using our "real" gdt, then unmap the lower 4mb.
lgdt [gdtr] ;load gdt
jmp KERNEL_CODE:newgdtcontinue
newgdtcontinue:
mov ax, KERNEL_DATA
mov es, ax
mov ds, ax
mov gs, ax
mov fs, ax
mov ss, ax
mov esp, VIRT_STACK_TOP ;stack just under 3gb+256mb, moves downward
lidt [idtr] ;load idt
mov [PDBR_V], dword 0 ;unmap 0x0, we are running completely paged at 0xC000_0000
mov edi, GDT_V + TSS0_SEG + 2 ; copy _tss0 base address
mov eax, _tss0 ; into the GDT descrtiptor
stosw ; for TSS0
shr eax, 16
stosb
add edi, 2
shr eax, 8
stosb
call _k_init ;C kernel initialization
mov ax, TSS0_SEG
ltr ax
mov eax, esp
push KERNEL_DATA
push eax
idle_loop: ; system idle loop
sti
hlt
jmp idle_loop
;-------------------------------------------------------
gdtrbs32:
dw gdt_endbs32-gdtbs32-1
dd gdtbs32-VIRT_OFFSET
gdtbs32: ; 0 = null descriptor
dd 0
dd 0
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
KERNEL_CODE_BS32 equ $-gdtbs32 ; 8
db 0xff ;limit 7:0
db 0xff ;limit 15:8
db 0x00 ;base 7:0
db 0x00 ;base 15:8
db 0x00 ;base 23:16
db 0x9a ;access
db 0xcf ;flags / limit 19:16
db 0x40 ;base 31:24
KERNEL_DATA_BS32 equ $-gdtbs32 ; 16
db 0xff ;limit 7:0
db 0xff ;limit 15:8
db 0x00 ;base 7:0
db 0x00 ;base 15:8
db 0x00 ;base 23:16
db 0x92 ;access
db 0xcf ;flags / limit 19:16
db 0x40 ;base 31:24
KERNEL_CODE_BS6_ equ $-gdtbs32 ; 24
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x9A ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x00 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
KERNEL_DATA_BS16 equ $-gdtbs32 ; 32
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x00 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
gdt_endbs32:
%include "gdt.inc"
%include "idt.inc"

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

@ -1,151 +0,0 @@
// keyboard.c
// Author: Josh Holtrop
// Created: 04/17/03
// Modified: 05/19/05
#include "hos_defines.h"
#include "char/keyboard.h"
#include "sys/io.h" // inportb, outportb
#include "functions.h"
#include "lang/conv.h" // asciiSwitchCase()
#include "display/kout.h" // kprintf()
#include "display/display.h" // display_activate()
u8_t kbdFlags = 0; // holds current keyboard flags - caps/num/scroll/shift/ctrl/alt
u8_t lastWasE0 = 0; // was the last byte 0x0E ?
u8_t rawIgnore = 0; // how many signals to blatantly ignore
u8_t ackReason = 0; // used to record the reason why we would get an acknowledge byte (0xFA)
//these arrays convert a keyboard scan code to an ASCII character value
const u8_t SCAN2ASCII[129] = // for normal keys
"\000\0331234567890-=\010\011" // null,esc,1234567890-=,bksp,tab
"qwertyuiop[]\n\000as" // qwertyuiop[],enter,lctrl,as
"dfghjkl;'`\000\\zxcv" // dfghjkl;'`,lshift,\zxcv
"bnm,./\000*\000 \000\000\000\000\000\000" // bnm,./,rshift,*,alt,space,caps,f1,f2,f3,f4,f5
"\000\000\000\000\000\000\000\000\000\000-\000\000\000+\000" // f6,f7,f8,f9,f10,num,scrl,home,up,pgup,dash,left,center,right,plus,end
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" // down,pgdn,ins,del,?,?,?,f11,f12,?,?,winL,winR,menu,?,?
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" // ?
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; // ?
const u8_t SCAN2ASCII2[129] = // for shifted or numlocked keys
"\000\033!@#$%^&*()_+\010\011" // null,esc,!@#$%^&*()_+,bksp,tab
"QWERTYUIOP{}\n\000AS" // QWERTYUIOP{},enter,lctrl,AS
"DFGHJKL:\"~\000|ZXCV" // DFGHJKL:"~,lshift,|ZXCV
"BNM<>?\000*\000 \000\000\000\000\000\000" // BNM<>?,rshift,*,alt,space,caps,f1,f2,f3,f4,f5
"\000\000\000\000\000\000\000789-456+1" // f6,f7,f8,f9,f10,num,scrl,789-456+1
"230.\000\000\000\000\000\000\000\000\000\000\000\000" // 230.,?,?,?,f11,f12,?,?,winL,winR,menu,?,?
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" // ?
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; // ?
// The Keyboard Interrupt Service Routine
void isr_keyboard()
{
u8_t kbdScan = inportb(0x60);
u8_t inState = inportb(0x61);
outportb(0x61, inState|0x80);
outportb(0x61, inState);
if (kbdScan == 0xFA) //250 // ACKnowledge
{
//printf("KBD_ACK 0x%x!\n", ackReason);
switch (ackReason)
{
case 0xED: // reset LEDs
outportb(0x60, (kbdFlags & 0x07));
break;
}
ackReason = 0;
}
if (rawIgnore) // ignore keycodes
{
rawIgnore--;
return;
}
if (lastWasE0 && (kbdScan == 0x2A || kbdScan == 0xAA)) // ignore extended "shift"
{
lastWasE0 = 0;
return;
}
if (kbdScan == 0xE0) // 0xE0 == extended key
{
lastWasE0 = 1;
return;
}
if (kbdScan == 0xE1) // 0xE1 == 2nd-set-extended key
{
rawIgnore = 2;
return;
}
switch (kbdScan) // handle control keys
{
case KBD_SCAN_LSHIFT:
kbdFlags |= KBDF_SHIFT;
break;
case KBD_SCAN_RSHIFT:
kbdFlags |= KBDF_SHIFT;
break;
case KBD_SCAN_CTRL:
kbdFlags |= KBDF_CTRL;
break;
case KBD_SCAN_ALT:
kbdFlags |= KBDF_ALT;
break;
case KBD_SCAN_LSHIFT + KBD_SCAN_RELEASED:
kbdFlags &= (KBDF_SHIFT ^ 0xFF);
break;
case KBD_SCAN_RSHIFT + KBD_SCAN_RELEASED:
kbdFlags &= (KBDF_SHIFT ^ 0xFF);
break;
case KBD_SCAN_CTRL + KBD_SCAN_RELEASED:
kbdFlags &= (KBDF_CTRL ^ 0xFF);
break;
case KBD_SCAN_ALT + KBD_SCAN_RELEASED:
kbdFlags &= (KBDF_ALT ^ 0xFF);
break;
case KBD_SCAN_CAPS+KBD_SCAN_RELEASED:
kbdFlags ^= KBDF_CAPS;
kbd_resetLEDs(); // update LEDs
break;
case KBD_SCAN_SCROLL+KBD_SCAN_RELEASED:
kbdFlags ^= KBDF_SCROLL;
kbd_resetLEDs(); // update LEDs
break;
case KBD_SCAN_NUM+KBD_SCAN_RELEASED:
kbdFlags ^= KBDF_NUM;
kbd_resetLEDs(); // update LEDs
break;
}
u8_t kbdAscii;
// shift or (numlock and key from numpad)
if ( (kbdFlags & KBDF_SHIFT) || ((kbdFlags & KBDF_NUM) && (kbdScan >= 71) && (kbdScan <= 83)) )
kbdAscii = SCAN2ASCII2[kbdScan & 0x7F];
else // normal key
kbdAscii = SCAN2ASCII[kbdScan & 0x7F];
if (kbdFlags & KBDF_CAPS)
kbdAscii = asciiSwitchCase(kbdAscii); // won't affect non-letter characters
//====do something with key::
// kprintf("kbdScan = \e[31;1m0x%x\e[0m\tkbdAscii = \e[1;32m0x%x\e[0m (\e[35m%c\e[0m)\tkbdFlags = \e[34m0x%x\e[0m\n", kbdScan, kbdAscii, kbdAscii, kbdFlags);
if ((kbdScan == 83) && (kbdFlags & KBDF_CTRL) && (kbdFlags & KBDF_ALT))
{
kprintf("Initiating reboot.");
restart();
}
if (kbdScan & KBD_SCAN_RELEASED)
kbdAscii = 0;
// send a key event to the display subsystem
display_key_event((kbdFlags << 16) | (kbdScan << 8) | kbdAscii);
}
//Resets the keyboard LEDs to reflect the current state of the num lock, caps lock, and scroll lock bits
void kbd_resetLEDs()
{
outportb(0x60, 0xED);
ackReason = 0xED;
}

View File

@ -1,36 +0,0 @@
// keyboard.h
// Author: Josh Holtrop
// Created: 04/17/03
// Modified: 05/19/05
#include "hos_defines.h"
#ifndef __HOS_KEYBOARD__
#define __HOS_KEYBOARD__ __HOS_KEYBOARD__
#define KBDF_SCROLL 0x01
#define KBDF_NUM 0x02
#define KBDF_CAPS 0x04
#define KBDF_SHIFT 0x10
#define KBDF_CTRL 0x20
#define KBDF_ALT 0x40
#define KBD_SCAN_RELEASED 0x80
#define KBD_SCAN_CTRL 29
#define KBD_SCAN_LSHIFT 42
#define KBD_SCAN_RSHIFT 54
#define KBD_SCAN_ALT 56
#define KBD_SCAN_SCROLL 70
#define KBD_SCAN_CAPS 58
#define KBD_SCAN_NUM 69
#define KBD_ASCII(x) ((x) & 0xFF)
#define KBD_SCAN(x) (((x) >> 8) & 0xFF)
#define KBD_FLAGS(x) (((x) >> 16) &0xFF)
void isr_keyboard();
void kbd_resetLEDs();
#endif

View File

@ -1,44 +0,0 @@
// misc_char.cpp
// Miscellaneous character devices
// Author: Josh Holtrop
// Date: 05/11/05
// Modified: 05/11/05
#include "hos_defines.h"
#include "devices.h"
#include "misc_char.h"
#include "sys/io.h"
int MiscChar::char_read(minor_t minor)
{
switch (minor)
{
case MISC_CHAR_NULL:
return DEV_EOF;
case MISC_CHAR_ZERO:
return 0;
case MISC_CHAR_LP0:
return DEV_INVALID_ACCESS;
default:
return DEV_INVALID_ACCESS;
}
}
int MiscChar::char_write(minor_t minor, int c)
{
switch (minor)
{
case MISC_CHAR_NULL:
return 0;
case MISC_CHAR_ZERO:
return 0;
case MISC_CHAR_LP0:
outportb(0x37a, 0xc);
outportb(0x378, c);
outportb(0x37a, 0x1);
return 0;
default:
return DEV_INVALID_ACCESS;
}
}

View File

@ -1,31 +0,0 @@
// misc_char.h
// Miscellaneous character devices
// Author: Josh Holtrop
// Date: 05/11/05
// Modified: 05/11/05
#ifndef __HOS_MISC_CHAR__
#define __HOS_MISC_CHAR__ __HOS_MISC_CHAR__
#define MISC_CHAR_NULL 3
#define MISC_CHAR_ZERO 5
#define MISC_CHAR_LP0 10
#include "hos_defines.h"
#include "devices.h"
#include "misc_char.h"
#ifdef _HOS_CPP_
class MiscChar : public DeviceDriver
{
public:
int char_read(minor_t minor);
int char_write(minor_t minor, int c);
};
#endif
#endif

View File

@ -1,52 +0,0 @@
// mouse.c
// Author: Josh Holtrop
// Date: 10/03/03
// Modified: 08/02/04
#include "hos_defines.h"
#include "char/mouse.h"
#include "video/video.h"
#include "sys/io.h"
int mouse_bytesRead;
byte mouse_inbuffer[MOUSE_BUFFER_LENGTH];
//This method initializes the ps/2 mouse
void mouse_init()
{
outportb(0x64, 0x20); //tell keyboard controller we are going to read keyboard controller command byte
byte temp = inportb(0x60); //read keyboard controller command byte
outportb(0x64, 0x60); //tell keyboard controller we are going to write keyboard controller command byte
outportb(0x60, 0x03 | (temp & 0x40)); //write keyboard controller command byte: enable mouse/keyboard ints, include original XLATE bit from temp (bit6)
outportb(0x64, 0xA8); //enable mouse port
outportb(0x64, 0xD4); //send command to mouse, not kbd
outportb(0x60, 0xF4); //enable data reporting
mouse_bytesRead = 0;
//outportb(0x64, 0xD4);
//outportb(0x60, 0xE7); //scaling 2:1
}
//This method is called when a mouse interrupt occurs
void isr_mouse()
{
byte inb = inportb(0x60); //read mouse byte
if ((inb == 0xFA) && (mouse_bytesRead < 1)) //ACK
return;
mouse_inbuffer[mouse_bytesRead] = inb;
mouse_bytesRead++;
if (mouse_bytesRead == 3) //complete packet received
{
mouse_bytesRead = 0;
int adjx = (char) mouse_inbuffer[1];
int adjy = (char) mouse_inbuffer[2];
// TODO: do something with adjx, adjy...
}
}

View File

@ -1,15 +0,0 @@
// mouse.h
// Author: Josh Holtrop
// Date: 10/03/03
// Modified: 08/02/04
#ifndef __HOS_MOUSE__
#define __HOS_MOUSE__ __HOS_MOUSE__
#define MOUSE_BUFFER_LENGTH 16
void mouse_init();
void isr_mouse();
#endif

View File

@ -1,274 +0,0 @@
// vconsole.cpp
// Author: Josh Holtrop
// Date: 08/02/04
// Modified: 05/11/05
extern "C"
{
#include "hos_defines.h"
#include "mm/vmm.h"
#include "lang/lang.h"
#include "display/display.h"
#include "functions.h"
}
#include "devices.h"
#include "char/vconsole.h"
VConsole *vconsoles[VCONSOLE_MAX]; // pointer to virtual console structs
char ansi2vgaAttr[8] = {0, 4, 2, 6, 1, 5, 3, 7};
void vconsole_setup(int width, int height)
{
for (int i = 0; i < VCONSOLE_MAX; i++)
vconsoles[i] = new VConsole(width, height);
}
int vconsole_activate(u32_t id)
{
if (id >= VCONSOLE_MAX)
return -1;
vconsoles[id]->activate();
return 0;
}
int vconsole_deactivate(u32_t id)
{
if (id >= VCONSOLE_MAX)
return -1;
vconsoles[id]->deactivate();
return 0;
}
VConsoleDriver::~VConsoleDriver()
{
for (int i = 0; i < VCONSOLE_MAX; i++)
if (vconsoles[i])
delete vconsoles[i];
}
int VConsoleDriver::char_write(minor_t minor, int c)
{
if (minor < 0 || minor >= VCONSOLE_MAX)
return -1;
if (!vconsoles[minor])
return -2;
return vconsoles[minor]->char_write(c);
}
VConsole::VConsole(int width, int height)
{
myBuffer = new u16_t[width * height];
myBuffer2 = NULL;
myWidth = width;
myHeight = height;
myAttribute = myForeground = 0x07;
memsetw(myBuffer, 0x0720, width * height);
myCursorPosition = 0;
myCursorStackPosition = myEscapeLevel = myEscapePosition = myBackground =
myBold = myReverse = myBlink = myConcealed = myActive = 0;
}
VConsole::~VConsole()
{
delete[] myBuffer;
}
void VConsole::activate()
{
if (myActive) // don't activate if already active
return;
myActive = 1;
myBuffer2 = myBuffer;
myBuffer = (u16_t *)CONSOLE_MEMORY;
memcpyd(myBuffer, myBuffer2, (myWidth * myHeight) >> 1);
writeCursorPosition(myCursorPosition);
}
void VConsole::deactivate()
{
if (!myActive) // don't deactivate non-active console
return;
myActive = 0;
myBuffer = myBuffer2;
myBuffer2 = NULL;
memcpyd(myBuffer, (u16_t *)CONSOLE_MEMORY, (myWidth * myHeight) >> 1);
}
int VConsole::char_write(int c)
{
int cursorY = myCursorPosition / myWidth;
int cursorX = myCursorPosition % myWidth;
switch (myEscapeLevel)
{
case 2:
if (c >= '0' && c <= '9') // c is part of an escape value
{
myEscapeValue[myEscapePosition] *= 10;
myEscapeValue[myEscapePosition] += c - '0';
return 0;
}
else if (c == ';')
{
if (myEscapePosition < 7)
myEscapePosition++;
return 0;
}
switch (c)
{
case 'A': // move cursor up n rows
update_cursor_coord(cursorY - myEscapeValue[0], cursorX);
break;
case 'B': // move cursor down n rows
update_cursor_coord(cursorY + myEscapeValue[0], cursorX);
break;
case 'C': // move cursor left n columns
update_cursor_coord(cursorY, cursorX - myEscapeValue[0]);
break;
case 'D': // move cursor right n columns
update_cursor_coord(cursorY, cursorX + myEscapeValue[0]);
break;
case 'H':
case 'f': // move cursor to position (x,y) upper left is (1,1)
update_cursor_coord(myEscapeValue[1] - 1, myEscapeValue[0] - 1);
break;
case 'J': // clear screen, home cursor
memsetw(myBuffer, 0x0720, myWidth * myHeight);
update_cursor_coord(0, 0);
break;
case 'K': // erase line from cursor position (including char. under cursor) to end of line
memsetw(myBuffer + myCursorPosition, 0x0720, myWidth - cursorX);
break;
case 's': // push cursor position on an internal stack
if (myCursorStackPosition < 16)
myCursorStack[myCursorStackPosition++] = myCursorPosition;
break;
case 'u': // pop cursor position from stack
if (myCursorStackPosition > 0)
update_cursor(myCursorStack[--myCursorStackPosition]);
break;
case 'm': // set text attributes
for (int evalEscapePosition = 0; evalEscapePosition <= myEscapePosition; evalEscapePosition++)
{
switch (myEscapeValue[evalEscapePosition])
{
case 0:
myForeground = 0x07;
myBackground = myConcealed = myReverse = myBlink = myBold = 0;
update_attribute();
break;
case 1:
myBold = 1;
update_attribute();
break;
case 5:
myBlink = 1;
update_attribute();
break;
case 7:
myReverse = 1;
update_attribute();
break;
case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
myForeground = ansi2vgaAttr[myEscapeValue[evalEscapePosition] - 30];
update_attribute();
break;
case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47:
myBackground = ansi2vgaAttr[myEscapeValue[evalEscapePosition] - 40];
update_attribute();
break;
}
}
myEscapePosition = 0;
break;
}
memsetd(myEscapeValue, 0, 8);
myEscapePosition = 0;
myEscapeLevel = 0;
return 0;
case 1:
if (c == '[')
myEscapeLevel = 2;
break;
myEscapeLevel = 0;
return 0; // invalid escape sequence
default:
if (c == '\e')
{
myEscapeLevel = 1;
return 0;
}
put_char(c);
}
return 0;
}
void VConsole::put_char(int c)
{
if (!myConcealed)
{
switch (c)
{
case '\t':
if (myCursorPosition % 8)
update_cursor(myCursorPosition + (8 - (myCursorPosition % 8)));
else
update_cursor(myCursorPosition + 8);
break;
case '\n':
if (myCursorPosition % myWidth)
update_cursor(myCursorPosition + (myWidth - (myCursorPosition % myWidth)));
else
update_cursor(myCursorPosition + myWidth);
break;
default:
myBuffer[myCursorPosition] = c | (myAttribute << 8);
update_cursor(myCursorPosition + 1);
}
}
}
void VConsole::update_cursor_coord(int y, int x)
{
if (y < 0)
y = 0;
else if (y >= myHeight)
y = myHeight - 1;
if (x < 0)
x = 0;
else if (x >= myWidth)
x = myWidth - 1;
update_cursor(myWidth * y + x);
}
void VConsole::update_cursor(u16_t position)
{
myCursorPosition = position;
if (position >= (myWidth * myHeight)) // time to scroll console
{
int i;
for (i = 0; i < myCursorStackPosition; i++)
{
myCursorStack[i] -= myWidth;
if (myCursorStack[i] < 0)
myCursorStack[i] = 0;
}
myCursorPosition -= myWidth;
memcpyw(myBuffer, myBuffer + myWidth, myWidth * (myHeight - 1));
memsetw(myBuffer + (myWidth * (myHeight - 1)), 0x0720, myWidth);
}
if (myActive)
writeCursorPosition(position);
}
void VConsole::update_attribute()
{
if (myReverse)
myAttribute = myBlink << 7 | myForeground << 4 | myBold << 3 | myBackground;
else
myAttribute = myBlink << 7 | myBackground << 4 | myBold << 3 | myForeground;
}

View File

@ -1,76 +0,0 @@
// vconsole.h
// Author: Josh Holtrop
// Date: 08/02/04
// Modified: 05/11/05
#ifndef __HOS_VCONSOLE__
#define __HOS_VCONSOLE__ __HOS_VCONSOLE__
#define VCONSOLE_MAX 12
#ifdef _HOS_CPP_
extern "C" {
#endif
#include "hos_defines.h"
void vconsole_setup(int width, int height);
int vconsole_activate(u32_t id);
int vconsole_deactivate(u32_t id);
#ifdef _HOS_CPP_
}
#include "devices.h"
class VConsoleDriver : public DeviceDriver
{
public:
~VConsoleDriver();
int char_write(minor_t minor, int c);
};
class VConsole
{
protected:
u16_t *myBuffer;
u16_t *myBuffer2;
u16_t myWidth;
u16_t myHeight;
u16_t myCursorPosition;
short myCursorStack[16];
u8_t myCursorStackPosition;
u32_t myEscapeValue[8];
u8_t myEscapeLevel;
u8_t myEscapePosition;
u8_t myAttribute;
u8_t myForeground;
u8_t myBackground;
u8_t myBold;
u8_t myReverse;
u8_t myBlink;
u8_t myConcealed;
u8_t myActive;
public:
VConsole(int width, int height);
~VConsole();
int char_read();
int char_write(int c);
void put_char(int c);
void update_cursor(u16_t position);
void update_cursor_coord(int y, int x);
void update_attribute();
void activate();
void deactivate();
};
#endif
#endif

View File

@ -1,65 +0,0 @@
// devices.cpp
// Device subsystem for HOS
// Author: Josh Holtrop
// Date: 05/11/05
// Modified: 05/11/05
#include "hos_defines.h"
#include "devices.h"
#include "char/misc_char.h"
#include "char/vconsole.h"
#include "block/ramdisk.h"
DeviceDriver *drivers[256];
int devices_init()
{
drivers[MAJOR_MISC_CHAR] = new MiscChar();
drivers[MAJOR_VCONSOLE] = new VConsoleDriver();
drivers[MAJOR_RAMDISK] = new Ramdisk();
return 0;
}
int block_read(major_t major, minor_t minor, u32_t blockStart, u32_t blocks, void *buffer)
{
if (drivers[major & 0xFF])
return drivers[major & 0xFF]->block_read(minor, blockStart, blocks, buffer);
return DEV_INVALID_DEVICE;
}
int block_write(major_t major, minor_t minor, u32_t blockStart, u32_t blocks, void *buffer)
{
if (drivers[major & 0xFF])
return drivers[major & 0xFF]->block_write(minor, blockStart, blocks, buffer);
return DEV_INVALID_DEVICE;
}
int char_read(major_t major, minor_t minor)
{
if (drivers[major & 0xFF])
return drivers[major & 0xFF]->char_read(minor);
return DEV_INVALID_DEVICE;
}
int char_write(major_t major, minor_t minor, int c)
{
if (drivers[major & 0xFF])
return drivers[major & 0xFF]->char_write(minor, c);
return DEV_INVALID_DEVICE;
}
DeviceDriver::DeviceDriver() {}
DeviceDriver::~DeviceDriver() {}
int DeviceDriver::char_read(minor_t minor)
{ return DEV_INVALID_ACCESS; }
int DeviceDriver::char_write(minor_t minor, int c)
{ return DEV_INVALID_ACCESS; }
int DeviceDriver::block_read(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer)
{ return DEV_INVALID_ACCESS; }
int DeviceDriver::block_write(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer)
{ return DEV_INVALID_ACCESS; }

View File

@ -1,58 +0,0 @@
// devices.h
// Device subsystem for HOS
// Author: Josh Holtrop
// Date: 05/11/05
// Modified: 06/02/05
#ifndef __HOS_DEVICES_H__
#define __HOS_DEVICES_H__ __HOS_DEVICES_H__
#include "hos_defines.h"
#define DEV_INVALID_ACCESS -256
#define DEV_INVALID_DEVICE -257
#define DEV_EOF -1
#define MAJOR_MISC_CHAR 1
#define MAJOR_RAMDISK 2
#define MAJOR_VCONSOLE 4
#define BLOCK_SIZE 512
#define BLOCK_SIZE_LOG 9
#define DEV_MAJOR(x) (((x) >> 8) & 0xFF)
#define DEV_MINOR(x) ((x) & 0xFF)
#define DEV(x,y) ((x) << 8 | (y))
typedef short major_t;
typedef short minor_t;
typedef u32_t device_t;
#ifdef _HOS_CPP_
extern "C" {
#endif
int devices_init();
int block_read(major_t major, minor_t minor, u32_t blockStart, u32_t blocks, void *buffer);
int block_write(major_t major, minor_t minor, u32_t blockStart, u32_t blocks, void *buffer);
int char_read(major_t major, minor_t minor);
int char_write(major_t major, minor_t minor, int c);
#ifdef _HOS_CPP_
}
class DeviceDriver
{
public:
DeviceDriver();
virtual ~DeviceDriver();
virtual int char_read(minor_t minor);
virtual int char_write(minor_t minor, int c);
virtual int block_read(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer);
virtual int block_write(minor_t minor, u32_t blockStart, u32_t blocks, void *buffer);
};
#endif
#endif

View File

@ -1,75 +0,0 @@
// display.c
// Author: Josh Holtrop
// Date: 08/07/04
// Modified: 03/19/05
#include "devices.h"
#include "char/vconsole.h"
#include "display.h"
#include "lang/lang.h"
#include "kernel.h"
#include "char/keyboard.h"
#include "display/kout.h"
extern real_mode_param_t rm_params; // check if a video mode is activated
int display_type;
int display_activeConsole = -1; // start with no active console
// initialization routine for display subsystem
int display_init()
{
if (!rm_params.vid_addr) // framebuffer mode
{
vconsole_setup(80, 25);
display_activate(KERNEL_MSG_CONSOLE);
display_type = DISPLAY_CONSOLE;
}
else
display_type = DISPLAY_GRAPHICAL;
return 0;
}
// activate the given display
int display_activate(u32_t id)
{
if (id == display_activeConsole)
return 0;
if (display_type != DISPLAY_CONSOLE)
return -1;
if (id >= VCONSOLE_MAX)
return -2;
if (display_activeConsole >= 0)
vconsole_deactivate(display_activeConsole);
if (vconsole_activate(id)) // if true, didn't work to activate console
{
vconsole_activate(display_activeConsole); // restore old one
return -3;
}
display_activeConsole = id;
return 0;
}
void display_key_event(u32_t keyCode)
{
if (display_type == DISPLAY_CONSOLE)
{
u32_t kbdScan = KBD_SCAN(keyCode);
if ( /* kbdFlags & KBDF_ALT && */ kbdScan >= 0x3B && kbdScan <= 0x44) // switch displays F1-F10
{
display_activate(kbdScan - 0x3B);
return;
}
if ( /* kbdFlags & KBDF_ALT && */ kbdScan >= 0x57 && kbdScan <= 0x58) // F11-F12
{
display_activate(kbdScan - 0x4D);
return;
}
if (KBD_ASCII(keyCode))
putc(KBD_ASCII(keyCode));
}
/* TODO: send key to process on active console
or graphical control process */
}

View File

@ -1,28 +0,0 @@
// display.h
// Author: Josh Holtrop
// Date: 08/07/04
// Modified: 03/19/05
#ifndef __HOS_CONSOLE__
#define __HOS_CONSOLE__ __HOS_CONSOLE__
#include "hos_defines.h"
#include "devices.h"
#define DISPLAY_CONSOLE 0
#define DISPLAY_GRAPHICAL 1
typedef struct
{
int type;
minor_t id;
} display_t;
int display_init();
int display_activate(u32_t id);
void display_key_event(u32_t keyCode);
#endif

View File

@ -1,141 +0,0 @@
// kout.c
// Author: Josh Holtrop
// Date: 08/02/04
// Modified: 11/02/05
#include "hos_defines.h"
#include "kout.h"
#include "lang/conv.h"
#include "devices.h"
#include "char/misc_char.h"
#include "functions.h"
char buffer[64]; // for hex/oct/dec/ascii conversion
// print a character
void putc(int c)
{
#ifdef PARALLEL_DEBUG
outportb(0x37a, 0xc);
outportb(0x378, c);
outportb(0x37a, 0x1);
// char_write(MAJOR_MISC_CHAR, MISC_CHAR_LP0, c);
#endif
char_write(MAJOR_VCONSOLE, KERNEL_MSG_CONSOLE, c);
}
// print a formatted string
void kprintf(char *fmt, ...)
{
u32_t *params = ((u32_t *)(&fmt)) + 1; // points to the first paramater
int i;
int special = 0;
for (i = 0; ; i++)
{
if (special)
{
special = 0;
switch (fmt[i])
{
case 0:
return;
case '%':
putc('%');
break;
case 's': case 'S':
puts((char *)*params);
params++;
break;
case 'c': case 'C':
putc(*params);
params++;
break;
case 'd': case 'D': case 'i': case 'I':
putDec(*params);
params++;
break;
case 'u': case 'U':
putDecu(*params);
params++;
break;
case 'x': case 'X':
putHex(*params);
params++;
break;
case 'o': case 'O':
putOct(*params);
params++;
break;
case 'b': case 'B':
kio_putBCD(*params);
params++;
break;
}
}
else
{
switch (fmt[i])
{
case '%':
special = 1;
break;
case 0:
return;
default:
putc(fmt[i]);
}
}
}
}
// This function prints a raw string
void puts(char *str)
{
while (*str)
{
putc(*str++);
}
}
// This function prints a signed, decimal integer
void putDec(int num)
{
itoa(num, buffer);
puts(buffer);
}
// This function prints an unsigned, decimal integer
void putDecu(u32_t num)
{
utoa(num, buffer);
puts(buffer);
}
// This function displays a number in hexadecimal
void putHex(u32_t num)
{
itox(num, buffer);
puts(buffer);
}
// This function displays a number in octal
void putOct(u32_t num)
{
itoo(num, buffer);
puts(buffer);
}
// This function prints a two-digit binary-coded-decimal value
void kio_putBCD(u32_t bcd)
{
bcdtoa(bcd, buffer);
}

View File

@ -1,20 +0,0 @@
// kout.h
// Author: Josh Holtrop
// Date: 08/02/04
#ifndef __HOS_KOUT__
#define __HOS_KOUT__ __HOS_KOUT__
#include "hos_defines.h"
void kprintf(char *fmt, ...);
void putHex(u32_t number);
void kio_putBCD(u32_t bcd);
void putc(int c);
void puts(char *str);
void putDec(int num);
void putDecu(u32_t num);
void putOct(u32_t number);
#endif

View File

@ -1,111 +0,0 @@
// vesafb.c
// Author: Josh Holtrop
// Date: 03/19/05
// Modified: 03/19/05
#include "display/display.h"
#include "display/vesafb.h"
#include "lang/lang.h"
#include "hos_defines.h" // BIOS_CHAR_MAP
u16_t *vmem16 = (u16_t *) VESAFB_VID_ADDR;
u32_t *vmem32 = (u32_t *) VESAFB_VID_ADDR;
int vesafb_bpp;
int vesafb_multiplier;
int vesafb_width; // pixels
int vesafb_height;
int vesafb_xres; // characters
int vesafb_yres;
int vesafb_cursor; // -1 to hide, 0+ for cursor position
int vesafb_init(int width, int height, int bpp)
{
switch(vesafb_bpp = bpp)
{
case 15: case 16:
vesafb_multiplier = 2;
break;
case 24:
vesafb_multiplier = 3;
break;
case 32:
vesafb_multiplier = 4;
break;
}
vesafb_width = width;
vesafb_height = height;
vesafb_xres = (width >> 3) & 0xFFF8; // columns divisible by 8
vesafb_yres = height >> 3;
return vesafb_cursor = 0;
}
void vesafb_clear()
{
memset(vmem32, 0, vesafb_width * vesafb_height * vesafb_multiplier);
vesafb_update_cursor(0);
}
void vesafb_update_cursor(int position)
{
vesafb_draw_cursor(vesafb_cursor, 0);
vesafb_draw_cursor(vesafb_cursor = position, 1);
}
void vesafb_draw_cursor(int position, int onoff)
{
int x = (position % vesafb_xres) << 3;
int y = ( (position / vesafb_xres) << 3 ) + 7;
int i;
for (i = 0; i < 7; i++)
vesafb_pset(x + i, y, onoff);
}
void vesafb_pset(int x, int y, int onoff)
{
switch (vesafb_bpp)
{
case 15: case 16:
*(vmem16 + vesafb_width*y + x) = (onoff ? 0xFFFF : 0);
break;
case 24:
*((u32_t *)(((u32_t)vmem32) + 3*vesafb_width*y + 3*x)) = (onoff ? 0x00FFFFFF : 0);
break;
case 32:
*(vmem32 + vesafb_width*y + x) = (onoff ? 0x00FFFFFF : 0);
break;
}
}
int vesafb_getWidth()
{
return vesafb_xres;
}
int vesafb_getHeight()
{
return vesafb_yres;
}
void vesafb_draw_char(int position, u16_t chr)
{
int x = (position % vesafb_xres) << 3;
int y = (position / vesafb_xres) << 3;
int xi, yi;
u8_t *charMap = (u8_t *) ( BIOS_CHAR_MAP + ((chr & 0xFF) << 3) );
for (yi = 0; yi < 7; yi++)
{
for (xi = 0; xi < 7; xi++)
vesafb_pset(x + xi, y + yi, (*charMap & (0x80 >> xi)));
charMap++;
}
}
int vesafb_draw(u16_t *buffer, int buff_len, int cursor_position)
{
int i;
for (i = 0; i < buff_len; i++)
vesafb_draw_char(i, *buffer++);
vesafb_update_cursor(cursor_position);
return 0;
}

View File

@ -1,25 +0,0 @@
// vesafb.h
// Author: Josh Holtrop
// Date: 03/19/05
// Modified: 03/19/05
#ifndef __HOS_VESAFB__
#define __HOS_VESAFB__ __HOS_VESAFB__
#include "hos_defines.h"
#define VESAFB_VID_ADDR 0xF0000000
int vesafb_init(int width, int height, int bpp);
void vesafb_clear();
void vesafb_update_cursor(int position);
void vesafb_draw_cursor(int position, int onoff);
void vesafb_pset(int x, int y, int onoff);
int vesafb_getWidth();
int vesafb_getHeight();
void vesafb_draw_char(int position, u16_t chr);
int vesafb_draw(u16_t *buffer, int buff_len, int cursor_position);
#endif

View File

@ -1,21 +0,0 @@
// FileSystem.cpp
// Virtual file system subsystem for HOS
// Author: Josh Holtrop
// Date: 06/21/05
// Modified: 06/21/05
#include "vfs.h"
#include "FileSystem.h"
FileSystem::FileSystem() {}
FileSystem::~FileSystem() {}
u32_t FileSystem::totalBlocks() {return 0;}
u32_t FileSystem::freeBlocks() {return 0;}
u32_t FileSystem::totalInodes() {return 0;}
u32_t FileSystem::freeInodes() {return 0;}
u32_t FileSystem::getRootInodeNumber() {return 0;}
OpenDirectory *FileSystem::openDirectory(u32_t inum, int mode) {return NULL;}
OpenFile *FileSystem::openFile(u32_t inum, int mode) {return NULL;}
int FileSystem::stat(u32_t inum, vfs_stat_t *buf) {return -1;}
int FileSystem::link_deref(u32_t inum, char *buf) {return -1;}

View File

@ -1,35 +0,0 @@
// FileSystem.h
// Virtual file system subsystem for HOS
// Author: Josh Holtrop
// Date: 06/21/05
// Modified: 06/21/05
#ifndef __HOS_FILESYSTEM__
#define __HOS_FILESYSTEM__ __HOS_FILESYSTEM__
#include "hos_defines.h"
#include "vfs.h"
#include "OpenDirectory.h"
#include "OpenFile.h"
class FileSystem
{
public:
FileSystem();
virtual ~FileSystem();
virtual u32_t totalBlocks(); /* 512 byte blocks */
virtual u32_t freeBlocks();
virtual u32_t totalInodes();
virtual u32_t freeInodes();
virtual u32_t getRootInodeNumber();
virtual OpenDirectory *openDirectory(u32_t inum, int mode);
virtual OpenFile *openFile(u32_t inum, int mode);
virtual int stat(u32_t inum, vfs_stat_t *buf);
virtual int link_deref(u32_t inum, char *buf);
};
#endif

View File

@ -1,15 +0,0 @@
// OpenDirectory.cpp
// Author: Josh Holtrop
// Date: 12/19/05
#include "vfs.h"
#include "OpenDirectory.h"
#include "lang/string.h"
OpenDirectory::OpenDirectory() {}
OpenDirectory::~OpenDirectory() {}
int OpenDirectory::seek(int pos, int mode) { return -1; }
int OpenDirectory::read(vfs_dir_entry_t *ent) { return -1; }
int OpenDirectory::create(char *name, int mode, u32_t permissions, u32_t dev)
{ return -1; }
int OpenDirectory::unlink(char *name) { return -1; }

View File

@ -1,23 +0,0 @@
// OpenDirectory.h
// Author: Josh Holtrop
// Date: 12/19/05
#ifndef __HOS_OPENDIRECTORY_H__
#define __HOS_OPENDIRECTORY_H__ __HOS_OPENDIRECTORY_H__
#include "vfs.h"
#include "lang/string.h"
class OpenDirectory
{
public:
OpenDirectory();
virtual ~OpenDirectory();
virtual int seek(int pos, int mode);
virtual int read(vfs_dir_entry_t *ent);
virtual int create(char *name, int mode, u32_t permissions, u32_t dev);
virtual int unlink(char *name);
};
#endif

View File

@ -1,13 +0,0 @@
// OpenFile.cpp
// Author: Josh Holtrop
// Date: 12/19/05
#include "OpenFile.h"
OpenFile::OpenFile() {}
OpenFile::~OpenFile() {}
int OpenFile::seek(int pos, int mode) { return -1; }
int OpenFile::read() { return -1; }
int OpenFile::read(void *buf, u32_t num) { return -1; }
int OpenFile::write(int chr) { return -1; }
int OpenFile::write(void *ptr, u32_t num) { return -1; }

View File

@ -1,23 +0,0 @@
// OpenFile.h
// Author: Josh Holtrop
// Date: 12/19/05
#ifndef __HOS_OPENFILE_H__
#define __HOS_OPENFILE_H__ __HOS_OPENFILE_H__
#include "hos_defines.h"
class OpenFile
{
public:
OpenFile();
virtual ~OpenFile();
virtual int seek(int pos, int mode);
virtual int read();
virtual int read(void *buf, u32_t num);
virtual int write(int chr);
virtual int write(void *ptr, u32_t num);
};
#endif

View File

@ -1,39 +0,0 @@
// VFSMount.cpp
// Virtual file system subsystem for HOS
// Author: Josh Holtrop
// Date: 06/21/05
// Modified: 06/21/05
extern "C" {
#include "display/kout.h"
}
#include "vfs.h"
#include "VFSMount.h"
#include "hos_defines.h"
#include "devices.h"
#include "lang/string.h"
VFSMount::VFSMount(device_t dev, string fsType, FileSystem *fs,
string mountPoint,
inode_num_t mountInode, inode_num_t thisInode)
{
myDev = dev;
myFSType = fsType;
myFS = fs;
myMountPoint = mountPoint;
myMountInode = mountInode;
myThisInode = thisInode;
}
VFSMount::~VFSMount()
{
if (umount_safe())
kprintf("Filesystem uncleanly mounted from %s\n", myMountPoint.data());
delete myFS;
}
int VFSMount::umount_safe()
{
return 0;
}

View File

@ -1,31 +0,0 @@
// VFSMount.h
// Virtual file system subsystem for HOS
// Author: Josh Holtrop
// Date: 06/21/05
// Modified: 06/21/05
#ifndef __HOS_VFSMOUNT__
#define __HOS_VFSMOUNT__ __HOS_VFSMOUNT__
#include "lang/string.h"
#include "devices.h"
#include "FileSystem.h"
class VFSMount
{
public:
device_t myDev;
string myFSType;
FileSystem *myFS;
string myMountPoint;
inode_num_t myMountInode;
inode_num_t myThisInode;
VFSMount(device_t dev, string fsType, FileSystem *fs,
string mountPoint,
inode_num_t mountInode, inode_num_t thisInode);
~VFSMount();
int umount_safe();
};
#endif

View File

@ -1,143 +0,0 @@
// Ext2BlockCache.cpp
// Author: Josh Holtrop
// Date: 12/29/05
// Modified: 12/29/05
#include "fs/vfs.h"
#include "Ext2BlockCache.h"
Ext2BlockCache::Ext2BlockCache(Ext2fs *fs, u32_t inum, ext2_inode_t *inode)
{
myFS = fs;
myInum = inum;
myInodeDirty = 0;
myInode = inode;
myBlockSize = 1024 << fs->getSuper()->s_log_block_size;
for (int i = 0; i < 3; i++)
{
myCache[i] = new u8_t[myBlockSize];
myCacheAddress[i] = 0;
myCacheDirty[i] = 0;
}
}
Ext2BlockCache::~Ext2BlockCache()
{
for (int i = 0; i < 3; i++)
{
if (myCacheDirty[i])
myFS->writeBlock(myCacheAddress[i], myCache[i]);
delete[] myCache[i];
}
if (myInodeDirty)
myFS->writeInode(myInum, myInode);
}
int Ext2BlockCache::readBlock(u32_t blockNum, void *buf)
{
u32_t fsblock = getFSBlock(blockNum, 0);
if (fsblock == 0)
return -1;
return myFS->readBlock(fsblock, buf);
}
int Ext2BlockCache::writeBlock(u32_t blockNum, void *buf)
{
u32_t fsblock = getFSBlock(blockNum, 1);
if (fsblock == 0)
return -1;
return myFS->writeBlock(fsblock, buf);
}
void Ext2BlockCache::setCache(u32_t level, u32_t fsblock)
{
if (myCacheAddress[level] == fsblock)
return;
if (myCacheDirty[level])
myFS->writeBlock(myCacheAddress[level], myCache[level]);
myCacheAddress[level] = fsblock;
myCacheDirty[level] = 0;
myFS->readBlock(fsblock, myCache[level]);
}
u32_t Ext2BlockCache::getFSBlock(u32_t blockNum, int create)
{
if (blockNum < 12) /* direct pointer */
{
if (create && myInode->i_block[blockNum] == 0)
{
myInode->i_block[blockNum] = myFS->allocBlock();
myInodeDirty = 1;
}
return myInode->i_block[blockNum];
}
blockNum -= 12;
if (blockNum < myBlockSize) /* i_block[12] */
{
if (create && myInode->i_block[12] == 0)
{
myInode->i_block[12] = myFS->allocBlock();
myInodeDirty = 1;
}
setCache(0, myInode->i_block[12]);
/* blockNum indexes cache 0 */
if (create && myCache[0][blockNum] == 0)
{
myCache[0][blockNum] = myFS->allocBlock();
myCacheDirty[0] = 1;
}
return myCache[0][blockNum];
}
blockNum -= myBlockSize;
if (blockNum < (myBlockSize * myBlockSize)) /* i_block[13] */
{
if (create && myInode->i_block[13] == 0)
{
myInode->i_block[13] = myFS->allocBlock();
myInodeDirty = 1;
}
setCache(0, myInode->i_block[13]);
/* blockNum / myBlockSize indexes cache 0 */
if (create && myCache[0][blockNum / myBlockSize] == 0)
{
myCache[0][blockNum / myBlockSize] = myFS->allocBlock();
myCacheDirty[0] = 1;
}
setCache(1, myCache[0][blockNum / myBlockSize]);
/* blockNum % myBlockSize indexes cache 1 */
if (create && myCache[1][blockNum % myBlockSize] == 0)
{
myCache[1][blockNum % myBlockSize] = myFS->allocBlock();
myCacheDirty[1] = 1;
}
return myCache[1][blockNum % myBlockSize];
}
blockNum -= (myBlockSize * myBlockSize); /* i_block[14] */
if (create && myInode->i_block[14] == 0)
{
myInode->i_block[14] = myFS->allocBlock();
myInodeDirty = 1;
}
setCache(0, myInode->i_block[14]);
/* blockNum / (myBlockSize^2) indexes cache 0 */
if (create && myCache[0][blockNum / (myBlockSize * myBlockSize)] == 0)
{
myCache[0][blockNum / (myBlockSize * myBlockSize)] = myFS->allocBlock();
myCacheDirty[0] = 1;
}
setCache(1, myCache[0][blockNum / (myBlockSize * myBlockSize)]);
/* blockNum / myBlockSize indexes cache 1 */
if (create && myCache[1][blockNum / myBlockSize] == 0)
{
myCache[1][blockNum / myBlockSize] = myFS->allocBlock();
myCacheDirty[1] = 1;
}
setCache(2, myCache[1][blockNum / myBlockSize]);
/* blockNum % myBlockSize indexes cache 2 */
if (create && myCache[2][blockNum % myBlockSize] == 0)
{
myCache[2][blockNum % myBlockSize] = myFS->allocBlock();
myCacheDirty[2] = 1;
}
return myCache[2][blockNum % myBlockSize];
}

View File

@ -1,34 +0,0 @@
// Ext2BlockCache.h
// Author: Josh Holtrop
// Date: 12/29/05
// Modified: 12/29/05
#ifndef __HOS_EXT2BLOCKCACHE_H__
#define __HOS_EXT2BLOCKCACHE_H__ __HOS_EXT2BLOCKCACHE_H__
#include "fs/vfs.h"
#include "ext2.h"
class Ext2BlockCache
{
protected:
Ext2fs *myFS;
u32_t myInum;
ext2_inode_t *myInode;
u32_t myBlockSize;
u8_t *myCache[3];
u8_t myCacheAddress[3];
u8_t myCacheDirty[3];
u32_t myInodeDirty;
void setCache(u32_t level, u32_t fsblock);
u32_t getFSBlock(u32_t block, int create);
public:
Ext2BlockCache(Ext2fs *fs, u32_t inum, ext2_inode_t *inode);
~Ext2BlockCache();
int readBlock(u32_t blockNum, void *buf);
int writeBlock(u32_t blockNum, void *buf);
};
#endif

View File

@ -1,238 +0,0 @@
// Ext2OpenDirectory.cpp
// Author: Josh Holtrop
// Date: 12/26/05
// Modified: 12/26/05
extern "C" {
#include "lang/lang.h"
}
#include "fs/vfs.h"
#include "Ext2OpenDirectory.h"
#include "Ext2OpenFile.h"
#include "ext2.h"
Ext2OpenDirectory::Ext2OpenDirectory(Ext2fs *fs, u32_t inum, int mode)
{
myPosition = 0;
myFS = fs;
myInum = inum;
myMode = mode;
myCache = new Ext2BlockCache(fs, inum, &myInode);
fs->readInode(inum, &myInode);
u32_t size = myInode.i_size;
u32_t logBlockSize = fs->getSuper()->s_log_block_size;
myBlockSize = 1024 << logBlockSize;
if (size % myBlockSize)
size += myBlockSize - (size % myBlockSize);
myBlocks = size >> (10 + logBlockSize);
myBuffer = new u8_t[size];
if ((mode & VFS_MODE_RW_MASK) == VFS_MODE_READ)
readDirectory();
}
/* destroy an open ext2 directory object */
Ext2OpenDirectory::~Ext2OpenDirectory()
{
delete myCache;
delete[] myBuffer;
}
void Ext2OpenDirectory::readDirectory()
{
/* read in the entire directory */
for (u32_t i = 0; i < myBlocks; i++)
myCache->readBlock(i, myBuffer + i * myBlockSize);
}
/* seek absolute or relative, only positive direction */
int Ext2OpenDirectory::seek(int pos, int mode)
{
if (mode == SEEK_ABSOLUTE)
myPosition = 0;
if (pos > 0)
{
while (myPosition < myInode.i_size)
{
ext2_dir_entry_t *de =
(ext2_dir_entry_t *) (myBuffer + myPosition);
myPosition += de->length;
pos--;
if (pos < 1)
return 0;
}
return -1;
}
return -2;
}
/* read a directory entry from the directory */
int Ext2OpenDirectory::read(vfs_dir_entry_t *ent)
{
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_READ)
return -1;
if (myPosition >= myInode.i_size)
return EOF;
ext2_dir_entry_t *de = (ext2_dir_entry_t *) (myBuffer + myPosition);
ent->inum = de->inode;
memcpy(ent->name, de->name, de->name_length);
ent->name[de->name_length] = 0;
myPosition += de->length;
return 0;
}
int Ext2OpenDirectory::create(char *name, int mode, u32_t permissions, u32_t dev)
{
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_WRITE)
return -1;
readDirectory();
myPosition = 0;
u32_t name_length = strlen(name);
while (myPosition < myInode.i_size)
{
ext2_dir_entry_t *de =
(ext2_dir_entry_t *) (myBuffer + myPosition);
if (name_length == de->name_length && !strncmp(name, de->name, name_length))
return -2; /* entry already exists */
myPosition += de->length;
}
u32_t newInode = myFS->allocInode();
if (newInode == 0)
return -3; /* no free inodes! */
/* initialize the inode */
ext2_inode_t in;
memset(&in, 0, sizeof(ext2_inode_t));
u32_t ext2_mode;
switch(mode)
{
case VFS_FT_DIR: ext2_mode = EXT2_I_MODE_DIR; break;
case VFS_FT_CHAR: ext2_mode = EXT2_I_MODE_CHAR;
in.i_block[0] = dev; break;
case VFS_FT_BLOCK: ext2_mode = EXT2_I_MODE_BLOCK;
in.i_block[0] = dev; break;
case VFS_FT_FIFO: ext2_mode = EXT2_I_MODE_FIFO; break;
case VFS_FT_SOCK: ext2_mode = EXT2_I_MODE_SOCK; break;
case VFS_FT_SYMLINK: ext2_mode = EXT2_I_MODE_SYM; break;
case VFS_FT_FILE:
default: ext2_mode = EXT2_I_MODE_FILE; break;
}
in.i_mode = ext2_mode | (permissions & EXT2_I_MODE_ATTR_MASK);
in.i_links_count = 1;
myFS->writeInode(newInode, &in);
if (mode == VFS_FT_DIR)
{
if (myFS->getSuper()->s_free_blocks_count < 3)
return -4; /* out of space on device */
if (myFS->initializeDirectory(newInode, myInum))
return -5; /* error initializing directory */
myInode.i_links_count++;
myFS->writeInode(myInum, &myInode);
}
u32_t entryLength = name_length + 8;
if (entryLength & 0x3)
entryLength = (entryLength + 4) & 0xFFFFFFFC; /* multiple of 4 bytes */
myPosition = 0;
for (;;)
{
ext2_dir_entry_t *de =
(ext2_dir_entry_t *) (myBuffer + myPosition);
u32_t thisEntryLength = de->name_length + 8;
if (thisEntryLength & 0x3)
thisEntryLength = (thisEntryLength + 4) & 0xFFFFFFFC;
if (de->length - thisEntryLength >= entryLength)
{
/* There is room in this entry for the new one */
u32_t newLength = de->length - thisEntryLength;
de->length = thisEntryLength;
u32_t firstPosition = myPosition;
myPosition += de->length;
de = (ext2_dir_entry_t *) (myBuffer + myPosition);
de->length = newLength;
de->name_length = name_length;
de->inode = newInode;
memcpy(de->name, name, name_length);
writeInclusiveRange(firstPosition,
myPosition + entryLength - 1);
return 0;
}
if (myPosition + de->length >= myInode.i_size)
{
if (myFS->getSuper()->s_free_blocks_count < 2)
{
myFS->freeInode(newInode);
return -4; /* out of space on device */
}
/* This is the last entry, we need to add a block */
myBlocks++;
u8_t *newBuffer = new u8_t[myBlockSize * myBlocks];
memcpy(newBuffer, myBuffer, myBlockSize * (myBlocks - 1));
delete[] myBuffer;
myBuffer = newBuffer;
de = (ext2_dir_entry_t *) (myBuffer + myPosition);
u32_t thisEntryLength = de->name_length + 8;
if (thisEntryLength & 0x3)
thisEntryLength = (thisEntryLength + 4) & 0xFFFFFFFC;
u32_t leftovers = de->length - thisEntryLength;
de->length -= leftovers;
u32_t firstPosition = myPosition;
myPosition += thisEntryLength;
de = (ext2_dir_entry_t *) (myBuffer + myPosition);
de->length = myBlockSize + leftovers;
de->name_length = name_length;
de->inode = newInode;
memcpy(de->name, name, name_length);
writeInclusiveRange(firstPosition,
myPosition + myBlockSize + leftovers - 1);
myInode.i_size += myBlockSize;
myFS->writeInode(myInum, &myInode);
return 0;
}
myPosition += de->length;
}
}
void Ext2OpenDirectory::writeInclusiveRange(u32_t first, u32_t last)
{
u32_t firstBlock = first / myBlockSize;
u32_t lastBlock = last / myBlockSize;
for (u32_t i = firstBlock; i <= lastBlock; i++)
myCache->writeBlock(i, myBuffer + i * myBlockSize);
}
int Ext2OpenDirectory::unlink(char *name)
{
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_WRITE)
return -1;
readDirectory();
myPosition = 0;
u32_t lastPosition = 0;
u32_t name_length = strlen(name);
while (myPosition < myInode.i_size)
{
ext2_dir_entry_t *de =
(ext2_dir_entry_t *) (myBuffer + myPosition);
if (name_length == de->name_length && !strncmp(name, de->name, name_length))
{
ext2_inode_t inode;
myFS->readInode(de->inode, &inode);
if ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) == EXT2_I_MODE_DIR)
{
if (myFS->attemptRemoveDir(de->inode))
return -3; /* can't unlink non-empty directory */
}
/* found entry to unlink
add the space to entry at lastPosition */
myFS->unlink(de->inode);
ext2_dir_entry_t *lde =
(ext2_dir_entry_t *) (myBuffer + lastPosition);
lde->length += de->length;
writeInclusiveRange(lastPosition, lastPosition + 8);
return 0;
}
lastPosition = myPosition;
myPosition += de->length;
}
return -2; /* entry not found */
}

View File

@ -1,37 +0,0 @@
// Ext2OpenDirectory.h
// Author: Josh Holtrop
// Date: 12/26/05
// Modified: 12/26/05
#ifndef __HOS_EXT2OPENDIRECTORY__
#define __HOS_EXT2OPENDIRECTORY__ __HOS_EXT2OPENDIRECTORY__
#include "ext2.h"
#include "Ext2BlockCache.h"
class Ext2OpenDirectory : public OpenDirectory
{
private:
u32_t myPosition;
Ext2fs *myFS;
int myMode;
u32_t myInum;
u8_t *myBuffer;
u32_t myBlocks;
u32_t myBlockSize;
Ext2BlockCache *myCache;
ext2_inode_t myInode;
void readDirectory();
void writeInclusiveRange(u32_t first, u32_t last);
public:
Ext2OpenDirectory(Ext2fs *fs, u32_t inum, int mode);
~Ext2OpenDirectory();
int seek(int pos, int mode);
int read(vfs_dir_entry_t *ent);
int create(char *name, int mode, u32_t permissions, u32_t dev);
int unlink(char *name);
};
#endif

View File

@ -1,228 +0,0 @@
// Ext2OpenFile.cpp
// Author: Josh Holtrop
// Date: 12/26/05
// Modified: 12/26/05
#include "Ext2OpenFile.h"
extern "C" {
#include "lang/lang.h"
#include "functions.h"
}
lock_t Ext2OpenFileListLock;
vector<Ext2OpenFileHandle> *Ext2OpenFileList = NULL;
/* make an Ext2OpenFile object
* maintain vector of open files for notifying when one is truncated
*/
Ext2OpenFile::Ext2OpenFile(Ext2fs *fs, u32_t inum, int mode)
{
myMode = mode;
myFS = fs;
myInum = inum;
myBeenTruncated = 0;
myPosition = 0;
myBlockSize = 1024 << fs->getSuper()->s_log_block_size;
myBlockCache = new u8_t[myBlockSize];
myBlockCacheBlock = 0;
myBlockCacheStatus = 0; /* 0: invalid; 1: valid; 2: dirty */
fs->readInode(inum, &myInode);
myCache = new Ext2BlockCache(fs, inum, &myInode);
lock(&Ext2OpenFileListLock);
if ((mode & VFS_MODE_RW_MASK) == VFS_MODE_WRITE)
{
if ((mode & VFS_MODE_WRITE_MASK) == VFS_MODE_TRUNCATE)
{
/* file opened for write/truncate
* tell any open files that it's been truncated, then
* tell ext2 filesystem to free its blocks
*/
u32_t size = Ext2OpenFileList->size();
for (u32_t i = 0; i < size; i++)
{
if ((*Ext2OpenFileList)[i].inode == inum)
(*Ext2OpenFileList)[i].ofile->notifyTruncated();
}
fs->truncateInode(inum);
fs->readInode(inum, &myInode); /* re-read inode */
}
else
myPosition = myInode.i_size;
}
if (Ext2OpenFileList == NULL)
Ext2OpenFileList = new vector<Ext2OpenFileHandle>();
/* add ourselves to the list */
Ext2OpenFileHandle thisHandle = {inum, this};
Ext2OpenFileList->add(thisHandle);
unlock(&Ext2OpenFileListLock);
}
/* destroy an Ext2OpenFile object */
Ext2OpenFile::~Ext2OpenFile()
{
/* remove ourselves from the open file list */
lock(&Ext2OpenFileListLock);
u32_t size = Ext2OpenFileList->size();
for (u32_t i = 0; i < size; i++)
{
if ((*Ext2OpenFileList)[i].ofile == this)
{
Ext2OpenFileList->remove(i);
break;
}
}
unlock(&Ext2OpenFileListLock);
/* write back any open caches if in write mode */
if ( !myBeenTruncated && ((myMode & VFS_MODE_RW_MASK) == VFS_MODE_WRITE) )
{
if (myBlockCacheStatus == 2)
myCache->writeBlock(myBlockCacheBlock, myBlockCache);
myFS->writeInode(myInum, &myInode);
}
/* free the memory we used */
delete myCache;
delete[] myBlockCache;
}
/* seek to a certain position in the file (only for reading) */
int Ext2OpenFile::seek(int pos, int mode)
{
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_READ)
return -1;
if (mode == SEEK_ABSOLUTE)
{
if (pos < 0)
return -2;
if ((u32_t)pos >= myInode.i_size)
return -3;
myPosition = pos;
return 0;
}
else if (mode == SEEK_RELATIVE)
{
if (myPosition + pos < 0)
return -2;
if (myPosition + pos >= myInode.i_size)
return -3;
myPosition += pos;
return 0;
}
else if (mode == SEEK_END)
{
if (myInode.i_size + pos < 0)
return -2;
if (myInode.i_size + pos >= myInode.i_size)
return -3;
myPosition = myInode.i_size + pos;
return 0;
}
return -4;
}
/* read a byte from the current file position, return error code/EOF */
int Ext2OpenFile::read()
{
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_READ)
return -1;
if (myBeenTruncated || myPosition >= myInode.i_size)
return EOF;
u32_t theBlock = myPosition / myBlockSize;
updateCache(theBlock);
return myBlockCache[myPosition++ % myBlockSize];
}
/* read num bytes from the current file position, put in buf
* return: number of bytes read (>=0) or error code (<0)
*/
int Ext2OpenFile::read(void *buf, u32_t num)
{
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_READ)
return -1;
if (myBeenTruncated || myPosition >= myInode.i_size)
return EOF;
if (myPosition + num > myInode.i_size)
num = myInode.i_size - myPosition;
u32_t bytesRead = 0;
u32_t bytesIntoFirstBlock = myPosition % myBlockSize;
if (bytesIntoFirstBlock)
{
updateCache(myPosition / myBlockSize);
bytesRead = min(myBlockSize - bytesIntoFirstBlock, num);
memcpy(buf, myBlockCache + bytesIntoFirstBlock, bytesRead);
myPosition += bytesRead;
}
while (bytesRead < num)
{
updateCache(myPosition / myBlockSize);
u32_t bytesToRead = min(num - bytesRead, myBlockSize);
memcpy((u8_t *)buf + bytesRead, myBlockCache, bytesToRead);
bytesRead += bytesToRead;
myPosition += bytesToRead;
}
return bytesRead;
}
/* write a byte to the current file position */
int Ext2OpenFile::write(int chr)
{
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_WRITE)
return -1;
if (myBeenTruncated)
return EOF;
u32_t theBlock = myPosition / myBlockSize;
updateCache(theBlock);
myBlockCache[myPosition++ % myBlockSize] = chr;
myBlockCacheStatus = 2;
myInode.i_size++;
return 0;
}
/* write num bytes from buf to the current file position
* return: number of bytes written (>=0) or error code (<0)
*/
int Ext2OpenFile::write(void *buf, u32_t num)
{
if (myBeenTruncated)
return -1;
if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_WRITE)
return -2;
u32_t bytesIntoFirstBlock = myPosition % myBlockSize;
u32_t bytesWritten = 0;
if (bytesIntoFirstBlock)
{
updateCache(myPosition / myBlockSize);
bytesWritten = min(myBlockSize - bytesIntoFirstBlock, num);
memcpy(myBlockCache + bytesIntoFirstBlock, buf, bytesWritten);
myBlockCacheStatus = 2;
myPosition += bytesWritten;
}
while (bytesWritten < num)
{
updateCache(myPosition / myBlockSize);
u32_t bytesToWrite = min(num - bytesWritten, myBlockSize);
memcpy(myBlockCache, (u8_t *)buf + bytesWritten, bytesToWrite);
myBlockCacheStatus = 2;
bytesWritten += bytesToWrite;
myPosition += bytesToWrite;
}
myInode.i_size += bytesWritten;
return bytesWritten;
}
void Ext2OpenFile::updateCache(u32_t blockNum)
{
if (myBlockCacheStatus && myBlockCacheBlock == blockNum)
return;
if (myBlockCacheStatus == 2)
myCache->writeBlock(myBlockCacheBlock, myBlockCache);
myCache->readBlock(blockNum, myBlockCache);
myBlockCacheStatus = 1;
myBlockCacheBlock = blockNum;
}
void Ext2OpenFile::notifyTruncated()
{
myBeenTruncated = 1;
}

View File

@ -1,47 +0,0 @@
// Ext2OpenFile.h
// Author: Josh Holtrop
// Date: 12/26/05
// Modified: 12/26/05
#ifndef __HOS_EXT2OPENFILE__
#define __HOS_EXT2OPENFILE__ __HOS_EXT2OPENFILE__
#include "ext2.h"
#include "fs/OpenFile.h"
#include "Ext2BlockCache.h"
class Ext2OpenFile : public OpenFile
{
protected:
Ext2fs *myFS;
u32_t myInum;
int myMode;
int myBeenTruncated; /* set true when the file truncated */
u32_t myPosition;
u32_t myBlockSize;
Ext2BlockCache *myCache;
ext2_inode_t myInode;
u8_t *myBlockCache;
u32_t myBlockCacheBlock;
int myBlockCacheStatus; /* 0: invalid; 1: valid; 2: dirty */
void updateCache(u32_t blockNum);
public:
Ext2OpenFile(Ext2fs *fs, u32_t inum, int mode);
~Ext2OpenFile();
int seek(int pos, int mode);
int read();
int read(void *buf, u32_t num);
int write(int chr);
int write(void *buf, u32_t num);
void notifyTruncated();
};
typedef struct
{
u32_t inode;
Ext2OpenFile *ofile;
} Ext2OpenFileHandle;
#endif

View File

@ -1,599 +0,0 @@
// ext2.cpp
// ext2 filesystem driver for HOS
// Author: Josh Holtrop
// Date: 05/10/05
// Modified: 05/10/05
/* example ext2 filesystem block group structure containing superblock and group descriptors:
* block offset description #blocks
* ------------ ----------- -------
* 0 superblock 1
* 1 group descriptors gd_blocks = ceil(ceil[s_blocks_count / s_blocks_per_group] / (1024 >> [5 - s_log_block_size]))
* gd_blocks+1 block bitmap block 1
* gd_blocks+2 inode bitmap block 1
* gd_blocks+3 inode table itblocks = ceil[s_inodes_per_group / (1024 >> [7 - s_log_block_size])]
* gd_blocks+3+itblocks data blocks s_blocks_per_group - gd_blocks - itblocks - 3
*/
extern "C" {
#include "display/kout.h"
#include "mm/vmm.h"
#include "lang/lang.h"
}
#include "ext2.h"
#include "Ext2OpenDirectory.h"
#include "Ext2OpenFile.h"
/* initialize the ext2 filesystem driver */
int ext2_init()
{
vfs_register("ext2", ext2__mount_func);
return 0;
}
/* a function to mount an ext2 filesystem and return a pointer to it */
FileSystem *ext2__mount_func(device_t dev)
{
ext2_super_block_t *super =
(ext2_super_block_t *) New(ext2_super_block_t);
if ( (block_read(DEV_MAJOR(dev), DEV_MINOR(dev), 2, 2, super) < 1024)
|| (super->s_magic != EXT2_MAGIC) )
{
kfree(super);
return NULL;
}
Ext2fs *fs = new Ext2fs(super, dev);
kfree(super);
return fs;
}
/* constructor for an actual ext2 filesystem object */
Ext2fs::Ext2fs(ext2_super_block_t *super, device_t dev)
{
myDevice = dev;
memcpy(&mySuper, super, sizeof(ext2_super_block_t));
mySuperDirty = 0;
myNumGroups = /* ceil[blocks_count / blocks_per_group] */
(mySuper.s_blocks_count + mySuper.s_blocks_per_group - 1)
/ mySuper.s_blocks_per_group;
myGroupDescriptorsPerBlock = 1024 >> (5 - mySuper.s_log_block_size);
myGroupDescriptorBlocks = /* ceil[num_groups / groupDescriptorsPerBlock] */
(myNumGroups + myGroupDescriptorsPerBlock - 1)
/ myGroupDescriptorsPerBlock;
myInodesPerBlock = 1024 >> (7 - mySuper.s_log_block_size);
myInodeTableBlocks = /* ceil[inodes_per_group / inodePerBlock] */
(mySuper.s_inodes_per_group + myInodesPerBlock - 1)
/ myInodesPerBlock;
/* test/debug code */
/* kprintf("free blocks: %u\n", mySuper.s_free_blocks_count);
OpenDirectory *od = openDirectory(2, VFS_MODE_WRITE);
kprintf("TEST: %d\n", od->unlink("link"));
kprintf("TEST: %d\n", od->create("test", VFS_FT_FILE, 0640, 0));
kprintf("TEST: %d\n", od->create("Block File baby", VFS_FT_BLOCK, 0666, 5 << 8 | 3));
kprintf("TEST: %d\n", od->unlink("bin"));
kprintf("TEST: %d\n", od->create("Character-File", VFS_FT_CHAR, 0644, 130 << 8 | 42));
kprintf("free blocks: %u\n", mySuper.s_free_blocks_count);
kprintf("TEST: %d\n", od->create("a directory", VFS_FT_DIR, 0755, 0));
kprintf("free blocks: %u\n", mySuper.s_free_blocks_count);
delete od;
*/
}
/* this destructor destroys an ext2 filesystem that was mounted */
Ext2fs::~Ext2fs()
{
if (mySuperDirty)
block_write(DEV_MAJOR(myDevice), DEV_MINOR(myDevice), 2, 2, &mySuper);
}
/* return the total number of 512-blocks on the filesystem */
u32_t Ext2fs::totalBlocks()
{
return mySuper.s_blocks_count << (mySuper.s_log_block_size + 1);
}
/* return the number of free 512-blocks on the filesystem */
u32_t Ext2fs::freeBlocks()
{
return mySuper.s_free_blocks_count << (mySuper.s_log_block_size + 1);
}
/* return the total number of inodes on the filesystem */
u32_t Ext2fs::totalInodes()
{
return mySuper.s_inodes_count;
}
/* return the free number of inodes on the filesystem */
u32_t Ext2fs::freeInodes()
{
return mySuper.s_free_inodes_count;
}
/* ext2 filesystems always have a root-directory inode number of 2 */
u32_t Ext2fs::getRootInodeNumber()
{
return 2;
}
/* open a directory */
OpenDirectory *Ext2fs::openDirectory(u32_t inum, int mode)
{
ext2_inode_t inode;
readInode(inum, &inode);
if ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) == EXT2_I_MODE_DIR)
return new Ext2OpenDirectory(this, inum, mode);
return NULL;
}
/* open a file */
OpenFile *Ext2fs::openFile(u32_t inum, int mode)
{
ext2_inode_t inode;
readInode(inum, &inode);
if ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) == EXT2_I_MODE_FILE)
return new Ext2OpenFile(this, inum, mode);
return NULL;
}
/* stat an inode */
int Ext2fs::stat(u32_t inum, vfs_stat_t *buf)
{
ext2_inode_t inode;
if (readInode(inum, &inode))
return -1;
buf->dev = 0;
switch(inode.i_mode & EXT2_I_MODE_TYPE_MASK)
{
case EXT2_I_MODE_FIFO: buf->type = VFS_FT_FIFO; break;
case EXT2_I_MODE_CHAR: buf->type = VFS_FT_CHAR;
buf->dev = inode.i_block[0]; break;
case EXT2_I_MODE_DIR: buf->type = VFS_FT_DIR; break;
case EXT2_I_MODE_BLOCK: buf->type = VFS_FT_BLOCK;
buf->dev = inode.i_block[0]; break;
case EXT2_I_MODE_FILE: buf->type = VFS_FT_FILE; break;
case EXT2_I_MODE_SYM: buf->type = VFS_FT_SYMLINK; break;
case EXT2_I_MODE_SOCK: buf->type = VFS_FT_SOCK; break;
default: buf->type = VFS_FT_UNKNOWN;
}
buf->size = inode.i_size;
buf->inode = inum;
buf->permissions = inode.i_mode & EXT2_I_MODE_ATTR_MASK;
buf->uid = inode.i_uid;
buf->gid = inode.i_gid;
buf->atime = inode.i_atime;
buf->mtime = inode.i_mtime;
buf->ctime = inode.i_ctime;
buf->links = inode.i_links_count;
return 0;
}
/* dereference a symbolink link */
int Ext2fs::link_deref(u32_t inum, char *buf)
{
ext2_inode_t inode;
if (readInode(inum, &inode))
return -1; /* Couldn't read inode */
if ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_SYM)
return -2;
if (inode.i_size > VFS_MAX_PATH_LENGTH)
return -3;
if (inode.i_size < 61)
{
memcpy(buf, inode.i_block, inode.i_size);
buf[inode.i_size] = 0;
return 0;
}
char *block = new char[1024 << mySuper.s_log_block_size];
readBlock(inode.i_block[0], block);
memcpy(buf, block, inode.i_size);
buf[inode.i_size] = 0;
delete[] block;
return 0;
}
/*************************** internal functions ***************************/
/* read an inode from the disk into memory */
int Ext2fs::readInode(u32_t inum, ext2_inode_t *buf)
{
if (inodeStatus(inum) != 1)
return -1;
inum--; /* turn inode number into a 0-based index */
u32_t group = inum / mySuper.s_inodes_per_group;
u32_t index = inum % mySuper.s_inodes_per_group;
ext2_group_desc_t group_desc;
readGroupDescriptor(group, &group_desc);
ext2_inode_t *inode_block = new ext2_inode_t[8 << mySuper.s_log_block_size];
readBlock(group_desc.bg_inode_table +
(index >> (3 + mySuper.s_log_block_size)), inode_block);
u32_t inode_block_index = index % (8 << mySuper.s_log_block_size);
memcpy(buf, inode_block + inode_block_index, sizeof(ext2_inode_t));
delete[] inode_block;
return 0;
}
/* write an inode from memory onto the disk */
int Ext2fs::writeInode(u32_t inum, ext2_inode_t *buf)
{
if (inodeStatus(inum) != 1)
return -1;
inum--; /* turn inode number into a 0-based index */
u32_t group = inum / mySuper.s_inodes_per_group;
u32_t index = inum % mySuper.s_inodes_per_group;
ext2_group_desc_t group_desc;
readGroupDescriptor(group, &group_desc);
ext2_inode_t *inode_block = new ext2_inode_t[8 << mySuper.s_log_block_size];
u32_t block_num = group_desc.bg_inode_table +
(index >> (3 + mySuper.s_log_block_size));
readBlock(block_num, inode_block);
u32_t inode_block_index = index % (8 << mySuper.s_log_block_size);
memcpy(inode_block + inode_block_index, buf, sizeof(ext2_inode_t));
writeBlock(block_num, inode_block);
delete[] inode_block;
return 0;
}
/* read the group descriptor for a given group number */
int Ext2fs::readGroupDescriptor(u32_t group, ext2_group_desc_t *buf)
{
if (group >= myNumGroups)
return -1;
ext2_group_desc_t *gd_block =
new ext2_group_desc_t[myGroupDescriptorsPerBlock];
readBlock(mySuper.s_first_data_block + 1 +
(group / myGroupDescriptorsPerBlock), gd_block);
memcpy(buf, gd_block + (group % myGroupDescriptorsPerBlock),
sizeof(ext2_group_desc_t));
delete[] gd_block;
return 0;
}
/* write the group descriptor for a given group number */
int Ext2fs::writeGroupDescriptor(u32_t group, ext2_group_desc_t *buf)
{
if (group >= myNumGroups)
return -1;
ext2_group_desc_t *gd_block =
new ext2_group_desc_t[myGroupDescriptorsPerBlock];
u32_t block_num = mySuper.s_first_data_block + 1 +
(group / myGroupDescriptorsPerBlock);
readBlock(block_num, gd_block);
memcpy(gd_block + (group % myGroupDescriptorsPerBlock), buf,
sizeof(ext2_group_desc_t));
writeBlock(block_num, gd_block);
delete[] gd_block;
return 0;
}
/* read a data block from the block device */
int Ext2fs::readBlock(u32_t blockNum, void *buf)
{
return block_read(DEV_MAJOR(myDevice), DEV_MINOR(myDevice),
blockNum << (mySuper.s_log_block_size + 1),
2 << mySuper.s_log_block_size,
buf);
}
/* write a data block to the block device */
int Ext2fs::writeBlock(u32_t blockNum, void *buf)
{
return block_write(DEV_MAJOR(myDevice), DEV_MINOR(myDevice),
blockNum << (mySuper.s_log_block_size + 1),
2 << mySuper.s_log_block_size,
buf);
}
/* check the status of an inode (1-based inode number)
* -1: invalid inode number
* 0: free inode
* 1: allocated (used) inode
*/
int Ext2fs::inodeStatus(u32_t inum)
{
if (inum < 1 || inum > mySuper.s_inodes_count)
return -1; /* invalid inode number */
inum--; /* turn inode number into a 0-based index */
u32_t group = inum / mySuper.s_inodes_per_group;
u32_t index = inum % mySuper.s_inodes_per_group;
ext2_group_desc_t group_desc;
readGroupDescriptor(group, &group_desc);
u8_t *bitmap_block = new u8_t[1024 << mySuper.s_log_block_size];
readBlock(group_desc.bg_inode_bitmap +
(index >> (13 + mySuper.s_log_block_size)), bitmap_block);
u32_t bitmap_index = index % (8192 << mySuper.s_log_block_size);
int inode_status = (bitmap_block[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1;
delete[] bitmap_block;
return inode_status;
}
/* check the status of a block
* -1: invalid block number
* 0: free block
* 1: allocated (used) block
*/
int Ext2fs::blockStatus(u32_t bnum)
{
if (bnum < mySuper.s_first_data_block)
return 1;
if (bnum >= mySuper.s_blocks_count)
return -1; /* invalid inode number */
bnum -= mySuper.s_first_data_block;
u32_t group = bnum / mySuper.s_blocks_per_group;
u32_t index = bnum % mySuper.s_blocks_per_group;
ext2_group_desc_t group_desc;
readGroupDescriptor(group, &group_desc);
u8_t *bitmap_block = new u8_t[1024 << mySuper.s_log_block_size];
readBlock(group_desc.bg_block_bitmap +
(index >> (13 + mySuper.s_log_block_size)), bitmap_block);
u32_t bitmap_index = index % (8192 << mySuper.s_log_block_size);
int block_status = (bitmap_block[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1;
delete[] bitmap_block;
return block_status;
}
/* allocate an inode, return number (0 on failure) */
u32_t Ext2fs::allocInode()
{
ext2_group_desc_t gd;
for (unsigned int bg = 0; bg < myNumGroups; bg++)
{
readGroupDescriptor(bg, &gd);
if (gd.bg_free_inodes_count)
{
u32_t index = allocFromBitmap(gd.bg_inode_bitmap,
mySuper.s_inodes_per_group);
if (index == 0xFFFFFFFF)
return 0;
gd.bg_free_inodes_count--;
writeGroupDescriptor(bg, &gd);
mySuper.s_free_inodes_count--;
mySuperDirty = 1;
return (bg * mySuper.s_inodes_per_group) + index + 1;
}
}
return 0;
}
/* allocate a block, return number (0 on failure) */
u32_t Ext2fs::allocBlock()
{
ext2_group_desc_t gd;
for (unsigned int bg = 0; bg < myNumGroups; bg++)
{
readGroupDescriptor(bg, &gd);
if (gd.bg_free_blocks_count)
{
u32_t index = allocFromBitmap(gd.bg_block_bitmap,
mySuper.s_blocks_per_group);
if (index == 0xFFFFFFFF)
return 0;
gd.bg_free_blocks_count--;
writeGroupDescriptor(bg, &gd);
mySuper.s_free_blocks_count--;
mySuperDirty = 1;
return (bg * mySuper.s_blocks_per_group) + index +
mySuper.s_first_data_block;
}
}
return 0;
}
/* free an inode, return error code */
int Ext2fs::freeInode(u32_t inum)
{
if (inum < 11 || inum > mySuper.s_inodes_count)
return -1;
if (inodeStatus(inum) != 1)
return -2;
inum--; /* now 0-based */
ext2_group_desc_t gd;
u32_t group_num = inum / mySuper.s_inodes_per_group;
readGroupDescriptor(group_num, &gd);
freeFromBitmap(gd.bg_inode_bitmap, inum % mySuper.s_inodes_per_group);
gd.bg_free_inodes_count++;
mySuper.s_free_inodes_count++;
mySuperDirty = 1;
writeGroupDescriptor(group_num, &gd);
return 0;
}
/* free a block, return error code */
int Ext2fs::freeBlock(u32_t bnum)
{
if (bnum < mySuper.s_first_data_block || bnum >= mySuper.s_blocks_count)
return -1;
if (blockStatus(bnum) != 1)
return -2;
bnum -= mySuper.s_first_data_block; /* now 0-based */
ext2_group_desc_t gd;
u32_t group_num = bnum / mySuper.s_blocks_per_group;
readGroupDescriptor(group_num, &gd);
freeFromBitmap(gd.bg_block_bitmap, bnum % mySuper.s_blocks_per_group);
gd.bg_free_blocks_count++;
mySuper.s_free_blocks_count++;
mySuperDirty = 1;
writeGroupDescriptor(group_num, &gd);
return 0;
}
/* allocate a node from a bitmap, return the index, 0xFFFFFFFF on failure */
u32_t Ext2fs::allocFromBitmap(u32_t blockNum, u32_t maxBits)
{
u8_t *block = new u8_t[1024 << mySuper.s_log_block_size];
u8_t *blockPtr = block;
u32_t maxBytes = (maxBits + 7) >> 3;
readBlock(blockNum, block);
for (u32_t idx = 0; idx < maxBytes; idx++)
{
if (*blockPtr != 0xFF)
{
for (u32_t bit = 0; bit < 8; bit++)
{
if ( !((*blockPtr) & (1 << bit)) )
{
u32_t nodeIndex = (idx << 3) + bit;
if (nodeIndex < maxBits)
{
*blockPtr |= (1 << bit);
writeBlock(blockNum, block);
return nodeIndex;
}
return 0xFFFFFFFF;
}
}
break;
}
blockPtr++;
}
delete[] block;
return 0xFFFFFFFF;
}
/* free a node from a bitmap */
void Ext2fs::freeFromBitmap(u32_t blockNum, u32_t node)
{
u8_t *block = new u8_t[1024 << mySuper.s_log_block_size];
readBlock(blockNum, block);
u8_t *blockPtr = block + (node >> 3);
*blockPtr &= ((1 << (node & 0x7)) ^ 0xFF);
writeBlock(blockNum, block);
delete[] block;
}
/* unlink an inode:
* decrement i_links_count
* if it is zero, free the inode
* if not, write the inode back
*/
void Ext2fs::unlink(u32_t inum)
{
ext2_inode_t inode;
readInode(inum, &inode);
inode.i_links_count--;
if (inode.i_links_count)
{
writeInode(inum, &inode);
return;
}
truncateInode(inum);
freeInode(inum);
}
int Ext2fs::attemptRemoveDir(u32_t inum)
{
vfs_dir_entry_t dentry, dentry2;
OpenDirectory *od = openDirectory(inum, VFS_MODE_READ);
if (od->read(&dentry))
{
delete od;
return -1;
}
if (od->read(&dentry2))
{
delete od;
return -1;
}
if (!od->read(&dentry))
{
delete od;
return -1;
}
delete od;
unlink(dentry.inum);
unlink(dentry2.inum);
return 0;
}
void Ext2fs::truncateInode(u32_t inum)
{
ext2_inode_t inode;
readInode(inum, &inode);
if ( ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_DIR) &&
((inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_FILE) )
return;
for (int i = 0; i < 12; i++)
if (inode.i_block[i])
freeBlock(inode.i_block[i]);
u32_t entriesPerBlock = 256 << mySuper.s_log_block_size;
u32_t *block = new u32_t[entriesPerBlock];
if (inode.i_block[12])
{
readBlock(inode.i_block[12], block);
for (u32_t i = 0; i < entriesPerBlock; i++)
if (block[i])
freeBlock(block[i]);
freeBlock(inode.i_block[12]);
}
if (inode.i_block[13])
{
readBlock(inode.i_block[13], block);
u32_t *block2 = new u32_t[entriesPerBlock];
for (u32_t i = 0; i < entriesPerBlock; i++)
if (block[i])
{
readBlock(block[i], block2);
for (u32_t j = 0; j < entriesPerBlock; j++)
if (block2[j])
freeBlock(block2[j]);
freeBlock(block[i]);
}
delete[] block2;
freeBlock(inode.i_block[13]);
}
if (inode.i_block[14])
{
readBlock(inode.i_block[14], block);
u32_t *block2 = new u32_t[entriesPerBlock];
u32_t *block3 = new u32_t[entriesPerBlock];
for (u32_t i = 0; i < entriesPerBlock; i++)
if (block[i])
{
readBlock(block[i], block2);
for (u32_t j = 0; j < entriesPerBlock; j++)
if (block2[j])
{
readBlock(block2[j], block3);
for (u32_t k = 0; k < entriesPerBlock; k++)
if (block3[k])
freeBlock(block3[k]);
freeBlock(block2[j]);
}
freeBlock(block[i]);
}
delete[] block2;
delete[] block3;
freeBlock(inode.i_block[14]);
}
delete[] block;
for (int i = 0; i < 15; i++)
inode.i_block[i] = 0;
inode.i_size = 0;
inode.i_blocks = 0;
writeInode(inum, &inode);
}
int Ext2fs::initializeDirectory(u32_t inum, u32_t parent)
{
ext2_inode_t inode;
readInode(inum, &inode);
if ( !(inode.i_block[0] = allocBlock()) )
return -1;
u8_t *buffer = new u8_t[1024 << mySuper.s_log_block_size];
ext2_dir_entry_t *de = (ext2_dir_entry_t *) buffer;
de->name_length = 1;
de->length = 12;
de->inode = inum;
memcpy(de->name, ".", 1);
de = (ext2_dir_entry_t *) (buffer + 12);
de->name_length = 2;
de->length = (1024 << mySuper.s_log_block_size) - 12;
de->inode = parent;
memcpy(de->name, "..", 2);
delete[] buffer;
return 0;
}

View File

@ -1,204 +0,0 @@
// ext2.h
// ext2 filesystem driver for HOS
// Author: Josh Holtrop
// Date: 05/10/05
// Modified: 05/23/05
#ifndef __HOS_EXT2_H__
#define __HOS_EXT2_H__ __HOS_EXT2_H__
#define EXT2_MAGIC 0xEF53
#define EXT2_NAME_LEN 255
#define EXT2_I_MODE_ATTR_MASK 0x0FFF
#define EXT2_I_MODE_OX 0x0001
#define EXT2_I_MODE_OW 0x0002
#define EXT2_I_MODE_OR 0x0004
#define EXT2_I_MODE_GX 0x0008
#define EXT2_I_MODE_GW 0x0010
#define EXT2_I_MODE_GR 0x0020
#define EXT2_I_MODE_UX 0x0040
#define EXT2_I_MODE_UW 0x0080
#define EXT2_I_MODE_UR 0x0100
#define EXT2_I_MODE_STICKY 0x0200
#define EXT2_I_MODE_SGID 0x0400
#define EXT2_I_MODE_SUID 0x0800
#define EXT2_I_MODE_TYPE_MASK 0xF000
#define EXT2_I_MODE_FIFO 0x1000
#define EXT2_I_MODE_CHAR 0x2000
#define EXT2_I_MODE_DIR 0x4000
#define EXT2_I_MODE_BLOCK 0x6000
#define EXT2_I_MODE_FILE 0x8000
#define EXT2_I_MODE_SYM 0xA000
#define EXT2_I_MODE_SOCK 0xC000
#define EXT2_I_FLAGS_SEC_DEL 0x01
#define EXT2_I_FLAGS_UNDELETE 0x02
#define EXT2_I_FLAGS_COMPRESS 0x04
#define EXT2_I_FLAGS_SYNC 0x08
#define EXT2_I_FLAGS_IMMUTABLE 0x10
#define EXT2_I_FLAGS_APPEND 0x20
#define EXT2_I_FLAGS_NODUMP 0x40
/* ext2 standard inode numbers */
#define EXT2_INODE_BAD_BLOCKS 1
#define EXT2_INODE_ROOT 2
#define EXT2_INODE_ACL_INDEX 3
#define EXT2_INODE_ACL_DATA 4
#define EXT2_INODE_BOOT_LOADER 5
#define EXT2_INODE_UNDELETE_DIR 6
#define EXT2_INODE_AVAIL 11
/* The directory entry file type field values */
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHAR 3
#define EXT2_FT_BLOCK 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
#include "fs/vfs.h"
typedef struct
{
u32_t s_inodes_count; /* Inodes count */
u32_t s_blocks_count; /* Blocks count */
u32_t s_r_blocks_count; /* Reserved blocks count */
u32_t s_free_blocks_count; /* Free blocks count */
u32_t s_free_inodes_count; /* Free inodes count */
u32_t s_first_data_block; /* First Data Block */
u32_t s_log_block_size; /* Block size: 0->1024, 1->2048, 2->4096 */
int s_log_frag_size; /* Fragment size */
u32_t s_blocks_per_group; /* # Blocks per group */
u32_t s_frags_per_group; /* # Fragments per group */
u32_t s_inodes_per_group; /* # Inodes per group */
u32_t s_mtime; /* Mount time */
u32_t s_wtime; /* Write time */
u16_t s_mnt_count; /* Mount count */
short s_max_mnt_count; /* Maximal mount count */
u16_t s_magic; /* Magic signature */
u16_t s_state; /* File system state */
u16_t s_errors; /* Behaviour when detecting errors */
u16_t s_minor_rev_level; /* minor revision level */
u32_t s_lastcheck; /* time of last check */
u32_t s_checkinterval; /* max. time between checks */
u32_t s_creator_os; /* OS */
u32_t s_rev_level; /* Revision level */
u16_t s_def_resuid; /* Default uid for reserved blocks */
u16_t s_def_resgid; /* Default gid for reserved blocks */
u32_t s_reserved[235];
} ext2_super_block_t;
typedef struct
{
u32_t bg_block_bitmap; // Blocks bitmap block
u32_t bg_inode_bitmap; // Inode bitmap block
u32_t bg_inode_table; // Inode table block
u16_t bg_free_blocks_count; // Free blocks count
u16_t bg_free_inodes_count; // Free Inodes count
u16_t bg_used_dirs_count; // Directories count
u16_t bg_pad1;
u32_t bg_reserved[3];
} ext2_group_desc_t;
typedef struct
{
u16_t i_mode; // File mode
u16_t i_uid; // Owner UID
u32_t i_size; // Size in bytes
u32_t i_atime; // Access time
u32_t i_ctime; // Creation time
u32_t i_mtime; // Modification time
u32_t i_dtime; // Deletion time
u16_t i_gid; // Group ID
u16_t i_links_count; // Links count
u32_t i_blocks; // Disk Blocks count (512)
u32_t i_flags; // File flags
u32_t i_reserved1;
u32_t i_block[15]; // Pointers to blocks (12 direct, single, double, triple indirect)
u32_t i_version; // File version (for NFS)
u32_t i_file_acl; // File ACL
u32_t i_dir_acl; // Directory ACL
u32_t i_faddr; // Fragment address
u8_t i_frag; // Fragment number
u8_t i_fsize; // Fragment size
u16_t i_pad1;
u32_t i_reserved2[2];
} ext2_inode_t;
typedef struct
{
u32_t inode; // inode number
u16_t length; // directory entry length
u8_t name_length; // name length
u8_t file_type; // File type (used???)
char name[EXT2_NAME_LEN];
} ext2_dir_entry_t;
#ifdef _HOS_CPP_
int ext2_init();
FileSystem *ext2__mount_func(device_t dev);
class Ext2fs : public FileSystem
{
protected:
/* my data members */
device_t myDevice;
int mySuperDirty;
ext2_super_block_t mySuper;
u32_t myNumGroups;
u32_t myGroupDescriptorBlocks;
u32_t myInodeTableBlocks;
u32_t myGroupDescriptorsPerBlock;
u32_t myInodesPerBlock;
/* my functions */
int readGroupDescriptor(u32_t group, ext2_group_desc_t *buf);
int writeGroupDescriptor(u32_t group, ext2_group_desc_t *buf);
int inodeStatus(u32_t inum);
int blockStatus(u32_t bnum);
u32_t allocFromBitmap(u32_t blockNum, u32_t max);
void freeFromBitmap(u32_t blockNum, u32_t node);
public:
Ext2fs(ext2_super_block_t *super, device_t dev);
~Ext2fs();
u32_t totalBlocks();
u32_t freeBlocks();
u32_t totalInodes();
u32_t freeInodes();
u32_t getRootInodeNumber();
OpenDirectory *openDirectory(u32_t inum, int mode);
OpenFile *openFile(u32_t inum, int mode);
int stat(u32_t inum, vfs_stat_t *buf);
int readBlock(u32_t blockNum, void *buf);
int writeBlock(u32_t blockNum, void *buf);
int link_deref(u32_t inum, char *buf);
int readInode(u32_t inum, ext2_inode_t *buf);
int writeInode(u32_t inum, ext2_inode_t *buf);
u32_t allocInode();
u32_t allocBlock();
int freeInode(u32_t inum);
int freeBlock(u32_t bnum);
void unlink(u32_t inum);
int attemptRemoveDir(u32_t inum);
void truncateInode(u32_t inum);
int initializeDirectory(u32_t inum, u32_t parent);
/* inlined functions */
inline u32_t numGroups() { return myNumGroups; }
inline u32_t groupDescriptorBlocks() { return myGroupDescriptorBlocks; }
inline u32_t inodeTableBlocks() { return myInodeTableBlocks; }
inline ext2_super_block_t *getSuper() { return &mySuper; }
};
#endif
#endif

View File

@ -1,762 +0,0 @@
// ext2.c
// Author: Josh Holtrop
// Date: 08/22/04
// Modified: 12/24/04
#include "hos_defines.h"
#include "fs/devices.h"
#include "display/kout.h"
#include "ext2.h"
#include "mm/vmm.h"
#include "fs/vfs.h"
#include "lang/lang.h"
#include "functions.h"
/* Turning an inode number into a (group, inode_index) pair:
* group = (inode - 1) / s_inodes_per_group
* index = (inode - 1) % s_inodes_per_group
*/
vfs_fs_t ext2_driver = {ext2_mount_super, ext2_umount_super, ext2_stat,
ext2__get_root_dir_inode, ext2__link_deref,
ext2__free_inodes, ext2__total_inodes,
ext2__free_blocks, ext2__total_blocks,
ext2_alloc_inode, ext2_free_inode, ext2_alloc_block, ext2_free_block,
ext2__open_dir, ext2__read_dir, ext2__close_dir,
ext2__open_file, ext2__read_file, ext2__close_file,
ext2__open_block_file, ext2__read_block_file, ext2__block_file_seek, ext2__close_block_file};
// initialize the filesystem driver
int ext2_init(int fsID)
{
vfs_fs_t *fs;
if (( fs = New(vfs_fs_t) )) // give the VFS our FS structure
{
*fs = ext2_driver;
vfs_register_fs(fsID, fs);
return 0;
}
return -1;
}
// lookup a file name in a directory and store the directory entry for it
int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry)
{
ext2_open_dir_t *dir = ext2_open_dir(mount, dir_inode);
if (!dir)
return -1; // bad directory inode number
ext2_dir_entry_t dentry;
while (!ext2_dir_read_entry(mount, dir, &dentry))
{
char *dentryName = kcalloc(1, dentry.name_length + 1);
memcpy(dentryName, dentry.name, dentry.name_length);
int res = strcmp(fileName, dentryName);
kfree(dentryName);
if (!res)
{
*direntry = dentry;
ext2_close_dir(mount, dir);
return 0;
}
}
ext2_close_dir(mount, dir);
return -2;
}
// open a directory by inode number for reading
ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number)
{
ext2_open_dir_t *open_dir = New(ext2_open_dir_t);
ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number);
if (!open_inode)
{
kfree(open_dir);
return NULL;
}
if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_DIR)
{
ext2_close_inode(mount, open_inode);
kfree(open_dir);
return NULL;
}
open_dir->open_inode = open_inode;
open_dir->position = 0;
return open_dir;
}
int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry)
{
ext2_super_block_t *super = mount->super;
if (open_dir->position >= open_dir->open_inode->inode.i_size)
return -1; // EOF
u32_t dir_block = open_dir->position >> (10 + super->s_log_block_size);
char *block = kmalloc(2048 << super->s_log_block_size);
ext2_inode_seek(mount, open_dir->open_inode, dir_block);
if (ext2_read_inode_block(mount, open_dir->open_inode, block))
ext2_read_inode_block(mount, open_dir->open_inode, block + (1024 << super->s_log_block_size));
ext2_dir_entry_t *dir_entry = (ext2_dir_entry_t *)(block + open_dir->position % (1024 << super->s_log_block_size));
if (!dir_entry->inode)
{
kfree(block);
return -2; // EOF
}
memcpy(dentry, dir_entry, min(dir_entry->length, sizeof(ext2_dir_entry_t)));
open_dir->position += dir_entry->length;
kfree(block);
return 0;
}
int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir)
{
ext2_close_inode(mount, open_dir->open_inode);
kfree(open_dir);
return 0;
}
// open an inode for reading
ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number)
{
ext2_open_inode_t *open_inode = New(ext2_open_inode_t);
if ( ext2_read_inode(mount, inode_number, &(open_inode->inode)) )
{
kfree(open_inode);
return NULL;
}
open_inode->block = 0;
open_inode->block_pointers = NULL;
open_inode->block_pointers_start = 0;
mount->refs++;
return open_inode;
}
// seek to a certain block of an open inode
int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number)
{
ext2_super_block_t *super = mount->super;
if (open_inode->inode.i_size <= (block_number << (10 + super->s_log_block_size)))
return -1; // at or past EOF
open_inode->block = block_number;
return 0;
}
// returns number of bytes read
int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block)
{
ext2_super_block_t *super = mount->super;
if (open_inode->inode.i_size <= (open_inode->block << (10 + super->s_log_block_size)))
return 0; // at or past EOF
u32_t leftover_bytes = open_inode->inode.i_size - (open_inode->block << (10 + super->s_log_block_size));
u32_t block_number = ext2_block_number(mount, open_inode);
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_number, super),
2 << super->s_log_block_size, block);
open_inode->block++;
return min(leftover_bytes, 1024 << super->s_log_block_size);
}
// close an open inode
int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode)
{
mount->refs--;
if (open_inode->block_pointers)
kfree(open_inode->block_pointers); // free the block pointers cache
kfree(open_inode);
return 0;
}
// check the status of an inode (1-based inode number)
// -1: invalid inode number
// 0: free inode
// 1: allocated inode
int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number)
{
ext2_super_block_t *super = mount->super;
if (inode_number < 1 || inode_number > super->s_inodes_count) // inode number invalid
return -1;
inode_number--; // turn inode_number into a 0-based index
u32_t group = inode_number / super->s_inodes_per_group;
u32_t index = inode_number % super->s_inodes_per_group;
u32_t inode_bitmap_block = ext2_get_group_desc(mount, group).bg_inode_bitmap + (index >> (13 + super->s_log_block_size));
u32_t bitmap_index = index % (8192 << super->s_log_block_size);
u8_t *inode_bitmap = kmalloc(1024 << super->s_log_block_size);
block_read(mount->major, mount->minor,
ext2_FSToDiskBlock(inode_bitmap_block, super), 2 << super->s_log_block_size, inode_bitmap);
int inode_status = (inode_bitmap[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1;
kfree(inode_bitmap);
return inode_status;
}
// check the status of a block
// -1: invalid block number
// 0: free block
// 1: allocated block
int ext2_block_status(vfs_mount_t *mount, u32_t block_number)
{
ext2_super_block_t *super = mount->super;
if (block_number < super->s_first_data_block || block_number > super->s_blocks_count) // block number invalid
return -1;
block_number -= super->s_first_data_block;
u32_t group = block_number / super->s_blocks_per_group;
u32_t index = block_number % super->s_blocks_per_group;
u32_t block_bitmap_block = ext2_get_group_desc(mount, group).bg_block_bitmap + (index >> (13 + super->s_log_block_size));
u32_t bitmap_index = index % (8192 << super->s_log_block_size);
u8_t *block_bitmap = kmalloc(1024 << super->s_log_block_size);
block_read(mount->major, mount->minor,
ext2_FSToDiskBlock(block_bitmap_block, super), 2 << super->s_log_block_size, block_bitmap);
int block_status = (block_bitmap[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1;
kfree(block_bitmap);
return block_status;
}
// transform open_inode->block (a relative block number) to an absolute block number for the filesystem
u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode)
{
if (open_inode->block < 12)
return open_inode->inode.i_block[open_inode->block];
ext2_super_block_t *super = mount->super;
int pointersPerBlock = 256 << super->s_log_block_size;
if (open_inode->block_pointers && // there is a block pointers cache block allocated
(open_inode->block >= open_inode->block_pointers_start) && // and the block number is in it
(open_inode->block < (open_inode->block_pointers_start + pointersPerBlock)))
return open_inode->block_pointers[open_inode->block - open_inode->block_pointers_start];
u32_t rel_block = open_inode->block - 12;
if (!open_inode->block_pointers)
open_inode->block_pointers = kmalloc(pointersPerBlock << 2);
if (rel_block < pointersPerBlock) // indirect block in i_block[12]
{
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[12], super),
2 << super->s_log_block_size, open_inode->block_pointers);
open_inode->block_pointers_start = 12;
return open_inode->block_pointers[rel_block];
}
rel_block -= pointersPerBlock;
if (rel_block < (pointersPerBlock * pointersPerBlock)) // double-indirect block in i_block[13]
{
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[13], super),
2 << super->s_log_block_size, open_inode->block_pointers);
u32_t real_block = open_inode->block_pointers[rel_block / pointersPerBlock];
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(real_block, super),
2 << super->s_log_block_size, open_inode->block_pointers);
open_inode->block_pointers_start = 12 + pointersPerBlock + rel_block - (rel_block % pointersPerBlock);
return open_inode->block_pointers[rel_block % pointersPerBlock];
}
// this code shouldn't run unless we are dealing with a 65+mb file ...
rel_block -= pointersPerBlock * pointersPerBlock;
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[14], super),
2 << super->s_log_block_size, open_inode->block_pointers);
u32_t index_1 = rel_block / (pointersPerBlock * pointersPerBlock);
u32_t leftover_1 = rel_block % (pointersPerBlock * pointersPerBlock);
u32_t block_1 = open_inode->block_pointers[index_1];
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_1, super),
2 << super->s_log_block_size, open_inode->block_pointers);
u32_t index_2 = leftover_1 / pointersPerBlock;
u32_t leftover_2 = leftover_1 % pointersPerBlock;
u32_t block_2 = open_inode->block_pointers[index_2];
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_2, super),
2 << super->s_log_block_size, open_inode->block_pointers);
open_inode->block_pointers_start = 12 + (pointersPerBlock + 1) * pointersPerBlock + rel_block - (rel_block % pointersPerBlock);
return open_inode->block_pointers[leftover_2];
}
// read the inode structure from the device
int ext2_read_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat)
{
if (ext2_inode_status(mount, inode) != 1)
return -1; // free or invalid inode number
ext2_super_block_t *super = mount->super;
inode--; // turn inode into a 0-based index
u32_t group = inode / super->s_inodes_per_group;
u32_t index = inode % super->s_inodes_per_group;
u32_t inodeAddr = (ext2_get_group_desc(mount, group).bg_inode_table <<
(10 + super->s_log_block_size)) + (index << 7);
void *block = kmalloc(512);
block_read(mount->major, mount->minor, inodeAddr >> 9, 1, block);
memcpy(dat, (block + (inodeAddr & 0x1FF)), sizeof(ext2_inode_t));
kfree(block);
return 0;
}
// write an inode structure to the device
int ext2_write_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat)
{
if (ext2_inode_status(mount, inode) != 1)
return -1; // free or invalid inode number
ext2_super_block_t *super = mount->super;
inode--; // turn inode into a 0-based index
u32_t group = inode / super->s_inodes_per_group;
u32_t index = inode % super->s_inodes_per_group;
u32_t inodeAddr = (ext2_get_group_desc(mount, group).bg_inode_table <<
(10 + super->s_log_block_size)) + (index << 7);
void *block = kmalloc(512);
block_read(mount->major, mount->minor, inodeAddr >> 9, 1, block);
memcpy( (block + (inodeAddr & 0x1FF)), dat, sizeof(ext2_inode_t));
block_write(mount->major, mount->minor, inodeAddr >> 9, 1, block);
kfree(block);
return 0;
}
// read the group descriptor structure from the device and return it
ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group)
{
ext2_super_block_t *super = mount->super;
u32_t groupDescAddr = ((1 + super->s_first_data_block) << (10 + super->s_log_block_size)) + (group << 5);
void *block = kmalloc(512);
block_read(mount->major, mount->minor, groupDescAddr >> 9, 1, block);
ext2_group_desc_t gd = *(ext2_group_desc_t *)(block + (groupDescAddr & 0x1FF));
kfree(block);
return gd;
}
// write the group descriptor structure to the device
void ext2_write_group_desc(vfs_mount_t *mount, u32_t group_num, ext2_group_desc_t *gd)
{
ext2_super_block_t *super = mount->super;
u32_t groupDescAddr = ((1 + super->s_first_data_block) << (10 + super->s_log_block_size)) + (group_num << 5);
void *block = kmalloc(512);
block_read(mount->major, mount->minor, groupDescAddr >> 9, 1, block);
memcpy( (block + (groupDescAddr & 0x1FF)), gd, sizeof(ext2_group_desc_t) );
block_write(mount->major, mount->minor, groupDescAddr >> 9, 1, block);
kfree(block);
}
// allocate an inode and return its number
u32_t ext2_alloc_inode(vfs_mount_t *mount)
{
ext2_super_block_t *super = mount->super;
if (!super->s_free_inodes_count)
return 0; // no free inodes
int bg, bg_max = ext2_num_block_groups(super);
for (bg = 0; bg < bg_max; bg++)
{
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
if (group_desc.bg_free_inodes_count)
{
u32_t node = ext2_reserve_node(mount, group_desc.bg_inode_bitmap, super->s_inodes_per_group);
group_desc.bg_free_inodes_count--;
ext2_write_group_desc(mount, bg, &group_desc);
super->s_free_inodes_count--;
return bg * super->s_inodes_per_group + node + 1;
}
}
return 0;
}
int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number)
{
ext2_super_block_t *super = mount->super;
if (inode_number < 11 || inode_number > super->s_inodes_count)
return -1; // invalid inode number
if (ext2_inode_status(mount, inode_number) != 1)
return -2; // inode not allocated
inode_number--; // now a 0-based inode number
int bg = inode_number / super->s_inodes_per_group;
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
ext2_free_node(mount, group_desc.bg_inode_bitmap, inode_number % super->s_inodes_per_group);
group_desc.bg_free_inodes_count++;
ext2_write_group_desc(mount, bg, &group_desc);
super->s_free_inodes_count++;
return 0;
}
// allocate a block and return its number
u32_t ext2_alloc_block(vfs_mount_t *mount)
{
ext2_super_block_t *super = mount->super;
if (!super->s_free_blocks_count)
return 0; // no free blocks
int bg, bg_max = ext2_num_block_groups(super);
for (bg = 0; bg < bg_max; bg++)
{
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
if (group_desc.bg_free_blocks_count)
{
u32_t node = ext2_reserve_node(mount, group_desc.bg_block_bitmap, super->s_blocks_per_group);
group_desc.bg_free_blocks_count--;
ext2_write_group_desc(mount, bg, &group_desc);
super->s_free_blocks_count--;
return bg * super->s_blocks_per_group + node + super->s_first_data_block;
}
}
return 0;
}
int ext2_free_block(vfs_mount_t *mount, u32_t block_number)
{
ext2_super_block_t *super = mount->super;
if (block_number < super->s_first_data_block || block_number > (super->s_blocks_count + super->s_first_data_block - 1))
return -1; // invalid block number
if (ext2_block_status(mount, block_number) != 1)
return -2; // block not allocated
block_number -= super->s_first_data_block; // now a 0-based block number
int bg = block_number / super->s_blocks_per_group;
ext2_group_desc_t group_desc = ext2_get_group_desc(mount, bg);
ext2_free_node(mount, group_desc.bg_block_bitmap, block_number % super->s_blocks_per_group);
group_desc.bg_free_blocks_count++;
ext2_write_group_desc(mount, bg, &group_desc);
super->s_free_blocks_count++;
return 0;
}
int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size)
{
ext2_inode_t inode;
if ( ext2_read_inode(mount, inode_number, &inode) )
return -1;
ext2_super_block_t *super = mount->super;
int current_blocks = (inode.i_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size);
int new_blocks = (new_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size);
if ( new_blocks == current_blocks )
return 0;
// TODO: resize
u32_t block_size = 1024 << super->s_log_block_size;
u32_t pointers_per_block = block_size >> 2;
u32_t *pointer_cache1 = kmalloc(3 * block_size);
u32_t *pointer_cache2 = pointer_cache1 + pointers_per_block;
u32_t *pointer_cache3 = pointer_cache2 + pointers_per_block;
u32_t c1_start, c2_start, c3_start;
c1_start = c2_start = c3_start = 0;
while (new_blocks < current_blocks) // delete, decrease current_blocks
{
current_blocks--;
// now delete block number current_blocks
}
while (current_blocks < new_blocks) // add, increase current_blocks
{
}
}
// reserve a node of a inode or block bitmap and mark its entry allocated
u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap_size)
{
ext2_super_block_t *super = mount->super;
u32_t *bitmap = kmalloc(1024 << super->s_log_block_size);
int block, max_block = (bitmap_size - 1) / (8192 << super->s_log_block_size) + 1;
for (block = 0; block < max_block; block++)
{
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block, super),
2 << super->s_log_block_size, bitmap);
int num, num_max = 256 << super->s_log_block_size;
u32_t *block_pointer = bitmap;
int done = 0;
for (num = 0; num < num_max && !done; num++)
{
if (*block_pointer != 0xFFFFFFFF)
{
done = 1;
int bit;
for (bit = 0; bit < 32; bit++)
{
if (!(*block_pointer & (1 << bit)))
{
u32_t node_number = (block * 8192 << super->s_log_block_size) + (num << 5) + bit;
if (node_number < bitmap_size)
{
// found a node, mark it allocated, write the bitmap, return
*block_pointer |= (1 << bit);
block_write(mount->major, mount->minor,
ext2_FSToDiskBlock(bitmap_block_num + block, super),
2 << super->s_log_block_size, bitmap);
kfree(bitmap);
return node_number;
}
kfree(bitmap);
return 0;
}
}
}
block_pointer++;
}
}
kfree(bitmap);
return 0;
}
int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number)
{
ext2_super_block_t *super = mount->super;
u32_t block_num = node_number >> (13 + super->s_log_block_size);
byte *block = kmalloc(1024 << super->s_log_block_size);
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block_num, super),
2 << super->s_log_block_size, block);
u32_t node_bit_offset = node_number % (8192 << super->s_log_block_size);
u32_t node_byte_offset = node_bit_offset >> 3;
block[node_byte_offset] &= (0xFF ^ (1 << (node_bit_offset & 0x7)));
block_write(mount->major, mount->minor, ext2_FSToDiskBlock(bitmap_block_num + block_num, super),
2 << super->s_log_block_size, block);
kfree(block);
return 0;
}
// return how many block groups are on the filesystem
int ext2_num_block_groups(ext2_super_block_t *super)
{
return (super->s_inodes_count / super->s_inodes_per_group) + 1;
}
void ext2_write_super(vfs_mount_t *mount)
{
block_write(mount->major, mount->minor, 2, 2, mount->super);
}
/***************** VFS INTERFACE FUNCTIONS *******************/
// mount the superblock of the filesystem and return a pointer to it, if valid
void *ext2_mount_super(major_t major, minor_t minor)
{
ext2_super_block_t *super = kmalloc(1024);
block_read(major, minor, 2, 2, super);
if (super->s_magic != EXT2_MAGIC) // not an ext2 filesystem
{
kfree(super);
return NULL;
}
return super;
}
// called when we are unmounting this filesystem mount
int ext2_umount_super(vfs_mount_t *mount)
{
ext2_write_super(mount);
return kfree(mount->super); // free memory that the superblock was taking
}
// stat a file, return a structure of info about it
int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat)
{
if (ext2_inode_status(mount, inode_number) != 1)
return -1;
ext2_inode_t *inode = New(ext2_inode_t);
if ( ext2_read_inode(mount, inode_number, inode) )
{
kfree(inode);
return -2;
}
stat->dev = 0;
switch(inode->i_mode & EXT2_I_MODE_TYPE_MASK)
{
case EXT2_I_MODE_FIFO: stat->type = VFS_FT_FIFO; break;
case EXT2_I_MODE_CHAR: stat->type = VFS_FT_CHAR; stat->dev = inode->i_block[0]; break;
case EXT2_I_MODE_DIR: stat->type = VFS_FT_DIR; break;
case EXT2_I_MODE_BLOCK: stat->type = VFS_FT_BLOCK; stat->dev = inode->i_block[0]; break;
case EXT2_I_MODE_FILE: stat->type = VFS_FT_FILE; break;
case EXT2_I_MODE_SYM: stat->type = VFS_FT_SYMLINK; break;
case EXT2_I_MODE_SOCK: stat->type = VFS_FT_SOCK; break;
default: stat->type = VFS_FT_UNKNOWN; break;
}
stat->size = inode->i_size;
stat->inode = inode_number;
stat->permissions = inode->i_mode & EXT2_I_MODE_ATTR_MASK;
stat->uid = inode->i_uid;
stat->gid = inode->i_gid;
stat->atime = inode->i_atime;
stat->mtime = inode->i_mtime;
stat->ctime = inode->i_ctime;
stat->links = inode->i_links_count;
kfree(inode);
return 0;
}
// what is the inode of the root directory?
u32_t ext2__get_root_dir_inode(vfs_mount_t *mount)
{
return 2;
}
// VFS interface function to dereference a symbolic link
int ext2__link_deref(vfs_mount_t *mount, u32_t link_inode, char *link)
{
ext2_inode_t inode;
if (ext2_read_inode(mount, link_inode, &inode))
return -1;
if ( (inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_SYM )
return -2;
if (!inode.i_size)
return -4;
if (inode.i_size < 61)
{
memcpy(link, inode.i_block, inode.i_size);
link[inode.i_size] = 0;
return 0;
}
else
{
ext2_open_inode_t *open_inode;
if (!(open_inode = ext2_open_inode(mount, link_inode)))
return -3;
ext2_super_block_t *super = mount->super;
void *buffer = kmalloc(1024 << super->s_log_block_size);
memset(link, 0, 4096);
int copied = 0;
while (copied < 4096)
{
int bytes_read = ext2_read_inode_block(mount, open_inode, buffer);
if (bytes_read == 0)
break;
memcpy(link + copied, buffer, bytes_read);
copied += bytes_read;
}
ext2_close_inode(mount, open_inode);
kfree(buffer);
return 0;
}
}
// VFS interface function to return the number of free inodes
int ext2__free_inodes(vfs_mount_t *mount)
{
ext2_super_block_t *super = mount->super;
return super->s_free_inodes_count;
}
// VFS interface function to return the total number of inodes
int ext2__total_inodes(vfs_mount_t *mount)
{
ext2_super_block_t *super = mount->super;
return super->s_inodes_count;
}
// VFS interface function to return the number of free 512-byte blocks
int ext2__free_blocks(vfs_mount_t *mount)
{
ext2_super_block_t *super = mount->super;
return super->s_free_blocks_count << (1 + super->s_log_block_size);
}
// VFS interface function to return the total number of 512-byte blocks
int ext2__total_blocks(vfs_mount_t *mount)
{
ext2_super_block_t *super = mount->super;
return super->s_blocks_count << (1 + super->s_log_block_size);
}
// VFS interface function to open a directory
int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir)
{
if (ext2_inode_status(mount, inode_number) != 1)
return -1;
ext2_open_dir_t *open_dir = ext2_open_dir(mount, inode_number);
if (!open_dir)
return -2;
dir->fs_data = open_dir;
return 0;
}
// VFS interface function to read a directory entry from an open directory
int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry)
{
ext2_dir_entry_t t_dentry;
int status = ext2_dir_read_entry(mount, dir->fs_data, &t_dentry);
if (status)
return status;
memcpy(dentry->name, t_dentry.name, t_dentry.name_length);
dentry->name[t_dentry.name_length] = 0;
dentry->inode_number = t_dentry.inode;
return 0;
}
// VFS interface function to close an open directory
int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir)
{
return ext2_close_dir(mount, dir->fs_data);
}
// VFS interface function to open a file for reading a byte at a time
int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file)
{
if (ext2_inode_status(mount, inode_number) != 1)
return -1;
return 0;
}
// VFS interface function to read a byte from an open file
int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
{
return 0;
}
// VFS interface function to close a byte-file
int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
{
return 0;
}
// VFS interface function to open a file for reading 512-byte blocks at a time
int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file)
{
if (ext2_inode_status(mount, inode_number) != 1)
return -1;
ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number);
if (!open_inode)
return -2;
if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_FILE)
{
ext2_close_inode(mount, open_inode);
return -3;
}
ext2__open_block_file_t *open_block_file = New(ext2__open_block_file_t);
open_block_file->open_inode = open_inode;
open_block_file->block = 0;
open_file->fs_data = open_block_file;
return 0;
}
// VFS interface function to read a block from an open block file
// returns the number of bytes read
int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer)
{
ext2_super_block_t *super = mount->super;
ext2__open_block_file_t *open_block_file = open_file->fs_data;
if (ext2_inode_seek(mount, open_block_file->open_inode, ext2_diskToFSBlock(open_block_file->block, super)))
return 0; // EOF
u8_t *block = kmalloc(1024 << super->s_log_block_size);
u32_t file_position_read = (1024 << super->s_log_block_size) * open_block_file->open_inode->block;
u32_t file_position_want = open_block_file->block << 9;
u32_t data_offset = file_position_want - file_position_read;
int bytes_read = ext2_read_inode_block(mount, open_block_file->open_inode, block);
if (bytes_read <= data_offset)
{
kfree(block);
return 0; // EOF
}
memcpy(buffer, block + data_offset, min(512, bytes_read - data_offset));
kfree(block);
open_block_file->block++;
return min(512, bytes_read - data_offset);
}
// VFS interface function to seek to a certain block number of an open block file
int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number)
{
ext2__open_block_file_t *open_block_file = open_file->fs_data;
return ext2_inode_seek(mount, open_block_file->open_inode, ext2_FSToDiskBlock(block_number, mount->super));
}
// VFS interface function to close an open block file
int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
{
ext2__open_block_file_t *open_block_file = open_file->fs_data;
ext2_close_inode(mount, open_block_file->open_inode);
kfree(open_block_file);
return 0;
}

View File

@ -1,241 +0,0 @@
// ext2.h
// Author: Josh Holtrop
// Date: 08/22/04
// Modified: 12/24/04
#ifndef __HOS_EXT2_H__
#define __HOS_EXT2_H__ __HOS_EXT2_H__
#include "hos_defines.h"
#include "fs/devices.h"
#include "fs/vfs.h"
#define EXT2_MAGIC 0xEF53
#define EXT2_NAME_LEN 255
#define EXT2_I_MODE_ATTR_MASK 0x0FFF
#define EXT2_I_MODE_OX 0x0001
#define EXT2_I_MODE_OW 0x0002
#define EXT2_I_MODE_OR 0x0004
#define EXT2_I_MODE_GX 0x0008
#define EXT2_I_MODE_GW 0x0010
#define EXT2_I_MODE_GR 0x0020
#define EXT2_I_MODE_UX 0x0040
#define EXT2_I_MODE_UW 0x0080
#define EXT2_I_MODE_UR 0x0100
#define EXT2_I_MODE_STICKY 0x0200
#define EXT2_I_MODE_SGID 0x0400
#define EXT2_I_MODE_SUID 0x0800
#define EXT2_I_MODE_TYPE_MASK 0xF000
#define EXT2_I_MODE_FIFO 0x1000
#define EXT2_I_MODE_CHAR 0x2000
#define EXT2_I_MODE_DIR 0x4000
#define EXT2_I_MODE_BLOCK 0x6000
#define EXT2_I_MODE_FILE 0x8000
#define EXT2_I_MODE_SYM 0xA000
#define EXT2_I_MODE_SOCK 0xC000
#define EXT2_I_FLAGS_SEC_DEL 0x01
#define EXT2_I_FLAGS_UNDELETE 0x02
#define EXT2_I_FLAGS_COMPRESS 0x04
#define EXT2_I_FLAGS_SYNC 0x08
#define EXT2_I_FLAGS_IMMUTABLE 0x10
#define EXT2_I_FLAGS_APPEND 0x20
#define EXT2_I_FLAGS_NODUMP 0x40
#define EXT2_INODE_BAD_BLOCKS 1
#define EXT2_INODE_ROOT 2
#define EXT2_INODE_ACL_INDEX 3
#define EXT2_INODE_ACL_DATA 4
#define EXT2_INODE_BOOT_LOADER 5
#define EXT2_INODE_UNDELETE_DIR 6
#define EXT2_INODE_AVAIL 11
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHAR 3
#define EXT2_FT_BLOCK 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
typedef struct
{
u32_t s_inodes_count; /* Inodes count */
u32_t s_blocks_count; /* Blocks count */
u32_t s_r_blocks_count; /* Reserved blocks count */
u32_t s_free_blocks_count; /* Free blocks count */
u32_t s_free_inodes_count; /* Free inodes count */
u32_t s_first_data_block; /* First Data Block */
u32_t s_log_block_size; /* Block size: 0->1024, 1->2048, 2->4096 */
int s_log_frag_size; /* Fragment size */
u32_t s_blocks_per_group; /* # Blocks per group */
u32_t s_frags_per_group; /* # Fragments per group */
u32_t s_inodes_per_group; /* # Inodes per group */
u32_t s_mtime; /* Mount time */
u32_t s_wtime; /* Write time */
u16_t s_mnt_count; /* Mount count */
short s_max_mnt_count; /* Maximal mount count */
u16_t s_magic; /* Magic signature */
u16_t s_state; /* File system state */
u16_t s_errors; /* Behaviour when detecting errors */
u16_t s_minor_rev_level; /* minor revision level */
u32_t s_lastcheck; /* time of last check */
u32_t s_checkinterval; /* max. time between checks */
u32_t s_creator_os; /* OS */
u32_t s_rev_level; /* Revision level */
u16_t s_def_resuid; /* Default uid for reserved blocks */
u16_t s_def_resgid; /* Default gid for reserved blocks */
u32_t s_reserved[235];
} ext2_super_block_t;
typedef struct
{
u32_t bg_block_bitmap; // Blocks bitmap block
u32_t bg_inode_bitmap; // Inode bitmap block
u32_t bg_inode_table; // Inode table block
u16_t bg_free_blocks_count; // Free blocks count
u16_t bg_free_inodes_count; // Free Inodes count
u16_t bg_used_dirs_count; // Directories count
u16_t bg_pad1;
u32_t bg_reserved[3];
} ext2_group_desc_t;
typedef struct
{
u16_t i_mode; // File mode
u16_t i_uid; // Owner UID
u32_t i_size; // Size in bytes
u32_t i_atime; // Access time
u32_t i_ctime; // Creation time
u32_t i_mtime; // Modification time
u32_t i_dtime; // Deletion time
u16_t i_gid; // Group ID
u16_t i_links_count; // Links count
u32_t i_blocks; // Blocks count
u32_t i_flags; // File flags
u32_t i_reserved1;
u32_t i_block[15]; // Pointers to blocks (12 direct, single, double, triple indirect)
u32_t i_version; // File version (for NFS)
u32_t i_file_acl; // File ACL
u32_t i_dir_acl; // Directory ACL
u32_t i_faddr; // Fragment address
u8_t i_frag; // Fragment number
u8_t i_fsize; // Fragment size
u16_t i_pad1;
u32_t i_reserved2[2];
} ext2_inode_t;
typedef struct
{
u32_t inode; // inode number
u16_t length; // directory entry length
u8_t name_length; // name length
u8_t file_type; // File type
char name[EXT2_NAME_LEN];
} ext2_dir_entry_t;
typedef struct
{
ext2_inode_t inode;
u32_t block;
u32_t *block_pointers;
u32_t block_pointers_start;
} ext2_open_inode_t;
typedef struct
{
ext2_open_inode_t *open_inode;
u32_t position;
} ext2_open_dir_t;
typedef struct
{
ext2_open_inode_t *open_inode;
u32_t position;
u32_t buffer_start;
u32_t buffer_bytes;
u8_t *buffer;
} ext2__open_file_t;
typedef struct
{
ext2_open_inode_t *open_inode;
u32_t block;
} ext2__open_block_file_t;
static inline u32_t ext2_diskToFSBlock(u32_t block, ext2_super_block_t *super)
{
// convert # of disk blocks to # of filesystem blocks
return block >> (super->s_log_block_size + 1);
}
static inline u32_t ext2_FSToDiskBlock(u32_t block, ext2_super_block_t *super)
{
// convert # of filesystem blocks to # of disk blocks
return block << (super->s_log_block_size + 1);
}
int ext2_init(int fsID);
int ext2_read_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat);
int ext2_write_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat);
ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group);
void ext2_write_group_desc(vfs_mount_t *mount, u32_t group_num, ext2_group_desc_t *gd);
ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number);
int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode);
int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block);
u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode);
int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number);
int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number);
int ext2_block_status(vfs_mount_t *mount, u32_t block_number);
u32_t ext2_alloc_inode(vfs_mount_t *mount);
int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number);
u32_t ext2_alloc_block(vfs_mount_t *mount);
int ext2_free_block(vfs_mount_t *mount, u32_t block_number);
u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap_size);
int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number);
int ext2_num_block_groups(ext2_super_block_t *super);
void ext2_write_super(vfs_mount_t *mount);
int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size);
ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number);
int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry);
int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir);
int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry);
void *ext2_mount_super(major_t major, minor_t minor);
int ext2_umount_super(vfs_mount_t *mount);
int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat);
u32_t ext2__get_root_dir_inode(vfs_mount_t *mount);
int ext2__link_deref(vfs_mount_t *mount, u32_t link_inode, char *link);
int ext2__free_inodes(vfs_mount_t *mount);
int ext2__total_inodes(vfs_mount_t *mount);
int ext2__free_blocks(vfs_mount_t *mount);
int ext2__total_blocks(vfs_mount_t *mount);
int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir);
int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry);
int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir);
int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer);
int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number);
int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
#endif

View File

@ -1,332 +0,0 @@
// lookup a file name in a directory and store the directory entry for it
int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry)
{
ext2_open_dir_t *dir = ext2_open_dir(mount, dir_inode);
if (!dir)
return -1; // bad directory inode number
ext2_dir_entry_t dentry;
while (!ext2_dir_read_entry(mount, dir, &dentry))
{
char *dentryName = kcalloc(1, dentry.name_length + 1);
memcpy(dentryName, dentry.name, dentry.name_length);
int res = strcmp(fileName, dentryName);
kfree(dentryName);
if (!res)
{
*direntry = dentry;
ext2_close_dir(mount, dir);
return 0;
}
}
ext2_close_dir(mount, dir);
return -2;
}
// open a directory by inode number for reading
ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number)
{
ext2_open_dir_t *open_dir = New(ext2_open_dir_t);
ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number);
if (!open_inode)
{
kfree(open_dir);
return NULL;
}
if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_DIR)
{
ext2_close_inode(mount, open_inode);
kfree(open_dir);
return NULL;
}
open_dir->open_inode = open_inode;
open_dir->position = 0;
return open_dir;
}
int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry)
{
ext2_super_block_t *super = mount->super;
if (open_dir->position >= open_dir->open_inode->inode.i_size)
return -1; // EOF
u32_t dir_block = open_dir->position >> (10 + super->s_log_block_size);
char *block = kmalloc(2048 << super->s_log_block_size);
ext2_inode_seek(mount, open_dir->open_inode, dir_block);
if (ext2_read_inode_block(mount, open_dir->open_inode, block))
ext2_read_inode_block(mount, open_dir->open_inode, block + (1024 << super->s_log_block_size));
ext2_dir_entry_t *dir_entry = (ext2_dir_entry_t *)(block + open_dir->position % (1024 << super->s_log_block_size));
if (!dir_entry->inode)
{
kfree(block);
return -2; // EOF
}
memcpy(dentry, dir_entry, min(dir_entry->length, sizeof(ext2_dir_entry_t)));
open_dir->position += dir_entry->length;
kfree(block);
return 0;
}
int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir)
{
ext2_close_inode(mount, open_dir->open_inode);
kfree(open_dir);
return 0;
}
// open an inode for reading
ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number)
{
ext2_open_inode_t *open_inode = New(ext2_open_inode_t);
if ( ext2_read_inode(mount, inode_number, &(open_inode->inode)) )
{
kfree(open_inode);
return NULL;
}
open_inode->block = 0;
open_inode->block_pointers = NULL;
open_inode->block_pointers_start = 0;
mount->refs++;
return open_inode;
}
// seek to a certain block of an open inode
int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number)
{
ext2_super_block_t *super = mount->super;
if (open_inode->inode.i_size <= (block_number << (10 + super->s_log_block_size)))
return -1; // at or past EOF
open_inode->block = block_number;
return 0;
}
// returns number of bytes read
int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block)
{
ext2_super_block_t *super = mount->super;
if (open_inode->inode.i_size <= (open_inode->block << (10 + super->s_log_block_size)))
return 0; // at or past EOF
u32_t leftover_bytes = open_inode->inode.i_size - (open_inode->block << (10 + super->s_log_block_size));
u32_t block_number = ext2_block_number(mount, open_inode);
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_number, super),
2 << super->s_log_block_size, block);
open_inode->block++;
return min(leftover_bytes, 1024 << super->s_log_block_size);
}
// close an open inode
int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode)
{
mount->refs--;
if (open_inode->block_pointers)
kfree(open_inode->block_pointers); // free the block pointers cache
kfree(open_inode);
return 0;
}
// transform open_inode->block (a relative block number) to an absolute block number for the filesystem
u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode)
{
if (open_inode->block < 12)
return open_inode->inode.i_block[open_inode->block];
ext2_super_block_t *super = mount->super;
int pointersPerBlock = 256 << super->s_log_block_size;
if (open_inode->block_pointers && // there is a block pointers cache block allocated
(open_inode->block >= open_inode->block_pointers_start) && // and the block number is in it
(open_inode->block < (open_inode->block_pointers_start + pointersPerBlock)))
return open_inode->block_pointers[open_inode->block - open_inode->block_pointers_start];
u32_t rel_block = open_inode->block - 12;
if (!open_inode->block_pointers)
open_inode->block_pointers = kmalloc(pointersPerBlock << 2);
if (rel_block < pointersPerBlock) // indirect block in i_block[12]
{
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[12], super),
2 << super->s_log_block_size, open_inode->block_pointers);
open_inode->block_pointers_start = 12;
return open_inode->block_pointers[rel_block];
}
rel_block -= pointersPerBlock;
if (rel_block < (pointersPerBlock * pointersPerBlock)) // double-indirect block in i_block[13]
{
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[13], super),
2 << super->s_log_block_size, open_inode->block_pointers);
u32_t real_block = open_inode->block_pointers[rel_block / pointersPerBlock];
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(real_block, super),
2 << super->s_log_block_size, open_inode->block_pointers);
open_inode->block_pointers_start = 12 + pointersPerBlock + rel_block - (rel_block % pointersPerBlock);
return open_inode->block_pointers[rel_block % pointersPerBlock];
}
// this code shouldn't run unless we are dealing with a 65+mb file ...
rel_block -= pointersPerBlock * pointersPerBlock;
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[14], super),
2 << super->s_log_block_size, open_inode->block_pointers);
u32_t index_1 = rel_block / (pointersPerBlock * pointersPerBlock);
u32_t leftover_1 = rel_block % (pointersPerBlock * pointersPerBlock);
u32_t block_1 = open_inode->block_pointers[index_1];
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_1, super),
2 << super->s_log_block_size, open_inode->block_pointers);
u32_t index_2 = leftover_1 / pointersPerBlock;
u32_t leftover_2 = leftover_1 % pointersPerBlock;
u32_t block_2 = open_inode->block_pointers[index_2];
block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_2, super),
2 << super->s_log_block_size, open_inode->block_pointers);
open_inode->block_pointers_start = 12 + (pointersPerBlock + 1) * pointersPerBlock + rel_block - (rel_block % pointersPerBlock);
return open_inode->block_pointers[leftover_2];
}
int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size)
{
ext2_inode_t inode;
if ( ext2_read_inode(mount, inode_number, &inode) )
return -1;
ext2_super_block_t *super = mount->super;
int current_blocks = (inode.i_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size);
int new_blocks = (new_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size);
if ( new_blocks == current_blocks )
return 0;
// TODO: resize
u32_t block_size = 1024 << super->s_log_block_size;
u32_t pointers_per_block = block_size >> 2;
u32_t *pointer_cache1 = kmalloc(3 * block_size);
u32_t *pointer_cache2 = pointer_cache1 + pointers_per_block;
u32_t *pointer_cache3 = pointer_cache2 + pointers_per_block;
u32_t c1_start, c2_start, c3_start;
c1_start = c2_start = c3_start = 0;
while (new_blocks < current_blocks) // delete, decrease current_blocks
{
current_blocks--;
// now delete block number current_blocks
}
while (current_blocks < new_blocks) // add, increase current_blocks
{
}
}
/***************** VFS INTERFACE FUNCTIONS *******************/
// VFS interface function to open a directory
int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir)
{
if (ext2_inode_status(mount, inode_number) != 1)
return -1;
ext2_open_dir_t *open_dir = ext2_open_dir(mount, inode_number);
if (!open_dir)
return -2;
dir->fs_data = open_dir;
return 0;
}
// VFS interface function to read a directory entry from an open directory
int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry)
{
ext2_dir_entry_t t_dentry;
int status = ext2_dir_read_entry(mount, dir->fs_data, &t_dentry);
if (status)
return status;
memcpy(dentry->name, t_dentry.name, t_dentry.name_length);
dentry->name[t_dentry.name_length] = 0;
dentry->inode_number = t_dentry.inode;
return 0;
}
// VFS interface function to close an open directory
int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir)
{
return ext2_close_dir(mount, dir->fs_data);
}
// VFS interface function to open a file for reading a byte at a time
int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file)
{
if (ext2_inode_status(mount, inode_number) != 1)
return -1;
return 0;
}
// VFS interface function to read a byte from an open file
int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
{
return 0;
}
// VFS interface function to close a byte-file
int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
{
return 0;
}
// VFS interface function to open a file for reading 512-byte blocks at a time
int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file)
{
if (ext2_inode_status(mount, inode_number) != 1)
return -1;
ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number);
if (!open_inode)
return -2;
if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_FILE)
{
ext2_close_inode(mount, open_inode);
return -3;
}
ext2__open_block_file_t *open_block_file = New(ext2__open_block_file_t);
open_block_file->open_inode = open_inode;
open_block_file->block = 0;
open_file->fs_data = open_block_file;
return 0;
}
// VFS interface function to read a block from an open block file
// returns the number of bytes read
int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer)
{
ext2_super_block_t *super = mount->super;
ext2__open_block_file_t *open_block_file = open_file->fs_data;
if (ext2_inode_seek(mount, open_block_file->open_inode, ext2_diskToFSBlock(open_block_file->block, super)))
return 0; // EOF
u8_t *block = kmalloc(1024 << super->s_log_block_size);
u32_t file_position_read = (1024 << super->s_log_block_size) * open_block_file->open_inode->block;
u32_t file_position_want = open_block_file->block << 9;
u32_t data_offset = file_position_want - file_position_read;
int bytes_read = ext2_read_inode_block(mount, open_block_file->open_inode, block);
if (bytes_read <= data_offset)
{
kfree(block);
return 0; // EOF
}
memcpy(buffer, block + data_offset, min(512, bytes_read - data_offset));
kfree(block);
open_block_file->block++;
return min(512, bytes_read - data_offset);
}
// VFS interface function to seek to a certain block number of an open block file
int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number)
{
ext2__open_block_file_t *open_block_file = open_file->fs_data;
return ext2_inode_seek(mount, open_block_file->open_inode, ext2_FSToDiskBlock(block_number, mount->super));
}
// VFS interface function to close an open block file
int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file)
{
ext2__open_block_file_t *open_block_file = open_file->fs_data;
ext2_close_inode(mount, open_block_file->open_inode);
kfree(open_block_file);
return 0;
}

View File

@ -1,241 +0,0 @@
// ext2.h
// Author: Josh Holtrop
// Date: 08/22/04
// Modified: 12/24/04
#ifndef __HOS_EXT2_H__
#define __HOS_EXT2_H__ __HOS_EXT2_H__
#include "hos_defines.h"
#include "fs/devices.h"
#include "fs/vfs.h"
#define EXT2_MAGIC 0xEF53
#define EXT2_NAME_LEN 255
#define EXT2_I_MODE_ATTR_MASK 0x0FFF
#define EXT2_I_MODE_OX 0x0001
#define EXT2_I_MODE_OW 0x0002
#define EXT2_I_MODE_OR 0x0004
#define EXT2_I_MODE_GX 0x0008
#define EXT2_I_MODE_GW 0x0010
#define EXT2_I_MODE_GR 0x0020
#define EXT2_I_MODE_UX 0x0040
#define EXT2_I_MODE_UW 0x0080
#define EXT2_I_MODE_UR 0x0100
#define EXT2_I_MODE_STICKY 0x0200
#define EXT2_I_MODE_SGID 0x0400
#define EXT2_I_MODE_SUID 0x0800
#define EXT2_I_MODE_TYPE_MASK 0xF000
#define EXT2_I_MODE_FIFO 0x1000
#define EXT2_I_MODE_CHAR 0x2000
#define EXT2_I_MODE_DIR 0x4000
#define EXT2_I_MODE_BLOCK 0x6000
#define EXT2_I_MODE_FILE 0x8000
#define EXT2_I_MODE_SYM 0xA000
#define EXT2_I_MODE_SOCK 0xC000
#define EXT2_I_FLAGS_SEC_DEL 0x01
#define EXT2_I_FLAGS_UNDELETE 0x02
#define EXT2_I_FLAGS_COMPRESS 0x04
#define EXT2_I_FLAGS_SYNC 0x08
#define EXT2_I_FLAGS_IMMUTABLE 0x10
#define EXT2_I_FLAGS_APPEND 0x20
#define EXT2_I_FLAGS_NODUMP 0x40
#define EXT2_INODE_BAD_BLOCKS 1
#define EXT2_INODE_ROOT 2
#define EXT2_INODE_ACL_INDEX 3
#define EXT2_INODE_ACL_DATA 4
#define EXT2_INODE_BOOT_LOADER 5
#define EXT2_INODE_UNDELETE_DIR 6
#define EXT2_INODE_AVAIL 11
#define EXT2_FT_UNKNOWN 0
#define EXT2_FT_FILE 1
#define EXT2_FT_DIR 2
#define EXT2_FT_CHAR 3
#define EXT2_FT_BLOCK 4
#define EXT2_FT_FIFO 5
#define EXT2_FT_SOCK 6
#define EXT2_FT_SYMLINK 7
#define EXT2_FT_MAX 8
typedef struct
{
u32_t s_inodes_count; /* Inodes count */
u32_t s_blocks_count; /* Blocks count */
u32_t s_r_blocks_count; /* Reserved blocks count */
u32_t s_free_blocks_count; /* Free blocks count */
u32_t s_free_inodes_count; /* Free inodes count */
u32_t s_first_data_block; /* First Data Block */
u32_t s_log_block_size; /* Block size: 0->1024, 1->2048, 2->4096 */
int s_log_frag_size; /* Fragment size */
u32_t s_blocks_per_group; /* # Blocks per group */
u32_t s_frags_per_group; /* # Fragments per group */
u32_t s_inodes_per_group; /* # Inodes per group */
u32_t s_mtime; /* Mount time */
u32_t s_wtime; /* Write time */
u16_t s_mnt_count; /* Mount count */
short s_max_mnt_count; /* Maximal mount count */
u16_t s_magic; /* Magic signature */
u16_t s_state; /* File system state */
u16_t s_errors; /* Behaviour when detecting errors */
u16_t s_minor_rev_level; /* minor revision level */
u32_t s_lastcheck; /* time of last check */
u32_t s_checkinterval; /* max. time between checks */
u32_t s_creator_os; /* OS */
u32_t s_rev_level; /* Revision level */
u16_t s_def_resuid; /* Default uid for reserved blocks */
u16_t s_def_resgid; /* Default gid for reserved blocks */
u32_t s_reserved[235];
} ext2_super_block_t;
typedef struct
{
u32_t bg_block_bitmap; // Blocks bitmap block
u32_t bg_inode_bitmap; // Inode bitmap block
u32_t bg_inode_table; // Inode table block
u16_t bg_free_blocks_count; // Free blocks count
u16_t bg_free_inodes_count; // Free Inodes count
u16_t bg_used_dirs_count; // Directories count
u16_t bg_pad1;
u32_t bg_reserved[3];
} ext2_group_desc_t;
typedef struct
{
u16_t i_mode; // File mode
u16_t i_uid; // Owner UID
u32_t i_size; // Size in bytes
u32_t i_atime; // Access time
u32_t i_ctime; // Creation time
u32_t i_mtime; // Modification time
u32_t i_dtime; // Deletion time
u16_t i_gid; // Group ID
u16_t i_links_count; // Links count
u32_t i_blocks; // Blocks count
u32_t i_flags; // File flags
u32_t i_reserved1;
u32_t i_block[15]; // Pointers to blocks (12 direct, single, double, triple indirect)
u32_t i_version; // File version (for NFS)
u32_t i_file_acl; // File ACL
u32_t i_dir_acl; // Directory ACL
u32_t i_faddr; // Fragment address
u8_t i_frag; // Fragment number
u8_t i_fsize; // Fragment size
u16_t i_pad1;
u32_t i_reserved2[2];
} ext2_inode_t;
typedef struct
{
u32_t inode; // inode number
u16_t length; // directory entry length
u8_t name_length; // name length
u8_t file_type; // File type
char name[EXT2_NAME_LEN];
} ext2_dir_entry_t;
typedef struct
{
ext2_inode_t inode;
u32_t block;
u32_t *block_pointers;
u32_t block_pointers_start;
} ext2_open_inode_t;
typedef struct
{
ext2_open_inode_t *open_inode;
u32_t position;
} ext2_open_dir_t;
typedef struct
{
ext2_open_inode_t *open_inode;
u32_t position;
u32_t buffer_start;
u32_t buffer_bytes;
u8_t *buffer;
} ext2__open_file_t;
typedef struct
{
ext2_open_inode_t *open_inode;
u32_t block;
} ext2__open_block_file_t;
static inline u32_t ext2_diskToFSBlock(u32_t block, ext2_super_block_t *super)
{
// convert # of disk blocks to # of filesystem blocks
return block >> (super->s_log_block_size + 1);
}
static inline u32_t ext2_FSToDiskBlock(u32_t block, ext2_super_block_t *super)
{
// convert # of filesystem blocks to # of disk blocks
return block << (super->s_log_block_size + 1);
}
int ext2_init(int fsID);
int ext2_read_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat);
int ext2_write_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat);
ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group);
void ext2_write_group_desc(vfs_mount_t *mount, u32_t group_num, ext2_group_desc_t *gd);
ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number);
int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode);
int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block);
u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode);
int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number);
int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number);
int ext2_block_status(vfs_mount_t *mount, u32_t block_number);
u32_t ext2_alloc_inode(vfs_mount_t *mount);
int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number);
u32_t ext2_alloc_block(vfs_mount_t *mount);
int ext2_free_block(vfs_mount_t *mount, u32_t block_number);
u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap_size);
int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number);
int ext2_num_block_groups(ext2_super_block_t *super);
void ext2_write_super(vfs_mount_t *mount);
int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size);
ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number);
int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry);
int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir);
int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry);
void *ext2_mount_super(major_t major, minor_t minor);
int ext2_umount_super(vfs_mount_t *mount);
int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat);
u32_t ext2__get_root_dir_inode(vfs_mount_t *mount);
int ext2__link_deref(vfs_mount_t *mount, u32_t link_inode, char *link);
int ext2__free_inodes(vfs_mount_t *mount);
int ext2__total_inodes(vfs_mount_t *mount);
int ext2__free_blocks(vfs_mount_t *mount);
int ext2__total_blocks(vfs_mount_t *mount);
int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir);
int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry);
int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir);
int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer);
int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number);
int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file);
#endif

View File

@ -1,42 +0,0 @@
// sysfs.cpp
// sysfs filesystem driver for HOS
// Author: Josh Holtrop
// Date: 06/27/05
// Modified: 06/27/05
extern "C" {
#include "display/kout.h"
}
#include "fs/vfs.h"
#include "sysfs.h"
#include "sysfs_entry.h"
int sysfs_init()
{
vfs_register("sysfs", sysfs__mount_func);
return 0;
}
FileSystem *sysfs__mount_func(device_t dev)
{
if (dev)
kprintf("sysfs: warning: device parameter ignored\n");
return new Sysfs();
}
Sysfs::Sysfs()
{
myEntries.add(Sysfs_Entry(SYSFS_FILE, "timer", SYSFS_TIMER));
}
Sysfs::~Sysfs()
{
}
u32_t Sysfs::getRootInodeNumber()
{
return 2;
}

View File

@ -1,37 +0,0 @@
// sysfs.h
// sysfs filesystem driver for HOS
// Author: Josh Holtrop
// Date: 06/27/05
// Modified: 06/27/05
#ifndef __HOS_SYSFS_H__
#define __HOS_SYSFS_H__ __HOS_SYSFS_H__
#define SYSFS_TIMER 1
#ifdef _HOS_CPP_
#include "fs/FileSystem.h"
#include "fs/vfs.h"
#include "lang/vector.h"
#include "lang/string.h"
#include "sysfs_entry.h"
int sysfs_init();
FileSystem *sysfs__mount_func(device_t dev);
class Sysfs : public FileSystem
{
protected:
vector<Sysfs_Entry> myEntries;
public:
Sysfs();
~Sysfs();
u32_t getRootInodeNumber();
};
#endif
#endif

View File

@ -1,20 +0,0 @@
// sysfs_entry.cpp
// sysfs filesystem driver for HOS
// Author: Josh Holtrop
// Date: 06/27/05
// Modified: 06/27/05
#include "sysfs_entry.h"
#include "lang/string.h"
Sysfs_Entry::Sysfs_Entry(int type, string name, int id)
{
myType = type;
myName = name;
myID = id;
}
Sysfs_Entry::~Sysfs_Entry()
{
}

View File

@ -1,30 +0,0 @@
// sysfs_entry.h
// sysfs filesystem driver for HOS
// Author: Josh Holtrop
// Date: 06/27/05
// Modified: 06/27/05
#ifndef __HOS_SYSFS_ENTRY_H__
#define __HOS_SYSFS_ENTRY_H__ __HOS_SYSFS_ENTRY_H__
#include "lang/vector.h"
#include "lang/string.h"
#define SYSFS_DIR 1
#define SYSFS_FILE 2
class Sysfs_Entry
{
protected:
int myType;
string myName;
int myID;
vector<Sysfs_Entry> myChildren;
public:
Sysfs_Entry(int type, string name, int id);
~Sysfs_Entry();
};
#endif

View File

@ -1,413 +0,0 @@
// vfs.cpp
// Virtual file system subsystem for HOS
// Author: Josh Holtrop
// Date: 05/10/05
// Modified: 12/26/05
extern "C" {
#include "hos_defines.h"
#include "display/kout.h"
#include "functions.h"
#include "lang/lang.h"
}
#include "vfs.h"
#include "fs/FileSystem.h"
#include "fs/VFSMount.h"
#include "fs/ext2/ext2.h"
#include "lang/vector.h"
#include "lang/string.h"
#include "devices.h"
/* Internal module function prototypes */
FileSystem *vfs_attempt_mount(device_t device, char *fsType);
mount_func_t vfs_get_mount_func(const string & fsName);
inode_num_t vfs_get_inode(const string & path);
inode_num_t vfs_get_dir_inode(const string & path);
inode_num_t vfs_get_inode_rel(const string & path, inode_num_t start_dir);
inode_num_t vfs_get_dir_entry_inode(inode_num_t dir, const string & fname);
int vfs_stat_inode(inode_num_t inum, vfs_stat_t *statptr);
int vfs_link_deref_inode(inode_num_t inum, char *link);
VFSMount *vfs_get_mount(u32_t mt_id);
vector<string> vfs_split_dirs(const string & path);
OpenDirectory *vfs_open_directory_inode(inode_num_t inum, int mode);
OpenFile *vfs_open_file_inode(inode_num_t inum, int mode);
void vfs_close_directory_real(OpenDirectory *o);
void vfs_close_file_real(OpenFile *o);
inode_num_t vfs_get_real_inode(inode_num_t inum);
/* Global module data members */
vector<VFSMount *> *mountPoints;
vector<FSHandle> *fses;
u32_t mount_id = 0;
/* initialize the VFS module */
int vfs_init()
{
mountPoints = new vector<VFSMount *>;
fses = new vector<FSHandle>;
ext2_init();
return 0;
}
/* register a filesystem driver to the VFS module */
int vfs_register(char *fs, mount_func_t mount_func)
{
string fsName(fs);
if (vfs_get_mount_func(fsName))
return -1;
FSHandle fsh = {fsName, mount_func};
fses->add(fsh);
return 0;
}
/* mount a device with a filesystem to a mount point */
int vfs_mount(device_t device, char *fsType, char *mountPoint)
{
string mountPt(mountPoint);
string fsName(fsType);
/* Bad filesystem type */
if (!vfs_get_mount_func(fsName))
{
kprintf("vfs_mount: %s: unrecognized filesystem\n", fsType);
return -501;
}
if (mountPt == "/")
{
if (mountPoints->size())
{
kprintf("/ must be the first filesystem mounted!\n");
return -1;
}
FileSystem *fs = vfs_attempt_mount(device, fsType);
/* Couldn't mount root */
if (fs == NULL)
return -2;
mountPoints->add(new VFSMount(device, fsName, fs, mountPt, 0, fs->getRootInodeNumber()));
mount_id++;
return 0;
}
inode_num_t mtInode = vfs_get_inode(mountPt);
/* Invalid mount point */
if (mtInode == 0)
return -3;
FileSystem *fs = vfs_attempt_mount(device, fsType);
/* Couldn't mount */
if (fs == NULL)
return -2;
inode_num_t thisInode = (((u64_t)(mount_id++)) << 32) | fs->getRootInodeNumber();
mountPoints->add(new VFSMount(device, fsName, fs, mountPt, mtInode, thisInode));
return 0;
}
/* get mount information about the mount point */
int vfs_get_mount_info(unsigned int mountNum, vfs_mount_info_t *infoptr)
{
if (mountNum >= mountPoints->size())
return -1;
VFSMount *mt = (*mountPoints)[mountNum];
strcpy(infoptr->fs, mt->myFSType.data());
strcpy(infoptr->mountPoint, mt->myMountPoint.data());
infoptr->totalBlocks = mt->myFS->totalBlocks();
infoptr->freeBlocks = mt->myFS->freeBlocks();
infoptr->totalInodes = mt->myFS->totalInodes();
infoptr->freeInodes = mt->myFS->freeInodes();
return 0;
}
/* unmount a device */
int vfs_umount(device_t dev)
{
unsigned int max = mountPoints->size();
for (unsigned int i = 0; i < max; i++)
{
if ((*mountPoints)[i]->myDev == dev)
{
if ((*mountPoints)[i]->umount_safe())
return -502;
delete (*mountPoints)[i];
mountPoints->remove(i);
return 0;
}
}
return -501;
}
/* stat a filename */
int vfs_stat(char *name, vfs_stat_t *buff)
{
string sname = string(name);
inode_num_t inum;
if ((inum = vfs_get_inode(sname)) == 0ULL)
return -502;
return vfs_stat_inode(inum, buff);
}
/* dereference a symbolic link */
int vfs_link_deref(char *name, char *buff)
{
string sname = string(name);
inode_num_t inum;
if ((inum = vfs_get_inode(sname)) == 0ULL)
return -502;
return vfs_link_deref_inode(inum, buff);
}
void *vfs_open_dir(char *name)
{
string sname(name);
inode_num_t inum = vfs_get_inode(sname);
return (void *) vfs_open_directory_inode(inum, VFS_MODE_READ);
}
void *vfs_open_file(char *name, int mode)
{
string sname(name);
inode_num_t inum = vfs_get_inode(sname);
return (void *) vfs_open_file_inode(inum, mode);
}
void vfs_close_dir(void *o)
{
vfs_close_directory_real((OpenDirectory *) o);
}
void vfs_close_file(void *o)
{
vfs_close_file_real((OpenFile *) o);
}
int vfs_read_dir(void *o, vfs_dir_entry_t *dirent)
{
OpenDirectory *odir = (OpenDirectory *) o;
return odir->read(dirent);
}
int vfs_seek_dir(void *o, int pos, int mode)
{
OpenDirectory *odir = (OpenDirectory *) o;
return odir->seek(pos, mode);
}
int vfs_read_file(void *o)
{
OpenFile *ofile = (OpenFile *) o;
return ofile->read();
}
int vfs_read_file_block(void *o, void *buf, u32_t num)
{
OpenFile *ofile = (OpenFile *) o;
return ofile->read(buf, num);
}
int vfs_write_file(void *o, int chr)
{
OpenFile *ofile = (OpenFile *) o;
return ofile->write(chr);
}
int vfs_write_file_block(void *o, void *buf, u32_t num)
{
OpenFile *ofile = (OpenFile *) o;
return ofile->write(buf, num);
}
int vfs_seek_file(void *o, int pos, int mode)
{
OpenFile *ofile = (OpenFile *) o;
return ofile->seek(pos, mode);
}
/**************************** Internal functions ****************************/
/* "attempt" a mount */
FileSystem *vfs_attempt_mount(device_t device, char *fsType)
{
mount_func_t mount_func;
if (( mount_func = vfs_get_mount_func(string(fsType)) ))
return mount_func(device);
else
return NULL;
}
/* Trace a file name to make an inode */
inode_num_t vfs_get_inode(const string & path)
{
return vfs_get_inode_rel(path, 0ULL);
}
/* Just get the inode of the directory containing the file */
inode_num_t vfs_get_dir_inode(const string & path)
{
vector<string> paths = vfs_split_dirs(path);
string dirPath("");
for (unsigned int i = 0; i < paths.size()-1; i++)
{
dirPath += "/";
dirPath += paths[i];
}
return vfs_get_inode_rel(dirPath, 0ULL);
}
/* Trace file name to inode starting from this directory (recursive) */
inode_num_t vfs_get_inode_rel(const string & path, inode_num_t start_dir)
{
vector<string> paths = vfs_split_dirs(path);
unsigned int paths_size = paths.size();
inode_num_t currentInum = start_dir;
for (unsigned int i = 0; i < paths_size; i++)
{
currentInum = vfs_get_dir_entry_inode(currentInum, paths[i]);
if (currentInum == 0ULL)
return 0ULL;
currentInum = vfs_get_real_inode(currentInum);
}
return currentInum;
}
/* return the inode of a directory entry in the directory pointed to by dir */
inode_num_t vfs_get_dir_entry_inode(inode_num_t dir, const string & fname)
{
OpenDirectory *odir = vfs_open_directory_inode(dir, VFS_MODE_READ);
if (odir == NULL)
return 0ULL;
vfs_dir_entry_t dir_ent;
inode_num_t inum = 0ULL;
while (vfs_read_dir(odir, &dir_ent) == 0)
{
if (strcmp(dir_ent.name, fname.data()) == 0)
{
inum = (dir & 0xFFFFFFFF00000000ULL) | dir_ent.inum;
break;
}
}
vfs_close_directory_real(odir);
return inum;
}
/* Just split up a string into a vector of strings based on the path
* delimeter character ('/').
*/
vector<string> vfs_split_dirs(const string & path)
{
char *sptr = new char[path.size() + 1];
strcpy(sptr, path.data());
char *bptr = sptr;
char *cptr = sptr;
vector<string> parts;
while (*cptr)
{
if (*cptr == '/')
{
*cptr = 0;
string dir(bptr);
if (dir.size() > 0)
parts.add(dir);
bptr = cptr + 1;
}
cptr++;
}
string dir(bptr);
if (dir.size() > 0)
parts.add(dir);
delete sptr;
return parts;
}
/* Return a pointer to the mount function for a certain file system type */
mount_func_t vfs_get_mount_func(const string & fsName)
{
unsigned int max = fses->size();
for (unsigned int i = 0; i < max; i++)
{
if (fsName == (*fses)[i].name)
return (*fses)[i].mount_func;
}
return NULL;
}
/* Return a pointer to a VFSMount by the "mount id" (upper 32 bits of inode) */
VFSMount *vfs_get_mount(u32_t mt_id)
{
int max = mountPoints->size();
for (int i = 0; i < max; i++)
{
if (((*mountPoints)[i]->myThisInode >> 32) == mt_id)
return (*mountPoints)[i];
}
return NULL;
}
/* FS function: stat a inode, return error code */
int vfs_stat_inode(inode_num_t inum, vfs_stat_t *statptr)
{
inum = vfs_get_real_inode(inum);
VFSMount *mt = vfs_get_mount(inum >> 32);
if (mt == NULL)
return -501;
return mt->myFS->stat((u32_t)inum, statptr);
}
/* FS function: dereference a link by inode number, return error code */
int vfs_link_deref_inode(inode_num_t inum, char *link)
{
inum = vfs_get_real_inode(inum);
VFSMount *mt = vfs_get_mount(inum >> 32);
if (mt == NULL)
return -501;
return mt->myFS->link_deref((u32_t)inum, link);
}
/* FS function: open a directory based on the inode number */
OpenDirectory *vfs_open_directory_inode(inode_num_t inum, int mode)
{
inum = vfs_get_real_inode(inum);
VFSMount *mt = vfs_get_mount(inum >> 32);
if (mt == NULL)
return NULL;
return mt->myFS->openDirectory((u32_t)inum, mode);
}
/* FS function: open a file based on the inode number */
OpenFile *vfs_open_file_inode(inode_num_t inum, int mode)
{
inum = vfs_get_real_inode(inum);
VFSMount *mt = vfs_get_mount(inum >> 32);
if (mt == NULL)
return NULL;
return mt->myFS->openFile((u32_t)inum, mode);
}
/* FS function: close a directory */
void vfs_close_directory_real(OpenDirectory *o)
{
delete o;
}
/* FS function: close a file */
void vfs_close_file_real(OpenFile *o)
{
delete o;
}
/* return the "real" inode number based on the given one
* This function enables inode numbers for directories that have something
* mounted in them to be converted to the inode number for the root directory
* of that mounted filesystem
*/
inode_num_t vfs_get_real_inode(inode_num_t inum)
{
unsigned int mounts = mountPoints->size();
for (unsigned int i = 0; i < mounts; i++)
{
if ((*mountPoints)[i]->myMountInode == inum)
return (*mountPoints)[i]->myThisInode;
}
return inum;
}

View File

@ -1,129 +0,0 @@
// vfs.h
// Virtual file system subsystem for HOS
// Author: Josh Holtrop
// Date: 05/10/05
// Modified: 12/26/05
#ifndef __HOS_VFS_H__
#define __HOS_VFS_H__ __HOS_VFS_H__
#define VFS_FT_UNKNOWN 0
#define VFS_FT_FILE 1
#define VFS_FT_DIR 2
#define VFS_FT_CHAR 3
#define VFS_FT_BLOCK 4
#define VFS_FT_FIFO 5
#define VFS_FT_SOCK 6
#define VFS_FT_SYMLINK 7
#define VFS_PERMS_OX 0x0001
#define VFS_PERMS_OW 0x0002
#define VFS_PERMS_OR 0x0004
#define VFS_PERMS_GX 0x0008
#define VFS_PERMS_GW 0x0010
#define VFS_PERMS_GR 0x0020
#define VFS_PERMS_UX 0x0040
#define VFS_PERMS_UW 0x0080
#define VFS_PERMS_UR 0x0100
#define VFS_PERMS_STICKY 0x0200
#define VFS_PERMS_SGID 0x0400
#define VFS_PERMS_SUID 0x0800
#define EOF -256
#define VFS_MAX_FILENAME 255
#define VFS_MAX_PATH_LENGTH 1024
#define SEEK_ABSOLUTE 0
#define SEEK_RELATIVE 1
#define SEEK_END 2
#define VFS_MODE_RW_MASK 0x1
#define VFS_MODE_READ 0x0
#define VFS_MODE_WRITE 0x1
#define VFS_MODE_WRITE_MASK 0x2
#define VFS_MODE_TRUNCATE 0x0
#define VFS_MODE_APPEND 0x2
#include "hos_defines.h"
#include "devices.h"
typedef struct
{
u16_t type; // file type, of VFS_FT_*
u32_t size;
u32_t inode;
u16_t permissions;
u16_t uid;
u16_t gid;
u32_t atime;
u32_t mtime;
u32_t ctime;
u16_t links;
u32_t dev;
} vfs_stat_t;
typedef struct
{
char name[VFS_MAX_FILENAME + 1];
u32_t inum;
} vfs_dir_entry_t;
typedef struct
{
char fs[16];
char mountPoint[256];
u32_t totalBlocks;
u32_t freeBlocks;
u32_t totalInodes;
u32_t freeInodes;
} vfs_mount_info_t;
typedef u64_t inode_num_t;
#ifdef _HOS_CPP_
extern "C" {
#endif
int vfs_init();
int vfs_mount(device_t device, char *fsType, char *mountPoint);
int vfs_umount(device_t dev);
int vfs_stat(char *name, vfs_stat_t *buff);
int vfs_link_deref(char *name, char *buff);
int vfs_get_mount_info(unsigned int mountNum, vfs_mount_info_t *infoptr);
void *vfs_open_dir(char *name);
void *vfs_open_file(char *name, int mode);
void vfs_close_dir(void *o);
void vfs_close_file(void *o);
int vfs_read_dir(void *o, vfs_dir_entry_t *dirent);
int vfs_seek_dir(void *o, int pos, int mode);
int vfs_read_file(void *o);
int vfs_read_file_block(void *o, void *buf, u32_t num);
int vfs_write_file(void *o, int chr);
int vfs_write_file_block(void *o, void *buf, u32_t num);
int vfs_seek_file(void *o, int pos, int mode);
#ifdef _HOS_CPP_
}
#include "lang/string.h"
#include "lang/vector.h"
#include "fs/FileSystem.h"
#include "fs/VFSMount.h"
typedef FileSystem *(*mount_func_t)(device_t);
typedef struct
{
string name;
mount_func_t mount_func;
} FSHandle;
int vfs_register(char *fs, mount_func_t mount_func);
#endif
#endif

View File

@ -1,432 +0,0 @@
// vfs.cpp
// Author: Josh Holtrop
// Date: 08/22/04
// Modified: 12/21/04
#define _HOS_CPP_ _HOS_CPP_
extern "C"
{
#include "hos_defines.h"
#include "display/kout.h"
#include "fs/vfs.h"
#include "fs/ext2.h"
#include "kernel.h"
#include "mm/vmm.h"
#include "lang/lang.h"
}
vfs_fs_t *fses[VFS_MAX_FS]; // a vfs_fs structure for every filesystem we support
vfs_mount_t *mounts;
// basic initialization routine, init all filesystem drivers
int vfs_init()
{
k_check(ext2_init(FS_EXT2), "ext2_init() failed!");
FileSystem fs;
FileSystem *ext2 = new Ext2();
FileSystem *jfs = new JoshsFS();
fs.out();
ext2->out();
jfs->out();
return 0;
}
// called by a filesystem driver to let us know that it is ready to handle fs requests
int vfs_register_fs(int fsn, vfs_fs_t *fs)
{
if (fsn < 0 || fsn >= VFS_MAX_FS || fses[fsn])
{
kprintf("Invalid filesystem register: %d\n", fsn);
return -1;
}
fses[fsn] = fs;
return 0;
}
// called to mount a block device with a certain filesystem to a part of our VFS Mount Tree
int vfs_mount(major_t maj, minor_t min, int fsType, char *mountPoint)
{
if (fsType < 0 || fsType >= VFS_MAX_FS || !fses[fsType])
return -1; // invalid filesystem type
if (!strcmp("/", mountPoint))
{
if (mounts)
return -2; // root already mounted
void *super = fses[fsType]->mount_super(maj, min);
if (!super)
return -3; // didn't mount superblock
vfs_mount_t *mnt = (vfs_mount_t *) New(vfs_mount_t);
mnt->refs = 0;
mnt->fs = fsType;
mnt->major = maj;
mnt->minor = min;
mnt->super = super;
mnt->next = NULL;
mnt->prev = NULL;
mnt->mountPoint = (char *) kmalloc(2);
strcpy(mnt->mountPoint, mountPoint);
mnt->vfs_mount_inode = 0; // root not mounted on another fs
mnt->vfs_root_inode = ((vfs_inode_t)maj << 40) | ((vfs_inode_t)min << 32) | fses[fsType]->get_root_inode(mnt);
mnt->vfs_up_inode = mnt->vfs_root_inode;
mounts = mnt;
return 0; // successfully mounted root
}
if (mountPoint[0] != '/')
return -3; // mount point must be absolute
if (!mounts)
return -4; // no root dir yet
vfs_stat_t stat;
if (vfs_stat(mountPoint, &stat))
return -5; // error statting
if (stat.type != VFS_FT_DIR)
return -6; // mountPoint not a directory
vfs_inode_t vfs_inode = vfs_get_inode_number(mountPoint);
vfs_inode_t updir = vfs_entry_lookup(vfs_inode, "..");
if (!updir || (updir & 0x8000000000000000ULL))
return -7;
void *super = fses[fsType]->mount_super(maj, min);
if (!super)
return -3; // didn't mount superblock
vfs_mount_t *mnt = (vfs_mount_t *) New(vfs_mount_t);
mnt->refs = 0;
mnt->super = super;
mnt->fs = fsType;
mnt->major = maj;
mnt->minor = min;
mnt->mountPoint = (char *) kmalloc(strlen(mountPoint) + 1);
strcpy(mnt->mountPoint, mountPoint);
mnt->vfs_mount_inode = vfs_inode;
mnt->vfs_up_inode = updir;
mnt->vfs_root_inode = ((vfs_inode_t)maj << 40) | ((vfs_inode_t)min << 32) | fses[fsType]->get_root_inode(mnt);
vfs_mount_t *mount = mounts;
while (mount->next)
mount = mount->next;
mount->next = mnt; // add mnt to end of mounts list
mnt->prev = mount;
mnt->next = NULL;
vfs_get_file_addr(updir).mount->refs++;
return -256;
}
int vfs_umount(char *mountPoint)
{
vfs_inode_t vfs_inode = vfs_get_inode_number(mountPoint);
if (!vfs_inode || (vfs_inode & 0x8000000000000000ULL))
return -1; // invalid
vfs_mount_t *mnt = mounts;
while (mnt)
{
if (mnt->vfs_root_inode == vfs_inode) // found mount point to unmount
{
if (mnt->refs)
return -2; // open references to mount point;
if (mnt->prev)
mnt->prev->next = mnt->next;
if (mnt->next)
mnt->next->prev = mnt->prev;
if (mnt == mounts)
mounts = NULL;
kfree(mnt->mountPoint);
kfree(mnt);
return 0;
}
}
return -3; // invalid mount point
}
vfs_inode_t vfs_get_inode_number(char *path)
{
if (path[0] != '/')
return 0;
if (!mounts)
return 0;
return vfs_get_inode_number_rel(mounts->vfs_root_inode, path + 1);
}
vfs_inode_t vfs_get_inode_number_rel(vfs_inode_t dir_inode, char *path)
{
char *path_copy = (char *) kmalloc(strlen(path) + 1);
strcpy(path_copy, path);
int stanzas = str_split(path_copy, '/');
char *lookup = path_copy;
vfs_inode_t vfs_inode = dir_inode;
for (; stanzas > 0; stanzas--)
{
vfs_inode_t vfs_inode_this_dir = vfs_inode;
vfs_inode = (strcmp("", lookup) ? vfs_entry_lookup(vfs_inode, lookup) : vfs_inode_this_dir);
vfs_stat_t stat;
if (vfs_stat_inode(vfs_inode, &stat))
return 0x8000000000000002ULL;
if (stat.type == VFS_FT_SYMLINK)
{
char *link = (char *) kmalloc(4096);
vfs_link_deref(vfs_inode, link);
if (link[0] == '/')
vfs_inode = vfs_get_inode_number(link);
else
vfs_inode = vfs_get_inode_number_rel(vfs_inode_this_dir, link);
kfree(link);
}
if (!vfs_inode || (vfs_inode & 0x8000000000000000ULL))
{
kfree(path_copy);
return 0;
}
lookup = str_advance(lookup);
}
kfree(path_copy);
return vfs_inode;
}
// look for entry in dir_inode, return the vfs_inode for the entry
vfs_inode_t vfs_entry_lookup(vfs_inode_t dir_inode, char *entry)
{
vfs_open_file_t *open_dir = vfs_open_dir_inode(dir_inode);
if (!open_dir)
return 0x8000000000000001ULL;
vfs_dir_entry_t dentry;
while (!vfs_read_dir(open_dir, &dentry))
{
if (!strcmp(dentry.name, entry))
{
vfs_close_dir(open_dir);
return vfs_real_inode((dir_inode & 0xFFFFFFFF00000000ULL) | dentry.inode_number);
}
}
vfs_close_dir(open_dir);
return 0x8000000000000002ULL;
}
// return the "real" vfs inode number (inode of the root of
// a mounted filesystem instead of the inode of the folder
// that the filesystem is mounted to)
vfs_inode_t vfs_real_inode(vfs_inode_t vfs_inode)
{
vfs_mount_t *mnt = mounts;
while (mnt)
{
if (mnt->vfs_mount_inode == vfs_inode)
return mnt->vfs_root_inode;
mnt = mnt->next;
}
return vfs_inode;
}
// translage a vfs inode number into a mount pointer and relative
// inode for a mounted filesystem
vfs_file_addr_t vfs_get_file_addr(vfs_inode_t vfs_inode)
{
vfs_inode = vfs_real_inode(vfs_inode);
vfs_file_addr_t addr = {mounts, vfs_inode & 0xFFFFFFFF};
vfs_mount_t *mnt = mounts;
while (mnt)
{
if ( (mnt->vfs_root_inode & 0xFFFFFFFF00000000ULL) == (vfs_inode & 0xFFFFFFFF00000000ULL) )
{
addr.mount = mnt;
return addr;
}
mnt = mnt->next;
}
return addr;
}
int vfs_mount_count()
{
vfs_mount_t *mnt = mounts;
int count = 0;
while (mnt)
{
count++;
mnt = mnt->next;
}
return count;
}
vfs_mount_t *vfs_get_mount(int index)
{
vfs_mount_t *mnt = mounts;
while (mnt && index)
{
mnt = mnt->next;
index--;
}
if (!index)
return mnt;
return NULL;
}
int vfs_free_inodes(vfs_mount_t *mount)
{
if (fses[mount->fs]->free_inodes)
return fses[mount->fs]->free_inodes(mount);
return -1;
}
int vfs_total_inodes(vfs_mount_t *mount)
{
if (fses[mount->fs]->total_inodes)
return fses[mount->fs]->total_inodes(mount);
return -1;
}
int vfs_free_blocks(vfs_mount_t *mount)
{
if (fses[mount->fs]->free_blocks)
return fses[mount->fs]->free_blocks(mount);
return -1;
}
int vfs_total_blocks(vfs_mount_t *mount)
{
if (fses[mount->fs]->total_blocks)
return fses[mount->fs]->total_blocks(mount);
return -1;
}
vfs_inode_t vfs_alloc_inode(vfs_mount_t *mount)
{
if (fses[mount->fs]->alloc_inode)
{
u32_t fs_inode = fses[mount->fs]->alloc_inode(mount);
if (!fs_inode)
return 0;
return (mount->vfs_root_inode & 0xFFFFFFFF00000000ULL) | fs_inode;
}
return 0;
}
int vfs_free_inode(vfs_mount_t *mount, u32_t inode_number)
{
if (fses[mount->fs]->free_inode)
return fses[mount->fs]->free_inode(mount, inode_number);
return -256;
}
u32_t vfs_alloc_block(vfs_mount_t *mount)
{
if (fses[mount->fs]->alloc_block)
return fses[mount->fs]->alloc_block(mount);
return 0;
}
int vfs_free_block(vfs_mount_t *mount, u32_t block_number)
{
if (fses[mount->fs]->free_block)
return fses[mount->fs]->free_block(mount, block_number);
return -256;
}
int vfs_link_deref(vfs_inode_t vfs_inode, char *link)
{
vfs_stat_t stat;
if (vfs_stat_inode(vfs_inode, &stat))
return -1;
if (stat.type != VFS_FT_SYMLINK)
return -2;
vfs_file_addr_t addr = vfs_get_file_addr(vfs_inode);
if (fses[addr.mount->fs]->link_deref)
return fses[addr.mount->fs]->link_deref(addr.mount, addr.inode, link);
return -3;
}
// stat a file, fills a vfs_stat_t structure with stat information and returns standard status
int vfs_stat(char *file, vfs_stat_t *stat)
{
vfs_inode_t vfs_inode = vfs_get_inode_number(file);
if (!vfs_inode || (vfs_inode & 0x8000000000000000ULL))
return -256;
return vfs_stat_inode(vfs_inode, stat);
}
int vfs_stat_inode(vfs_inode_t vfs_inode, vfs_stat_t *stat)
{
vfs_file_addr_t addr = vfs_get_file_addr(vfs_inode);
if (fses[addr.mount->fs]->stat)
return fses[addr.mount->fs]->stat(addr.mount, addr.inode, stat);
return -257;
}
vfs_open_file_t *vfs_open_dir(char *path)
{
vfs_inode_t vfs_inode = vfs_get_inode_number(path);
if (!vfs_inode || (vfs_inode & 0x8000000000000000ULL))
return NULL;
return vfs_open_dir_inode(vfs_inode);
}
vfs_open_file_t *vfs_open_dir_inode(vfs_inode_t vfs_inode)
{
vfs_file_addr_t addr = vfs_get_file_addr(vfs_inode);
vfs_open_file_t *open_dir = (vfs_open_file_t *) New(vfs_open_file_t);
if (fses[addr.mount->fs]->open_dir && !(fses[addr.mount->fs]->open_dir(addr.mount, addr.inode, open_dir)))
{
open_dir->mount = addr.mount;
return open_dir;
}
kfree(open_dir);
return NULL;
}
int vfs_read_dir(vfs_open_file_t *open_dir, vfs_dir_entry_t *dentry)
{
return !(fses[open_dir->mount->fs]->read_dir &&
!(fses[open_dir->mount->fs]->read_dir(open_dir->mount, open_dir, dentry)));
}
int vfs_close_dir(vfs_open_file_t *open_dir)
{
int status = 0;
if (fses[open_dir->mount->fs]->close_dir)
status = fses[open_dir->mount->fs]->close_dir(open_dir->mount, open_dir);
kfree(open_dir);
return status;
}
vfs_open_file_t *vfs_open_block_file(char *path)
{
vfs_inode_t vfs_inode = vfs_get_inode_number(path);
if (!vfs_inode || (vfs_inode & 0x8000000000000000ULL))
return NULL;
return vfs_open_block_file_inode(vfs_inode);
}
vfs_open_file_t *vfs_open_block_file_inode(vfs_inode_t vfs_inode)
{
vfs_file_addr_t addr = vfs_get_file_addr(vfs_inode);
vfs_open_file_t *open_file = (vfs_open_file_t *) New(vfs_open_file_t);
if (fses[addr.mount->fs]->open_block_file && !(fses[addr.mount->fs]->open_block_file(addr.mount, addr.inode, open_file)))
{
open_file->mount = addr.mount;
return open_file;
}
kfree(open_file);
return NULL;
}
int vfs_read_block_file(vfs_open_file_t *open_file, void *buffer)
{
if (fses[open_file->mount->fs]->read_block_file)
return fses[open_file->mount->fs]->read_block_file(open_file->mount, open_file, buffer);
return 0;
}
int vfs_block_file_seek(vfs_open_file_t *open_file, u32_t block_number)
{
if (fses[open_file->mount->fs]->block_file_seek)
return fses[open_file->mount->fs]->block_file_seek(open_file->mount, open_file, block_number);
return -1;
}
int vfs_close_block_file(vfs_open_file_t *open_file)
{
int status = 0;
if (fses[open_file->mount->fs]->close_block_file)
status = fses[open_file->mount->fs]->close_block_file(open_file->mount, open_file);
kfree(open_file);
return status;
}

View File

@ -1,165 +0,0 @@
// vfs.h
// Author: Josh Holtrop
// Date: 08/22/04
// Modified: 12/21/04
#ifndef __HOS_VFS_H__
#define __HOS_VFS_H__ __HOS_VFS_H__
#include "hos_defines.h"
#include "fs/devices.h"
#define FS_EXT2 1
#define VFS_MAX_FS 10
#define VFS_FT_UNKNOWN 0
#define VFS_FT_FILE 1
#define VFS_FT_DIR 2
#define VFS_FT_CHAR 3
#define VFS_FT_BLOCK 4
#define VFS_FT_FIFO 5
#define VFS_FT_SOCK 6
#define VFS_FT_SYMLINK 7
#define VFS_PERMS_OX 0x0001
#define VFS_PERMS_OW 0x0002
#define VFS_PERMS_OR 0x0004
#define VFS_PERMS_GX 0x0008
#define VFS_PERMS_GW 0x0010
#define VFS_PERMS_GR 0x0020
#define VFS_PERMS_UX 0x0040
#define VFS_PERMS_UW 0x0080
#define VFS_PERMS_UR 0x0100
#define VFS_PERMS_STICKY 0x0200
#define VFS_PERMS_SGID 0x0400
#define VFS_PERMS_SUID 0x0800
#define EOF 1000000
typedef u64_t vfs_inode_t;
/* Structure to hold information about a mount point */
typedef struct vfs_mount_s
{
int refs;
void *super;
int fs;
major_t major;
minor_t minor;
char *mountPoint;
vfs_inode_t vfs_mount_inode;
vfs_inode_t vfs_up_inode;
vfs_inode_t vfs_root_inode;
struct vfs_mount_s *next;
struct vfs_mount_s *prev;
} vfs_mount_t;
typedef struct
{
u16_t type; // file type, of VFS_FILE_TYPE_*
u32_t size;
u32_t inode;
u16_t permissions;
u16_t uid;
u16_t gid;
u32_t atime;
u32_t mtime;
u32_t ctime;
u16_t links;
u32_t dev;
} vfs_stat_t;
typedef struct
{
vfs_mount_t *mount;
void *fs_data;
} vfs_open_file_t;
typedef struct
{
char name[257];
u32_t inode_number; // relative inode number returned from fs
} vfs_dir_entry_t;
typedef struct
{
vfs_mount_t *mount;
u32_t inode;
} vfs_file_addr_t;
/* Every filesystem must provide pointers to its respective functions in a structure like this */
typedef struct
{
void *(*mount_super)(major_t major, minor_t minor);
int (*umount_super)(vfs_mount_t *mount);
int (*stat)(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat);
u32_t (*get_root_inode)(vfs_mount_t *mount);
int (*link_deref)(vfs_mount_t *mount, u32_t inode_number, char *link);
int (*free_inodes)(vfs_mount_t *mount);
int (*total_inodes)(vfs_mount_t *mount);
int (*free_blocks)(vfs_mount_t *mount);
int (*total_blocks)(vfs_mount_t *mount);
u32_t (*alloc_inode)(vfs_mount_t *mount);
int (*free_inode)(vfs_mount_t *mount, u32_t inode_number);
u32_t (*alloc_block)(vfs_mount_t *mount);
int (*free_block)(vfs_mount_t *mount, u32_t block_number);
int (*open_dir)(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir);
int (*read_dir)(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry);
int (*close_dir)(vfs_mount_t *mount, vfs_open_file_t *dir);
int (*open_file)(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
int (*read_file)(vfs_mount_t *mount, vfs_open_file_t *open_file);
int (*close_file)(vfs_mount_t *mount, vfs_open_file_t *open_file);
int (*open_block_file)(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file);
int (*read_block_file)(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer);
int (*block_file_seek)(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number);
int (*close_block_file)(vfs_mount_t *mount, vfs_open_file_t *open_file);
} vfs_fs_t;
int vfs_init();
int vfs_mount(major_t maj, minor_t min, int fsType, char *mountPoint);
int vfs_umount(char *mountPoint);
int vfs_register_fs(int fsn, vfs_fs_t *fs);
int vfs_umount(char *mountPoint);
vfs_inode_t vfs_get_inode_number(char *path);
vfs_inode_t vfs_get_inode_number_rel(vfs_inode_t dir_inode, char *path);
vfs_inode_t vfs_real_inode(vfs_inode_t vfs_inode);
vfs_file_addr_t vfs_get_file_addr(vfs_inode_t vfs_inode);
vfs_inode_t vfs_entry_lookup(vfs_inode_t dir_inode, char *entry);
int vfs_mount_count();
vfs_mount_t *vfs_get_mount(int index);
int vfs_free_inodes(vfs_mount_t *mount);
int vfs_total_inodes(vfs_mount_t *mount);
int vfs_free_blocks(vfs_mount_t *mount);
int vfs_total_blocks(vfs_mount_t *mount);
vfs_inode_t vfs_alloc_inode(vfs_mount_t *mount);
int vfs_free_inode(vfs_mount_t *mount, u32_t inode_number);
u32_t vfs_alloc_block(vfs_mount_t *mount);
int vfs_free_block(vfs_mount_t *mount, u32_t block_number);
int vfs_link_deref(vfs_inode_t vfs_inode, char *link);
int vfs_stat(char *file, vfs_stat_t *stat);
int vfs_stat_inode(vfs_inode_t vfs_inode, vfs_stat_t *stat);
vfs_open_file_t *vfs_open_dir(char *path);
vfs_open_file_t *vfs_open_dir_inode(vfs_inode_t inode);
int vfs_read_dir(vfs_open_file_t *open_dir, vfs_dir_entry_t *dentry);
int vfs_close_dir(vfs_open_file_t *open_dir);
vfs_open_file_t *vfs_open_block_file(char *file);
vfs_open_file_t *vfs_open_block_file_inode(vfs_inode_t vfs_inode);
int vfs_read_block_file(vfs_open_file_t *open_file, void *buffer);
int vfs_block_file_seek(vfs_open_file_t *open_file, u32_t block_number);
int vfs_close_block_file(vfs_open_file_t *open_file);
#endif

View File

@ -1,105 +0,0 @@
//functions.h
//05/07/03 Josh Holtrop
//for HOS
//Modified: 02/26/04
#ifndef __HOS_FUNCTIONS__
#define __HOS_FUNCTIONS__ __HOS_FUNCTIONS__
#include "hos_defines.h"
#include "sys/io.h"
extern u32_t _code;
extern u32_t _bss;
extern u32_t _end;
//Enables (SeTs) Interrupt Flag on the processor
static inline void enable_ints()
{
asm("sti");
}
//Disables (CLears) Interrupt Flag on the processor
static inline void disable_ints()
{
asm("cli");
}
//Restarts the computer
static inline void restart()
{
enable_ints();
byte temp;
do
{
temp = inportb(0x64);
if (temp & 1)
inportb(0x60);
} while(temp & 2);
outportb (0x64, 0xfe);
for (;;) {}
}
//Halts (freezes) the computer
static inline void halt()
{
asm("cli");
asm("hlt");
while (1) ;
}
//Initializes 8253 Programmable Interrupt Timer
static inline void timer_init(u32_t freq)
{
u32_t wait = 1193180 / freq; //how many ticks the PIT must wait before issuing an interrupt
outportb(0x43, 0x34);
outportb(0x40, wait); //lsb
outportb(0x40, wait >> 8); //msb
}
//Returns the size of the kernel (code & data & bss)
// - this should be 4kb aligned per the linker script
// - this is the amount of RAM the kernel code, data, & bss take
static inline u32_t kernel_size_used()
{
return (u32_t)(&_end)-(u32_t)(&_code);
}
//Returns the size of the kernel (code & data)
// - this does not include the bss section
// - this should be 4kb aligned per the linker script
// - this should be the size of kernel.bin
static inline u32_t kernel_size()
{
return (u32_t)(&_bss)-(u32_t)(&_code);
}
//converts a binary-coded-decimal byte to its decimal equivalent
static inline byte bcd2byte(byte bcd)
{
return (10 * ((bcd & 0xF0) >> 4)) + (bcd & 0x0F);
}
//converts a binary-coded-decimal byte to its decimal equivalent
static inline byte byte2bcd(byte bite)
{
return ((bite / 10) << 4) | (bite % 10);
}
// get the maximum of two values
static inline u32_t max(u32_t v1, u32_t v2)
{
return ( (v2 > v1) ? v2 : v1 );
}
// get the minimum of two values
static inline u32_t min(u32_t v1, u32_t v2)
{
return ( (v2 > v1) ? v1 : v2 );
}
#endif

View File

@ -1,57 +0,0 @@
;gdt.inc
;Author: Josh Holtrop
;Date: 10/30/03
;Modified: 03/02/04
gdtr:
dw gdt_end-gdt-1
dd GDT_V
gdt: ; 0
dd 0
dd 0
KERNEL_CODE equ $-gdt ; 8
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x9A ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
KERNEL_DATA equ $-gdt ; 16
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
USER_CODE equ $-gdt ; 24
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0xFA ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
USER_DATA equ $-gdt ; 32
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0xF2 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
TSS0_SEG equ $-gdt ; 40
dw 0x67 ;limit 15:0
dw 0 ;base 15:0
db 0 ;base 23:16
db 0xE9 ;access ([P][DPL][0][1][0][Busy][1])
db 0x00 ;flags ([G][0][0][AVL]) / limit 19:16
db 0 ;base 31:24
gdt_end:

View File

@ -1,52 +0,0 @@
// hos_defines.h
// Author: Josh Holtrop
// Date: 08/15/04
// Modified: 08/16/04
#ifndef __HOS_DEFINES_H__
#define __HOS_DEFINES_H__ __HOS_DEFINES_H__
#define PARALLEL_DEBUG
#define HOS_TIMER_FREQ 1000
#define KERNEL_MSG_CONSOLE 11
#define VIRT_OFFSET 0xC0000000
#define PHYS_LOAD 0x00108000
#define PDBR 0x00104000
#define VIRT_STACK_TOP 0xD0000000
#define HEAP_START 0xD0000000
#define HEAP_LENGTH 0x20000000
#define CONSOLE_MEMORY 0xC00B8000
#define BIOS_CHAR_MAP 0xC00FFA6E
#define LFB_MEMORY 0xF0000000
#define SEG_KERNEL_CODE 8
#define SEG_KERNEL_DATA 16
#define SEG_USER_CODE 24
#define SEG_USER_DATA 32
#define SEG_TSS0 40
#define MAX_MODULES 16
#define MAX_MMAP 16
#define NULL 0
#define HOS_INIT_TASK "/bin/init"
#define New(x) kcalloc(1, sizeof(x))
typedef unsigned long long u64_t;
typedef unsigned int u32_t;
typedef unsigned short u16_t;
typedef unsigned char u8_t;
typedef unsigned char byte;
typedef int lock_t;
extern u32_t _end;
extern u32_t _bss;
extern u32_t start;
#endif

View File

@ -1,117 +0,0 @@
;idt.inc
;Author: Josh Holtrop
;Date: 10/30/03
;Modified: 01/02/06
idtr:
dw 50*8-1 ;size of idt
dd IDT_V ;address of idt
%macro isr_label 1
isr_%1:
push eax
mov eax, %1
jmp isr_main
%endmacro
isr_label 0
isr_label 1
isr_label 2
isr_label 3
isr_label 4
isr_label 5
isr_label 6
isr_label 7
isr_label 8
isr_label 9
isr_label 10
isr_label 11
isr_label 12
isr_label 13
isr_label 14
isr_label 15
isr_label 16
isr_label 17
isr_label 18
isr_label 19
isr_label 20
isr_label 21
isr_label 22
isr_label 23
isr_label 24
isr_label 25
isr_label 26
isr_label 27
isr_label 28
isr_label 29
isr_label 30
isr_label 31
isr_label 32
isr_label 33
isr_label 34
isr_label 35
isr_label 36
isr_label 37
isr_label 38
isr_label 39
isr_label 40
isr_label 41
isr_label 42
isr_label 43
isr_label 44
isr_label 45
isr_label 46
isr_label 47
isr_label 48
isr_label 49
isr_main:
; ok, here, we need to duplicate the top item on the stack
; (the old eax) 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
cmp eax, 8
jz isr_main_nodup ; if int=8, no dup
cmp eax, 10
jb isr_main_dup ; if int<10, dup
cmp eax, 14
jbe isr_main_nodup ; if int<=14, no dup
isr_main_dup: ; else dup
sub esp, 4
push eax
mov eax, [esp+8]
mov [esp+4], eax
pop eax
isr_main_nodup:
push ebx
push ecx
push edx
push edi
push esi
push ebp
push ds
push es
push fs
push gs
push esp
push eax ;interrupt number
call _isr
add esp, 8
pop gs
pop fs
pop es
pop ds
pop ebp
pop esi
pop edi
pop edx
pop ecx
pop ebx
add esp, 4 ;bypass error code
pop eax ;original saved eax
iret

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

View File

@ -1,288 +0,0 @@
/* kernel.h
* Author: Josh Holtrop
* Date: 08/16/04
* Modified: 11/02/05
* This is the main kernel initialization and boot-strapping file
*/
#include "kernel.h"
#include "multiboot.h"
#include "module.h"
#include "lang/lang.h"
#include "functions.h"
#include "mm/mm.h"
#include "mm/vmm.h"
#include "lang/conv.h"
#include "devices.h"
#include "display/display.h"
#include "display/kout.h"
#include "sys/io.h"
#include "sys/pic.h"
#include "char/keyboard.h"
#include "block/ramdisk.h"
#include "fs/vfs.h"
#include "fs/ext2/ext2.h"
#include "sys/pci.h"
#include "proc/proc.h"
#include "syscall.h"
mb_info_t mb_info_block;
mb_mmap_t mb_mmap[MAX_MMAP];
u32_t mmap_entries;
mb_module_t mb_modules[MAX_MODULES];
mb_apm_t mb_apm_table;
mb_module_t *real_mode_module; // pointer to real mode module (if present)
real_mode_param_t rm_params;
char mb_cmdline[256];
int criticalCounter; // semaphore for if interrupts are disabled
u32_t timer; // number of IRQ 0's
extern u32_t mm_freepages;
extern u32_t proc_new_esp;
extern u32_t cur_task;
/* This function runs in segmented memory - 0xC000_0000 is mapped to 0x0 but 0x0
itself is an invalid linear address. Therefore, the multiboot information addresses
must be manually adjusted by VIRT_OFFSET to become valid linear addresses. */
mb_module_t *k_mbsave(mb_info_t *mbinfo, unsigned int mb_magic)
{
real_mode_module = NULL;
if (mb_magic != MULTIBOOT_BOOTLOADER_MAGIC)
{
char *msg = "Bad multiboot magic identifier!";
char *dest = (char *) CONSOLE_MEMORY;
while (*msg)
{
*dest++ = *msg++;
*dest++ = 0x04; //red error message
}
for (;;) ;
}
mb_info_block = *mbinfo;
if (mb_info_block.flags & MB_BOOTLOADER_COMMAND_LINE)
{
mb_info_block.cmdline += VIRT_OFFSET;
memcpy(mb_cmdline, (void *)mb_info_block.cmdline, 256);
mb_cmdline[255] = 0;
}
if (mb_info_block.flags & MB_BOOTLOADER_MODS)
{
mb_info_block.mods_addr += VIRT_OFFSET;
int i;
for (i = 0; i < mb_info_block.mods_count && i < MAX_MODULES; i++)
{
mb_modules[i] = ((mb_module_t *)mb_info_block.mods_addr)[i];
mb_modules[i].mod_start += VIRT_OFFSET;
mb_modules[i].mod_end += VIRT_OFFSET;
hos_module_header_t *mod = (hos_module_header_t *)mb_modules[i].mod_start;
if (mod->mod_magic == 0x4D534F48 && mod->mod_type == MOD_REAL_MODE)
real_mode_module = &mb_modules[i];
}
}
if (mb_info_block.flags & MB_BOOTLOADER_MMAP)
{
mb_info_block.mmap_addr += (VIRT_OFFSET - 4); //-4 to get to size field, not base_addr_low field
mb_mmap_t *mmap = (mb_mmap_t *)mb_info_block.mmap_addr;
int i, sz = 0;
for (i = 0; sz < mb_info_block.mmap_length && i < MAX_MMAP; i++)
{
sz += mmap->size + 4;
mb_mmap[i] = *mmap;
mmap = (mb_mmap_t *)(((u32_t) mmap) + mmap->size + 4);
mmap_entries++;
}
}
if (mb_info_block.flags & MB_BOOTLOADER_APM)
{
mb_info_block.apm_table += VIRT_OFFSET;
mb_apm_table = *(mb_apm_t *)mb_info_block.apm_table;
}
return real_mode_module;
}
/* Main kernel initialization routine */
void k_init()
{
criticalCounter++;
pic_remap(0x20, 0x28);
pic_mask1(0); //unmask IRQ's 0-7
pic_mask2(0); //unmask IRQ's 8-15
timer_init(HOS_TIMER_FREQ);
mm_init();
vmm_init();
devices_init();
if (real_mode_module)
{
if (rm_params.vid_addr) // there is video memory to map in
{
u32_t vid_mem = rm_params.width * rm_params.height;
switch (rm_params.bpp)
{
case 15: case 16:
vid_mem <<= 1; break;
case 24:
vid_mem *= 3; break;
case 32:
vid_mem <<= 2; break;
}
// map in video memory so we can access the video card's LFB
vmm_mapn(LFB_MEMORY, (u32_t)rm_params.vid_addr, (vid_mem >> 12) + 1);
}
}
display_init(); // initialize display subsystem
kprintf("HOS v0.16 initializing...\n");
kprintf("Kernel load line: '%s'\n", mb_cmdline);
kprintf("Kernel load size: %d (0x%x) bytes (%d kb)\n", kernel_size(), kernel_size(), kernel_size() >> 10);
kprintf("Kernel memory size: %d (0x%x) bytes (%d kb)\n", kernel_size_used(), kernel_size_used(), kernel_size_used() >> 10);
k_check(pci_init(), "pci_init() failed!");
k_check(vfs_init(), "vfs_init() failed!");
k_check(proc_init(), "proc_init() failed!");
int i;
for (i = 0; i < mb_info_block.mods_count; i++)
{
kprintf("Loaded kernel module %d: 0x%x - 0x%x (%d bytes, type %d)\n", i, mb_modules[i].mod_start, mb_modules[i].mod_end, mb_modules[i].mod_end - mb_modules[i].mod_start, ((hos_module_header_t*)mb_modules[i].mod_start)->mod_type);
if (((mb_modules[i].mod_end - mb_modules[i].mod_start) > 2048) &&
((ext2_super_block_t *)(mb_modules[i].mod_start + 1024))->s_magic == EXT2_MAGIC)
{
// we found an initrd
minor_t initrd_minor = ramdisk_register((void *)mb_modules[i].mod_start, mb_modules[i].mod_end - mb_modules[i].mod_start);
kprintf("initrd (%dkb) loaded\n", (mb_modules[i].mod_end - mb_modules[i].mod_start) >> 10);
k_check(vfs_mount(DEV(MAJOR_RAMDISK, initrd_minor), "ext2", "/"), "Kernel panic: Could not mount initrd to /!");
}
}
void *root = vfs_open_dir("///");
char name[VFS_MAX_PATH_LENGTH];
if (root)
{
vfs_dir_entry_t dentry;
vfs_stat_t fstat;
while (!vfs_read_dir(root, &dentry))
{
strcpy(name, "/");
strcat(name, dentry.name);
vfs_stat(name, &fstat);
kprintf("%d\t", fstat.inode);
putc(fstat.type == VFS_FT_DIR ? 'd' : fstat.type == VFS_FT_CHAR ? 'c' : fstat.type == VFS_FT_BLOCK ? 'b' : fstat.type == VFS_FT_SYMLINK ? 'l' : '-');
putc(fstat.permissions & VFS_PERMS_UR ? 'r' : '-');
putc(fstat.permissions & VFS_PERMS_UW ? 'w' : '-');
putc(fstat.permissions & VFS_PERMS_UX ? 'x' : '-');
putc(fstat.permissions & VFS_PERMS_GR ? 'r' : '-');
putc(fstat.permissions & VFS_PERMS_GW ? 'w' : '-');
putc(fstat.permissions & VFS_PERMS_GX ? 'x' : '-');
putc(fstat.permissions & VFS_PERMS_OR ? 'r' : '-');
putc(fstat.permissions & VFS_PERMS_OW ? 'w' : '-');
putc(fstat.permissions & VFS_PERMS_OX ? 'x' : '-');
kprintf(" %d\t%d\t%d\t%d\t%s", fstat.links, fstat.uid, fstat.gid, fstat.size, dentry.name);
if (fstat.type == VFS_FT_CHAR || fstat.type == VFS_FT_BLOCK)
kprintf("\t(%d, %d)", fstat.dev >> 8, fstat.dev & 0xFF);
if (fstat.type == VFS_FT_SYMLINK)
{
char *link = kmalloc(4096);
vfs_link_deref(name, link);
kprintf(" -> %s", link);
kfree(link);
}
putc('\n');
}
vfs_close_dir(root);
}
else
kprintf("Error: Could not open directory\n");
/* Create the initial task */
vfs_stat_t stat;
if (!vfs_stat(HOS_INIT_TASK, &stat))
{
if (stat.permissions &
(VFS_PERMS_UX | VFS_PERMS_GX | VFS_PERMS_UX))
{
u8_t *buf = kmalloc(stat.size);
void *file = vfs_open_file(HOS_INIT_TASK, VFS_MODE_READ);
vfs_read_file_block(file, buf, stat.size);
vfs_close_file(file);
create_task(buf, stat.size, 0, 0);
}
}
criticalCounter--;
}
void isr(u32_t num, int_stack_t *int_stack)
{
criticalCounter++;
switch (num)
{
case 0x0: /* divide by zero */
kprintf("divide by zero, current process: %u\n", cur_task);
break;
case 0x20: // timer
timer++;
(*(u16_t *)CONSOLE_MEMORY)++;
proc_sched(int_stack);
pic_eoi();
break;
case 0x21: // keyboard
isr_keyboard();
pic_eoi();
break;
case 0x30:
syscall(cur_task, int_stack);
break;
case 0x0D: /* general protection (error code) */
kprintf("General protection fault process %u, error #%u\n", cur_task, int_stack->error);
break;
case 0x0E: /* Page fault (error code) */
kprintf("Page fault process %u, error #%u\n", cur_task, int_stack->error);
break;
case 0x01: /* debug exception */
case 0x02: /* non-maskable interrupt */
case 0x03: /* breakpoint */
case 0x04: /* overflow */
case 0x05: /* bound exception */
case 0x06: /* invalid opcode */
case 0x07: /* FPU not available */
case 0x08: /* Double fault (error code) */
case 0x09: /* coprocessor segment overrun */
case 0x0A: /* invalid TSS (error code) */
case 0x0B: /* segment not present (error code) */
case 0x0C: /* stack exception (error code) */
case 0x10: /* floating point error */
case 0x11: /* alignment check */
case 0x12: /* machine check */
default:
kprintf("Unhandled interrupt #%d, CR2 = 0x%x, int_stack at 0x%x!\n", num, read_cr2(), int_stack);
halt();
}
criticalCounter--;
}
void k_enter_critical() // functions for implementing "atomic actions"
{
disable_ints();
criticalCounter++;
}
void k_leave_critical()
{
criticalCounter--;
if (!criticalCounter)
enable_ints();
}
void k_check(int val, char *msg)
{
if (val)
{
kprintf("\e[31;1m%s\n", msg);
halt();
}
}

View File

@ -1,53 +0,0 @@
// kernel.h
// Author: Josh Holtrop
// Date: 08/16/04
// Modified: 08/18/05
#ifndef __HOS_KERNEL_H__
#define __HOS_KERNEL_H__ __HOS_KERNEL_H__
#include "hos_defines.h"
#include "multiboot.h"
typedef struct
{
void *vid_addr; // address of LFB, 0 if console mode
u32_t width; // width in pixels or columns if vid_mem == 0
u32_t height; // height in pixels or columns if vid_mem == 0
u32_t bpp; // bits per pixel - 15/16/24/32
} __attribute__ ((packed)) real_mode_param_t;
typedef struct
{
u32_t gs;
u32_t fs;
u32_t es;
u32_t ds;
u32_t ebp;
u32_t esi;
u32_t edi;
u32_t edx;
u32_t ecx;
u32_t ebx;
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;
/* returns true to callee if we should jump to a real mode module */
mb_module_t *k_mbsave(mb_info_t *mbinfo, unsigned int mb_magic);
void _init();
void isr(u32_t num, int_stack_t *stack_frame);
void k_enter_critical(); // functions for implementing "atomic actions"
void k_leave_critical();
void k_check(int val, char *msg);
#endif

2
kernel/lang/Makefile Normal file
View File

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

View File

@ -1,109 +0,0 @@
// conv.h
// Author: Josh Holtrop
// Date: 08/02/04
// Modified: 12/30/04
#include "conv.h"
#include "hos_defines.h"
// BCD to string
// returns number of characters generated before null terminator
int bcdtoa(u32_t bcd, char *buf)
{
*buf++ = ((bcd & 0xF0) >> 4) + '0';
*buf++ = (bcd & 0xF) + '0';
*buf = 0;
return 2;
}
// convert integer to hexadecimal string
int itox(u32_t num, char *buf)
{
int s, i = 0;
for (s = 28; s >= 0; s -= 4)
{
u32_t val = (num >> s) & 0xF;
if (i || val || (!s))
{
val = (val > 9) ? (val + 'A' - 10) : (val + '0');
buf[i++] = val;
}
}
buf[i] = 0;
return i - 1;
}
// convert integer to an octal string
int itoo(u32_t num, char *buf)
{
int s, i = 0;
for (s = 30; s >= 0; s -= 3)
{
u32_t val = (num >> s) & 0x7;
if (i || val || (!s))
buf[i++] = val + '0';
}
buf[i] = 0;
return i - 1;
}
// convert signed integer to decimal string
int itoa(int num, char *buf)
{
// 4,294,967,296
int hitNum = 0, i = 0, mod, val;
if (num < 0)
{
buf[i++] = '-';
num = -num;
}
for (mod = 1000000000; mod >= 1; mod /= 10)
{
val = num / mod;
num %= mod;
if (val || (mod == 1))
hitNum = 1;
if (hitNum)
{
buf[i++] = val + '0';
}
}
buf[i] = 0;
return i - 1;
}
// convert an unsigned integer to decimal string
int utoa(u32_t num, char *buf)
{
// 4,294,967,296
int hitNum = 0, i = 0, mod, val;
for (mod = 1000000000; mod >= 1; mod /= 10)
{
val = num / mod;
num %= mod;
if (val || (mod == 1))
hitNum = 1;
if (hitNum)
{
buf[i++] = val + '0';
}
}
buf[i] = 0;
return i - 1;
}
char asciiSwitchCase(char chr)
{
if (chr >= 'A' && chr <= 'Z')
return chr + ('a' - 'A');
if (chr >= 'a' && chr <= 'z')
return chr - ('a' - 'A');
return chr;
}

View File

@ -1,20 +0,0 @@
// conv.h
// Author: Josh Holtrop
// Date: 08/02/04
// Modified: 12/30/04
#ifndef __HOS_CONV__
#define __HOS_CONV__ __HOS_CONV__
#include "hos_defines.h"
int bcdtoa(u32_t bcd, char *buf);
int itox(u32_t num, char *buf);
int itoo(u32_t num, char *buf);
int itoa(int num, char *buf);
int utoa(u32_t num, char *buf);
char asciiSwitchCase(char chr);
#endif

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

View File

@ -1,362 +0,0 @@
; lang.asm
; Josh Holtrop
; Created: 10/23/03
; Modified: 12/30/04
[bits 32]
%macro jzfar 1
jnz %%skip
jmp %1
%%skip:
%endmacro
;implements a lock
[global _lock]
_lock:
push ebp
mov ebp, esp
push eax
push ebx
push esi
mov esi, [ebp + 8]
_lock_loop0:
xor eax, eax
mov ebx, 1
cmpxchg [esi], ebx
jnz _lock_loop0 ; failed to acquire lock
pop esi
pop ebx
pop eax
pop ebp
ret
;releases a lock
[global _unlock]
_unlock:
push ebp
mov ebp, esp
push esi
mov esi, [ebp + 8]
mov [esi], dword 0
pop esi
pop ebp
ret
;returns the value in the CR0 register
;extern dword read_cr0();
[global _read_cr0]
_read_cr0:
mov eax, cr0;
ret
;stores the parameter to the CR0 register
;extern dword write_cr0(dword cr0);
[global _write_cr0]
_write_cr0:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov cr0, eax
pop ebp
ret
;returns the value in the CR2 register
;extern dword read_cr2();
[global _read_cr2]
_read_cr2:
mov eax, cr2;
ret
;returns the value in the CR3 register
;extern dword read_cr3();
[global _read_cr3]
_read_cr3:
mov eax, cr3;
ret
;stores the parameter to the CR3 register
;extern dword write_cr3(dword cr3);
[global _write_cr3]
_write_cr3:
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov cr3, eax
pop ebp
ret
; read ss register
[global _read_ss]
_read_ss:
mov ax, ss
ret
;copies a string from the source to the destination parameter
;extern void strcpy(char *dest, char *src);
[global _strcpy]
_strcpy:
push ebp
mov ebp, esp
push esi
push edi
mov edi, [ebp+8]
mov esi, [ebp+12]
strcpyloop:
lodsb
stosb
or al, al
jnz strcpyloop
pop edi
pop esi
pop ebp
ret
;copies memory of n bytes from src to destination
;void memcpy(void *dest, void *src, dword n);
[global _memcpy]
_memcpy:
push ebp
mov ebp, esp
push esi
push edi
push ecx
mov edi, [ebp+8]
mov esi, [ebp+12]
mov ecx, [ebp+16]
cld
rep movsb
pop ecx
pop edi
pop esi
pop ebp
ret
;copies memory of n words (n*2 bytes) from src to destination
;void memcpyw(void *dest, void *src, dword n);
[global _memcpyw]
_memcpyw:
push ebp
mov ebp, esp
push esi
push edi
push ecx
mov edi, [ebp+8]
mov esi, [ebp+12]
mov ecx, [ebp+16]
cld
rep movsw
pop ecx
pop edi
pop esi
pop ebp
ret
;copies memory of n dwords (n*4 bytes) from src to destination
;void memcpyd(void *dest, void *src, dword n);
[global _memcpyd]
_memcpyd:
push ebp
mov ebp, esp
push esi
push edi
push ecx
mov edi, [ebp+8]
mov esi, [ebp+12]
mov ecx, [ebp+16]
cld
rep movsd
pop ecx
pop edi
pop esi
pop ebp
ret
;sets num bytes at buffer to the value of c
;void *memset(void *buffer, int c, int num);
[global _memset]
_memset:
push ebp
mov ebp, esp
push edi
push ecx
mov edi, [ebp+8]
push edi ;save for return address
mov eax, [ebp+12]
mov ecx, [ebp+16]
rep stosb
pop eax
pop ecx
pop edi
pop ebp
ret
;sets num words at buffer to the value of c
;void *memsetw(void *buffer, int c, int num);
[global _memsetw]
_memsetw:
push ebp
mov ebp, esp
push edi
push ecx
mov edi, [ebp+8]
push edi ;save for return address
mov eax, [ebp+12]
mov ecx, [ebp+16]
rep stosw
pop eax
pop ecx
pop edi
pop ebp
ret
;sets num dwords at buffer to the value of c
;void *memsetd(void *buffer, int c, int num);
[global _memsetd]
_memsetd:
push ebp
mov ebp, esp
push edi
push ecx
mov edi, [ebp+8]
push edi ;save for return address
mov eax, [ebp+12]
mov ecx, [ebp+16]
rep stosd
pop eax
pop ecx
pop edi
pop ebp
ret
;returns the number of characters in a string
;extern dword strlen(char *str);
[global _strlen]
_strlen:
push ebp
mov ebp, esp
push esi
push ebx
mov esi, [ebp+8]
xor ebx, ebx
strlenloop:
lodsb
or al, al
jz strlendone
inc ebx
jmp strlenloop
strlendone:
mov eax, ebx
pop ebx
pop esi
pop ebp
ret
;this function invalidates the page directory/table entry that
; would be used to access the memory address given in the parameter
;extern void invlpg_(dword addr);
[global _invlpg_]
_invlpg_:
mov eax, [esp+4]
invlpg [eax]
ret
;
;void writeCursorPosition(word pos)
;
[global _writeCursorPosition]
_writeCursorPosition:
push ebp
mov ebp, esp
push eax
push ebx
push edx
mov eax, [ebp+8] ;cursor position in ax
mov bl, al
mov dx, 0x03D4
mov al, 0x0E
out dx, al
inc dx
mov al, ah
out dx, al
dec dx
mov al, 0x0F
out dx, al
inc dx
mov al, bl
out dx, al
pop edx
pop ebx
pop eax
pop ebp
ret
;
;word getCursorPosition()
;
[global _getCursorPosition]
_getCursorPosition:
push ebx
push edx
xor eax, eax
mov dx, 0x03D4
mov al, 0x0E
out dx, al
inc dx
in al, dx
mov bl, al
dec dx
mov al, 0x0F
out dx, al
inc dx
in al, dx
mov ah, bl
pop edx
pop ebx
ret

View File

@ -1,114 +0,0 @@
// lang.c
// Author: Josh Holtrop
// Date: 12/30/04
// Modified: 12/30/04
#include "lang.h"
/* strcmp compares two strings
* Returns:
* 0 if the strings are equal
* <0 if the second string is less than the first
* >0 if the second string is greater than the first
*/
int strcmp(char *str1, char *str2)
{
while (*str1 || *str2)
{
if (*str1 != *str2)
return *str2 - *str1;
str1++;
str2++;
}
return 0;
}
/* strncmp compares up to n characters of two strings
* Returns:
* 0 if the strings are equal
* <0 if the second string is less than the first
* >0 if the second string is greater than the first
*/
int strncmp(char *str1, char *str2, int n)
{
while (n > 0 && (*str1 || *str2))
{
if (*str1 != *str2)
return *str2 - *str1;
str1++;
str2++;
n--;
}
return 0;
}
/* str_change changes a certain character in a string
* to a different character
* Returns: how many characters were changed
*/
int str_change(char *str, char ch1, char ch2)
{
int count = 0;
while (*str)
{
if (*str == ch1)
{
*str = ch2;
count++;
}
str++;
}
return count;
}
// counts the occurrences of lookfor in str
int str_count(char *str, char lookfor)
{
int count = 0;
while (*str)
{
if (*str == lookfor)
count++;
str++;
}
return count;
}
// split the string into substrings by the splitchar, return number of substrings
int str_split(char *str, char splitchar)
{
if (!(*str))
return 0;
int subs = 1;
while (*str)
{
if (*str == splitchar)
{
*str = 0;
subs++;
}
str++;
}
return subs;
}
// advance the string pointer to the next substring, return a pointer to the next substring
char *str_advance(char *str)
{
char *next = str;
while (*next)
next++; // advance pointer to end of this substring (null character)
return next + 1;
}
// concatentate src onto the end of dest
void strcat(char *dest, char *src)
{
while (*dest)
dest++;
strcpy(dest, src);
}

Some files were not shown because too many files have changed in this diff Show More