Root/
| 1 | #pypp 0 |
| 2 | // Iris: micro-kernel for a capability-based operating system. |
| 3 | // bootstrap/init.ccp: Bootstrapping code. |
| 4 | // Copyright 2009 Bas Wijnen <wijnen@debian.org> |
| 5 | // |
| 6 | // This program is free software: you can redistribute it and/or modify |
| 7 | // it under the terms of the GNU General Public License as published by |
| 8 | // the Free Software Foundation, either version 3 of the License, or |
| 9 | // (at your option) any later version. |
| 10 | // |
| 11 | // This program is distributed in the hope that it will be useful, |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | // GNU General Public License for more details. |
| 15 | // |
| 16 | // You should have received a copy of the GNU General Public License |
| 17 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | |
| 19 | #include "devices.hh" |
| 20 | #include "iris.hh" |
| 21 | #include "keys.hh" |
| 22 | |
| 23 | #define INIT_CONFIG "init.config" |
| 24 | #define INIT_CONFIG_SIZE 12 |
| 25 | |
| 26 | #define NUM_SLOTS 8 |
| 27 | #define NUM_CAPS 32 |
| 28 | |
| 29 | enum Captype: |
| 30 | SYSREQ |
| 31 | PROGRAM |
| 32 | FILE |
| 33 | |
| 34 | static unsigned _free |
| 35 | extern unsigned _end |
| 36 | |
| 37 | void init_alloc (): |
| 38 | _free = ((unsigned)&_end + PAGE_SIZE - 1) & PAGE_MASK |
| 39 | |
| 40 | char *alloc_space (unsigned pages): |
| 41 | unsigned ret = (_free + PAGE_SIZE - 1) & PAGE_MASK |
| 42 | _free = ret + (pages << PAGE_BITS) |
| 43 | return (char *)ret |
| 44 | |
| 45 | void *operator new[] (unsigned size): |
| 46 | //kdebug ("new ") |
| 47 | void *ret = (void *)_free |
| 48 | size = (size + 3) & ~3 |
| 49 | unsigned rest = PAGE_SIZE - (((_free - 1) & ~PAGE_MASK) + 1) |
| 50 | if rest < size: |
| 51 | unsigned pages = ((size - rest) + PAGE_SIZE - 1) >> PAGE_BITS |
| 52 | for unsigned p = 0; p < pages; ++p: |
| 53 | Iris::Page page = Iris::my_memory.create_page () |
| 54 | page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME) |
| 55 | Iris::my_memory.map (page, _free + rest + (p << PAGE_BITS)) |
| 56 | Iris::free_cap (page) |
| 57 | _free += size |
| 58 | //kdebug_num ((unsigned)ret) |
| 59 | //kdebug ("+") |
| 60 | //kdebug_num (size) |
| 61 | //kdebug ("\n") |
| 62 | return ret |
| 63 | |
| 64 | void *operator new (unsigned size): |
| 65 | return new char[size] |
| 66 | |
| 67 | template <typename _T> // |
| 68 | struct List: |
| 69 | struct Item: |
| 70 | Item *prev, *next |
| 71 | _T value |
| 72 | _T &operator* (): |
| 73 | return value |
| 74 | _T *operator-> (): |
| 75 | return &value |
| 76 | Item *first |
| 77 | Item *begin (): |
| 78 | return first |
| 79 | void erase (Item *i): |
| 80 | if i->prev: |
| 81 | i->prev->next = i->next |
| 82 | else: |
| 83 | first = i->next |
| 84 | if i->next: |
| 85 | i->next->prev = i->prev |
| 86 | delete i |
| 87 | Item *insert (Item *after = NULL): |
| 88 | Item *ret = new Item |
| 89 | if after: |
| 90 | ret->prev = after->prev |
| 91 | ret->next = after |
| 92 | if ret->prev: |
| 93 | ret->prev->next = ret |
| 94 | else: |
| 95 | first = ret |
| 96 | after->prev = ret |
| 97 | else: |
| 98 | ret->prev = NULL |
| 99 | ret->next = first |
| 100 | first = ret |
| 101 | if ret->next: |
| 102 | ret->next->prev = ret |
| 103 | return ret |
| 104 | void init (): |
| 105 | first = NULL |
| 106 | List () : first (NULL): |
| 107 | |
| 108 | struct Program |
| 109 | |
| 110 | struct Devbase: |
| 111 | char *name |
| 112 | unsigned name_len |
| 113 | unsigned type |
| 114 | Program *client |
| 115 | Iris::Cap cap |
| 116 | |
| 117 | struct Serverdevice : public Devbase: |
| 118 | unsigned index |
| 119 | Program *server |
| 120 | |
| 121 | struct Clientdevice: |
| 122 | unsigned type, index |
| 123 | Devbase *dev |
| 124 | |
| 125 | static Iris::Memory top_memory |
| 126 | static Iris::Directory root |
| 127 | static Iris::Elfrun elfrun |
| 128 | |
| 129 | struct Program: |
| 130 | char *name |
| 131 | unsigned name_len |
| 132 | unsigned size |
| 133 | Iris::Caps pages |
| 134 | Iris::Memory memory |
| 135 | Iris::Thread thread |
| 136 | List <Serverdevice> server_devices |
| 137 | List <Clientdevice> client_devices |
| 138 | unsigned num_waiting |
| 139 | bool priv |
| 140 | void run (): |
| 141 | Iris::Cap cap = Iris::my_receiver.create_capability (Iris::Num (PROGRAM, (unsigned)this)) |
| 142 | if priv: |
| 143 | kdebug ("priv ") |
| 144 | kdebug ("running ") |
| 145 | for unsigned i = 0; i < name_len; ++i: |
| 146 | kdebug_char (name[i]) |
| 147 | kdebug ("\n") |
| 148 | Iris::Caps caps = elfrun.run_caps (top_memory, pages, cap.copy (), (size + PAGE_SIZE - 1) >> PAGE_BITS) |
| 149 | Iris::free_cap (cap) |
| 150 | thread = caps.get (__thread_num) |
| 151 | memory = caps.get (__memory_num) |
| 152 | Iris::free_cap (caps) |
| 153 | if priv: |
| 154 | thread.make_priv () |
| 155 | thread.run () |
| 156 | |
| 157 | struct File : public Devbase: |
| 158 | unsigned size |
| 159 | Iris::Caps pages |
| 160 | |
| 161 | static List <Program> programs |
| 162 | static List <File> files |
| 163 | static Serverdevice *sysreq |
| 164 | |
| 165 | static bool name_match (char const *name, unsigned name_len, Iris::String n): |
| 166 | char nm[16] |
| 167 | n.get_chars (0, nm) |
| 168 | for unsigned t = 0; t < 16 && t < name_len; ++t: |
| 169 | if nm[t] != name[t]: |
| 170 | return false |
| 171 | return true |
| 172 | |
| 173 | static Iris::Caps load (char const *name, unsigned name_len, unsigned &size, Iris::Caps target = Iris::alloc_cap ()): |
| 174 | kdebug ("loading ") |
| 175 | for unsigned i = 0; i < name_len; ++i: |
| 176 | kdebug_char (name[i]) |
| 177 | kdebug ("\n") |
| 178 | root.lock_ro () |
| 179 | Iris::Num sz = root.get_size () |
| 180 | if sz.h: |
| 181 | Iris::panic (sz.h, "too many files") |
| 182 | for unsigned i = 0; i < sz.l; ++i: |
| 183 | Iris::String n = root.get_name (i) |
| 184 | if !name_match (name, name_len, n): |
| 185 | Iris::free_cap (n) |
| 186 | continue |
| 187 | Iris::free_cap (n) |
| 188 | Iris::Block file = root.get_file_ro (i) |
| 189 | Iris::Num s = file.get_size () |
| 190 | if s.h: |
| 191 | Iris::panic (s.h, "file is too large to load") |
| 192 | size = s.l |
| 193 | unsigned pages = (size + PAGE_SIZE - 1) >> PAGE_BITS |
| 194 | if pages > 0: |
| 195 | Iris::set_recv_arg (target) |
| 196 | Iris::my_memory.create_caps (pages) |
| 197 | unsigned slot = target.use () |
| 198 | for unsigned p = 0; p < pages; ++p: |
| 199 | Iris::set_recv_arg (Iris::Cap (slot, p)) |
| 200 | file.get_block (p << PAGE_BITS) |
| 201 | Iris::free_slot (slot) |
| 202 | Iris::free_cap (file) |
| 203 | root.unlock_ro () |
| 204 | return target |
| 205 | Iris::panic (0, "file not found for init") |
| 206 | return target |
| 207 | |
| 208 | static void delspace (char *&line, unsigned &maxlen): |
| 209 | while maxlen && (*line == ' ' || *line == '\t'): |
| 210 | ++line |
| 211 | --maxlen |
| 212 | if maxlen && *line == '#': |
| 213 | line += maxlen |
| 214 | maxlen = 0 |
| 215 | |
| 216 | static bool match (char *&line, unsigned &maxlen, char const *word): |
| 217 | delspace (line, maxlen) |
| 218 | char const *w = word |
| 219 | char *l = line |
| 220 | unsigned len = 0 |
| 221 | while *word: |
| 222 | if *l++ != *word++: |
| 223 | return false |
| 224 | ++len |
| 225 | line = l |
| 226 | maxlen -= len |
| 227 | delspace (line, maxlen) |
| 228 | //kdebug ("match: ") |
| 229 | //kdebug (w) |
| 230 | //kdebug ("\n") |
| 231 | return true |
| 232 | |
| 233 | static bool isnamechar (char c): |
| 234 | if c >= 'a' && c <= 'z': |
| 235 | return true |
| 236 | if c >= 'A' && c <= 'Z': |
| 237 | return true |
| 238 | if c >= '0' && c <= '9': |
| 239 | return true |
| 240 | if c == '_': |
| 241 | return true |
| 242 | return false |
| 243 | |
| 244 | static bool get_name (char *&line, unsigned &len, char *&name, unsigned &name_len): |
| 245 | delspace (line, len) |
| 246 | if !len: |
| 247 | return false |
| 248 | name_len = 0 |
| 249 | while name_len < len && isnamechar (line[name_len]): |
| 250 | ++name_len |
| 251 | name = new char[name_len] |
| 252 | //kdebug ("name: ") |
| 253 | for unsigned i = 0; i < name_len; ++i: |
| 254 | name[i] = line[i] |
| 255 | //kdebug_char (name[i]) |
| 256 | //kdebug_char ('\n') |
| 257 | line += name_len |
| 258 | len -= name_len |
| 259 | delspace (line, len) |
| 260 | return true |
| 261 | |
| 262 | static bool string_match (char const *s1, unsigned l1, char const *s2, unsigned l2): |
| 263 | if l1 != l2: |
| 264 | return false |
| 265 | for unsigned i = 0; i < l1; ++i: |
| 266 | if s1[i] != s2[i]: |
| 267 | return false |
| 268 | return true |
| 269 | |
| 270 | struct Type: |
| 271 | char const *name |
| 272 | unsigned len |
| 273 | unsigned type |
| 274 | |
| 275 | static unsigned read_num (char *&line, unsigned &len): |
| 276 | delspace (line, len) |
| 277 | unsigned num = 0 |
| 278 | while len && *line >= '0' && *line <= '9': |
| 279 | num *= 10 |
| 280 | num += *line - '0' |
| 281 | ++line |
| 282 | --len |
| 283 | delspace (line, len) |
| 284 | return num |
| 285 | |
| 286 | static Type types[] = { |
| 287 | { "String", 6, Iris::String::ID }, |
| 288 | { "WString", 7, Iris::WString::ID }, |
| 289 | { "Block", 5, Iris::Block::ID }, |
| 290 | { "WBlock", 6, Iris::WBlock::ID }, |
| 291 | { "Boot", 4, Iris::Boot::ID }, |
| 292 | { "Device", 6, Iris::Device::ID }, |
| 293 | { "Event", 5, Iris::Event::ID }, |
| 294 | { "Parent", 6, Iris::Parent::ID }, |
| 295 | { "Keyboard", 8, Iris::Keyboard::ID }, |
| 296 | { "Buzzer", 6, Iris::Buzzer::ID }, |
| 297 | { "Display", 7, Iris::Display::ID }, |
| 298 | { "Font", 4, Iris::Font::ID }, |
| 299 | { "Setting", 7, Iris::Setting::ID }, |
| 300 | { "Directory", 9, Iris::Directory::ID }, |
| 301 | { "WDirectory", 10, Iris::WDirectory::ID }, |
| 302 | { "Stream", 6, Iris::Stream::ID }, |
| 303 | { "UI", 2, Iris::UI::ID }, |
| 304 | { "RTC", 3, Iris::RTC::ID }, |
| 305 | { NULL, 0, 0 } |
| 306 | } |
| 307 | |
| 308 | static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &index): |
| 309 | char *n |
| 310 | unsigned l |
| 311 | if !get_name (line, len, n, l) || !len: |
| 312 | Iris::panic (0, "no name for type") |
| 313 | for unsigned t = 0; types[t].len != 0; ++t: |
| 314 | if string_match (types[t].name, types[t].len, n, l): |
| 315 | type = types[t].type |
| 316 | if len && *line == ',': |
| 317 | ++line |
| 318 | --len |
| 319 | index = read_num (line, len) |
| 320 | else: |
| 321 | index = 0 |
| 322 | return |
| 323 | Iris::panic (0, "no valid type found") |
| 324 | |
| 325 | static bool find_cap (char *&line, unsigned &len, Program **server, Devbase *&dev, bool &present): |
| 326 | char *n |
| 327 | unsigned l |
| 328 | if !get_name (line, len, n, l): |
| 329 | Iris::panic (0, "no capability name found in init.config") |
| 330 | for List <Program>::Item *p = programs.begin (); p; p = p->next: |
| 331 | List <Serverdevice>::Item *d |
| 332 | for d = (*p)->server_devices.begin (); d; d = d->next: |
| 333 | if string_match (n, l, (*d)->name, (*d)->name_len): |
| 334 | if server: |
| 335 | *server = &**p |
| 336 | dev = &**d |
| 337 | present = false |
| 338 | return true |
| 339 | if server: |
| 340 | return false |
| 341 | for List <File>::Item *f = files.begin (); f; f = f->next: |
| 342 | if string_match (n, l, (*f)->name, (*f)->name_len): |
| 343 | dev = &**f |
| 344 | present = true |
| 345 | return true |
| 346 | return false |
| 347 | |
| 348 | static void parse_line (char *&line, unsigned maxlen) |
| 349 | static void include (char const *name, unsigned name_len): |
| 350 | unsigned size |
| 351 | Iris::Caps caps = load (name, name_len, size) |
| 352 | unsigned pages = (size + PAGE_SIZE - 1) >> PAGE_BITS |
| 353 | char *config = alloc_space (pages) |
| 354 | unsigned pages_slot = caps.use () |
| 355 | for unsigned p = 0; p < pages; ++p: |
| 356 | Iris::Page page (pages_slot, p) |
| 357 | Iris::my_memory.map (page, (unsigned)&config[p << PAGE_BITS]) |
| 358 | char *ptr = config |
| 359 | while ptr - config < size: |
| 360 | parse_line (ptr, config + size - ptr) |
| 361 | for unsigned p = 0; p < pages; ++p: |
| 362 | Iris::my_memory.destroy (Iris::Cap (pages_slot, p)) |
| 363 | Iris::my_memory.destroy (caps) |
| 364 | Iris::free_cap (caps) |
| 365 | Iris::free_slot (pages_slot) |
| 366 | |
| 367 | static char *get_filename (char *&line, unsigned &maxlen, unsigned &len): |
| 368 | char q = *line++ |
| 369 | --maxlen |
| 370 | len = 0 |
| 371 | while maxlen && *line != q: |
| 372 | ++line |
| 373 | --maxlen |
| 374 | ++len |
| 375 | if !maxlen: |
| 376 | Iris::panic (0, "no closing quote in init.config") |
| 377 | return line - len |
| 378 | |
| 379 | static void do_load (char *&line, unsigned &maxlen, bool priv): |
| 380 | Program *p = &**programs.insert () |
| 381 | if !get_name (line, maxlen, p->name, p->name_len) || !match (line, maxlen, "=") || !maxlen: |
| 382 | Iris::panic (0, "syntax error in init.config (load)") |
| 383 | unsigned l |
| 384 | char *n = get_filename (line, maxlen, l) |
| 385 | p->pages = load (n, l, p->size) |
| 386 | p->priv = priv |
| 387 | p->num_waiting = 0 |
| 388 | ++line |
| 389 | --maxlen |
| 390 | |
| 391 | static void parse_line (char *&line, unsigned maxlen): |
| 392 | char *start = line |
| 393 | while maxlen && *line != '\n': |
| 394 | ++line |
| 395 | --maxlen |
| 396 | // The line to execute is from start to line. |
| 397 | maxlen = line - start |
| 398 | if *line == '\n': |
| 399 | ++line |
| 400 | delspace (start, maxlen) |
| 401 | if !maxlen: |
| 402 | return |
| 403 | if match (start, maxlen, "program"): |
| 404 | // program <name> = "<filename>" |
| 405 | do_load (start, maxlen, false) |
| 406 | else if match (start, maxlen, "driver"): |
| 407 | // driver <name> = "<filename>" |
| 408 | do_load (start, maxlen, true) |
| 409 | else if match (start, maxlen, "file"): |
| 410 | // file <name> = "<filename>" |
| 411 | File *f = &**files.insert () |
| 412 | f->type = Iris::Block::ID |
| 413 | if !get_name (start, maxlen, f->name, f->name_len) || !match (start, maxlen, "=") || !maxlen: |
| 414 | Iris::panic (0, "syntax error in init.config (file name)") |
| 415 | unsigned l |
| 416 | char *n = get_filename (start, maxlen, l) |
| 417 | f->pages = load (n, l, f->size) |
| 418 | f->cap = Iris::my_receiver.create_capability (Iris::Num (FILE, (unsigned)f)) |
| 419 | ++line |
| 420 | --maxlen |
| 421 | else if match (start, maxlen, "receive"): |
| 422 | // receive <name> / <type> [, <index>] = <cap> |
| 423 | char *n |
| 424 | unsigned l |
| 425 | if !get_name (start, maxlen, n, l) || !match (start, maxlen, "/") || !maxlen: |
| 426 | Iris::panic (0, "syntax error in init.config (receive)") |
| 427 | List <Program>::Item *p |
| 428 | for p = programs.begin (); p; p = p->next: |
| 429 | if string_match ((*p)->name, (*p)->name_len, n, l): |
| 430 | break |
| 431 | if !p: |
| 432 | Iris::panic (0, "program not found for receive") |
| 433 | List <Serverdevice>::Item *dev = (*p)->server_devices.insert () |
| 434 | find_type (start, maxlen, (*dev)->type, (*dev)->index) |
| 435 | if !match (start, maxlen, "=") || !get_name (start, maxlen, (*dev)->name, (*dev)->name_len): |
| 436 | Iris::panic (1, "syntax error in init.config (receive)") |
| 437 | (*dev)->server = &**p |
| 438 | (*dev)->client = NULL |
| 439 | (*dev)->cap = Iris::Cap () |
| 440 | else if match (start, maxlen, "sysreq"): |
| 441 | Program *server |
| 442 | if sysreq: |
| 443 | Iris::panic (0, "double registration of sysreq") |
| 444 | bool dummy |
| 445 | if !find_cap (start, maxlen, &server, *(Devbase **)&sysreq, dummy): |
| 446 | Iris::panic (0, "capability not found for sysreq") |
| 447 | if sysreq->type != Iris::Keyboard::ID: |
| 448 | kdebug ("capability for sysreq is not a keyboard\n") |
| 449 | else if match (start, maxlen, "give"): |
| 450 | // give <name> / <type> [, <index>] = <cap> |
| 451 | char *n |
| 452 | unsigned l |
| 453 | if !get_name (start, maxlen, n, l) || !match (start, maxlen, "/") || !maxlen: |
| 454 | Iris::panic (0, "syntax error in init.config (give)") |
| 455 | List <Program>::Item *p |
| 456 | for p = programs.begin (); p; p = p->next: |
| 457 | if string_match ((*p)->name, (*p)->name_len, n, l): |
| 458 | break |
| 459 | if !p: |
| 460 | Iris::panic (0, "program not found for give") |
| 461 | List <Clientdevice>::Item *d = (*p)->client_devices.insert () |
| 462 | find_type (start, maxlen, (*d)->type, (*d)->index) |
| 463 | if !match (start, maxlen, "="): |
| 464 | Iris::panic (1, "syntax error in init.config (give)") |
| 465 | bool present |
| 466 | if !find_cap (start, maxlen, NULL, (*d)->dev, present): |
| 467 | Iris::panic (0, "capability not found for give") |
| 468 | if (*d)->dev->type != (*d)->type: |
| 469 | kdebug ("capability type mismatch for give\n") |
| 470 | if (*d)->dev->client: |
| 471 | Iris::panic (0, "capability given out twice") |
| 472 | (*d)->dev->client = &**p |
| 473 | if !present: |
| 474 | ++(*p)->num_waiting |
| 475 | //kdebug ("registered give device: ") |
| 476 | //kdebug_num ((*d)->type) |
| 477 | //kdebug ("\n") |
| 478 | else if match (start, maxlen, "include"): |
| 479 | unsigned name_len |
| 480 | char *name = get_filename (line, maxlen, name_len) |
| 481 | include (name, name_len) |
| 482 | else: |
| 483 | for unsigned i = 0; i < maxlen; ++i: |
| 484 | kdebug_char (start[i]) |
| 485 | kdebug_char ('\n') |
| 486 | Iris::panic (0, "invalid line in init.config") |
| 487 | delspace (start, maxlen) |
| 488 | if maxlen: |
| 489 | kdebug ("Junk: ") |
| 490 | for unsigned i = 0; i < maxlen; ++i: |
| 491 | kdebug_char (start[i]) |
| 492 | kdebug_char ('\n') |
| 493 | Iris::panic (0, "junk at end of line in init.config") |
| 494 | |
| 495 | Iris::Num start (): |
| 496 | init_alloc () |
| 497 | programs.init () |
| 498 | files.init () |
| 499 | root = Iris::my_parent.get_capability <Iris::Directory> () |
| 500 | elfrun = Iris::my_parent.get_capability <Iris::Elfrun> () |
| 501 | sysreq = NULL |
| 502 | top_memory = Iris::get_top_memory () |
| 503 | include (INIT_CONFIG, INIT_CONFIG_SIZE) |
| 504 | kdebug ("killing boot threads\n") |
| 505 | Iris::my_parent.init_done () |
| 506 | for List <Program>::Item *p = programs.begin (); p; p = p->next: |
| 507 | if !(*p)->num_waiting: |
| 508 | (*p)->run () |
| 509 | if !sysreq: |
| 510 | Iris::panic (0, "sysreq not registered") |
| 511 | if sysreq->client: |
| 512 | Iris::panic (0, "sysreq set to reserved capability") |
| 513 | kdebug ("waiting for events.\n") |
| 514 | while true: |
| 515 | Iris::wait () |
| 516 | switch Iris::recv.protected_data.l: |
| 517 | case SYSREQ: |
| 518 | if Iris::recv.data[0].l & Iris::Keyboard::RELEASE: |
| 519 | Iris::reboot () |
| 520 | continue |
| 521 | kdebug ("sysreq event: rebooting device at release\n") |
| 522 | continue |
| 523 | case FILE: |
| 524 | File *file = (File *)Iris::recv.protected_data.h |
| 525 | switch Iris::recv.data[0].l: |
| 526 | case Iris::Block::GET_SIZE: |
| 527 | Iris::recv.reply.invoke (file->size) |
| 528 | break |
| 529 | case Iris::Block::GET_ALIGN_BITS: |
| 530 | Iris::recv.reply.invoke (PAGE_BITS) |
| 531 | break |
| 532 | case Iris::Block::GET_BLOCK: |
| 533 | Iris::Cap reply = Iris::get_reply () |
| 534 | Iris::Page target = Iris::get_arg () |
| 535 | Iris::Page source = file->pages.get (Iris::recv.data[1].l >> PAGE_BITS) |
| 536 | source.share (target, Iris::Page::READONLY) |
| 537 | reply.invoke () |
| 538 | Iris::free_cap (reply) |
| 539 | Iris::free_cap (source) |
| 540 | Iris::free_cap (target) |
| 541 | break |
| 542 | default: |
| 543 | Iris::panic (Iris::recv.data[0].l, "unknown request for init string") |
| 544 | break |
| 545 | case PROGRAM: |
| 546 | Program *caller = (Program *)Iris::recv.protected_data.h |
| 547 | switch Iris::recv.data[0].l: |
| 548 | case Iris::Parent::GET_CAPABILITY: |
| 549 | unsigned index = Iris::recv.data[0].h |
| 550 | unsigned type = Iris::recv.data[1].l |
| 551 | if Iris::recv.data[1].h: |
| 552 | Iris::panic (Iris::recv.data[1].h, "high device requested") |
| 553 | //kdebug ("requested device ") |
| 554 | //kdebug_num (type) |
| 555 | //kdebug (":") |
| 556 | //kdebug_num (index) |
| 557 | //kdebug ("\n") |
| 558 | List <Clientdevice>::Item *d |
| 559 | for d = caller->client_devices.begin (); d; d = d->next: |
| 560 | //kdebug ("checking ") |
| 561 | //kdebug_num ((*d)->type) |
| 562 | //kdebug (":") |
| 563 | //kdebug_num ((*d)->index) |
| 564 | //kdebug ("\n") |
| 565 | if (*d)->type == type && (*d)->index == index: |
| 566 | break |
| 567 | if !d: |
| 568 | Iris::debug ("requested %x by %s\n", type, caller->name) |
| 569 | Iris::panic (type, "unregistered device requested") |
| 570 | Iris::recv.reply.invoke (0, 0, (*d)->dev->cap) |
| 571 | //kdebug ("given device ") |
| 572 | //kdebug_num (type) |
| 573 | //kdebug (":") |
| 574 | //kdebug_num (index) |
| 575 | //kdebug ("\n") |
| 576 | break |
| 577 | case Iris::Parent::PROVIDE_CAPABILITY: |
| 578 | if Iris::recv.data[1].h != 0: |
| 579 | kdebug ("init: too high device provided\n") |
| 580 | continue |
| 581 | unsigned type = Iris::recv.data[1].l |
| 582 | unsigned index = Iris::recv.data[0].h |
| 583 | List <Serverdevice>::Item *d |
| 584 | for d = caller->server_devices.begin (); d; d = d->next: |
| 585 | if (*d)->type == type && (*d)->index == index: |
| 586 | break |
| 587 | if !d: |
| 588 | Iris::debug ("caller: %s\n", caller->name) |
| 589 | Iris::panic (type, "unregistered device provided") |
| 590 | (*d)->cap = Iris::get_arg () |
| 591 | Iris::recv.reply.invoke () |
| 592 | if (*d)->client: |
| 593 | if !--(*d)->client->num_waiting: |
| 594 | (*d)->client->run () |
| 595 | //kdebug ("provided ") |
| 596 | //kdebug_num ((*d)->type) |
| 597 | //kdebug (":") |
| 598 | //kdebug_num ((*d)->index) |
| 599 | //kdebug ("\n") |
| 600 | break |
| 601 | case Iris::Parent::INIT_DONE: |
| 602 | //kdebug ("init done\n") |
| 603 | Iris::recv.reply.invoke () |
| 604 | if caller == sysreq->server: |
| 605 | Iris::Cap cap = Iris::my_receiver.create_capability (SYSREQ) |
| 606 | Iris::Keyboard (sysreq->cap).set_cb (cap.copy ()) |
| 607 | Iris::free_cap (cap) |
| 608 | kdebug ("registered sysreq\n") |
| 609 | break |
| 610 | case Iris::Parent::EXIT: |
| 611 | kdebug ("child ") |
| 612 | for unsigned i = 0; i < caller->name_len; ++i: |
| 613 | kdebug_char (caller->name[i]) |
| 614 | kdebug (" exits with code ") |
| 615 | kdebug_num (Iris::recv.data[1].h) |
| 616 | kdebug (":") |
| 617 | kdebug_num (Iris::recv.data[1].l) |
| 618 | kdebug ("\n") |
| 619 | top_memory.destroy (caller->memory) |
| 620 | break |
| 621 | default: |
| 622 | // TODO. |
| 623 | kdebug ("child request: ") |
| 624 | kdebug_num (Iris::recv.data[0].l) |
| 625 | kdebug (" from ") |
| 626 | for unsigned i = 0; i < caller->name_len; ++i: |
| 627 | kdebug_char (caller->name[i]) |
| 628 | kdebug ("\n") |
| 629 |
Branches:
master
