changeset 32:3a6a9b929db0

Added initial ramdisk and some virtual file system functions
author windel
date Fri, 13 Jan 2012 18:18:17 +0100
parents 88590c42320f
children d8185ddb6c7b
files cos/Makefile cos/grub/menu.lst cos/hello/Makefile cos/hello/hello.c cos/kernel/Makefile cos/kernel/asmcode.asm cos/kernel/fs.c cos/kernel/goto64.asm cos/kernel/handlers.c cos/kernel/initrd.c cos/kernel/kernel.c cos/kernel/kernel.h cos/kernel/keyboard.c cos/kernel/klib.c cos/kernel/mm.c cos/makeinitrd.py
diffstat 16 files changed, 270 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/cos/Makefile	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/Makefile	Fri Jan 13 18:18:17 2012 +0100
@@ -2,7 +2,9 @@
 
 all:
 	make -C kernel
+	python makeinitrd.py lcfosinitrd.img hello/hello.bin
 	cp grub/emptybootdisk.img bootdisk.img
 	mcopy -D o -i bootdisk.img kernel/lcfos.bin ::
+	mcopy -D o -i bootdisk.img lcfosinitrd.img ::
 	mcopy -D o -i bootdisk.img grub/menu.lst ::/grub
 
--- a/cos/grub/menu.lst	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/grub/menu.lst	Fri Jan 13 18:18:17 2012 +0100
@@ -3,4 +3,5 @@
 title lcfos
 root (fd0)
 kernel /lcfos.bin
+module /lcfosinitrd.img
 
--- a/cos/hello/Makefile	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/hello/Makefile	Fri Jan 13 18:18:17 2012 +0100
@@ -11,8 +11,8 @@
 			-Wextra \
 			-Werror
 
-hello.bin: hello.o
-	ld -T hello.ld -s -o hello.bin hello.o
+hello.bin: hello.o liblcfos.o
+	ld -T hello.ld -s -o hello.bin hello.o liblcfos.o
 
 %.o: %.c
 	gcc $(CFLAGS) -o $@ -c $<
