127 Commits
Author SHA1 Message Date
josh c6ae200a54 Update to rscons 2.3.0
Move cross compiler to i686-elf-gcc directory.
Automatically build cross compiler using rscons subsidiary script.
2021-12-08 11:33:03 -05:00
josh 6b1de7c9d4 Explicitly check page boundaries when adding bootloader-provided memory regions 2021-08-16 17:35:11 -04:00
josh ebfeca47b5 Use size_t rather than uint32_t 2021-08-16 14:01:39 -04:00
josh 43f4a1f4b1 Show kernel size/address 2021-08-16 13:59:39 -04:00
josh 0f73efbdc3 add mm module to manage free physical page regions 2020-10-26 20:17:08 -04:00
josh a084ab296c define _hos_mem_start and _hos_mem_end symbols 2020-10-25 17:08:07 -04:00
josh aa28284187 build kernel .size file on build 2020-10-25 17:06:56 -04:00
josh 87c135b010 set up a GDT to stop using the one GRUB set up 2020-10-25 16:49:09 -04:00
josh 3d30025d3b write a map file when linking 2020-10-25 16:48:42 -04:00
josh 556b0f0c4d add gdt.h 2020-10-23 00:48:40 -04:00
josh bffd652c16 walk multiboot2 memory map 2020-10-23 00:47:19 -04:00
josh cbd427b14b add 64-bit formatting support 2020-10-23 00:46:40 -04:00
josh fa4ff5facf load some multiboot2 info after the framebuffer is initialized 2020-10-22 22:03:43 -04:00
josh db16e69d5d add klog module to print kernel messages 2020-10-20 21:44:21 -04:00
josh 1d3b0a5621 make fb_clear() public 2020-10-20 20:24:48 -04:00
josh d03a34ab3e fb: store fb.pitch in words, not bytes 2020-10-20 20:07:51 -04:00
josh 494ef6de81 add fb_width(), fb_height() 2020-10-20 20:06:54 -04:00
josh 784009ba6c hos_printf: handle field width, zero-padding, and left-justifiying conversion specifiers 2020-10-20 19:56:30 -04:00
josh 9bddf11ee4 stream: use char instead of uint8_t 2020-10-20 19:47:15 -04:00
josh 313b86fdc7 provide an implementation for memcpy() 2020-10-20 19:31:26 -04:00
josh 75491dd36b add hos_printf and stream modules 2020-10-20 19:30:23 -04:00
josh c8db9fe905 add string.h 2020-10-20 17:55:31 -04:00
josh d0cbaba4d1 add memcpy(), memmove(), memset() 2020-10-20 17:47:40 -04:00
josh 1f22d0c900 add a few multiboot2 info structures 2020-10-20 17:34:08 -04:00
josh a474368435 increase kernel font size a little 2020-10-20 17:28:43 -04:00
josh fb88595dec add fb_clear(), just clear to solid bluish color for now 2020-10-20 17:28:16 -04:00
josh 70b4db9dbb fix fb_text_render_char() to use given color 2020-10-20 17:23:51 -04:00
josh 9fde638b6e build with -O2 2020-10-20 15:09:00 -04:00
josh b4b77dd52c add mem.h and memset32() 2020-10-20 15:08:12 -04:00
josh 79951bd0f1 add cross/clean.sh 2020-10-20 14:15:28 -04:00
josh 41152cb4ca add fb_fill() 2020-10-20 14:01:14 -04:00
josh dba3d28bbf draw a character 2020-10-20 13:34:02 -04:00
josh 610f30fae9 generate a built-in kernel font 2020-10-20 00:34:53 -04:00
josh e22b90b768 configure GRUB to boot HOS automatically after 1s 2020-10-20 00:17:05 -04:00
josh 08fc9a5445 rename target run-bios -> run 2020-10-20 00:11:12 -04:00
josh a66df19edc add fb_ready() 2020-10-20 00:09:09 -04:00
josh 5bc844649b set desired framebuffer size to 1600x900x32 2020-10-19 23:57:54 -04:00
josh 0d390465f6 simplify boot.S 2020-10-19 23:42:02 -04:00
josh 04d29fdb71 add mbinfo module to parse multiboot2 boot info 2020-10-19 23:34:42 -04:00
josh e9f426894c rename kernel_main.c -> hos_main.c 2020-10-19 22:40:55 -04:00
josh c8810e4701 rename _start -> hos_start 2020-10-19 22:26:12 -04:00
josh b202eca0cc define startup stack in linker script, not assembly 2020-10-19 22:23:39 -04:00
josh 05de14800b remove hard tabs! 2020-10-19 22:12:34 -04:00
josh 8ae84716d6 rename kernel_main() to hos_main() 2020-10-19 22:12:17 -04:00
josh bb495eceec add "fb" module for framebuffer control 2020-10-19 22:09:33 -04:00
josh 67b90a482f add "clean" target 2020-10-19 21:59:54 -04:00
josh 85e5b76aa3 Move multiboot2 header from assembly to C. 2020-10-19 21:44:27 -04:00
josh 412925a790 switch from multiboot to multiboot2 2020-10-18 14:25:06 -04:00
josh 21afa93c4b fill in framebuffer with more exciting pattern - working in qemu BIOS but lost graphics in qemu EFI 2020-10-18 13:47:35 -04:00
josh d08d54ecbf make run tasks depend on all 2020-10-18 13:29:56 -04:00
josh 06644a02f9 draw pixels to screen to verify framebuffer access and multiboot info 2020-10-18 13:25:26 -04:00
josh 8f9881889b build both BIOS and EFI images 2020-10-18 13:16:02 -04:00
josh a91ea8d620 update Makefile to wrap rscons and add run target 2020-10-15 20:05:58 -04:00
josh a9a2f6dcaf fix GRUB config to add a HOS menu entry 2020-10-15 20:01:40 -04:00
josh 9befd553eb always disassemble kernel when building 2020-10-15 19:47:20 -04:00
josh 6053745ee9 build kernel as 32-bit ELF for now so GRUB can recognize it as multiboot 2020-10-15 19:46:53 -04:00
josh 0adc6e395c Add more modern build script for kernel and disk image based on osdev Bare Bones template
GRUB is not identifying the kernel as multiboot compatible. Possibly
because I am using x86_64 instead of i686. Need to investigate further.
2020-10-14 21:20:41 -04:00
josh bbf212d5a2 add configure script 2020-10-13 19:53:14 -04:00
josh 94ed9078df update rscons 2020-10-13 19:20:19 -04:00
josh e97e76da7b add cross compiler build script and configure script 2020-10-06 20:06:19 -04:00
josh 1f5e3507ba change nasm output format to elf32 2020-10-02 10:21:10 -04:00
josh a9a6f6f4d4 avoid make jobserver warnings 2020-10-02 10:17:32 -04:00
josh 2d009273a1 add readme.txt 2017-07-26 13:51:58 -04:00
josh 2b936758ff add .gitignore 2017-07-26 13:42:21 -04:00
josh 509009d134 get HOS building again on Ubuntu 17.04 with GCC 6 2017-07-26 13:41:23 -04:00
josh 0aaf5db5ad Import backup from 2006-01-02 2017-07-25 22:23:52 -04:00
josh 89d962e33a Import backup from 2005-12-31 2017-07-25 22:23:52 -04:00
josh 712337c485 Import backup from 2005-12-30 2017-07-25 22:23:52 -04:00
josh 761e3f0483 Import backup from 2005-12-26 2017-07-25 22:23:51 -04:00
josh 98abfc2af0 Import backup from 2005-12-19 2017-07-25 22:23:51 -04:00
josh 677551fba5 Import backup from 2005-11-03 2017-07-25 22:23:51 -04:00
josh 7daa1c5336 Import backup from 2005-11-01 2017-07-25 22:23:51 -04:00
josh 79ca453f66 Import backup from 2005-09-13 2017-07-25 22:23:51 -04:00
josh 0521733e20 Import backup from 2005-09-11 2017-07-25 22:23:51 -04:00
josh 396c5f3452 Import backup from 2005-09-01 2017-07-25 22:23:51 -04:00
josh 9e03bfc8b6 Import backup from 2005-08-30 2017-07-25 22:23:51 -04:00
josh 2b67ff6f49 Import backup from 2005-08-29 2017-07-25 22:23:51 -04:00
josh daa29212d0 Import backup from 2005-08-27 2017-07-25 22:23:50 -04:00
josh 83a5b032f8 Import backup from 2005-08-25 2017-07-25 22:23:50 -04:00
josh 345ef6c9f3 Import backup from 2005-08-18 2017-07-25 22:23:50 -04:00
josh e1682a2fe7 Import backup from 2005-08-17 2017-07-25 22:23:50 -04:00
josh 2cefd9441c Import backup from 2005-06-21 2017-07-25 22:23:50 -04:00
josh da90bcc164 Import backup from 2005-06-20 2017-07-25 22:23:50 -04:00
josh 4689c11cc8 Import backup from 2005-06-13 2017-07-25 22:23:50 -04:00
josh 692cf2fc08 Import backup from 2005-06-02 2017-07-25 22:23:50 -04:00
josh b0132c866e Import backup from 2005-05-12 2017-07-25 22:23:50 -04:00
josh 14792ef954 Import backup from 2005-03-21 2017-07-25 22:23:50 -04:00
josh bb8ff09e3f Import backup from 2005-03-11 2017-07-25 22:23:50 -04:00
josh dfeabc39aa Import backup from 2005-02-23 2017-07-25 22:23:50 -04:00
josh 14148e4d80 Import backup from 2005-02-15 2017-07-25 22:23:49 -04:00
josh 80774c48fe Import backup from 2005-02-07 2017-07-25 22:23:49 -04:00
josh 862b36b37b Import backup from 2005-02-01 2017-07-25 22:23:49 -04:00
josh 4638656aaf Import backup from 2005-01-31 2017-07-25 22:23:49 -04:00
josh 3381041a8f Import backup from 2005-01-26 2017-07-25 22:23:49 -04:00
josh f09ed66826 Import backup from 2005-01-18 2017-07-25 22:23:49 -04:00
josh ba5906c7a3 Import backup from 2005-01-14 2017-07-25 22:23:49 -04:00
josh 05183a3949 Import backup from 2005-01-05 2017-07-25 22:23:49 -04:00
josh d8580a9393 Import backup from 2005-01-04 2017-07-25 22:23:49 -04:00
josh 50285aa33b Import backup from 2005-01-01 2017-07-25 22:23:49 -04:00
josh ee63a84c0e Import backup from 2004-12-31 2017-07-25 22:23:49 -04:00
josh 76a243d894 Import backup from 2004-12-30 2017-07-25 22:23:49 -04:00
josh 6bad3f2b96 Import backup from 2004-12-29 2017-07-25 22:23:49 -04:00
josh 51948ce081 Import backup from 2004-12-24 2017-07-25 22:23:49 -04:00
josh b40a68f581 Import backup from 2004-12-23 2017-07-25 22:23:49 -04:00
josh 55b7429d4e Import backup from 2004-12-22 2017-07-25 22:23:49 -04:00
josh 7b805f2495 Import backup from 2004-12-21 2017-07-25 22:23:48 -04:00
josh 2445034e43 Import backup from 2004-12-20 2017-07-25 22:23:48 -04:00
josh 3c531f3b7b Import backup from 2004-12-17 2017-07-25 22:23:48 -04:00
josh 11cc0c87f3 Import backup from 2004-12-16 2017-07-25 22:23:48 -04:00
josh bad7f79ed1 Import backup from 2004-09-21 2017-07-25 22:23:48 -04:00
josh 78272f6bc3 Import backup from 2004-08-20 2017-07-25 22:23:48 -04:00
josh 396d5015d2 Import backup from 2004-08-19 2017-07-25 22:23:48 -04:00
josh 1bf14ddefa Import backup from 2004-08-17 2017-07-25 22:23:48 -04:00
josh c0dd3b529e Import backup from 2004-08-16 2017-07-25 22:23:48 -04:00
josh 8a8f56decb Import backup from 2004-08-15 2017-07-25 22:23:48 -04:00
josh b9c77827bd Import backup from 2004-08-06 2017-07-25 22:23:48 -04:00
josh cd02211b21 Import backup from 2004-08-03 2017-07-25 22:23:48 -04:00
josh a50c2a1233 Import backup from 2004-08-02 2017-07-25 22:23:48 -04:00
josh 07e8a0f4cf Import backup from 2004-07-31 2017-07-25 22:23:48 -04:00
josh 6d23c76e84 Import backup from 2004-07-29 2017-07-25 22:23:48 -04:00
josh 11da8cb162 Import backup from 2004-07-25 2017-07-25 22:23:48 -04:00
josh 1063a68a21 Import backup from 2004-07-20 2017-07-25 22:23:47 -04:00
josh 286b5e9ae1 Import backup from 2004-07-17 2017-07-25 22:23:47 -04:00
josh d4aadbea38 Import backup from 2004-07-15 2017-07-25 22:23:47 -04:00
josh dfb71cc759 Import backup from 2004-07-12 2017-07-25 22:23:47 -04:00
josh 872d562d6a Import backup from 2004-07-10 2017-07-25 22:23:47 -04:00
josh 0729754659 Import backup from 2004-07-09 2017-07-25 22:23:47 -04:00
183 changed files with 12938 additions and 6540 deletions

No files matched your search

