diff options
| author | Jake Mannens <jake72360@gmail.com> | 2018-09-09 00:19:12 +1000 |
|---|---|---|
| committer | Jake Mannens <jake72360@gmail.com> | 2018-09-09 00:19:12 +1000 |
| commit | 02107df3f476c19bb7eaa3c49a368d703898615b (patch) | |
| tree | 7cbace89d150f2f6c39f3ec5766f7263441fea22 /kernel | |
| parent | 6d87016287ea76afbdf7e16fb2cf9e4fa20cc0de (diff) | |
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.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/boot.s | 4 | ||||
| -rw-r--r-- | kernel/fs/block.c | 10 | ||||
| -rw-r--r-- | kernel/fs/fs.c | 28 | ||||
| -rw-r--r-- | kernel/fs/mount.c | 35 | ||||
| -rw-r--r-- | kernel/hd.c | 207 | ||||
| -rw-r--r-- | kernel/serial.c | 21 | ||||
| -rw-r--r-- | kernel/sys.c | 58 |
7 files changed, 231 insertions, 132 deletions
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 <kernel/hd.h> +#include <sys/types.h> + +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 <kernel/con.h> +#include <kernel/fs.h> +#include <kernel/hd.h> +#include <kernel/kernel.h> +#include <kernel/sched.h> +#include <kernel/tty.h> +#include <string.h> +#include <sys/types.h> + +/* 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 <kernel/con.h> +#include <kernel/fs.h> +#include <string.h> + +/* 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 <asm/io.h> #include <kernel/con.h> +#include <kernel/fs.h> #include <kernel/kernel.h> #include <stdint.h> +#include <sys/types.h> + +#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 <time.h> #include <unistd.h> -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) { |
