diff options
| author | Jake Mannens <jake72360@gmail.com> | 2018-07-14 03:42:12 +1000 |
|---|---|---|
| committer | Jake Mannens <jake72360@gmail.com> | 2018-07-14 03:42:12 +1000 |
| commit | 35685c20a5dc299edf6f3b76ed898a2e71d0e457 (patch) | |
| tree | 0c4ef9eb71eedb2a3d414b6454f86529400a717e | |
| parent | be74842e37ad54f4fd18ae647e2bdf3e435a0fb8 (diff) | |
con_init() is now called during the kernel's boot sequence in kboot()
rather than in kmain() as some subsystems may now require early console
I/O.
Added 16-bit read/write I/O functions to asm/io.h. These functions are
inw() and outw() respectively.
Added the file kernel/fs.h which will contain definitions relating to
filesystem functions.
Defined the type off_t as a signed 32-bit value in sys/types.h. This
type will be required for filesystem functionality.
Added the directory 'kernel/fs' to the project's source tree. The
kernel's makefile has been updated accordingly. This directory will
contain any source files relating to filesystem functionality (both
assembly and C files).
Added the file 'fs/hd.c' to the kernel's source tree. This file
currently contains three main functions (which are defined in
kernel/hd.h). These functions are as follows; hd_init() to enumerate and
initialize the hard disks, hd_read() to read sectors from the disk and
hd_write() to write sectors to the disk. Currently, all transfers are
done in ATA PIO mode using polling, however this will change in future.
The function hd_init() is called during the kernel's boot sequence in
kboot().
Added the file hd.img to the project's root directory. This is a 20MB
raw image file that will be used by Qemu as a 20MB hard disk. The main
makefile has been updated to tell Qemu to use this file on launch.
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | hd.img | bin | 0 -> 20971520 bytes | |||
| -rw-r--r-- | include/asm/io.h | 19 | ||||
| -rw-r--r-- | include/kernel/fs.h | 18 | ||||
| -rw-r--r-- | include/kernel/hd.h | 7 | ||||
| -rw-r--r-- | include/sys/types.h | 2 | ||||
| -rw-r--r-- | kernel/Makefile | 4 | ||||
| -rw-r--r-- | kernel/boot.s | 14 | ||||
| -rw-r--r-- | kernel/fs/hd.c | 132 | ||||
| -rw-r--r-- | kernel/kmain.c | 35 |
10 files changed, 222 insertions, 13 deletions
@@ -21,7 +21,7 @@ clean: rm -f $(TARGET) run: $(TARGET) - qemu-system-x86_64 -s -kernel $(TARGET) - # qemu-system-x86_64 -s -S -kernel $(TARGET) + qemu-system-x86_64 -s -kernel $(TARGET) -drive file=hd.img,format=raw + #qemu-system-x86_64 -s -S -kernel $(TARGET) -drive file=hd.img,format=raw .FORCE: Binary files differdiff --git a/include/asm/io.h b/include/asm/io.h index 1c2e5bc..09294f4 100644 --- a/include/asm/io.h +++ b/include/asm/io.h @@ -5,10 +5,19 @@ */ #define inb(port) ({ \ - unsigned char _val; \ - __asm__ volatile ("inb %%dx, %%al" : "=a" (_val) : "d" (port)); \ - _val; \ - }) + unsigned char _val; \ + __asm__ volatile ("inb %%dx, %%al" : "=a" (_val) : "d" (port)); \ + _val; \ + }) + +#define inw(port) ({ \ + unsigned short _val; \ + __asm__ volatile ("inw %%dx, %%ax" : "=a" (_val) : "d" (port)); \ + _val; \ + }) #define outb(port, val) \ - __asm__ volatile ("outb %%al, %%dx" : : "d" (port), "a" (val)); + __asm__ volatile ("outb %%al, %%dx" :: "d" (port), "a" (val)); + +#define outw(port, val) \ + __asm__ volatile ("outw %%ax, %%dx" :: "d" (port), "a" (val)); diff --git a/include/kernel/fs.h b/include/kernel/fs.h new file mode 100644 index 0000000..8f21110 --- /dev/null +++ b/include/kernel/fs.h @@ -0,0 +1,18 @@ +#ifndef _FS_H +#define _FS_H + +#include <stdint.h> +#include <sys/types.h> + +#define BLOCK_SIZE 1024 +#define NRFILE 128 +#define NROPEN 32 + +struct file { + uint16_t f_mode; + uint16_t f_flags; + /* TODO: inode pointer here */ + off_t f_pos; +}; + +#endif diff --git a/include/kernel/hd.h b/include/kernel/hd.h new file mode 100644 index 0000000..26c705d --- /dev/null +++ b/include/kernel/hd.h @@ -0,0 +1,7 @@ +#ifndef _HD_H +#define _HD_H + +int hd_read(void*, uint32_t, uint8_t); +int hd_write(void*, uint32_t, uint8_t); + +#endif diff --git a/include/sys/types.h b/include/sys/types.h index ace1a62..6c18e16 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -17,4 +17,6 @@ typedef uint32_t size_t; typedef int32_t time_t; #endif +typedef long off_t; + #endif diff --git a/kernel/Makefile b/kernel/Makefile index 29b5566..f9e14e8 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,7 +1,7 @@ TARGET = kernel.o -SRCS = $(wildcard *.c) -ASMS = $(wildcard *.s) +SRCS = $(wildcard *.c) $(wildcard fs/*.c) +ASMS = $(wildcard *.s) $(wildcard fs/*.s) OBJS = $(SRCS:.c=.o) $(ASMS:.s=.o) CFLAGS = -m32 -I../include -ffreestanding -nostdinc -nostdlib -fno-stack-protector -fno-pie -gstabs+ -g diff --git a/kernel/boot.s b/kernel/boot.s index 98732f6..96f0e43 100644 --- a/kernel/boot.s +++ b/kernel/boot.s @@ -2,8 +2,11 @@ global gdt global idt global kboot global register_isr +extern con_init +extern hd_init extern kmain extern paging_init +extern printk extern syscall_init extern timer_init extern traps_init @@ -24,10 +27,18 @@ kboot: ; WARNING: don't change this without changing the corresponding ; entries in the TSS constructor in sched.c mov esp, 0x80000 - ; setup descriptor tables + ; setup descriptor tables and enable paging call flush_gdt call paging_init call flush_idt + ; initialize the console + call con_init + ; add this point, we can display *some* output + push .msg + call printk + add esp, 4 + ; initialize the disk interface + call hd_init ; last minute setup, then transfer to kmain call timer_init call kmain @@ -35,6 +46,7 @@ kboot: ; disable interrupts and halt the system. cli hlt +.msg: db "Kernel booting...", 10, 0 gdt: ; null descriptor diff --git a/kernel/fs/hd.c b/kernel/fs/hd.c new file mode 100644 index 0000000..706d503 --- /dev/null +++ b/kernel/fs/hd.c @@ -0,0 +1,132 @@ +#include <asm/io.h> +#include <kernel/con.h> +#include <kernel/kernel.h> +#include <stdint.h> + +#define ST_ERR 1 +#define ST_DRQ 8 +#define ST_SRV 16 +#define ST_DF 32 +#define ST_RDY 64 +#define ST_BSY 128 + +/* sector 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); + + while(1) { + s = inb(0x1F7); + if(!s) { + printk("[hd] Master drive not detected on primary bus!\n"); + panic(); + } + if(s & ST_ERR) { + if(!inb(0x1F4) && !inb(0x1F5)) + continue; + printk("[hd] IDENTIFY command error!\n"); + panic(); + } + 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) { + int n; + uint8_t s; + uint16_t *p = buf; + + if(!c) + return 0; + + /* 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); + /* set the LBA address for the read operation */ + outb(0x1F3, lba); + outb(0x1F4, lba >> 8); + outb(0x1F5, lba >> 16); + /* 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; + } + + /* 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) { + int n; + uint8_t s; + uint16_t *p = buf; + + if(!c) + return 0; + + /* 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); + /* set the LBA address for the write operation */ + outb(0x1F3, lba); + outb(0x1F4, lba >> 8); + outb(0x1F5, lba >> 16); + /* 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; + } + + /* refill the drive's buffer */ + n = 256; + while(n--) + outw(0x1F0, *(p++)); + } + + return 0; +} diff --git a/kernel/kmain.c b/kernel/kmain.c index 6b550b7..00455b7 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -3,11 +3,40 @@ #include <kernel/sys.h> #include <stdint.h> +extern int hd_read(void*, uint32_t, uint8_t); +extern int hd_write(void*, uint32_t, uint8_t); + +static char buf[0x1000]; + void kmain(void) { - con_init(); + int i; + int ret; - printk("Kernel booting...\n"); printk("Kernel booted!\n\n"); - sched_init(); + /* sched_init(); */ + + /* try to read some data */ + + ret = hd_read(buf, 0, 2); + if(ret < 0) { + printk("Failed to read data!\n"); + return; + } + printk("Successfully read first and second sectors!\n"); + printk("First dword (sector 0): 0x%08x\n", *((uint32_t*) buf)); + printk("First dword (sector 1): 0x%08x\n", *((uint32_t*) (buf + 512))); + + /* try to write some data */ + + for(i = 0; i < 256; i++) + ((uint16_t*) buf)[i] = i; + + ret = hd_write(buf, 2, 1); + if(ret < 0) { + printk("Failed to write data!\n"); + return; + } + + printk("Successfully wrote to sector 2\n"); } |
