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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
/*
* Kernel relocation stub for MIPS devices
*
* Copyright (C) 2015 Felix Fietkau <nbd@openwrt.org>
*
* Based on:
*
* LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* Some parts of this code was based on the OpenWrt specific lzma-loader
* for the BCM47xx and ADM5120 based boards:
* Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <asm/asm.h>
#include <asm/regdef.h>
#include "cp0regdef.h"
#include "cacheops.h"
#define KSEG0 0x80000000
.macro ehb
sll zero, 3
.endm
.macro reset
li t0, 0xbe000034
lw t1, 0(t0)
ori t1, 1
sw t1, 0(t0)
.endm
.text
LEAF(startup)
.set noreorder
.set mips32
.fill 0x10000
mtc0 zero, CP0_WATCHLO # clear watch registers
mtc0 zero, CP0_WATCHHI
mtc0 zero, CP0_CAUSE # clear before writing status register
mfc0 t0, CP0_STATUS
li t1, 0x1000001f
or t0, t1
xori t0, 0x1f
mtc0 t0, CP0_STATUS
ehb
mtc0 zero, CP0_COUNT
mtc0 zero, CP0_COMPARE
ehb
la t0, __reloc_label # get linked address of label
bal __reloc_label # branch and link to label to
nop # get actual address
__reloc_label:
subu t0, ra, t0 # get reloc_delta
/* Copy our code to the right place */
la t1, _code_start # get linked address of _code_start
la t2, _code_end # get linked address of _code_end
addu t4, t2, t0 # calculate actual address of _code_end
lw t5, 0(t4) # get extra data size
add t2, t5
add t2, 4
add t0, t1 # calculate actual address of _code_start
__reloc_copy:
lw t3, 0(t0)
sw t3, 0(t1)
add t1, 4
blt t1, t2, __reloc_copy
add t0, 4
/* flush cache */
la t0, _code_start
la t1, _code_end
li t2, ~(CONFIG_CACHELINE_SIZE - 1)
and t0, t2
and t1, t2
li t2, CONFIG_CACHELINE_SIZE
b __flush_check
nop
__flush_line:
cache Hit_Writeback_Inv_D, 0(t0)
cache Hit_Invalidate_I, 0(t0)
add t0, t2
__flush_check:
bne t0, t1, __flush_line
nop
sync
la t0, __reloc_back
j t0
nop
__reloc_back:
la t0, _code_end
add t0, 4
addu t1, t0, t5
li t2, KERNEL_ADDR
__kernel_copy:
lw t3, 0(t0)
sw t3, 0(t2)
add t0, 4
blt t0, t1, __kernel_copy
add t2, 4
/* flush cache */
li t0, KERNEL_ADDR
addu t1, t0, t5
add t1, CONFIG_CACHELINE_SIZE - 1
li t2, ~(CONFIG_CACHELINE_SIZE - 1)
and t0, t2
and t1, t2
li t2, CONFIG_CACHELINE_SIZE
b __kernel_flush_check
nop
__kernel_flush_line:
cache Hit_Writeback_Inv_D, 0(t0)
cache Hit_Invalidate_I, 0(t0)
add t0, t2
__kernel_flush_check:
bne t0, t1, __kernel_flush_line
nop
sync
li t0, KERNEL_ADDR
jr t0
nop
.set reorder
END(startup)
|