1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-12-28 12:49:54 +02:00

working boot loader

This commit is contained in:
Bas Wijnen 2010-08-23 23:55:51 +02:00
parent 04ed743042
commit aef83317c9
11 changed files with 380 additions and 124 deletions

View File

@ -85,11 +85,21 @@ namespace Iris:
void set_block (Num idx, Page page, unsigned size = PAGE_SIZE, unsigned offset = 0):
ocall (page, Iris::Num (CAP_MASTER_DIRECT | SET_BLOCK, size << 16 | offset), idx)
// This interface allows another kernel to be booted by Iris.
struct Boot : public Cap:
Boot (Cap c = Cap ()) : Cap (c):
enum request:
BOOT = WString::ID
ID
// Boot a new kernel.
void boot (String code, unsigned load, unsigned entry):
ocall (code, CAP_MASTER_DIRECT | BOOT, Iris::Num (load, entry))
// Every process which wants to be switchable through a terminal must implement this interface.
struct Device : public Cap:
Device (Cap c = Cap ()) : Cap (c):
enum request:
RESET = WString::ID
RESET = Boot::ID
ID
// Reset the device. This is called by the terminal while switching owners.
void reset ():

View File

@ -1,5 +1,6 @@
# driver <name> = '<filename>' load a file into memory to be run priviledged.
# program <name> = '<filename>' load a file into memory to be run normally.
# file <name> = '<filename>' load a file into memory as a String.
# receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
# sysreq <cap> use a capability as the system request keyboard.
# give <name> / <type> [, <index>] = <cap> give this capability to this program when it requests it.
@ -12,24 +13,32 @@
receive driver_gpio / Event = sdmmc_gpio
sysreq sysreq
driver nand = "nand.elf"
#driver nand = "nand.elf"
#driver driver_lcd = "lcd.elf"
#receive driver_lcd / Display = display
#receive driver_lcd / Setting = display_bright
#driver driver_boot = "boot.elf"
#receive driver_boot / Boot = boot
#driver driver_buzzer = "buzzer.elf"
#receive driver_buzzer / Buzzer = buzzer
#file kernel = "kernel.raw"
#program booter = "booter.elf"
#give booter / String = kernel
#give booter / Boot = boot
#program alarm = "alarm.elf"
#receive alarm / UI = ui
driver driver_lcd = "lcd.elf"
receive driver_lcd / Display = display
receive driver_lcd / Setting = display_bright
#program gui = "gui.elf"
#give gui / UI = ui
#give gui / Display = display
#give gui / Setting = display_bright
#give gui / Buzzer = buzzer
#give gui / Keyboard = keyboard
driver driver_buzzer = "buzzer.elf"
receive driver_buzzer / Buzzer = buzzer
program alarm = "alarm.elf"
receive alarm / UI = ui
program gui = "gui.elf"
give gui / UI = ui
give gui / Display = display
give gui / Setting = display_bright
give gui / Buzzer = buzzer
give gui / Keyboard = keyboard
#driver sdmmc = "sd+mmc.elf"
#receive sdmmc / WString = sdmmc

View File

@ -501,7 +501,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
break
case Iris::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK:
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_MEMORY:
panic (0x54365435, "non-memory argument to alloc_range")
dpanic (0x54365435, "non-memory argument to alloc_range")
reply_num (Iris::ERR_INVALID_ARGUMENT)
return
kMemory *mem = (kMemory *)c->arg->protected_data.l
@ -559,7 +559,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
case Iris::Thread::PRIV_POWEROFF & REQUEST_MASK:
arch_poweroff ()
case Iris::Thread::PRIV_BOOT & REQUEST_MASK:
arch_boot (c->data[1].l)
arch_boot (c->data[1].l, c->data[1].h)
case Iris::Thread::PRIV_PANIC & REQUEST_MASK:
if c->data[1].l == 0xdeaddead:
dbg_code.l = 1

View File

@ -582,8 +582,8 @@ namespace Iris:
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_REBOOT)
inline void poweroff ():
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_POWEROFF)
inline void boot (unsigned address):
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_BOOT, address)
inline void boot (unsigned address, unsigned arg):
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_BOOT, Iris::Num (address, arg))
void Receiver::sleep (unsigned value):
set_alarm (value)