+8 -8
View File
@@ -5,13 +5,13 @@ megs: 32
romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000 romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000
vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latest vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latest
boot: floppy boot: floppy
floppya: 1_44="/dev/fd0", status=inserted floppya: 1_44="hos.flp", status=inserted
# no floppyb # no floppyb
ata0: enabled=0 ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=0 ata1: enabled=0
ata2: enabled=0 ata2: enabled=0
ata3: enabled=0 ata3: enabled=0
parport1: enabled=1, file="" parport1: enabled=1, file="parallel.out"
com1: enabled=1, dev="" com1: enabled=1, dev=""
usb1: enabled=1, ioaddr=0xff80, irq=10 usb1: enabled=1, ioaddr=0xff80, irq=10
# no sb16 # no sb16
@@ -24,20 +24,20 @@ ips: 500000
text_snapshot_check: 0 text_snapshot_check: 0
mouse: enabled=0 mouse: enabled=0
private_colormap: enabled=0 private_colormap: enabled=0
i440fxsupport: enabled=0 i440fxsupport: enabled=1
clock: sync=none, time0=local clock: sync=realtime, time0=local
# no ne2k # no ne2k
newharddrivesupport: enabled=1 #newharddrivesupport: enabled=1
# no loader # no loader
log: - log: -
logprefix: %t%e%d logprefix: %t%e%d
debugger_log: - debugger_log: -
panic: action=fatal panic: action=ask
error: action=report error: action=report
info: action=report info: action=report
debug: action=ignore debug: action=ignore
pass: action=fatal pass: action=fatal
keyboard_mapping: enabled=0, map= keyboard_mapping: enabled=0, map=
keyboard_type: mf keyboard_type: mf
user_shortcut: keys=none user_shortcut: keys=ctrlaltdel
# no cmosimage # no cmosimage
+13
View File
@@ -0,0 +1,13 @@
/hos.flp
/hos_initrd
/hos_initrd.gz
*.lst
*.map
*.bin
.rscons*
/i686-elf-gcc/build*/
/i686-elf-gcc/*.xz
/i686-elf-gcc/binutils-*/
/i686-elf-gcc/gcc-*/
/i686-elf-gcc/i686-elf-gcc/
/build/
+11 -113
View File
@@ -1,117 +1,15 @@
##################################################################### .PHONY: all
# Author: Josh Holtrop / Benjamen R. Meyer #
# Date: 02/15/04 Modified: 06/07/04 #
# Purpose: To build Josh Holtrop's OS (HOS) using GNU make #
# Note: This makefile is for use on Linux & other Unix-like systems #
#####################################################################
##############
# Variables: #
##############
# Information for creating a floppy image
# Note: FLOPPY_FS and FLOPPY_FAT_SIZE are related fields.
# FLOPPY_FAT_SIZE should be either 12 or 16,
# depending on if FLOPPY_FS is FAT12 or FAT16, respectively.
MKDOSFS_PROG=mkdosfs
FLOPPY_IMAGE=floppy.img
FLOPPY_BLOCK_COUNT=1440
FLOPPY_FS=FAT12
FLOPPY_FAT_SIZE=12
FLOPPY_MOUNT=./floppy_image
# Floppy images are good for programs like VMware and Bochs Pentium Emulator. ;-)
# Program for copying
COPY_BIN=cp
##########################################
# Build the IPL (Boot Loader) and Kernel #
##########################################
all: all:
# A word of warning to users :-> And a little helpful information ;-) ./rscons build
@echo "Installation must be done as root."
@echo "Type 'make install' to install to a floppy in drive '/dev/fd0'"
@echo "Type 'make install_img' to create a floppy image and install to it."
make -C boot .PHONY: run-efi
make -C kernel run-efi: all
qemu-system-x86_64 -bios OVMF.fd -hda build/hos-efi.img
################################################# .PHONY: run
# Clean up the source directory of any binaries # run: all
################################################# qemu-system-x86_64 -hda build/hos.img
.PHONY: clean
clean: clean:
make -C boot clean ./rscons clean
make -C kernel clean
###########################################
# The following is for the floppy drive #
# Note: This must be done on *nix as root #
###########################################
##########################
# Make install to floppy #
##########################
install: Install_IPL File_Copy
############################################
# Write the Stage 1 IPL to the boot sector #
############################################
Install_IPL:
$(MKDOSFS_PROG) /dev/fd0
dd if=boot/stage1.bin of=/dev/fd0
#################################
# Copy the files onto the drive #
#################################
File_Copy:
- mkdir floppy_mount
@echo "Mounting floppy to ./floppy_mount..."
mount /dev/fd0 ./floppy_mount
@echo "Copying stage 2 bootloader to the floppy..."
$(COPY_BIN) boot/stage2.bin ./floppy_mount
@echo "Copying kernel to the floppy..."
$(COPY_BIN) kernel/kernel.bin ./floppy_mount
@echo "Unmounting floppy..."
umount ./floppy_mount
- rm -rf floppy_mount
############################################
# The following is for the floppy image. #
# Note: This must be done on *nix as root. #
############################################
######################################
# Create and Format the floppy image #
######################################
install_img:
$(MKDOSFS_PROG) -C -F $(FLOPPY_FAT_SIZE) -r 112 $(FLOPPY_IMAGE) $(FLOPPY_BLOCK_COUNT)
############################################
# Write the Stage 1 IPL to the boot sector #
############################################
@echo "Writing boot sector to image..."
dd if=boot/stage1.bin of=$(FLOPPY_IMAGE) seek=0
#################################
# Copy the files onto the image #
#################################
- mkdir $(FLOPPY_MOUNT)
@echo "Mounting floppy image..."
mount $(FLOPPY_IMAGE) $(FLOPPY_MOUNT) -o loop
@echo "Copying stage 2 bootloader to the floppy image..."
$(COPY_BIN) boot/stage2.bin $(FLOPPY_MOUNT)
@echo "Copying kernel to the floppy image..."
$(COPY_BIN) kernel/kernel.bin $(FLOPPY_MOUNT)
@echo "Unmounting floppy image..."
mount $(FLOPPY_IMAGE) $(FLOPPY_MOUNT) -o loop
+155
View File
@@ -0,0 +1,155 @@
path_prepend "i686-elf-gcc/i686-elf-gcc/bin"
configure do
rscons "i686-elf-gcc"
check_c_compiler "i686-elf-gcc"
check_program "genext2fs"
check_program "grub-mkstandalone"
check_program "mformat", on_fail: "Install the mtools package"
check_program "xorriso"
check_cfg package: "freetype2", on_fail: "Install libfreetype-dev", use: "freetype"
end
build do
require "tmpdir"
# EFI (w/ GRUB) partition size (MiB)
EFI_PART_SIZE = 8
# HOS partition size (MiB)
HOS_PART_SIZE = 4
# Kernel default font size
KFONT_SIZE = 15
class BiosImage < Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Generating BIOS boot image #{@target}", nil)
Dir.mktmpdir do |tmpdir|
# Create iso directory.
FileUtils.mkdir_p("#{tmpdir}/iso/boot/grub")
File.open("#{tmpdir}/iso/boot/grub/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
set default="0"
set timeout=1
menuentry "HOS" {
insmod multiboot2
multiboot2 /hos.elf
}
EOF
end
@sources.each do |source|
FileUtils.cp(source, "#{tmpdir}/iso")
end
# Build bootable GRUB image.
system(*%W[grub-mkrescue -o #{@target} #{tmpdir}/iso], err: "#{@env.build_root}/grub-mkrescue.log")
end
@cache.register_build(@target, nil, @sources, @env)
end
true
end
end
class EfiImage < Builder
def run(options)
unless @cache.up_to_date?(@target, nil, @sources, @env)
print_run_message("Generating EFI boot image #{@target}", nil)
Dir.mktmpdir do |tmpdir|
# Build a standalone GRUB.
File.open("#{tmpdir}/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
insmod part_gpt
configfile (hd0,gpt2)/grub.cfg
EOF
end
system(*%W[grub-mkstandalone -O x86_64-efi -o #{tmpdir}/BOOTX64.EFI boot/grub/grub.cfg=#{tmpdir}/grub.cfg])
# Create EFI partition.
system(*%W[dd if=/dev/zero of=#{tmpdir}/efi.part bs=1M count=#{EFI_PART_SIZE}], err: "/dev/null")
system(*%W[mformat -i #{tmpdir}/efi.part ::])
system(*%W[mmd -i #{tmpdir}/efi.part ::/EFI])
system(*%W[mmd -i #{tmpdir}/efi.part ::/EFI/BOOT])
system(*%W[mcopy -i #{tmpdir}/efi.part #{tmpdir}/BOOTX64.EFI ::/EFI/BOOT])
# Create ext2 HOS partition.
FileUtils.mkdir_p("#{tmpdir}/ext2")
@sources.each do |source|
FileUtils.cp(source, "#{tmpdir}/ext2")
end
File.open("#{tmpdir}/ext2/grub.cfg", "wb") do |fh|
fh.write(<<EOF)
set default="0"
set timeout=1
menuentry "HOS" {
insmod part_gpt
insmod multiboot2
set root=(hd0,gpt2)
multiboot2 /hos.elf
}
EOF
end
system(*%W[genext2fs -b #{HOS_PART_SIZE * 1024} -d #{tmpdir}/ext2 #{tmpdir}/ext2.part])
# Create full disk image.
system(*%W[dd if=/dev/zero of=#{@target} bs=1M count=#{EFI_PART_SIZE + HOS_PART_SIZE + 2}], err: "/dev/null")
system(*%W[parted -s #{@target} mklabel gpt])
system(*%W[parted -s #{@target} mkpart efi 1MiB #{EFI_PART_SIZE + 1}MiB])
system(*%W[parted -s #{@target} mkpart hos #{EFI_PART_SIZE + 1}MiB #{EFI_PART_SIZE + HOS_PART_SIZE + 1}MiB])
system(*%W[dd if=#{tmpdir}/efi.part of=#{@target} bs=1M seek=1 conv=notrunc], err: "/dev/null")
system(*%W[dd if=#{tmpdir}/ext2.part of=#{@target} bs=1M seek=#{1 + EFI_PART_SIZE} conv=notrunc], err: "/dev/null")
end
@cache.register_build(@target, nil, @sources, @env)
end
true
end
end
class FontGen < Builder
def run(options)
if @command
finalize_command
else
@sources += ["build/fontgen"]
command = %W[build/fontgen #{@sources.first} #{KFONT_SIZE} #{@target}]
standard_command("FontGen <target>#{@target}<reset>", command, {})
end
end
end
class Size < Builder
def run(options)
if @command
finalize_command
else
@vars["_SOURCES"] = @sources
@vars["_TARGET"] = @target
command = @env.build_command(%w[${SIZE} ${_SOURCES}], @vars)
standard_command("Size <target>#{@target}<reset>", command, stdout: @target)
end
end
end
# FontGen Environment
Environment.new(use: "freetype") do |env|
env["CC"] = "gcc"
env.Program("build/fontgen", glob("fontgen/**/*.c"))
end
# Kernel Environment
Environment.new do |env|
env.add_builder(EfiImage)
env.add_builder(BiosImage)
env.add_builder(FontGen)
env.add_builder(Size)
env["OBJDUMP"] = "i686-elf-objdump"
env["SIZE"] = "i686-elf-size"
env["CCFLAGS"] += %w[-ffreestanding -Wall -O2]
env["LDFLAGS"] += %w[-ffreestanding -nostdlib -T src/link.ld]
env["LDFLAGS"] += %W[-Wl,-Map,${_TARGET}.map]
env["LIBS"] += %w[gcc]
env.FontGen("^/kfont/kfont.c", "font/Hack-Regular.ttf")
env["CPPPATH"] += ["#{env.build_root}/kfont"]
env.Program("^/hos.elf", glob("src/**/*.{S,c}") + ["^/kfont/kfont.c"])
env.depends("#{env.build_root}/hos.elf", "src/link.ld")
env.Disassemble("^/hos.elf.txt", "^/hos.elf")
env.Size("^/hos.elf.size", "^/hos.elf")
env.EfiImage("build/hos-efi.img", %w[^/hos.elf])
env.BiosImage("build/hos.img", %w[^/hos.elf])
end
end
+5
View File
@@ -0,0 +1,5 @@
all:
make -C hash
nasm -f bin -l test1.lst test1.asm -o test1.app
nasm -f bin test2.asm -o test2.app
+3
View File
@@ -0,0 +1,3 @@
all:
nasm -f bin hash.asm -o hash
+1
View File
@@ -0,0 +1 @@
�0�
+6
View File
@@ -0,0 +1,6 @@
[bits 32]
begin:
int 0x30
ret
BIN
View File
Binary file not shown.
+20
View File
@@ -0,0 +1,20 @@
; 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
+22
View File
@@ -0,0 +1,22 @@
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
BIN
View File
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
; 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
-32
View File
@@ -1,32 +0,0 @@
#####################################################################
# Author: Josh Holtrop / Benjamen R. Meyer #
# Date: 02/15/04 #
# Purpose: To build Josh Holtrop's OS (HOS) using GNU make #
# Note: This makefile is for use on Linux & other Unix-like systems #
#####################################################################
# Assembler information:
NASM_BIN=nasm
#################
# Build the IPL #
#################
all: stage1 stage2
################
# IPL: Stage 1 #
################
stage1: stage1.asm
$(NASM_BIN) stage1.asm -o stage1.bin
################
# IPL: Stage 2 #
################
stage2: stage2.asm
$(NASM_BIN) stage2.asm -o stage2.bin
#########
# Clean #
#########
clean:
- rm *.bin *~
-26
View File
@@ -1,26 +0,0 @@
%define VERSION "0.03" ;HOS bootloader version
%define BOOT_FAT_SEG 0x07E0 ;right after boot sector
%define BOOT_ROOT_SEG 0x0900 ;right after FAT
%define BOOT_KERNEL_SEG 0x0AC0 ;right after ROOT_DIR
%define BOOT_STAGE2_SEG 0x0B00 ;right after KERNEL_SEG
%define BOOT_STAGE2_ADD 0xB000 ;address of stage2 to jump to, org at
%define BOOT_KERNEL_ADD 0x106000 ;final pmode kernel destination - physical
%define BOOT_RD_ADD 0x200000 ;2mb for ram disk
%define BOOT_DATA_SEG 0x9000 ;data gathered by stage2 loader goes here
%define BOOT_HASRD 0x0000 ;1
%define BOOT_VESA 0x0002 ;2 - 0 for console, otherwise VESA mode
%define BOOT_VESA_OEM 0x0004 ;258 - null-terminated OEM identification string
%define BOOT_VESA_VBE 0x0106 ;512 - copy of VESA VBEInfoBlock
%define BOOT_VESA_INFO 0x0306 ;256 - copy of VESA ModeInfoBlock for selected mode
%define BOOT_MEMENTRIES 0x040A ;4 - dword = number of memmap entries
%define BOOT_MEMMAP 0x2000 ;? - memory map information
%define BOOT_DRIVE 0x7C24 ;1 - boot drive
-235
View File
@@ -1,235 +0,0 @@
;stage1.asm
;This is the stage1 section of the HOS bootloader
;It is 512 bytes to be put on the first sector of a floppy
;Author: Josh Holtrop
;Date: 03/11/04
;Modified: 05/21/04
%include "bootdef.inc"
[bits 16]
org 0x7c00
jmp short start
; --------------------------------------------------
; data portion of the "DOS BOOT RECORD"
; ----------------------------------------------------------------------
brINT13Flag DB 90H ; 0002h - 0EH for INT13 AH=42 READ
brOEM DB 'MSDOS5.0' ; 0003h - OEM ID - Windows 95B
brBPS DW 512 ; 000Bh - Bytes per sector
brSPC DB 1 ; 000Dh - Sector per cluster
brSc_b4_fat DW 1 ; 000Eh - Reserved sectors
brFATs DB 2 ; 0010h - FAT copies
brRootEntries DW 0E0H ; 0011h - Root directory entries
brSectorCount DW 2880 ; 0013h - Sectors in volume, < 32MB
brMedia DB 240 ; 0015h - Media descriptor
brSPF DW 9 ; 0016h - Sectors per FAT
brSc_p_trk DW 18 ; 0018h - Sectors per head/track
brHPC DW 2 ; 001Ah - Heads per cylinder
brSc_b4_prt DD 0 ; 001Ch - Hidden sectors
brSectors DD 0 ; 0020h - Total number of sectors
brDrive DB 0 ; 0024h - Physical drive no.
DB 0 ; 0025h - Reserved (FAT32)
DB 29H ; 0026h - Extended boot record sig (FAT32)
brSerialNum DD 404418EAH ; 0027h - Volume serial number
brLabel DB 'Holtrops OS' ; 002Bh - Volume label
brFSID DB 'FAT12 ' ; 0036h - File System ID
;------------------------------------------------------------------------
start:
jmp 0:jmphere ;ensure that cs=0 and ip=0x7c00...
jmphere:
;dl=drive number, save it!
xor ax, ax
mov ds, ax
mov [brDrive], dl
cli
mov ss, ax
mov sp, 0x7Bfe ;right under boot sector
sti
mov ax, 0xb800
mov ds, ax
mov es, ax
xor di, di
mov ax, 0x0700
mov cx, 2000
cls:
stosw
loop cls
enable_a20:
in al, 0x64
test al, 2
jnz enable_a20
mov al, 0xD1
out 0x64, al
ea20_2: in al, 0x64
and ax, byte 2
jnz ea20_2
mov al, 0xDF
out 0x60, al
unreal:
xor ax, ax
mov es, ax
mov ds, ax
lgdt [gdtr] ;load gdt
cli
push es
push ds ;save segment values
mov ebx, cr0
inc bl
mov cr0, ebx ;pmode!
mov ax, KERNEL_DATA
mov es, ax
mov ds, ax ;load segment limits
dec bl
mov cr0, ebx ;back to real mode!
pop ds
pop es ;segments back, with 4gb limits!
sti
;now lets read in the FAT and root directory so we can search for the stage2 file...
mov ax, 0x0209 ;FAT1
mov cx, 0x0002
xor dh, dh
mov dl, [brDrive]
mov bx, BOOT_FAT_SEG
mov es, bx
xor bx, bx
int 0x13
mov ax, 0x020E ;root directory
mov cx, 0x0002 ;cyl/sect
mov dh, 0x01 ;head
mov dl, [brDrive] ;drive
mov bx, BOOT_ROOT_SEG
mov es, bx
xor bx, bx
int 0x13
;k now read root directory
mov bx, BOOT_ROOT_SEG
mov ds, bx
xor si, si ;k now ds:si points to beginning of root directory
mov es, si
mov cx, 224 ;max root entries
loop_compare:
mov di, stage2
push cx
push si ;save pointer to root dir entry
mov cx, 11
loop_name:
cmpsb
loopz loop_name
jnz goon ;cx didn't get to zero, bad file
pop si
pop cx
jmp found_file ;good file, ds:si points to start of root directory entry
goon:
pop si
pop cx
add si, 32
loop loop_compare
error:
jmp $ ;halt! no kernel file found!
found_file: ;ds:si points to root dir entry
xor ax, ax
mov gs, ax
mov ax, BOOT_STAGE2_SEG
mov es, ax
mov ax, [ds:si+26]
mov bx, BOOT_FAT_SEG
mov ds, bx ;ds points to beginning of FAT
xor di, di
readstage2_loop:
cmp ax, 0xff7
jg readstage2_done
inc di
push ax
call getCHSfromCluster
mov ax, 0x0201
mov dl, [gs:BOOT_DRIVE]
xor bx, bx
int 0x13
mov bx, es
add bx, 0x0020
mov es, bx
pop ax ;current logical cluster #
mov cx, ax ;cx=logical cluster
mov dx, 3
mul dx
shr ax, 1 ;ax=logical cluster * 3 / 2
mov si, ax
test cl, 1 ;is bit0 set?
jnz odd_cluster
even_cluster:
lodsw
and ax, 0x0fff
jmp got_cluster
odd_cluster:
lodsw
shr ax, 4
got_cluster:
jmp readstage2_loop
readstage2_done:
jmp 0:BOOT_STAGE2_ADD
;------------------------------------------------------
getCHSfromCluster:
;input: ax=lba of sector on floppy (0-2879)
add ax, 31 ;convert logical cluster# to lba#
xor dx, dx ;lba->chs
mov bx, 18
div bx
inc dx
mov cl, dl ;sector# (1-18)
xor dx, dx
mov bx, 2
div bx
mov ch, al ;cylinder# (0-79)
mov dh, dl ;head# (0-1)
ret
;-------------------------------------------------------
gdtr:
dw gdt_end-gdt-1
dd gdt
gdt:
dd 0
dd 0
KERNEL_DATA equ $-gdt
db 0xff ;segment 16 = 4gb data
db 0xff
db 0x00
db 0x00
db 0x00
db 0x92
db 0xcf ;cf
db 0x00
gdt_end:
stage2: db "STAGE2 BIN"
times 510-($-$$) db 0
db 0x55, 0xaa
-978
View File
@@ -1,978 +0,0 @@
;stage2.asm
;This is the stage2 section of the HOS bootloader
;It is to be copied into the normal FAT12 filesystem to be loaded by stage1
;Author: Josh Holtrop
;Date: 03/11/04
;Modified: 05/21/04
%include "bootdef.inc"
%define VESA_MODEINFO_SEG 0x0120
%define VESA_MODELIST_SEG 0x0140
%define GOOD_MODELIST_SEG 0x0160
[bits 16]
org BOOT_STAGE2_ADD
;k now read root directory
mov bx, BOOT_ROOT_SEG
mov ds, bx
xor si, si ;k now ds:si points to beginning of root directory
mov es, si
mov cx, 224 ;max root entries
loop_compare:
mov di, kernel
push cx
push si ;save pointer to root dir entry
mov cx, 11
loop_name:
cmpsb
loopz loop_name
jnz goon ;cx didn't get to zero, bad file
pop si
pop cx
jmp found_file ;good file, ds:si points to start of root directory entry
goon:
pop si
add si, 32
pop cx
loop loop_compare
error:
jmp $ ;halt! no kernel file found!
found_file: ;ds:si points to root dir entry of kernel file
xor ax, ax
mov gs, ax
mov ax, [ds:si+26]
mov bx, BOOT_FAT_SEG
mov ds, bx ;ds points to beginning of FAT
mov edi, BOOT_KERNEL_ADD
readkernel_loop:
cmp ax, 0xff7
jg readkernel_done
push ax
call getCHSfromCluster
mov ax, 0x0201
mov dl, [gs:BOOT_DRIVE]
mov bx, BOOT_KERNEL_SEG
mov es, bx
xor bx, bx
int 0x13
mov cx, 256
xor ax, ax
mov es, ax
mov esi, BOOT_KERNEL_SEG*16
copykernel_loop:
mov ax, [es:esi]
mov [es:edi], ax
inc esi
inc esi
inc edi
inc edi
loop copykernel_loop
pop ax ;current logical cluster #
mov cx, ax ;cx=logical cluster
mov dx, 3
mul dx
shr ax, 1 ;ax=logical cluster * 3 / 2
mov si, ax
test cl, 1 ;is bit0 set?
jnz odd_cluster
even_cluster:
lodsw
and ax, 0x0fff
jmp got_cluster
odd_cluster:
lodsw
shr ax, 4
got_cluster:
jmp readkernel_loop
;------------------------------------------------------
readkernel_done: ;-------------put more real mode init stuff here!
;----ask to load RD from floppy
mov ax, 0xb800
mov es, ax
xor ax, ax
mov ds, ax
xor di, di
mov cx, 2000
mov ax, 0x0700
cls_loop:
stosw
loop cls_loop
mov dx, 0x3d4 ;move cursor off screen...
mov al, 0x0e
out dx, al
inc dx
mov al, 0xff
out dx, al
dec dx
mov al, 0x0f
out dx, al
inc dx
out dx, al
xor di, di
mov si, txt_welcome
mov ah, 0x1f
call puts
mov di, 160
mov si, txt_rd1
mov ah, 7
call puts
mov si, txt_rd2
mov di, 160*2
call puts
mov di, 160*3
mov si, txt_input
call puts
get_rd:
xor ax, ax
int 0x16
cmp al, '1'
jz got_rd
cmp al, '2'
jnz get_rd
got_rd:
stosb
sub al, '1'
push ds
mov bx, BOOT_DATA_SEG ;segment for data to send kernel
mov ds, bx
mov [ds:BOOT_HASRD], al
pop ds ;ds=0
cmp al, 0 ;dont load rd
jnz yes_rd
jmp no_rd
yes_rd:
mov cx, 80
mov edi, 0xb8000+160*4
filler_loop: ;draw a red bar
mov word [ds:edi], 0x0400+177
inc edi
inc edi
loop filler_loop
mov cx, 80 ;80 cylinders to read
xor si, si ;start at cylinder 0
mov edi, BOOT_RD_ADD ;ram disk address
read_cylinder:
push cx
mov bx, 0x0100 ;read sectors from head 0
mov es, bx
xor bx, bx ;es:bx = data buffer for read
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
mov cx, si ;what cyl. we are on is now in cx
mov ch, cl ;ch = cyl. number
mov cl, 1 ;cl = sector number 1-63
xor dx, dx ;dh = head number
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
int 0x13
mov bx, 0x0100 ;now read sectors from head 1
mov es, bx
mov bx, 9216 ;es:bx = data buffer for read
mov ax, 0x0212 ;ah = int 0x13 function 2, al = number of sectors to read
mov cx, si ;what cyl. we are on is now in cx
mov ch, cl ;ch = cyl. number
mov cl, 1 ;cl = sector number 1-63
mov dh, 1 ;dh = head number
mov dl, [gs:BOOT_DRIVE] ;dl = drive number
int 0x13
mov ebx, 0xb8000
add bx, si
shl bl, 1
mov word [ds:ebx+160*4], 0x0200+219
push si
mov esi, 0x1000
mov cx, 0x2400
copydisk_loop:
mov ax, [ds:esi]
inc esi
inc esi
mov [ds:edi], ax
inc edi
inc edi
loop copydisk_loop
pop si ;what cylinder# we are on...
inc si
pop cx
loop read_cylinder
;------------------------------------------------------
no_rd:
mov ax, BOOT_DATA_SEG
mov es, ax
mov di, BOOT_MEMMAP ;store memmap info in es:di for kernel
xor edx, edx
mov ax, 0x0100
mov ds, ax
xor ebx, ebx
getmemmap_loop:
push es
push di
push edx
mov ax, 0x0100 ;get memory map
mov es, ax
xor di, di
mov eax, 0x0000E820
mov ecx, 0x00000014
;mov ebx, 0x00000000
mov edx, 0x534D4150 ;'SMAP'
int 0x15
jc getmemmap_carry
cmp eax, 0x534D4150 ;eax should be 'SMAP' on return...
jnz getmemmap_error
cmp ebx, 0
jz getmemmap_done
pop edx ;now, copy memmap entry to es:di on the stack
pop di
pop es
xor si, si
mov cx, 20
getmemmap_copymem_loop:
lodsb
stosb
loop getmemmap_copymem_loop
inc edx
jmp getmemmap_loop
getmemmap_error:
mov ax, 0xb800
mov es, ax
mov di, 160*24
xor ax, ax
mov ds, ax
mov si, txt_memerror
mov ah, 0x04
call puts
hlt
jmp $
getmemmap_carry:
dec edx
getmemmap_done:
pop edx
pop di
pop es
xor si, si
mov cx, 20
getmemmap_done_copymem_loop:
lodsb
stosb
loop getmemmap_done_copymem_loop
inc edx
mov di, BOOT_MEMENTRIES
mov [es:di], edx ;save # of memmap entries for kernel
;on to vesa info...
xor ax, ax
mov gs, ax
mov ds, ax
mov ax, 0xb800
mov es, ax
mov di, 160
mov cx, 2000-80
mov ax, 0x0700
cls_vesa_loop:
stosw
loop cls_vesa_loop
mov si, txt_vesa
mov di, 160*1
mov ah, 7
call puts
push di
mov ax, 0x0100
mov es, ax
xor di, di
mov dword [es:di], "2EBV"
mov ax, 0x4F00
int 0x10
pop di
cmp ax, 0x004F
jz vesa_good
mov si, txt_novesa
mov ax, 0xb800
mov es, ax
mov ah, 7
call puts
mov ax, BOOT_DATA_SEG
mov ds, ax
mov word [ds:BOOT_VESA], 0
jmp vesa_done
vesa_good:
mov ax, 0xb800
mov es, ax
mov ax, 0x0100
mov ds, ax
xor si, si
mov bx, [4]
mov al, bh
call puthex
mov al, '.'
stosb
mov al, 7
stosb
mov al, bl
call puthex
add di, 4
cmp bh, 2
jge vesa_good2
xor ax, ax
mov ds, ax
mov si, txt_vesaold
mov ah, 7
call puts
mov ax, BOOT_DATA_SEG
mov ds, ax
mov word [ds:BOOT_VESA], 0
jmp vesa_done
vesa_good2:
mov ebx, [6] ;something like 0x00000E60
mov edx, [14]
mov si, bx
shr ebx, 16
mov ds, bx ;ds:si points to null-terminated OEM identification string
mov ah, 2
push si
call puts
pop si
mov ax, BOOT_DATA_SEG
mov es, ax
mov di, BOOT_VESA_OEM
vesa_copyoem:
lodsb
stosb
or al, al
jnz vesa_copyoem
mov ax, 0x0100
mov ds, ax
xor si, si
mov di, BOOT_VESA_VBE
mov cx, 512
vesa_copyvbe:
lodsb
stosb
loop vesa_copyvbe
mov si, dx
shr edx, 16
mov ds, dx ;ds:si points to video mode list
mov ax, VESA_MODELIST_SEG
mov es, ax
xor di, di
vesa_copymodes:
lodsw
stosw
cmp ax, 0xffff
jnz vesa_copymodes
mov ax, GOOD_MODELIST_SEG
mov es, ax
xor di, di
mov cx, 256
mov ax, 0xffff
clear_good_mode_list_loop:
stosw
loop clear_good_mode_list_loop
mov ax, VESA_MODELIST_SEG
mov ds, ax
xor si, si ;ds:si points to video mode list where we can edit it :)
mov ax, GOOD_MODELIST_SEG
mov es, ax
xor di, di
xor dx, dx ;dx=what good mode # we are on
vesa_readmodeinfo_loop:
lodsw
cmp ax, 0xffff
jz vesa_endofmodes
push ax ;save mode#
call checkmode
cmp ax, 0
jz vesa_readmodeinfo_good
pop ax
jmp vesa_readmodeinfo_loop
vesa_readmodeinfo_good:
pop ax ;restore mode#
stosw
call vesa_showmodeinfo
inc dx
jmp vesa_readmodeinfo_loop
vesa_endofmodes: ;here we have a list of good modes at GOOD_MODELIST_SEG:0
xor ax, ax
mov ds, ax
mov si, txt_consolemode
mov ax, 0xb800
mov es, ax
mov di, 160*2
mov ah, 7
call puts
mov di, 160*3
mov cx, dx
mov al, 'b'
vesa_displaylabels:
stosb
push ax
mov al, 7
stosb
mov al, '.'
stosb
mov al, 7
stosb
pop ax
inc al
add di, 160-4
loop vesa_displaylabels ;done drawing screen of VESA choices, now ask for one
;valid options are 'a' through (al-1)
mov bl, al
xor ax, ax
mov ds, ax
mov di, 160*24
mov si, txt_input
mov ah, 14
call puts
vesa_getchoice:
xor ax, ax
int 0x16
cmp al, 'a'
jl vesa_getchoice
cmp al, bl
jge vesa_getchoice
stosb
push ax
mov al, 14
stosb
pop ax
xor ah, ah
sub ax, 'a'
cmp ax, 0
jz vesa_consolemode_only
mov cx, ax ;cx holds good mode# (1=first good vesa mode)
dec cx
mov ax, GOOD_MODELIST_SEG
mov ds, ax
shl cx, 1
mov si, cx ;ds:si points to word containing selected mode#
lodsw
mov cx, ax
mov dx, ax ;cx and dx hold mode#
mov ax, VESA_MODEINFO_SEG
mov es, ax
xor di, di
mov ax, 0x4F01
int 0x10
call checkvesa
mov ax, VESA_MODEINFO_SEG
mov ds, ax
xor si, si
mov ax, BOOT_DATA_SEG
mov es, ax
mov di, BOOT_VESA_INFO
mov cx, 256
vesa_copymodeinfo_loop:
lodsb
stosb
loop vesa_copymodeinfo_loop ;store ModeInfoBlock for current
mov [es:BOOT_VESA], dx ;store mode# for kernel
; mov ax, 0xb800
; mov es, ax
; xor di, di
; mov al, dh
; call puthex2
; mov al, dl
; call puthex2
mov bx, dx
or bx, 0x4000 ;set "use LFB" bit of mode#
mov ax, 0x4F02
int 0x10 ;switch to graphics mode!!!
call checkvesa
jmp vesa_done
vesa_consolemode_only:
mov ax, BOOT_DATA_SEG
mov es, ax
mov word [es:BOOT_VESA], 0
jmp vesa_done
;------------------------------------------------------
vesa_showmodeinfo:
pusha
push es
push ds
mov ax, VESA_MODEINFO_SEG
mov ds, ax
xor si, si
mov ax, 0xb800
mov es, ax
mov cx, dx
mov ax, 160
mul dx ;ax=160*mod#
add ax, 160*3+6 ;offset first line of modes and room on left for label
mov di, ax
mov ax, [ds:18]
call console_putDec
add di, 10
mov al, 'x'
call console_putChar
inc di
inc di
mov ax, [ds:20]
call console_putDec
add di, 10
mov al, 'x'
call console_putChar
inc di
inc di
xor ah, ah
mov al, [ds:25]
call console_putDec
add di, 8
mov al, [ds:0]
test al, 0x80
jz vesa_showmodeinfo_done
mov al, 'L'
call console_putChar
mov al, 'F'
call console_putChar
mov al, 'B'
call console_putChar
inc di
inc di
mov ebx, [ds:40]
mov eax, ebx
shr eax, 24
call puthex2
mov eax, ebx
shr eax, 16
call puthex2
mov al, bh
call puthex2
mov al, bl
call puthex2
vesa_showmodeinfo_done:
pop ds
pop es
popa
ret
;------------------------------------------------------
checkmode:
push bx
push cx
push dx
push es
push ds
push di
push si
mov cx, ax ;cx=modenumber
mov ax, VESA_MODEINFO_SEG
mov es, ax
xor di, di
mov ax, 0x4F01
int 0x10
call checkvesa
xor di, di ;es:di -> ModeInfoBlock struc
mov ax, [es:di] ;ModeAttributes
test al, 1 ;mode supported
jz vesa_modenogood
test al, 8 ;color mode
jz vesa_modenogood
test al, 0x10 ;graphics mode
jz vesa_modenogood
test al, 0x80 ;Linear Frame Buffer supported
jz vesa_modenogood
mov al, [es:di+25] ;BitsPerPixel
cmp al, 16
jz vesa_bppok
cmp al, 24
jz vesa_bppok
cmp al, 32
jnz vesa_modenogood
vesa_bppok:
mov ax, [es:di+18] ;XResolution
mov bx, [es:di+20] ;YResolution
cmp ax, 640 ;640x480
jnz res_goon1
cmp bx, 480
jnz vesa_modenogood
jmp vesa_modegood
res_goon1:
cmp ax, 800
jnz res_goon2
cmp bx, 600
jnz vesa_modenogood
jmp vesa_modegood
res_goon2:
cmp ax, 1024
jnz res_goon3
cmp bx, 768
jnz vesa_modenogood
jmp vesa_modegood
res_goon3:
cmp ax, 1280
jnz res_goon4
cmp bx, 1024
jz vesa_modegood
cmp bx, 960
jz vesa_modegood
jmp vesa_modenogood
res_goon4:
cmp ax, 1600
jnz vesa_modenogood
cmp bx, 1200
jnz vesa_modenogood
vesa_modegood:
pop si
pop di
pop ds
pop es
pop dx
pop cx
pop bx
xor ax, ax
ret
vesa_modenogood:
pop si
pop di
pop ds
pop es
pop dx
pop cx
pop bx
mov ax, 0xffff
ret
;------------------------------------------------------
vesa_done:
; xor ax, ax ;wait for keypress...
; int 0x16
jmp go_pm
;------------------------------------------------------
puts:
lodsb
or al, al
jz puts_done
stosb
mov al, ah
stosb
jmp puts
puts_done:
ret
;------------------------------------------------------
checkvesa:
cmp ax, 0x004F
jnz vesaerror
ret
vesaerror:
mov ax, 0xb800
mov es, ax
xor ax, ax
mov ds, ax
mov si, txt_vesaerror
mov di, 160*24
mov ah, 4
call puts
cli
hlt
;-------Function console_putDec
;input:
; AX = number to display
;output:
; number written in decimal to es:di
console_putDec:
pusha
xor dx, dx
xor bh, bh ;no characters written yet
mov cx, 10000
div cx ;ax=quotiont, dx=remainder
add ax, '0'
cmp ax, '0'
je .goon1
call console_putChar
mov bh, 1
.goon1:
mov ax, dx ;load remainder to ax
xor dx, dx
mov cx, 1000
div cx ;ax=quotiont, dx=remainder
add ax, '0'
cmp ax, '0'
je .goon11
call console_putChar
mov bh, 1
jmp .goon2
.goon11:
cmp bh, 0
je .goon2
call console_putChar
.goon2:
mov ax, dx ;load remainder to ax
xor dx, dx
mov cx, 100
div cx ;ax=quotiont, dx=remainder
add ax, '0'
cmp ax, '0'
je .goon21
call console_putChar
mov bh, 1
jmp .goon3
.goon21:
cmp bh, 0
je .goon3
call console_putChar
.goon3:
mov ax, dx ;load remainder to ax
xor dx, dx
mov cx, 10
div cx ;ax=quotiont, dx=remainder
add ax, '0'
cmp ax, '0'
je .goon31
call console_putChar
mov bh, 1
jmp .goon4
.goon31:
cmp bh, 0
je .goon4
call console_putChar
.goon4: ;here dx contains last remainder
mov ax, dx
add ax, '0'
call console_putChar
popa
ret
;------------------------------------------------------
console_putChar:
stosb
mov al, 7
stosb
ret
;------------------------------------------------------
puthex:
;es:di points to video memory
;al holds hex value
push ax
mov ah, al
shr ax, 4
and al, 0x0F
add al, '0'
cmp al, '9'
jle puthex_goon1
add al, 'A'-'9'-1
puthex_goon1:
cmp al, '0'
jz puthex_skipzero
stosb
mov al, 7
stosb
puthex_skipzero:
pop ax
push ax
and al, 0x0F
add al, '0'
cmp al, '9'
jle puthex_goon2
add al, 'A'-'9'-1
puthex_goon2:
stosb
mov al, 7
stosb
pop ax
ret
;------------------------------------------------------
puthex2:
;es:di points to video memory, always displays 2 characters!
;al holds hex value
push ax
mov ah, al
shr ax, 4
and al, 0x0F
add al, '0'
cmp al, '9'
jle puthex2_goon1
add al, 'A'-'9'-1
puthex2_goon1:
stosb
mov al, 7
stosb
pop ax
push ax
and al, 0x0F
add al, '0'
cmp al, '9'
jle puthex2_goon2
add al, 'A'-'9'-1
puthex2_goon2:
stosb
mov al, 7
stosb
pop ax
ret
;------------------------------------------------------
txt_welcome: db " HOS bootloader v", VERSION, "! ", 0
txt_rd1: db "1. Do not load an initial ram disk", 0
txt_rd2: db "2. Load initial ram disk from boot media", 0
txt_input: db "Enter your selection: ", 0
txt_vesa: db "VESA version: ", 0
txt_vesaerror: db "VESA function call error! Halting system!", 0
txt_novesa: db "VESA not found. Starting in console mode...", 0
txt_vesaold: db "VESA version 2.0 required. Starting in console mode...", 0
txt_consolemode: db "a. Console mode only.", 0
txt_memerror: db "Extended Memory Map information unavailable! Halting system...", 0
;------------------------------------------------------
getCHSfromCluster:
;input: ax=lba of sector on floppy (0-2879)
add ax, 31 ;convert logical cluster# to lba#
xor dx, dx ;lba->chs
mov bx, 18
div bx
inc dx
mov cl, dl ;sector# (1-18)
xor dx, dx
mov bx, 2
div bx
mov ch, al ;cylinder# (0-79)
mov dh, dl ;head# (0-1)
ret
;-------------------------------------------------------
gdtr:
dw gdt_end-gdt-1
dd gdt
gdt:
dd 0
dd 0
KERNEL_CODE equ $-gdt
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 0x00 ;base 31:24
KERNEL_DATA equ $-gdt
db 0xff ;segment 16 = 4gb data
db 0xff
db 0x00
db 0x00
db 0x00
db 0x92
db 0xcf
db 0x00
gdt_end:
;-------------------------------------------------------
gdtr32:
dw gdt_end32-gdt32-1
dd gdt32
gdt32:
dd 0
dd 0
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
KERNEL_CODE32 equ $-gdt32
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_DATA32 equ $-gdt32
db 0xff ;segment 16 = 4gb data
db 0xff
db 0x00
db 0x00
db 0x00
db 0x92
db 0xcf
db 0x40
gdt_end32:
;------------------------------------------------------
go_pm:
xor ax, ax
mov ds, ax
lgdt [gdtr]
cli
mov eax, cr0
inc eax
mov cr0, eax
jmp KERNEL_CODE:pmode
bits 32
pmode:
lgdt [gdtr32]
jmp KERNEL_CODE32:pmode_offsetted+0xC0000000
pmode_offsetted:
mov ax, KERNEL_DATA32
mov es, ax
mov ds, ax
mov fs, ax
mov gs, ax
jmp KERNEL_CODE:BOOT_KERNEL_ADD+0xC0000000
kernel: db "KERNEL BIN", 0
+2
View File
@@ -0,0 +1,2 @@
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)
Vendored Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exec ./rscons configure "$@"
BIN
View File
Binary file not shown.
Binary file not shown.
+224
View File
@@ -0,0 +1,224 @@
#include <stdlib.h>
#include <stdint.h>
#include <ft2build.h>
#include <stdio.h>
#include FT_FREETYPE_H
#include <string.h>
#include <strings.h>
#include <ctype.h>
#define N_CHARS 128
#define round_up_26_6(val) (((val) + 63) >> 6u)
int max_advance;
int max_top = -9999;
int min_bottom = 9999;
int line_height;
int baseline_offset;
typedef struct {
int width;
int height;
int top;
int left;
uint8_t * bitmap;
} char_info_t;
static char_info_t char_infos[N_CHARS];
static void load_char(FT_Face face, int char_code)
{
if (FT_Load_Char(face, char_code, FT_LOAD_RENDER) != 0)
{
return;
}
int advance = round_up_26_6(face->glyph->advance.x);
if (advance > max_advance)
{
max_advance = advance;
}
if ((face->glyph->bitmap.width == 0) ||
(face->glyph->bitmap.rows == 0))
{
return;
}
char_infos[char_code].width = face->glyph->bitmap.width;
char_infos[char_code].height = face->glyph->bitmap.rows;
char_infos[char_code].top = face->glyph->bitmap_top;
if (char_infos[char_code].top > max_top)
{
max_top = char_infos[char_code].top;
}
int bottom = char_infos[char_code].top - char_infos[char_code].height;
if (bottom < min_bottom)
{
min_bottom = bottom;
}
char_infos[char_code].left = face->glyph->bitmap_left;
char_infos[char_code].bitmap = malloc(char_infos[char_code].width * char_infos[char_code].height);
memcpy(char_infos[char_code].bitmap,
face->glyph->bitmap.buffer,
char_infos[char_code].width * char_infos[char_code].height);
}
static const char * bare_header_name(const char * h_file_name)
{
const char * p = rindex(h_file_name, '/');
if (p == NULL)
{
p = h_file_name;
}
else
{
p++;
}
return p;
}
static char * include_guard_name(const char * h_file_name)
{
const char * p = bare_header_name(h_file_name);
char * guard_name = malloc(strlen(p) + 1);
strcpy(guard_name, p);
char * m = guard_name;
while (*m != '\0')
{
if ('a' <= *m && *m <= 'z')
{
*m = toupper(*m);
}
else if (('0' <= *m && *m <= '9') || ('A' <= *m && *m <= 'Z'))
{
/* no change */
}
else
{
*m = '_';
}
m++;
}
return guard_name;
}
static void generate_bytes(FILE * file, const uint8_t * bytes, int count)
{
for (int i = 0; i < count; i++)
{
if (i % 8 == 0)
{
fprintf(file, " ");
}
fprintf(file, "0x%02xu,", bytes[i]);
if ((i + 1) % 8 == 0)
{
fprintf(file, "\n");
}
else if (i < (count - 1))
{
fprintf(file, " ");
}
}
if (count % 8 != 0)
{
fprintf(file, "\n");
}
}
static void generate(const char * c_file_name)
{
char * h_file_name = malloc(strlen(c_file_name) + 1);
strcpy(h_file_name, c_file_name);
h_file_name[strlen(h_file_name) - 1] = 'h';
char * guard = include_guard_name(h_file_name);
FILE * h_file = fopen(h_file_name, "wb");
fprintf(h_file, "#ifndef %s\n", guard);
fprintf(h_file, "#define %s\n\n", guard);
fprintf(h_file, "#include <stdint.h>\n");
fprintf(h_file, "typedef struct {\n int width;\n int height;\n int top;\n int left;\n const uint8_t * bitmap;\n} fontgen_char_info_t;\n");
fprintf(h_file, "typedef struct {\n int line_height;\n int advance;\n int baseline_offset;\n const fontgen_char_info_t ** char_infos;\n} fontgen_font_t;\n");
fprintf(h_file, "extern const fontgen_font_t kfont;\n");
fprintf(h_file, "#endif\n");
fclose(h_file);
FILE * c_file = fopen(c_file_name, "wb");
fprintf(c_file, "#include \"%s\"\n", bare_header_name(h_file_name));
fprintf(c_file, "#include <stddef.h>\n");
for (int i = 0; i < N_CHARS; i++)
{
if (char_infos[i].width > 0)
{
fprintf(c_file, "static const uint8_t char_bitmap_%d[] = {\n", i);
generate_bytes(c_file, char_infos[i].bitmap, char_infos[i].width * char_infos[i].height);
fprintf(c_file, "};\n");
}
fprintf(c_file, "static const fontgen_char_info_t char_%d = {\n", i);
fprintf(c_file, " %d,\n", char_infos[i].width);
fprintf(c_file, " %d,\n", char_infos[i].height);
fprintf(c_file, " %d,\n", char_infos[i].top);
fprintf(c_file, " %d,\n", char_infos[i].left);
if (char_infos[i].width > 0)
{
fprintf(c_file, " char_bitmap_%d,\n", i);
}
else
{
fprintf(c_file, " NULL,\n");
}
fprintf(c_file, "};\n\n");
}
fprintf(c_file, "const fontgen_char_info_t * char_infos[] = {\n");
for (int i = 0; i < N_CHARS; i++)
{
fprintf(c_file, " &char_%d,\n", i);
}
fprintf(c_file, "};\n");
fprintf(c_file, "const fontgen_font_t kfont = {\n");
fprintf(c_file, " %d,\n", line_height);
fprintf(c_file, " %d,\n", max_advance);
fprintf(c_file, " %d,\n", baseline_offset);
fprintf(c_file, " char_infos,\n");
fprintf(c_file, "};\n");
fclose(c_file);
}
int main(int argc, char * argv[])
{
/* Expect: font file, size, out file */
if (argc != 4)
{
fprintf(stderr, "Incorrect arguments\n");
return 1;
}
const char * font_file = argv[1];
int size = atoi(argv[2]);
const char * out_file = argv[3];
FT_Library ft_library;
if (FT_Init_FreeType(&ft_library) != 0)
{
fprintf(stderr, "Could not initialize freetype\n");
return 2;
}
FT_Face face;
if (FT_New_Face(ft_library, font_file, 0, &face) != 0)
{
fprintf(stderr, "Could not open %s\n", font_file);
return 3;
}
FT_Set_Pixel_Sizes(face, 0, size);
for (int i = 0; i < N_CHARS; i++)
{
load_char(face, i);
}
line_height = round_up_26_6(face->size->metrics.height);
baseline_offset = (line_height - (max_top - min_bottom)) / 2 - min_bottom;
generate(out_file);
return 0;
}
BIN
View File
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
configure do
check_c_compiler "gcc"
check_program "make"
check_program "bison"
check_program "flex"
check_program "texi2any", on_fail: "Install the texinfo package"
check_program "wget"
check_lib "gmp", on_fail: "Install the libgmp-dev package"
check_lib "mpc", on_fail: "Install the libmpc-dev package"
check_lib "mpfr", on_fail: "Install the libmpfr-dev package"
end
build do
unless File.exist?("i686-elf-gcc")
system("./build.sh")
end
end
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
BINUTILS_VERSION="2.35"
BINUTILS_CHECKSUM="1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85"
GCC_VERSION="10.2.0"
GCC_CHECKSUM="b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
if [ ! -e binutils-${BINUTILS_VERSION}.tar.xz ]; then
wget -O binutils-${BINUTILS_VERSION}.tar.xz https://ftp.gnu.org/gnu/binutils/binutils-${BINUTILS_VERSION}.tar.xz
fi
if [[ ! `sha256sum binutils-${BINUTILS_VERSION}.tar.xz` =~ $BINUTILS_CHECKSUM ]]; then
echo "Invalid binutils-${BINUTILS_VERSION}.tar.xz checksum"
exit
fi
if [ ! -d binutils-${BINUTILS_VERSION} ]; then
tar xJf binutils-${BINUTILS_VERSION}.tar.xz
fi
if [ ! -e gcc-${GCC_VERSION}.tar.xz ]; then
wget -O gcc-${GCC_VERSION}.tar.xz https://ftp.gnu.org/gnu/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.xz
fi
if [[ ! `sha256sum gcc-${GCC_VERSION}.tar.xz` =~ $GCC_CHECKSUM ]]; then
echo "Invalid gcc-${GCC_VERSION}.tar.xz checksum"
exit
fi
if [ ! -d gcc-${GCC_VERSION} ]; then
tar xJf gcc-${GCC_VERSION}.tar.xz
fi
export PREFIX="$PWD/i686-elf-gcc"
export TARGET="i686-elf"
export PATH="$PREFIX/bin:$PATH"
function build_binutils()
{
rm -rf build-binutils
mkdir -p build-binutils
(
cd build-binutils
../binutils-${BINUTILS_VERSION}/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror && \
make && \
make install
)
}
function build_gcc()
{
rm -rf build-gcc
mkdir -p build-gcc
(
cd build-gcc
../gcc-${GCC_VERSION}/configure --target="$TARGET" --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers && \
make all-gcc && \
make all-target-libgcc && \
make install-gcc && \
make install-target-libgcc
)
}
build_binutils && build_gcc
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
rm -rf build build-* binutils* gcc-*
Vendored Executable
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
exec ../rscons configure
BIN
View File
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
test_file
+46
View File
@@ -0,0 +1,46 @@
# 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
+117 -64
View File
@@ -1,76 +1,129 @@
##################################################################### # Makefile for HOS
# Author: Josh Holtrop / Benjamen R. Meyer # # Josh Holtrop
# Date: 02/15/04 Modified: 06/16/04 # # Created: 07/08/04
# Purpose: To build Josh Holtrop's OS (HOS) using GNU make # # Modified: 06/13/05
# Note: This makefile is for use on Linux & other Unix-like systems #
#####################################################################
############## # Assembler Information:
# Variables: # NASM=nasm
############## NASM_FLAGS=-f elf32
# Format of kernel object files: # C/C++ Information:
# Do not change unless you know what you are doing CPPFLAGS=-ffreestanding -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -I. -Wall -m32 -fno-pic
KERNEL_FORMAT=aout # -S -masm=intel
CC=gcc
# Assembler information: CXX=g++
NASM_BIN=nasm CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_ -std=gnu++98
NASM_FLAGS=-f $(KERNEL_FORMAT)
# C++ Compile Information:
CPP=g++
CPP_FLAGS=-fleading-underscore -fno-builtin -nostdlib -nostdinc++ -nostartfiles -fno-rtti -fno-exceptions -nodefaultlibs -I. -Wall
# Linker Information: # Linker Information:
LD=ld LD=gcc
LD_FLAGS=-nodefaultlibs -nostdlib --no-demangle -T link.ld LDFLAGS=-ffreestanding -fno-builtin -nostartfiles -nodefaultlibs -nostdlib -Wl,--no-demangle -T link.ld -m32
LIBS=-static-libgcc
# Files
OBJS=boot.o lang/lang_a.o \
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
# Linking the kernel together #
###############################
all: Asm_Kernel Asm_Functions C_Kernel
$(LD) $(LD_FLAGS) -o kernel.bin -Map ./lst/LDout.doc ks.o kernel.o asmfuncs.o fdc.o keyboard.o kio.o mm.o mouse.o stdfont.o video.o vmm.o rtc.o pic.o io.o cstring.o string.o cmos.o hos_defines.o vfs.o devfs.o Mount.o
########################## all: $(OBJS)
# Assembly Kernel Loader # $(LD) $(LDFLAGS) -Wl,-Map -Wl,kernel.map $(OBJS) -o kernel.bin $(LIBS)
########################## @echo ' Kernel built: ' `ls -sk kernel.bin | cut -d' ' -f1`kb
Asm_Kernel: kernel.asm
$(NASM_BIN) $(NASM_FLAGS) -o ks.o -l ./lst/kernel.lst kernel.asm
################################# depend:
# Assembly Functions for Kernel # makedepend -- $(CPPFLAGS) -- $(CSRC) $(CXXSRC)
#################################
Asm_Functions: asmfuncs.asm
$(NASM_BIN) $(NASM_FLAGS) -o asmfuncs.o -l ./lst/asmfuncs.lst asmfuncs.asm
############ boot.o: boot.asm idt.inc gdt.inc
# C Kernel # $(NASM) $(NASM_FLAGS) -l boot.lst boot.asm -o boot.o
############
C_Kernel: lang/lang_a.o: lang/lang.asm
$(CPP) $(CPP_FLAGS) -c kernel.cpp -o kernel.o $(NASM) $(NASM_FLAGS) -l lang.lst lang/lang.asm -o lang/lang_a.o
$(CPP) $(CPP_FLAGS) -c kio.cpp -o kio.o
$(CPP) $(CPP_FLAGS) -c sys/rtc.cpp -o rtc.o
$(CPP) $(CPP_FLAGS) -c sys/pic.cpp -o pic.o
$(CPP) $(CPP_FLAGS) -c sys/io.cpp -o io.o
$(CPP) $(CPP_FLAGS) -c sys/cmos.cpp -o cmos.o
$(CPP) $(CPP_FLAGS) -c lang/cstring.cpp -o cstring.o
$(CPP) $(CPP_FLAGS) -c lang/string.cpp -o string.o
$(CPP) $(CPP_FLAGS) -c video/stdfont.cpp -o stdfont.o
$(CPP) $(CPP_FLAGS) -c video/video.cpp -o video.o
$(CPP) $(CPP_FLAGS) -c block/fdc.cpp -o fdc.o
$(CPP) $(CPP_FLAGS) -c char/keyboard.cpp -o keyboard.o
$(CPP) $(CPP_FLAGS) -c char/mouse.cpp -o mouse.o
$(CPP) $(CPP_FLAGS) -c mm/mm.cpp -o mm.o
$(CPP) $(CPP_FLAGS) -c mm/vmm.cpp -o vmm.o
$(CPP) $(CPP_FLAGS) -c hos_defines.cpp -o hos_defines.o
$(CPP) $(CPP_FLAGS) -c fs/vfs.cpp -o vfs.o
$(CPP) $(CPP_FLAGS) -c fs/devfs.cpp -o devfs.o
$(CPP) $(CPP_FLAGS) -c fs/Mount.cpp -o Mount.o
#################################################
# Clean up the source directory of any binaries #
#################################################
clean: clean:
- rm *.s *.o *.bin *~ block/*~ char/*~ fs/*~ lang/*~ mm/*~ sys/*~ video/*~ -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 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
+123
View File
@@ -0,0 +1,123 @@
# 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
-36
View File
@@ -1,36 +0,0 @@
// asmfuncs.h
// Author: Josh Holtrop
// Created: 02/26/04
// Modified: 05/21/04
#ifndef __HOS_ASMFUNCS__
#define __HOS_ASMFUNCS__ __HOS_ASMFUNCS__
#include "hos_defines.h"
extern "C" {
dword write_cr0(dword cr0);
dword read_cr0();
dword write_cr3(dword cr3);
dword read_cr2();
dword read_cr3();
void writeCursorPosition(dword pos);
dword getCursorPosition();
int puts(char *str);
int putDec(int number);
int putDecu(dword number);
void strcpy(char *dest, const char *src);
void memcpy(void *dest, const void *src, dword n);
void memcpyd(void *dest, const void *src, dword n);
void *memset(void *buffer, int c, int num);
void *memsetw(void *buffer, int c, int num);
void *memsetd(void *buffer, int c, int num);
dword strlen(const char *str);
void invlpg_(dword addr);
}
#endif
-9
View File
@@ -1,9 +0,0 @@
//fdc.c
//Author: Josh Holtrop
//Created: 10/30/03
//Modified: 02/26/04
#include "fdc.h"
-23
View File
@@ -1,23 +0,0 @@
//fdc.h
//Author: Josh Holtrop
//Date: 10/30/03
//Modified: 02/26/04
#ifndef __HOS_FDC__
#define __HOS_FDC__ __HOS_FDC__
#include "sys/io.h"
#define FDC_DOR 0x3f2
#define FDC_MSR 0x3f4
//inline void fdc_sendDOR(byte dor);
static inline void fdc_sendDOR(byte dor)
{
outportb(FDC_DOR, dor);
}
#endif
-22
View File
@@ -1,22 +0,0 @@
// loop.c
// Author: Josh Holtrop
// Date: 03/16/04
// Provides a loop-back device for mounting files on existing volumes as new volumes
#include "hos_defines.h"
#include "loop.h"
#include "fs/vfs.h"
int loop_readSector(LoopDevice *ld, dword sector, byte *buffer)
{
return vfs_readFileBlock(ld->vol, ld->filePath, sector * LOOP_SECTOR_SIZE, buffer, LOOP_SECTOR_SIZE);
}
int loop_writeSector(LoopDevice *ld, dword sector, byte *buffer)
{
return vfs_writeFileBlock(ld->vol, ld->filePath, sector * LOOP_SECTOR_SIZE, buffer, LOOP_SECTOR_SIZE);
}
-22
View File
@@ -1,22 +0,0 @@
// loop.h
// Author: Josh Holtrop
// Date: 03/16/04
// Provides a loop-back device for mounting files on existing volumes as new volumes
#ifndef __HOS_LOOP__
#define __HOS_LOOP__ __HOS_LOOP__
#include "hos_includes.h"
typedef struct
{
Volume *vol;
char filePath[256];
} LoopDevice;
int loop_readSector(LoopDevice *ld, dword sector, byte *buffer);
int loop_writeSector(LoopDevice *ld, dword sector, byte *buffer);
#endif
+91
View File
@@ -0,0 +1,91 @@
// 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;
}
+38
View File
@@ -0,0 +1,38 @@
// 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
+100
View File
@@ -0,0 +1,100 @@
// 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;
}
+25
View File
@@ -0,0 +1,25 @@
// 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
-7
View File
@@ -1,7 +0,0 @@
// rd.c
// Author: Josh Holtrop
// Date: 03/11/04
#include "rd.h"
-12
View File
@@ -1,12 +0,0 @@
// rd.h
// Author: Josh Holtrop
// Date: 03/11/04
#ifndef __HOS_RD__
#define __HOS_RD__ __HOS_RD__
#endif
+236
View File
@@ -0,0 +1,236 @@
;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 0x100000000+multiboot_header-VIRT_OFFSET ;header_addr
dd 0x100000000+start-VIRT_OFFSET ;load_addr
dd 0 ;load_end_addr
dd 0x100000000+end-VIRT_OFFSET ;bss_end_addr
dd 0x100000000+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 [0x100000000+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 0x100000000+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"
+151
View File
@@ -0,0 +1,151 @@
// 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;
}
-252
View File
@@ -1,252 +0,0 @@
// keyboard.c
// Author: Josh Holtrop
// Created: 04/17/03
// Modified: 03/02/04
#include "hos_defines.h"
#include "keyboard.h"
#include "sys/io.h"
#include "sys/pic.h"
#include "functions.h"
#include "kio.h"
#define KBD_BUFFER_LENGTH 64
extern "C" {
byte kbdFlags = 0; //holds current keyboard flags - caps/num/scroll/shift/ctrl/alt
byte kbdAscii = 0; //holds ASCII value of a key pressed
byte kbdScan = 0; //holds the keyboard scan code of a key pressed
dword kbdBuffer[KBD_BUFFER_LENGTH]; //a buffer for all keypresses
int kbdBufferStart = 0; //position of next key in buffer
int kbdBufferLen = 0; //number of keys left in the buffer
byte kbdExt = 0; //# of extended key codes left to input
byte kbdExt2 = 0; //# of 2nd-set-extended key codes left to input
byte 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
//nul esc bksp tab lctl lsft rsft lalt caps F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 numScrlNumPad------- unknown---- F11 F12 unknown....
const byte SCAN2ASCII[129] = "\000\0331234567890-=\010\011qwertyuiop[]\n\001asdfghjkl;'`\001\\zxcvbnm,./\001*\001 \001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001-\001\001\001+\001\001\001\001\001\002\002\002\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002";
const byte SCAN2ASCIISHIFT[129] = "\000\033!@#$%^&*()_+\010\011QWERTYUIOP{}\n\001ASDFGHJKL:\"~\001|ZXCVBNM<>?\001*\001 \001\001\001\001\001\001\001\001\001\001\001\001\001789-456+1230.\002\002\002\001\001\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002";
//====FUNCTIONS:
// The Keyboard Interrupt Service Routine
void isr_keyboard()
{
kbdScan = inportb(0x60);
//printf("\nKEYBOARD INTERRUPT: 0x%x", kbdScan);
byte inState = inportb(0x61);
outportb(0x61, inState|0x80);
outportb(0x61, inState);
//printf("IRQ 1: %x\n", kbdScan);
if (kbdScan == 0xFA) //250 //ACKnowledge
{
//printf("KBD_ACK 0x%x!\n", ackReason);
if (ackReason == 0xED) //reset LEDs
{
outportb(0x60, (kbdFlags & 0x07));
}
ackReason = 0;
}
if (kbdScan == 224) //extended key
{
kbdExt = 1;
pic_eoi();
return;
}
if (kbdScan == 225) //2nd-set-extended key
{
kbdExt2 = 2;
pic_eoi();
return;
}
//====handle control keys::
kbdAscii = 2;
switch (kbdScan) //control keys
{
case KBD_SCAN_LSHIFT:
kbdFlags |= KBD_SHIFT;
kbdAscii = 1;
break;
case KBD_SCAN_RSHIFT:
kbdFlags |= KBD_SHIFT;
kbdAscii = 1;
break;
case KBD_SCAN_LCTRL:
kbdFlags |= KBD_CTRL;
kbdAscii = 1;
break;
case KBD_SCAN_LALT:
kbdFlags |= KBD_ALT;
kbdAscii = 1;
break;
case KBD_SCAN_LSHIFT + KBD_SCAN_RELEASED:
kbdFlags &= (KBD_SHIFT ^ 0xFF);
kbdAscii = 1;
break;
case KBD_SCAN_RSHIFT + KBD_SCAN_RELEASED:
kbdFlags &= (KBD_SHIFT ^ 0xFF);
kbdAscii = 1;
break;
case KBD_SCAN_LCTRL + KBD_SCAN_RELEASED:
kbdFlags &= (KBD_CTRL ^ 0xFF);
kbdAscii = 1;
break;
case KBD_SCAN_LALT + KBD_SCAN_RELEASED:
kbdFlags &= (KBD_ALT ^ 0xFF);
kbdAscii = 1;
break;
case KBD_SCAN_CAPS+KBD_SCAN_RELEASED:
kbdFlags ^= KBD_CAPS;
kbdAscii = 1;
kbd_resetLEDs(); //update LEDs
break;
case KBD_SCAN_SCROLL+KBD_SCAN_RELEASED:
kbdFlags ^= KBD_SCROLL;
kbdAscii = 1;
kbd_resetLEDs(); //update LEDs
break;
case KBD_SCAN_NUM+KBD_SCAN_RELEASED:
kbdFlags ^= KBD_NUM;
kbdAscii = 1;
kbd_resetLEDs(); //update LEDs
break;
}
if (kbdAscii == 1)
{
if (kbdExt > 0)
kbdExt--;
pic_eoi();
return;
}
//====determine ASCII value of key::
if (kbdExt > 0) //extended key, kbdScan holds extended key
{
kbdExt--;
kbdAscii = 1;
switch (kbdScan)
{
case KBD_SCANE_ENTER:
kbdAscii = '\n'; break;
case 53: // '/' character (divide on numpad)
kbdAscii = '/'; break;
}
}
else if (kbdExt2 > 0) //extended key 2
{
kbdExt2--;
// if (kbdScan == 69) // (pause|break)
// kbdAscii = 2; //flag ascii value of 1 means control character (pausebreak)
// else
kbdAscii = 2; //flag ascii value of 2 means ignore key (or unknown value)
}
else //not an extended key
{
// if letter key
if (((kbdScan >= 16) && (kbdScan <= 25)) || ((kbdScan >= 30) && (kbdScan <= 38)) || ((kbdScan >= 44) && (kbdScan <= 50)))
{
// if caps and shift are different (either one pressed, not both)
if (((kbdFlags & KBD_SHIFT) != 0) & ((kbdFlags & KBD_CAPS) != 0))
kbdAscii = SCAN2ASCII[kbdScan & 0x7F];
else if (((kbdFlags & KBD_SHIFT) == 0) & ((kbdFlags & KBD_CAPS) == 0))
kbdAscii = SCAN2ASCII[kbdScan & 0x7F];
else
kbdAscii = SCAN2ASCIISHIFT[kbdScan & 0x7F];
}
// if numpad key
else if ((kbdScan >= 71) && (kbdScan <= 83))
{
// if numlock on
if (kbdFlags & KBD_NUM)
kbdAscii = SCAN2ASCIISHIFT[kbdScan & 0x7F];
else
kbdAscii = SCAN2ASCII[kbdScan & 0x7F];
}
// other key
else
{
if ((kbdFlags & KBD_SHIFT) != 0)
kbdAscii = SCAN2ASCIISHIFT[kbdScan & 0x7F];
else
kbdAscii = SCAN2ASCII[kbdScan & 0x7F];
}
}
//====do something with key::
// printf("kbdScan == %d\nkbdAscii == %d\nkbdFlags == %d\n", kbdScan, kbdAscii, kbdFlags);
if ((kbdScan == 83) && (kbdFlags & KBD_CTRL) && (kbdFlags & KBD_ALT))
{
printf("Initiating reboot.");
restart();
}
if (kbdAscii == 2) //unknown key / ignore key
{
pic_eoi();
return;
}
if (kbdScan < KBD_SCAN_RELEASED) //a key was pressed, save it
{
if (kbdBufferLen >= KBD_BUFFER_LENGTH) //no key slots available
{
pic_eoi();
return;
}
else
{
kbdBuffer[(kbdBufferStart+kbdBufferLen++)%KBD_BUFFER_LENGTH] = (dword) ((kbdFlags << 16) | (kbdScan << 8) | kbdAscii);
// printf("S:%d\tL:%d\tR:%x\n", kbdBufferStart, kbdBufferLen, kbdBuffer[kbdBufferStart]);
}
}
pic_eoi();
}
//Gets a key from the buffer, returns 0 if no keys available, returns immediately
dword kbdGetKey()
{
if (kbdBufferLen == 0) //buffer empty
return 0;
dword retVal = kbdBuffer[kbdBufferStart];
kbdBufferStart++;
kbdBufferLen--;
if (kbdBufferStart >= KBD_BUFFER_LENGTH)
kbdBufferStart = 0;
return retVal;
}
//Gets a key from the buffer, if no keys available, waits for one to be entered
dword kbdWaitKey()
{
for (;;)
{
if (kbdBufferLen != 0) //buffer empty
break;
}
dword retVal = kbdBuffer[kbdBufferStart];
kbdBufferStart++;
kbdBufferLen--;
if (kbdBufferStart >= KBD_BUFFER_LENGTH)
kbdBufferStart = 0;
return retVal;
}
//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;
}
}
+13 -30
View File
@@ -1,53 +1,36 @@
// keyboard.h // keyboard.h
// Author: Josh Holtrop // Author: Josh Holtrop
// Created: 04/17/03 // Created: 04/17/03
// Modified: 03/02/04 // Modified: 05/19/05
#include "hos_defines.h" #include "hos_defines.h"
#ifndef __HOS_KEYBOARD__ #ifndef __HOS_KEYBOARD__
#define __HOS_KEYBOARD__ __HOS_KEYBOARD__ #define __HOS_KEYBOARD__ __HOS_KEYBOARD__
#define KBD_SCROLL 0x01 #define KBDF_SCROLL 0x01
#define KBD_NUM 0x02 #define KBDF_NUM 0x02
#define KBD_CAPS 0x04 #define KBDF_CAPS 0x04
#define KBD_SHIFT 0x10 #define KBDF_SHIFT 0x10
#define KBD_CTRL 0x20 #define KBDF_CTRL 0x20
#define KBD_ALT 0x40 #define KBDF_ALT 0x40
#define KBD_SCAN_RELEASED 128 #define KBD_SCAN_RELEASED 0x80
#define KBD_SCAN_LCTRL 29 #define KBD_SCAN_CTRL 29
#define KBD_SCAN_LSHIFT 42 #define KBD_SCAN_LSHIFT 42
#define KBD_SCAN_RSHIFT 54 #define KBD_SCAN_RSHIFT 54
#define KBD_SCAN_LALT 56 #define KBD_SCAN_ALT 56
#define KBD_SCAN_SCROLL 70 #define KBD_SCAN_SCROLL 70
#define KBD_SCAN_CAPS 58 #define KBD_SCAN_CAPS 58
#define KBD_SCAN_NUM 69 #define KBD_SCAN_NUM 69
#define KBD_SCANE_PRINTSCREEN 55 #define KBD_ASCII(x) ((x) & 0xFF)
#define KBD_SCANE_INS 82 #define KBD_SCAN(x) (((x) >> 8) & 0xFF)
#define KBD_SCANE_HOME 71 #define KBD_FLAGS(x) (((x) >> 16) &0xFF)
#define KBD_SCANE_PGUP 73
#define KBD_SCANE_DEL 83
#define KBD_SCANE_END 79
#define KBD_SCANE_PGDN 81
#define KBD_SCANE_ENTER 28
#define KBD_SCANE_NULL 42
//====PROTOTYPES:
extern "C" {
void isr_keyboard(); void isr_keyboard();
void kbd_resetLEDs(); void kbd_resetLEDs();
dword kbdGetKey();
dword kbdWaitKey();
}
#endif #endif
+44
View File
@@ -0,0 +1,44 @@
// 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;
}
}
+31
View File
@@ -0,0 +1,31 @@
// 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
+4 -28
View File
@@ -1,19 +1,13 @@
// mouse.c // mouse.c
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 10/03/03 // Date: 10/03/03
// Modified: 05/21/04 // Modified: 08/02/04
#include "mouse.h"
#include "hos_defines.h" #include "hos_defines.h"
#include "char/mouse.h"
#include "video/video.h" #include "video/video.h"
#include "sys/io.h" #include "sys/io.h"
#define MOUSE_BUFFER_LENGTH 16
extern "C" {
int mouse_x;
int mouse_y;
int mouse_bytesRead; int mouse_bytesRead;
byte mouse_inbuffer[MOUSE_BUFFER_LENGTH]; byte mouse_inbuffer[MOUSE_BUFFER_LENGTH];
@@ -23,16 +17,13 @@ void mouse_init()
outportb(0x64, 0x20); //tell keyboard controller we are going to read keyboard controller command byte outportb(0x64, 0x20); //tell keyboard controller we are going to read keyboard controller command byte
byte temp = inportb(0x60); //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(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(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, 0xA8); //enable mouse port
outportb(0x64, 0xD4); //send command to mouse, not kbd outportb(0x64, 0xD4); //send command to mouse, not kbd
outportb(0x60, 0xF4); //enable data reporting outportb(0x60, 0xF4); //enable data reporting
mouse_x = video_getWidth() >> 1;
mouse_y = video_getHeight() >> 1;
mouse_bytesRead = 0; mouse_bytesRead = 0;
//outportb(0x64, 0xD4); //outportb(0x64, 0xD4);
@@ -53,24 +44,9 @@ void isr_mouse()
mouse_bytesRead = 0; mouse_bytesRead = 0;
int adjx = (char) mouse_inbuffer[1]; int adjx = (char) mouse_inbuffer[1];
int adjy = (char) mouse_inbuffer[2]; int adjy = (char) mouse_inbuffer[2];
mouse_x += adjx; // TODO: do something with adjx, adjy...
mouse_y -= adjy; //-= because screen y coordinates are opposite mouse y coordinates
if (mouse_x < 0)
mouse_x = 0;
if (mouse_x >= video_getWidth())
mouse_x = video_getWidth() - 1;
if (mouse_y < 0)
mouse_y = 0;
if (mouse_y >= video_getHeight())
mouse_y = video_getHeight() - 1;
if (mouse_inbuffer[0] & 0x01) //left button
video_pset(mouse_x, mouse_y, 0x00FF9900);
else
video_pset(mouse_x, mouse_y, 0x00FFFFFF);
} }
} }
}
+2 -4
View File
@@ -1,17 +1,15 @@
// mouse.h // mouse.h
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 10/03/03 // Date: 10/03/03
// Modified: 03/02/04 // Modified: 08/02/04
#ifndef __HOS_MOUSE__ #ifndef __HOS_MOUSE__
#define __HOS_MOUSE__ __HOS_MOUSE__ #define __HOS_MOUSE__ __HOS_MOUSE__
extern "C" { #define MOUSE_BUFFER_LENGTH 16
void mouse_init(); void mouse_init();
void isr_mouse(); void isr_mouse();
}
#endif #endif
+274
View File
@@ -0,0 +1,274 @@
// 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;
}
+76
View File
@@ -0,0 +1,76 @@
// 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
+65
View File
@@ -0,0 +1,65 @@
// 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; }
+58
View File
@@ -0,0 +1,58 @@
// 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
+75
View File
@@ -0,0 +1,75 @@
// 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 */
}
+28
View File
@@ -0,0 +1,28 @@
// 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
+141
View File
@@ -0,0 +1,141 @@
// 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);
}
+20
View File
@@ -0,0 +1,20 @@
// 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
+111
View File
@@ -0,0 +1,111 @@
// 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;
}
+25
View File
@@ -0,0 +1,25 @@
// 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
+21
View File
@@ -0,0 +1,21 @@
// 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;}
+35
View File
@@ -0,0 +1,35 @@
// 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
-28
View File
@@ -1,28 +0,0 @@
// Mount.cpp
// Author: Josh Holtrop
// Date: 06/16/04
// Modified: 06/16/04
#include "lang/string.h"
#include "Mount.h"
Mount::Mount()
{
}
Mount::Mount(string dev, string mount)
{
mountPoint = mount;
device = dev;
}
bool Mount::operator==(const Mount & second) const
{
/* Match *either* device or mountPoint to signal an invalid mount attempt */
return (device == second.device || mountPoint == second.mountPoint);
}
-28
View File
@@ -1,28 +0,0 @@
// Mount.h
// Author: Josh Holtrop
// Date: 06/16/04
// Modified: 06/16/04
#ifndef __HOS_MOUNT__
#define __HOS_MOUNT__ __HOS_MOUNT__
#include "hos_defines.h"
class Mount
{
public:
string mountPoint;
string device;
dword major;
dword minor;
Mount();
Mount(string dev, string mount);
bool operator==(const Mount & second) const;
};
#endif
+15
View File
@@ -0,0 +1,15 @@
// 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; }
+23
View File
@@ -0,0 +1,23 @@
// 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
+13
View File
@@ -0,0 +1,13 @@
// 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; }
+23
View File
@@ -0,0 +1,23 @@
// 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
+39
View File
@@ -0,0 +1,39 @@
// 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;
}
+31
View File
@@ -0,0 +1,31 @@
// 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
-25
View File
@@ -1,25 +0,0 @@
// devfs.cpp
// device filesystem for HOS
// Author: Josh Holtrop
// Date: 06/03/04
// Modified: 06/16/04
#include "devfs.h"
#include "kio.h"
#include "lang/string.h"
#include "vfs.h"
void devfs_init(string mountPoint)
{
vfs_mount("devfs ", mountPoint);
vfs_mount("testdev ", "/mnt/win");
vfs_mount("/dev/hda6", "/scratch");
vfs_mount("/dev/rd0 ", "/");
vfs_mount("/dev/sda1", "/mnt/usb");
vfs_mount("sysfs ", "/sys");
vfs_mount("sysfs ", "/tmp");
vfs_mount("otherfs ", "/sys");
}
-17
View File
@@ -1,17 +0,0 @@
// devfs.h
// device filesystem for HOS
// Author: Josh Holtrop
// Date: 06/03/04
// Modified: 06/08/04
#ifndef __HOS_DEVFS__
#define __HOS_DEVFS__ __HOS_DEVFS__
#include "lang/string.h"
void devfs_init(string mountPoint);
#endif
+143
View File
@@ -0,0 +1,143 @@
// 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];
}
+34
View File
@@ -0,0 +1,34 @@
// 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
+238
View File
@@ -0,0 +1,238 @@
// 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 */
}
+37
View File
@@ -0,0 +1,37 @@
// 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
+228
View File
@@ -0,0 +1,228 @@
// 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);
lockit(&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 */
lockit(&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;
}
+47
View File
@@ -0,0 +1,47 @@
// 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
+599
View File
@@ -0,0 +1,599 @@
// 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;
}
+204
View File
@@ -0,0 +1,204 @@
// 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
+762
View File
@@ -0,0 +1,762 @@
// 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;
}
+241
View File
@@ -0,0 +1,241 @@
// 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
+332
View File
@@ -0,0 +1,332 @@
// 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;
}
+241
View File
@@ -0,0 +1,241 @@
// 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
+42
View File
@@ -0,0 +1,42 @@
// 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;
}
+37
View File
@@ -0,0 +1,37 @@
// 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
+20
View File
@@ -0,0 +1,20 @@
// 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()
{
}
+30
View File
@@ -0,0 +1,30 @@
// 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
-113
View File
@@ -1,113 +0,0 @@
// vfat.c
// Author: Josh Holtrop
// Date: 03/11/04
// Modified: 03/22/04
#include "vfat.h"
#include "hos_defines.h"
#include "fs/vfs.h"
#include "mm/vmm.h"
#include "lang/cstring.h"
//From Microsoft's FAT32 File System Specification
DSKSZTOSECPERCLUS DskTableFAT16 [] =
{
{ 8400, 0}, /* disks up to 4.1 MB, the 0 value for SecPerClusVal trips an error */
{ 32680, 2}, /* disks up to 16 MB, 1k cluster */
{ 262144, 4}, /* disks up to 128 MB, 2k cluster */
{ 524288, 8}, /* disks up to 256 MB, 4k cluster */
{ 1048576, 16}, /* disks up to 512 MB, 8k cluster */
/* The entries after this point are not used unless FAT16 is forced */
// { 2097152, 32}, /* disks up to 1 GB, 16k cluster */
// { 4194304, 64}, /* disks up to 2 GB, 32k cluster */
{ 0xFFFFFFFF, 0} /* any disk greater than 2GB, 0 value for SecPerClusVal trips an error */
};
//From Microsoft's FAT32 File System Specification
DSKSZTOSECPERCLUS DskTableFAT32 [] =
{
{ 66600, 0}, /* disks up to 32.5 MB, the 0 value for SecPerClusVal trips an error */
{ 532480, 1}, /* disks up to 260 MB, .5k cluster */
{ 16777216, 8}, /* disks up to 8 GB, 4k cluster */
{ 33554432, 16}, /* disks up to 16 GB, 8k cluster */
{ 67108864, 32}, /* disks up to 32 GB, 16k cluster */
{ 0xFFFFFFFF, 64}/* disks greater than 32GB, 32k cluster */
};
int vfat_identify(vfat_bpb *bpb)
{
int rootDirSectors = ((bpb->rootEntries * 32) + (bpb->bytesPerSector - 1)) / bpb->bytesPerSector;
int totalSectors = bpb->totalSectors16 ? bpb->totalSectors16 : bpb->totalSectors32;
int fatSectors = bpb->sectorsPerFAT16 ? bpb->sectorsPerFAT16 : bpb->sectorsPerFAT32;
int dataSectors = totalSectors - (bpb->reservedSectors + bpb->numFATs * fatSectors + rootDirSectors);
int clusters = dataSectors / bpb->sectorsPerCluster;
if (clusters < 4085)
return 12;
if (clusters < 65525)
return 16;
return 32;
}
int vfat_format(Volume *vol)
{
}
FILE *vfat_open(char *fileName, dword attributes, Volume *vol)
{
while (*fileName == '/')
++fileName;
if (strlen(fileName) < 1)
return 0;
vfat_bpb *bpb = vfat_getBootSector(vol);
if (!bpb) return 0;
byte *fat = vfat_loadFAT(vol, bpb);
if (!fat)
{
free(bpb);
return 0;
}
int segs = string_split(fileName); //number of sections of path (1=file is in root directory)
int me = vfat_identify(bpb);
if (me != 32)
{
if (segs == 1) //we are looking for the file in the root directory
{
vfat_getEntryInRoot(vol, bpb, fileName, 0);
}
}
else
{
}
}
byte *vfat_loadFAT(Volume *vol, vfat_bpb *bpb)
{
int fatSize = bpb->sectorsPerFAT16 ? bpb->sectorsPerFAT16 : bpb->sectorsPerFAT32;
byte *fat = malloc(fatSize << 9); //512 bytes per sector
if (!fat) return 0;
if (vfs_readSectorn(vol, bpb->reservedSectors, fat, fatSize))
{
free(fat);
return 0;
}
return fat;
}
vfat_bpb *vfat_getBootSector(Volume *vol)
{
vfat_bpb *bs;
if (!(bs = malloc(512)))
return 0;
vfs_readSector(vol, 0, bs);
return bs;
}
int vfat_close(FILE *fp)
{
return free(fp);
}
-134
View File
@@ -1,134 +0,0 @@
// vfat.h
// Author: Josh Holtrop
// Date: 03/11/04
// Modified: 03/22/04
#ifndef __HOS_VFAT__
#define __HOS_VFAT__ __HOS_VFAT__
#include "hos_defines.h"
#include "fs/vfs.h"
#define VFAT_FAT12_EOCL 0x0FF8 // end-of-cluster chain reached if FatValue >= EOCL
#define VFAT_FAT16_EOCL 0xFFF8
#define VFAT_FAT32_EOCL 0x0FFFFFF8
#define VFAT_FAT12_EOC 0x0FFF // end-of-cluster chain value
#define VFAT_FAT16_EOC 0xFFFF
#define VFAT_FAT32_EOC 0x0FFFFFFF
#define VFAT_FAT12_BAD 0x0FF7 // bad cluster mark
#define VFAT_FAT16_BAD 0xFFF7
#define VFAT_FAT32_BAD 0x0FFFFFF7
#define VFAT_DIRENTRY_FREE 0xE5
#define VFAT_DIRENTRY_FREE_LAST 0x00
typedef struct
{
byte jmpBoot[3]; // {0xEB, 0x??, 0x90} or {0xE9, 0x??, 0x??}
char OEMName[8]; // any 8-char string (def. "MSWIN4.1")
word bytesPerSector; // 512 (default), 1024, 2048, 4096
byte sectorsPerCluster; // 1 (default), 2, 4, 8, 16, 32, 64, 128
word reservedSectors; // 1 (fat12/16), 32 (fat32)
byte numFATs; // 2
word rootEntries; // number of 32-byte root directory entries (224 for 1440k floppy) - 0 for fat32
word totalSectors16; // total number of sectors in volume (2880 for floppy) - 0 for fat32
byte media; // >= 0xF0 valid, 0xF8 (default non-removable), 0xF0 (default removable), must match lsb of FAT[0]
word sectorsPerFAT16; // number of sectors in FAT (9 for floppy)
word sectorsPerTrack; // (18 for floppy)
word numHeads; // number of heads (2 for floppy)
dword hiddenSectors; // 0
dword totalSectors32; // 0, non-zero for fat32 volumes
/* FAT32 specific members */
dword sectorsPerFAT32; // number of sectors in a fat for fat32 volumes
word extFlags; // bits 0-3 active fat, bit 7 {0 = mirror all FATs, 1 = only use 1 FAT}
word fsVersion; // fat32 version (0:0)
dword rootCluster; // first cluster of root directory (default 2)
word fsInfo; // sector number of FSINFO block (default 1)
word bootCopy; // sector of backup boot record (default 6)
} __attribute__ ((packed)) vfat_bpb;
typedef struct
{
dword leadSignature; // 0x41615252
byte reserved1[480];
dword structSignature; // 0x61417272
dword lastFree; // last known free cluster (0xFFFFFFFF == unknown)
dword nextFree; // start looking for free clusters here (0xFFFFFFFF == unknown)
byte reserved2[12];
dword trailSignature; // 0xAA550000
} __attribute__ ((packed)) vfat_fsinfo;
typedef struct
{
char fileName[8]; // file name, 8 char. max, pad w/ spaces
char fileExt[3]; // file extension, 3 char. max, pad w/ spaces
byte attributes; // file attributes, read-only, etc.
byte reserved; // 0
byte timeTenths; // 0-199
word time; // time of creation
word date; // date of creation
word adate; // last accessed date
word clusterHigh; // 0 for fat12/16
word wtime; // last write time
word wdate; // last write date
word clusterLow; // LSW of first cluster of file data
dword fileSize;
} __attribute__ ((packed)) vfat_dirEntry;
typedef struct
{
byte order;
word name0_4[5]; // filename - first 5 characters (unicode)
byte attributes; // must be VFAT_LONG_NAME
byte type; // 0 = part of long name
byte checksum; // checksum of short entry at end of long entry set
word name5_10[6]; // filename - next 6 characters (unicode)
word clusterLow; // 0
word name11_12[2]; // filename - next 2 characters
} __attribute__ ((packed)) vfat_lfnEntry;
#define VFAT_READ_ONLY 0x01
#define VFAT_HIDDEN 0x02
#define VFAT_SYSTEM 0x04
#define VFAT_VOLUME 0x08
#define VFAT_DIRECTORY 0x10
#define VFAT_ARCHIVE 0x20
#define VFAT_LONG_NAME 0x0F // VFAT_READ_ONLY | VFAT_HIDDEN | VFAT_SYSTEM | VFAT_VOLUME
#define VFAT_ATTR_MASK 0x3F // VFAT_READ_ONLY | VFAT_HIDDEN | VFAT_SYSTEM | VFAT_VOLUME | VFAT_DIRECTORY | VFAT_ARCHIVE
#define VFAT_ORDER_MASK 0x40
/*
* Illegal file name characters:
* Values less than 0x20 except for 0x05. 0x05 signifies that the actual filename character is 0xE5
* 0x22 ("), 0x2A (*)
* 0x2E (.), 0x2F (/), 0x3A (:)
* 0x3C (<), 0x3E (>), 0x3F (?), 0x5C (\), 0x7C (|)
* The following are illegal in 8.3 but legal in LFN:
* 0x2B (+), 0x2C (,), 0x3B (;), 0x3D (=), 0x5B ([), 0x5D (])
*/
//From Microsoft's FAT32 File System Specification
typedef struct
{
dword diskSize;
byte sectorsPerCluster;
} DSKSZTOSECPERCLUS;
// sector[510] == 0x55
// sector[511] == 0xAA
int vfat_identify(vfat_bpb *bpb);
int vfat_format(Volume *vol);
FILE *vfat_open(char *fileName, dword attributes, Volume *vol);
vfat_bpb *vfat_getBootSector(Volume *vol);
int vfat_close(FILE *fp);
byte *vfat_loadFAT(Volume *vol, vfat_bpb *bpb)
#endif
+400 -42
View File
@@ -1,55 +1,413 @@
// vfs.cpp // vfs.cpp
// Virtual file system subsystem for HOS
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 03/11/04 // Date: 05/10/05
// Modified: 04/16/04 // Modified: 12/26/05
extern "C" {
#include "hos_defines.h" #include "hos_defines.h"
#include "display/kout.h"
#include "functions.h"
#include "lang/lang.h"
}
#include "vfs.h" #include "vfs.h"
//#include "fs/vfat.h" #include "fs/FileSystem.h"
//#include "block/rd.h" #include "fs/VFSMount.h"
//#include "block/loop.h" #include "fs/ext2/ext2.h"
#include "lang/LinkedList.h" #include "lang/vector.h"
#include "lang/string.h" #include "lang/string.h"
#include "devfs.h" #include "devices.h"
#include "kio.h"
#include "Mount.h"
LinkedList<Mount> *mounts;
void vfs_init() /* 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 *>;
mounts = new LinkedList<Mount>; fses = new vector<FSHandle>;
ext2_init();
}
void list()
{
LinkedList<Mount>::iterator it = mounts->begin();
while (it != mounts->end())
{
printf("%s\t%s\n", (*it).device.data(), (*it).mountPoint.data());
++it;
}
}
int vfs_mount(string device, string mountPoint)
{
Mount mount(device, mountPoint);
LinkedList<Mount>::iterator it = mounts->begin();
int i = 0;
while (it != mounts->end() && (*it).mountPoint <= mount.mountPoint)
{
if (*it == mount)
return 1; //device already mounted or mount point already taken
i++;
++it;
}
mounts->insert(i, mount);
return 0; 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;
}
+119 -9
View File
@@ -1,19 +1,129 @@
// vfs.h // vfs.h
// Virtual file system subsystem for HOS
// Author: Josh Holtrop // Author: Josh Holtrop
// Date: 03/11/04 // Date: 05/10/05
// Modified: 06/16/04 // Modified: 12/26/05
#ifndef __HOS_VFS__ #ifndef __HOS_VFS_H__
#define __HOS_VFS__ __HOS_VFS__ #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 "hos_defines.h"
#include "lang/string.h" #include "devices.h"
void vfs_init();
int vfs_mount(string device, string mountPoint); typedef struct
void list(); {
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
#endif
+432
View File
@@ -0,0 +1,432 @@
// 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;
}
+165
View File
@@ -0,0 +1,165 @@
// 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
+31 -14
View File
@@ -9,9 +9,15 @@
#include "hos_defines.h" #include "hos_defines.h"
#include "sys/io.h" #include "sys/io.h"
extern dword _code; #ifdef __cplusplus
extern dword _bss; extern "C" {
extern dword _end; #endif
extern u32_t _code;
extern u32_t _bss;
extern u32_t _end;
#ifdef __cplusplus
}
#endif
//Enables (SeTs) Interrupt Flag on the processor //Enables (SeTs) Interrupt Flag on the processor
static inline void enable_ints() static inline void enable_ints()
@@ -47,34 +53,33 @@ static inline void halt()
{ {
asm("cli"); asm("cli");
asm("hlt"); asm("hlt");
while (1); while (1) ;
} }
//Initializes 8253 Programmable Interrupt Timer //Initializes 8253 Programmable Interrupt Timer
static inline void timer_init() static inline void timer_init(u32_t freq)
{ {
//set timer : 2e9c = 100hz u32_t wait = 1193180 / freq; //how many ticks the PIT must wait before issuing an interrupt
outportb(0x43, 0x34); outportb(0x43, 0x34);
outportb(0x40, 0x9c); //lsb outportb(0x40, wait); //lsb
outportb(0x40, 0x2e); //msb outportb(0x40, wait >> 8); //msb
} }
//Returns the size of the kernel (code & data) //Returns the size of the kernel (code & data & bss)
// - this does include the bss section
// - this should be 4kb aligned per the linker script // - this should be 4kb aligned per the linker script
// - this is the amount of RAM the kernel code, data, & bss take // - this is the amount of RAM the kernel code, data, & bss take
static inline dword kernel_size_used() static inline u32_t kernel_size_used()
{ {
return (dword)(&_end)-(dword)(&_code); return (u32_t)(&_end)-(u32_t)(&_code);
} }
//Returns the size of the kernel (code & data) //Returns the size of the kernel (code & data)
// - this does not include the bss section // - this does not include the bss section
// - this should be 4kb aligned per the linker script // - this should be 4kb aligned per the linker script
// - this should be the size of kernel.bin // - this should be the size of kernel.bin
static inline dword kernel_size() static inline u32_t kernel_size()
{ {
return (dword)(&_bss)-(dword)(&_code); return (u32_t)(&_bss)-(u32_t)(&_code);
} }
//converts a binary-coded-decimal byte to its decimal equivalent //converts a binary-coded-decimal byte to its decimal equivalent
@@ -89,6 +94,18 @@ static inline byte byte2bcd(byte bite)
return ((bite / 10) << 4) | (bite % 10); 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 #endif
+19 -33
View File
@@ -6,65 +6,51 @@
gdtr: gdtr:
dw gdt_end-gdt-1 dw gdt_end-gdt-1
dd GDT_V dd GDT_V
gdt: gdt: ; 0
dd 0 dd 0
dd 0 dd 0
KERNEL_CODE equ $-gdt
KERNEL_CODE equ $-gdt ; 8
dw 0xffff ;limit 15:0 dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0 dw 0x0000 ;base 15:0
db 0x00 ;base 23:16 db 0x00 ;base 23:16
db 0x9A ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A]) db 0x9A ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16 db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24 db 0x00 ;base 31:24
KERNEL_DATA equ $-gdt
KERNEL_DATA equ $-gdt ; 16
dw 0xffff ;limit 15:0 dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0 dw 0x0000 ;base 15:0
db 0x00 ;base 23:16 db 0x00 ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A]) db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16 db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24 db 0x00 ;base 31:24
USER_CODE equ $-gdt
USER_CODE equ $-gdt ; 24
dw 0xffff ;limit 15:0 dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0 dw 0x0000 ;base 15:0
db 0x00 ;base 23:16 db 0x00 ;base 23:16
db 0xFA ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A]) db 0xFA ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16 db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24 db 0x00 ;base 31:24
USER_DATA equ $-gdt
USER_DATA equ $-gdt ; 32
dw 0xffff ;limit 15:0 dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0 dw 0x0000 ;base 15:0
db 0x00 ;base 23:16 db 0x00 ;base 23:16
db 0xF2 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A]) db 0xF2 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16 db 0xCF ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24 db 0x00 ;base 31:24
gVESA_CODE equ $-gdt
dw 0xffff ;limit 15:0 TSS0_SEG equ $-gdt ; 40
dw 0x0000 ;base 15:0 dw 0x67 ;limit 15:0
db 0x00 ;base 23:16 dw 0 ;base 15:0
db 0x9A ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A]) db 0 ;base 23:16
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16 db 0xE9 ;access ([P][DPL][0][1][0][Busy][1])
db 0x00 ;base 31:24 db 0x00 ;flags ([G][0][0][AVL]) / limit 19:16
VESA_DATA equ $-gdt db 0 ;base 31:24
dw 0xffff ;limit 15:0
dw 0x0000 ;base 15:0
db 0x00 ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
VIDEO_TEXT equ $-gdt
dw 0x7FFF ;limit 15:0
dw 0x8000 ;base 15:0
db 0x0B ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
VIDEO_GRAPHICS equ $-gdt
dw 0xFFFF ;limit 15:0
dw 0x0000 ;base 15:0
db 0x0A ;base 23:16
db 0x92 ;access ([P][DPL][1][Executable][Direction/Conforming][Writable/Readable][A])
db 0x40 ;flags ([G][D/B][0][0]) / limit 19:16
db 0x00 ;base 31:24
gdt_end: gdt_end:
-27
View File
@@ -1,27 +0,0 @@
#include "mm/vmm.h"
//overload the operator "new"
void * operator new (dword size)
{
return malloc(size);
}
//overload the operator "new[]"
void * operator new[] (dword size)
{
return malloc(size);
}
//overload the operator "delete"
void operator delete (void *p)
{
free(p);
}
//overload the operator "delete[]"
void operator delete[] (void *p)
{
free(p);
}
+45 -35
View File
@@ -1,48 +1,58 @@
//hos_defines.h // hos_defines.h
//03/17/03 Josh Holtrop // Author: Josh Holtrop
//Modified: 03/02/04 // Date: 08/15/04
// Modified: 08/16/04
#ifndef __HOS_HOS_DEFINES__ #ifndef __HOS_DEFINES_H__
#define __HOS_HOS_DEFINES__ __HOS_HOS_DEFINES__ #define __HOS_DEFINES_H__ __HOS_DEFINES_H__
#define FREERAM_START 0x368000 // 0x368000 is first available byte (this is right after the initrd @ 2mb, 1440kb. #define PARALLEL_DEBUG
#define MAX_RAM 0x40000000 //1gb maximum RAM supported
#define PID_KERNEL 0x02 //kernel's PID #define HOS_TIMER_FREQ 1000
#define PID_VMM 0x03 #define KERNEL_MSG_CONSOLE 11
#define PID_USER 0x10000 //user processes' start PID
#define VIRT_OFFSET 0xC0000000
#define PHYS_LOAD 0x00108000
#define PDBR 0x00104000
#define VIRT_STACK_TOP 0xD0000000
#define HEAP_START 0xD0000000
#define HEAP_LENGTH 0x20000000
//these defines are the memory locations of values saved by the stage 2 bootloader #define CONSOLE_MEMORY 0xC00B8000
#define BOOT_MEMMAP_ENTRIES 0xC009040A #define BIOS_CHAR_MAP 0xC00FFA6E
#define BOOT_FIRST_MEMMAP 0xC0092000 #define LFB_MEMORY 0xF0000000
#define BOOT_VIDEO_MODE 0xC0090002
#define BOOT_VIDEO_MODE_INFO_BLOCK 0xC0090306 #define SEG_KERNEL_CODE 8
#define BOOT_HASRD 0xC0090000 #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 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 unsigned char byte;
typedef unsigned short word; typedef int lock_t;
typedef unsigned int dword;
typedef struct { #ifdef __cplusplus
dword lowdword; extern "C" {
dword highdword; #endif
} __attribute__((packed)) qword; extern u32_t _end;
extern u32_t _bss;
//overload the operator "new" extern u32_t start;
void * operator new (dword size); #ifdef __cplusplus
}
//overload the operator "new[]" #endif
void * operator new[] (dword size);
//overload the operator "delete"
void operator delete (void *p);
//overload the operator "delete[]"
void operator delete[] (void *p);
#endif #endif
+39 -39
View File
@@ -1,7 +1,7 @@
;idt.inc ;idt.inc
;Author: Josh Holtrop ;Author: Josh Holtrop
;Date: 10/30/03 ;Date: 10/30/03
;Modified: 03/02/04 ;Modified: 01/02/06
idtr: idtr:
dw 50*8-1 ;size of idt dw 50*8-1 ;size of idt
@@ -67,51 +67,51 @@ isr_label 48
isr_label 49 isr_label 49
isr_main: isr_main:
cmp eax, 0x30 ; ok, here, we need to duplicate the top item on the stack
jz isr_syscall ; (the old eax) if the interrupt number is not 8 or 10-14
; this is to properly align the stack for both exceptions
pusha ; having and not having error codes
push ds cmp eax, 8
push es 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 push eax
mov eax, [esp+8]
call _isr mov [esp+4], eax
add esp, 4
pop es
pop ds
popa
pop eax pop eax
isr_main_nodup:
iret push ebx
push ecx
push edx
isr_syscall: push edi
pop eax ;syscall function number push esi
pusha push ebp
push ds push ds
push es push es
push fs
push gs
sc1: push esp
cmp eax, 1 ;syscall 1 - putc push eax ;interrupt number
jnz sc2 call isr
push ebx add esp, 8
call _putc
add esp, 4
jmp scdone
sc2:
scdone: pop gs
pop fs
pop es pop es
pop ds pop ds
popa pop ebp
pop esi
pop edi
pop edx
pop ecx
pop ebx
add esp, 4 ;bypass error code
pop eax ;original saved eax
iret iret
Loaded 100 of 183 files, more files were not shown because too many files have changed in this diff. Show more