OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [cris/] [boot/] [rescue/] [head.S] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Rescue code, made to reside at the beginning of the
3
 * flash-memory. when it starts, it checks a partition
4
 * table at the first sector after the rescue sector.
5
 * the partition table was generated by the product builder
6
 * script and contains offsets, lengths, types and checksums
7
 * for each partition that this code should check.
8
 *
9
 * If any of the checksums fail, we assume the flash is so
10
 * corrupt that we cant use it to boot into the ftp flash
11
 * loader, and instead we initialize the serial port to
12
 * receive a flash-loader and new flash image. we dont include
13
 * any flash code here, but just accept a certain amount of
14
 * bytes from the serial port and jump into it. the downloaded
15
 * code is put in the cache.
16
 *
17
 * The partitiontable is designed so that it is transparent to
18
 * code execution - it has a relative branch opcode in the
19
 * beginning that jumps over it. each entry contains extra
20
 * data so we can add stuff later.
21
 *
22
 * Partition table format:
23
 *
24
 *     Code transparency:
25
 *
26
 *     2 bytes    [opcode 'nop']
27
 *     2 bytes    [opcode 'di']
28
 *     4 bytes    [opcode 'ba ', 8-bit or 16-bit version]
29
 *     2 bytes    [opcode 'nop', delay slot]
30
 *
31
 *     Table validation (at +10):
32
 *
33
 *     2 bytes    [magic/version word for partitiontable - 0xef, 0xbe]
34
 *     2 bytes    [length of all entries plus the end marker]
35
 *     4 bytes    [checksum for the partitiontable itself]
36
 *
37
 *     Entries, each with the following format, last has offset -1:
38
 *
39
 *        4 bytes    [offset in bytes, from start of flash]
40
 *        4 bytes    [length in bytes of partition]
41
 *        4 bytes    [checksum, simple longword sum]
42
 *        2 bytes    [partition type]
43
 *        2 bytes    [flags, only bit 0 used, ro/rw = 1/0]
44
 *        16 bytes   [reserved for future use]
45
 *
46
 *     End marker
47
 *
48
 *        4 bytes    [-1]
49
 *
50
 *       10 bytes    [0, padding]
51
 *
52
 * Bit 0 in flags signifies RW or RO. The rescue code only bothers
53
 * to check the checksum for RO partitions, since the others will
54
 * change their data without updating the checksums. A 1 in bit 0
55
 * means RO, 0 means RW. That way, it is possible to set a partition
56
 * in RO mode initially, and later mark it as RW, since you can always
57
 * write 0's to the flash.
58
 *
59
 * During the wait for serial input, the status LED will flash so the
60
 * user knows something went wrong.
61
 *
62
 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Axis Communications AB
63
 */
64
 
65
#include 
66
#define ASSEMBLER_MACROS_ONLY
67
#include 
68
 
69
        ;; The partitiontable is looked for at the first sector after the boot
70
        ;; sector. Sector size is 65536 bytes in all flashes we use.
71
 
72
#define PTABLE_START CONFIG_ETRAX_PTABLE_SECTOR
73
#define PTABLE_MAGIC 0xbeef
74
 
75
        ;; The normal Etrax100 on-chip boot ROM does serial boot at 0x380000f0.
76
        ;; That is not where we put our downloaded serial boot-code. The length is
77
        ;; enough for downloading code that loads the rest of itself (after
78
        ;; having setup the DRAM etc). It is the same length as the on-chip
79
        ;; ROM loads, so the same host loader can be used to load a rescued
80
        ;; product as well as one booted through the Etrax serial boot code.
81
 
82
#define CODE_START 0x40000000
83
#define CODE_LENGTH 784
84
 
85
#ifdef CONFIG_ETRAX_RESCUE_SER0
86
#define SERXOFF R_SERIAL0_XOFF
87
#define SERBAUD R_SERIAL0_BAUD
88
#define SERRECC R_SERIAL0_REC_CTRL
89
#define SERRDAT R_SERIAL0_REC_DATA
90
#define SERSTAT R_SERIAL0_STATUS
91
#endif
92
#ifdef CONFIG_ETRAX_RESCUE_SER1
93
#define SERXOFF R_SERIAL1_XOFF
94
#define SERBAUD R_SERIAL1_BAUD
95
#define SERRECC R_SERIAL1_REC_CTRL
96
#define SERRDAT R_SERIAL1_REC_DATA
97
#define SERSTAT R_SERIAL1_STATUS
98
#endif
99
#ifdef CONFIG_ETRAX_RESCUE_SER2
100
#define SERXOFF R_SERIAL2_XOFF
101
#define SERBAUD R_SERIAL2_BAUD
102
#define SERRECC R_SERIAL2_REC_CTRL
103
#define SERRDAT R_SERIAL2_REC_DATA
104
#define SERSTAT R_SERIAL2_STATUS
105
#endif
106
#ifdef CONFIG_ETRAX_RESCUE_SER3
107
#define SERXOFF R_SERIAL3_XOFF
108
#define SERBAUD R_SERIAL3_BAUD
109
#define SERRECC R_SERIAL3_REC_CTRL
110
#define SERRDAT R_SERIAL3_REC_DATA
111
#define SERSTAT R_SERIAL3_STATUS
112
#endif
113
 
