mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
starting list object implementation
This commit is contained in:
136
bootstrap/init.ccp
Normal file
136
bootstrap/init.ccp
Normal file
@@ -0,0 +1,136 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// bootstrap/init.ccp: Bootstrapping code.
|
||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "iris.hh"
|
||||
|
||||
struct file:
|
||||
unsigned size
|
||||
// Only the first 16 characters of the name are used, because that's much easier.
|
||||
// This means that file names must be different in the first 16 characters if sort order matters.
|
||||
char name[16]
|
||||
String string
|
||||
|
||||
static unsigned num_files
|
||||
static file *files
|
||||
static unsigned index
|
||||
static Kernel::Memory top_memory
|
||||
static unsigned max_pages
|
||||
static char *mapping
|
||||
|
||||
// Get the initial block device and filesystem.
|
||||
static Directory receive_devices ():
|
||||
String dev
|
||||
Filesystem fs
|
||||
for unsigned i = 0; i < 2; ++i:
|
||||
Kernel::wait ()
|
||||
if Kernel::recv.data[0].l != Parent::PROVIDE_DEVICE:
|
||||
kdebug ("Invalid bootstrap request.\n")
|
||||
Kernel::panic (0)
|
||||
switch Kernel::recv.data[1].l:
|
||||
case String::ID:
|
||||
if dev:
|
||||
kdebug ("duplicate device.\n")
|
||||
Kernel::panic (0)
|
||||
dev = Kernel::get_arg ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Filesystem::ID:
|
||||
if fs:
|
||||
kdebug ("duplicate filesystem.\n")
|
||||
Kernel::panic (0)
|
||||
fs = Kernel::get_arg ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected device: ")
|
||||
kdebug_num (Kernel::recv.data[1].l)
|
||||
kdebug_char ('\n')
|
||||
Kernel::panic (0)
|
||||
// Initialize the root file system.
|
||||
Directory root = fs.use_device (dev.copy ())
|
||||
Kernel::free_cap (dev)
|
||||
Kernel::free_cap (fs)
|
||||
return root
|
||||
|
||||
// Make a list of all files.
|
||||
static void list_files (Directory root):
|
||||
Kernel::Num fullsize = root.get_size ()
|
||||
if fullsize.h != 0:
|
||||
kdebug ("Too many files in bootstrap directory.\n")
|
||||
Kernel::panic (0)
|
||||
num_files = fullsize.l
|
||||
files = new file[num_files]
|
||||
Kernel::Caps caps = Kernel::my_memory.create_caps (num_files * 2)
|
||||
unsigned slot = Kernel::alloc_slot ()
|
||||
caps.use (slot)
|
||||
for unsigned i = 0; i < num_files; ++i:
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2))
|
||||
String n = root.get_name (i)
|
||||
n.get_chars (0, files[i].name)
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, i * 2 + 1))
|
||||
files[i].string = root.get_file_ro (i)
|
||||
Kernel::Num fullsize = files[i].string.get_size ()
|
||||
if fullsize.h != 0:
|
||||
kdebug ("initial file size too large.\n")
|
||||
Kernel::panic (0)
|
||||
files[i].size = fullsize.l
|
||||
if max_pages < (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK:
|
||||
max_pages = (fullsize.l + PAGE_SIZE - 1) & PAGE_MASK
|
||||
|
||||
// Sort the list of files.
|
||||
static bool is_less (file *f1, file *f2):
|
||||
return
|
||||
|
||||
// Bubble sort.
|
||||
static void sort ():
|
||||
index = new unsigned[num_files]
|
||||
index[0] = 0
|
||||
// Invariant: index[0...f-1] is sorted.
|
||||
for unsigned f = 1; f < num_files; ++f:
|
||||
// Bubble up until top. Test for less-than, because it wraps to maxunsigned.
|
||||
unsigned i
|
||||
// Invariant: index[0...f] \ index[i+1] is sorted and index[i+1...f] is sorted.
|
||||
for i = f - 1; i < f; --i:
|
||||
if is_less (&files[index[i]], &files[f]):
|
||||
break
|
||||
index[i + 1] = index[i]
|
||||
index[i + 1] = f
|
||||
|
||||
static void run (file *f):
|
||||
Kernel::Memory mem = top_memory.create_memory ()
|
||||
unsigned num_pages = (f->size + PAGE_SIZE - 1) & PAGE_MASK
|
||||
for unsigned p = 0; p < num_pages; ++p:
|
||||
pages[p] = f->string.get_page (p << PAGE_BITS, mem.create_page ())
|
||||
Kernel::my_memory.map (pages[p], (unsigned)&mapping[p << PAGE_BITS])
|
||||
// TODO: parse elf file.
|
||||
|
||||
Kernel::Num start ():
|
||||
top_memory = Kernel::get_top_memory ()
|
||||
// Wait for the debugging device to be active, in case there is one.
|
||||
Kernel::schedule ()
|
||||
Directory root = receive_devices ()
|
||||
root.lock_ro ()
|
||||
list_files (root)
|
||||
sort ()
|
||||
pages = new Kernel::Page[max_pages]
|
||||
mapping = alloc_space (max_pages)
|
||||
for unsigned i = 0; i < num_files; ++i:
|
||||
run (files[i])
|
||||
root.unlock_ro ()
|
||||
return 0
|
||||
Reference in New Issue
Block a user