1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
/*
* Copyright (c) 2017 Richard Braun.
*
* 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 <machine/asm.h>
#include <machine/boot.h>
#include <machine/pmap.h>
.section BOOT_LOAD_SECTION, "awx"
ASM_DATA(boot_exception_table):
.long _start /* Reset */
.long 0 /* Undefined instruction */
.long 0 /* Software interrupt */
.long 0 /* Prefetch abort */
.long 0 /* Data abort */
.long 0 /* IRQ */
.long 0 /* FIQ */
ASM_END(boot_exception_table)
ASM_FUNC(_start):
/*
* Assume the code runs from flash. For the sake of simplicity, make
* the kernel run from RAM. This requires relocating it, and since the
* RAM size isn't known, we can't use it for a stack. As a result,
* perform the relocation in assembly without using a stack.
*/
ldr %r5, =(BOOT_RAM_START) /* Load RAM address in %r5 */
mov %r6, #0 /* Load kernel address in %r6 */
ldr %r0, boot_kernel_end /* Load kernel end virtual address
in %r0 */
ldr %r1, =(PMAP_START_KERNEL_ADDRESS) /* Load kernel virtual address in %r1 */
sub %r7, %r0, %r1 /* Compute kernel size in bytes */
lsr %r7, %r7, #2 /* Compute kernel size in words */
sub %r5, %r5, #4 /* Prepare for auto-increment */
sub %r6, %r6, #4
1:
ldr %r0, [%r6, #4]! /* Load word with auto-increment */
str %r0, [%r5, #4]! /* Store word with auto-increment */
sub %r7, %r7, #4 /* Account for the written word */
cmp %r7, #0 /* Check the number of words left */
beq 1f /* Break if copy complete */
b 1b /* Continue otherwise */
1:
/*
* Relocation is done. Make sure that the processor actually runs kernel
* code by flushing all the relevant caches.
*/
mov %r0, #0
mcr p15, 0, %r0, c7, c7, 0 /* Clean all caches */
mcr p15, 0, %r0, c7, c10, 5 /* Data synchronization barrier */
mcr p15, 0, %r0, c7, c5, 4 /* Flush prefetch buffer */
/* Set up the stack */
ldr %r13, boot_stack_addr
add %r13, %r13, #BOOT_STACK_SIZE
bl boot_setup_paging
/* Never reached */
nop
ASM_END(_start)
boot_kernel_end:
.long _end
boot_stack_addr:
.long boot_stack
|