changeset 42:980b2f14c9be

Merge
author windel
date Fri, 03 Feb 2012 18:01:18 +0100
parents 35cc54e078dd (diff) 600f48b74799 (current diff)
children e47bfef80baf
files data/lcfos.png ide/compiler/__init__.py ide/compiler/assembler.py ide/compiler/builtin.py ide/compiler/codegenerator.py ide/compiler/compiler.py ide/compiler/display.py ide/compiler/errors.py ide/compiler/lexer.py ide/compiler/modules.py ide/compiler/nodes.py ide/compiler/parser.py ide/compiler/symboltable.py ide/ide/__init__.py ide/ide/astviewer.py ide/ide/codeeditor.py ide/ide/ide.py ide/project.py ide/runbuild.py ide/runide.py ide/runtests.py testproject/main.mod testproject/test.lcp testproject/test.mod
diffstat 12 files changed, 347 insertions(+), 231 deletions(-) [+]
line wrap: on
line diff
--- a/README	Fri Feb 03 18:40:43 2012 +0100
+++ b/README	Fri Feb 03 18:01:18 2012 +0100
@@ -22,3 +22,22 @@
 $ cd ide
 $ python runide.py
 
+= About the C version of the OS =
+
+To build the C kernel, enter:
+$ cd cos
+$ make
+
+Running the OS with bochs:
+$ bochs -q
+
+required tools:
+- bochs: for simulating the OS
+- mtools: for copying files to the bootdisk
+- nasm: for assembler instructions
+- gcc: for compiling the C sources
+- make: for building the system
+- python 3: for building the initial ramdisk
+
+Enjoy!
+
--- a/cos/Makefile	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/Makefile	Fri Feb 03 18:01:18 2012 +0100
@@ -2,7 +2,7 @@
 
 all:
 	make -C kernel
-	python makeinitrd.py lcfosinitrd.img hello/hello.bin
+	python utils/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 ::
--- a/cos/README	Fri Feb 03 18:40:43 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-This directory contains the C version of the OS.
-
-To build the kernel, enter:
-$ make
-
-To make the bootdisk, hit:
-$ make bootdisk
-
-Running the OS with bochs:
-$ bochs -q
-
-required tools:
-- bochs: for simulating the OS
-- mtools: for copying files to the bootdisk
-- nasm: for assembler instructions
-- gcc: for compiling the C sources
-- make: for building the system
-- python: for building the initial ramdisk
-
-Enjoy!
-
--- a/cos/kernel/handlers.c	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/kernel/handlers.c	Fri Feb 03 18:01:18 2012 +0100
@@ -1,43 +1,43 @@
 #include "kernel.h"
 
 // Assembler wrapper prototypes:
-void INT255(void);
-void INT0(void);
-void INT1(void);
-void INT2(void);
-void INT3(void);
-void INT4(void);
-void INT5(void);
-void INT6(void);
-void INT7(void);
-void INT8(void);
-void INT9(void);
-void INT10(void);
-void INT11(void);
-void INT12(void);
-void INT13(void);
-void INT14(void);
-void INT16(void);
-void INT17(void);
-void INT18(void);
-void INT19(void);
+extern void INT255(void);
+extern void INT0(void);
+extern void INT1(void);
+extern void INT2(void);
+extern void INT3(void);
+extern void INT4(void);
+extern void INT5(void);
+extern void INT6(void);
+extern void INT7(void);
+extern void INT8(void);
+extern void INT9(void);
+extern void INT10(void);
+extern void INT11(void);
+extern void INT12(void);
+extern void INT13(void);
+extern void INT14(void);
+extern void INT16(void);
+extern void INT17(void);
+extern void INT18(void);
+extern void INT19(void);
 // Remapped irq assembler wrappers:
