aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml2
-rw-r--r--README.md6
-rwxr-xr-xrun35
-rw-r--r--src/kernel/fs/ata.c332
-rw-r--r--src/kernel/fs/ata.h144
-rw-r--r--src/kernel/fs/ext2.c884
-rw-r--r--src/kernel/fs/ext2.h309
-rw-r--r--src/kernel/fs/vfs.c369
-rw-r--r--src/kernel/fs/vfs.h149
-rw-r--r--src/kernel/kernel.c5
10 files changed, 405 insertions, 1830 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index cbd8a05..d14d177 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -12,7 +12,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Install
- run: sudo apt-get update && sudo apt-get install -y build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo libcloog-isl-dev libisl-0.18-dev ccache curl nasm genisoimage qemu qemu-kvm mtools
+ run: sudo apt-get update && sudo apt-get install -y build-essential bison flex libgmp3-dev libmpc-dev libmpfr-dev texinfo libcloog-isl-dev libisl-0.18-dev ccache curl nasm genisoimage qemu qemu-kvm mtools genext2fs
- name: Get cross compiler
id: cache-cross
uses: actions/cache@v1
diff --git a/README.md b/README.md
index 9ec05b0..9247247 100644
--- a/README.md
+++ b/README.md
@@ -8,13 +8,10 @@
<a href="https://app.codacy.com/manual/marvin-borner/Melvix/dashboard" target="_blank">
<img src="https://img.shields.io/codacy/grade/4ae29e218d7c439eaa549ea828ffcaac?style=for-the-badge" />
</a>
- <a href="https://marvinborner.de/melvix/" target="_blank">
- <img src="https://img.shields.io/badge/download-latest-brightgreen?style=for-the-badge" />
- </a>
</p>
## Build
-* Use any system running GNU/Linux (Successfully tried building on Debian, Arch Linux and even OpenBSD)
+* Use any system running GNU/Linux
* Install build dependencies (package names may vary depending on your operating system)
* Ubuntu/Debian _"instructions"_ can be found here: [GitHub Workflow](https://raw.githubusercontent.com/marvinborner/Melvix/master/.github/workflows/build.yml)
@@ -32,6 +29,7 @@
* nasm
* genisoimage
* qemu
+ * genext2fs
* Build a cross compiler using `./run cross`
diff --git a/run b/run
index 7dff314..9857d22 100755
--- a/run
+++ b/run
@@ -119,41 +119,18 @@ make_build() {
cp ./src/bootloader/grub.cfg ./iso/boot/grub/
cp ./build/user.bin ./iso/user.bin
cp ./build/font.bin ./iso/font.bin
- grub-mkrescue -o ./build/melvix.iso ./iso/
- dd if=/dev/zero of=./build/ext2_hda.img bs=1k count=100000 >/dev/zero
- mkfs -t ext2 -i 1024 -b 1024 -F ./build/ext2_hda.img >/dev/zero
- fdisk ./build/ext2_hda.img <<EOF
-x
-c
-10
-h
-16
-s
-63
-r
-n
-p
-1
-2048
-199999
-w
-EOF
-
- cp ./build/ext2_hda.img ./build/ext2_hdb.img
- cp ./build/ext2_hda.img ./build/ext2_hdc.img
- cp ./build/ext2_hda.img ./build/ext2_hdd.img
-
- mkdir mnt/
- sudo mount ./build/ext2_hda.img mnt/
- echo "Bananenkuchen" | sudo tee -a mnt/test.txt
- sudo umount mnt
+ grub-mkrescue -o ./build/melvix.iso ./iso/ || exit 1
+
+ mkdir ./mnt/
+ echo "Bananenkuchen" >./mnt/test
+ genext2fs -d ./mnt/ -U -N 4096 -b 65536 ./build/disk.img || exit 1
rm -r mnt/
printf "Build finshed successfully!\n\n"
}
make_test() {
- qemu_with_flags -cdrom ./build/melvix.iso -hda ./build/ext2_hda.img -hdb ./build/ext2_hdb.img -hdd ./build/ext2_hdd.img -boot d
+ qemu_with_flags -cdrom ./build/melvix.iso -hda ./build/disk.img -boot d
}
make_debug() {
diff --git a/src/kernel/fs/ata.c b/src/kernel/fs/ata.c
index b637dbd..d5c758c 100644
--- a/src/kernel/fs/ata.c
+++ b/src/kernel/fs/ata.c
@@ -1,292 +1,120 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <kernel/fs/ata.h>
#include <kernel/system.h>
#include <kernel/io/io.h>
-#include <kernel/fs/ata.h>
-#include <kernel/lib/lib.h>
-#include <kernel/lib/stdlib.h>
-#include <kernel/lib/stdio.h>
-#include <kernel/memory/alloc.h>
-#include <kernel/pci/pci.h>
-#include <kernel/interrupts/interrupts.h>
-uint32_t ata_device = 0x00000000;
+static uint16_t sel_base_port = 0;
+static uint8_t sel_master_or_slave = 0;
-ata_dev_t primary_master = { .slave = 0 };
-ata_dev_t primary_slave = { .slave = 1 };
-ata_dev_t secondary_master = { .slave = 0 };
-ata_dev_t secondary_slave = { .slave = 1 };
-
-void io_wait(ata_dev_t *dev)
-{
- inb(dev->alt_status);
- inb(dev->alt_status);
- inb(dev->alt_status);
- inb(dev->alt_status);
-}
+static uint32_t max_sector;
-void software_reset(ata_dev_t *dev)
+static uint8_t read_stat(uint16_t base)
{
- outb(dev->control, CONTROL_SOFTWARE_RESET);
- io_wait(dev);
- outb(dev->control, CONTROL_ZERO);
-}
+ inb(base + COM_STAT);
+ inb(base + COM_STAT);
+ inb(base + COM_STAT);
+ inb(base + COM_STAT);
-void ata_handler(struct regs *r)
-{
- inb(primary_master.status);
- inb(primary_master.BMR_STATUS);
- outb(primary_master.BMR_COMMAND, BMR_COMMAND_DMA_STOP);
- //irq_ack(14);
+ return inb(base + COM_STAT);
}
-void ata_open(vfs_node_t *node, uint32_t flags)
+static void check_drive(uint16_t base, uint8_t master_or_slave)
{
- return;
-}
+ if (sel_base_port != 0)
+ return;
-void ata_close(vfs_node_t *node)
-{
- return;
-}
+ outb(base + DRIVE_SELECT, master_or_slave);
-uint32_t ata_read(vfs_node_t *node, uint32_t offset, uint32_t size, char *buf)
-{
- uint32_t start = offset / SECTOR_SIZE;
- uint32_t start_offset = offset % SECTOR_SIZE;
+ outb(base + SECTOR_COUNT, 0);
+ outb(base + LBA_LOW, 0);
+ outb(base + LBA_MID, 0);
+ outb(base + LBA_HIGH, 0);
- uint32_t end = (offset + size - 1) / SECTOR_SIZE;
- uint32_t end_offset = (offset + size - 1) % SECTOR_SIZE;
+ outb(base + COM_STAT, IDENTIFY);
+ uint8_t stat = read_stat(base);
- char *buf_curr = buf;
- uint32_t counter = start;
- uint32_t read_size;
- uint32_t off, total = 0;
-
- while (counter <= end) {
- off = 0;
- read_size = SECTOR_SIZE;
+ if (stat == 0)
+ return;
- char *ret = ata_read_sector((ata_dev_t *)node->device, counter);
+ while ((stat & BSY) != 0)
+ stat = read_stat(base);
- if (counter == start) {
- off = start_offset;
- read_size = SECTOR_SIZE - off;
- }
- if (counter == end)
- read_size = end_offset - off + 1;
+ while ((stat & DRQ) == 0 && (stat & ERR) == 0)
+ stat = read_stat(base);
- memcpy(buf_curr, ret + off, read_size);
- buf_curr = buf_curr + read_size;
- total = total + read_size;
- counter++;
- }
- return total;
-}
-
-uint32_t ata_write(vfs_node_t *node, uint32_t offset, uint32_t size, char *buf)
-{
- uint32_t start = offset / SECTOR_SIZE;
- uint32_t start_offset = offset % SECTOR_SIZE;
+ if ((stat & ERR) != 0)
+ return;
- uint32_t end = (offset + size - 1) / SECTOR_SIZE;
- uint32_t end_offset = (offset + size - 1) % SECTOR_SIZE;
+ uint16_t drive_data[256];
+ for (size_t i = 0; i < 256; i++)
+ drive_data[i] = inw(base + DATA);
- char *buf_curr = buf;
- uint32_t counter = start;
- uint32_t write_size;
- uint32_t off, total = 0;
+ max_sector = drive_data[MAX_28LBA_SECTORS] | drive_data[MAX_28LBA_SECTORS + 1] << 16;
- while (counter <= end) {
- off = 0;
- write_size = SECTOR_SIZE;
- char *ret = ata_read_sector((ata_dev_t *)node->device, counter);
- if (counter == start) {
- off = start_offset;
- write_size = SECTOR_SIZE - off;
- }
- if (counter == end) {
- write_size = end_offset - off + 1;
- }
- memcpy(ret + off, buf_curr, write_size);
- ata_write_sector((ata_dev_t *)node->device, counter, ret);
- buf_curr = buf_curr + write_size;
- total = total + write_size;
- counter++;
- }
- return total;
+ sel_base_port = base;
+ sel_master_or_slave = master_or_slave;
}
-void ata_write_sector(ata_dev_t *dev, uint32_t lba, char *buf)
+void ata_init()
{
- memcpy(dev->mem_buffer, buf, SECTOR_SIZE);
-
- outb(dev->BMR_COMMAND, 0);
- outl(dev->BMR_prdt, (uint32_t)dev->prdt_phys);
- outb(dev->drive, 0xe0 | dev->slave << 4 | (lba & 0x0f000000) >> 24);
- outb(dev->sector_count, 1);
- outb(dev->lba_lo, lba & 0x000000ff);
- outb(dev->lba_mid, (lba & 0x0000ff00) >> 8);
- outb(dev->lba_high, (lba & 0x00ff0000) >> 16);
-
- outb(dev->command, 0xCA);
-
- outb(dev->BMR_COMMAND, 0x1);
-
- while (1) {
- int status = inb(dev->BMR_STATUS);
- int dstatus = inb(dev->status);
- if (!(status & 0x04)) {
- continue;
- }
- if (!(dstatus & 0x80)) {
- break;
- }
+ uint8_t pri_status = inb(PRIMARY_BASE + COM_STAT);
+ uint8_t sec_status = inb(SECONDARY_BASE + COM_STAT);
+ bool primary_floating = false;
+ bool secondary_floating = false;
+ if (pri_status == 0xFF)
+ primary_floating = true;
+ if (sec_status == 0xFF)
+ secondary_floating = true;
+
+ if (primary_floating && secondary_floating) {
+ log("No drives attached! What's going on?");
+ return;
}
-}
-
-char *ata_read_sector(ata_dev_t *dev, uint32_t lba)
-{
- char *buf = kmalloc(SECTOR_SIZE);
- outb(dev->BMR_COMMAND, 0);
- outl(dev->BMR_prdt, (uint32_t)dev->prdt_phys);
- outb(dev->drive, 0xe0 | dev->slave << 4 | (lba & 0x0f000000) >> 24);
- outb(dev->sector_count, 1);
- outb(dev->lba_lo, lba & 0x000000ff);
- outb(dev->lba_mid, (lba & 0x0000ff00) >> 8);
- outb(dev->lba_high, (lba & 0x00ff0000) >> 16);
-
- outb(dev->command, 0xC8);
-
- outb(dev->BMR_COMMAND, 0x8 | 0x1);
-
- while (1) {
- int status = inb(dev->BMR_STATUS);
- int dstatus = inb(dev->status);
- if (!(status & 0x04)) {
- continue;
- }
- if (!(dstatus & 0x80)) {
- break;
- }
+ check_drive(PRIMARY_BASE, SEL_MASTER);
+ check_drive(PRIMARY_BASE, SEL_SLAVE);
+ check_drive(SECONDARY_BASE, SEL_MASTER);
+ check_drive(SECONDARY_BASE, SEL_SLAVE);
+
+ if (sel_base_port == 0)
+ log("No drives attached! What's going on?");
+ else {
+ log("Found a drive!\nSelected drive is the %s on the %s bus",
+ sel_master_or_slave == SEL_MASTER ? "master" : "slave",
+ sel_base_port == PRIMARY_BASE ? "primary" : "secondary");
+ log("Max LBA value is %d", max_sector);
}
-
- memcpy(buf, dev->mem_buffer, SECTOR_SIZE);
- return buf;
}
-vfs_node_t *create_ata_device(ata_dev_t *dev)
+static void poll()
{
- vfs_node_t *t = kcalloc(sizeof(vfs_node_t), 1);
- strcpy(t->name, "ata device ");
- t->name[strlen(t->name)] = dev->mountpoint[strlen(dev->mountpoint) - 1];
- t->device = dev;
- t->flags = FS_BLOCKDEVICE;
- t->read = ata_read;
- t->write = ata_write;
- t->open = ata_open;
- t->close = ata_close;
- return t;
-}
-
-void ata_device_init(ata_dev_t *dev, int primary)
-{
- dev->prdt = (void *)kmalloc(sizeof(prdt_t));
- memset(dev->prdt, 0, sizeof(prdt_t));
- dev->prdt_phys = (uint8_t *)paging_get_phys((uint32_t)dev->prdt);
- dev->mem_buffer = (void *)kmalloc(4096);
- memset(dev->mem_buffer, 0, 4096);
-
- dev->prdt[0].buffer_phys = (uint32_t)paging_get_phys((uint32_t)dev->mem_buffer);
- dev->prdt[0].transfer_size = SECTOR_SIZE;
- dev->prdt[0].mark_end = MARK_END;
+ uint8_t stat;
- uint16_t base_addr = primary ? (0x1F0) : (0x170);
- uint16_t alt_status = primary ? (0x3F6) : (0x376);
-
- dev->data = base_addr;
- dev->error = base_addr + 1;
- dev->sector_count = base_addr + 2;
- dev->lba_lo = base_addr + 3;
- dev->lba_mid = base_addr + 4;
- dev->lba_high = base_addr + 5;
- dev->drive = base_addr + 6;
- dev->command = base_addr + 7;
- dev->alt_status = alt_status;
-
- dev->bar4 = pci_read_field(ata_device, PCI_BAR4, 4);
- if (dev->bar4 & 0x1) {
- dev->bar4 = dev->bar4 & 0xfffffffc;
- }
- dev->BMR_COMMAND = dev->bar4;
- dev->BMR_STATUS = dev->bar4 + 2;
- dev->BMR_prdt = dev->bar4 + 4;
-
- memset(dev->mountpoint, 0, 32);
- strcpy(dev->mountpoint, "/dev/hd");
- dev->mountpoint[strlen(dev->mountpoint)] = 'a' + (((!primary) << 1) | dev->slave);
+ do
+ stat = read_stat(sel_base_port);
+ while ((stat & BSY) != 0);
}
-void ata_device_detect(ata_dev_t *dev, int primary)
+void read_abs_sectors(uint32_t lba, uint8_t sector_count, uint16_t buf[])
{
- ata_device_init(dev, primary);
+ assert(lba >> LBA_BITS == 0);
- software_reset(dev);
- io_wait(dev);
- outb(dev->drive, (0xA + dev->slave) << 4);
- outb(dev->sector_count, 0);
- outb(dev->lba_lo, 0);
- outb(dev->lba_mid, 0);
- outb(dev->lba_high, 0);
+ outb(sel_base_port + DRIVE_SELECT, (lba >> (LBA_BITS - 4)) | sel_master_or_slave | 1 << 6);
+ outb(sel_base_port + SECTOR_COUNT, sector_count);
- outb(dev->command, COMMAND_IDENTIFY);
- if (!inb(dev->status)) {
- warn("Device does not exist: %s", dev->mountpoint);
- return;
- }
+ outb(sel_base_port + LBA_LOW, lba & 0xFF);
+ outb(sel_base_port + LBA_MID, (lba >> 8) & 0xFF);
+ outb(sel_base_port + LBA_HIGH, (lba >> 16) & 0xFF);
- uint8_t lba_lo = inb(dev->lba_lo);
- uint8_t lba_hi = inb(dev->lba_high);
- if (lba_lo != 0 || lba_hi != 0) {
- warn("Device is not ata-compatible: %s", dev->mountpoint);
- return;
- }
- uint8_t drq = 0, err = 0;
- while (!drq && !err) {
- drq = inb(dev->status) & STATUS_DRQ;
- err = inb(dev->status) & STATUS_ERR;
- }
- if (err) {
- warn("Error while polling: %s", dev->mountpoint);
- return;
- }
+ outb(sel_base_port + COM_STAT, READ_SECTORS);
- for (int i = 0; i < 256; i++)
- inw(dev->data);
+ size_t i = 0;
+ for (; sector_count > 0; sector_count--) {
+ poll();
- uint32_t pci_command_reg = pci_read_field(ata_device, PCI_COMMAND, 2);
- if (!(pci_command_reg & (1 << 2))) {
- pci_command_reg |= (1 << 2);
- pci_write_field(ata_device, PCI_COMMAND, pci_command_reg);
+ asm("rep insw" ::"c"(SECTOR_SIZE / 2), "d"(sel_base_port + DATA), "D"(buf + i));
+ i += SECTOR_SIZE / 2;
}
-
- log("Detected drive: %s", dev->mountpoint);
- vfs_mount(dev->mountpoint, create_ata_device(dev));
-}
-
-void ata_find(uint32_t device, uint16_t vendor_id, uint16_t device_id, void *extra)
-{
- if ((vendor_id == ATA_VENDOR_ID) && (device_id == ATA_DEVICE_ID))
- *((uint32_t *)extra) = device;
-}
-
-void ata_init()
-{
- pci_scan(&ata_find, -1, &ata_device);
-
- irq_install_handler(14, ata_handler);
-
- ata_device_detect(&primary_master, 1);
- ata_device_detect(&primary_slave, 1);
- // ata_device_detect(&secondary_master, 0);
- // ata_device_detect(&secondary_slave, 0);
} \ No newline at end of file
diff --git a/src/kernel/fs/ata.h b/src/kernel/fs/ata.h
index 36dec8d..b3774e1 100644
--- a/src/kernel/fs/ata.h
+++ b/src/kernel/fs/ata.h
@@ -1,119 +1,45 @@
#ifndef ATA_DRIVER_H
#define ATA_DRIVER_H
-#include <kernel/fs/vfs.h>
-#include <kernel/memory/paging.h>
-#include <kernel/interrupts/interrupts.h>
+#include <stdint.h>
-typedef struct prdt {
- uint32_t buffer_phys;
- uint16_t transfer_size;
- uint16_t mark_end;
-} __attribute__((packed)) prdt_t;
-
-typedef struct ata_dev {
- uint16_t data;
- uint16_t error;
- uint16_t sector_count;
-
- union {
- uint16_t sector_num;
- uint16_t lba_lo;
- };
- union {
- uint16_t cylinder_low;
- uint16_t lba_mid;
- };
- union {
- uint16_t cylinder_high;
- uint16_t lba_high;
- };
- union {
- uint16_t drive;
- uint16_t head;
- };
- union {
- uint16_t command;
- uint16_t status;
- };
- union {
- uint16_t control;
- uint16_t alt_status;
- };
-
- int slave;
- uint32_t bar4;
- uint32_t BMR_COMMAND;
- uint32_t BMR_prdt;
- uint32_t BMR_STATUS;
-
- prdt_t *prdt;
- uint8_t *prdt_phys;
-
- uint8_t *mem_buffer;
- uint8_t *mem_buffer_phys;
-
- char mountpoint[32];
-} __attribute__((packed)) ata_dev_t;
-
-// ATA PCI info of QEMU // TODO: Remove Qemu based device id
-#define ATA_VENDOR_ID 0x8086
-#define ATA_DEVICE_ID 0x7010
-
-// Control reg
-#define CONTROL_STOP_INTERRUPT 0x2
-#define CONTROL_SOFTWARE_RESET 0x4
-#define CONTROL_HIGH_ORDER_BYTE 0x80
-#define CONTROL_ZERO 0x00
-
-// Command reg
-#define COMMAND_IDENTIFY 0xEC
-#define COMMAND_DMA_READ 0xC8
-#define ATA_CMD_READ_PIO 0x20
-
-// Status reg
-#define STATUS_ERR 0x0
-#define STATUS_DRQ 0x8
-#define STATUS_SRV 0x10
-#define STATUS_DF 0x20
-#define STATUS_RDY 0x40
-#define STATUS_BSY 0x80
-
-// Bus Master Reg Command
-#define BMR_COMMAND_DMA_START 0x1
-#define BMR_COMMAND_DMA_STOP 0x0
-#define BMR_COMMAND_READ 0x8
-#define BMR_STATUS_INT 0x4
-#define BMR_STATUS_ERR 0x2
-
-// Prdt
#define SECTOR_SIZE 512
-#define MARK_END 0x8000
-void io_wait(ata_dev_t *dev);
-
-void software_reset(ata_dev_t *dev);
-
-void ata_handler(struct regs *reg);
-
-void ata_open(vfs_node_t *node, uint32_t flags);
-
-void ata_close(vfs_node_t *node);
-
-uint32_t ata_read(vfs_node_t *node, uint32_t offset, uint32_t size, char *buf);
-
-uint32_t ata_write(vfs_node_t *node, uint32_t offset, uint32_t size, char *buf);
-
-void ata_write_sector(ata_dev_t *dev, uint32_t lba, char *buf);
-
-char *ata_read_sector(ata_dev_t *dev, uint32_t lba);
-
-vfs_node_t *create_ata_device(ata_dev_t *dev);
-
-void ata_device_init(ata_dev_t *dev, int primary);
-
-void ata_device_detect(ata_dev_t *dev, int primary);
+#define LBA_BITS 28
+
+// Port bases and offsets
+#define PRIMARY_BASE 0x1F0
+#define SECONDARY_BASE 0x170
+#define DATA 0
+#define ERROR 1
+#define SECTOR_COUNT 2
+#define LBA_LOW 3
+#define LBA_MID 4
+#define LBA_HIGH 5
+#define DRIVE_SELECT 6
+#define COM_STAT 7
+
+#define PRI_CONTROL 0x3F6
+#define SEC_CONTROL 0x376
+
+// Commands
+#define SEL_MASTER 0xA0
+#define SEL_SLAVE 0xB0
+#define IDENTIFY 0xEC
+#define READ_SECTORS 0x20
+
+// Status byte flags
+#define ERR (1 << 0)
+#define DRQ (1 << 3)
+#define SRV (1 << 4)
+#define DF (1 << 5)
+#define RDY (1 << 6)
+#define BSY (1 << 7)
+
+#define MAX_28LBA_SECTORS 60
void ata_init();
+void read_abs_sectors(uint32_t lba, uint8_t sector_count, uint16_t buf[]);
+
#endif \ No newline at end of file
diff --git a/src/kernel/fs/ext2.c b/src/kernel/fs/ext2.c
index 41c2a3d..7ce0601 100644
--- a/src/kernel/fs/ext2.c
+++ b/src/kernel/fs/ext2.c
@@ -1,799 +1,235 @@
#include <stddef.h>
#include <stdint.h>
+#include <stdbool.h>
+#include <kernel/fs/ata.h>
+#include <kernel/fs/ext2.h>
#include <kernel/system.h>
-#include <kernel/lib/stdlib.h>
-#include <kernel/lib/stdio.h>
-#include <kernel/lib/lib.h>
#include <kernel/memory/alloc.h>
-#include <kernel/fs/ext2.h>
-
-uint32_t ext2_file_size(vfs_node_t *node)
-{
- ext2_fs_t *ext2fs = node->device;
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, node->inode_num);
- uint32_t ret = inode->size;
- kfree(inode);
- return ret;
-}
+#include <kernel/lib/lib.h>
+#include <kernel/lib/stdlib.h>
-void ext2_mkdir(vfs_node_t *parent, char *name, uint16_t permission)
-{
- ext2_fs_t *ext2fs = parent->device;
- uint32_t inode_idx = alloc_inode(ext2fs);
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, inode_idx);
- inode->permission = EXT2_S_IFDIR;
- inode->permission |= 0xFFF & permission;
- inode->atime = 0;
- inode->ctime = 0;
- inode->dtime = 0;
- inode->gid = 0;
- inode->userid = 0;
- inode->f_block_addr = 0;
- inode->num_sectors = 0;
- inode->size = ext2fs->block_size;
- inode->hard_links = 2;
- inode->flags = 0;
- inode->file_acl = 0;
- inode->dir_acl = 0;
- inode->generation = 0;
- inode->os_specific1 = 0;
- memset(inode->blocks, 0, sizeof(inode->blocks));
- memset(inode->os_specific2, 0, 12);
- alloc_inode_block(ext2fs, inode, inode_idx, 0);
- write_inode_metadata(ext2fs, inode, inode_idx);
- ext2_create_entry(parent, name, inode_idx);
-
- inode_t *p_inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, p_inode, parent->inode_num);
- p_inode->hard_links++;
- write_inode_metadata(ext2fs, p_inode, parent->inode_num);
- rewrite_bgds(ext2fs);
-}
+static struct ext2_superblock superblock;
+static struct bgd *bgdt;
+static size_t block_size;
+static size_t num_groups;
+static void read_block(uint32_t block_num, void *buf);
+static void load_superblock();
+static void load_bgdt();
+static void read_inode(struct ext2_inode *inode, uint32_t inode_num);
-void ext2_mkfile(vfs_node_t *parent, char *name, uint16_t permission)
+void ext2_init_fs()
{
- ext2_fs_t *ext2fs = parent->device;
- uint32_t inode_idx = alloc_inode(ext2fs);
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, inode_idx);
- inode->permission = EXT2_S_IFREG;
- inode->permission |= 0xFFF & permission;
- inode->atime = 0;
- inode->ctime = 0;
- inode->dtime = 0;
- inode->gid = 0;
- inode->userid = 0;
- inode->f_block_addr = 0;
- inode->num_sectors = 0;
- inode->size = ext2fs->block_size;
- inode->hard_links = 2;
- inode->flags = 0;
- inode->file_acl = 0;
- inode->dir_acl = 0;
- inode->generation = 0;
- inode->os_specific1 = 0;
- memset(inode->blocks, 0, sizeof(inode->blocks));
- memset(inode->os_specific2, 0, 12);
- alloc_inode_block(ext2fs, inode, inode_idx, 0);
- write_inode_metadata(ext2fs, inode, inode_idx);
- ext2_create_entry(parent, name, inode_idx);
-
- inode_t *p_inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, p_inode, parent->inode_num);
- p_inode->hard_links++;
- write_inode_metadata(ext2fs, p_inode, parent->inode_num);
- rewrite_bgds(ext2fs);
-}
+ load_superblock();
+ load_bgdt();
-void ext2_unlink(vfs_node_t *parent, char *name)
-{
- ext2_fs_t *ext2fs = parent->device;
- ext2_remove_entry(parent, name);
-
- inode_t *p_inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, p_inode, parent->inode_num);
- p_inode->hard_links--;
- write_inode_metadata(ext2fs, p_inode, parent->inode_num);
- rewrite_bgds(ext2fs);
-}
+ struct ext2_inode root_inode;
+ read_inode(&root_inode, ROOT_INODE);
+ log("Creation time = %d", root_inode.creation_time);
+ log("UID = %d", root_inode.uid);
+ log("Type & perms = 0x%x", root_inode.type_and_permissions);
+ log("Size = %d", root_inode.size);
-char **ext2_listdir(vfs_node_t *parent)
-{
- ext2_fs_t *ext2fs = parent->device;
- inode_t *p_inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, p_inode, parent->inode_num);
- uint32_t curr_offset = 0;
- uint32_t block_offset = 0;
- uint32_t in_block_offset = 0;
- int size = 0, cap = 10;
- char **ret = kmalloc(sizeof(char *) * cap);
- char *block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- while (curr_offset < p_inode->size) {
- if (in_block_offset >= ext2fs->block_size) {
- block_offset++;
- in_block_offset = 0;
- block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- }
- if (size + 1 == cap) {
- ret = krealloc(ret, sizeof(char *) * cap * 2);
- cap = cap * 2;
- }
+ log("Files:");
- direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset);
- if (curr_dir->inode != 0) {
- char *temp = kcalloc(curr_dir->name_len + 1, 1);
- memcpy(temp, curr_dir->name, curr_dir->name_len);
- ret[size++] = temp;
- }
- uint32_t expected_size =
- ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4;
- uint32_t real_size = curr_dir->size;
- if (real_size != expected_size) {
- break;
- }
- in_block_offset += curr_dir->size;
- curr_offset += curr_dir->size;
- }
- ret[size] = NULL;
- return ret;
-}
+ struct ext2_file file;
+ ext2_open_inode(ROOT_INODE, &file);
+ struct ext2_dirent dirent;
-vfs_node_t *vfsnode_from_direntry(ext2_fs_t *ext2fs, direntry_t *dir, inode_t *inode)
-{
- vfs_node_t *ret = kcalloc(sizeof(vfs_node_t), 1);
-
- ret->device = (void *)ext2fs;
- ret->inode_num = dir->inode;
- memcpy(ret->name, dir->name, dir->name_len);
-
- ret->uid = inode->userid;
- ret->uid = inode->gid;
- ret->size = inode->size;
- ret->mask = inode->permission & 0xFFF;
- ret->nlink = inode->hard_links;
-
- ret->flags = 0;
- if ((inode->permission & EXT2_S_IFREG) == EXT2_S_IFREG) {
- ret->flags |= FS_FILE;
- ret->read = ext2_read;
- ret->write = ext2_write;
- ret->unlink = ext2_unlink;
- ret->get_file_size = ext2_file_size;
- }
- if ((inode->permission & EXT2_S_IFDIR) == EXT2_S_IFDIR) {
- ret->flags |= FS_DIRECTORY;
- ret->mkdir = ext2_mkdir;
- ret->finddir = ext2_finddir;
- ret->unlink = ext2_unlink;
- ret->create = ext2_mkfile;
- ret->listdir = ext2_listdir;
- ret->read = ext2_read;
- ret->write = ext2_write;
- }
- if ((inode->permission & EXT2_S_IFBLK) == EXT2_S_IFBLK) {
- ret->flags |= FS_BLOCKDEVICE;
- }
- if ((inode->permission & EXT2_S_IFCHR) == EXT2_S_IFCHR) {
- ret->flags |= FS_CHARDEVICE;
- }
- if ((inode->permission & EXT2_S_IFIFO) == EXT2_S_IFIFO) {
- ret->flags |= FS_PIPE;
- }
- if ((inode->permission & EXT2_S_IFLNK) == EXT2_S_IFLNK) {
- ret->flags |= FS_SYMLINK;
- }
+ while (ext2_next_dirent(&file, &dirent))
+ log("Inode %d, name `%s'", dirent.inode_num, dirent.name);
- ret->access_time = inode->atime;
- ret->modified_time = inode->mtime;
- ret->create_time = inode->ctime;
+ kfree(file.buf);
- ret->chmod = ext2_chmod;
- ret->open = ext2_open;
- ret->close = ext2_close;
- return ret;
+ log("Looking for file '/test'...");
+ uint32_t inode = ext2_look_up_path("/test");
+ if (inode == 0)
+ log("File not found");
+ else
+ log("Found: inode = %d", inode);
+ panic("nice");
}
-vfs_node_t *ext2_finddir(vfs_node_t *parent, char *name)
+static void read_block(uint32_t block_num, void *buf)
{
- ext2_fs_t *ext2fs = parent->device;
- inode_t *p_inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, p_inode, parent->inode_num);
- uint32_t expected_size;
- uint32_t real_size;
- uint32_t curr_offset = 0;
- uint32_t block_offset = 0;
- uint32_t in_block_offset = 0;
- char *block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- while (curr_offset < p_inode->size) {
- if (in_block_offset >= ext2fs->block_size) {
- block_offset++;
- in_block_offset = 0;
- block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- }
-
- direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset);
- char *temp = kcalloc(curr_dir->name_len + 1, 1);
- memcpy(temp, curr_dir->name, curr_dir->name_len);
- if (curr_dir->inode != 0 && !strcmp(temp, name)) {
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, curr_dir->inode);
- return vfsnode_from_direntry(ext2fs, curr_dir, inode);
- }
- if (((sizeof(direntry_t) + curr_dir->name_len) & 0x00000003) != 0)
- expected_size =
- ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4;
- else
- expected_size = ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc);
- real_size = curr_dir->size;
- if (real_size != expected_size) {
- break;
- }
- in_block_offset += curr_dir->size;
- curr_offset += curr_dir->size;
- }
- return NULL;
-}
+ uint32_t lba = block_num * block_size / SECTOR_SIZE;
+ size_t sectors = block_size / SECTOR_SIZE;
-void ext2_create_entry(vfs_node_t *parent, char *entry_name, uint32_t entry_inode)
-{
- ext2_fs_t *ext2fs = parent->device;
- inode_t *p_inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, p_inode, parent->inode_num);
- uint32_t curr_offset = 0;
- uint32_t block_offset = 0;
- uint32_t in_block_offset = 0;
- uint32_t found = 0;
- uint32_t entry_name_len = strlen(entry_name);
- char *check = kcalloc(entry_name_len + 1, 1);
- char *block_buf = read_inode_block(ext2fs, p_inode, block_offset);
-
- while (curr_offset < p_inode->size) {
- if (in_block_offset >= ext2fs->block_size) {
- block_offset++;
- in_block_offset = 0;
- block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- }
- direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset);
- if (curr_dir->name_len == entry_name_len) {
- memcpy(check, curr_dir->name, entry_name_len);
- if (curr_dir->inode != 0 && !strcmp(entry_name, check)) {
- log("Entry by the same name %s already exist", check);
- return;
- }
- }
- if (found) {
- curr_dir->inode = entry_inode;
- curr_dir->size =
- (uint32_t)block_buf + ext2fs->block_size - (uint32_t)curr_dir;
- curr_dir->name_len = strlen(entry_name);
- curr_dir->type = 0;
- memcpy(curr_dir->name, entry_name, strlen(entry_name));
- write_inode_block(ext2fs, p_inode, block_offset, block_buf);
- in_block_offset += curr_dir->size;
- if (in_block_offset >= ext2fs->block_size) {
- block_offset++;
- in_block_offset = 0;
- block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- }
- curr_dir = (direntry_t *)(block_buf + in_block_offset);
- memset(curr_dir, 0, sizeof(direntry_t));
- write_inode_block(ext2fs, p_inode, block_offset, block_buf);
- return;
- }
- uint32_t expected_size =
- ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4;
- uint32_t real_size = curr_dir->size;
- if (real_size != expected_size) {
- found = 1;
- curr_dir->size = expected_size;
- in_block_offset += expected_size;
- curr_offset += expected_size;
- continue;
- }
- in_block_offset += curr_dir->size;
- curr_offset += curr_dir->size;
- }
+ read_abs_sectors(lba, sectors, buf);
}
-void ext2_remove_entry(vfs_node_t *parent, char *entry_name)
+static void load_superblock()
{
- ext2_fs_t *ext2fs = parent->device;
- inode_t *p_inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, p_inode, parent->inode_num);
- uint32_t curr_offset = 0;
- uint32_t block_offset = 0;
- uint32_t in_block_offset = 0;
- uint32_t entry_name_len = strlen(entry_name);
- char *check = kcalloc(entry_name_len + 1, 1);
- char *block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- while (curr_offset < p_inode->size) {
- if (in_block_offset >= ext2fs->block_size) {
- block_offset++;
- in_block_offset = 0;
- block_buf = read_inode_block(ext2fs, p_inode, block_offset);
- }
- direntry_t *curr_dir = (direntry_t *)(block_buf + in_block_offset);
- if (curr_dir->name_len == entry_name_len) {
- memcpy(check, curr_dir->name, entry_name_len);
- if (curr_dir->inode != 0 && !strcmp(entry_name, check)) {
- curr_dir->inode = 0;
- write_inode_block(ext2fs, p_inode, block_offset, block_buf);
- return;
- }
- }
- uint32_t expected_size =
- ((sizeof(direntry_t) + curr_dir->name_len) & 0xfffffffc) + 0x4;
- uint32_t real_size = curr_dir->size;
- if (real_size != expected_size)
- return;
- in_block_offset += curr_dir->size;
- curr_offset += curr_dir->size;
- }
-}
+ uint16_t buf[SUPERBLOCK_LENGTH / 2];
-void ext2_chmod(vfs_node_t *file, uint32_t mode)
-{
- ext2_fs_t *ext2fs = file->device;
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, file->inode_num);
- inode->permission = (inode->permission & 0xFFFFF000) | mode;
- write_inode_metadata(ext2fs, inode, file->inode_num);
-}
+ read_abs_sectors(SUPERBLOCK_LBA, SUPERBLOCK_SECTORS, buf);
+ memcpy(&superblock, buf, sizeof(struct ext2_superblock));
-uint32_t ext2_read(vfs_node_t *file, uint32_t offset, uint32_t size, char *buf)
-{
- ext2_fs_t *ext2fs = file->device;
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, file->inode_num);
- read_inode_filedata(ext2fs, inode, offset, size, buf);
- return size;
-}
+ block_size = 1024 << superblock.log2_block_size;
+ num_groups = superblock.total_blocks / superblock.blocks_per_group;
-uint32_t ext2_write(vfs_node_t *file, uint32_t offset, uint32_t size, char *buf)
-{
- ext2_fs_t *ext2fs = file->device;
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, file->inode_num);
- write_inode_filedata(ext2fs, inode, file->inode_num, offset, size, buf);
- return size;
+ assert(superblock.signature == EXT2_SIGNATURE);
+ log("Total inodes = 0x%x", superblock.total_inodes);
+ log("Total blocks = 0x%x", superblock.total_blocks);
+ log("Block size = %b", block_size);
+ log("Num blocks = %d", superblock.total_blocks);
+ log("Blocks/group = %d", superblock.blocks_per_group);
+ log("Inodes/group = %d", superblock.inodes_per_group);
+ log("Num groups = %d", num_groups);
}
-void ext2_open(vfs_node_t *file, uint32_t flags)
+static void load_bgdt()
{
- ext2_fs_t *ext2fs = file->device;
- if (flags & O_TRUNC) {
- inode_t *inode = kmalloc(sizeof(inode_t));
- read_inode_metadata(ext2fs, inode, file->inode_num);
- inode->size = 0;
- write_inode_metadata(ext2fs, inode, file->inode_num);
- }
-}
+ size_t bgdt_sectors = (sizeof(struct bgd) * num_groups) / SECTOR_SIZE + 1;
+ size_t bgdt_block = (SUPERBLOCK_OFFSET + SUPERBLOCK_LENGTH) / block_size + 1;
+ uint32_t bgdt_lba = bgdt_block * block_size / SECTOR_SIZE;
-void ext2_close()
-{
- return;
-}
+ uint16_t buf[bgdt_sectors * SECTOR_SIZE / 2];
+ read_abs_sectors(bgdt_lba, bgdt_sectors, buf);
-void read_inode_metadata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx)
-{
- uint32_t group = inode_idx / ext2fs->inodes_per_group;
- uint32_t inode_table_block = ext2fs->bgds[group].inode_table;
- uint32_t idx_in_group = inode_idx - group * ext2fs->inodes_per_group;
- uint32_t block_offset = (idx_in_group - 1) * ext2fs->sb->inode_size / ext2fs->block_size;
- uint32_t offset_in_block =
- (idx_in_group - 1) - block_offset * (ext2fs->block_size / ext2fs->sb->inode_size);
- char *block_buf = kmalloc(ext2fs->block_size);
- read_disk_block(ext2fs, inode_table_block + block_offset, block_buf);
- memcpy(inode, block_buf + offset_in_block * ext2fs->sb->inode_size, ext2fs->sb->inode_size);
- kfree(block_buf);
+ size_t bgdt_size = sizeof(struct bgd) * num_groups;
+ bgdt = kmalloc(bgdt_size);
+ memcpy(bgdt, buf, bgdt_size);
}
-void write_inode_metadata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx)
+static void read_inode(struct ext2_inode *inode, uint32_t inode_num)
{
- uint32_t group = inode_idx / ext2fs->inodes_per_group;
- uint32_t inode_table_block = ext2fs->bgds[group].inode_table;
- uint32_t block_offset = (inode_idx - 1) * ext2fs->sb->inode_size / ext2fs->block_size;
- uint32_t offset_in_block =
- (inode_idx - 1) - block_offset * (ext2fs->block_size / ext2fs->sb->inode_size);
- char *block_buf = kmalloc(ext2fs->block_size);
- read_disk_block(ext2fs, inode_table_block + block_offset, block_buf);
- memcpy(block_buf + offset_in_block * ext2fs->sb->inode_size, inode, ext2fs->sb->inode_size);
- write_disk_block(ext2fs, inode_table_block + block_offset, block_buf);
- kfree(block_buf);
-}
+ inode_num--;
+ size_t block_group = inode_num / superblock.inodes_per_group;
-uint32_t read_inode_filedata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t offset, uint32_t size,
- char *buf)
-{
- uint32_t end_offset = (inode->size >= offset + size) ? (offset + size) : (inode->size);
- uint32_t start_block = offset / ext2fs->block_size;
- uint32_t end_block = end_offset / ext2fs->block_size;
- uint32_t start_off = offset % ext2fs->block_size;
- uint32_t end_size = end_offset - end_block * ext2fs->block_size;
-
- uint32_t i = start_block;
- uint32_t curr_off = 0;
- while (i <= end_block) {
- uint32_t left = 0, right = ext2fs->block_size - 1;
- char *block_buf = read_inode_block(ext2fs, inode, i);
- if (i == start_block)
- left = start_off;
- if (i == end_block)
- right = end_size - 1;
- memcpy(buf + curr_off, block_buf + left, (right - left + 1));
- curr_off = curr_off + (right - left + 1);
- kfree(block_buf);
- i++;
- }
- return end_offset - offset;
-}
+ struct bgd *bgd = &bgdt[block_group];
+ uint32_t i_table_block = bgd->inode_table_addr;
-void write_inode_filedata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t offset,
- uint32_t size, char *buf)
-{
- if (offset + size > inode->size) {
- inode->size = offset + size;
- write_inode_metadata(ext2fs, inode, inode_idx);
- }
- uint32_t end_offset = (inode->size >= offset + size) ? (offset + size) : (inode->size);
- uint32_t start_block = offset / ext2fs->block_size;
- uint32_t end_block = end_offset / ext2fs->block_size;
- uint32_t start_off = offset % ext2fs->block_size;
- uint32_t end_size = end_offset - end_block * ext2fs->block_size;
-
- uint32_t i = start_block;
- uint32_t curr_off = 0;
- while (i <= end_block) {
- uint32_t left = 0, right = ext2fs->block_size;
- char *block_buf = read_inode_block(ext2fs, inode, i);
-
- if (i == start_block)
- left = start_off;
- if (i == end_block)
- right = end_size - 1;
- memcpy(block_buf + left, buf + curr_off, (right - left + 1));
- curr_off = curr_off + (right - left + 1);
- write_inode_block(ext2fs, inode, i, block_buf);
- kfree(block_buf);
- i++;
- }
-}
+ size_t index = inode_num % superblock.inodes_per_group;
+ size_t block_offset = (index * INODE_SIZE) / block_size;
+ size_t offset_in_block = (index * INODE_SIZE) % block_size;
+ size_t block = i_table_block + block_offset;
-char *read_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t iblock)
-{
- char *buf = kmalloc(ext2fs->block_size);
- uint32_t disk_block = get_disk_block_number(ext2fs, inode, iblock);
- read_disk_block(ext2fs, disk_block, buf);
- return buf;
+ size_t num_sectors = sizeof(struct ext2_inode) / SECTOR_SIZE + 1;
+ uint16_t buf[num_sectors * SECTOR_SIZE / 2];
+ read_abs_sectors(block * block_size / SECTOR_SIZE, num_sectors, buf);
+ memcpy(inode, &buf[offset_in_block / 2], sizeof(struct ext2_inode));
}
-void write_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t iblock, char *buf)
+void ext2_open_inode(uint32_t inode_num, struct ext2_file *file)
{
- uint32_t disk_block = get_disk_block_number(ext2fs, inode, iblock);
- write_disk_block(ext2fs, disk_block, buf);
-}
+ read_inode(&file->inode, inode_num);
+ file->pos = 0;
+ file->block_index = 0;
+ file->buf = kmalloc(block_size);
+ file->curr_block_pos = 0;
-void read_disk_block(ext2_fs_t *ext2fs, uint32_t block, char *buf)
-{
- vfs_read(ext2fs->disk_device, ext2fs->block_size * block, ext2fs->block_size, buf);
+ read_block(file->inode.dbp[0], file->buf);
}
-void write_disk_block(ext2_fs_t *ext2fs, uint32_t block, char *buf)
+size_t ext2_read(struct ext2_file *file, uint8_t *buf, size_t count)
{
- vfs_write(ext2fs->disk_device, ext2fs->block_size * block, ext2fs->block_size, buf);
-}
+ if (file->pos + count > file->inode.size)
+ count = file->inode.size - file->pos;
-void rewrite_bgds(ext2_fs_t *ext2fs)
-{
- for (uint32_t i = 0; i < ext2fs->bgd_blocks; i++)
- write_disk_block(ext2fs, 2, (void *)ext2fs->bgds + i * ext2fs->block_size);
-}
+ size_t bytes_left = count;
-void rewrite_superblock(ext2_fs_t *ext2fs)
-{
- write_disk_block(ext2fs, 1, (void *)ext2fs->sb);
-}
+ while (bytes_left > 0) {
+ size_t to_copy = bytes_left;
-int alloc_inode_metadata_block(uint32_t *block_ptr, ext2_fs_t *ext2fs, inode_t *inode,
- uint32_t inode_idx, char *buffer, unsigned int block_overwrite)
-{
- if (!(*block_ptr)) {
- unsigned int block_no = ext2_alloc_block(ext2fs);
- if (!block_no)
- return 0;
- *block_ptr = block_no;
- if (buffer)
- write_disk_block(ext2fs, block_overwrite, (void *)buffer);
- else
- write_inode_metadata(ext2fs, inode, inode_idx);
- return 1;
- }
- return 0;
-}
+ bool new_block = file->curr_block_pos + to_copy >= block_size;
+ if (new_block)
+ to_copy = block_size - file->curr_block_pos;
-uint32_t get_disk_block_number(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_block)
-{
- unsigned int p = ext2fs->block_size / 4;
- int a, b, c, d, e, f, g;
- uint32_t *tmp = kmalloc(ext2fs->block_size);
- uint32_t ret = -1;
- a = inode_block - EXT2_DIRECT_BLOCKS;
- if (a < 0) {
- ret = inode->blocks[inode_block];
- goto done;
- }
- b = a - p;
- if (b < 0) {
- read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS], (void *)tmp);
- ret = tmp[a];
- goto done;
- }
- c = b - p * p;
- if (c < 0) {
- c = b / p;
- d = b - c * p;
- read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 1], (void *)tmp);
- read_disk_block(ext2fs, tmp[c], (void *)tmp);
- ret = tmp[d];
- goto done;
- }
- d = c - p * p * p;
- if (d < 0) {
- e = c / (p * p);
- f = (c - e * p * p) / p;
- g = (c - e * p * p - f * p);
- read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 2], (void *)tmp);
- read_disk_block(ext2fs, tmp[e], (void *)tmp);
- read_disk_block(ext2fs, tmp[f], (void *)tmp);
- ret = tmp[g];
- goto done;
- }
-done:
- kfree(tmp);
- return ret;
-}
+ memcpy(buf + (count - bytes_left), file->buf + file->curr_block_pos, to_copy);
+ file->curr_block_pos += to_copy;
+ file->pos += to_copy;
+ bytes_left -= to_copy;
-void set_disk_block_number(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx,
- uint32_t inode_block, uint32_t disk_block)
-{
- unsigned int p = ext2fs->block_size / 4;
- int a, b, c, d, e, f, g;
- int iblock = inode_block;
- uint32_t *tmp = kmalloc(ext2fs->block_size);
-
- a = iblock - EXT2_DIRECT_BLOCKS;
- if (a <= 0) {
- inode->blocks[inode_block] = disk_block;
- goto done;
- }
- b = a - p;
- if (b <= 0) {
- if (!alloc_inode_metadata_block(&(inode->blocks[EXT2_DIRECT_BLOCKS]), ext2fs, inode,
- inode_idx, NULL, 0))
- ;
- read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS], (void *)tmp);
- ((unsigned int *)tmp)[a] = disk_block;
- write_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS], (void *)tmp);
- tmp[a] = disk_block;
- goto done;
- }
- c = b - p * p;
- if (c <= 0) {
- c = b / p;
- d = b - c * p;
- if (!alloc_inode_metadata_block(&(inode->blocks[EXT2_DIRECT_BLOCKS + 1]), ext2fs,
- inode, inode_idx, NULL, 0))
- ;
- read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 1], (void *)tmp);
- if (!alloc_inode_metadata_block(&(tmp[c]), ext2fs, inode, inode_idx, (void *)tmp,
- inode->blocks[EXT2_DIRECT_BLOCKS + 1]))
- ;
- unsigned int temp = tmp[c];
- read_disk_block(ext2fs, temp, (void *)tmp);
- tmp[d] = disk_block;
- write_disk_block(ext2fs, temp, (void *)tmp);
- goto done;
- }
- d = c - p * p * p;
- if (d <= 0) {
- e = c / (p * p);
- f = (c - e * p * p) / p;
- g = (c - e * p * p - f * p);
- if (!alloc_inode_metadata_block(&(inode->blocks[EXT2_DIRECT_BLOCKS + 2]), ext2fs,
- inode, inode_idx, NULL, 0))
- ;
- read_disk_block(ext2fs, inode->blocks[EXT2_DIRECT_BLOCKS + 2], (void *)tmp);
- if (!alloc_inode_metadata_block(&(tmp[e]), ext2fs, inode, inode_idx, (void *)tmp,
- inode->blocks[EXT2_DIRECT_BLOCKS + 2]))
- ;
- unsigned int temp = tmp[e];
- read_disk_block(ext2fs, tmp[e], (void *)tmp);
- if (!alloc_inode_metadata_block(&(tmp[f]), ext2fs, inode, inode_idx, (void *)tmp,
- temp))
- ;
- temp = tmp[f];
- read_disk_block(ext2fs, tmp[f], (void *)tmp);
- tmp[g] = disk_block;
- write_disk_block(ext2fs, temp, (void *)tmp);
- goto done;
- }
-done:
- kfree(tmp);
-}
+ if (new_block) {
+ file->curr_block_pos = 0;
+ file->block_index++;
+ if (file->block_index >= 12)
+ panic("Indirect block pointers are currently unsupported");
-uint32_t ext2_alloc_block(ext2_fs_t *ext2fs)
-{
- uint32_t *buf = kcalloc(ext2fs->block_size, 1);
- for (uint32_t i = 0; i < ext2fs->total_groups; i++) {
- if (!ext2fs->bgds[i].free_blocks)
- continue;
-
- uint32_t bitmap_block = ext2fs->bgds[i].block_bitmap;
- read_disk_block(ext2fs, bitmap_block, (void *)buf);
- for (uint32_t j = 0; j < ext2fs->block_size / 4; j++) {
- uint32_t sub_bitmap = buf[j];
- if (sub_bitmap == 0xFFFFFFFF)
- continue;
- for (uint32_t k = 0; k < 32; k++) {
- uint32_t free = !((sub_bitmap >> k) & 0x1);
- if (free) {
- uint32_t mask = (0x1 << k);
- buf[j] = buf[j] | mask;
- write_disk_block(ext2fs, bitmap_block, (void *)buf);
- ext2fs->bgds[i].free_blocks--;
- rewrite_bgds(ext2fs);
- return i * ext2fs->blocks_per_group + j * 32 + k;
- }
- }
+ read_block(file->inode.dbp[file->block_index], file->buf);
}
}
- panic("We're out of blocks!");
- return (uint32_t)-1;
+
+ return count;
}
-void ext2_free_block(ext2_fs_t *ext2fs, uint32_t block)
+#define READ_SIZE (sizeof(struct ext2_dirent) - sizeof(uint8_t *))
+
+bool ext2_next_dirent(struct ext2_file *file, struct ext2_dirent *dir)
{
- uint32_t *buf = kcalloc(ext2fs->block_size, 1);
- uint32_t group_idx = block / ext2fs->blocks_per_group;
- uint32_t sub_bitmap_idx = (block - (ext2fs->blocks_per_group * group_idx)) / 4;
- uint32_t idx = (block - (ext2fs->blocks_per_group * group_idx)) % 4;
+ uint8_t buf[READ_SIZE];
+ if (ext2_read(file, buf, READ_SIZE) != READ_SIZE)
+ return false;
- uint32_t bitmap_block = ext2fs->bgds[group_idx].block_bitmap;
- read_disk_block(ext2fs, bitmap_block, (void *)buf);
+ memcpy(dir, buf, READ_SIZE);
- uint32_t mask = ~(0x1 << idx);
- buf[sub_bitmap_idx] = buf[sub_bitmap_idx] & mask;
+ size_t size = dir->name_len + 1;
+ uint8_t *name = kmalloc(size);
+ if (ext2_read(file, name, size - 1) != size - 1)
+ return false;
- write_disk_block(ext2fs, bitmap_block, (void *)buf);
+ dir->name = name;
+ dir->name[size - 1] = '\0';
- ext2fs->bgds[group_idx].free_blocks++;
- rewrite_bgds(ext2fs);
-}
+ size_t bytes_left = dir->total_len - (READ_SIZE + size - 1);
+ if (bytes_left > 0) {
+ uint8_t dummy[bytes_left];
+ ext2_read(file, dummy, bytes_left);
+ }
-void alloc_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t block)
-{
- uint32_t ret = ext2_alloc_block(ext2fs);
- set_disk_block_number(ext2fs, inode, inode_idx, block, ret);
- inode->num_sectors = (block + 1) * (ext2fs->block_size / 512);
- write_inode_metadata(ext2fs, inode, inode_idx);
+ return true;
}
-void free_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t block)
+uint32_t ext2_find_in_dir(uint32_t dir_inode, const char *name)
{
- uint32_t ret = get_disk_block_number(ext2fs, inode, block);
- ext2_free_block(ext2fs, ret);
- set_disk_block_number(ext2fs, inode, inode_idx, ret, 0);
- write_inode_metadata(ext2fs, inode, inode_idx);
-}
+ uint32_t inode;
+ struct ext2_file dir;
+ struct ext2_dirent dirent;
-uint32_t alloc_inode(ext2_fs_t *ext2fs)
-{
- uint32_t *buf = kcalloc(ext2fs->block_size, 1);
- for (uint32_t i = 0; i < ext2fs->total_groups; i++) {
- if (!ext2fs->bgds[i].free_inodes)
- continue;
-
- uint32_t bitmap_block = ext2fs->bgds[i].inode_bitmap;
- read_disk_block(ext2fs, bitmap_block, (void *)buf);
- for (uint32_t j = 0; j < ext2fs->block_size / 4; j++) {
- uint32_t sub_bitmap = buf[j];
- if (sub_bitmap == 0xFFFFFFFF)
- continue;
- for (uint32_t k = 0; k < 32; k++) {
- uint32_t free = !((sub_bitmap >> k) & 0x1);
- if (free) {
- uint32_t mask = (0x1 << k);
- buf[j] = buf[j] | mask;
- write_disk_block(ext2fs, bitmap_block, (void *)buf);
- ext2fs->bgds[i].free_inodes--;
- rewrite_bgds(ext2fs);
- return i * ext2fs->inodes_per_group + j * 32 + k;
- }
- }
+ ext2_open_inode(dir_inode, &dir);
+ while (ext2_next_dirent(&dir, &dirent)) {
+ if (strcmp((char *)dirent.name, name) == 0) {
+ inode = dirent.inode_num;
+ goto cleanup;
}
}
- panic("We're out of inodes!");
- return (uint32_t)-1;
+
+ inode = 0;
+
+cleanup:
+ kfree(dir.buf);
+ return inode;
}
-void free_inode(ext2_fs_t *ext2fs, uint32_t inode)
+uint32_t ext2_look_up_path(char *path)
{
- uint32_t *buf = kcalloc(ext2fs->block_size, 1);
- uint32_t group_idx = inode / ext2fs->inodes_per_group;
- uint32_t sub_bitmap_idx = (inode - (ext2fs->inodes_per_group * group_idx)) / 4;
- uint32_t idx = (inode - (ext2fs->inodes_per_group * group_idx)) % 4;
+ if (path[0] != '/')
+ return 0;
- uint32_t bitmap_block = ext2fs->bgds[group_idx].inode_bitmap;
- read_disk_block(ext2fs, bitmap_block, (void *)buf);
+ path++;
+ uint32_t curr_dir_inode = ROOT_INODE;
- uint32_t mask = ~(0x1 << idx);
- buf[sub_bitmap_idx] = buf[sub_bitmap_idx] & mask;
+ for (;;) {
+ size_t j;
+ for (j = 0; path[j] != '/' && path[j] != '\0'; j++)
+ ;
- write_disk_block(ext2fs, bitmap_block, (void *)buf);
+ if (path[j] == '\0')
+ break;
- ext2fs->bgds[group_idx].free_inodes++;
- rewrite_bgds(ext2fs);
-}
+ path[j] = '\0';
+ curr_dir_inode = ext2_find_in_dir(curr_dir_inode, path);
+ path[j] = '/';
-vfs_node_t *get_ext2_root(ext2_fs_t *ext2fs, inode_t *inode)
-{
- vfs_node_t *ext2root = kcalloc(sizeof(vfs_node_t), 1);
- strcpy(ext2root->name, "/");
- ext2root->device = ext2fs;
- ext2root->mask = inode->permission;
- ext2root->inode_num = ROOT_INODE_NUMBER;
-
- ext2root->access_time = inode->atime;
- ext2root->modified_time = inode->mtime;
- ext2root->create_time = inode->ctime;
-
- ext2root->flags |= FS_DIRECTORY;
- ext2root->read = NULL;
- ext2root->write = NULL;
- ext2root->chmod = ext2_chmod;
- ext2root->open = ext2_open;
- ext2root->close = ext2_close;
- ext2root->read = ext2_read;
- ext2root->write = ext2_write;
- ext2root->mkdir = ext2_mkdir;
- ext2root->create = ext2_mkfile;
- ext2root->listdir = ext2_listdir;
- ext2root->finddir = ext2_finddir;
- ext2root->unlink = ext2_unlink;
- return ext2root;
-}
+ if (curr_dir_inode == 0)
+ return 0;
-void ext2_init(char *device_path, char *mountpoint)
-{
- ext2_fs_t *ext2fs = kcalloc(sizeof(ext2_fs_t), 1);
- ext2fs->disk_device = file_open(device_path, 0);
- log("%s", ext2fs->disk_device->name);
- ext2fs->sb = kmalloc(SUPERBLOCK_SIZE);
- ext2fs->block_size = 1024;
- read_disk_block(ext2fs, 1, (void *)ext2fs->sb); //!
- log("%x", ext2fs->sb->ext2_magic);
- log("%x", ext2fs->sb->total_inodes);
- ext2fs->block_size = (1024 << ext2fs->sb->log2block_size);
- ext2fs->blocks_per_group = ext2fs->sb->blocks_per_group;
- ext2fs->inodes_per_group = ext2fs->sb->inodes_per_group;
-
- ext2fs->total_groups = ext2fs->sb->total_blocks /
- ext2fs->blocks_per_group; // REMEMBER: Zero Division Exception
- if (ext2fs->blocks_per_group * ext2fs->total_groups < ext2fs->total_groups)
- ext2fs->total_groups++;
-
- ext2fs->bgd_blocks = (ext2fs->total_groups * sizeof(bgd_t)) / ext2fs->block_size;
- if (ext2fs->bgd_blocks * ext2fs->block_size < ext2fs->total_groups * sizeof(bgd_t))
- ext2fs->bgd_blocks++;
-
- ext2fs->bgds = kcalloc(sizeof(bgd_t), ext2fs->bgd_blocks * ext2fs->block_size);
- for (uint32_t i = 0; i < ext2fs->bgd_blocks; i++) {
- read_disk_block(ext2fs, 2, (void *)ext2fs->bgds + i * ext2fs->block_size);
+ path += j + 1;
}
- inode_t *root_inode = kcalloc(sizeof(inode_t), 1);
- read_inode_metadata(ext2fs, root_inode, ROOT_INODE_NUMBER);
- vfs_mount(mountpoint, get_ext2_root(ext2fs, root_inode));
+ uint32_t inode = ext2_find_in_dir(curr_dir_inode, path);
+ if (inode == 0)
+ return 0;
+
+ return inode;
} \ No newline at end of file
diff --git a/src/kernel/fs/ext2.h b/src/kernel/fs/ext2.h
index 562d96c..e5e0f1c 100644
--- a/src/kernel/fs/ext2.h
+++ b/src/kernel/fs/ext2.h
@@ -2,210 +2,139 @@
#define MELVIX_EXT2_H
#include <stdint.h>
-#include <kernel/fs/vfs.h>
+#include <stddef.h>
+#include <stdbool.h>
-#define EXT2_DIRECT_BLOCKS 12
+#define ROOT_INODE 2
-#define SUPERBLOCK_SIZE 1024
-#define ROOT_INODE_NUMBER 2
+#define EXT2_SIGNATURE 0xEF53
+#define INODE_SIZE 128
-#define EXT2_S_IFSOCK 0xC000
-#define EXT2_S_IFLNK 0xA000
-#define EXT2_S_IFREG 0x8000
-#define EXT2_S_IFBLK 0x6000
-#define EXT2_S_IFDIR 0x4000
-#define EXT2_S_IFCHR 0x2000
-#define EXT2_S_IFIFO 0x1000
+#define SUPERBLOCK_OFFSET 1024
+#define SUPERBLOCK_LENGTH 1024
-// http://wiki.osdev.org/Ext2#Locating_the_Superblock
-typedef struct superblock {
+#define SUPERBLOCK_LBA (SUPERBLOCK_OFFSET / SECTOR_SIZE)
+#define SUPERBLOCK_SECTORS (SUPERBLOCK_LENGTH / SECTOR_SIZE)
+
+struct ext2_superblock {
uint32_t total_inodes;
uint32_t total_blocks;
- uint32_t su_blocks;
+ uint32_t su_res_blocks; // Superuser reserved
uint32_t free_blocks;
uint32_t free_inodes;
- uint32_t superblock_idx;
- uint32_t log2block_size;
- uint32_t log2frag_size;
+ uint32_t superblock_block_num;
+ uint32_t log2_block_size;
+ uint32_t log2_frag_size;
uint32_t blocks_per_group;
uint32_t frags_per_group;
uint32_t inodes_per_group;
+ uint32_t last_mount_time;
+ uint32_t last_write_time;
+ uint16_t mounts_since_fsck;
+ uint16_t max_mounts_since_fsck;
+ uint16_t signature;
+ uint16_t state;
+ uint16_t error_action;
+ uint16_t minor_version;
+ uint32_t last_fsck_time;
+ uint32_t max_time_since_fsck;
+ uint32_t creator_OS_id;
+ uint32_t major_version;
+ uint16_t res_block_uid;
+ uint16_t res_block_gid;
+} __attribute__((packed));
+
+// Block group descriptor
+struct bgd {
+ uint32_t block_bitmap_addr;
+ uint32_t inode_bitmap_addr;
+ uint32_t inode_table_addr;
+ uint16_t free_blocks;
+ uint16_t free_inodes;
+ uint16_t used_dirs;
+ uint16_t pad;
+ uint8_t bg_reserved[12];
+} __attribute__((packed));
+
+struct ext2_inode {
+ uint16_t type_and_permissions;
+ uint16_t uid;
+ uint32_t size;
- uint32_t mtime;
- uint32_t wtime;
-
- uint16_t mount_count;
- uint16_t mount_allowed_count;
- uint16_t ext2_magic;
- uint16_t fs_state;
- uint16_t err;
- uint16_t minor;
-
- uint32_t last_check;
- uint32_t interval;
- uint32_t os_id;
- uint32_t major;
-
- uint16_t r_userid;
- uint16_t r_groupid;
-
- // Extensions
- uint32_t first_inode;
- uint16_t inode_size;
- uint16_t superblock_group;
- uint32_t optional_feature;
- uint32_t required_feature;
- uint32_t readonly_feature;
- char fs_id[16];
- char vol_name[16];
- char last_mount_path[64];
- uint32_t compression_method;
- uint8_t file_pre_alloc_blocks;
- uint8_t dir_pre_alloc_blocks;
- uint16_t unused1;
- char journal_id[16];
- uint32_t journal_inode;
- uint32_t journal_device;
- uint32_t orphan_head;
-
- char unused2[1024 - 236];
-} __attribute__((packed)) superblock_t;
-
-typedef struct bgd {
- uint32_t block_bitmap;
- uint32_t inode_bitmap;
- uint32_t inode_table;
- uint32_t free_blocks;
- uint32_t free_inodes;
- uint32_t num_dirs;
- uint32_t unused1;
- uint32_t unused2;
-} __attribute__((packed)) bgd_t;
-
-typedef struct direntry {
- uint32_t inode;
- uint16_t size;
- uint8_t name_len;
- uint8_t type;
- char name[];
-} __attribute__((packed)) direntry_t;
+ uint32_t last_access_time;
+ uint32_t creation_time;
+ uint32_t last_modification_time;
+ uint32_t deletion_time;
-typedef struct inode {
- uint16_t permission;
- uint16_t userid;
- uint32_t size;
- uint32_t atime;
- uint32_t ctime;
- uint32_t mtime;
- uint32_t dtime;
uint16_t gid;
- uint16_t hard_links;
- uint32_t num_sectors;
+ uint16_t link_count;
+ uint32_t sectors_used;
uint32_t flags;
- uint32_t os_specific1;
- uint32_t blocks[EXT2_DIRECT_BLOCKS + 3];
- uint32_t generation;
- uint32_t file_acl;
- union {
- uint32_t dir_acl;
- uint32_t size_high;
- };
- uint32_t f_block_addr;
- char os_specific2[12];
-} __attribute__((packed)) inode_t;
-
-typedef struct ext2_cache {
- uint32_t block;
- uint32_t times;
- uint8_t dirty;
- char *block_data;
-} ext2_cache_t;
-
-typedef struct ext2_fs {
- vfs_node_t *disk_device;
-
- superblock_t *sb;
- bgd_t *bgds;
- uint32_t block_size;
- uint32_t blocks_per_group;
- uint32_t inodes_per_group;
- uint32_t total_groups;
-
- uint32_t bgd_blocks;
-} ext2_fs_t;
-
-uint32_t ext2_file_size(vfs_node_t *node);
-
-void ext2_mkdir(vfs_node_t *parent, char *name, uint16_t permission);
-
-void ext2_mkfile(vfs_node_t *parent, char *name, uint16_t permission);
-
-void ext2_create_entry(vfs_node_t *parent, char *entry_name, uint32_t entry_inode);
-
-void ext2_unlink(vfs_node_t *parent, char *name);
-
-char **ext2_listdir(vfs_node_t *parent);
-
-vfs_node_t *ext2_finddir(vfs_node_t *parent, char *name);
-
-void ext2_create_entry(vfs_node_t *parent, char *entry_name, uint32_t entry_inode);
-
-void ext2_remove_entry(vfs_node_t *parent, char *entry_name);
-
-void ext2_chmod(vfs_node_t *file, uint32_t mode);
-
-uint32_t ext2_read(vfs_node_t *file, uint32_t offset, uint32_t size, char *buf);
-
-uint32_t ext2_write(vfs_node_t *file, uint32_t offset, uint32_t size, char *buf);
-
-void ext2_open(vfs_node_t *file, uint32_t flags);
-
-void ext2_close();
-
-void read_inode_metadata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx);
-
-void write_inode_metadata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx);
-
-uint32_t read_inode_filedata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t offset, uint32_t size,
- char *buf);
-
-void write_inode_filedata(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t offset,
- uint32_t size, char *buf);
-
-char *read_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t iblock);
-
-void write_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t iblock, char *buf);
-
-void read_disk_block(ext2_fs_t *ext2fs, uint32_t block, char *buf);
-
-void write_disk_block(ext2_fs_t *ext2fs, uint32_t block, char *buf);
-
-void rewrite_bgds(ext2_fs_t *ext2fs);
-
-void rewrite_superblock(ext2_fs_t *ext2fs);
-
-int alloc_inode_metadata_block(uint32_t *block_ptr, ext2_fs_t *ext2fs, inode_t *inode,
- uint32_t inode_idx, char *buffer, unsigned int block_overwrite);
-
-uint32_t get_disk_block_number(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_block);
-
-void set_disk_block_number(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx,
- uint32_t inode_block, uint32_t disk_block);
-
-uint32_t ext2_alloc_block(ext2_fs_t *ext2fs);
-
-void ext2_free_block(ext2_fs_t *ext2fs, uint32_t block);
-
-void alloc_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t block);
-
-void free_inode_block(ext2_fs_t *ext2fs, inode_t *inode, uint32_t inode_idx, uint32_t block);
-
-uint32_t alloc_inode(ext2_fs_t *ext2fs);
-
-void free_inode(ext2_fs_t *ext2fs, uint32_t inode);
-
-vfs_node_t *get_ext2_root(ext2_fs_t *ext2fs, inode_t *inode);
-
-void ext2_init(char *device_path, char *mountpoint);
+ uint32_t os_specific_val1;
+ uint32_t dbp[12];
+ uint32_t ibp;
+ uint32_t dibp;
+ uint32_t tibp;
+ uint32_t gen_number;
+
+ uint32_t reserved1;
+ uint32_t reserved2;
+
+ uint32_t fragment_addr;
+ uint8_t os_specific_val2[12];
+} __attribute__((packed));
+
+#define S_IFIFO 0x1000
+#define S_IFCHR 0x2000
+#define S_IFDIR 0x4000
+#define S_IFBLK 0x6000
+#define S_IFREG 0x8000
+#define S_IFLNK 0xA000
+#define S_IFSOCK 0xC000
+
+#define S_ISUID 04000
+#define S_ISGID 02000
+#define S_ISTICK 01000
+#define S_IRUSR 00400
+#define S_IWUSR 00200
+#define S_IXUSR 00100
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+
+#define SECURE_DELETE 0x00001
+#define UNDELETE 0x00002
+#define COMPRESSED 0x00004
+#define SYNCRONOUS 0x00008
+#define IMMUTABLE 0x00010
+#define APPEND_ONLY 0x00020
+#define DUMP_IGNORE 0x00040
+#define NO_UPDATE_ACCESS 0x00080
+
+struct ext2_dirent {
+ uint32_t inode_num;
+ uint16_t total_len;
+ uint8_t name_len;
+ uint8_t type_indicator;
+ uint8_t *name;
+} __attribute__((packed));
+
+struct ext2_file {
+ struct ext2_inode inode;
+ size_t pos;
+ uint8_t block_index;
+ uint8_t *buf;
+ size_t curr_block_pos;
+};
+
+void ext2_init_fs();
+void ext2_open_inode(uint32_t inode_num, struct ext2_file *file);
+size_t ext2_read(struct ext2_file *file, uint8_t *buf, size_t count);
+bool ext2_next_dirent(struct ext2_file *file, struct ext2_dirent *dir);
+uint32_t ext2_find_in_dir(uint32_t dir_inode, const char *name);
+uint32_t ext2_look_up_path(char *path);
#endif \ No newline at end of file
diff --git a/src/kernel/fs/vfs.c b/src/kernel/fs/vfs.c
deleted file mode 100644
index afe3780..0000000
--- a/src/kernel/fs/vfs.c
+++ /dev/null
@@ -1,369 +0,0 @@
-#include <kernel/system.h>
-#include <kernel/fs/vfs.h>
-#include <kernel/lib/data/list.h>
-#include <kernel/lib/data/generic_tree.h>
-#include <kernel/memory/alloc.h>
-#include <kernel/lib/stdlib.h>
-#include <kernel/lib/lib.h>
-
-gtree_t *vfs_tree;
-vfs_node_t *vfs_root;
-
-uint32_t vfs_get_file_size(vfs_node_t *node)
-{
- if (node && node->get_file_size) {
- return node->get_file_size(node);
- }
- return 0;
-}
-
-void vfs_db_listdir(char *name)
-{
- vfs_node_t *n = file_open(name, 0);
- if (!n) {
- log("Could not list a directory that does not exist");
- return;
- }
- if (!n->listdir)
- return;
- char **files = n->listdir(n);
- char **save = files;
- while (*files) {
- log("%s ", *files);
- kfree(*files);
- files++;
- }
- kfree(save);
-}
-
-void print_vfstree_recur(gtreenode_t *node, int parent_offset)
-{
- if (!node)
- return;
- char *tmp = kmalloc(512);
- int len = 0;
- memset(tmp, 0, 512);
- for (int i = 0; i < parent_offset; ++i) {
- strcat(tmp, " ");
- }
- struct vfs_entry *fnode = (struct vfs_entry *)node->value;
- if (fnode->file) {
- log("%s(0x%x, %s)", fnode->name, (uint32_t)fnode->file, fnode->file->name);
- } else {
- log("%s(empty)", fnode->name);
- }
- log("%s", tmp);
- len = strlen(fnode->name);
- kfree(tmp);
- foreach(child, node->children)
- {
- print_vfstree_recur(child->val, parent_offset + len + 1);
- }
-}
-
-void print_vfstree()
-{
- print_vfstree_recur(vfs_tree->root, 0);
-}
-
-uint32_t vfs_read(vfs_node_t *node, uint32_t offset, uint32_t size, char *buffer)
-{
- if (node && node->read) {
- uint32_t ret = node->read(node, offset, size, buffer);
- return ret;
- }
- return -1;
-}
-
-uint32_t vfs_write(vfs_node_t *node, uint32_t offset, uint32_t size, char *buffer)
-{
- if (node && node->write) {
- uint32_t ret = node->write(node, offset, size, buffer);
- return ret;
- }
- return -1;
-}
-
-void vfs_open(struct vfs_node *node, uint32_t flags)
-{
- if (!node)
- return;
- if (node->refcount >= 0)
- node->refcount++;
- node->open(node, flags);
-}
-
-void vfs_close(vfs_node_t *node)
-{
- if (!node || node == vfs_root || node->refcount == -1)
- return;
- node->refcount--;
- if (node->refcount == 0)
- node->close(node);
-}
-
-void vfs_chmod(vfs_node_t *node, uint32_t mode)
-{
- if (node->chmod)
- return node->chmod(node, mode);
-}
-
-struct dirent *vfs_readdir(vfs_node_t *node, uint32_t index)
-{
- if (node && (node->flags & FS_DIRECTORY) && node->readdir)
- return node->readdir(node, index);
- return NULL;
-}
-
-vfs_node_t *vfs_finddir(vfs_node_t *node, char *name)
-{
- if (node && (node->flags & FS_DIRECTORY) && node->finddir)
- return node->finddir(node, name);
- return NULL;
-}
-
-int vfs_ioctl(vfs_node_t *node, int request, void *argp)
-{
- if (!node)
- return -1;
- if (node->ioctl)
- return node->ioctl(node, request, argp);
- return -1; // ENOTTY
-}
-
-void vfs_mkdir(char *name, unsigned short permission)
-{
- // Find parent directory
- int i = strlen(name);
- char *dirname = strdup(name);
- char *save_dirname = dirname;
- char *parent_path = "/";
- while (i >= 0) {
- if (dirname[i] == '/') {
- if (i != 0) {
- dirname[i] = '\0';
- parent_path = dirname;
- }
- dirname = &dirname[i + 1];
- break;
- }
- i--;
- }
-
- // Open file
- vfs_node_t *parent_node = file_open(parent_path, 0);
- if (!parent_node) {
- kfree(save_dirname);
- }
-
- // mkdir
- if (parent_node->mkdir)
- parent_node->mkdir(parent_node, dirname, permission);
- kfree(save_dirname);
-
- vfs_close(parent_node);
-}
-
-int vfs_create_file(char *name, unsigned short permission)
-{
- // Find parent directory
- int i = strlen(name);
- char *dirname = strdup(name);
- char *save_dirname = dirname;
- char *parent_path = "/";
- while (i >= 0) {
- if (dirname[i] == '/') {
- if (i != 0) {
- dirname[i] = '\0';
- parent_path = dirname;
- }
- dirname = &dirname[i + 1];
- break;
- }
- i--;
- }
-
- // Open file
- vfs_node_t *parent_node = file_open(parent_path, 0);
- if (!parent_node) {
- kfree(save_dirname);
- return -1;
- }
- if (parent_node->create)
- parent_node->create(parent_node, dirname, permission);
- kfree(save_dirname);
- vfs_close(parent_node);
- return 0;
-}
-
-void vfs_unlink(char *name)
-{
- // Find parent directory
- int i = strlen(name);
- char *dirname = strdup(name);
- char *save_dirname = dirname;
- char *parent_path = "/";
- while (i >= 0) {
- if (dirname[i] == '/') {
- if (i != 0) {
- dirname[i] = '\0';
- parent_path = dirname;
- }
- dirname = &dirname[i + 1];
- break;
- }
- i--;
- }
-
- // Open file
- vfs_node_t *parent_node = file_open(parent_path, 0);
- if (!parent_node) {
- kfree(save_dirname);
- }
- if (parent_node->unlink)
- parent_node->unlink(parent_node, dirname);
- kfree(save_dirname);
- vfs_close(parent_node);
-}
-
-char *expand_path(char *input)
-{
- list_t *input_list = str_split(input, "/", NULL);
- char *ret = list2str(input_list, "/");
- return ret;
-}
-
-vfs_node_t *get_mountpoint_recur(char **path, gtreenode_t *subroot)
-{
- int found = 0;
- char *curr_token = strsep(path, "/");
- if (curr_token == NULL || !strcmp(curr_token, "")) {
- struct vfs_entry *ent = (struct vfs_entry *)subroot->value;
- return ent->file;
- }
- foreach(child, subroot->children)
- {
- gtreenode_t *tchild = (gtreenode_t *)child->val;
- struct vfs_entry *ent = (struct vfs_entry *)(tchild->value);
- if (strcmp(ent->name, curr_token) == 0) {
- found = 1;
- subroot = tchild;
- break;
- }
- }
-
- if (!found) {
- *path = curr_token;
- return ((struct vfs_entry *)(subroot->value))->file;
- }
- return get_mountpoint_recur(path, subroot);
-}
-
-vfs_node_t *get_mountpoint(char **path)
-{
- if (strlen(*path) > 1 && (*path)[strlen(*path) - 1] == '/')
- *(path)[strlen(*path) - 1] = '\0';
- if (!*path || *(path)[0] != '/')
- return NULL;
- if (strlen(*path) == 1) {
- *path = '\0';
- struct vfs_entry *ent = (struct vfs_entry *)vfs_tree->root->value;
- return ent->file;
- }
- (*path)++;
- return get_mountpoint_recur(path, vfs_tree->root);
-}
-
-vfs_node_t *file_open(const char *file_name, uint32_t flags)
-{
- char *curr_token = NULL;
- char *filename = strdup(file_name);
- char *free_filename = filename;
- char *save = strdup(filename);
- char *original_filename = filename;
- char *new_start = NULL;
- vfs_node_t *nextnode = NULL;
- vfs_node_t *startpoint = get_mountpoint(&filename);
- if (!startpoint)
- return NULL;
- if (filename)
- new_start = strstr(save + (filename - original_filename), filename);
- while (filename != NULL && ((curr_token = strsep(&new_start, "/")) != NULL)) {
- nextnode = vfs_finddir(startpoint, curr_token);
- if (!nextnode)
- return NULL;
- startpoint = nextnode;
- }
- if (!nextnode)
- nextnode = startpoint;
- vfs_open(nextnode, flags);
- kfree(save);
- kfree(free_filename);
- return nextnode;
-}
-
-void vfs_init()
-{
- vfs_tree = tree_create();
- struct vfs_entry *root = kmalloc(sizeof(struct vfs_entry));
- root->name = strdup("root");
- root->file = NULL;
- tree_insert(vfs_tree, NULL, root);
-}
-
-void vfs_mount_dev(char *mountpoint, vfs_node_t *node)
-{
- vfs_mount(mountpoint, node);
-}
-
-void vfs_mount_recur(char *path, gtreenode_t *subroot, vfs_node_t *fs_obj)
-{
- int found = 0;
- char *curr_token = strsep(&path, "/");
-
- if (curr_token == NULL || !strcmp(curr_token, "")) {
- struct vfs_entry *ent = (struct vfs_entry *)subroot->value;
- if (ent->file) {
- warn("The path is already mounted, please unmount before mounting again");
- return;
- }
- if (!strcmp(ent->name, "/"))
- vfs_root = fs_obj;
- ent->file = fs_obj;
- return;
- }
-
- foreach(child, subroot->children)
- {
- gtreenode_t *tchild = (gtreenode_t *)child->val;
- struct vfs_entry *ent = (struct vfs_entry *)(tchild->value);
- if (strcmp(ent->name, curr_token) == 0) {
- found = 1;
- subroot = tchild;
- }
- }
-
- if (!found) {
- struct vfs_entry *ent = kcalloc(sizeof(struct vfs_entry), 1);
- ent->name = strdup(curr_token);
- subroot = tree_insert(vfs_tree, subroot, ent);
- }
- vfs_mount_recur(path, subroot, fs_obj);
-}
-
-void vfs_mount(char *path, vfs_node_t *fs_obj)
-{
- fs_obj->refcount = -1;
- fs_obj->fs_type = 0;
- if (path[0] == '/' && strlen(path) == 1) {
- struct vfs_entry *ent = (struct vfs_entry *)vfs_tree->root->value;
- if (ent->file) {
- warn("The path is already mounted, please unmount before mounting again");
- return;
- }
- vfs_root = fs_obj;
- ent->file = fs_obj;
- return;
- }
- vfs_mount_recur(path + 1, vfs_tree->root, fs_obj);
-} \ No newline at end of file
diff --git a/src/kernel/fs/vfs.h b/src/kernel/fs/vfs.h
deleted file mode 100644
index b31767e..0000000
--- a/src/kernel/fs/vfs.h
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef MELVIX_VFS_H
-#define MELVIX_VFS_H
-
-#include <stdint.h>
-
-#define PATH_SEPARATOR '/'
-#define PATH_SEPARATOR_STRING "/"
-#define PATH_UP ".."
-#define PATH_DOT "."
-#define VFS_EXT2_MAGIC 0xeeee2222
-
-#define O_RDONLY 0x0000
-#define O_WRONLY 0x0001
-#define O_RDWR 0x0002
-#define O_APPEND 0x0008
-#define O_CREAT 0x0200
-#define O_TRUNC 0x0400
-#define O_EXCL 0x0800
-#define O_NOFOLLOW 0x1000
-#define O_PATH 0x2000
-
-#define FS_FILE 0x01
-#define FS_DIRECTORY 0x02
-#define FS_CHARDEVICE 0x04
-#define FS_BLOCKDEVICE 0x08
-#define FS_PIPE 0x10
-#define FS_SYMLINK 0x20
-#define FS_MOUNTPOINT 0x40
-
-#define _IFMT 0170000 /* type of file */
-#define _IFDIR 0040000 /* directory */
-#define _IFCHR 0020000 /* character special */
-#define _IFBLK 0060000 /* block special */
-#define _IFREG 0100000 /* regular */
-#define _IFLNK 0120000 /* symbolic link */
-#define _IFSOCK 0140000 /* socket */
-#define _IFIFO 0010000 /* fifo */
-
-struct vfs_node;
-
-typedef uint32_t (*get_file_size_callback)(struct vfs_node *node);
-typedef uint32_t (*read_callback)(struct vfs_node *, uint32_t, uint32_t, char *);
-typedef uint32_t (*write_callback)(struct vfs_node *, uint32_t, uint32_t, char *);
-typedef void (*open_callback)(struct vfs_node *, uint32_t flags);
-typedef void (*close_callback)(struct vfs_node *);
-typedef struct dirent *(*readdir_callback)(struct vfs_node *, uint32_t);
-typedef struct vfs_node *(*finddir_callback)(struct vfs_node *, char *name);
-typedef void (*create_callback)(struct vfs_node *, char *name, uint16_t permission);
-typedef void (*unlink_callback)(struct vfs_node *, char *name);
-typedef void (*mkdir_callback)(struct vfs_node *, char *name, uint16_t permission);
-typedef int (*ioctl_callback)(struct vfs_node *, int request, void *argp);
-typedef int (*get_size_callback)(struct vfs_node *);
-typedef void (*chmod_callback)(struct vfs_node *, uint32_t mode);
-typedef char **(*listdir_callback)(struct vfs_node *);
-
-typedef struct vfs_node {
- char name[256];
- void *device;
- uint32_t mask;
- uint32_t uid;
- uint32_t gid;
- uint32_t flags;
- uint32_t inode_num;
- uint32_t size;
- uint32_t fs_type;
- uint32_t open_flags;
- uint32_t create_time;
- uint32_t access_time;
- uint32_t modified_time;
-
- uint32_t offset;
- unsigned nlink;
- int refcount;
-
- // File operations
- read_callback read;
- write_callback write;
- open_callback open;
- close_callback close;
- readdir_callback readdir;
- finddir_callback finddir;
- create_callback create;
- unlink_callback unlink;
- mkdir_callback mkdir;
- ioctl_callback ioctl;
- get_size_callback get_size;
- chmod_callback chmod;
- get_file_size_callback get_file_size;
-
- listdir_callback listdir;
-} vfs_node_t;
-
-struct dirent {
- char name[256];
- uint32_t inode_num;
-};
-
-typedef struct vfs_entry {
- char *name;
- vfs_node_t *file;
-} vfs_entry_t;
-
-uint32_t vfs_get_file_size(vfs_node_t *node);
-
-uint32_t vfs_read(vfs_node_t *node, uint32_t offset, uint32_t size, char *buffer);
-
-uint32_t vfs_write(vfs_node_t *node, uint32_t offset, uint32_t size, char *buffer);
-
-void vfs_open(struct vfs_node *node, uint32_t flags);
-
-void vfs_close(vfs_node_t *node);
-
-vfs_node_t *vfs_finddir(vfs_node_t *node, char *name);
-
-void vfs_mkdir(char *name, uint16_t permission);
-
-void vfs_mkfile(char *name, uint16_t permission);
-
-int vfs_create_file(char *name, uint16_t permission);
-
-vfs_node_t *file_open(const char *file_name, uint32_t flags);
-
-char *expand_path(char *input);
-
-int vfs_ioctl(vfs_node_t *node, int request, void *argp);
-
-void vfs_chmod(vfs_node_t *node, uint32_t mode);
-
-void vfs_unlink(char *name);
-
-int vfs_symlink(char *value, char *name);
-
-int vfs_readlink(vfs_node_t *node, char *buf, uint32_t size);
-
-void vfs_init();
-
-void vfs_mount(char *path, vfs_node_t *local_root);
-
-typedef vfs_node_t *(*vfs_mount_callback)(char *arg, char *mountpoint);
-
-void vfs_register(char *name, vfs_mount_callback callme);
-
-void vfs_mount_dev(char *mountpoint, vfs_node_t *node);
-
-void print_vfstree();
-
-void vfs_db_listdir(char *name);
-
-#endif \ No newline at end of file
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index 944fd75..84ed953 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -17,7 +17,6 @@
#include <kernel/lib/stdio.h>
#include <kernel/fs/ata.h>
#include <kernel/fs/ext2.h>
-#include <kernel/fs/vfs.h>
#include <kernel/cmos/rtc.h>
void kernel_main(uint32_t magic, uint32_t multiboot_address)
@@ -56,9 +55,9 @@ void kernel_main(uint32_t magic, uint32_t multiboot_address)
memory_print();
rtc_print();
- vfs_init();
ata_init();
- ext2_init("/dev/hda", "/");
+ ext2_init_fs();
+ panic("YAY");
load_binaries();
set_optimal_resolution();