--- a/cos/hello/hello.c	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/hello/hello.c	Fri Jan 13 18:18:17 2012 +0100
@@ -2,6 +2,7 @@
 
 int main()
 {
+
    unsigned char * const screen = (unsigned char*)0xB8000;
    screen[0] = 'H';
    screen[2] = 'o';
--- a/cos/kernel/Makefile	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/Makefile	Fri Jan 13 18:18:17 2012 +0100
@@ -8,7 +8,7 @@
 	-fno-builtin -mcmodel=large -Wall -Wextra -Werror
 
 OBJECTS = video.o snprintf.o kernel.o asmcode.o handlers.o keyboard.o \
-			klib.o malloc.o task.o mm.o timer.o
+			klib.o malloc.o task.o mm.o timer.o fs.o initrd.o
 
 lcfos.bin: $(CRT0) $(OBJECTS) link.ld
 	ld -T link.ld -s -o lcfos.bin $(CRT0) $(OBJECTS)
@@ -20,5 +20,5 @@
 	gcc $(CFLAGS) -o $@ -c $<
 
 clean:
-	rm $(OBJECTS) $(CRT0) lcfosc.bin
+	rm $(OBJECTS) $(CRT0) lcfos.bin
 
--- a/cos/kernel/asmcode.asm	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/asmcode.asm	Fri Jan 13 18:18:17 2012 +0100
@@ -2,6 +2,9 @@
 ; from 20 - 31 are reserved vectors.
 ; below are the custom ones!
 
+; Calling convention AMD64 ABI:
+; parameters in: rdi, rsi, rdx, rcx ....
+
 section .text
 align 4
 
@@ -18,6 +21,11 @@
   lidt [idtP]
   ret
 
+global setCR3
+setCR3:
+   mov cr3, rdi ; Load cr3
+   ret
+
 ; ISR related assembler wrappers:
 
 %macro ISR_NOERRCODE 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/kernel/fs.c	Fri Jan 13 18:18:17 2012 +0100
@@ -0,0 +1,56 @@
+
+#include "kernel.h"
+
+uint64_t read_fs(fs_node_t *node, uint64_t offset, uint64_t size, uint8_t *buffer)
+{
+   if (node->read != 0)
+   {
+      return node->read(node, offset, size, buffer);
+   }
+   else
+   {
+      return 0;
+   }
+}
+
+uint64_t write_fs(fs_node_t *node, uint64_t offset, uint64_t size, uint8_t *buffer)
+{
+   if (node->write != 0)
+   {
+      return node->write(node, offset, size, buffer);
+   }
+   else
+   {
+      return 0;
+   }
+}
+
+void open_fs(fs_node_t *node)
+{
+   if (node->open != 0)
+   {
+      node->open(node);
+   }
+}
+
+void close_fs(fs_node_t *node)
+{
+   if (node->close != 0)
+   {
+      node->close(node);
+   }
+}
+
+// TODO: why not return an fs_node_t* ?
+fs_dirent_t* readdir_fs(fs_node_t *node, int i)
+{
+   if (node->readdir != 0)
+   {
+      return node->readdir(node, i);
+   }
+   else
+   {
+      return 0;
+   }
+}
+
--- a/cos/kernel/goto64.asm	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/goto64.asm	Fri Jan 13 18:18:17 2012 +0100
@@ -18,15 +18,6 @@
 ; 0x5000 - 0x6000 : IDT entries
 ; 0x6000 - 0xA000 : Stack
 
-; panic macro to debug on real hardware
-%macro DOPANIC 1
-mov al, %1
-mov edi, 0xb8000
-stosb
-xchg bx,bx
-hlt
-%endmacro
-
 bits 32 ; Start in 32 bits mode, as loaded by GRUB
 
 ; Multiboot header:
@@ -103,6 +94,9 @@
 
 ; Start of loader code:
 loader:
+; here ebx contains the pointer to the multiboot header, store is for later use.
+extern multiboot_info
+mov [multiboot_info], ebx
 
 ; Check that the CPU supports long mode:
 mov eax, 80000000h
@@ -220,6 +214,7 @@
 
 lgdt [gdt64pointer]    ; Reload GDT in 64 bits mode
 
+; TODO: determine a good place for the kernel stack.
 mov rsp, 0xA000      ; Setup stack pointer.
 
 extern kmain
--- a/cos/kernel/handlers.c	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/handlers.c	Fri Jan 13 18:18:17 2012 +0100
@@ -128,23 +128,24 @@
 // Hopefully, this function get called with the correct registers.
 void isr_handler(uint64_t* registers)
 {
-
    uint64_t intnum = registers[7];
 
+   // TODO: make a list with handler pointers:
    if (intnum == 32)
    {
       timerDriverUpdate();
    }
    else if (intnum == 33)
    {
-      unsigned char scancode = inb(0x60);
-      keyboardDriverUpdate(scancode);
+      keyboardDriverUpdate();
    }
    else
    {
-      printf("Interrupt %d called, registers at: %x\n", registers[7], registers);
+      // printf("Interrupt %d called, registers at: %x\n", registers[7], registers);
    }
 
+   // TODO: EOI to slave?
+   // TODO: replace this with APIC code?
    outb(0x20, 0x20); // EOI to master
 }
 
@@ -170,26 +171,6 @@
   panic("Unhandled exception!");
 }
 
