Compare commits

..

62 Commits

Author SHA1 Message Date
cb6bd3914c Remove HOS v0.16 sources 2022-02-28 15:10:25 -05:00
56c3be9207 Update to rscons 3.0.0 2022-02-28 13:40:08 -05:00
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
6b1de7c9d4 Explicitly check page boundaries when adding bootloader-provided memory regions 2021-08-16 17:35:11 -04:00
ebfeca47b5 Use size_t rather than uint32_t 2021-08-16 14:01:39 -04:00
43f4a1f4b1 Show kernel size/address 2021-08-16 13:59:39 -04:00
0f73efbdc3 add mm module to manage free physical page regions 2020-10-26 20:17:08 -04:00
a084ab296c define _hos_mem_start and _hos_mem_end symbols 2020-10-25 17:08:07 -04:00
aa28284187 build kernel .size file on build 2020-10-25 17:06:56 -04:00
87c135b010 set up a GDT to stop using the one GRUB set up 2020-10-25 16:49:09 -04:00
3d30025d3b write a map file when linking 2020-10-25 16:48:42 -04:00
556b0f0c4d add gdt.h 2020-10-23 00:48:40 -04:00
bffd652c16 walk multiboot2 memory map 2020-10-23 00:47:19 -04:00
cbd427b14b add 64-bit formatting support 2020-10-23 00:46:40 -04:00
fa4ff5facf load some multiboot2 info after the framebuffer is initialized 2020-10-22 22:03:43 -04:00
db16e69d5d add klog module to print kernel messages 2020-10-20 21:44:21 -04:00
1d3b0a5621 make fb_clear() public 2020-10-20 20:24:48 -04:00
d03a34ab3e fb: store fb.pitch in words, not bytes 2020-10-20 20:07:51 -04:00
494ef6de81 add fb_width(), fb_height() 2020-10-20 20:06:54 -04:00
784009ba6c hos_printf: handle field width, zero-padding, and left-justifiying conversion specifiers 2020-10-20 19:56:30 -04:00
9bddf11ee4 stream: use char instead of uint8_t 2020-10-20 19:47:15 -04:00
313b86fdc7 provide an implementation for memcpy() 2020-10-20 19:31:26 -04:00
75491dd36b add hos_printf and stream modules 2020-10-20 19:30:23 -04:00
c8db9fe905 add string.h 2020-10-20 17:55:31 -04:00
d0cbaba4d1 add memcpy(), memmove(), memset() 2020-10-20 17:47:40 -04:00
1f22d0c900 add a few multiboot2 info structures 2020-10-20 17:34:08 -04:00
a474368435 increase kernel font size a little 2020-10-20 17:28:43 -04:00
fb88595dec add fb_clear(), just clear to solid bluish color for now 2020-10-20 17:28:16 -04:00
70b4db9dbb fix fb_text_render_char() to use given color 2020-10-20 17:23:51 -04:00
9fde638b6e build with -O2 2020-10-20 15:09:00 -04:00
b4b77dd52c add mem.h and memset32() 2020-10-20 15:08:12 -04:00
79951bd0f1 add cross/clean.sh 2020-10-20 14:15:28 -04:00
41152cb4ca add fb_fill() 2020-10-20 14:01:14 -04:00
dba3d28bbf draw a character 2020-10-20 13:34:02 -04:00
610f30fae9 generate a built-in kernel font 2020-10-20 00:34:53 -04:00
e22b90b768 configure GRUB to boot HOS automatically after 1s 2020-10-20 00:17:05 -04:00
08fc9a5445 rename target run-bios -> run 2020-10-20 00:11:12 -04:00
a66df19edc add fb_ready() 2020-10-20 00:09:09 -04:00
5bc844649b set desired framebuffer size to 1600x900x32 2020-10-19 23:57:54 -04:00
0d390465f6 simplify boot.S 2020-10-19 23:42:02 -04:00
04d29fdb71 add mbinfo module to parse multiboot2 boot info 2020-10-19 23:34:42 -04:00
e9f426894c rename kernel_main.c -> hos_main.c 2020-10-19 22:40:55 -04:00
c8810e4701 rename _start -> hos_start 2020-10-19 22:26:12 -04:00
b202eca0cc define startup stack in linker script, not assembly 2020-10-19 22:23:39 -04:00
05de14800b remove hard tabs! 2020-10-19 22:12:34 -04:00
8ae84716d6 rename kernel_main() to hos_main() 2020-10-19 22:12:17 -04:00
bb495eceec add "fb" module for framebuffer control 2020-10-19 22:09:33 -04:00
67b90a482f add "clean" target 2020-10-19 21:59:54 -04:00
85e5b76aa3 Move multiboot2 header from assembly to C. 2020-10-19 21:44:27 -04:00
412925a790 switch from multiboot to multiboot2 2020-10-18 14:25:06 -04:00
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
d08d54ecbf make run tasks depend on all 2020-10-18 13:29:56 -04:00
06644a02f9 draw pixels to screen to verify framebuffer access and multiboot info 2020-10-18 13:25:26 -04:00
8f9881889b build both BIOS and EFI images 2020-10-18 13:16:02 -04:00
a91ea8d620 update Makefile to wrap rscons and add run target 2020-10-15 20:05:58 -04:00
a9a2f6dcaf fix GRUB config to add a HOS menu entry 2020-10-15 20:01:40 -04:00
9befd553eb always disassemble kernel when building 2020-10-15 19:47:20 -04:00
6053745ee9 build kernel as 32-bit ELF for now so GRUB can recognize it as multiboot 2020-10-15 19:46:53 -04:00
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
bbf212d5a2 add configure script 2020-10-13 19:53:14 -04:00
94ed9078df update rscons 2020-10-13 19:20:19 -04:00
e97e76da7b add cross compiler build script and configure script 2020-10-06 20:06:19 -04:00
142 changed files with 1672 additions and 12657 deletions

View File

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

9
.gitignore vendored
View File

@ -1,6 +1,3 @@
/hos.flp
/hos_initrd
/hos_initrd.gz
*.lst
*.map
*.bin
.rscons*
/i686-elf-gcc/
/build/

View File

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

166
Rsconscript Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

View File

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

View File

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

Binary file not shown.

View File

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

View File

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

BIN
e2fs

Binary file not shown.

BIN
font/Hack-Regular.ttf Normal file

Binary file not shown.

224
fontgen/fontgen.c Normal file
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
grub.flp

Binary file not shown.

75
i686-elf-gcc.rb Normal file
View File

@ -0,0 +1,75 @@
binutils_version = "2.35"
binutils_checksum = "1b11659fb49e20e18db460d44485f09442c8c56d5df165de9461eb09c8302f85"
gcc_version = "10.2.0"
gcc_checksum = "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c"
install_path = File.expand_path("i686-elf-gcc")
target = "i686-elf"
path_prepend "#{install_path}/bin"
configure do
check_c_compiler "gcc"
check_program "make"
check_program "bison"
check_program "flex"
check_program "texi2any", on_fail: "Install the texinfo package"
check_program "wget"
check_lib "gmp", on_fail: "Install the libgmp-dev package"
check_lib "mpc", on_fail: "Install the libmpc-dev package"
check_lib "mpfr", on_fail: "Install the libmpfr-dev package"
end
default do
unless Dir.exist?(install_path)
# Download archives.
download "https://ftp.gnu.org/gnu/binutils/binutils-#{binutils_version}.tar.xz",
"#{build_dir}/binutils-#{binutils_version}.tar.xz",
sha256sum: binutils_checksum
download "https://ftp.gnu.org/gnu/gcc/gcc-#{gcc_version}/gcc-#{gcc_version}.tar.xz",
"#{build_dir}/gcc-#{gcc_version}.tar.xz",
sha256sum: gcc_checksum
# Extract archives.
sh "tar", "xJf", "binutils-#{binutils_version}.tar.xz",
chdir: build_dir
sh "tar", "xJf", "gcc-#{gcc_version}.tar.xz",
chdir: build_dir
# Build binutils.
rm_rf "#{build_dir}/build-binutils"
mkdir_p "#{build_dir}/build-binutils"
cd "#{build_dir}/build-binutils" do
sh %W[../binutils-#{binutils_version}/configure
--target=#{target} --prefix=#{install_path} --with-sysroot --disable-nls
--disable-werror]
sh "make"
sh "make install"
end
# Build gcc.
rm_rf "#{build_dir}/build-gcc"
mkdir_p "#{build_dir}/build-gcc"
cd "#{build_dir}/build-gcc" do
sh %W[../gcc-#{gcc_version}/configure
--target=#{target} --prefix=#{install_path} --disable-nls
--enable-languages=c,c++ --without-headers]
sh "make all-gcc"
sh "make all-target-libgcc"
sh "make install-gcc"
sh "make install-target-libgcc"
end
# Remove archives and build directories if everything succeeded.
rm_f "#{build_dir}/binutils-#{binutils_version}.tar.xz"
rm_rf "#{build_dir}/binutils-#{binutils_version}"
rm_rf "#{build_dir}/build-binutils"
rm_f "#{build_dir}/gcc-#{gcc_version}.tar.xz"
rm_rf "#{build_dir}/gcc-#{gcc_version}"
rm_rf "#{build_dir}/build-gcc"
end
end
distclean do
rm_rf install_path
end