-void INT32(void);
-void INT33(void);
-void INT34(void);
-void INT35(void);
-void INT36(void);
-void INT37(void);
-void INT38(void);
-void INT39(void);
-void INT40(void);
-void INT41(void);
-void INT42(void);
-void INT43(void);
-void INT44(void);
-void INT45(void);
-void INT46(void);
-void INT47(void);
+extern void INT32(void);
+extern void INT33(void);
+extern void INT34(void);
+extern void INT35(void);
+extern void INT36(void);
+extern void INT37(void);
+extern void INT38(void);
+extern void INT39(void);
+extern void INT40(void);
+extern void INT41(void);
+extern void INT42(void);
+extern void INT43(void);
+extern void INT44(void);
+extern void INT45(void);
+extern void INT46(void);
+extern void INT47(void);
 
 // THE interrupt descriptor table:
 IDT_entry *idt = (IDT_entry*)0x5000;
@@ -184,8 +184,8 @@
    panic("No resolution to page fault!");
 
 }
+
 // Global isr handler:
-
 // Hopefully, this function get called with the correct registers.
 void isr_handler(uint64_t* registers)
 {
@@ -223,30 +223,3 @@
    outb(0x20, 0x20); // EOI to master
 }
 
-// Interrupt service routines:
-
-void INT14handler()
-{
-  uint64_t faulting_address;
-
-  printf("Segfault!\n");
-
-  // Retrieve failed page from CR2:
-  asm volatile("mov %%cr2, %0" : "=r" (faulting_address));
-
-  printf("INT14 called! Page fault for address 0x%X!\n", faulting_address);
-
-  panic("Unhandled exception!");
-}
-
-void INT15handler() 
-{
-  printf("INT15 called!\n");
-  panic("Unhandled exception!");
-}
-
-void INTDEF_handler() 
-{
-  panic("Default int handler called\n");
-}
-
--- a/cos/kernel/initrd.c	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/kernel/initrd.c	Fri Feb 03 18:01:18 2012 +0100
@@ -4,22 +4,81 @@
 
 #include "kernel.h"
 
-fs_node_t *initrd_root = 0;
-
-typedef struct
-{
-   uint32_t magic;
-   uint32_t numfiles;
-} initrd_header_t;
+// Global data struct:
+initrd_file_header_t *files;
 
 fs_node_t* initialize_initrd(uint64_t location)
 {
-   // We need a valid malloc here!
-   initrd_root = (fs_node_t*)kmalloc(sizeof(fs_node_t));
+   uint32_t *u32ptr;
+
+   u32ptr = (uint32_t*)location;
+   if (*u32ptr != 0x1337babe)
+   {
+      printf("Invalid ramdisk magic\n");
+      return 0;
+   }
 
-   initrd_header_t *header = (initrd_header_t*)location;
-   initrd_root->length = header->numfiles;
+   // Allocate root dir:
+   fs_node_t *root = (fs_node_t*)kmalloc(sizeof(fs_node_t));
+   memset(root, 0, sizeof(fs_node_t));
+   root->flags = FS_DIRECTORY;
+   root->readdir = initrd_readdir;
+   
+   u32ptr++;
+   root->length = *u32ptr;
+   
+   // Allocate an node for each file.
+   void *x = kmalloc(sizeof(fs_node_t) * root->length);
+   memset(x, 0, sizeof(fs_node_t) * root->length);
 
-   return initrd_root;
+   for (i = 0; i < root->length; i++)
+   {
+      
+   }
+
+   return root;
 }
 
