summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--hd.imgbin0 -> 20971520 bytes
-rw-r--r--include/asm/io.h19
-rw-r--r--include/kernel/fs.h18
-rw-r--r--include/kernel/hd.h7
-rw-r--r--include/sys/types.h2
-rw-r--r--kernel/Makefile4
-rw-r--r--kernel/boot.s14
-rw-r--r--kernel/fs/hd.c132
-rw-r--r--kernel/kmain.c35
10 files changed, 222 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index c29b673..f043bea 100644
--- a/Makefile
+++ b/Makefile
@@ -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:
diff --git a/hd.img b/hd.img
new file mode 100644
index 0000000..0ab36b5
--- /dev/null
+++ b/hd.img
Binary files differ
diff --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");
}