Root/userspace/nanonote/boot.ccp

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
22extern "C":
23    extern unsigned pre_code, pre_end, post_code, post_end
24
25struct args_t:
26    unsigned load
27    unsigned size
28    unsigned entry
29    unsigned source
30
31Iris::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
97asm 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

Archive Download this file

Branches:
master



interactive