From 02107df3f476c19bb7eaa3c49a368d703898615b Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Sun, 9 Sep 2018 00:19:12 +1000 Subject: Re-ordered system call numbers and definitions into alphabetical order to make management/maintenance easier. Defined the structures super_block and m_inode in kernel/fs.h for super blocks and inodes respectively. Added the new header file sys/stat.h which contains basic definitions for inode types and permissions. These definitions will be required by any functions handling m_inode structures. Moved the sys_read and sys_write system calls to the filesystem's main source file at kernel/fs/fs.c. Added the file kernel/fs/mount.c which will contain the super-blocks table as well as the function mount_root() which will attempt to mount the root filesystem during boot. Eventually, this file will be expanded to include a general-purpose mount function to mount any filesystem as well as the system call handler for sys_mount. Seperated block I/O functions into their own subsystem under kernel/fs/block.c which currently supports two functions; block_read() and block_write() to read and write blocks from block devices. Currently, no device can be specified since the primary ATA master drive is the only possible target. This will change in the future however. Modified the hard disk driver's read and write functions to use filesystem blocks rather than sectors as the units of transfer. This is intended to keep the block I/O subsystem simple by ensuring a uniform transfer unit is used across all block devices and drivers. The hard disk driver is no longer initialized during the main boot procedure. Instead, a call is made to the new function fs_init() which will setup filesystem tables and structures, call hd_init() to initialize the disk and finally, attempt to load the super-block for the root filesystem. The hard disk driver now stores the disk's size and sanity checks addresses and sizes in read and write calls against this value. --- kernel/boot.s | 4 +- kernel/fs/block.c | 10 +++ kernel/fs/fs.c | 28 ++++++++ kernel/fs/mount.c | 35 +++++++++ kernel/hd.c | 207 ++++++++++++++++++++++++++++++++++-------------------- kernel/serial.c | 21 ------ kernel/sys.c | 58 +++++++-------- 7 files changed, 231 insertions(+), 132 deletions(-) create mode 100644 kernel/fs/block.c create mode 100644 kernel/fs/fs.c create mode 100644 kernel/fs/mount.c (limited to 'kernel') diff --git a/kernel/boot.s b/kernel/boot.s index ac7e0e3..d1f5606 100644 --- a/kernel/boot.s +++ b/kernel/boot.s @@ -4,7 +4,7 @@ global kboot global register_isr global register_trap extern con_init -extern hd_init +extern fs_init extern kmain extern paging_init extern printk @@ -42,8 +42,8 @@ kboot: call printk add esp, 4 ; initialize secondary subsystems + call fs_init call tty_init - call hd_init ; last minute setup, then transfer to kmain call timer_init call kmain diff --git a/kernel/fs/block.c b/kernel/fs/block.c new file mode 100644 index 0000000..b3f7386 --- /dev/null +++ b/kernel/fs/block.c @@ -0,0 +1,10 @@ +#include +#include + +size_t block_read(void *buf, size_t block, size_t len) { + return hd_read_block(buf, block, len); +} + +size_t block_write(void *buf, size_t block, size_t len) { + return hd_write_block(buf, block, len); +} diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c new file mode 100644 index 0000000..792668e --- /dev/null +++ b/kernel/fs/fs.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* master file table */ +static struct file ftable[NRFILE]; + +ssize_t sys_read(void *buf, size_t len) { + return tty_read(ctask->ctty, buf, len); +} + +ssize_t sys_write(void *buf, size_t len) { + return tty_write(ctask->ctty, buf, len); +} + +void fs_init(void) { + memset(&sblocks, 0, sizeof(sblocks)); + memset(&ftable, 0, sizeof(ftable)); + + hd_init(); + + mount_root(); +} diff --git a/kernel/fs/mount.c b/kernel/fs/mount.c new file mode 100644 index 0000000..47911fb --- /dev/null +++ b/kernel/fs/mount.c @@ -0,0 +1,35 @@ +#include +#include +#include + +/* super blocks table */ +struct super_block sblocks[NRSUPER]; + +void mount_root(void) { + size_t ret; + char buf[BLOCK_SIZE]; + struct super_block *s = (void*) buf; + + ret = block_read(buf, 1, 1); + if(ret < 1) { + printk("[fs] Failed to read super block\n"); + return; + } + + if(s->s_magic != SUPER_MAGIC) { + printk("[fs] Invalid magic number in super block!\n"); + return; + } + + printk("[fs] Found valid super-block for /\n"); + printk(" 0x%01x inodes\n", s->s_ninodes); + printk(" 0x%01x zones\n", s->s_nzones); + printk(" 0x%01x inode block bitmaps\n", s->s_imap_blocks); + printk(" 0x%01x zone block bitmaps\n", s->s_zmap_blocks); + printk(" First data zone: 0x%01x\n", s->s_firstdatazone); + printk(" Log zone size: 0x%01x\n", s->s_log_zone_size); + printk(" Max file size: 0x%01x\n", s->s_max_size); + + /* copy the super block into the table */ + memcpy(sblocks, buf, ((unsigned) &s->s_imap - (unsigned) s)); +} diff --git a/kernel/hd.c b/kernel/hd.c index 65ebfd7..eab82dc 100644 --- a/kernel/hd.c +++ b/kernel/hd.c @@ -1,7 +1,12 @@ #include #include +#include #include #include +#include + +#define SECTS(n) ((n) * (BLOCK_SIZE / 512)) +#define BLOCKS(n) ((n) / (BLOCK_SIZE / 512)) #define ST_ERR 1 #define ST_DRQ 8 @@ -10,53 +15,23 @@ #define ST_RDY 64 #define ST_BSY 128 -/* sector buffer */ +/* status buffer */ static char sbuf[512]; -void hd_init(void) { - int i; - uint8_t s; - uint16_t *buf = (uint16_t*) sbuf; - - /* select the master drive */ - outb(0x1F6, 0xA0); - /* send the IDENTIFY command */ - outb(0x1F7, 0xEC); +static uint32_t nblocks; - while(1) { - s = inb(0x1F7); - if(!s) { - printk("[hd] Master drive not detected on primary bus!\n"); - return; - } - if(s & ST_ERR) { - if(!inb(0x1F4) && !inb(0x1F5)) - continue; - printk("[hd] IDENTIFY command error!\n"); - return; - } - if(s & ST_DRQ && !(s & ST_ERR)) - break; - } - - printk("[hd] Master drive detected on primary bus! (status: 0x%02x)\n", s); - - for(i = 0; i < 256; i++) - buf[i] = inw(0x1F0); -} - -int hd_read(void *buf, uint32_t lba, uint8_t c) { +static int read_sect(void *buf, uint32_t lba) { int n; uint8_t s; uint16_t *p = buf; - if(!c) - return 0; + if(lba > nblocks - 1) + return -1; /* select the master disk on the primary bus */ outb(0x1F6, 0xE0 | ((lba >> 24) & 0xF)); /* set the number of sectors to be read */ - outb(0x1F2, c); + outb(0x1F2, 1); /* set the LBA address for the read operation */ outb(0x1F3, lba); outb(0x1F4, lba >> 8); @@ -64,42 +39,40 @@ int hd_read(void *buf, uint32_t lba, uint8_t c) { /* send the READ command */ outb(0x1F7, 0x20); - while(c--) { - /* wait for the drive */ - while(1) { - /* poll the drive's status */ - s = inb(0x1F7); - if(s & ST_DF) { - printk("[hd] Drive failure!\n"); - panic(); - } - if(s & ST_ERR) - return -1; - if(!(s & ST_BSY) && s & ST_DRQ) - break; + /* wait for the drive */ + while(1) { + /* poll the drive's status */ + s = inb(0x1F7); + if(s & ST_DF) { + printk("[hd] Drive failure!\n"); + panic(); } - - /* buffer is full, copy it's data */ - n = 256; - while(n--) - *(p++) = inw(0x1F0); + if(s & ST_ERR) + return -1; + if(!(s & ST_BSY) && s & ST_DRQ) + break; } + /* buffer is full, copy it's data */ + n = 256; + while(n--) + *(p++) = inw(0x1F0); + return 0; } -int hd_write(void *buf, uint32_t lba, uint8_t c) { +static int write_sect(void *buf, uint32_t lba) { int n; uint8_t s; uint16_t *p = buf; - if(!c) - return 0; + if(lba > nblocks - 1) + return -1; /* select the master disk on the primary bus */ outb(0x1F6, 0xE0 | ((lba >> 24) & 0xF)); /* set the number of sectors to be written */ - outb(0x1F2, c); + outb(0x1F2, 1); /* set the LBA address for the write operation */ outb(0x1F3, lba); outb(0x1F4, lba >> 8); @@ -107,26 +80,108 @@ int hd_write(void *buf, uint32_t lba, uint8_t c) { /* send the WRITE command */ outb(0x1F7, 0x30); - while(c--) { - /* wait for the drive */ - while(1) { - /* poll the drive's status */ - s = inb(0x1F7); - if(s & ST_DF) { - printk("[hd] Drive failure!\n"); - panic(); - } - if(s & ST_ERR) - return -1; - if(!(s & ST_BSY) && s & ST_DRQ) - break; + /* wait for the drive */ + while(1) { + /* poll the drive's status */ + s = inb(0x1F7); + if(s & ST_DF) { + printk("[hd] Drive failure!\n"); + panic(); } - - /* refill the drive's buffer */ - n = 256; - while(n--) - outw(0x1F0, *(p++)); + if(s & ST_ERR) + return -1; + if(!(s & ST_BSY) && s & ST_DRQ) + break; } + /* refill the drive's buffer */ + n = 256; + while(n--) + outw(0x1F0, *(p++)); + return 0; } + +size_t hd_read_block(void *buf, size_t block, size_t len) { + int ret; + size_t i; + uint32_t s = SECTS(block); + uint32_t e = SECTS(block + len); + + if(s > nblocks - 1) + s = nblocks - 1; + if(e > nblocks - 1) + e = nblocks - 1; + + for(i = 0; i < (e - s); i++) { + ret = read_sect(buf, i + s); + + if(ret < 0) + return BLOCKS(i); + + buf = ((char*) buf + 512); + } + + return len; +} + +size_t hd_write_block(void *buf, size_t block, size_t len) { + int ret; + size_t i; + uint32_t s = SECTS(block); + uint32_t e = SECTS(block + len); + + if(s > nblocks - 1) + s = nblocks - 1; + if(e > nblocks - 1) + e = nblocks - 1; + + for(i = 0; i < (e - s); i++) { + ret = write_sect(buf, i + s); + + if(ret < 0) + return BLOCKS(i); + + buf = ((char*) buf + 512); + } + + return len; +} + +void hd_init(void) { + int i; + uint8_t s; + uint16_t *buf = (uint16_t*) sbuf; + + /* select the master drive */ + outb(0x1F6, 0xA0); + /* send the IDENTIFY command */ + outb(0x1F7, 0xEC); + + while(1) { + s = inb(0x1F7); + if(!s) { + printk("[hd] Master drive not detected on primary bus!\n"); + return; + } + if(s & ST_ERR) { + if(!inb(0x1F4) && !inb(0x1F5)) + continue; + printk("[hd] IDENTIFY command error!\n"); + return; + } + if(s & ST_DRQ && !(s & ST_ERR)) + break; + } + + for(i = 0; i < 256; i++) + buf[i] = inw(0x1F0); + + nblocks = *((uint32_t*) &buf[60]); + if(!nblocks) { + printk("[hd] Drive does not support LBA28 addressing!\n"); + return; + } + + printk("[hd] Primary bus master drive initialized! (status: 0x%02x, nblocks: 0x%01x)\n", s, nblocks); +} diff --git a/kernel/serial.c b/kernel/serial.c index e712e53..6821bdc 100644 --- a/kernel/serial.c +++ b/kernel/serial.c @@ -91,27 +91,6 @@ void rsint_rx(void) { wake_up(&q->waiting); } -/* - * void rsint_tx(void) { - * int copied = 0; - * struct tty_queue *q = &tty_rs.wqueue; - * - * while(q->pread != q->pwrite) { - * [> we're done if the TX FIFO is full <] - * if((inb(RSLINES) & 0x20) == 0) - * break; - * - * outb(RSDATA, q->buf[q->pread]); - * q->pread = (q->pread + 1) % TTY_BUF_SIZE; - * - * copied = 1; - * } - * - * if(copied) - * wake_up(&q->waiting); - * } - */ - void rsint_tx(void) { int i; int copied = 0; diff --git a/kernel/sys.c b/kernel/sys.c index b750072..f21e35a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -11,8 +11,19 @@ #include #include -time_t sys_time(void) { - return ticks / 100; +int sys_alarm(unsigned int seconds) { + if(!seconds) { + ctask->alarm = 0; + return 0; + } + + ctask->alarm = ticks + (seconds * 100); +} + +int sys_ctty(int ctty) { + ctask->ctty = ctty; + + return 0; } pid_t sys_getpid(void) { @@ -27,26 +38,8 @@ void *sys_getpdir(void) { return (void*) pdir; } -void *sys_signal(int sig, void (*func)(int)) { - if(sig < 0 || sig >= NRSIG) - return NULL; - - /* SIGKILL and SIGSTOP cannot be caught */ - if(sig == SIGKILL || sig == SIGSTOP) - return NULL; - - ctask->sig_handlers[sig] = func; - - return func; -} - -int sys_alarm(unsigned int seconds) { - if(!seconds) { - ctask->alarm = 0; - return 0; - } - - ctask->alarm = ticks + (seconds * 100); +void sys_panic(void) { + panic(); } int sys_pause(void) { @@ -55,22 +48,21 @@ int sys_pause(void) { return -1; } -int sys_ctty(int ctty) { - ctask->ctty = ctty; +void *sys_signal(int sig, void (*func)(int)) { + if(sig < 0 || sig >= NRSIG) + return NULL; - return 0; -} + /* SIGKILL and SIGSTOP cannot be caught */ + if(sig == SIGKILL || sig == SIGSTOP) + return NULL; -ssize_t sys_read(void *buf, size_t len) { - return tty_read(ctask->ctty, buf, len); -} + ctask->sig_handlers[sig] = func; -ssize_t sys_write(void *buf, size_t len) { - return tty_write(ctask->ctty, buf, len); + return func; } -void sys_panic(void) { - panic(); +time_t sys_time(void) { + return ticks / 100; } int sys_dummy(void) { -- cgit v1.3