Root/
| 1 | #pypp 0 |
| 2 | // Iris: micro-kernel for a capability-based operating system. |
| 3 | // source/boot.ccp: Boot into another kernel. |
| 4 | // Copyright 2010 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 <iris.hh> |
| 20 | #include <devices.hh> |
| 21 | |
| 22 | extern "C": |
| 23 | extern unsigned pre_code, pre_end, post_code, post_end |
| 24 | |
| 25 | struct args_t: |
| 26 | unsigned load |
| 27 | unsigned size |
| 28 | unsigned entry |
| 29 | unsigned source |
| 30 | |
| 31 | Iris::Num start (): |
| 32 | unsigned *loader_addr = (unsigned *)0x15000 |
| 33 | unsigned *page_addr = (unsigned *)0x16000 |
| 34 | unsigned *tmp_addr = (unsigned *)0x17000 |
| 35 | Iris::Boot cap = Iris::my_receiver.create_capability (0) |
| 36 | Iris::my_parent.provide_capability <Iris::Boot> (cap.copy ()) |
| 37 | Iris::free_cap (cap) |
| 38 | Iris::my_parent.init_done () |
| 39 | |
| 40 | while true: |
| 41 | Iris::wait () |
| 42 | switch Iris::recv.data[0].l: |
| 43 | case Iris::Boot::BOOT: |
| 44 | Iris::Block code = Iris::get_arg () |
| 45 | unsigned load = Iris::recv.data[1].l |
| 46 | unsigned entry = Iris::recv.data[1].h |
| 47 | Iris::Num lsize = code.get_size () |
| 48 | if lsize.h != 0: |
| 49 | Iris::panic (lsize.h, "string to boot is too large to be loaded") |
| 50 | unsigned size = lsize.l |
| 51 | unsigned pages = ((size + ~PAGE_MASK) >> PAGE_BITS) + 1 |
| 52 | unsigned phys = Iris::my_memory.alloc_range (pages) |
| 53 | if phys & ~PAGE_MASK: |
| 54 | Iris::panic (size, "unable to allocate space for string to load") |
| 55 | unsigned target, offset |
| 56 | if phys < (load & ~0xa0000000): |
| 57 | Iris::debug ("pre-loading\n") |
| 58 | Iris::Page pre = Iris::my_memory.create_page () |
| 59 | pre.alloc_physical (phys, true, true) |
| 60 | Iris::my_memory.map (pre, (unsigned)loader_addr) |
| 61 | for unsigned i = 0; i < &pre_end - &pre_code; ++i: |
| 62 | loader_addr[i] = (&pre_code)[i] |
| 63 | target = phys |
| 64 | offset = 1 |
| 65 | else: |
| 66 | Iris::debug ("post-loading\n") |
| 67 | Iris::Page post = Iris::my_memory.create_page () |
| 68 | post.alloc_physical (phys + ((pages - 1) << PAGE_BITS), true, true) |
| 69 | Iris::my_memory.map (post, (unsigned)loader_addr) |
| 70 | for unsigned i = 0; i < &post_end - &post_code; ++i: |
| 71 | loader_addr[i] = (&post_code)[i] |
| 72 | target = phys + ((pages - 1) << PAGE_BITS) |
| 73 | offset = 0 |
| 74 | Iris::Page tmp = Iris::my_memory.create_page () |
| 75 | tmp.set_flags (Iris::Page::PAYING | Iris::Page::FRAME) |
| 76 | Iris::my_memory.map (tmp, (unsigned)tmp_addr) |
| 77 | for unsigned i = 0; i < pages - 1; ++i: |
| 78 | Iris::Page page = Iris::my_memory.create_page () |
| 79 | page.alloc_physical (phys + ((i + offset) << PAGE_BITS), true, true) |
| 80 | Iris::my_memory.map (page, (unsigned)page_addr) |
| 81 | code.get_block (i << PAGE_BITS, PAGE_SIZE, 0, tmp) |
| 82 | for unsigned t = 0; t < PAGE_SIZE / 4; ++t: |
| 83 | page_addr[t] = tmp_addr[t] |
| 84 | args_t *args = (args_t *)((unsigned)loader_addr + PAGE_SIZE - sizeof (args_t)) |
| 85 | unsigned phys_args = target + PAGE_SIZE - sizeof (args_t) |
| 86 | args->load = load |
| 87 | args->entry = entry |
| 88 | args->size = size |
| 89 | args->source = phys + (offset << PAGE_BITS) | 0x80000000 |
| 90 | Iris::debug ("booting into: %x+%x->%x@%x (%x, %x)\n", args->source, args->size, args->load, args->entry, args, phys_args) |
| 91 | // Everything is set up; jump to the loader. |
| 92 | Iris::boot (target | 0x80000000, phys_args | 0x80000000) |
| 93 | Iris::panic (0, "Iris::boot should not return, but it does") |
| 94 | default: |
| 95 | Iris::panic (Iris::recv.data[0].l, "invalid commend received on boot capability") |
| 96 | |
| 97 | asm volatile ("\t.set noreorder\n" |
| 98 | "\t.globl pre_code, pre_end, post_code, post_end\n" |
| 99 | "\t.text\n" |
| 100 | "pre_code:\n" |
| 101 | "\tlw $t0, 0($a0)\n" // t0 is the load address |
| 102 | "\tlw $t1, 4($a0)\n" // t1 is the size |
| 103 | "\tlw $t9, 8($a0)\n" // t9 is the entry point |
| 104 | "\tlw $t2, 12($a0)\n" // t2 is the source of the loaded image |
| 105 | "\tadd $t0, $t0, $t1\n" // t0 is the end of the load region |
| 106 | "\tadd $t2, $t2, $t1\n" // t2 is the end of the source |
| 107 | "1:\n" |
| 108 | "\tlw $t3, -4($t2)\n" |
| 109 | "\tsw $t3, -4($t0)\n" |
| 110 | "\taddiu $t2, $t2, -4\n" |
| 111 | "\taddiu $t1, $t1, -4\n" |
| 112 | "\tbnez $t1, 1b\n" |
| 113 | "\taddiu $t0, $t0, -4\n" |
| 114 | // Done copying |
| 115 | "\tjr $t9\n" |
| 116 | "\tnop\n" |
| 117 | "pre_end:\n" |
| 118 | "\n" |
| 119 | "post_code:\n" |
| 120 | "\tlw $t0, 0($a0)\n" // t0 is the load address |
| 121 | "\tlw $t1, 4($a0)\n" // t1 is the size |
| 122 | "\tlw $t9, 8($a0)\n" // t9 is the entry point |
| 123 | "\tlw $t2, 12($a0)\n" // t2 is the source of the loaded image |
| 124 | "1:\n" |
| 125 | "\tlw $t3, 0($t2)\n" |
| 126 | "\tsw $t3, 0($t0)\n" |
| 127 | "\taddiu $t2, $t2, 4\n" |
| 128 | "\taddiu $t1, $t1, -4\n" |
| 129 | "\tbnez $t1, 1b\n" |
| 130 | "\taddiu $t0, $t0, 4\n" |
| 131 | // Done copying |
| 132 | "\tjr $t9\n" |
| 133 | "\tnop\n" |
| 134 | "post_end:\n" |
| 135 | "\n" |
| 136 | "\t.set reorder\n") |
| 137 |
Branches:
master
