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 | |
| 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.
| -rw-r--r-- | hd.img | bin | 20971520 -> 20971520 bytes | |||
| -rw-r--r-- | include/kernel/fs.h | 46 | ||||
| -rw-r--r-- | include/kernel/hd.h | 7 | ||||
| -rw-r--r-- | include/kernel/sys.h | 33 | ||||
| -rw-r--r-- | include/sys/stat.h | 42 | ||||
| -rw-r--r-- | include/unistd.h | 18 | ||||
| -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 | ||||
| -rw-r--r-- | usrbin/main.c | 17 |
14 files changed, 348 insertions, 178 deletions
| Binary files differ diff --git a/include/kernel/fs.h b/include/kernel/fs.h index 8f21110..a2b0086 100644 --- a/include/kernel/fs.h +++ b/include/kernel/fs.h @@ -4,10 +4,14 @@ #include <stdint.h> #include <sys/types.h> -#define BLOCK_SIZE 1024 +#define NRSUPER 8 #define NRFILE 128 #define NROPEN 32 +/* these shouldn't change */ +#define BLOCK_SIZE 1024 +#define SUPER_MAGIC 0x137F + struct file { uint16_t f_mode; uint16_t f_flags; @@ -15,4 +19,44 @@ struct file { off_t f_pos; }; +struct super_block { + uint16_t s_ninodes; + uint16_t s_nzones; + uint16_t s_imap_blocks; + uint16_t s_zmap_blocks; + uint16_t s_firstdatazone; + uint16_t s_log_zone_size; + uint32_t s_max_size; + uint16_t s_magic; + /* loaded in memory only */ + struct s_buff *s_imap[8]; + struct s_buff *s_zmap[8]; + uint16_t s_dev; + uint16_t s_dirt; + uint16_t s_start; + uint16_t s_super; + uint16_t s_imap_off; + uint16_t s_zmap_off; + uint16_t s_inode_off; +} __attribute__((packed)); + +struct m_inode { + uint16_t i_mode; + uint16_t i_uid; + uint32_t i_size; + uint32_t i_mtime; + uint8_t i_gid; + uint8_t i_nlinks; + uint16_t i_zone[9]; +} __attribute__((packed)); + +extern struct super_block sblocks[NRSUPER]; + +size_t block_read(void*, size_t , size_t); +size_t block_write(void*, size_t , size_t); + +void mount_root(void); + +void fs_init(void); + #endif diff --git a/include/kernel/hd.h b/include/kernel/hd.h index 292b92e..2a2f3c6 100644 --- a/include/kernel/hd.h +++ b/include/kernel/hd.h @@ -2,8 +2,11 @@ #define _HD_H #include <stdint.h> +#include <sys/types.h> -int hd_read(void*, uint32_t, uint8_t); -int hd_write(void*, uint32_t, uint8_t); +void hd_init(void); + +size_t hd_read_block(void*, size_t , size_t); +size_t hd_write_block(void*, size_t , size_t); #endif diff --git a/include/kernel/sys.h b/include/kernel/sys.h index 1b8be8e..95cfb79 100644 --- a/include/kernel/sys.h +++ b/include/kernel/sys.h @@ -1,31 +1,30 @@ typedef int (*syscall_t) (void); -extern int sys_time(void); -extern int sys_time(void); -extern int sys_getpid(void); -extern int sys_getpdir(void); -extern int sys_signal(void); extern int sys_alarm(void); -extern int sys_pause(void); extern int sys_ctty(void); -extern int sys_read(void); -extern int sys_write(void); +extern int sys_getpdir(void); +extern int sys_getpid(void); extern int sys_kill(void); extern int sys_panic(void); +extern int sys_pause(void); +extern int sys_read(void); +extern int sys_signal(void); +extern int sys_time(void); +extern int sys_write(void); extern int sys_dummy(void); syscall_t call_table[256] = { - [0] = &sys_time, - [1] = &sys_getpid, + [0] = &sys_alarm, + [1] = &sys_ctty, [2] = &sys_getpdir, - [3] = &sys_signal, - [4] = &sys_alarm, - [5] = &sys_pause, - [6] = &sys_ctty, + [3] = &sys_getpid, + [4] = &sys_kill, + [5] = &sys_panic, + [6] = &sys_pause, [7] = &sys_read, - [8] = &sys_write, - [9] = &sys_kill, - [10] = &sys_panic, + [8] = &sys_signal, + [9] = &sys_time, + [10] = &sys_write, [11] = &sys_dummy, [12] = &sys_dummy, [13] = &sys_dummy, diff --git a/include/sys/stat.h b/include/sys/stat.h new file mode 100644 index 0000000..fab014c --- /dev/null +++ b/include/sys/stat.h @@ -0,0 +1,42 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +/* permission bits */ + +#define S_IRWXU 0700 +#define S_IRUSR 0400 +#define S_IWUSR 0200 +#define S_IXUSR 0100 + +#define S_IRWXG 0070 +#define S_IRGRP 0040 +#define S_IWGRP 0020 +#define S_IXGRP 0010 + +#define S_IRWXO 0007 +#define S_IROTH 0004 +#define S_IWOTH 0002 +#define S_IXOTH 0001 + +/* inode type bits */ + +#define S_IFMT 0170000 +#define S_IFSOCK 0140000 +#define S_IFLNK 0120000 +#define S_IFREG 0100000 +#define S_IFBLK 0060000 +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFIFO 0010000 + +/* inode type conditionals */ + +#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) + +#endif diff --git a/include/unistd.h b/include/unistd.h index cc0f766..47e1621 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -10,17 +10,17 @@ typedef int32_t ssize_t; typedef int16_t pid_t; -#define __SYS_time 0 -#define __SYS_getpid 1 +#define __SYS_alarm 0 +#define __SYS_ctty 1 #define __SYS_getpdir 2 -#define __SYS_signal 3 -#define __SYS_alarm 4 -#define __SYS_pause 5 -#define __SYS_ctty 6 +#define __SYS_getpid 3 +#define __SYS_kill 4 +#define __SYS_panic 5 +#define __SYS_pause 6 #define __SYS_read 7 -#define __SYS_write 8 -#define __SYS_kill 9 -#define __SYS_panic 10 +#define __SYS_signal 8 +#define __SYS_time 9 +#define __SYS_write 10 #define _syscall0(type, name) \ type name(void) { \ 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) { diff --git a/usrbin/main.c b/usrbin/main.c index 70c0ab3..3b6dd97 100644 --- a/usrbin/main.c +++ b/usrbin/main.c @@ -50,23 +50,6 @@ void pid2(void) { } void main(void) { - int i; - char c = 'a'; - char buf[2048]; - -/* - * for(i = 0; i < 2048; i++) { - * buf[i] = c; - * - * c++; - * if(c > 'z') - * c = 'a'; - * } - * ctty(1); - * write(buf, 2048); - * while(1); - */ - if(getpid() == 1) { ctty(1); pid1(); |
