linux/arch/cris/boot/rescue/head_v10.S
<<
>>
Prefs
   1/*
   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 can't 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 <offset>', 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-2007 Axis Communications AB
  63 */
  64
  65#ifdef CONFIG_ETRAX_AXISFLASHMAP
  66
  67#define ASSEMBLER_MACROS_ONLY
  68#include <arch/sv_addr_ag.h>
  69
  70        ;; The partitiontable is looked for at the first sector after the boot
  71        ;; sector. Sector size is 65536 bytes in all flashes we use.
  72
  73#define PTABLE_START CONFIG_ETRAX_PTABLE_SECTOR
  74#define PTABLE_MAGIC 0xbeef
  75
  76        ;; The normal Etrax100 on-chip boot ROM does serial boot at 0x380000f0.
  77        ;; That is not where we put our downloaded serial boot-code.
  78        ;; The length is enough for downloading code that loads the rest
  79        ;; of itself (after having setup the DRAM etc).
  80        ;; It is the same length as the on-chip ROM loads, so the same
  81        ;; host loader can be used to load a rescued product as well as
  82        ;; one booted through the Etrax serial boot code.
  83
  84#define CODE_START 0x40000000
  85#define CODE_LENGTH 784
  86
  87#ifdef CONFIG_ETRAX_RESCUE_SER0
  88#define SERXOFF R_SERIAL0_XOFF
  89#define SERBAUD R_SERIAL0_BAUD
  90#define SERRECC R_SERIAL0_REC_CTRL
  91#define SERRDAT R_SERIAL0_REC_DATA
  92#define SERSTAT R_SERIAL0_STATUS
  93#endif
  94#ifdef CONFIG_ETRAX_RESCUE_SER1
  95#define SERXOFF R_SERIAL1_XOFF
  96#define SERBAUD R_SERIAL1_BAUD
  97#define SERRECC R_SERIAL1_REC_CTRL
  98#define SERRDAT R_SERIAL1_REC_DATA
  99#define SERSTAT R_SERIAL1_STATUS
 100#endif
 101#ifdef CONFIG_ETRAX_RESCUE_SER2
 102#define SERXOFF R_SERIAL2_XOFF
 103#define SERBAUD R_SERIAL2_BAUD
 104#define SERRECC R_SERIAL2_REC_CTRL
 105#define SERRDAT R_SERIAL2_REC_DATA
 106#define SERSTAT R_SERIAL2_STATUS
 107#endif
 108#ifdef CONFIG_ETRAX_RESCUE_SER3
 109#define SERXOFF R_SERIAL3_XOFF
 110#define SERBAUD R_SERIAL3_BAUD
 111#define SERRECC R_SERIAL3_REC_CTRL
 112#define SERRDAT R_SERIAL3_REC_DATA
 113#define SERSTAT R_SERIAL3_STATUS
 114#endif
 115
 116#define NOP_DI 0xf025050f
 117#define RAM_INIT_MAGIC 0x56902387
 118
 119        .text
 120
 121        ;; This is the entry point of the rescue code
 122        ;; 0x80000000 if loaded in flash (as it should be)
 123        ;; Since etrax actually starts at address 2 when booting from flash, we
 124        ;; put a nop (2 bytes) here first so we dont accidentally skip the di
 125
 126        nop
 127        di
 128
 129        jump    in_cache        ; enter cached area instead
 130in_cache:
 131
 132
 133        ;; First put a jump test to give a possibility of upgrading the
 134        ;; rescue code without erasing/reflashing the sector.
 135        ;; We put a longword of -1 here and if it is not -1, we jump using
 136        ;; the value as jump target. Since we can always change 1's to 0's
 137        ;; without erasing the sector, it is possible to add new
 138        ;; code after this and altering the jumptarget in an upgrade.
 139
 140jtcd:   move.d  [jumptarget], $r0
 141        cmp.d   0xffffffff, $r0
 142        beq     no_newjump
 143        nop
 144
 145        jump    [$r0]
 146
 147jumptarget:
 148        .dword  0xffffffff      ; can be overwritten later to insert new code
 149
 150no_newjump:
 151#ifdef CONFIG_ETRAX_ETHERNET
 152        ;; Start MII clock to make sure it is running when tranceiver is reset
 153        move.d 0x3, $r0    ; enable = on, phy = mii_clk
 154        move.d $r0, [R_NETWORK_GEN_CONFIG]
 155#endif
 156
 157        ;; We need to setup the bus registers before we start using the DRAM
 158#include "../../../arch-v10/lib/dram_init.S"
 159
 160        ;; we now should go through the checksum-table and check the listed
 161        ;; partitions for errors.
 162
 163        move.d  PTABLE_START, $r3
 164        move.d  [$r3], $r0
 165        cmp.d   NOP_DI, $r0     ; make sure the nop/di is there...
 166        bne     do_rescue
 167        nop
 168
 169        ;; skip the code transparency block (10 bytes).
 170
 171        addq    10, $r3
 172
 173        ;; check for correct magic
 174
 175        move.w  [$r3+], $r0
 176        cmp.w   PTABLE_MAGIC, $r0
 177        bne     do_rescue       ; didn't recognize - trig rescue
 178        nop
 179
 180        ;; check for correct ptable checksum
 181
 182        movu.w  [$r3+], $r2     ; ptable length
 183        move.d  $r2, $r8        ; save for later, length of total ptable
 184        addq    28, $r8         ; account for the rest
 185        move.d  [$r3+], $r4     ; ptable checksum
 186        move.d  $r3, $r1
 187        jsr     checksum        ; r1 source, r2 length, returns in r0
 188
 189        cmp.d   $r0, $r4
 190        bne     do_rescue       ; didn't match - trig rescue
 191        nop
 192
 193        ;; ptable is ok. validate each entry.
 194
 195        moveq   -1, $r7
 196
 197ploop:  move.d  [$r3+], $r1     ; partition offset (from ptable start)
 198        bne     notfirst        ; check if it is the partition containing ptable
 199        nop                     ; yes..
 200        move.d  $r8, $r1        ; for its checksum check, skip the ptable
 201        move.d  [$r3+], $r2     ; partition length
 202        sub.d   $r8, $r2        ; minus the ptable length
 203        ba      bosse
 204        nop
 205notfirst:
 206        cmp.d   -1, $r1         ; the end of the ptable ?
 207        beq     flash_ok        ;   if so, the flash is validated
 208        move.d  [$r3+], $r2     ; partition length
 209bosse:  move.d  [$r3+], $r5     ; checksum
 210        move.d  [$r3+], $r4     ; type and flags
 211        addq    16, $r3         ; skip the reserved bytes
 212        btstq   16, $r4         ; check ro flag
 213        bpl     ploop           ;   rw partition, skip validation
 214        nop
 215        btstq   17, $r4         ; check bootable flag
 216        bpl     1f
 217        nop
 218        move.d  $r1, $r7        ; remember boot partition offset
 2191:
 220        add.d   PTABLE_START, $r1
 221
 222        jsr     checksum        ; checksum the partition
 223
 224        cmp.d   $r0, $r5
 225        beq     ploop           ; checksums matched, go to next entry
 226        nop
 227
 228        ;; otherwise fall through to the rescue code.
 229
 230do_rescue:
 231        ;; setup port PA and PB default initial directions and data
 232        ;; (so we can flash LEDs, and so that DTR and others are set)
 233
 234        move.b  CONFIG_ETRAX_DEF_R_PORT_PA_DIR, $r0
 235        move.b  $r0, [R_PORT_PA_DIR]
 236        move.b  CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r0
 237        move.b  $r0, [R_PORT_PA_DATA]
 238
 239        move.b  CONFIG_ETRAX_DEF_R_PORT_PB_DIR, $r0
 240        move.b  $r0, [R_PORT_PB_DIR]
 241        move.b  CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r0
 242        move.b  $r0, [R_PORT_PB_DATA]
 243
 244        ;; setup the serial port at 115200 baud
 245
 246        moveq   0, $r0
 247        move.d  $r0, [SERXOFF]
 248
 249        move.b  0x99, $r0
 250        move.b  $r0, [SERBAUD]  ; 115.2kbaud for both transmit and receive
 251
 252        move.b  0x40, $r0       ; rec enable
 253        move.b  $r0, [SERRECC]
 254
 255        moveq   0, $r1          ; "timer" to clock out a LED red flash
 256        move.d  CODE_START, $r3 ; destination counter
 257        movu.w  CODE_LENGTH, $r4; length
 258
 259wait_ser:
 260        addq    1, $r1
 261#ifndef CONFIG_ETRAX_NO_LEDS
 262#ifdef CONFIG_ETRAX_PA_LEDS
 263        move.b  CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r2
 264#endif
 265#ifdef CONFIG_ETRAX_PB_LEDS
 266        move.b  CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r2
 267#endif
 268        move.d  (1 << CONFIG_ETRAX_LED1R) | (1 << CONFIG_ETRAX_LED2R), $r0
 269        btstq   16, $r1
 270        bpl     1f
 271        nop
 272        or.d    $r0, $r2        ; set bit
 273        ba      2f
 274        nop
 2751:      not     $r0             ; clear bit
 276        and.d   $r0, $r2
 2772:
 278#ifdef CONFIG_ETRAX_PA_LEDS
 279        move.b  $r2, [R_PORT_PA_DATA]
 280#endif
 281#ifdef CONFIG_ETRAX_PB_LEDS
 282        move.b  $r2, [R_PORT_PB_DATA]
 283#endif
 284#ifdef CONFIG_ETRAX_90000000_LEDS
 285        move.b  $r2, [0x90000000]
 286#endif
 287#endif
 288
 289        ;; check if we got something on the serial port
 290
 291        move.b  [SERSTAT], $r0
 292        btstq   0, $r0          ; data_avail
 293        bpl     wait_ser
 294        nop
 295
 296        ;; got something - copy the byte and loop
 297
 298        move.b  [SERRDAT], $r0
 299        move.b  $r0, [$r3+]
 300
 301        subq    1, $r4          ; decrease length
 302        bne     wait_ser
 303        nop
 304
 305        ;; jump into downloaded code
 306
 307        move.d  RAM_INIT_MAGIC, $r8     ; Tell next product that DRAM is
 308                                        ; initialized
 309        jump    CODE_START
 310
 311flash_ok:
 312        ;; check r7, which contains either -1 or the partition to boot from
 313
 314        cmp.d   -1, $r7
 315        bne     1f
 316        nop
 317        move.d  PTABLE_START, $r7; otherwise use the ptable start
 3181:
 319        move.d  RAM_INIT_MAGIC, $r8     ; Tell next product that DRAM is
 320                                        ; initialized
 321        jump    $r7             ; boot!
 322
 323
 324        ;; Helper subroutines
 325
 326        ;; Will checksum by simple addition
 327        ;; r1 - source
 328        ;; r2 - length in bytes
 329        ;; result will be in r0
 330checksum:
 331        moveq   0, $r0
 332        moveq   CONFIG_ETRAX_FLASH1_SIZE, $r6
 333
 334        ;; If the first physical flash memory is exceeded wrap to the
 335        ;; second one
 336        btstq   26, $r1         ; Are we addressing first flash?
 337        bpl     1f
 338        nop
 339        clear.d $r6
 340
 3411:      test.d  $r6             ; 0 = no wrapping
 342        beq     2f
 343        nop
 344        lslq    20, $r6         ; Convert MB to bytes
 345        sub.d   $r1, $r6
 346
 3472:      addu.b  [$r1+], $r0
 348        subq    1, $r6          ; Flash memory left
 349        beq     3f
 350        subq    1, $r2          ; Length left
 351        bne     2b
 352        nop
 353        ret
 354        nop
 355
 3563:      move.d  MEM_CSE1_START, $r1 ; wrap to second flash
 357        ba      2b
 358        nop
 359
 360#endif
 361