#pypp 0 // Iris: micro-kernel for a capability-based operating system. // bootstrap/init.ccp: Bootstrapping code. // Copyright 2009 Bas Wijnen // // 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 . #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