View File

@ -323,7 +323,7 @@ void kPage_arch_update_mapping (kPage *page)
void arch_register_interrupt (unsigned num, kReceiverP r)
void arch_reboot ()
void arch_poweroff ()
void arch_boot (unsigned address)
void arch_boot (unsigned address, unsigned arg)
void arch_uncache_page (unsigned page)
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)

View File

@ -19,10 +19,15 @@
#define ARCH
#include "../kernel.hh"
typedef unsigned cacheline[8]
void arch_flush_cache ():
for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line:
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
__asm__ volatile ("\t.set noreorder\n"
"\tlui $k0, 0x8000\n"
"\tori $k1, $k0, 0x4000 - 0x20\n"
"1:\tcache 0, 0($k0)\n"
"\tcache 1, 0($k0)\n"
"\tbne $k0, $k1, 1b\n"
"\taddiu $k0, $k0, 0x20\n"
"\t.set reorder\n")
static kThread *handle_exit ():
dbg_check ()

View File

@ -26,7 +26,7 @@ udc_boot_programs = udc
sd_boot_programs = sd+mmc partition fat
standard_boot_programs = bootinit
programs = init gpio lcd bsquare ball buzzer metronome elfrun alarm rtc gui nand test $(udc_boot_programs) $(sd_boot_programs) $(standard_boot_programs)
programs = init gpio lcd bsquare ball buzzer metronome elfrun alarm rtc gui nand test boot booter $(udc_boot_programs) $(sd_boot_programs) $(standard_boot_programs)
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
CROSS = mipsel-linux-gnu-

View File

@ -118,8 +118,8 @@ void arch_poweroff ():
kdebug ("Power down failed! Rebooting instead.\n")
arch_reboot ()
void arch_boot (unsigned address):
// Boot into another kernel.
void arch_boot (unsigned address, unsigned arg):
sync_serial ()
// Boot into another kernel.
arch_flush_cache ()
return ((void (*)())address) ()
((void (*)(unsigned))address) (arg)

136
source/boot.ccp Normal file
View File