Binary file not shown.

View File

@ -1 +0,0 @@
test_file

View File

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

View File

@ -1,129 +0,0 @@
# Makefile for HOS
# Josh Holtrop
# Created: 07/08/04
# Modified: 06/13/05
# Assembler Information:
NASM=nasm
NASM_FLAGS=-f elf32
# C/C++ Information:
CPPFLAGS=-ffreestanding -fno-builtin -nostdlib -nostartfiles -nodefaultlibs -I. -Wall -m32 -fno-pic
# -S -masm=intel
CC=gcc
CXX=g++
CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_ -std=gnu++98
# Linker Information:
LD=gcc
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
all: $(OBJS)
$(LD) $(LDFLAGS) -Wl,-Map -Wl,kernel.map $(OBJS) -o kernel.bin $(LIBS)
@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 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,236 +0,0 @@
;boot.asm
;Author: Josh Holtrop
;Date: 07/08/04
;Modified: 11/01/05
%define MULTIBOOT_MAGIC 0x1BADB002
%define MULTIBOOT_FLAGS 0x00010003
%define VIRT_OFFSET 0xC0000000 ;3gb virtual address
%define PHYS_START 0x00100000 ;1mb physical address
%define VIRT_STACK_TOP 0xD0000000 ;3gb+256mb virtual address
%define GDT_P PHYS_START ;1mb physical - Global Descriptor Table space
%define GDT_V GDT_P+VIRT_OFFSET
%define IDT_P PHYS_START+0x2000 ;1mb+8kb - Interrupt Descriptor Table space
%define IDT_V IDT_P+VIRT_OFFSET
%define PDBR_P PHYS_START+0x4000 ;1mb+16kb - Page Directory Base Register (first PD)
%define PDBR_V PDBR_P+VIRT_OFFSET
%define LOPT_P PHYS_START+0x5000 ;1mb+20kb - LOw Page Table for mapping first 4mb
%define LOPT_V LOPT_P+VIRT_OFFSET
%define PT_STACK_P PHYS_START+0x6000 ;1mb+24kb - page table for initial kernel stack pages (under 0xD0000000)
%define PT_STACK_V PT_STACK_P+VIRT_OFFSET
%define STACK_P PHYS_START+0x7000 ;1mb+28kb - initial 4kb kernel stack page
%define STACK_V STACK_P+VIRT_OFFSET
%define KERNEL_P PHYS_START+0x8000 ;1mb+32kb - the kernel's physical address
%define KERNEL_V KERNEL_P+VIRT_OFFSET ;3gb+1mb+32kb, the virtual address of the kernel
extern k_init, isr, k_mbsave, end, rm_params, initrd, tss0
[bits 32]
[global start]
start:
multiboot_header:
dd MULTIBOOT_MAGIC ;magic
dd MULTIBOOT_FLAGS ;flags
dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) ;checksum
dd 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"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,228 +0,0 @@
// Ext2OpenFile.cpp
// Author: Josh Holtrop
// Date: 12/26/05
// Modified: 12/26/05
#include "Ext2OpenFile.h"
extern "C" {
#include "lang/lang.h"
#include "functions.h"
}
lock_t Ext2OpenFileListLock;
vector<Ext2OpenFileHandle> *Ext2OpenFileList = NULL;
/* make an Ext2OpenFile object
* maintain vector of open files for notifying when one is truncated
*/
Ext2OpenFile::Ext2OpenFile(Ext2fs *fs, u32_t inum, int mode)
{
myMode = mode;
myFS = fs;
myInum = inum;
myBeenTruncated = 0;
myPosition = 0;
myBlockSize = 1024 << fs->getSuper()->s_log_block_size;
myBlockCache = new u8_t[myBlockSize];
myBlockCacheBlock = 0;
myBlockCacheStatus = 0; /* 0: invalid; 1: valid; 2: dirty */
fs->readInode(inum, &myInode);
myCache = new Ext2BlockCache(fs, inum, &myInode);
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,43 +0,0 @@
// lang.h
// Author: Josh Holtrop
// Created: 02/26/04
// Modified: 12/30/04
#ifndef __HOS_LANG__
#define __HOS_LANG__ __HOS_LANG__
#include "hos_defines.h"
/* lang.asm */
void lockit(lock_t *addr);
void unlock(lock_t *addr);
u32_t read_cr0();
u32_t write_cr0(u32_t cr0);
u32_t read_cr2();
u32_t read_cr3();
u32_t write_cr3(u32_t cr3);
u32_t read_ss();
void writeCursorPosition(u32_t pos);
u32_t getCursorPosition();
void strcpy(char *dest, const char *src);
void memcpy(void *dest, const void *src, u32_t n);
void memcpyw(void *dest, const void *src, u32_t n);
void memcpyd(void *dest, const void *src, u32_t 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);
u32_t strlen(const char *str);
void invlpg_(u32_t addr);
/* lang.c */
int strcmp(char *str1, char *str2);
int strncmp(char *str1, char *str2, int n);
int str_change(char *str, char ch1, char ch2);
int str_count(char *str, char lookfor);
int str_split(char *str, char splitchar);
char *str_advance(char *str);
void strcat(char *dest, char *src);
#endif

View File

@ -1,25 +0,0 @@
// Author: Josh Holtrop
// Date: 05/10/05
// Adds C++ support for new, delete functions
extern "C"
{
#include "hos_defines.h"
#include "mm/vmm.h"
}
//overload the operator "new"
void * operator new (u32_t size)
{ return kmalloc(size); }
//overload the operator "new[]"
void * operator new[] (u32_t size)
{ return kmalloc(size); }
//overload the operator "delete"
void operator delete (void *p)
{ kfree(p); }
//overload the operator "delete[]"
void operator delete[] (void *p)
{ kfree(p); }

View File

@ -1,258 +0,0 @@
// string.cpp
// implements c++ string object for HOS
// Author: Josh Holtrop
// Date: 06/01/04
// Modified: 05/10/05
extern "C"
{
#include "string.h" //string class declaration
#include "lang/lang.h" //memcpy(void *dest, void *src, int n), strlen(char *str)
}
string::string()
{
myLength = 0;
myChars = new char; //myChars must be a valid pointer at all times
*myChars = 0;
}
string::~string()
{
delete[] myChars;
}
string::string(const string & orig)
{
myLength = orig.myLength;
myChars = new char[myLength + 1];
memcpy(myChars, orig.myChars, myLength + 1);
}
string::string(const char *cstring)
{
myLength = strlen(cstring);
myChars = new char[myLength + 1];
memcpy(myChars, cstring, myLength + 1);
}
string & string::operator=(const string & orig)
{
if (this != &orig)
{
delete[] myChars;
myLength = orig.myLength;
myChars = new char[myLength + 1];
memcpy(myChars, orig.myChars, myLength + 1);
}
return *this;
}
string & string::operator=(const char *cstring)
{
if (myChars != cstring)
{
delete[] myChars;
myLength = strlen(cstring);
myChars = new char[myLength + 1];
memcpy(myChars, cstring, myLength + 1);
}
return *this;
}
char * string::data() const { return myChars; }
int string::size() const { return myLength; }
string & string::operator+=(const string & str)
{
char *newStr = new char[myLength + str.myLength + 1];
memcpy(newStr, myChars, myLength);
memcpy(newStr + myLength, str.myChars, str.myLength + 1);
delete[] myChars;
myChars = newStr;
myLength += str.myLength;
return *this;
}
string & string::operator+=(const char *cstring)
{
char *newStr = new char[myLength + strlen(cstring) + 1];
memcpy(newStr, myChars, myLength);
memcpy(newStr + myLength, cstring, strlen(cstring) + 1);
delete[] myChars;
myChars = newStr;
myLength += strlen(cstring);
return *this;
}
string & string::operator+=(char chr)
{
myLength++;
char *newStr = new char[myLength + 1];
memcpy(newStr, myChars, myLength);
newStr[myLength - 1] = chr;
newStr[myLength] = 0;
delete[] myChars;
myChars = newStr;
return *this;
}
string string::operator+(const string & str)
{ return string(*this, str); }
string string::operator+(const char *cstring)
{ return string(*this, cstring); }
string string::operator+(char chr)
{ return string(*this, chr); }
string::string(const string & str1, const string & str2)
{
myLength = str1.myLength + str2.myLength;
myChars = new char[myLength + 1];
memcpy(myChars, str1.myChars, str1.myLength);
memcpy(myChars + str1.myLength, str2.myChars, str2.myLength + 1);
}
string::string(const string & str1, const char *cstring)
{
myLength = str1.myLength + strlen(cstring);
myChars = new char[myLength + 1];
memcpy(myChars, str1.myChars, str1.myLength);
memcpy(myChars + str1.myLength, cstring, strlen(cstring) + 1);
}
string::string(const char *cstring, const string & str)
{
myLength = str.myLength + strlen(cstring);
myChars = new char[myLength + 1];
memcpy(myChars, cstring, strlen(cstring));
memcpy(myChars + strlen(cstring), str.myChars, str.myLength + 1);
}
string::string(const string & str1, char chr)
{
myLength = str1.myLength + 1;
myChars = new char[myLength + 1];
memcpy(myChars, str1.myChars, myLength);
myChars[myLength - 1] = chr;
myChars[myLength] = 0;
}
string::string(char chr, const string & str1)
{
myLength = str1.myLength + 1;
myChars = new char[myLength + 1];
memcpy(myChars + 1, str1.myChars, myLength + 1);
*myChars = chr;
}
const char & string::operator[](unsigned int index) const
{
if (index < myLength)
return myChars[index];
return *myChars; //if index is invalid, return a pointer to the trailing 0
}
char & string::operator[](unsigned int index)
{
if (index < myLength)
return myChars[index];
return *myChars; //if index is invalid, return a pointer to the trailing 0
}
bool string::operator==(const string & second) const
{
if (myLength != second.myLength)
return false;
for (unsigned int i = 0; i < myLength; i++)
{
if (myChars[i] != second.myChars[i])
return false;
}
return true;
}
bool string::operator==(const char *cstring) const
{
if (myLength != strlen(cstring))
return false;
for (unsigned int i = 0; i < myLength; i++)
{
if (myChars[i] != cstring[i])
return false;
}
return true;
}
bool string::operator!=(const string & second) const
{ return !operator==(second); }
bool string::operator!=(const char *cstring) const
{ return !operator==(cstring); }
bool string::operator<(const string & second) const
{
char *c1 = myChars, *c2 = second.myChars;
while (*c1 == *c2 && *c1)
{
c1++;
c2++;
}
return *c1 < *c2;
}
bool string::operator>(const string & second) const
{
char *c1 = myChars, *c2 = second.myChars;
while (*c1 == *c2 && *c1)
{
c1++;
c2++;
}
return *c1 > *c2;
}
bool string::operator<(const char *cstring) const
{
char *c1 = myChars;
while (*c1 == *cstring && *c1)
{
c1++;
cstring++;
}
return *c1 < *cstring;
}
bool string::operator>(const char *cstring) const
{
char *c1 = myChars;
while (*c1 == *cstring && *c1)
{
c1++;
cstring++;
}
return *c1 > *cstring;
}
bool string::operator<=(const string & second) const
{ return !operator>(second); }
bool string::operator>=(const string & second) const
{ return !operator<(second); }
bool string::operator<=(const char *cstring) const
{ return operator<(cstring) || operator==(cstring); }
bool string::operator>=(const char *cstring) const
{ return operator>(cstring) || operator==(cstring); }

View File

@ -1,110 +0,0 @@
// string.h
// implements c++ string object for HOS
// Author: Josh Holtrop
// Date: 06/01/04
// Modified: 05/10/05
#ifndef __HOS_STRING__
#define __HOS_STRING__ __HOS_STRING__
class string
{
private:
/* myChars is a pointer to a character array
* It will always be a valid pointer, not null.
* The constructor is responsible for initializing
* it to point to a 1-char array with myChars[0] == 0 */
char * myChars;
/* myLength holds how many characters are in the
* string, not including the trailing null value
* (ASCII 0 character) */
unsigned int myLength;
public:
/* Basic constructors */
string();
~string();
/* Copy constructor */
string(const string & orig);
/* Construct strings from c-style strings:
* Allows declarations like string s = "data"; */
string(const char *cstring);
/* Assignment operators */
string & operator=(const string & orig);
string & operator=(const char *cstring);
/* Boolean comparison operators */
bool operator==(const string & second) const;
bool operator==(const char *cstring) const;
bool operator!=(const string & second) const;
bool operator!=(const char *cstring) const;
bool operator<(const string & second) const;
bool operator>(const string & second) const;
bool operator<(const char *cstring) const;
bool operator>(const char *cstring) const;
bool operator<=(const string & second) const;
bool operator>=(const string & second) const;
bool operator<=(const char *cstring) const;
bool operator>=(const char *cstring) const;
/* Construct strings made up of combinations of other
* strings, c-style strings, and characters */
string(const string & str1, const string & str2);
string(const string & str1, const char *cstring);
string(const char *cstring, const string & str);
string(const string & str1, char chr);
string(char chr, const string & str1);
/* Append operators */
string & operator+=(const string & str);
string & operator+=(const char *cstring);
string & operator+=(char chr);
string operator+(const string & str);
string operator+(const char *cstring);
string operator+(char chr);
/* Direct character-access operators */
const char & operator[](unsigned int index) const;
char & operator[](unsigned int index);
/* Returns handle to actual character-array for programs
* that need raw data instead of a string object */
char * data() const;
/* Returns the size of the string. This is myLength
* and is the number of characters in the string
* not counting the trailing null (ASCII 0) character */
int size() const;
};
static inline bool operator==(char *cstring, const string & str)
{ return str == cstring; }
static inline bool operator!=(char *cstring, const string & str)
{ return str != cstring; }
static inline bool operator<(const char *cstring, const string & str)
{ return str > cstring; }
static inline bool operator>(const char *cstring, const string & str)
{ return str < cstring; }
static inline bool operator<=(const char *cstring, const string & str)
{ return str >= cstring; }
static inline bool operator>=(const char *cstring, const string & str)
{ return str <= cstring; }
static inline string operator+(const char *cstring, const string & str)
{ return string(cstring, str); }
#endif

View File

@ -1,147 +0,0 @@
// vector.h
// implements c++ vector object for HOS
// Author: Josh Holtrop
// Date: 05/30/05
// Modified: 05/30/05
#ifndef __HOS_VECTOR__
#define __HOS_VECTOR__ __HOS_VECTOR__
#include "hos_defines.h"
template<typename type>
class vector
{
protected:
typedef type * type_ptr_t;
/* Pointers to vector elements */
type **myData;
/* How many elements are present */
unsigned int mySize;
/* How many elements there are pointers for */
unsigned int myAllocated;
/* Causes the vector to double in its allocated size */
void grow()
{
myAllocated <<= 1;
if (myAllocated == 0)
myAllocated = 1;
type **data_new = new type_ptr_t[myAllocated];
for (unsigned int i = 0; i < mySize; i++)
data_new[i] = myData[i];
if (myData)
delete[] myData;
myData = data_new;
}
public:
/* Constructors/Destructor */
vector<type>()
{
myData = NULL;
mySize = 0;
myAllocated = 0;
}
vector<type>(unsigned int size)
{
myData = new type_ptr_t[size];
mySize = 0;
myAllocated = size;
}
vector<type>(const vector<type> & v1)
{
mySize = v1.mySize;
myAllocated = v1.myAllocated;
myData = new type_ptr_t[myAllocated];
for (u32_t i = 0; i < mySize; i++)
myData[i] = new type(*v1.myData[i]);
}
~vector<type>()
{
for (unsigned int i = 0; i < mySize; i++)
delete myData[i];
delete[] myData;
}
/* Assignment operator */
vector<type> & operator=(const vector<type> & v1)
{
mySize = v1.mySize;
myAllocated = v1.myAllocated;
myData = new type_ptr_t[myAllocated];
for (u32_t i = 0; i < mySize; i++)
myData[i] = new type(*v1.myData[i]);
return *this;
}
/* Returns the size of the vector */
unsigned int size() const
{
return mySize;
}
/* Add an element to the end of the vector */
vector<type> & add(type elem)
{
while (mySize >= myAllocated)
grow();
myData[mySize++] = new type(elem);
return *this;
}
/* Remove an element from the vector */
vector<type> & remove(unsigned int index)
{
if (index < mySize)
{
delete myData[index];
for (unsigned int i = index; i < (mySize - 1); i++)
myData[i] = myData[i+1];
mySize--;
}
return *this;
}
/* Insert an element into a position in the vector */
vector<type> & insert(type elem, unsigned int position)
{
if (position <= mySize)
{
if (mySize >= myAllocated)
grow();
for (unsigned int i = mySize; i > position; i--)
myData[i] = myData[i-1];
myData[position] = new type(elem);
mySize++;
}
return *this;
}
/* Direct access operators */
const type & operator[](unsigned int index) const
{
return *myData[index];
}
type & operator[](unsigned int index)
{
return *myData[index];
}
/* Returns pointer to data */
type **data()
{
return myData;
}
};
#endif

View File

@ -1,26 +0,0 @@
OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
.text 0xC0108000 : {
code = .; _code = .; __code = .;
*(.text)
*(.eh_frame*)
}
.gnulinkonce : {
*(.gnu.linkonce*)
. = ALIGN(4096);
}
.data : {
data = .; _data = .; __data = .;
*(.data*)
*(.rodata*)
. = ALIGN(4096);
}
.bss : {
bss = .; _bss = .; __bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}

View File

@ -1,155 +0,0 @@
// mm.c
// Author: Josh Holtrop
// Created: 09/01/03
// Modified: 08/19/04
#include "kernel.h"
#include "mm/mm.h"
#include "multiboot.h"
#include "hos_defines.h"
extern mb_info_t mb_info_block;
extern mb_mmap_t mb_mmap[MAX_MMAP];
extern u32_t mmap_entries;
extern mb_module_t mb_modules[MAX_MODULES];
u32_t mm_totalmem;
u32_t mm_megabytes;
u32_t mm_freepages;
u32_t mm_first_free_byte;
byte page_bitmap[MM_BITMAP_SIZE]; //used to store a bit for each page that is used, 0 if available
//0x20000*(8 bits/byte)=0x100000 pages in 4gb total
//This function initializes the memory manager's linked list, filling it with the
// memory areas returned by bios interrupt 0x8E20
void mm_init()
{
u32_t a;
for (a = 0; a < MM_BITMAP_SIZE; a++) //mark all pages used
{
page_bitmap[a] = 0xFF;
}
for (a = 0; a < mmap_entries; a++) //free BIOS #1 areas
{
if (mb_mmap[a].type == 1) // (1) mem free to OS
{
mm_totalmem += mb_mmap[a].length;
u32_t freethis = mb_mmap[a].base;
u32_t limit = mb_mmap[a].base + mb_mmap[a].length - 4096;
while (freethis <= limit)
{
if (freethis >= PHYS_LOAD) //above physical kernel load point
mm_pfree(freethis);
freethis += 4096;
}
}
}
mm_preserven(PHYS_LOAD, (((u32_t)&_end - (u32_t)&start) >> 12) + 1); //reserve kernel memory
int i;
for (i = 0; i < mb_info_block.mods_count; i++) //reserve module memory
{
mm_preserven(mb_modules[i].mod_start - VIRT_OFFSET, (mb_modules[i].mod_end - mb_modules[i].mod_start + 4095) >> 12);
}
mm_megabytes = (mm_totalmem >> 20) + ((mm_totalmem % 0x100000) ? 1 : 0);
}
// This function frees a certain number of pages starting at the address
// specified in base for a length of pages pages
void mm_pfreen(u32_t base, u32_t pages)
{
//convert pages to max address
for (pages = base + (pages << 12); base < pages; base += 4096)
mm_pfree(base);
}
// This function frees a single page
void mm_pfree(u32_t base)
{
// u32_t pageNumber = base >> 12; // >>12 == /4096
u32_t byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
u32_t bitNumber = (base >> 12) & 0x07; //pageNumber % 8;
page_bitmap[byteNumber] = page_bitmap[byteNumber] & ((0x01 << bitNumber) ^ 0xFF);
mm_freepages++;
if (byteNumber < mm_first_free_byte)
mm_first_free_byte = byteNumber;
}
// This function reserves a certain number of pages starting at the address
// specified in base for a length of pages pages
void mm_preserven(u32_t base, u32_t pages)
{
//convert pages to max address
for (pages = base + (pages << 12); base < pages; base += 4096)
mm_preserve(base);
}
// This function reserves a single page
void mm_preserve(u32_t base)
{
// u32_t pageNumber = base >> 12; // >>12 == /4096
u32_t byteNumber = base >> 15; //pageNumber >> 3; //pageNumber/8
u32_t bitNumber = (base >> 12) & 0x07; //pageNumber % 8;
page_bitmap[byteNumber] = page_bitmap[byteNumber] | (0x01 << bitNumber);
mm_freepages--;
}
// This function allocates a single page, returning its physical address
u32_t mm_palloc()
{
u32_t bite;
for (bite = mm_first_free_byte; bite < MM_BITMAP_SIZE; bite++)
{
if (page_bitmap[bite] != 0xFF) //there is an available page within this 8-page region
{
int bit;
for (bit = 0; bit < 8; bit++)
{
if (!(page_bitmap[bite] & (1 << bit))) //this bite/bit combination is available
{
mm_first_free_byte = bite; //start searching from here next time
mm_freepages--;
page_bitmap[bite] = page_bitmap[bite] | (1 << bit); //set page as used
return ((bite << 15) | (bit << 12));
}
}
}
}
return 0; //no free page
}
// This function reports the number of bytes of free physical memory
u32_t mm_getFreeMem()
{
return mm_freepages << 12;
}
u32_t mm_getFreePages()
{
return mm_freepages;
}
u32_t mm_getTotalMem()
{
return mm_totalmem;
}
u32_t mm_getTotalMegs()
{
return mm_megabytes;
}

View File

@ -1,27 +0,0 @@
// mm.c
// Author: Josh Holtrop
// Created: 09/01/03
// Modified: 03/08/04
#ifndef __HOS_MM__
#define __HOS_MM__ __HOS_MM__
#include "kernel.h"
//The total amount of physical memory available (bytes, 1 bit per page)
#define MM_BITMAP_SIZE 0x20000
void mm_init();
void mm_pfreen(u32_t base, u32_t pages);
void mm_pfree(u32_t base);
void mm_preserven(u32_t base, u32_t pages);
void mm_preserve(u32_t base);
u32_t mm_palloc();
u32_t mm_getFreeMem();
u32_t mm_getFreePages();
u32_t mm_getTotalMem();
u32_t mm_getTotalMegs();
#endif

View File

@ -1,528 +0,0 @@
// vmm.c
// Author: Josh Holtrop
// Date: 09/30/03
// Rewritten from scratch: 12/23/03
// Modified: 09/12/05
#include "hos_defines.h"
#include "kernel.h"
#include "mm/vmm.h"
#include "lang/lang.h"
#include "mm/mm.h"
int vmm_map_range(void *virt_start, void *virt_end, u32_t phys_start);
void *vmm_getFreeChunk(u32_t size);
void vmm_removeHeapEntry(u32_t queue, HeapEntry_t *he);
int vmm_moreCore(u32_t size);
int vmm_coalesceEntry(u32_t queue, HeapEntry_t *newHE);
void vmm_heb_init(HeapEntryBlock_t *heb);
void vmm_addToQueue(u32_t queue, HeapEntry_t *preceeding, HeapEntry_t *he);
int vmm_countHeapEntries(HeapEntry_t *he);
HeapEntry_t *vmm_followChain(HeapEntry_t *he);
HeapEntry_t *vmm_getUnusedEntry();
HeapEntry_t *vmm_stripUnusedEntry();
extern mb_info_t mb_info_block;
extern mb_module_t mb_modules[MAX_MODULES];
extern u32_t mm_freepages;
HeapEntryQueue_t heapEntryQueues[VMM_HE_TYPES]; // linked queues of HeapEntry objects
HeapEntry_t heapEntryHeadNodes[VMM_HE_TYPES]; // head nodes for linked queues
HeapEntry_t heapEntryTailNodes[VMM_HE_TYPES]; // tail nodes for linked queues
HeapEntryBlock_t initialHEB; // block for initial 256 HeapEntry objects
// This is the initialization procedure for the Virtual Memory Manager
// It sets up the heap for dynamic memory allocation and virtual page allocation
void vmm_init()
{
int i;
for (i = 0; i < mb_info_block.mods_count; i++) //page in the kernel modules
vmm_map_range((void*)mb_modules[i].mod_start, (void*)mb_modules[i].mod_end - 1, mb_modules[i].mod_start - VIRT_OFFSET);
for (i = 0; i < VMM_HE_TYPES; i++)
{
heapEntryQueues[i].count = 0;
heapEntryQueues[i].head = &heapEntryHeadNodes[i];
heapEntryHeadNodes[i].next = &heapEntryTailNodes[i];
heapEntryTailNodes[i].prev = &heapEntryHeadNodes[i];
}
vmm_heb_init(&initialHEB);
vmm_addToQueue(VMM_HE_UNUSED, &heapEntryHeadNodes[VMM_HE_UNUSED], &initialHEB.entry[0]);
HeapEntry_t *wilderness = vmm_stripUnusedEntry();
wilderness->base = (void *) HEAP_START;
wilderness->length = HEAP_LENGTH;
vmm_addToQueue(VMM_HE_HOLE, &heapEntryHeadNodes[VMM_HE_HOLE], wilderness);
}
/* Allocate a physical page and map the virtual address to it, return physical address allocated or NULL */
int vmm_map(void *virt)
{
u32_t dum;
return vmm_map_addr(virt, &dum);
}
int vmm_map_addr(void *virt, u32_t *phys_addr)
{
if (mm_freepages < 10)
return -1;
return vmm_map1((u32_t)virt, *phys_addr = mm_palloc());
}
// This function maps a virtual address to a physical address using the page directory / page table
int vmm_map1(u32_t virt, u32_t physical)
{
virt &= 0xFFFFF000;
physical &= 0xFFFFF000;
u32_t pde = virt >> 22;
u32_t pte = (virt & 0x003FF000) >> 12;
u32_t *pageTables = (u32_t *)0xFFFFF000; //this is the location of the page directory
if (!(pageTables[pde] & 0x01)) //the page directory entry is not present, we must allocate a page table
{
u32_t newpagetable;
if (!(newpagetable = mm_palloc()))
return -1; //out of physical memory
pageTables[pde] = newpagetable | 0x03;
invlpg_(0xFFFFF000 + (pde << 2));
invlpg_(virt); //in case it was cached, so we can fill page table safely
memsetd((void*)(0xFFC00000 | (pde << 12)), 0, 1024); //zero out new page table
}
*(u32_t *)(0xFFC00000 | (pde << 12) | (pte << 2)) = physical | 0x03;
invlpg_((0xFFC00000 | (pde << 12) | (pte << 2)));
invlpg_(virt);
return 0;
}
// This function maps a variable number of pages in a row
int vmm_mapn(u32_t virt, u32_t physical, u32_t n)
{
while (n > 0)
{
if (vmm_map1(virt, physical))
return 1; // error mapping page
virt += 4096;
physical += 4096;
n--;
}
return 0;
}
// This function removes the virtual address's entry in the
// page directory / page table
void vmm_unmap1(u32_t virt)
{
*(u32_t *)(0xFFC00000 |
((virt & 0xFFC00000) >> 10) |
((virt & 0x003FF000) >> 10)) = 0;
invlpg_(virt);
}
// This function removes multiple pages' entries
void vmm_unmapn(u32_t virt, u32_t n)
{
while (n > 0)
{
vmm_unmap1(virt);
virt += 4096;
n--;
}
}
// This function maps an entire address range into memory
int vmm_map_range(void *virt_start, void *virt_end, u32_t phys_start)
{
if (virt_end < virt_start)
return -1; // invalid region
while (virt_start < virt_end)
{
if (vmm_map1((u32_t)virt_start, phys_start))
return -2; // out of memory
virt_start += 4096;
phys_start += 4096;
}
return 0;
}
// kernel virtual memory allocator
void *kmalloc(u32_t size)
{
k_enter_critical();
if (size % VMM_MALLOC_GRANULARITY)
size = size + VMM_MALLOC_GRANULARITY -
(size % VMM_MALLOC_GRANULARITY);
/* added 09/12/05 by josh - fixed bug returning size 0 segments
multiple times */
if (size < VMM_MALLOC_GRANULARITY)
size = VMM_MALLOC_GRANULARITY;
void *attempt = vmm_getFreeChunk(size);
if (attempt)
{
k_leave_critical();
return attempt;
}
if (vmm_moreCore(size))
{
k_leave_critical();
return NULL; //we could not get any more heap memory
}
attempt = vmm_getFreeChunk(size);
k_leave_critical();
return attempt;
}
// kernel virtual memory de-allocator
int kfree(void *addr)
{
k_enter_critical();
HeapEntry_t *he = heapEntryQueues[VMM_HE_USED].head->next;
while (he->next)
{
if (he->base == addr)
{
vmm_removeHeapEntry(VMM_HE_USED, he);
if (vmm_coalesceEntry(VMM_HE_FREE, he))
vmm_addToQueue(VMM_HE_FREE, heapEntryQueues[VMM_HE_FREE].head, he);
else
vmm_addToQueue(VMM_HE_UNUSED, heapEntryQueues[VMM_HE_UNUSED].head, he);
break;
}
he = (HeapEntry_t *)he->next;
}
k_leave_critical();
return 0;
}
// This function allocates a virtual page and maps it to a physical page
void *vmm_palloc()
{
u32_t dum;
return vmm_palloc_addr(&dum);
}
void *vmm_palloc_addr(u32_t *phys_addr)
{
k_enter_critical();
HeapEntry_t *he = heapEntryQueues[VMM_HE_HOLE].head->next;
HeapEntry_t *wilderness = he;
while (he->next)
{
if (he->length == 4096)
{
vmm_removeHeapEntry(VMM_HE_HOLE, he);
vmm_addToQueue(VMM_HE_USED, &heapEntryHeadNodes[VMM_HE_USED], he);
if (vmm_map_addr(he->base, phys_addr))
he->base = NULL;
k_leave_critical();
return he->base;
}
if (he->length > wilderness->length)
wilderness = he;
he = (HeapEntry_t *)he->next;
}
if (wilderness->length < 0x00010000) //leave 16 pages free
{
k_leave_critical();
return NULL;
}
wilderness->length -= 4096; //strip 4k from the top
he = vmm_getUnusedEntry();
he->base = wilderness->base + wilderness->length;
he->length = 4096;
vmm_addToQueue(VMM_HE_USED, &heapEntryHeadNodes[VMM_HE_USED], he);
if (vmm_map_addr(he->base, phys_addr))
he->base = NULL;
k_leave_critical();
return he->base;
}
// This function frees a previously-allocated virtual page
int vmm_pfree(void *addr)
{
u32_t pbase = *(u32_t *)(0xFFC00000 |
(((u32_t)addr & 0xFFC00000) >> 10) |
(((u32_t)addr & 0x003FF000) >> 10));
if (vmm_unmapp(addr))
return -1;
mm_pfree(pbase);
return 0;
}
int vmm_unmapp(void *addr)
{
if (!addr)
return -2;
k_enter_critical();
HeapEntry_t *he = heapEntryQueues[VMM_HE_USED].head->next;
while (he->next)
{
if (he->base == addr) //found the page to free
{
vmm_removeHeapEntry(VMM_HE_USED, he);
vmm_unmap1((u32_t)he->base);
vmm_addToQueue(VMM_HE_HOLE, &heapEntryHeadNodes[VMM_HE_HOLE], he);
k_leave_critical();
return 0;
}
he = he->next;
}
k_leave_critical();
return -1; // page not found
}
// This function allocates and zeros memory for the given number of objects,
// given the size of each object
void *kcalloc(u32_t number, u32_t size)
{
void *mem = kmalloc(number * size);
if (!mem)
return NULL; //could not get memory
memset(mem, 0, number * size);
return mem;
}
// This function re-allocates memory already allocated, preserving the old contents
// (as long as newSize is greater than oldSize)
void *krealloc(void *orig, unsigned int newSize)
{
void *newMem;
if ((newMem = kmalloc(newSize)))
{
HeapEntry_t *he = heapEntryQueues[VMM_HE_USED].head->next;
while (he->next)
{
if (he->base == orig)
{
memcpy(newMem, orig, (he->length < newSize ? he->length : newSize));
kfree(orig);
return newMem;
}
he = (HeapEntry_t *)he->next;
}
kfree(newMem);
return NULL; // base address not found
}
else
return NULL; // could not get mem for new chunk
}
// This function returns the base address of a free chunk of virtual memory - called from kmalloc()
void *vmm_getFreeChunk(u32_t size)
{
HeapEntry_t *he = heapEntryQueues[VMM_HE_FREE].head->next;
HeapEntry_t *good = NULL;
while (he->next) // he is not the tail node
{
if (he->length == size)
{
vmm_removeHeapEntry(VMM_HE_FREE, he);
vmm_addToQueue(VMM_HE_USED, heapEntryQueues[VMM_HE_USED].head, he);
return he->base;
}
if (good)
{
if ((he->length > size) && (he->length < good->length))
good = he;
}
else
{
if (he->length > size)
good = he;
}
he = (HeapEntry_t *)he->next;
}
if (!good)
return NULL;
HeapEntry_t *newHE = vmm_getUnusedEntry();
newHE->base = good->base;
newHE->length = size;
newHE->next = NULL;
newHE->prev = NULL;
good->base += size;
good->length -= size;
vmm_addToQueue(VMM_HE_USED, heapEntryQueues[VMM_HE_USED].head, newHE);
return newHE->base;
}
// This function retrieves more core memory for the virtual memory allocator to allocate
int vmm_moreCore(u32_t size)
{
int pages = (size >> 12) + 2;
size = pages << 12;
if ((mm_freepages - 5) < pages)
return -1; // out of physical memory
HeapEntry_t *he = heapEntryQueues[VMM_HE_HOLE].head->next;
HeapEntry_t *wilderness = he;
while (he->next)
{
if (he->length > wilderness->length)
wilderness = he;
he = (HeapEntry_t *)he->next;
}
if (wilderness->length <= size)
return -2; // out of virtual memory
int i;
void *virt = wilderness->base;
for (i = 0; i < pages; i++)
{
vmm_map(virt);
virt += 4096;
}
HeapEntry_t *newHE = vmm_getUnusedEntry();
newHE->base = wilderness->base;
newHE->length = size;
newHE->next = 0;
newHE->prev = 0;
wilderness->base += size;
wilderness->length -= size;
if (vmm_coalesceEntry(VMM_HE_FREE, newHE)) // returns 0 on success (coalesced into previous entry)
vmm_addToQueue(VMM_HE_FREE, heapEntryQueues[VMM_HE_FREE].head, newHE);
else
vmm_addToQueue(VMM_HE_UNUSED, heapEntryQueues[VMM_HE_UNUSED].head, newHE);
return 0;
}
// This function coalesces to heap entries into one
int vmm_coalesceEntry(u32_t queue, HeapEntry_t *newHE)
{
HeapEntry_t *existing = heapEntryQueues[queue].head->next;
while (existing->next)
{
if ((existing->base + existing->length) == newHE->base)
{
existing->length += newHE->length;
return 0;
}
else if ((newHE->base + newHE->length) == existing->base)
{
existing->base = newHE->base;
existing->length += newHE->length;
return 0;
}
existing = (HeapEntry_t *)existing->next;
}
return -1; // an entry to coalesce with was not found
}
// This function removes a heap entry from a queue
void vmm_removeHeapEntry(u32_t queue, HeapEntry_t *he)
{
((HeapEntry_t *)he->prev)->next = he->next;
((HeapEntry_t *)he->next)->prev = he->prev;
heapEntryQueues[queue].count--;
he->next = NULL;
he->prev = NULL;
}
// This function initialzes a Heap Entry Block to entries linked together
void vmm_heb_init(HeapEntryBlock_t *heb)
{
int a;
for (a = 0; a < 255; a++)
{
heb->entry[a].next = &heb->entry[a+1];
heb->entry[a+1].prev = &heb->entry[a];
}
heb->entry[0].prev = NULL;
heb->entry[255].next = NULL;
}
// This function adds a HeapEntry structure to the queue following 'preceeding' the queue
// fails if add to tail (add one element before tail node)
void vmm_addToQueue(u32_t queue, HeapEntry_t *preceeding, HeapEntry_t *he)
{
heapEntryQueues[queue].count += vmm_countHeapEntries(he);
HeapEntry_t *last = vmm_followChain(he);
last->next = preceeding->next;
he->prev = preceeding;
((HeapEntry_t *)last->next)->prev = last;
preceeding->next = he;
}
// This function returns how many HeapEntry objects are in a queue starting/including from the object given
int vmm_countHeapEntries(HeapEntry_t *he)
{
int count = 0;
while (he)
{
count++;
he = (HeapEntry_t *)he->next;
}
return count;
}
// This function follows a chain of HeapEntry objects and returns a pointer to the last one
HeapEntry_t *vmm_followChain(HeapEntry_t *he)
{
while (he->next)
he = (HeapEntry_t *)he->next;
return he;
}
// This function breaks an unused chunk from its queue and returns a pointer to it
// 09/10/05 nasty bug fixed by josh, wasn't adding unused entries when we ran out of them
HeapEntry_t *vmm_getUnusedEntry()
{
if (heapEntryQueues[VMM_HE_UNUSED].count < 5)
{
HeapEntry_t *he = heapEntryQueues[VMM_HE_HOLE].head->next;
HeapEntry_t *wilderness = he;
while (he)
{
if ((he->length) > (wilderness->length))
wilderness = he;
he = (HeapEntry_t *)he->next;
}
if (wilderness->length < 10000)
{
k_check(-1, "Kernel panic: out of virtual memory\n");
}
wilderness->length -= 4096; //strip 4k from the top
HeapEntryBlock_t *newHEB = wilderness->base + wilderness->length;
vmm_map(newHEB);
vmm_heb_init(newHEB);
vmm_addToQueue(VMM_HE_UNUSED, heapEntryTailNodes[VMM_HE_UNUSED].prev, &newHEB->entry[0]);
}
return vmm_stripUnusedEntry();
}
// Return pointer to an unused HeapEntry object, ASSUMES THERE IS ONE PRESENT IN QUEUE
HeapEntry_t *vmm_stripUnusedEntry()
{
HeapEntry_t *he = heapEntryQueues[VMM_HE_UNUSED].head->next;
heapEntryQueues[VMM_HE_UNUSED].head->next = he->next;
if (! he->next)
k_check(1, "kernel panic: he->next is NULL\n");
((HeapEntry_t *)he->next)->prev = he->prev;
heapEntryQueues[VMM_HE_UNUSED].count--;
he->next = 0;
he->prev = 0;
return he;
}

View File

@ -1,58 +0,0 @@
// vmm.h
// Author: Josh Holtrop
// Date: 09/30/03
// Rewritten from scratch: 12/23/03, 07/13/04
// Modified: 08/28/04
#ifndef __HOS_VMM__
#define __HOS_VMM__ __HOS_VMM__
#include "hos_defines.h"
#include "multiboot.h"
#define VMM_HE_TYPES 4 //4 types of heap entries
#define VMM_HE_UNUSED 0 //available entry
#define VMM_HE_FREE 1 //free section of memory
#define VMM_HE_USED 2 //used section of memory
#define VMM_HE_HOLE 3 //a "hole" (unmapped/wilderness) section of virtual memory
#define VMM_MALLOC_GRANULARITY 4 //a power of 2, granularity for all memory requests
#define VMM_MALLOC_GRAN_MASK VMM_MALLOC_GRANULARITY-1 //mask for determining how much of a request is past granularity
typedef struct {
void *base; //virtual base address
u32_t length; //size in bytes
void *next; //link to next HeapEntry
void *prev; //link to previous HeapEntry
} __attribute__((packed)) HeapEntry_t;
typedef struct {
HeapEntry_t entry[256]; //256 HeapEntry objects = 4kb (1 page)
} __attribute__((packed)) HeapEntryBlock_t;
typedef struct {
int count;
HeapEntry_t *head;
} HeapEntryQueue_t;
void vmm_init();
void *kmalloc(u32_t size);
int kfree(void *addr);
int vmm_unmapp(void *addr);
void *vmm_palloc();
void *vmm_palloc_addr(u32_t *phys_addr);
int vmm_pfree(void *addr);
void *kcalloc(unsigned int number, unsigned int size);
int vmm_map(void *virt);
int vmm_map_addr(void *virt, u32_t *phys_addr);
int vmm_map1(unsigned int virt, unsigned int physical);
int vmm_mapn(unsigned int virt, unsigned int physical, unsigned int n);
void vmm_unmap1(unsigned int virt);
void vmm_unmapn(unsigned int virt, unsigned int n);
#endif

View File

@ -1,16 +0,0 @@
#ifndef __HOS_MODULE_H__
#define __HOS_MODULE_H__ __HOS_MODULE_H__
#define MOD_INITRD 0
#define MOD_REAL_MODE 1
typedef struct {
unsigned int mod_magic; // "HOSM" = dword value 0x4D534F48
unsigned int mod_type; // module type
void (*init) (); // address of void initialization function
unsigned int reserved;
} hos_module_header_t;
#endif

View File

@ -1,145 +0,0 @@
#ifndef __HOS_MULTIBOOT_H__
#define __HOS_MULTIBOOT_H__ __HOS_MULTIBOOT_H__
#include "hos_defines.h"
/* The magic number for the Multiboot header. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
#define MB_HEADER_ALIGN_MODULES 0x01
#define MB_HEADER_MEM_INFO 0x02
#define MB_HEADER_VIDEO_INFO 0x04
#define MB_HEADER_KLUDGE_OFFSETS 0x10000
/* The magic number passed by a Multiboot-compliant boot loader. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#define MB_BOOTLOADER_MEM_INFO 0x01
#define MB_BOOTLOADER_BOOT_DEVICE 0x02
#define MB_BOOTLOADER_COMMAND_LINE 0x04
#define MB_BOOTLOADER_MODS 0x08
#define MB_BOOTLOADER_AOUT 0x10
#define MB_BOOTLOADER_ELF 0x20
#define MB_BOOTLOADER_MMAP 0x40
#define MB_BOOTLOADER_DRIVES 0x80
#define MB_BOOTLOADER_CONFIG 0x0100
#define MB_BOOTLOADER_APM 0x0200
#define MB_BOOTLOADER_GRAPHICS 0x0400
#define MB_DRIVE_MODE_CHS 0
#define MB_DRIVE_MODE_LBA 1
/* The Multiboot header. */
typedef struct
{
unsigned int magic;
unsigned int flags;
unsigned int checksum;
unsigned int header_addr;
unsigned int load_addr;
unsigned int load_end_addr;
unsigned int bss_end_addr;
unsigned int entry_addr;
} mb_header_t;
/* The symbol table for a.out. */
typedef struct
{
unsigned int tabsize;
unsigned int strsize;
unsigned int addr;
unsigned int reserved;
} mb_aout_symbol_table_t;
/* The section header table for ELF. */
typedef struct
{
unsigned int num;
unsigned int size;
unsigned int addr;
unsigned int shndx;
} mb_elf_section_header_table_t;
/* The Multiboot information. */
typedef struct
{
unsigned int flags;
unsigned int mem_lower; // present if flags[0] is set
unsigned int mem_upper;
unsigned int boot_device; // 1
unsigned int cmdline; // 2
unsigned int mods_count; // 3
unsigned int mods_addr;
union
{
mb_aout_symbol_table_t aout_sym; // 4
mb_elf_section_header_table_t elf_sec; // 5
};
unsigned int mmap_length; // 6
unsigned int mmap_addr;
unsigned int drives_length; // 7
unsigned int drives_addr;
unsigned int config_table; // 8
unsigned int bootloader_name; // 9
unsigned int apm_table; // 10
unsigned int vbe_control_info; // 11
unsigned int vbe_mode_info;
unsigned short vbe_mode;
unsigned short vbe_interface_seg;
unsigned short vbe_interface_off;
unsigned short vbe_interface_len;
} mb_info_t;
/* The module structure. */
typedef struct
{
unsigned int mod_start;
unsigned int mod_end;
unsigned int string;
unsigned int reserved;
} mb_module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low, not size. */
typedef struct
{
unsigned int size; //offset -4
// unsigned int base_addr_low; //offset 0
// unsigned int base_addr_high;
// unsigned int length_low;
// unsigned int length_high;
u64_t base;
u64_t length;
unsigned int type;
} mb_mmap_t;
/* The drive structure */
typedef struct
{
unsigned int size;
unsigned char drive_number;
unsigned char drive_mode;
unsigned char drive_cylinders;
unsigned char drive_heads;
unsigned char drive_sectors;
unsigned short drive_ports[1];
} mb_drive_t;
/* APM table structure */
typedef struct
{
unsigned short version;
unsigned short cseg;
unsigned int offset;
unsigned short cseg_16;
unsigned short dseg;
unsigned short flags;
unsigned short cseg_len;
unsigned short cseg_16_len;
unsigned short dseg_len;
} mb_apm_t;
#endif

View File

@ -1,117 +0,0 @@
// hash.cpp
// Author: Josh Holtrop
// Date: 08/28/05
// Modified: 08/28/05
// Implements a basic hash table (u32_t -> void*)
#include "hos_defines.h"
#include "hash.h"
#include "lang/vector.h"
extern "C"{
#include "display/kout.h"
#include "mm/vmm.h"
}
/* Hash Primes come from
* http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
*/
const u32_t hash_primes[] =
{53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};
hash::hash()
{
mySizeIndex = 0;
mySize = 0;
for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++)
myTable.add(vector<hash_entry_t>());
}
int hash::add(u32_t key, void *val)
{
u32_t hashed = hash_key(key);
for (u32_t i = 0; i < myTable[hashed].size(); i++)
if ( myTable[hashed][i].key == key )
return -1; // key exists already
hash_entry_t he = {key, val};
myTable[hashed].add(he);
mySize++;
if ( mySize > (hash_primes[mySizeIndex] << 1) ) // re-hash
{
vector< vector<hash_entry_t> > oldTable = myTable;
mySizeIndex++;
myTable = vector< vector<hash_entry_t> >();
for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++)
myTable.add(vector<hash_entry_t>());
mySize = 0;
for (u32_t i = 0; i < hash_primes[mySizeIndex - 1]; i++)
{
for (u32_t j = 0; j < oldTable[i].size(); j++)
{
add( oldTable[i][j].key,
oldTable[i][j].data );
}
}
}
return 0;
}
void *hash::get(u32_t key)
{
u32_t hashed = hash_key(key);
for (u32_t i = 0; i < myTable[hashed].size(); i++)
if ( myTable[hashed][i].key == key )
return myTable[hashed][i].data;
return NULL;
}
int hash::remove(u32_t key)
{
u32_t hashed = hash_key(key);
for (u32_t i = 0; i < myTable[hashed].size(); i++)
if ( myTable[hashed][i].key == key )
{
myTable[hashed].remove(i); // remove key
mySize--;
return 0;
}
return -1;
}
int hash::exists(u32_t key)
{
u32_t hashed = hash_key(key);
for (u32_t i = 0; i < myTable[hashed].size(); i++)
if ( myTable[hashed][i].key == key )
return 1; // key exists
return 0;
}
u32_t hash::hash_key(u32_t key)
{
return ((key * 11) + mySizeIndex) % hash_primes[mySizeIndex];
}
u32_t hash::size()
{
return mySize;
}
void hash::dump()
{
kprintf("hash table @ 0x%x : {\n", &myTable);
for (u32_t i = 0; i < hash_primes[mySizeIndex]; i++)
{
kprintf("\t%d @ 0x%x (", i, &myTable[i]);
for (u32_t j = 0; j < myTable[i].size(); j++)
kprintf("%s%d -> %d @ 0x%x", (j ? ", " : ""),
myTable[i][j].key,
myTable[i][j].data,
&myTable[i][j]);
kprintf(")\n");
}
kprintf("}\n");
}

