summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorJake Mannens <jake72360@gmail.com>2018-07-14 03:42:12 +1000
committerJake Mannens <jake72360@gmail.com>2018-07-14 03:42:12 +1000
commit35685c20a5dc299edf6f3b76ed898a2e71d0e457 (patch)
tree0c4ef9eb71eedb2a3d414b6454f86529400a717e /kernel
parentbe74842e37ad54f4fd18ae647e2bdf3e435a0fb8 (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.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile4
-rw-r--r--kernel/boot.s14
-rw-r--r--kernel/fs/hd.c132
-rw-r--r--kernel/kmain.c35
4 files changed, 179 insertions, 6 deletions
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");
}