@ -0,0 +1,136 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// source/boot.ccp: Boot into another kernel.
// Copyright 2010 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 <iris.hh>
#include <devices.hh>
extern "C":
extern unsigned pre_code, pre_end, post_code, post_end
struct args_t:
unsigned load
unsigned size
unsigned entry
unsigned source
Iris::Num start ():
unsigned *loader_addr = (unsigned *)0x15000
unsigned *page_addr = (unsigned *)0x16000
unsigned *tmp_addr = (unsigned *)0x17000
Iris::Boot cap = Iris::my_receiver.create_capability (0)
Iris::my_parent.provide_capability <Iris::Boot> (cap.copy ())
Iris::free_cap (cap)
Iris::my_parent.init_done ()
while true:
Iris::wait ()
switch Iris::recv.data[0].l:
case Iris::Boot::BOOT:
Iris::String code = Iris::get_arg ()
unsigned load = Iris::recv.data[1].l
unsigned entry = Iris::recv.data[1].h
Iris::Num lsize = code.get_size ()
if lsize.h != 0:
Iris::panic (lsize.h, "string to boot is too large to be loaded")
unsigned size = lsize.l
unsigned pages = ((size + ~PAGE_MASK) >> PAGE_BITS) + 1
unsigned phys = Iris::my_memory.alloc_range (pages)
if phys & ~PAGE_MASK:
Iris::panic (size, "unable to allocate space for string to load")
unsigned target, offset
if phys < (load & ~0xa0000000):
Iris::debug ("pre-loading\n")
Iris::Page pre = Iris::my_memory.create_page ()
pre.alloc_physical (phys, true, true)
Iris::my_memory.map (pre, (unsigned)loader_addr)
for unsigned i = 0; i < &pre_end - &pre_code; ++i:
loader_addr[i] = (&pre_code)[i]
target = phys
offset = 1
else:
Iris::debug ("post-loading\n")
Iris::Page post = Iris::my_memory.create_page ()
post.alloc_physical (phys + ((pages - 1) << PAGE_BITS), true, true)
Iris::my_memory.map (post, (unsigned)loader_addr)
for unsigned i = 0; i < &post_end - &post_code; ++i:
loader_addr[i] = (&post_code)[i]
target = phys + ((pages - 1) << PAGE_BITS)
offset = 0
Iris::Page tmp = Iris::my_memory.create_page ()
tmp.set_flags (Iris::Page::PAYING | Iris::Page::FRAME)
Iris::my_memory.map (tmp, (unsigned)tmp_addr)
for unsigned i = 0; i < pages - 1; ++i:
Iris::Page page = Iris::my_memory.create_page ()
page.alloc_physical (phys + ((i + offset) << PAGE_BITS), true, true)
Iris::my_memory.map (page, (unsigned)page_addr)
code.get_block (i << PAGE_BITS, PAGE_SIZE, 0, tmp)
for unsigned t = 0; t < PAGE_SIZE / 4; ++t:
page_addr[t] = tmp_addr[t]
args_t *args = (args_t *)((unsigned)loader_addr + PAGE_SIZE - sizeof (args_t))
unsigned phys_args = target + PAGE_SIZE - sizeof (args_t)
args->load = load
args->entry = entry
args->size = size
args->source = phys + (offset << PAGE_BITS) | 0x80000000
Iris::debug ("booting into: %x+%x->%x@%x (%x, %x)\n", args->source, args->size, args->load, args->entry, args, phys_args)
// Everything is set up; jump to the loader.
Iris::boot (target | 0x80000000, phys_args | 0x80000000)
Iris::panic (0, "Iris::boot should not return, but it does")
default:
Iris::panic (Iris::recv.data[0].l, "invalid commend received on boot capability")
asm volatile ("\t.set noreorder\n"
"\t.globl pre_code, pre_end, post_code, post_end\n"
"\t.text\n"
"pre_code:\n"
"\tlw $t0, 0($a0)\n" // t0 is the load address
"\tlw $t1, 4($a0)\n" // t1 is the size
"\tlw $t9, 8($a0)\n" // t9 is the entry point
"\tlw $t2, 12($a0)\n" // t2 is the source of the loaded image
"\tadd $t0, $t0, $t1\n" // t0 is the end of the load region
"\tadd $t2, $t2, $t1\n" // t2 is the end of the source
"1:\n"
"\tlw $t3, -4($t2)\n"
"\tsw $t3, -4($t0)\n"
"\taddiu $t2, $t2, -4\n"
"\taddiu $t1, $t1, -4\n"
"\tbnez $t1, 1b\n"
"\taddiu $t0, $t0, -4\n"
// Done copying
"\tjr $t9\n"
"\tnop\n"
"pre_end:\n"
"\n"
"post_code:\n"
"\tlw $t0, 0($a0)\n" // t0 is the load address
"\tlw $t1, 4($a0)\n" // t1 is the size
"\tlw $t9, 8($a0)\n" // t9 is the entry point
"\tlw $t2, 12($a0)\n" // t2 is the source of the loaded image
"1:\n"
"\tlw $t3, 0($t2)\n"
"\tsw $t3, 0($t0)\n"
"\taddiu $t2, $t2, 4\n"
"\taddiu $t1, $t1, -4\n"
"\tbnez $t1, 1b\n"
"\taddiu $t0, $t0, 4\n"
// Done copying
"\tjr $t9\n"
"\tnop\n"
"post_end:\n"
"\n"
"\t.set reorder\n")

28
source/booter.ccp Normal file
View File

@ -0,0 +1,28 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// source/booter.ccp: Boot into another kernel.
// Copyright 2010 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 <iris.hh>
#include <devices.hh>
Iris::Num start ():
Iris::String data = Iris::my_parent.get_capability <Iris::String> ()
Iris::Boot boot = Iris::my_parent.get_capability <Iris::Boot> ()
//boot.boot (data, 0x81fff000, 0x81fff000)
boot.boot (data, 0xa1fff000, 0xa1fff000)
Iris::panic (0, "boot returns")
return 0

View File