View File

@ -1,58 +0,0 @@
// hash.h
// Author: Josh Holtrop
// Date: 08/28/05
// Modified: 08/28/05
// Implements a basic hash table (u32_t -> void*)
#ifndef __HOS_HASH_H__
#define __HOS_HASH_H__ __HOS_HASH_H__
#include "hos_defines.h"
#include "lang/vector.h"
typedef struct
{
u32_t key;
void *data;
} hash_entry_t;
class hash
{
private:
/* index into hash_primes[] */
u32_t mySizeIndex;
/* How many values in the hash table */
u32_t mySize;
/* array of hash entries */
vector< vector<hash_entry_t> > myTable;
/* hash the key to a table index */
u32_t hash_key(u32_t key);
public:
/* Constructor */
hash();
/* Add a value to the hash table */
int add(u32_t key, void *val);
/* Retrieve a value from the hash table */
void *get(u32_t key);
/* Remove a value from the hash table */
int remove(u32_t key);
/* Check if the given key exists in the hash table */
int exists(u32_t key);
/* Dump a hash */
void dump();
/* How many values are in the hash table */
u32_t size();
};
#endif

View File

@ -1,214 +0,0 @@
// proc.c
// Author: Josh Holtrop
// Date; 08/18/05
// Modified: 08/18/05
extern "C" {
#include "hos_defines.h"
#include "mm/mm.h"
#include "mm/vmm.h"
#include "lang/lang.h"
#include "kernel.h"
#include "functions.h" //halt()
#include "display/kout.h"
extern u32_t mm_freepages;
}
#include "proc.h"
#include "proc/hash.h"
extern "C" {
u32_t cur_task = 0; /* PID of currently executing process */
u32_t n_processes = 0; /* total number of processes */
tss_t tss0;
u32_t pid_base = 1024;
u32_t pid_index = 0; /* index of running process in 'pids' vector */
}
hash *processes;
vector<u32_t> *pids;
int proc_init()
{
/* initialize tss0 */
memset(&tss0, 0, sizeof(tss_t));
tss0.ss0 = SEG_KERNEL_DATA;
tss0.esp0 = VIRT_STACK_TOP;
processes = new hash();
process_t *proc = (process_t *)New(process_t);
proc->p_page_dir = read_cr3();
proc->page_dir = (u32_t *)0xFFFFF000;
processes->add(0, proc);
pids = new vector<u32_t>();
pids->add(0);
return 0;
}
process_t *proc_get_struct(u32_t pid)
{
return (process_t *) processes->get(pid);
}
void proc_sched(int_stack_t *int_stack)
{
u32_t new_pid_index = (pid_index + 1) % pids->size();
switch_task(int_stack, (*pids)[new_pid_index]);
pid_index = new_pid_index;
}
u32_t get_pid()
{
u32_t potential = pid_base;
while (processes->exists(potential))
{
potential++;
if (potential == 0)
potential = PROC_MIN_USER_PID;
}
pid_base = potential + 1;
if (pid_base == 0)
pid_base = PROC_MIN_USER_PID;
return potential;
}
void switch_task(int_stack_t *int_stack, u32_t new_task)
{
memcpy(&((process_t *)processes->get(cur_task))->int_stack, int_stack,
sizeof(int_stack_t));
cur_task = new_task;
memcpy(int_stack, &((process_t *)processes->get(cur_task))->int_stack,
sizeof(int_stack_t));
write_cr3( ((process_t *)processes->get(cur_task))->p_page_dir );
}
u32_t create_task(void *base, u32_t image_size, u32_t bss_size, void *entry)
{
u32_t pid = get_pid();
processes->add(pid, create_process(base, image_size, bss_size, entry));
pids->add(pid);
return pid;
}
/* Create process_t struct for a new process
* image_size should be a multiple of 4096
*/
process_t *create_process(void *base, u32_t image_size, u32_t bss_size, void *entry)
{
if (mm_freepages < ((image_size + bss_size) >> 12) + 25)
return 0;
process_t *process = (process_t *) New(process_t); /* Allocate process_t struct */
create_address_space(process);
create_process_stack(process, entry);
int i;
u32_t *ptr32 = process->v_page_dir = (u32_t *) vmm_palloc();
for (i = 0; i < 1024; i++)
*ptr32++ = 0;
u32_t code_data_pages = (image_size + 4095) >> 12;
u32_t bss_pages = (bss_size + 4095) >> 12;
/* Load program at address 0 */
copy_into_address_space(0, (char *) base, code_data_pages, process);
zero_address_space(code_data_pages << 12, bss_pages, process);
ptr32 = process->v_page_dir;
for (i = 0; i < 1024; i++)
if (*ptr32)
vmm_unmapp((void *)*ptr32);
vmm_unmapp(process->v_page_dir);
process->v_page_dir = 0;
process->size = image_size + bss_size;
return process;
}
void create_address_space(process_t *p)
{
/* Allocate a new page directory */
p->page_dir = (u32_t *) vmm_palloc_addr(&p->p_page_dir);
int i;
u32_t *ptr32 = p->page_dir;
for (i = 0; i < 768; i++) /* zero 3 gigs */
*ptr32++ = 0;
memcpyd(ptr32, (void *)0xFFFFFC00, 256); /* 1 gig kernel mem */
}
void create_process_stack(process_t *p, void *entry)
{
u32_t p_stack_table, p_stack;
u32_t *v_stack_table = (u32_t *) vmm_palloc_addr(&p_stack_table);
u32_t *v_stack = (u32_t *) vmm_palloc_addr(&p_stack);
int i;
u32_t *ptr32 = v_stack_table;
for (i = 0; i < 1023; i++)
*ptr32++ = 0;
v_stack_table[1023] = p_stack | 0x7; /* user permissions */
p->page_dir[511] = p_stack_table | 0x7; /* stack at 2GB */
vmm_unmapp(v_stack_table);
vmm_unmapp(v_stack);
p->int_stack.ds = SEG_USER_DATA | 0x3;
p->int_stack.es = SEG_USER_DATA | 0x3;
p->int_stack.fs = SEG_USER_DATA | 0x3;
p->int_stack.gs = SEG_USER_DATA | 0x3;
p->int_stack.ss = SEG_USER_DATA | 0x3;
p->int_stack.esp = 0x80000000; /* esp at 2GB */
p->int_stack.eflags = 0x0202;
p->int_stack.cs = SEG_USER_CODE | 0x3;
p->int_stack.eip = (u32_t)entry;
}
/* Copy pages into new address space (v_page_dir must be set up) */
void copy_into_address_space(u32_t dest_addr,
char *src_addr,
u32_t pages,
process_t *p)
{
u32_t pde, pte;
void *page;
while (pages)
{
pde = dest_addr >> 22;
pte = (dest_addr >> 12) & 0x3FF;
u32_t p_page_addr;
if (!p->v_page_dir[pde])
{
/* Time for a new page table & page directory entry! */
p->v_page_dir[pde] = (u32_t)vmm_palloc_addr(&p_page_addr);
p->page_dir[pde] = p_page_addr | 0x7;
}
page = vmm_palloc_addr(&p_page_addr);
((u32_t *)(p->v_page_dir[pde]))[pte] = p_page_addr | 0x7;
memcpyd(page, src_addr, 1024);
vmm_unmapp(page);
dest_addr += 4096;
src_addr += 4096;
pages--;
}
}
/* Zeros pages into new address space (v_page_dir must be set up) */
void zero_address_space(u32_t dest_addr, u32_t pages, process_t *p)
{
u32_t pde, pte;
void *page;
while (pages)
{
pde = dest_addr >> 22;
pte = (dest_addr >> 12) & 0x3FF;
u32_t p_page_addr;
if (!p->v_page_dir[pde])
{
/* Time for a new page table & page directory entry! */
p->v_page_dir[pde] = (u32_t)vmm_palloc_addr(&p_page_addr);
p->page_dir[pde] = p_page_addr | 0x7;
vmm_unmapp((void *)p->v_page_dir[pde]);
}
page = vmm_palloc_addr(&p_page_addr);
((u32_t *)(p->v_page_dir[pde]))[pte] = p_page_addr | 0x7;
memsetd(page, 0, 1024);
vmm_unmapp(page);
dest_addr += 4096;
pages--;
}
}