-// remapped IRQ from master PIC:
-void INT32handler() 
-{
-  // System timer.
-  //printf("INT32 called!\n");
-  // called very frequent, what is this?
-  timerDriverUpdate();
-  // Acknowledge int:
-  outb(0x20, 0x20); // EOI to master
-}
-
-void INT33handler() 
-{
-  //printf("INT33 called, key pressed????\n");
-  unsigned char scancode = inb(0x60);
-  //printf("Scancode = 0x%x\n", scancode);
-  keyboardDriverUpdate(scancode);
-  outb(0x20, 0x20); // EOI to master
-}
-
 void INTDEF_handler() 
 {
   panic("Default int handler called\n");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/kernel/initrd.c	Fri Jan 13 18:18:17 2012 +0100
@@ -0,0 +1,25 @@
+/*
+ * Initial ramdisk filesystem driver.
+ * */
+
+#include "kernel.h"
+
+fs_node_t *initrd_root = 0;
+
+typedef struct
+{
+   uint32_t magic;
+   uint32_t numfiles;
+} initrd_header_t;
+
+fs_node_t* initialize_initrd(uint64_t location)
+{
+   // We need a valid malloc here!
+   initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t));
+
+   initrd_header_t *header = (initrd_header_t*)location;
+   initrd_root->length = header->numfiles;
+
+   return initrd_root;
+}
+
--- a/cos/kernel/kernel.c	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/kernel.c	Fri Jan 13 18:18:17 2012 +0100
@@ -15,6 +15,8 @@
    kfree(a);
 }
 
+multiboot_info_t *multiboot_info = 0; // Set by startup code.
+
 /* This routine initializes the kernel.
  * We are left here in 64-bit long mode with the first 6 MB identity mapped.
  * */
@@ -22,14 +24,66 @@
 {
    init_screen();
    setupIDT();
-   // init_heap();
+
+   uint64_t available_memory = 0;
+
+   /* Display memory information from multiboot header */
+   if ((multiboot_info->flags & (1<<6)) == (1<<6))
+   {
+      multiboot_memory_map_t *mmap;
+      for (mmap = (multiboot_memory_map_t*)(uint64_t)multiboot_info->mmap_addr; 
+            (uint64_t)mmap < multiboot_info->mmap_addr + multiboot_info->mmap_length; 
+            mmap = (multiboot_memory_map_t*) ( (uint64_t)mmap + mmap->size + sizeof(mmap->size)) )
+      {
+         printf("size: %d, start: 0x%x, length=0x%x, type=%d\n", mmap->size, mmap->base, mmap->length, mmap->type);
+
+         if ( (mmap->type == 1) && (mmap->base == 0x100000) )
+         {
+            available_memory = mmap->length;
+         }
+      }
+   }
+
+   printf("Running with %d MB ram\n", available_memory / 1000000);
+
+   fs_node_t *fs_root = 0;
+
+   if ( (multiboot_info->flags & (1<<3)) == (1<<3))
+   {
+      printf("Mod count: %d\n", multiboot_info->mods_count);
+      uint64_t i;
+      multiboot_module_t *mod;
+      for (i=0, mod=(multiboot_module_t*)(uint64_t)multiboot_info->mods_addr; i<multiboot_info->mods_count; i++, mod++)
+      {
+         printf("Mod start: %x, end: %x\n", mod->mod_start, mod->mod_end);
+         if (i == 0)
+         {
+            uint64_t ramdisk_location = ((uint32_t*)((uint64_t)multiboot_info->mods_addr))[0];
+            fs_root = initialize_initrd(ramdisk_location);
+         }
+      }
+   }
+   
+   if (fs_root != 0)
+   {
+      fs_dirent_t *node = 0;
+      int i = 0;
+      while ( (node = readdir_fs(fs_root, i)) != 0)
+      {
+
+      }
+   }
+
+   // TODO: Make sure that placement malloc does not overwrite the ramdisk.
+   printf("Mod size: ");
 
    // Assume first 16MB:
    // TODO: get size from grub
    init_memory(0x1000000);
 
-  // TODO: make below a user space program!
-  printf("Welcome!\n");
+   // TODO: make below a user space program!
+   printf("Welcome!\n");
+
 
   while (1==1) 
   {
--- a/cos/kernel/kernel.h	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/kernel.h	Fri Jan 13 18:18:17 2012 +0100
@@ -34,7 +34,8 @@
   uint32_t strsize, addr, reserved;
 };
 
-struct multiboot_info {
+typedef struct multiboot_info_tag 
+{
   uint32_t flags; // Multiboot flags / version
   uint32_t mem_lower; // available memory from BIOS
   uint32_t mem_upper;
@@ -48,14 +49,23 @@
 
   uint32_t mmap_length;
   uint32_t mmap_addr;
-};
+} multiboot_info_t;
 
-struct memory_map {
+typedef struct memory_map_tag 
+{
   uint32_t size;
-  uint32_t baselow, basehigh;
-  uint32_t lenlow, lenhigh;
+  uint64_t base;
+  uint64_t length;
   uint32_t type;
-};
+} __attribute__((packed)) multiboot_memory_map_t;
+
+typedef struct
+{
+   uint32_t mod_start;
+   uint32_t mod_end;
+   uint32_t cmdline;
+   uint32_t pad;
+} multiboot_module_t;
 
 // Memory manager structures:
 typedef struct
@@ -195,6 +205,48 @@
   console_t *console;
 } task_t;
 