@ -26,7 +26,10 @@
#define NUM_SLOTS 8
#define NUM_CAPS 32
#define SYSREQ 0x100
enum Captype:
SYSREQ
PROGRAM
FILE
static unsigned _free
extern unsigned _end
@ -104,17 +107,20 @@ struct List:
struct Program
struct Serverdevice:
struct Devbase:
char *name
unsigned name_len
unsigned type, index
Iris::Cap cap
Program *server
unsigned type
Program *client
Iris::Cap cap
struct Serverdevice : public Devbase:
unsigned index
Program *server
struct Clientdevice:
unsigned type, index
Serverdevice *dev
Devbase *dev
static Iris::Memory top_memory
static Iris::Directory root
@ -132,7 +138,7 @@ struct Program:
unsigned num_waiting
bool priv
void run ():
Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)this)
Iris::Cap cap = Iris::my_receiver.create_capability (Iris::Num (PROGRAM, (unsigned)this))
if priv:
kdebug ("priv ")
kdebug ("running ")
@ -148,7 +154,12 @@ struct Program:
thread.make_priv ()
thread.run ()
struct File : public Devbase:
unsigned size
Iris::Caps pages
static List <Program> programs
static List <File> files
static Serverdevice *sysreq
static bool name_match (char const *name, unsigned name_len, Iris::String n):
@ -238,8 +249,11 @@ static bool get_name (char *&line, unsigned &len, char *&name, unsigned &name_le
while name_len < len && isnamechar (line[name_len]):
++name_len
name = new char[name_len]
kdebug ("name: ")
for unsigned i = 0; i < name_len; ++i:
name[i] = line[i]
kdebug_char (name[i])
kdebug_char ('\n')
line += name_len
len -= name_len
delspace (line, len)
@ -272,6 +286,7 @@ static unsigned read_num (char *&line, unsigned &len):
static Type types[] = {
{ "String", 6, Iris::String::ID },
{ "WString", 7, Iris::WString::ID },
{ "Boot", 4, Iris::Boot::ID },
{ "Device", 6, Iris::Device::ID },
{ "Event", 5, Iris::Event::ID },
{ "Parent", 6, Iris::Parent::ID },
@ -303,19 +318,27 @@ static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &ind
return
Iris::panic (0, "no valid type found")
static bool find_cap (char *&line, unsigned &len, Program *&server, Serverdevice *&dev):
static bool find_cap (char *&line, unsigned &len, Program **server, Devbase *&dev, bool &present):
char *n
unsigned l
if !get_name (line, len, n, l):
Iris::panic (0, "no capability name found in init.config")
List <Program>::Item *p
for p = programs.begin (); p; p = p->next:
for List <Program>::Item *p = programs.begin (); p; p = p->next:
List <Serverdevice>::Item *d
for d = (*p)->server_devices.begin (); d; d = d->next:
if string_match (n, l, (*d)->name, (*d)->name_len):
server = &**p
if server:
*server = &**p
dev = &**d
present = false
return true
if server:
return false
for List <File>::Item *f = files.begin (); f; f = f->next:
if string_match (n, l, (*f)->name, (*f)->name_len):
dev = &**f
present = true
return true
return false
static void parse_line (char *&line, unsigned maxlen)
@ -374,9 +397,23 @@ static void parse_line (char *&line, unsigned maxlen):
if !maxlen:
return
if match (start, maxlen, "program"):
// program <name> = "<filename>"
do_load (start, maxlen, false)
else if match (start, maxlen, "driver"):
// driver <name> = "<filename>"
do_load (start, maxlen, true)
else if match (start, maxlen, "file"):
// file <name> = "<filename>"
File *f = &**files.insert ()
f->type = Iris::String::ID
if !get_name (start, maxlen, f->name, f->name_len) || !match (start, maxlen, "=") || !maxlen:
Iris::panic (0, "syntax error in init.config (file name)")
unsigned l
char *n = get_filename (start, maxlen, l)
f->pages = load (n, l, f->size)
f->cap = Iris::my_receiver.create_capability (Iris::Num (FILE, (unsigned)f))
++line
--maxlen
else if match (start, maxlen, "receive"):
// receive <name> / <type> [, <index>] = <cap>
char *n
@ -400,7 +437,8 @@ static void parse_line (char *&line, unsigned maxlen):
Program *server
if sysreq:
Iris::panic (0, "double registration of sysreq")
if !find_cap (start, maxlen, server, sysreq):
bool dummy
if !find_cap (start, maxlen, &server, *(Devbase **)&sysreq, dummy):
Iris::panic (0, "capability not found for sysreq")
if sysreq->type != Iris::Keyboard::ID:
kdebug ("capability for sysreq is not a keyboard\n")
@ -420,15 +458,16 @@ static void parse_line (char *&line, unsigned maxlen):
find_type (start, maxlen, (*d)->type, (*d)->index)
if !match (start, maxlen, "="):
Iris::panic (1, "syntax error in init.config (give)")
Program *server
if !find_cap (start, maxlen, server, (*d)->dev):
bool present
if !find_cap (start, maxlen, NULL, (*d)->dev, present):
Iris::panic (0, "capability not found for give")
if (*d)->dev->type != (*d)->type:
kdebug ("capability type mismatch for give\n")
if (*d)->dev->client:
Iris::panic (0, "capability given out twice")
(*d)->dev->client = &**p
++(*p)->num_waiting
if !present:
++(*p)->num_waiting
//kdebug ("registered give device: ")
//kdebug_num ((*d)->type)
//kdebug ("\n")
@ -452,6 +491,7 @@ static void parse_line (char *&line, unsigned maxlen):
Iris::Num start ():
init_alloc ()
programs.init ()
files.init ()
root = Iris::my_parent.get_capability <Iris::Directory> ()
elfrun = Iris::my_parent.get_capability <Iris::Elfrun> ()
sysreq = NULL
@ -469,88 +509,116 @@ Iris::Num start ():
kdebug ("waiting for events.\n")
while true:
Iris::wait ()
if Iris::recv.protected_data.l == SYSREQ:
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
continue
kdebug ("sysreq event: powering device off\n")
Iris::poweroff ()
continue
Program *caller = (Program *)Iris::recv.protected_data.l
switch Iris::recv.data[0].l:
case Iris::Parent::GET_CAPABILITY:
unsigned index = Iris::recv.data[0].h
unsigned type = Iris::recv.data[1].l
if Iris::recv.data[1].h:
Iris::panic (Iris::recv.data[1].h, "high device requested")
//kdebug ("requested device ")
//kdebug_num (type)
//kdebug (":")
//kdebug_num (index)
//kdebug ("\n")
List <Clientdevice>::Item *d
for d = caller->client_devices.begin (); d; d = d->next:
//kdebug ("checking ")
//kdebug_num ((*d)->type)
//kdebug (":")
//kdebug_num ((*d)->index)
//kdebug ("\n")
if (*d)->type == type && (*d)->index == index:
break
if !d:
Iris::panic (type, "unregistered device requested")
Iris::recv.reply.invoke (0, 0, (*d)->dev->cap)
//kdebug ("given device ")
//kdebug_num (type)
//kdebug (":")
//kdebug_num (index)
//kdebug ("\n")
break
case Iris::Parent::PROVIDE_CAPABILITY:
if Iris::recv.data[1].h != 0:
kdebug ("init: too high device provided\n")
switch Iris::recv.protected_data.l:
case SYSREQ:
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
Iris::poweroff ()
continue
unsigned type = Iris::recv.data[1].l
unsigned index = Iris::recv.data[0].h
List <Serverdevice>::Item *d
for d = caller->server_devices.begin (); d; d = d->next:
if (*d)->type == type && (*d)->index == index:
kdebug ("sysreq event: powering device off at release\n")
continue
case FILE:
File *file = (File *)Iris::recv.protected_data.h
switch Iris::recv.data[0].l:
case Iris::String::GET_SIZE:
Iris::recv.reply.invoke (file->size)
break
if !d:
Iris::panic (0, "unregistered device provided")
(*d)->cap = Iris::get_arg ()
Iris::recv.reply.invoke ()
if (*d)->client:
if !--(*d)->client->num_waiting:
(*d)->client->run ()
//kdebug ("provided ")
//kdebug_num ((*d)->type)
//kdebug (":")
//kdebug_num ((*d)->index)
//kdebug ("\n")
case Iris::String::GET_CHARS:
Iris::panic (0, "get_chars is not defined for init strings")
case Iris::String::GET_ALIGN_BITS:
Iris::recv.reply.invoke (PAGE_BITS)
break
case Iris::String::GET_BLOCK:
Iris::Cap reply = Iris::get_reply ()
Iris::Page target = Iris::get_arg ()
Iris::Page source = file->pages.get (Iris::recv.data[1].l >> PAGE_BITS)
source.share (target, Iris::Page::READONLY)
reply.invoke ()
Iris::free_cap (reply)
Iris::free_cap (source)
Iris::free_cap (target)
break
default:
Iris::panic (Iris::recv.data[0].l, "unknown request for init string")
break
case Iris::Parent::INIT_DONE:
//kdebug ("init done\n")
Iris::recv.reply.invoke ()
if caller == sysreq->server:
Iris::Cap cap = Iris::my_receiver.create_capability (SYSREQ)
Iris::Keyboard (sysreq->cap).set_cb (cap.copy ())
Iris::free_cap (cap)
kdebug ("registered sysreq\n")
break
case Iris::Parent::EXIT:
kdebug ("child exits with code ")
// TODO: print name.
kdebug_num (Iris::recv.data[1].h)
kdebug (":")
kdebug_num (Iris::recv.data[1].l)
kdebug ("\n")
// TODO: destroy memory.
break
default:
// TODO.
kdebug ("child request: ")
kdebug_num (Iris::recv.data[0].l)
kdebug (" from ")
for unsigned i = 0; i < caller->name_len; ++i:
kdebug_char (caller->name[i])
kdebug ("\n")
case PROGRAM:
Program *caller = (Program *)Iris::recv.protected_data.h
switch Iris::recv.data[0].l:
case Iris::Parent::GET_CAPABILITY:
unsigned index = Iris::recv.data[0].h
unsigned type = Iris::recv.data[1].l
if Iris::recv.data[1].h:
Iris::panic (Iris::recv.data[1].h, "high device requested")
//kdebug ("requested device ")
//kdebug_num (type)
//kdebug (":")
//kdebug_num (index)
//kdebug ("\n")
List <Clientdevice>::Item *d
for d = caller->client_devices.begin (); d; d = d->next:
//kdebug ("checking ")
//kdebug_num ((*d)->type)
//kdebug (":")
//kdebug_num ((*d)->index)
//kdebug ("\n")
if (*d)->type == type && (*d)->index == index:
break
if !d:
Iris::panic (type, "unregistered device requested")
Iris::recv.reply.invoke (0, 0, (*d)->dev->cap)
//kdebug ("given device ")
//kdebug_num (type)
//kdebug (":")
//kdebug_num (index)
//kdebug ("\n")
break
case Iris::Parent::PROVIDE_CAPABILITY:
if Iris::recv.data[1].h != 0:
kdebug ("init: too high device provided\n")
continue
unsigned type = Iris::recv.data[1].l
unsigned index = Iris::recv.data[0].h
List <Serverdevice>::Item *d
for d = caller->server_devices.begin (); d; d = d->next:
if (*d)->type == type && (*d)->index == index:
break
if !d:
Iris::panic (0, "unregistered device provided")
(*d)->cap = Iris::get_arg ()
Iris::recv.reply.invoke ()
if (*d)->client:
if !--(*d)->client->num_waiting:
(*d)->client->run ()
//kdebug ("provided ")
//kdebug_num ((*d)->type)
//kdebug (":")
//kdebug_num ((*d)->index)
//kdebug ("\n")
break
case Iris::Parent::INIT_DONE:
//kdebug ("init done\n")
Iris::recv.reply.invoke ()
if caller == sysreq->server:
Iris::Cap cap = Iris::my_receiver.create_capability (SYSREQ)
Iris::Keyboard (sysreq->cap).set_cb (cap.copy ())
Iris::free_cap (cap)
kdebug ("registered sysreq\n")
break
case Iris::Parent::EXIT:
kdebug ("child ")
for unsigned i = 0; i < caller->name_len; ++i:
kdebug_char (caller->name[i])
kdebug (" exits with code ")
kdebug_num (Iris::recv.data[1].h)
kdebug (":")
kdebug_num (Iris::recv.data[1].l)
kdebug ("\n")
top_memory.destroy (caller->memory)
break
default:
// TODO.
kdebug ("child request: ")
kdebug_num (Iris::recv.data[0].l)
kdebug (" from ")
for unsigned i = 0; i < caller->name_len; ++i:
kdebug_char (caller->name[i])
kdebug ("\n")