114
#define NOP_DI 0xf025050f
115
#define RAM_INIT_MAGIC 0x56902387
116
 
117
        .text
118
 
119
        ;; This is the entry point of the rescue code
120
        ;; 0x80000000 if loaded in flash (as it should be)
121
        ;; since etrax actually starts at address 2 when booting from flash, we
122
        ;; put a nop (2 bytes) here first so we dont accidentally skip the di
123
 
124
        nop
125
        di
126
 
127
        jump    in_cache        ; enter cached area instead
128
in_cache:
129
 
130
        ;; first put a jump test to give a possibility of upgrading the rescue code
131
        ;; without erasing/reflashing the sector. we put a longword of -1 here and if
132
        ;; it is not -1, we jump using the value as jump target. since we can always
133
        ;; change 1's to 0's without erasing the sector, it is possible to add new
134
        ;; code after this and altering the jumptarget in an upgrade.
135
 
136
jtcd:   move.d  [jumptarget], $r0
137
        cmp.d   0xffffffff, $r0
138
        beq     no_newjump
139
        nop
140
 
141
        jump    [$r0]
142
 
143
jumptarget:
144
        .dword  0xffffffff      ; can be overwritten later to insert new code
145
 
146
no_newjump:
147
#ifdef CONFIG_ETRAX_ETHERNET
148
        ;; Start MII clock to make sure it is running when tranceiver is reset
149
        move.d 0x3, $r0    ; enable = on, phy = mii_clk
150
        move.d $r0, [R_NETWORK_GEN_CONFIG]
151
#endif
152
 
153
        ;; Setup port PA and PB default initial directions and data
154
        ;; (so we can flash LEDs, and so that DTR and others are set)
155
 
156
        move.b  CONFIG_ETRAX_DEF_R_PORT_PA_DIR, $r0
157
        move.b  $r0, [R_PORT_PA_DIR]
158
        move.b  CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r0
159
        move.b  $r0, [R_PORT_PA_DATA]
160
 
161
        move.b  CONFIG_ETRAX_DEF_R_PORT_PB_DIR, $r0
162
        move.b  $r0, [R_PORT_PB_DIR]
163
        move.b  CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r0
164
        move.b  $r0, [R_PORT_PB_DATA]
165
 
166
        ;; We need to setup the bus registers before we start using the DRAM
167
#include "../../lib/dram_init.S"
168
 
169
        ;; we now should go through the checksum-table and check the listed
170
        ;; partitions for errors.
171
 
172
        move.d  PTABLE_START, $r3
173
        move.d  [$r3], $r0
174
        cmp.d   NOP_DI, $r0     ; make sure the nop/di is there...
175
        bne     do_rescue
176
        nop
177
 
178
        ;; skip the code transparency block (10 bytes).
179
 
180
        addq    10, $r3
181
 
182
        ;; check for correct magic
183
 
184
        move.w  [$r3+], $r0
185
        cmp.w   PTABLE_MAGIC, $r0
186
        bne     do_rescue       ; didn't recognize - trig rescue
187
        nop
188
 
189
        ;; check for correct ptable checksum
190
 
191
        movu.w  [$r3+], $r2     ; ptable length
192
        move.d  $r2, $r8        ; save for later, length of total ptable
193
        addq    28, $r8         ; account for the rest
194
        move.d  [$r3+], $r4     ; ptable checksum
195
        move.d  $r3, $r1
196
        jsr     checksum        ; r1 source, r2 length, returns in r0
197
 
198
        cmp.d   $r0, $r4
199
        bne     do_rescue       ; didn't match - trig rescue
200
        nop
201
 
202
        ;; ptable is ok. validate each entry.
203
 
204
        moveq   -1, $r7
205
 
206
ploop:  move.d  [$r3+], $r1     ; partition offset (from ptable start)
207
        bne     notfirst        ; check if it is the partition containing ptable
208
        nop                     ; yes..
