1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-06-28 23:29:50 +03:00
iris/source/boot.ccp
2010-09-01 23:27:14 +02:00

137 lines
4.9 KiB
COBOL

#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::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")