View File

@ -1,91 +0,0 @@
// proc.h
// Author: Josh Holtrop
// Date; 08/18/05
// Modified: 08/18/05
#ifndef __HOS_PROC_H__
#define __HOS_PROC_H__ __HOS_PROC_H__
#ifdef _HOS_CPP_
extern "C" {
#endif
#include "hos_defines.h"
#include "kernel.h"
#define PROC_MIN_USER_PID 1024
typedef struct
{
u32_t *page_dir; /* Page directory with physical PT addys */
u32_t *v_page_dir; /* Virtual page table addresses for init */
u32_t p_page_dir; /* Physical address of page directory */
u32_t size; /* Process size, bytes from 0 through bss */
u32_t uid; /* Process owner */
int_stack_t int_stack;
} process_t;
typedef struct
{
u16_t backlink;
u16_t reserved0;
u32_t esp0;
u16_t ss0;
u16_t _ss0;
u32_t esp1;
u16_t ss1;
u16_t _ss1;
u32_t esp2;
u16_t ss2;
u16_t _ss2;
u32_t pdbr;
u32_t eip;
u32_t eflags;
u32_t eax;
u32_t ecx;
u32_t edx;
u32_t ebx;
u32_t esp;
u32_t ebp;
u32_t esi;
u32_t edi;
u16_t es;
u16_t _es;
u16_t cs;
u16_t _cs;
u16_t ss;
u16_t _ss;
u16_t ds;
u16_t _ds;
u16_t fs;
u16_t _fs;
u16_t gs;
u16_t _gs;
u16_t ldt;
u16_t _ldt;
u16_t trap;
u16_t iomap;
} __attribute__((packed)) tss_t;
int proc_init();
process_t *proc_get_struct(u32_t pid);
void proc_sched(int_stack_t *int_stack);
u32_t get_pid();
void switch_task(int_stack_t *int_stack, u32_t new_task);
u32_t create_task(void *base, u32_t image_size, u32_t bss_size, void *entry);
process_t *create_process(void *base, u32_t image_size, u32_t bss_size, void *entry);
void create_address_space(process_t *p);
void create_process_stack(process_t *p, void *entry);
void copy_into_address_space(u32_t dest_addr,
char *src_addr,
u32_t pages,
process_t *p);
void zero_address_space(u32_t dest_addr, u32_t pages, process_t *p);
#ifdef _HOS_CPP_
}
#endif
#endif

View File

@ -1,42 +0,0 @@
// cmos.c
// Author: Josh Holtrop
// Created: 02/26/04
// Implements various CMOS function calls
#include "hos_defines.h"
#include "sys/cmos.h"
#include "sys/io.h"
//Returns the cmos type of floppy disk drive 0 (0 = not present)
unsigned char cmos_getfd0()
{
outportb(0x70, 0x10);
return (inportb(0x71) >> 4);
}
//Returns the cmos type of floppy disk drive 1 (0 = not present)
unsigned char cmos_getfd1()
{
outportb(0x70, 0x10);
return (inportb(0x71) & 0x0F);
}
//Returns the cmos type of hard disk drive 0 (0 = not present)
unsigned char cmos_gethd0()
{
outportb(0x70, 0x12);
return (inportb(0x71) >> 4);
}
//Returns the cmos type of hard disk drive 1 (0 = not present)
unsigned char cmos_gethd1()
{
outportb(0x70, 0x12);
return (inportb(0x71) & 0x0F);
}

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