+/* Filesystem related types: */
+struct fs_node_tag;
+struct fs_dirent_tag;
+
+typedef uint64_t (*read_type_t)(struct fs_node_tag*, uint64_t, uint64_t, uint8_t*);
+typedef uint64_t (*write_type_t)(struct fs_node_tag*, uint64_t, uint64_t, uint8_t*);
+typedef void (*open_type_t)(struct fs_node_tag*);
+typedef void (*close_type_t)(struct fs_node_tag*);
+typedef struct fs_dirent_tag* (*readdir_type_t)(struct fs_node_tag*, int);
+
+typedef struct fs_node_tag
+{
+   char name[129];
+   uint64_t flags;
+   uint64_t length;
+   uint64_t inode;
+   // Accessor functions:
+   read_type_t read;
+   write_type_t write;
+   open_type_t open;
+   close_type_t close;
+   readdir_type_t readdir;
+} fs_node_t;
+
+typedef struct fs_dirent_tag
+{
+   char name[65];
+   uint64_t inode;
+} fs_dirent_t;
+
+#define FS_FILE 0x1
+#define FS_DIRECTORY 0x2
+
+uint64_t read_fs(fs_node_t *node, uint64_t offset, uint64_t size, uint8_t *buffer);
+uint64_t write_fs(fs_node_t *node, uint64_t offset, uint64_t size, uint8_t *buffer);
+void open_fs(fs_node_t *node);
+void close_fs(fs_node_t *node);
+fs_dirent_t* readdir_fs(fs_node_t *node, int i);
+
+// Initial ramdisk functions:
+fs_node_t* initialize_initrd(uint64_t location);
+
 // Variable argument list things:
 #define va_start(v,l)	__builtin_va_start(v,l)
 #define va_end(v)	__builtin_va_end(v)
@@ -261,7 +313,7 @@
 void doCPUID(int eax, int *ebx, int *ecx, int *edx);
 
 // Keyboard driver:
-void keyboardDriverUpdate(unsigned char scancode);
+void keyboardDriverUpdate(void);
 void getline(char *buffer, int len);
 
 // Timer:
--- a/cos/kernel/keyboard.c	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/keyboard.c	Fri Jan 13 18:18:17 2012 +0100
@@ -4,7 +4,9 @@
 static volatile uint8_t charAvail = 0;
 static volatile char kbdchar = ' ';
 