+void load_ramdisk()
+{
+   printf("Ramdisk location: %p\n", ramdisk_location);
+
+   fs_node_t *root = initialize_initrd(ramdisk_location);
+
+   if (root != 0)
+   {
+      fs_node_t *node = 0;
+      int i = 0;
+      while ( (node = readdir_fs(root, i)) != 0)
+      {
+         printf("File %s\n", node->name);
+      }
+   }
+}
+
+static uint64_t initrd_read(fs_node_t *node, uint64_t offset, uint64_t size, void *buffer)
+{
+   // TODO: check errors
+
+   if (size > node->length)
+   {
+      return 0;
+   }
+
+   if (size + offset > node->length)
+   {
+      size = node->length - offset;
+   }
+
+   memcpy(buffer, node.data + offset, size);
+   return size;
+}
+
+fs_node_t *readdir(fs_node_t *dir, int index)
+{
+   if (index >= dir->length)
+   {
+      return 0;
+   }
+}
+
--- a/cos/kernel/kernel.c	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/kernel/kernel.c	Fri Feb 03 18:01:18 2012 +0100
@@ -13,23 +13,7 @@
    // From here kmalloc can be used.
    keyboard_init();
    timer_init();
-   printf("Ramdisk location: %p\n", ramdisk_location);
-
-   /*
-   fs_node_t *fs_root = 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)
-      {
-
-      }
-   }
-   */
+   load_ramdisk();
 
    // TODO: make shell a user space program!
    shell(); // Start user shell
--- a/cos/kernel/kernel.h	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/kernel/kernel.h	Fri Feb 03 18:01:18 2012 +0100
@@ -147,7 +147,6 @@
    uint64_t physicalAddress;
 } PD_t;
 
