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:
parent
04ed743042
commit
aef83317c9
12
devices.hhp
12
devices.hhp
@ -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 ():
|
||||
|
37
init.config
37
init.config
@ -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
|
||||
|
@ -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
|
||||
|
4
iris.hhp
4
iris.hhp
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 ()
|
||||
|
@ -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-
|
||||
|
@ -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
136
source/boot.ccp
Normal 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
28
source/booter.ccp
Normal 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
|
262
source/init.ccp
262
source/init.ccp
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user