mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 03:21:09 +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):
|
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)
|
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.
|
// Every process which wants to be switchable through a terminal must implement this interface.
|
||||||
struct Device : public Cap:
|
struct Device : public Cap:
|
||||||
Device (Cap c = Cap ()) : Cap (c):
|
Device (Cap c = Cap ()) : Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
RESET = WString::ID
|
RESET = Boot::ID
|
||||||
ID
|
ID
|
||||||
// Reset the device. This is called by the terminal while switching owners.
|
// Reset the device. This is called by the terminal while switching owners.
|
||||||
void reset ():
|
void reset ():
|
||||||
|
37
init.config
37
init.config
@ -1,5 +1,6 @@
|
|||||||
# driver <name> = '<filename>' load a file into memory to be run priviledged.
|
# driver <name> = '<filename>' load a file into memory to be run priviledged.
|
||||||
# program <name> = '<filename>' load a file into memory to be run normally.
|
# 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.
|
# receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
|
||||||
# sysreq <cap> use a capability as the system request keyboard.
|
# 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.
|
# 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
|
receive driver_gpio / Event = sdmmc_gpio
|
||||||
sysreq sysreq
|
sysreq sysreq
|
||||||
|
|
||||||
driver nand = "nand.elf"
|
#driver nand = "nand.elf"
|
||||||
|
|
||||||
#driver driver_lcd = "lcd.elf"
|
#driver driver_boot = "boot.elf"
|
||||||
#receive driver_lcd / Display = display
|
#receive driver_boot / Boot = boot
|
||||||
#receive driver_lcd / Setting = display_bright
|
|
||||||
|
|
||||||
#driver driver_buzzer = "buzzer.elf"
|
#file kernel = "kernel.raw"
|
||||||
#receive driver_buzzer / Buzzer = buzzer
|
#program booter = "booter.elf"
|
||||||
|
#give booter / String = kernel
|
||||||
|
#give booter / Boot = boot
|
||||||
|
|
||||||
#program alarm = "alarm.elf"
|
driver driver_lcd = "lcd.elf"
|
||||||
#receive alarm / UI = ui
|
receive driver_lcd / Display = display
|
||||||
|
receive driver_lcd / Setting = display_bright
|
||||||
|
|
||||||
#program gui = "gui.elf"
|
driver driver_buzzer = "buzzer.elf"
|
||||||
#give gui / UI = ui
|
receive driver_buzzer / Buzzer = buzzer
|
||||||
#give gui / Display = display
|
|
||||||
#give gui / Setting = display_bright
|
program alarm = "alarm.elf"
|
||||||
#give gui / Buzzer = buzzer
|
receive alarm / UI = ui
|
||||||
#give gui / Keyboard = keyboard
|
|
||||||
|
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"
|
#driver sdmmc = "sd+mmc.elf"
|
||||||
#receive sdmmc / WString = sdmmc
|
#receive sdmmc / WString = sdmmc
|
||||||
|
@ -501,7 +501,7 @@ static void thread_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
|||||||
break
|
break
|
||||||
case Iris::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK:
|
case Iris::Thread::PRIV_ALLOC_RANGE & REQUEST_MASK:
|
||||||
if !c->arg.valid () || ((unsigned)c->arg->target) & ~REQUEST_MASK != CAPTYPE_MEMORY:
|
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)
|
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||||
return
|
return
|
||||||
kMemory *mem = (kMemory *)c->arg->protected_data.l
|
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:
|
case Iris::Thread::PRIV_POWEROFF & REQUEST_MASK:
|
||||||
arch_poweroff ()
|
arch_poweroff ()
|
||||||
case Iris::Thread::PRIV_BOOT & REQUEST_MASK:
|
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:
|
case Iris::Thread::PRIV_PANIC & REQUEST_MASK:
|
||||||
if c->data[1].l == 0xdeaddead:
|
if c->data[1].l == 0xdeaddead:
|
||||||
dbg_code.l = 1
|
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)
|
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_REBOOT)
|
||||||
inline void poweroff ():
|
inline void poweroff ():
|
||||||
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_POWEROFF)
|
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_POWEROFF)
|
||||||
inline void boot (unsigned address):
|
inline void boot (unsigned address, unsigned arg):
|
||||||
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_BOOT, address)
|
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_BOOT, Iris::Num (address, arg))
|
||||||
|
|
||||||
void Receiver::sleep (unsigned value):
|
void Receiver::sleep (unsigned value):
|
||||||
set_alarm (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_register_interrupt (unsigned num, kReceiverP r)
|
||||||
void arch_reboot ()
|
void arch_reboot ()
|
||||||
void arch_poweroff ()
|
void arch_poweroff ()
|
||||||
void arch_boot (unsigned address)
|
void arch_boot (unsigned address, unsigned arg)
|
||||||
void arch_uncache_page (unsigned page)
|
void arch_uncache_page (unsigned page)
|
||||||
|
|
||||||
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
#define assert(x) do { if (!(x)) panic (__LINE__, "assertion failed"); } while (0)
|
||||||
|
@ -19,10 +19,15 @@
|
|||||||
#define ARCH
|
#define ARCH
|
||||||
#include "../kernel.hh"
|
#include "../kernel.hh"
|
||||||
|
|
||||||
typedef unsigned cacheline[8]
|
|
||||||
void arch_flush_cache ():
|
void arch_flush_cache ():
|
||||||
for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line:
|
__asm__ volatile ("\t.set noreorder\n"
|
||||||
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
|
"\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 ():
|
static kThread *handle_exit ():
|
||||||
dbg_check ()
|
dbg_check ()
|
||||||
|
@ -26,7 +26,7 @@ udc_boot_programs = udc
|
|||||||
sd_boot_programs = sd+mmc partition fat
|
sd_boot_programs = sd+mmc partition fat
|
||||||
standard_boot_programs = bootinit
|
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
|
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
||||||
CROSS = mipsel-linux-gnu-
|
CROSS = mipsel-linux-gnu-
|
||||||
|
@ -118,8 +118,8 @@ void arch_poweroff ():
|
|||||||
kdebug ("Power down failed! Rebooting instead.\n")
|
kdebug ("Power down failed! Rebooting instead.\n")
|
||||||
arch_reboot ()
|
arch_reboot ()
|
||||||
|
|
||||||
void arch_boot (unsigned address):
|
// Boot into another kernel.
|
||||||
|
void arch_boot (unsigned address, unsigned arg):
|
||||||
sync_serial ()
|
sync_serial ()
|
||||||
// Boot into another kernel.
|
|
||||||
arch_flush_cache ()
|
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_SLOTS 8
|
||||||
#define NUM_CAPS 32
|
#define NUM_CAPS 32
|
||||||
|
|
||||||
#define SYSREQ 0x100
|
enum Captype:
|
||||||
|
SYSREQ
|
||||||
|
PROGRAM
|
||||||
|
FILE
|
||||||
|
|
||||||
static unsigned _free
|
static unsigned _free
|
||||||
extern unsigned _end
|
extern unsigned _end
|
||||||
@ -104,17 +107,20 @@ struct List:
|
|||||||
|
|
||||||
struct Program
|
struct Program
|
||||||
|
|
||||||
struct Serverdevice:
|
struct Devbase:
|
||||||
char *name
|
char *name
|
||||||
unsigned name_len
|
unsigned name_len
|
||||||
unsigned type, index
|
unsigned type
|
||||||
Iris::Cap cap
|
|
||||||
Program *server
|
|
||||||
Program *client
|
Program *client
|
||||||
|
Iris::Cap cap
|
||||||
|
|
||||||
|
struct Serverdevice : public Devbase:
|
||||||
|
unsigned index
|
||||||
|
Program *server
|
||||||
|
|
||||||
struct Clientdevice:
|
struct Clientdevice:
|
||||||
unsigned type, index
|
unsigned type, index
|
||||||
Serverdevice *dev
|
Devbase *dev
|
||||||
|
|
||||||
static Iris::Memory top_memory
|
static Iris::Memory top_memory
|
||||||
static Iris::Directory root
|
static Iris::Directory root
|
||||||
@ -132,7 +138,7 @@ struct Program:
|
|||||||
unsigned num_waiting
|
unsigned num_waiting
|
||||||
bool priv
|
bool priv
|
||||||
void run ():
|
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:
|
if priv:
|
||||||
kdebug ("priv ")
|
kdebug ("priv ")
|
||||||
kdebug ("running ")
|
kdebug ("running ")
|
||||||
@ -148,7 +154,12 @@ struct Program:
|
|||||||
thread.make_priv ()
|
thread.make_priv ()
|
||||||
thread.run ()
|
thread.run ()
|
||||||
|
|
||||||
|
struct File : public Devbase:
|
||||||
|
unsigned size
|
||||||
|
Iris::Caps pages
|
||||||
|
|
||||||
static List <Program> programs
|
static List <Program> programs
|
||||||
|
static List <File> files
|
||||||
static Serverdevice *sysreq
|
static Serverdevice *sysreq
|
||||||
|
|
||||||
static bool name_match (char const *name, unsigned name_len, Iris::String n):
|
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]):
|
while name_len < len && isnamechar (line[name_len]):
|
||||||
++name_len
|
++name_len
|
||||||
name = new char[name_len]
|
name = new char[name_len]
|
||||||
|
kdebug ("name: ")
|
||||||
for unsigned i = 0; i < name_len; ++i:
|
for unsigned i = 0; i < name_len; ++i:
|
||||||
name[i] = line[i]
|
name[i] = line[i]
|
||||||
|
kdebug_char (name[i])
|
||||||
|
kdebug_char ('\n')
|
||||||
line += name_len
|
line += name_len
|
||||||
len -= name_len
|
len -= name_len
|
||||||
delspace (line, len)
|
delspace (line, len)
|
||||||
@ -272,6 +286,7 @@ static unsigned read_num (char *&line, unsigned &len):
|
|||||||
static Type types[] = {
|
static Type types[] = {
|
||||||
{ "String", 6, Iris::String::ID },
|
{ "String", 6, Iris::String::ID },
|
||||||
{ "WString", 7, Iris::WString::ID },
|
{ "WString", 7, Iris::WString::ID },
|
||||||
|
{ "Boot", 4, Iris::Boot::ID },
|
||||||
{ "Device", 6, Iris::Device::ID },
|
{ "Device", 6, Iris::Device::ID },
|
||||||
{ "Event", 5, Iris::Event::ID },
|
{ "Event", 5, Iris::Event::ID },
|
||||||
{ "Parent", 6, Iris::Parent::ID },
|
{ "Parent", 6, Iris::Parent::ID },
|
||||||
@ -303,19 +318,27 @@ static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &ind
|
|||||||
return
|
return
|
||||||
Iris::panic (0, "no valid type found")
|
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
|
char *n
|
||||||
unsigned l
|
unsigned l
|
||||||
if !get_name (line, len, n, l):
|
if !get_name (line, len, n, l):
|
||||||
Iris::panic (0, "no capability name found in init.config")
|
Iris::panic (0, "no capability name found in init.config")
|
||||||
List <Program>::Item *p
|
for List <Program>::Item *p = programs.begin (); p; p = p->next:
|
||||||
for p = programs.begin (); p; p = p->next:
|
|
||||||
List <Serverdevice>::Item *d
|
List <Serverdevice>::Item *d
|
||||||
for d = (*p)->server_devices.begin (); d; d = d->next:
|
for d = (*p)->server_devices.begin (); d; d = d->next:
|
||||||
if string_match (n, l, (*d)->name, (*d)->name_len):
|
if string_match (n, l, (*d)->name, (*d)->name_len):
|
||||||
server = &**p
|
if server:
|
||||||
|
*server = &**p
|
||||||
dev = &**d
|
dev = &**d
|
||||||
|
present = false
|
||||||
return true
|
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
|
return false
|
||||||
|
|
||||||
static void parse_line (char *&line, unsigned maxlen)
|
static void parse_line (char *&line, unsigned maxlen)
|
||||||
@ -374,9 +397,23 @@ static void parse_line (char *&line, unsigned maxlen):
|
|||||||
if !maxlen:
|
if !maxlen:
|
||||||
return
|
return
|
||||||
if match (start, maxlen, "program"):
|
if match (start, maxlen, "program"):
|
||||||
|
// program <name> = "<filename>"
|
||||||
do_load (start, maxlen, false)
|
do_load (start, maxlen, false)
|
||||||
else if match (start, maxlen, "driver"):
|
else if match (start, maxlen, "driver"):
|
||||||
|
// driver <name> = "<filename>"
|
||||||
do_load (start, maxlen, true)
|
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"):
|
else if match (start, maxlen, "receive"):
|
||||||
// receive <name> / <type> [, <index>] = <cap>
|
// receive <name> / <type> [, <index>] = <cap>
|
||||||
char *n
|
char *n
|
||||||
@ -400,7 +437,8 @@ static void parse_line (char *&line, unsigned maxlen):
|
|||||||
Program *server
|
Program *server
|
||||||
if sysreq:
|
if sysreq:
|
||||||
Iris::panic (0, "double registration of 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")
|
Iris::panic (0, "capability not found for sysreq")
|
||||||
if sysreq->type != Iris::Keyboard::ID:
|
if sysreq->type != Iris::Keyboard::ID:
|
||||||
kdebug ("capability for sysreq is not a keyboard\n")
|
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)
|
find_type (start, maxlen, (*d)->type, (*d)->index)
|
||||||
if !match (start, maxlen, "="):
|
if !match (start, maxlen, "="):
|
||||||
Iris::panic (1, "syntax error in init.config (give)")
|
Iris::panic (1, "syntax error in init.config (give)")
|
||||||
Program *server
|
bool present
|
||||||
if !find_cap (start, maxlen, server, (*d)->dev):
|
if !find_cap (start, maxlen, NULL, (*d)->dev, present):
|
||||||
Iris::panic (0, "capability not found for give")
|
Iris::panic (0, "capability not found for give")
|
||||||
if (*d)->dev->type != (*d)->type:
|
if (*d)->dev->type != (*d)->type:
|
||||||
kdebug ("capability type mismatch for give\n")
|
kdebug ("capability type mismatch for give\n")
|
||||||
if (*d)->dev->client:
|
if (*d)->dev->client:
|
||||||
Iris::panic (0, "capability given out twice")
|
Iris::panic (0, "capability given out twice")
|
||||||
(*d)->dev->client = &**p
|
(*d)->dev->client = &**p
|
||||||
++(*p)->num_waiting
|
if !present:
|
||||||
|
++(*p)->num_waiting
|
||||||
//kdebug ("registered give device: ")
|
//kdebug ("registered give device: ")
|
||||||
//kdebug_num ((*d)->type)
|
//kdebug_num ((*d)->type)
|
||||||
//kdebug ("\n")
|
//kdebug ("\n")
|
||||||
@ -452,6 +491,7 @@ static void parse_line (char *&line, unsigned maxlen):
|
|||||||
Iris::Num start ():
|
Iris::Num start ():
|
||||||
init_alloc ()
|
init_alloc ()
|
||||||
programs.init ()
|
programs.init ()
|
||||||
|
files.init ()
|
||||||
root = Iris::my_parent.get_capability <Iris::Directory> ()
|
root = Iris::my_parent.get_capability <Iris::Directory> ()
|
||||||
elfrun = Iris::my_parent.get_capability <Iris::Elfrun> ()
|
elfrun = Iris::my_parent.get_capability <Iris::Elfrun> ()
|
||||||
sysreq = NULL
|
sysreq = NULL
|
||||||
@ -469,88 +509,116 @@ Iris::Num start ():
|
|||||||
kdebug ("waiting for events.\n")
|
kdebug ("waiting for events.\n")
|
||||||
while true:
|
while true:
|
||||||
Iris::wait ()
|
Iris::wait ()
|
||||||
if Iris::recv.protected_data.l == SYSREQ:
|
switch Iris::recv.protected_data.l:
|
||||||
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
|
case SYSREQ:
|
||||||
continue
|
if Iris::recv.data[0].l & Iris::Keyboard::RELEASE:
|
||||||
kdebug ("sysreq event: powering device off\n")
|
Iris::poweroff ()
|
||||||
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")
|
|
||||||
continue
|
continue
|
||||||
unsigned type = Iris::recv.data[1].l
|
kdebug ("sysreq event: powering device off at release\n")
|
||||||
unsigned index = Iris::recv.data[0].h
|
continue
|
||||||
List <Serverdevice>::Item *d
|
case FILE:
|
||||||
for d = caller->server_devices.begin (); d; d = d->next:
|
File *file = (File *)Iris::recv.protected_data.h
|
||||||
if (*d)->type == type && (*d)->index == index:
|
switch Iris::recv.data[0].l:
|
||||||
|
case Iris::String::GET_SIZE:
|
||||||
|
Iris::recv.reply.invoke (file->size)
|
||||||
break
|
break
|
||||||
if !d:
|
case Iris::String::GET_CHARS:
|
||||||
Iris::panic (0, "unregistered device provided")
|
Iris::panic (0, "get_chars is not defined for init strings")
|
||||||
(*d)->cap = Iris::get_arg ()
|
case Iris::String::GET_ALIGN_BITS:
|
||||||
Iris::recv.reply.invoke ()
|
Iris::recv.reply.invoke (PAGE_BITS)
|
||||||
if (*d)->client:
|
break
|
||||||
if !--(*d)->client->num_waiting:
|
case Iris::String::GET_BLOCK:
|
||||||
(*d)->client->run ()
|
Iris::Cap reply = Iris::get_reply ()
|
||||||
//kdebug ("provided ")
|
Iris::Page target = Iris::get_arg ()
|
||||||
//kdebug_num ((*d)->type)
|
Iris::Page source = file->pages.get (Iris::recv.data[1].l >> PAGE_BITS)
|
||||||
//kdebug (":")
|
source.share (target, Iris::Page::READONLY)
|
||||||
//kdebug_num ((*d)->index)
|
reply.invoke ()
|
||||||
//kdebug ("\n")
|
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
|
break
|
||||||
case Iris::Parent::INIT_DONE:
|
case PROGRAM:
|
||||||
//kdebug ("init done\n")
|
Program *caller = (Program *)Iris::recv.protected_data.h
|
||||||
Iris::recv.reply.invoke ()
|
switch Iris::recv.data[0].l:
|
||||||
if caller == sysreq->server:
|
case Iris::Parent::GET_CAPABILITY:
|
||||||
Iris::Cap cap = Iris::my_receiver.create_capability (SYSREQ)
|
unsigned index = Iris::recv.data[0].h
|
||||||
Iris::Keyboard (sysreq->cap).set_cb (cap.copy ())
|
unsigned type = Iris::recv.data[1].l
|
||||||
Iris::free_cap (cap)
|
if Iris::recv.data[1].h:
|
||||||
kdebug ("registered sysreq\n")
|
Iris::panic (Iris::recv.data[1].h, "high device requested")
|
||||||
break
|
//kdebug ("requested device ")
|
||||||
case Iris::Parent::EXIT:
|
//kdebug_num (type)
|
||||||
kdebug ("child exits with code ")
|
//kdebug (":")
|
||||||
// TODO: print name.
|
//kdebug_num (index)
|
||||||
kdebug_num (Iris::recv.data[1].h)
|
//kdebug ("\n")
|
||||||
kdebug (":")
|
List <Clientdevice>::Item *d
|
||||||
kdebug_num (Iris::recv.data[1].l)
|
for d = caller->client_devices.begin (); d; d = d->next:
|
||||||
kdebug ("\n")
|
//kdebug ("checking ")
|
||||||
// TODO: destroy memory.
|
//kdebug_num ((*d)->type)
|
||||||
break
|
//kdebug (":")
|
||||||
default:
|
//kdebug_num ((*d)->index)
|
||||||
// TODO.
|
//kdebug ("\n")
|
||||||
kdebug ("child request: ")
|
if (*d)->type == type && (*d)->index == index:
|
||||||
kdebug_num (Iris::recv.data[0].l)
|
break
|
||||||
kdebug (" from ")
|
if !d:
|
||||||
for unsigned i = 0; i < caller->name_len; ++i:
|
Iris::panic (type, "unregistered device requested")
|
||||||
kdebug_char (caller->name[i])
|
Iris::recv.reply.invoke (0, 0, (*d)->dev->cap)
|
||||||
kdebug ("\n")
|
//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