209
        move.d  $r8, $r1        ; for its checksum check, skip the ptable
210
        move.d  [$r3+], $r2     ; partition length
211
        sub.d   $r8, $r2        ; minus the ptable length
212
        ba      bosse
213
        nop
214
notfirst:
215
        cmp.d   -1, $r1         ; the end of the ptable ?
216
        beq     flash_ok        ;   if so, the flash is validated
217
        move.d  [$r3+], $r2     ; partition length
218
bosse:  move.d  [$r3+], $r5     ; checksum
219
        move.d  [$r3+], $r4     ; type and flags
220
        addq    16, $r3         ; skip the reserved bytes
221
        btstq   16, $r4         ; check ro flag
222
        bpl     ploop           ;   rw partition, skip validation
223
        nop
224
        btstq   17, $r4         ; check bootable flag
225
        bpl     1f
226
        nop
227
        move.d  $r1, $r7        ; remember boot partition offset
228
1:
229
 
230
        add.d   PTABLE_START, $r1
231
 
232
        jsr     checksum        ; checksum the partition
233
 
234
        cmp.d   $r0, $r5
235
        beq     ploop           ; checksums matched, go to next entry
236
        nop
237
 
238
        ;; otherwise fall through to the rescue code.
239
 
240
do_rescue:
241
 
242
        ;; setup the serial port at 115200 baud
243
 
244
        moveq   0, $r0
245
        move.d  $r0, [SERXOFF]
246
 
247
        move.b  0x99, $r0
248
        move.b  $r0, [SERBAUD]          ; 115.2kbaud for both transmit and receive
249
 
250
        move.b  0x40, $r0               ; rec enable
251
        move.b  $r0, [SERRECC]
252
 
253
        moveq   0, $r1          ; "timer" to clock out a LED red flash
254
        move.d  CODE_START, $r3 ; destination counter
255
        movu.w  CODE_LENGTH, $r4; length
256
 
257
wait_ser:
258
        addq    1, $r1
259
#ifndef CONFIG_ETRAX_NO_LEDS
260
#ifdef CONFIG_ETRAX_PA_LEDS
261
        move.b  CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r2
262
#endif
263
#ifdef CONFIG_ETRAX_PB_LEDS
264
        move.b  CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r2
265
#endif
266
        move.d  (1 << CONFIG_ETRAX_LED1R) | (1 << CONFIG_ETRAX_LED2R), $r0
267
        btstq   16, $r1
268
        bpl     1f
269
        nop
270
        or.d    $r0, $r2        ; set bit
271
        ba      2f
272
        nop
273
1:      not     $r0             ; clear bit
274
        and.d   $r0, $r2
275
2:
276
#ifdef CONFIG_ETRAX_PA_LEDS
277
        move.b  $r2, [R_PORT_PA_DATA]
278
#endif
279
#ifdef CONFIG_ETRAX_PB_LEDS
280
        move.b  $r2, [R_PORT_PB_DATA]
281
#endif
282
#ifdef CONFIG_ETRAX_90000000_LEDS
283
        move.b  $r2, [0x90000000]
284
#endif
285
#endif
286
 
287
        ;; check if we got something on the serial port
288
 
289
        move.b  [SERSTAT], $r0
290
        btstq   0, $r0          ; data_avail
291
        bpl     wait_ser
292
        nop
293
 
294
        ;; got something - copy the byte and loop
295
 
296
        move.b  [SERRDAT], $r0
297
        move.b  $r0, [$r3+]
298
 
299
        subq    1, $r4          ; decrease length
300
        bne     wait_ser
301
        nop
302
 
303
        ;; jump into downloaded code
304
 
305
        move.d  RAM_INIT_MAGIC, $r8     ; Tell next product that DRAM is initialized
306
        jump    CODE_START
307
 
308
flash_ok:
309
        ;; check r7, which contains either -1 or the partition to boot from
310
 
311
        cmp.d   -1, $r7
312
        bne     1f
313
        nop
314
        move.d  PTABLE_START, $r7; otherwise use the ptable start
315
1:
316
        move.d  RAM_INIT_MAGIC, $r8     ; Tell next product that DRAM is initialized
317
        jump    $r7             ; boot!
318
 
319
 
320
        ;; Helper subroutines
321
 
322
        ;; Will checksum by simple addition
323
        ;; r1 - source
324
        ;; r2 - length in bytes
325
        ;; result will be in r0
326
checksum:
327
        moveq   0, $r0
328
1:      addu.b  [$r1+], $r0
329
        subq    1, $r2
330
        bne     1b
331
        nop
332
        ret
333
        nop

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.