diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-10-17 10:55:43 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-10-17 10:57:23 +0200 |
commit | 9171521752b0b382f1f70453b4f24915999144b9 (patch) | |
tree | a3bb1e3533e591c4693ce98b245870e4da5daede /Kernel | |
parent | aec8ab0a606a1ccb3eaf5816ef85e3951c2d5227 (diff) | |
download | serenity-9171521752b0b382f1f70453b4f24915999144b9.zip |
Integrate ext2 from VFS into Kernel.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/.bochsrc | 54 | ||||
-rwxr-xr-x | Kernel/Boot/boot.asm | 134 | ||||
-rw-r--r-- | Kernel/Ext2FileSystem.h | 74 | ||||
-rw-r--r-- | Kernel/InlineLinkedList.h (renamed from Kernel/DoublyLinkedList.h) | 34 | ||||
-rw-r--r-- | Kernel/Makefile | 13 | ||||
-rw-r--r-- | Kernel/OwnPtr.h | 78 | ||||
-rw-r--r-- | Kernel/StdLib.cpp | 9 | ||||
-rw-r--r-- | Kernel/StdLib.h | 13 | ||||
-rw-r--r-- | Kernel/String.cpp | 86 | ||||
-rw-r--r-- | Kernel/String.h | 31 | ||||
-rw-r--r-- | Kernel/Task.cpp | 8 | ||||
-rw-r--r-- | Kernel/Task.h | 10 | ||||
-rw-r--r-- | Kernel/Vector.h | 90 | ||||
-rw-r--r-- | Kernel/fs.cpp | 451 | ||||
-rw-r--r-- | Kernel/init.cpp | 6 | ||||
-rwxr-xr-x | Kernel/run | 4 |
16 files changed, 222 insertions, 873 deletions
diff --git a/Kernel/.bochsrc b/Kernel/.bochsrc new file mode 100644 index 0000000000..16e4fb79d7 --- /dev/null +++ b/Kernel/.bochsrc @@ -0,0 +1,54 @@ +# configuration file generated by Bochs +plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true +config_interface: textconfig +display_library: x +memory: host=32, guest=32 +romimage: file="/usr/local/share/bochs/BIOS-bochs-latest", address=0x00000000, options=none +vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest" +boot: floppy +floppy_bootsig_check: disabled=0 +floppya: type=1_44, 1_44=".floppy-image", status=inserted, write_protected=0 +# no floppyb +ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, path="_fs_contents", mode=flat, cylinders=0, heads=0, spt=0, model="Generic 1234", biosdetect=auto, translation=auto +ata0-slave: type=none +ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata1-master: type=none +ata1-slave: type=none +ata2: enabled=false +ata3: enabled=false +optromimage1: file=none +optromimage2: file=none +optromimage3: file=none +optromimage4: file=none +optramimage1: file=none +optramimage2: file=none +optramimage3: file=none +optramimage4: file=none +pci: enabled=1, chipset=i440fx +vga: extension=vbe, update_freq=5, realtime=1 +cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU " +cpuid: mmx=true, apic=xapic, simd=sse2, sse4a=false, misaligned_sse=false, sep=true +cpuid: movbe=false, adx=false, aes=false, sha=false, xsave=false, xsaveopt=false, smep=false +cpuid: smap=false, mwait=true +print_timestamps: enabled=0 +port_e9_hack: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local, rtc_sync=0 +# no cmosimage +log: - +logprefix: %t%e%d +debug: action=ignore +info: action=report +error: action=report +panic: action=ask +keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none +mouse: type=ps2, enabled=false, toggle=ctrl+mbutton +speaker: enabled=true, mode=system +parport1: enabled=true, file=none +parport2: enabled=false +com1: enabled=true, mode=null +com2: enabled=false +com3: enabled=false +com4: enabled=false diff --git a/Kernel/Boot/boot.asm b/Kernel/Boot/boot.asm index 10f7f49c95..7a7569583e 100755 --- a/Kernel/Boot/boot.asm +++ b/Kernel/Boot/boot.asm @@ -4,42 +4,57 @@ [bits 16] boot: - push cs - pop ds - xor bx, bx - mov ah, 0x0e - mov si, message + cli + mov ax, 0x8000 + mov ss, ax + mov sp, 0xffff + + push cs + pop ds + xor bx, bx + mov ah, 0x0e + mov si, message lodsb .lewp: - int 0x10 + int 0x10 lodsb - cmp al, 0 - jne .lewp + cmp al, 0 + jne .lewp - mov bx, 0x1000 - mov es, bx - xor bx, bx ; Load kernel @ 0x10000 + mov bx, 0x1000 + mov es, bx + xor bx, bx ; Load kernel @ 0x10000 + + mov cx, word [cur_lba] +.sector_loop: + call convert_lba_to_chs mov ah, 0x02 ; cmd 0x02 - Read Disk Sectors - mov al, 72 ; 72 sectors (max allowed by bochs BIOS) - mov ch, 0 ; track 0 - mov cl, 10 ; sector 10 - mov dh, 0 ; head 0 + mov al, 1 ; 1 sector at a time mov dl, 0 ; drive 0 (fd0) int 0x13 jc fug - mov ah, 0x02 - mov al, 32 - add bx, 0x9000 - mov ch, 2 - mov cl, 10 - mov dh, 0 - mov dl, 0 - int 0x13 + mov ah, 0x0e + mov al, '.' + int 0x10 - jc fug + inc word [cur_lba] + mov cx, word [cur_lba] + cmp cx, 300 + jz .sector_loop_end + + mov bx, es + add bx, 0x20 + mov es, bx + xor bx, bx + + jmp .sector_loop + +.sector_loop_end: + + call durk lgdt [cs:test_gdt_ptr] @@ -49,6 +64,20 @@ boot: jmp 0x08:pmode +durk: + push cs + pop ds + xor bx, bx + mov ah, 0x0e + mov si, msg_sectors_loaded + lodsb +.lewp: + int 0x10 + lodsb + cmp al, 0 + jne .lewp + ret + pmode: [bits 32] mov ax, 0x10 @@ -60,6 +89,14 @@ pmode: mov ss, ax mov esp, 0x2000 + xor eax, eax + xor ebx, ebx + xor ecx, ecx + xor edx, edx + xor ebp, ebp + xor esi, esi + xor edi, edi + jmp 0x10000 hlt @@ -95,7 +132,56 @@ fug: cli hlt + +; Input: +; +; AX = LBA +; +; Output: +; +; CX and DH = C/H/S address formatted for Int13,2 + +; CL = sector (LBA % sectors_per_track) + 1 +; +; 1.44M floppy stats: +; (sectors_per_track: 18) +; (heads: 2) +; (sectors: 2880) + +convert_lba_to_chs: + mov ax, cx + + ; AX = LBA/spt, DX = LBA%spt + xor dx, dx + div word [sectors_per_track] + + ; CL = sector (LBA % sectors_per_track) + 1 + mov cl, dl + inc cl + + ; CH = track (LBA / sectors_per_track) / heads + mov ch, al + shr ch, 1 + + ; AX = (LBA/spt)/heads, DX = (LBA/spt)%heads + xor dx, dx + div word [heads] + + ; DH = sector (LBA / sectors_per_track) % heads + mov dh, dl + + ret +cur_lba: + dw 9 +sectors_per_track: + dw 18 +heads: + dw 2 + +msg_sectors_loaded: + db "sectors loaded", 0x0d, 0x0a, 0 + message: db "boot!", 0x0d, 0x0a, 0 diff --git a/Kernel/Ext2FileSystem.h b/Kernel/Ext2FileSystem.h deleted file mode 100644 index 9509531d48..0000000000 --- a/Kernel/Ext2FileSystem.h +++ /dev/null @@ -1,74 +0,0 @@ -#pragma once - -#include "ext2fs.h" -#include "OwnPtr.h" -#include "DataBuffer.h" -#include "FileSystem.h" - -static const size_t bytesPerSector = 512; - -class Ext2VirtualNode; - -class Ext2FileSystem { -public: - Ext2FileSystem() { } - ~Ext2FileSystem(); - - void initialize(); - RefPtr<DataBuffer> loadFile(ext2_dir_entry*); - - ext2_inode* findInode(DWORD index); - ext2_inode* findPath(const String& path, DWORD& inodeIndex); - -private: - friend class Ext2VirtualNode; - - void readSuperBlock(); - void readBlockGroup(DWORD); - void readInodeTable(DWORD); - void dumpDirectory(ext2_inode&); - void dumpFile(ext2_inode&); - - template<typename F> void forEachBlockIn(ext2_inode&, F func); - template<typename F> void traverseDirectory(ext2_dir_entry&, DWORD blockCount, F); - template<typename F> void traverseDirectory(ext2_inode&, F); - RefPtr<DataBuffer> readFile(ext2_inode&); - - RefPtr<DataBuffer> readBlocks(DWORD blockIndex, BYTE count); - void readDiskSector(DWORD sectorIndex, BYTE* buffer); - - size_t blockSize() const { return 1024 << m_superBlock->s_log_frag_size; } - size_t sectorsPerBlock() const { return blockSize() / bytesPerSector; } - DWORD blockGroupForInode(DWORD inode) const; - DWORD toInodeTableIndex(DWORD inode) const; - - ext2_super_block& superBlock() { ASSERT(m_superBlock); return *m_superBlock; } - - OwnPtr<ext2_super_block> m_superBlock; - ext2_inode* m_root { nullptr }; // raw pointer into one of the m_inodeTables - - size_t m_blockGroupCount { 0 }; - ext2_group_descriptor* m_groupTable { nullptr }; - ext2_inode** m_inodeTables { nullptr }; -}; - -class Ext2VirtualNode final : public FileSystem::VirtualNode { -public: - static RefPtr<Ext2VirtualNode> create(DWORD index, String&& path, Ext2FileSystem&, DWORD inodeNumber); - - virtual ~Ext2VirtualNode(); - - virtual size_t size() const override { return m_inode.i_size; } - virtual uid_t uid() const override { return m_inode.i_uid; } - virtual gid_t gid() const override { return m_inode.i_gid; } - virtual size_t mode() const override { return m_inode.i_mode; } - - virtual size_t read(BYTE* outbuf, size_t start, size_t maxLength) override; - -private: - Ext2VirtualNode(DWORD index, String&& path, Ext2FileSystem&, ext2_inode&, DWORD inodeNumber); - - Ext2FileSystem& m_fileSystem; - ext2_inode& m_inode; - DWORD m_inodeNumber { 0 }; -}; diff --git a/Kernel/DoublyLinkedList.h b/Kernel/InlineLinkedList.h index 5184e34d29..2c83a710e1 100644 --- a/Kernel/DoublyLinkedList.h +++ b/Kernel/InlineLinkedList.h @@ -3,9 +3,9 @@ #include "Assertions.h" #include "types.h" -template<typename T> class DoublyLinkedListNode { +template<typename T> class InlineLinkedListNode { public: - DoublyLinkedListNode(); + InlineLinkedListNode(); void setPrev(T*); void setNext(T*); @@ -14,35 +14,35 @@ public: T* next() const; }; -template<typename T> inline DoublyLinkedListNode<T>::DoublyLinkedListNode() +template<typename T> inline InlineLinkedListNode<T>::InlineLinkedListNode() { setPrev(0); setNext(0); } -template<typename T> inline void DoublyLinkedListNode<T>::setPrev(T* prev) +template<typename T> inline void InlineLinkedListNode<T>::setPrev(T* prev) { static_cast<T*>(this)->m_prev = prev; } -template<typename T> inline void DoublyLinkedListNode<T>::setNext(T* next) +template<typename T> inline void InlineLinkedListNode<T>::setNext(T* next) { static_cast<T*>(this)->m_next = next; } -template<typename T> inline T* DoublyLinkedListNode<T>::prev() const +template<typename T> inline T* InlineLinkedListNode<T>::prev() const { return static_cast<const T*>(this)->m_prev; } -template<typename T> inline T* DoublyLinkedListNode<T>::next() const +template<typename T> inline T* InlineLinkedListNode<T>::next() const { return static_cast<const T*>(this)->m_next; } -template<typename T> class DoublyLinkedList { +template<typename T> class InlineLinkedList { public: - DoublyLinkedList() { } + InlineLinkedList() { } bool isEmpty() const { return !m_head; } size_t size() const; @@ -56,14 +56,14 @@ public: void prepend(T*); void append(T*); void remove(T*); - void append(DoublyLinkedList<T>&); + void append(InlineLinkedList<T>&); private: T* m_head { nullptr }; T* m_tail { nullptr }; }; -template<typename T> inline size_t DoublyLinkedList<T>::size() const +template<typename T> inline size_t InlineLinkedList<T>::size() const { size_t size = 0; for (T* node = m_head; node; node = node->next()) @@ -71,13 +71,13 @@ template<typename T> inline size_t DoublyLinkedList<T>::size() const return size; } -template<typename T> inline void DoublyLinkedList<T>::clear() +template<typename T> inline void InlineLinkedList<T>::clear() { m_head = 0; m_tail = 0; } -template<typename T> inline void DoublyLinkedList<T>::prepend(T* node) +template<typename T> inline void InlineLinkedList<T>::prepend(T* node) { if (!m_head) { ASSERT(!m_tail); @@ -95,7 +95,7 @@ template<typename T> inline void DoublyLinkedList<T>::prepend(T* node) m_head = node; } -template<typename T> inline void DoublyLinkedList<T>::append(T* node) +template<typename T> inline void InlineLinkedList<T>::append(T* node) { if (!m_tail) { ASSERT(!m_head); @@ -113,7 +113,7 @@ template<typename T> inline void DoublyLinkedList<T>::append(T* node) m_tail = node; } -template<typename T> inline void DoublyLinkedList<T>::remove(T* node) +template<typename T> inline void InlineLinkedList<T>::remove(T* node) { if (node->prev()) { ASSERT(node != m_head); @@ -132,7 +132,7 @@ template<typename T> inline void DoublyLinkedList<T>::remove(T* node) } } -template<typename T> inline T* DoublyLinkedList<T>::removeHead() +template<typename T> inline T* InlineLinkedList<T>::removeHead() { T* node = head(); if (node) @@ -140,7 +140,7 @@ template<typename T> inline T* DoublyLinkedList<T>::removeHead() return node; } -template<typename T> inline void DoublyLinkedList<T>::append(DoublyLinkedList<T>& other) +template<typename T> inline void InlineLinkedList<T>::append(InlineLinkedList<T>& other) { if (!other.head()) return; diff --git a/Kernel/Makefile b/Kernel/Makefile index 93a28f5515..330b658214 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -14,10 +14,8 @@ KERNEL_OBJS = \ PIC.o \ Syscall.o \ DataBuffer.o \ - String.o \ panel.o \ Disk.o \ - fs.o \ Userspace.o \ IDEDiskDevice.o @@ -27,9 +25,16 @@ VFS_OBJS = \ ../VirtualFileSystem/NullDevice.o \ ../VirtualFileSystem/FullDevice.o \ ../VirtualFileSystem/ZeroDevice.o \ - ../VirtualFileSystem/RandomDevice.o + ../VirtualFileSystem/RandomDevice.o \ + ../VirtualFileSystem/FileSystem.o \ + ../VirtualFileSystem/DiskBackedFileSystem.o \ + ../VirtualFileSystem/Ext2FileSystem.o -OBJS = $(KERNEL_OBJS) $(VFS_OBJS) +AK_OBJS = \ + ../AK/String.o \ + ../AK/StringImpl.o + +OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) NASM = nasm KERNEL = kernel diff --git a/Kernel/OwnPtr.h b/Kernel/OwnPtr.h deleted file mode 100644 index 855bafcf01..0000000000 --- a/Kernel/OwnPtr.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include "types.h" - -template<typename T> -class OwnPtr { -public: - OwnPtr() { } - explicit OwnPtr(T* ptr) : m_ptr(ptr) { } - OwnPtr(OwnPtr&& other) : m_ptr(other.leakPtr()) { } - template<typename U> OwnPtr(OwnPtr<U>&& other) : m_ptr(static_cast<T*>(other.leakPtr())) { } - ~OwnPtr() { clear(); } - - OwnPtr& operator=(OwnPtr&& other) - { - if (this != &other) { - delete m_ptr; - m_ptr = other.leakPtr(); - } - return *this; - } - - template<typename U> - OwnPtr& operator=(OwnPtr<U>&& other) - { - if (this != static_cast<void*>(&other)) { - delete m_ptr; - m_ptr = other.leakPtr(); - } - return *this; - } - - OwnPtr& operator=(T* ptr) - { - if (m_ptr != ptr) - delete m_ptr; - m_ptr = ptr; - return *this; - } - - void clear() - { - delete m_ptr; - m_ptr = nullptr; - } - - bool operator!() const { return !m_ptr; } - - typedef T* OwnPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : nullptr; } - - T* leakPtr() - { - T* leakedPtr = m_ptr; - m_ptr = nullptr; - return leakedPtr; - } - - T* ptr() { return m_ptr; } - const T* ptr() const { return m_ptr; } - - T* operator->() { return m_ptr; } - const T* operator->() const { return m_ptr; } - - T& operator*() { return *m_ptr; } - const T& operator*() const { return *m_ptr; } - - operator bool() { return !!m_ptr; } - -private: - T* m_ptr = nullptr; -}; - -template<class T, class... Args> inline OwnPtr<T> -make(Args&&... args) -{ - return OwnPtr<T>(new T(forward<Args>(args)...)); -} diff --git a/Kernel/StdLib.cpp b/Kernel/StdLib.cpp index 50759b4c2d..1ecdc6c9af 100644 --- a/Kernel/StdLib.cpp +++ b/Kernel/StdLib.cpp @@ -49,6 +49,15 @@ char* strdup(const char *str) return s; } +int memcmp(const void* v1, const void* v2, size_t n) +{ + size_t m; + const char* s1 = (const char*)v1; + const char* s2 = (const char*)v2; + for (m = 0; m < n && *s1 == *s2; ++s1, ++s2); + return m == n ? 0 : -1; +} + extern "C" void __cxa_pure_virtual() { ASSERT_NOT_REACHED(); diff --git a/Kernel/StdLib.h b/Kernel/StdLib.h index 177fdde0eb..f507773e55 100644 --- a/Kernel/StdLib.h +++ b/Kernel/StdLib.h @@ -2,9 +2,10 @@ #include "types.h" -void memcpy(void *, const void *, DWORD); -void strcpy(char *, const char *); -int strcmp(char const *, const char *); -DWORD strlen(const char *) PURE; -void *memset(void *, BYTE, DWORD); -char *strdup(const char *); +void memcpy(void*, const void*, DWORD); +void strcpy(char*, const char*); +int strcmp(char const*, const char*); +DWORD strlen(const char*); +void *memset(void*, BYTE, DWORD); +char *strdup(const char*); +int memcmp(const void*, const void*, size_t); diff --git a/Kernel/String.cpp b/Kernel/String.cpp deleted file mode 100644 index e8a199226f..0000000000 --- a/Kernel/String.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "String.h" -#include <AK/StdLib.h> - -String::String() -{ -} - -String::String(const char* characters) - : m_data(DataBuffer::copy((const BYTE*)characters, strlen(characters) + 1)) -{ -} - -String::String(const char* characters, size_t length) - : m_data(DataBuffer::createUninitialized(length + 1)) -{ - memcpy(m_data->data(), characters, length); - m_data->data()[length] = '\0'; -} - -String::String(String&& other) - : m_data(move(other.m_data)) -{ -} - -String::String(const String& other) - : m_data(other.m_data) -{ -} - -String& String::operator=(const String& other) -{ - if (this == &other) - return *this; - m_data = other.m_data; - return *this; -} - -String& String::operator=(const String&& other) -{ - if (this == &other) - return *this; - m_data = move(other.m_data); - return *this; -} - -String::~String() -{ -} - -bool String::operator==(const String& other) const -{ - if (length() != other.length()) - return false; - return strcmp(characters(), other.characters()) == 0; -} - -String String::substring(size_t start, size_t length) const -{ - ASSERT(start + length <= m_data->length()); - // FIXME: This needs some input bounds checking. - auto buffer = DataBuffer::createUninitialized(length + 1); - memcpy(buffer->data(), characters() + start, length); - buffer->data()[length] = '\0'; - String s; - s.m_data = move(buffer); - return s; -} - -Vector<String> String::split(char separator) const -{ - Vector<String> v; - size_t substart = 0; - for (size_t i = 0; i < length(); ++i) { - char ch = characters()[i]; - if (ch == separator) { - size_t sublen = i - substart; - if (sublen != 0) - v.append(substring(substart, sublen)); - substart = i + 1; - } - } - size_t taillen = length() - 1 - substart; - if (taillen != 0) - v.append(substring(substart, taillen)); - return v; -} diff --git a/Kernel/String.h b/Kernel/String.h deleted file mode 100644 index c55b6e8996..0000000000 --- a/Kernel/String.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "DataBuffer.h" -#include "Vector.h" - -class String { -public: - String(); - String(const char* characters); - String(const char* characters, size_t length); - String(String&&); - String(const String&); - String& operator=(const String&); - String& operator=(const String&&); - ~String(); - - bool isEmpty() const { return m_data ? m_data->isEmpty() : true; } - size_t length() const { return m_data ? m_data->length() : 0; } - - char operator[](size_t i) const { return (char)m_data->data()[i]; } - - const char* characters() const { return m_data ? (const char*)m_data->data() : nullptr; } - - bool operator==(const String&) const; - - Vector<String> split(char separator) const; - String substring(size_t start, size_t length) const; - -private: - RefPtr<DataBuffer> m_data; -}; diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index b38b37335f..32f06d57e2 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -11,7 +11,7 @@ Task* current; Task* s_kernelTask; static pid_t next_pid; -static DoublyLinkedList<Task>* s_tasks; +static InlineLinkedList<Task>* s_tasks; static bool contextSwitch(Task*); @@ -46,7 +46,7 @@ void Task::initialize() { current = nullptr; next_pid = 0; - s_tasks = new DoublyLinkedList<Task>; + s_tasks = new InlineLinkedList<Task>; s_kernelTask = new Task(0, "idle", IPC::Handle::Any, Task::Ring0); redoKernelTaskTSS(); loadTaskRegister(s_kernelTask->selector()); @@ -415,12 +415,14 @@ int Task::sys$open(const char* path, size_t pathLength) FileHandle* Task::openFile(String&& path) { +#if 0 auto vnode = FileSystem::createVirtualNode(move(path)); if (!vnode) { kprintf("createVirtualNode failed\n"); return nullptr; } -#if 1 +#endif +#if 0 FileHandle* fh = new FileHandle; kprintf("made new FileHandle\n"); fh->m_fd = m_fileHandles.size(); diff --git a/Kernel/Task.h b/Kernel/Task.h index 7078a94c25..9929da4b7f 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -2,18 +2,18 @@ #include "types.h" #include "IPC.h" -#include "DoublyLinkedList.h" -#include "String.h" +#include "InlineLinkedList.h" +#include <AK/String.h> #include "TSS.h" -#include "Vector.h" +#include <AK/Vector.h> #include "i386.h" //#define TASK_SANITY_CHECKS class FileHandle; -class Task : public DoublyLinkedListNode<Task> { - friend class DoublyLinkedListNode<Task>; +class Task : public InlineLinkedListNode<Task> { + friend class InlineLinkedListNode<Task>; public: #ifdef TASK_SANITY_CHECKS static void checkSanity(const char* msg = nullptr); diff --git a/Kernel/Vector.h b/Kernel/Vector.h deleted file mode 100644 index 7b5fbded38..0000000000 --- a/Kernel/Vector.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -#include "Assertions.h" -#include "kmalloc.h" - -#define SANITIZE_VECTOR - -template<typename T> -class Vector { -public: - Vector() { } - ~Vector(); - - Vector(const Vector&&); - Vector& operator=(const Vector&&); - - bool isEmpty() const { return m_size == 0; } - size_t size() const { return m_size; } - size_t capacity() const { return m_capacity; } - - void append(T&&); - void clear(); - - const T& operator[](size_t i) const { return m_elements[i]; } - T& operator[](size_t i) { return m_elements[i]; } - -private: - Vector(const Vector&) = delete; - Vector& operator=(const Vector&) = delete; - - void ensureCapacity(size_t); - - T* m_elements { nullptr }; - size_t m_size { 0 }; - size_t m_capacity { 0 }; -}; - -template<typename T> -Vector<T>::~Vector() -{ - clear(); -#ifdef SANITIZE_VECTOR - m_elements = (T*)0xdddddddd; - m_size = 0x8a8a8a8a; - m_capacity = 0xa8a8a8a8; -#endif -} - -template<typename T> -void Vector<T>::clear() -{ - if (!m_elements) - return; - for (size_t i = 0; i < m_size; ++i) { - m_elements[i].~T(); - } - kfree(m_elements); - m_elements = nullptr; - m_size = 0; - m_capacity = 0; -} - -template<typename T> -void Vector<T>::append(T&& element) -{ - ensureCapacity(m_size + 1); - new (&m_elements[m_size]) T(move(element)); - ++m_size; -} - -template<typename T> -void Vector<T>::ensureCapacity(size_t neededCapacity) -{ - if (neededCapacity <= m_capacity) - return; - size_t newCapacity = (neededCapacity + 8) & ~7; - // FIXME: We need to support further growth here, jeez... - ASSERT(m_capacity == 0); - ASSERT(!m_elements); - m_capacity = newCapacity; - T* newElements = (T*)kmalloc(m_capacity * sizeof(T)); -#ifdef SANITIZE_VECTOR - memset(newElements, 0x66, m_capacity * sizeof(T)); -#endif - if (m_elements) { - memcpy(newElements, m_elements, m_size * sizeof(T)); - kfree(m_elements); - } - m_elements = newElements; -} diff --git a/Kernel/fs.cpp b/Kernel/fs.cpp deleted file mode 100644 index 23cadacfec..0000000000 --- a/Kernel/fs.cpp +++ /dev/null @@ -1,451 +0,0 @@ -#include "Disk.h" -#include "Task.h" -#include "VGA.h" -#include "kmalloc.h" -#include "Ext2FileSystem.h" -#include "i386.h" -#include "StdLib.h" -#include "OwnPtr.h" -#include "FileSystem.h" -#include "String.h" - -//#define FS_DEBUG - -Ext2FileSystem::~Ext2FileSystem() -{ - kprintf("fs: kill Ext2FileSystem\n"); - ASSERT(false); - kfree(m_groupTable); - m_groupTable = nullptr; - if (m_inodeTables) { - for (DWORD i = 0; i < m_blockGroupCount; ++i) - delete [] m_inodeTables[i]; - } - delete [] m_inodeTables; - m_inodeTables = nullptr; -} - -static Ext2FileSystem* fileSystem; - -void Ext2FileSystem::readDiskSector(DWORD sectorIndex, BYTE* buffer) -{ - Task::checkSanity("Ext2FileSystem::readDiskSector"); - bool success = Disk::readSectors(sectorIndex, 1, buffer); - (void) success; -} - -RefPtr<DataBuffer> Ext2FileSystem::readBlocks(DWORD blockIndex, BYTE count) -{ - Task::checkSanity("readBlocks"); - if (!m_superBlock) { - kprintf("fs: Attempt to read blocks without superblock!\n"); - HANG; - } - -#ifdef FS_DEBUG - kprintf("Read %u block(s) starting at %u\n", count, blockIndex); -#endif - // FIXME: This is broken up into 1-sector reads because the disk task can't handle multi-sector reads yet. - auto buffer = DataBuffer::createUninitialized(count * sectorsPerBlock() * bytesPerSector); - BYTE* bufptr = (BYTE*)buffer->data(); - for (DWORD i = 0; i < count; ++i) { - readDiskSector(((blockIndex + i) * sectorsPerBlock()) + 0, bufptr); - readDiskSector(((blockIndex + i) * sectorsPerBlock()) + 1, bufptr + bytesPerSector); - bufptr += bytesPerSector * 2; - } - return buffer; -} - -void Ext2FileSystem::readSuperBlock() -{ - ASSERT(!m_superBlock); - ASSERT(!m_groupTable); - - m_superBlock = make<ext2_super_block>(); - readDiskSector(2, (BYTE*)m_superBlock.ptr()); - - if (m_superBlock->s_magic != EXT2_MAGIC) { - kprintf("fs: PANIC! No ext2 filesystem found\n"); - HANG; - } - - kprintf("fs: ext2 filesystem found -- %u inodes, %u blocks\n", - m_superBlock->s_inodes_count, - m_superBlock->s_blocks_count); - - const BYTE* u = m_superBlock->s_uuid; - kprintf("fs: UUID: %b%b%b%b-%b%b-%b%b-%b%b-%b%b%b%b%b%b\n", - u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8], - u[9], u[10], u[11], u[12], u[13], u[14], u[15], u[16]); - -#ifdef FS_DEBUG - kprintf("fs: Block size is %u bytes\n", 1024 << m_superBlock->s_log_frag_size); - kprintf("fs: Blocks per group: %u\n", m_superBlock->s_blocks_per_group); -#endif - - m_blockGroupCount = m_superBlock->s_blocks_count / m_superBlock->s_blocks_per_group; - if ((m_superBlock->s_blocks_count % m_superBlock->s_blocks_per_group) != 0) - ++m_blockGroupCount; - - m_inodeTables = new ext2_inode*[m_blockGroupCount]; - memset(m_inodeTables, 0, sizeof(ext2_inode*) * m_blockGroupCount); -} - -void Ext2FileSystem::readBlockGroup(DWORD index) -{ - Task::checkSanity("readBlockGroup"); - DWORD superBlockBI = m_superBlock->s_first_data_block + (m_superBlock->s_blocks_per_group * index); - DWORD descriptorTableBI = superBlockBI + 1; - //DWORD blockBitmapBI = descriptorTableBI + 1; - //DWORD inodeBitmapBI = blockBitmapBI + 1; - //DWORD inodeTableBI = inodeBitmapBI + 1; - - auto buffer = readBlocks(descriptorTableBI, 1); - -#ifdef FS_DEBUG - kprintf("Inodes per group = %u\n", superBlock().s_inodes_per_group); - kprintf("First data block = %u\n", superBlock().s_first_data_block); -#endif - - m_groupTable = (ext2_group_descriptor*)kmalloc(blockSize()); - memcpy(m_groupTable, buffer->data(), buffer->length()); - -#ifdef FS_DEBUG - kprintf("[%u] block bitmap: %u\n", index, m_groupTable[index].bg_block_bitmap); - kprintf("[%u] inode bitmap: %u\n", index, m_groupTable[index].bg_inode_bitmap); - kprintf("[%u] inode table: %u\n", index, m_groupTable[index].bg_inode_table); -#endif -} - -template<typename F> -void Ext2FileSystem::traverseDirectory(ext2_dir_entry& firstEntry, DWORD blockCount, F func) -{ - Task::checkSanity("traverseDirectory1"); - auto* entry = &firstEntry; - char* name = new char[EXT2_NAME_LEN + 1]; - auto* end = (ext2_dir_entry*)((BYTE*)entry + blockCount * blockSize()); - - while (entry < end) { - if (entry->d_inode != 0) { - memcpy(name, entry->d_name, entry->d_name_len); - name[entry->d_name_len] = 0; - func(name, *entry); - } - entry = (ext2_dir_entry*)((BYTE *)entry + entry->d_rec_len); - } - - delete [] name; -} - -void Ext2FileSystem::readInodeTable(DWORD blockGroup) -{ - Task::checkSanity("readInodeTable"); - ext2_inode*& inodeTable = m_inodeTables[blockGroup]; - - if (!inodeTable) - inodeTable = new ext2_inode[m_superBlock->s_inodes_per_group]; - - DWORD inodeTableBlocks = (m_superBlock->s_inodes_per_group * sizeof(ext2_inode)) / blockSize(); -// kprintf("inode table blocks: %u\n", inodeTableBlocks); - - auto buffer = readBlocks(m_groupTable[blockGroup].bg_inode_table, inodeTableBlocks); - memcpy(inodeTable, buffer->data(), m_superBlock->s_inodes_per_group * sizeof(ext2_inode)); - m_root = &inodeTable[1]; - -#ifdef FS_DEBUG - kprintf("Root directory inode:\n"); - kprintf("sizeof(ext2_inode): %u\n", sizeof(ext2_inode)); - kprintf("sizeof(ext2_dir_entry): %u\n", sizeof(ext2_dir_entry)); - kprintf("Mode: %u, Owner: %u/%u, Size: %u\n", m_root->i_mode, m_root->i_uid, m_root->i_gid, m_root->i_size); - - kprintf("Directory blocks: { "); - for (DWORD i = 0; i < 12; ++i) { - kprintf( "%u ", m_root->i_block[i] ); - } - kprintf("}\n"); -#endif -} - -template<typename F> -void Ext2FileSystem::forEachBlockIn(ext2_inode& inode, F func) -{ - Task::checkSanity("forEachBlockIn"); - DWORD blockCount = inode.i_blocks / (2 << m_superBlock->s_log_block_size); - // FIXME: Support indirect blocks - for (DWORD i = 0; i < blockCount; ++i) { - //kprintf(" [blk %u]\n", inode.i_block[i]); - auto buffer = readBlocks(inode.i_block[i], 1); - func(move(buffer)); - } -} - -DWORD Ext2FileSystem::blockGroupForInode(DWORD inode) const -{ - // FIXME: Implement - (void)inode; - return 0; -} - -DWORD Ext2FileSystem::toInodeTableIndex(DWORD inode) const -{ - // FIXME: Implement - return inode - 1; -} - -ext2_inode* Ext2FileSystem::findInode(DWORD index) -{ - if (index >= m_superBlock->s_inodes_count) - return nullptr; - return &m_inodeTables[blockGroupForInode(index)][toInodeTableIndex(index)]; -} - -ext2_inode* Ext2FileSystem::findPath(const String& path, DWORD& inodeIndex) -{ - Task::checkSanity("findPath entry"); - ASSERT(m_root); - Task::checkSanity("findPath entry2"); - - if (path.isEmpty()) - return nullptr; - if (path[0] != '/') - return nullptr; - - ext2_inode* dir = m_root; - - Task::checkSanity("findPath pre-vector"); - Vector<String> pathParts = path.split('/'); - Task::checkSanity("findPath post-split"); - - for (size_t i = 0; i < pathParts.size(); ++i) { - //kprintf("[%u] %s\n", i, pathParts[i].characters()); - auto& part = pathParts[i]; - bool foundPart = false; - //kprintf("looking for part '%s' in inode{%p}\n", part.characters(), dir); - traverseDirectory(*dir, [&] (const char* name, ext2_dir_entry& entry) { - //kprintf(" ?= %s\n", name); - if (String(name) == part) { - foundPart = true; - //kprintf("found part ==> inode %u (type %b)\n", entry.d_inode, entry.d_file_type); - dir = findInode(entry.d_inode); - inodeIndex = entry.d_inode; - // FIXME: don't try to traverse files as if they're directories - // FIXME: need a way to skip the remaining traverseDirectory() callbacks - } - }); - if (!foundPart) - return nullptr; - } - - return dir; -} - -template<typename F> -void Ext2FileSystem::traverseDirectory(ext2_inode& inode, F func) -{ - Task::checkSanity("traverseDirectory2"); - //kprintf("in traverseDir\n"); - forEachBlockIn(inode, [this, &func] (RefPtr<DataBuffer>&& data) { - auto* directory = (ext2_dir_entry*)data->data(); - traverseDirectory<F>(*directory, 1, func); - }); - //kprintf("out traverseDir\n"); -} - -RefPtr<DataBuffer> Ext2FileSystem::readFile(ext2_inode& inode) -{ - auto buffer = DataBuffer::createUninitialized(inode.i_size + 1); - BYTE* bufptr = buffer->data(); - size_t dataRemaining = inode.i_size; - forEachBlockIn(inode, [this, &bufptr, &dataRemaining] (RefPtr<DataBuffer>&& data) { - memcpy(bufptr, data->data(), min(dataRemaining, data->length())); - dataRemaining -= blockSize(); - bufptr += blockSize(); - }); - // HACK: This is silly, but let's just null terminate here for comfort. - buffer->data()[buffer->length() - 1] = '\0'; - return buffer; -} - -void Ext2FileSystem::dumpFile(ext2_inode& inode) -{ - auto buffer = readFile(inode); - kprintf("%s", buffer->data()); -} - -void Ext2FileSystem::dumpDirectory(ext2_inode& inode) -{ - traverseDirectory(inode, [this] (const char* name, ext2_dir_entry& entry) { - bool isDirectory = entry.d_file_type == EXT2_FT_DIR; - ext2_inode& inode = m_inodeTables[blockGroupForInode(entry.d_inode)][toInodeTableIndex(entry.d_inode)]; - kprintf("i:%x %b %u:%u %x %s%s\n", - entry.d_inode, - entry.d_file_type, - inode.i_uid, - inode.i_gid, - inode.i_size, - name, - isDirectory ? "/" : ""); - }); -} - -#if 0 -void Ext2FileSystem::readRoot() -{ - auto buffer = readBlocks(m_root->i_block[0], 1); - auto* dir_block = (ext2_dir_entry*)buffer.data(); - - traverseDirectory(dir_block, [this] (const char* name, ext2_dir_entry* entry) { - if (!strcmp(name, "test2")) { - auto test2_entry = loadFile(entry); - new Task((void (*)())test2_entry.data(), "test2", IPC::Handle::Any, Task::Ring3); - // HACK: Don't delete the code we just started running :) - test2_entry.leak(); - } else if (!strcmp( name, "motd.txt")) { - auto motd_txt = loadFile(entry); - kprintf("===============================================\n\n"); - vga_set_attr(0x03); - kprintf("%s\n", motd_txt.data()); - vga_set_attr(0x07); - kprintf("===============================================\n"); - } - }); -} -#endif - -void Ext2FileSystem::initialize() -{ - readSuperBlock(); - readBlockGroup(0); - readInodeTable(0); - -#ifdef FS_DEBUG - dumpDirectory(*m_root); -#endif - - DWORD inodeIndex; - auto* file = findPath("/motd.txt", inodeIndex); - dumpFile(*file); -} - -RefPtr<DataBuffer> Ext2FileSystem::loadFile(ext2_dir_entry* dirent) -{ - Task::checkSanity("loadFile"); - DWORD inode_group = (dirent->d_inode - 1) / superBlock().s_inodes_per_group; - -#ifdef FS_DEBUG - kprintf("inode: %u (group %u)\n", dirent->d_inode, inode_group); - kprintf("inode table at block %u\n", m_groupTable[inode_group].bg_inode_table); -#endif - - // Calculate interesting offset into inode block. - DWORD inode_index = (dirent->d_inode - 1) % superBlock().s_inodes_per_group; - - // Load the relevant inode block. - auto buffer = readBlocks(m_groupTable[inode_group].bg_inode_table, 4); - auto* inode_table = (ext2_inode*)buffer->data(); - -#ifdef FS_DEBUG - kprintf("inode index: %u\n", inode_index); -#endif - - ext2_inode* inode = &inode_table[inode_index]; - -#ifdef FS_DEBUG - kprintf("Mode: %u UID: %u GID: %u Size: %u Block0: %u\n", inode->i_mode, inode->i_uid, inode->i_gid, inode->i_size, inode->i_block[0]); -#endif - - auto fileContents = readBlocks(inode->i_block[0], 1); - -#ifdef FS_DEBUG - kprintf("File @ %p\n", fileContents->data()); - kprintf("File contents: %b %b %b %b %b\n", - (*fileContents)[0], - (*fileContents)[1], - (*fileContents)[2], - (*fileContents)[3], - (*fileContents)[4]); -#endif - - return fileContents; -} - -RefPtr<Ext2VirtualNode> Ext2VirtualNode::create(DWORD index, String&& path, Ext2FileSystem& fs, DWORD inodeNumber) -{ - Task::checkSanity("enter E2VN::create"); - ext2_inode* inode = fs.findInode(inodeNumber); - Task::checkSanity("post findInode"); - if (!inode) - return nullptr; - auto* v = new Ext2VirtualNode(index, move(path), fs, *inode, inodeNumber); - kprintf("v=%p\n", v); - auto r = adoptRef(v); - kprintf("adopted(v)=%p\n", r.ptr()); - return r; -} - -Ext2VirtualNode::Ext2VirtualNode(DWORD index, String&& path, Ext2FileSystem& fs, ext2_inode& inode, DWORD inodeNumber) - : VirtualNode(index, move(path)) - , m_fileSystem(fs) - , m_inode(inode) - , m_inodeNumber(inodeNumber) -{ - Task::checkSanity("Ext2VirtualNode::Ext2VirtualNode"); -} - -Ext2VirtualNode::~Ext2VirtualNode() -{ - Task::checkSanity("Ext2VirtualNode::~Ext2VirtualNode"); -} - -size_t Ext2VirtualNode::read(BYTE* outbuf, size_t start, size_t maxLength) -{ - Task::checkSanity("Ext2VirtualNode::read"); - kprintf("Ext2VirtualNode::read\n"); - if (start >= size()) - return 0; - - auto fileContents = m_fileSystem.readFile(m_inode); - if (!fileContents) - return 0; - ASSERT(start < fileContents->length()); - size_t nread = min(maxLength, fileContents->length() - start); - memcpy(outbuf, fileContents->data(), nread); - return nread; -} - -namespace FileSystem { - -static DWORD nextVNodeIndex; - -void initialize() -{ - nextVNodeIndex = 0; - fileSystem = new Ext2FileSystem; - fileSystem->initialize(); -} - -VirtualNode::VirtualNode(DWORD index, String&& path) - : m_index(index) - , m_path(move(path)) -{ -} - -VirtualNode::~VirtualNode() -{ -} - -RefPtr<VirtualNode> createVirtualNode(String&& path) -{ - Task::checkSanity("createVirtualNode"); - DWORD inodeIndex = 0x12345678; - Task::checkSanity("pre-findPath"); - kprintf("path: '%s'\n", path.characters()); - auto* inode = fileSystem->findPath(path, inodeIndex); - Task::checkSanity("post-findPath"); - if (!inode) - return nullptr; - kprintf("creating e2vn\n"); - return Ext2VirtualNode::create(nextVNodeIndex++, move(path), *fileSystem, inodeIndex); -} - -} diff --git a/Kernel/init.cpp b/Kernel/init.cpp index bd3aee7755..ba0bdee0ff 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -12,13 +12,13 @@ #include "StdLib.h" #include "Syscall.h" #include "CMOS.h" -#include "FileSystem.h" #include "Userspace.h" #include "IDEDiskDevice.h" #include <VirtualFileSystem/NullDevice.h> #include <VirtualFileSystem/ZeroDevice.h> #include <VirtualFileSystem/FullDevice.h> #include <VirtualFileSystem/RandomDevice.h> +#include <VirtualFileSystem/Ext2FileSystem.h> #include <AK/OwnPtr.h> #if 0 @@ -127,7 +127,6 @@ void init() banner(); Disk::initialize(); - FileSystem::initialize(); auto dev_hd0 = IDEDiskDevice::create(); auto dev_null = make<NullDevice>(); @@ -135,6 +134,9 @@ void init() auto dev_zero = make<ZeroDevice>(); auto dev_random = make<RandomDevice>(); + auto e2fs = Ext2FileSystem::create(dev_hd0.copyRef()); + e2fs->initialize(); + // new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0); new Task(user_main, "user", IPC::Handle::UserTask, Task::Ring3); diff --git a/Kernel/run b/Kernel/run index 067e05dfea..f3454dbf4e 100755 --- a/Kernel/run +++ b/Kernel/run @@ -1,5 +1,5 @@ #!/bin/sh -#bochs -q -f .bochs.conf +bochs -q -f .bochsrc -qemu-system-i386 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents $@ +#qemu-system-i386 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents $@ |