#pypp 0 // Iris: micro-kernel for a capability-based operating system. // source/boot.ccp: Boot into another kernel. // Copyright 2010 Bas Wijnen // // 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 . #include #include 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 (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::Block 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")