diff options
author | Marvin Borner | 2020-04-19 23:58:09 +0200 |
---|---|---|
committer | Marvin Borner | 2020-04-19 23:58:09 +0200 |
commit | f3427d6e37a1ebec78adac57f69d5efad0170d66 (patch) | |
tree | 65389988a30951d2a29a36acad38e942e0d7bd4e | |
parent | 63a2e138f3f5f8d4fa731a06dc2b0e3ab4eab3bc (diff) |
Clean ext2 implementation :)
-rw-r--r-- | .github/workflows/build.yml | 2 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rwxr-xr-x | run | 35 | ||||
-rw-r--r-- | src/kernel/fs/ata.c | 332 | ||||
-rw-r--r-- | src/kernel/fs/ata.h | 144 | ||||
-rw-r--r-- | src/kernel/fs/ext2.c | 884 | ||||
-rw-r--r-- | src/kernel/fs/ext2.h | 309 | ||||
-rw-r--r-- | src/kernel/fs/vfs.c | 369 | ||||
-rw-r--r-- | src/kernel/fs/vfs.h | 149 | ||||
-rw-r--r-- | src/kernel/kernel.c | 5 |
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 @@ -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` @@ -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(); |