-
 typedef struct
 {
    unsigned present : 1;
@@ -181,6 +180,20 @@
 // Make memmap a PML4 type:
 typedef PML4_t memmap_t;
 
+// Malloc related functions
+typedef struct {
+   uint64_t magic;
+   uint64_t state;
+   uint64_t size;
+} heap_header_t;
+
+typedef struct
+{
+   heap_header_t *first_block;
+   uint64_t start_address;
+   uint64_t end_address;
+} heap_t;
+
 // Task related types:
 typedef struct 
 {
@@ -254,6 +267,8 @@
 // Initial ramdisk functions:
 fs_node_t* initialize_initrd(uint64_t location);
 
+void load_ramdisk(void);
+
 // Variable argument list things:
 #define va_start(v,l)	__builtin_va_start(v,l)
 #define va_end(v)	__builtin_va_end(v)
@@ -263,23 +278,25 @@
 /* Global variables */
 extern uint64_t kernel_end;
 extern uint64_t placement_address;
+extern memmap_t* kernel_map;
 
 /* Procedures */
 
 // memory functions:
 // TODO: remove some redundant API functions:
-void init_heap();
 void init_memory(uint64_t total_mem_size);
 page_t* get_page(uint64_t address, memmap_t*);
-void* kmalloc(uint64_t size);
-void kfree(void* ptr);
-void* kmalloc_int(uint64_t size);
-void* kmalloc_aligned_int(uint64_t size);
-void mappage(uint64_t address);
+void alloc_frame(page_t *page);
 void loadPageTable(void* tableAddress);
 void switch_mapping(memmap_t* mapping);
 void enablePaging();
 
+// Malloc related:
+void* kmalloc(uint64_t size);
+void* kmalloc_a(uint64_t size); // Aligned on a 4 KiB page.
+void kfree(void* ptr);
+heap_t* create_heap(uint64_t location, uint64_t size);
+
 // task related functions:
 void initialize_tasking();
 void new_task();
--- a/cos/kernel/malloc.c	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/kernel/malloc.c	Fri Feb 03 18:01:18 2012 +0100
@@ -5,104 +5,153 @@
 
 uint64_t placement_address = (uint64_t)&kernel_end;
 
-void* kmalloc_int(uint64_t size)
-{
-   uint64_t tmp = placement_address;
-   placement_address += size;
-   return (void*)tmp;
-}
-
-void* kmalloc_aligned_int(uint64_t size)
-{
-   if ( (placement_address | 0xFFF) != 0 )
-   {
-      placement_address &= ~(0xFFF);
-      placement_address += 0x1000;
-   }
-   uint64_t tmp = placement_address;
-   placement_address += size;
-   return (void*)tmp;
-}
-
-
 // ================= Other malloc
 // TODO: move this to user space?
 
 #define HEAP_MAGIC 0xc0ffee
-#define HEAP_START 0x400000
-#define HEAP_SIZE  0x200000
 #define HEAP_INUSE 1
 #define HEAP_FREE 0
 
-typedef struct {
-   uint64_t magic;
-   uint64_t state;
-   uint64_t size;
-} heap_t;
-
 /*
   malloc and free divide the chunks of memory present at the heap
   of the kernel into smaller parts.
   The heap is located at: 0x
 */
 
-static heap_t* kernel_heap = (heap_t*) 0x400000; // 4 MB - 6 MB is heap
+static heap_t* kernel_heap = 0; 
+
+void expand_heap(heap_t *heap, uint64_t newsize);
+
 /* Allocates 'size' bytes and returns the pointer if succesfull.
+   Before the kernel is initialized, placement malloc is used.
    Kernelpanic in case of failure..
 */
-
-void* kmalloc(uint64_t size) 
+static void* kmalloc_int(uint64_t size, uint64_t aligned) 
 {
-   return kmalloc_int(size);
-
-   // Start at the beginning of our heap and search a free block:
-   heap_t *current = kernel_heap;
-   while (current->magic == HEAP_MAGIC)
+   // Check if there exists a kernel heap. If not, use placement malloc for now.
+   if (kernel_heap == 0)
    {
-      if ((current->state == HEAP_FREE) && (current->size >= size))
+      // Before that the heap is initialized, use placement malloc
+      if (aligned == 1)
       {
-         // Mark block as used:
-         current->state = HEAP_INUSE;
+         // Align placement address
+         if ( (placement_address | 0xFFF) != 0 )
+         {
+            placement_address &= ~(0xFFF);
+            placement_address += 0x1000;
+         }
+      }
+      uint64_t tmp = placement_address;
+      placement_address += size;
+      return (void*)tmp;
+   }
+   else
+   {
+      // We have a kernel heap, search the heap for a block of suitable size.
 
-         // Insert a heap header if required:
-         if (current->size > size + sizeof(heap_t) + 1)
+      // Start at the beginning of our heap and search a free block:
+      heap_header_t *current = kernel_heap->first_block;
+      while (current->magic == HEAP_MAGIC)
+      {
+         if ((current->state == HEAP_FREE) && (current->size >= size))
          {
-            // Calculate location of the inserted header:
-            heap_t *newheader = (heap_t*) (((char*)current)+size+sizeof(heap_t));
+            // We found a hole with suitable size. Determine if split is of any use.
+
+            // Insert a heap header if required:
+            if (current->size > size + sizeof(heap_t) + 1)
+            {
+               // Calculate location of the inserted header:
+               heap_header_t *newheader = (heap_header_t*) (((uint64_t)current)+size+sizeof(heap_header_t));
 
-            // Set the new header fields:
-            newheader->size = current->size - size - sizeof(heap_t);
-            newheader->state = HEAP_FREE;
-            newheader->magic = HEAP_MAGIC;
+               // Set the new header fields:
+               newheader->size = current->size - size - sizeof(heap_header_t);
+               newheader->state = HEAP_FREE;
+               newheader->magic = HEAP_MAGIC;
 
-            // Set the size of this block
-            current->size = size; 
+               // Set the size of this block
+               current->size = size; 
+            }
+            else
+            {
+               // We allocate this whole block
+               // Mark block as used:
+               current->state = HEAP_INUSE;
+            }
+            // Calculate the size of the block:
+            char *address = ((char*)current)+sizeof(heap_header_t);
+            return address;
+            
          }
-         else
-         {
-            // We allocate this whole block
-         }
-         // Calculate the size of the block:
-         char *address = ((char*)current)+sizeof(heap_t);
-         return address;
-         
+         // Goto next heap block:
+         current = (heap_header_t*)(((uint64_t) current) + current->size + sizeof(heap_header_t));
       }
-      // Goto next heap block:
-      current = (heap_t*)(((char*) current) + current->size + sizeof(heap_t));
+
+      // We did not find a block large enough. Expand the heap and try again.
+      expand_heap(kernel_heap, 0x10000000);
+      return kmalloc_int(size, aligned); 
    }
-   return 0x0;
+}
+
+// Convenient wrappers:
+void* kmalloc(uint64_t size)
+{
+   return kmalloc_int(size, 0);
+}
+
+void* kmalloc_a(uint64_t size)
+{
+   return kmalloc_int(size, 1);
 }
 
 void kfree(void* ptr) 
 {
-  printf("Free address %x\n", ptr);
+   printf("Free address %x\n", ptr);
+   if (kernel_heap == 0)
+   {
+      return;
+   }
+   else
+   {
+      // TODO
+   }
+   // TODO: free blocks:
 }
 
-void init_heap(void)
+heap_t* create_heap(uint64_t location, uint64_t size)
 {
-   // Initialize the kernel heap:
-   kernel_heap->magic = HEAP_MAGIC;
-   kernel_heap->state = HEAP_FREE;
-   kernel_heap->size = HEAP_SIZE - sizeof(heap_t);
+   // Make sure that the new heap location is mapped into the address space:
+   uint64_t i = 0;
+   while (i < size)
+   {
+      alloc_frame( get_page(location + i, kernel_map));
+      i += 0x1000;
+   }
+
+   // create new heap structure:
+   heap_t* h = (heap_t*)kmalloc(sizeof(heap_t));
+   
+   // Create one big hole:
+   h->first_block = (heap_header_t*)location; // Place header at beginning of heap
+   h->first_block->magic = HEAP_MAGIC;
+   h->first_block->state = HEAP_FREE;
+   h->first_block->size = size - sizeof(heap_header_t);
+   return h;
 }
 
+// Make the total heap bigger:
+void expand_heap(heap_t *heap, uint64_t newsize)
+{
+   uint64_t oldsize = heap->end_address - heap->start_address;
+   if (newsize < oldsize)
+   {
+      panic("Cannot expand heap to a smaller size\n");
+   }
+
+   uint64_t i = oldsize;
+   while (i < newsize)
+   {
+      alloc_frame( get_page(heap->start_address + i, kernel_map));
+      i += 0x1000;
+   }
+}
+
--- a/cos/kernel/mm.c	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/kernel/mm.c	Fri Feb 03 18:01:18 2012 +0100
@@ -6,13 +6,19 @@
 
 #include "kernel.h"
 
+#define HEAP_START 0xC000000000000000
+#define HEAP_INITIAL_SIZE  0x100000
+
 // Bitmap that keeps track of all the 4 kB memory pages in the system:
 static uint64_t *frames = 0;
 static uint64_t nframes = 0;
 
 memmap_t* kernel_map = 0; // kernel memory mapping
+// TODO: determine if this is required.
 memmap_t* current_map = 0; // The currently active memory mapping
 
+heap_t* kernel_heap = 0;
+
 static void set_frame(uint64_t frame)
 {
    uint64_t idx = frame / 64;
@@ -56,6 +62,24 @@
    return (uint64_t) -1;
 }
 
+void memory_status(void)
+{
+   // Determine amount of used memory.
+   uint64_t i, j;
+   uint64_t inuse = 0;
+   for (i = 0; i < nframes / 64; i++)
+   {
+      for (j = 0; j < 64; j++)
+      {
+         if ((frames[i] & (1UL<<j)) == (1UL<<j))
+         {
+            inuse++;
+         }
+      }
+   }
+   printf("Memory: %d, in use: %d\n", nframes/0x100, inuse/0x100);
+}
+
 /*
  * Initializes the memory manager, allocating a bitmap once.
  */
@@ -63,22 +87,27 @@
 {
    printf("Running with %d MB ram\n", total_mem_size / 1000000);
 
+   // Memory size is from address 0x100000
+   total_mem_size += 0x100000;
+
    // Only here placement malloc is used!
    //
    // Allocate and clear bits to remember which 4KiB-frames are in use:
-   nframes = (total_mem_size / 0x1000); // Calculate number of frames
-   frames = (uint64_t*)kmalloc_int( (nframes / 64) * sizeof(uint64_t) );
-   memset(frames, 0, (nframes / 64) * sizeof(uint64_t));
+   // Calculate number of frames. memory size is indicated from address 0x100000
+   nframes = (total_mem_size) / 0x1000; // Calculate number of frames
+   int numbytes = ((nframes / 64) + 1) * sizeof(uint64_t);
+   frames = (uint64_t*)kmalloc(numbytes);
+   memset(frames, 0, numbytes);
 
    // Create kernel map:
-   kernel_map = (memmap_t*)kmalloc_aligned_int(sizeof(memmap_t));
+   kernel_map = (memmap_t*)kmalloc_a(sizeof(memmap_t));
    memset(kernel_map, 0, sizeof(memmap_t));
 
    // Identity map lower memory and mark as used by the kernel.
    // Mark as used by the kernel:
    uint64_t i;
    i = 0;
-   while ( i <= placement_address)
+   while ( i <= placement_address + 0x100000)
    {
       page_t *page;
 
@@ -95,9 +124,10 @@
    }
 
    // Set the created mapping as active:
-   switch_mapping(kernel_map);
+   switch_mapping(kernel_map); // Loads cr3
 
    // TODO: set the use of placement malloc to invalid after here.
+   // kernel_heap = create_heap(HEAP_START, HEAP_INITIAL_SIZE);
 }
 
 void alloc_frame(page_t *page)
@@ -130,6 +160,7 @@
 {
    current_map = mapping;
 
+   // Load table address:
    asm volatile("mov %0, %%cr3" :: "r"(&mapping->table));
 
    // Enable paging (and flush cache):
@@ -152,7 +183,9 @@
    else
    {
       // Create new table:
-      pdpt = (PDPT_t*)kmalloc_aligned_int(sizeof(PDPT_t));
+   printf("Get page for address %x\n", address);
+      // TODO: make sure that this function calls kmalloc instead of placement malloc.
+      pdpt = (PDPT_t*)kmalloc_a(sizeof(PDPT_t));
       memset(pdpt, 0, sizeof(PDPT_t));
 
       // TODO: get function like virt2phys or something here
@@ -173,7 +206,7 @@
    else
    {
       // Create a new table:
-      pd = (PD_t*)kmalloc_aligned_int(sizeof(PD_t));
+      pd = (PD_t*)kmalloc_a(sizeof(PD_t));
       memset(pd, 0, sizeof(PD_t));
 
       // Enter table into PDPT:
@@ -195,7 +228,7 @@
    else
    {
       // Create table:
-      pt = (PT_t*)kmalloc_aligned_int(sizeof(PD_t));
+      pt = (PT_t*)kmalloc_a(sizeof(PD_t));
       memset(pt, 0, sizeof(PT_t));
 
       // Enter PT into PD:
--- a/cos/kernel/shell.c	Fri Feb 03 18:40:43 2012 +0100
+++ b/cos/kernel/shell.c	Fri Feb 03 18:01:18 2012 +0100
@@ -17,6 +17,8 @@
    kfree(a);
 }
 
+void memory_status(void);
+
 void shell()
 {
    printf("Welcome!\n");
@@ -30,6 +32,7 @@
       if (buffer[0] == 'x') 
       {
          printf("System time in ms: %d\n", getTimeMS());
+         memory_status();
       }
     if (buffer[0] == 't')
     {
--- a/cos/makeinitrd.py	Fri Feb 03 18:40:43 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-#!/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)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/utils/makeinitrd.py	Fri Feb 03 18:01:18 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)
+