mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-16 19:48:06 +02:00
137 lines
4.9 KiB
COBOL
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")
|