-static char keymap[128] = {
+// TODO: move to user land:
+static char keymap[128] = 
+{
   '?','?','1','2', '3', '4', '5','6', '7', '8','9', '0', '-','=', 0xe, '?',
   'q','w','e','r', 't', 'y', 'u','i', 'o', 'p','[', ']', '\n','?', 'a', 's',
   'd','f','g','h', 'j', 'k', 'l',';', '\'', '?','?', '?', 'z','x', 'c', 'v',
@@ -16,7 +18,8 @@
   '?','?','?','?', '?', '?', '?','?', '?', '?','?', '?', '?','?', '?', '?'
 };
 
-static char keymapUPPER[128] = {
+static char keymapUPPER[128] = 
+{
   '?','?','!','@', '#', '$', '%','^', '&', '*','(', ')', '_','+', '?', '?',
   'Q','W','E','R', 'T', 'Y', 'U','I', 'O', 'P','{', '}', '|','?', 'A', 'S',
   'D','F','G','H', 'J', 'K', 'L',':', '"', '?','?', '?', 'Z','X', 'C', 'V',
@@ -28,8 +31,10 @@
   '?','?','?','?', '?', '?', '?','?', '?', '?','?', '?', '?','?', '?', '?'
 };
 
-void keyboardDriverUpdate(unsigned char scancode)
+void keyboardDriverUpdate()
 {
+  unsigned char scancode = inb(0x60);
+
   switch(scancode) {
     case 0x2a:
       shiftstate = 1;
@@ -64,6 +69,7 @@
   return c;
 }
 
+// Move to user code:
 void getline(char *buffer, int len) 
 {
   char c;
--- a/cos/kernel/klib.c	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/klib.c	Fri Jan 13 18:18:17 2012 +0100
@@ -1,5 +1,6 @@
 #include "kernel.h"
 
+/* Panic and shutdown functions */
 void magicBochsBreak()
 {
    asm volatile("xchg %bx, %bx");
@@ -28,7 +29,7 @@
    asm volatile("hlt");
 }
 
-// IO port helpers:
+/* IO port helpers: */
 void outb(uint16_t port, uint8_t value)
 {
    asm volatile ("outb %1, %0" : : "dN" (port), "a" (value));
@@ -48,7 +49,7 @@
    return ret;
 }
 
-// string functions:
+/* string functions: */
 int strncmp(const char* s1, const char* s2, int size) 
 {
   int i;
@@ -59,7 +60,6 @@
   return 1;
 }
 
-// mem functions:
 void memset(void* data, uint8_t value, uint64_t size)
 {
    uint64_t i;
--- a/cos/kernel/mm.c	Tue Jan 10 20:40:35 2012 +0100
+++ b/cos/kernel/mm.c	Fri Jan 13 18:18:17 2012 +0100
@@ -58,8 +58,8 @@
 // Memory manager functions:
 void init_memory(uint64_t total_mem_size)
 {
-   printf("Size of PT_t = %d\n", sizeof(PD_t));
-   printf("Size of page_t = %d\n", sizeof(page_t));
+   // Only here placement malloc is used!
+   //
    // Allocate and clear bits to remember which 4kb-frames are in use:
    nframes = (total_mem_size / 0x1000);
    frames = (uint64_t*)kmalloc_int( (nframes / 64) * sizeof(uint64_t) );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/makeinitrd.py	Fri Jan 13 18:18:17 2012 +0100
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+
+# Script for generation of an initial ramdisk that contains 
+# the first programs to run.
+
+import struct
+import sys
+
+if len(sys.argv) < 3:
+   print('Usage: {0} output file1 [file2] ...'.format(sys.argv[0]))
+   sys.exit(1)
+
+outputfilename = sys.argv[1]
+inputFileNames = sys.argv[2:]
+
+with open(outputfilename, 'wb') as outputFile:
+   # Amount of files:
+   outputFile.write(struct.pack('<I', 0x1337babe))
+   outputFile.write(struct.pack('<I', len(inputFileNames)))
+   for inputFileName in inputFileNames:
+      # Magic:
+      outputFile.write(struct.pack('<I', 0xcafebabe))
+
+      # Filename:
+      fn = inputFileName.encode('ascii')
+      outputFile.write(struct.pack('<I', len(fn)))
+      outputFile.write(fn)
+
+      # Data:
+      with open(inputFileName, 'rb') as inputFile:
+         data = inputFile.read()
+      outputFile.write(struct.pack('<I', len(data)))
+      outputFile.write(data)
+