August 21, 2018

Nanopi Fire3 - the S5P6818 bootrom

As you might expect, the chip contains bootrom code. It also has 64K of static ram at 0xffff0000 (this ends at 0xffffffff). This is where the bootrom must place the "first stage) boot loader. On reset, the chip has no idea what sort of external ram may be attached to it, and any external ram needs to have clocks set up for it and be in various ways initialized. This is a job that may vary from board to board.

Chapter 3 of the user manual for the S5P6818 is devoted to booting. The internal bootrom is 20kb in size. It will be mapped to address 0 on reset when it is selected, as it always will be on systems that I work with.

Memory Map

See page 15.5 in the user manual for this. Here is the general picture:
0x0000_0000 to 0x3fff_ffff  MCU-S  "static"
0x4000_0000 to 0xBfff_ffff  MCU-A  DDR (2G)
0xC000_0000 to 0xDfff_ffff  IO ("normal" IO)
0xE000_0000 to 0xFFFE_FFFF  -- reserved
0xFFFF_0000 to 0xFFFF_FFFF  SRAM
Note that my Nanopi Fire3 has only 1G of DDR ram from 0x40000000 to 0x7fffffff. It is worth noting that there is a "trust zone" controller that can partition this area and impose various restrictions on access to each region.

Also note that the MCU-S zone does not contain any static ram. I has zones that may be mapped to external static ram or nand memory, but my Nanopi Fire3 does not have any of this. It does contain the 20K bootrom.

0x0000_0000 to 0x03ff_ffff  -- Static zone 0
0x0400_0000 to 0x07ff_ffff  -- Static zone 1
0x0800_0000 to 0x2Bff_ffff  -- reserved
0x2C00_0000 to 0x2fff_ffff  -- NAND rom zone
0x3000_0000 to 0x33ff_ffff  -- reserved
0x3400_0000 to 0x3400_4fff  -- bootrom (20K)
0x3400_5000 to 0xFFFF_FFFF  -- reserved
Not that on reset, the bootrom and static zone 0 will be exchanged on the systems that I work with.

I have a linux program that I used on the Orange Pi to read out the H3 bootrom. When I compile it and run it on the S5P6818, it reads a nonsense pattern of 0x4545 from the bootrom address, and locks up the system when I try to read from address 0. Using U-Boot is instructive:

nanopi3# md.l 0
00000000: e59ff018 e59ff018 e59ff018 e59ff018    ................
00000010: e59ff018 eafffffe e59ff018 e59ff018    ................
00000020: 00000040 ffff0004 ffff0008 ffff000c    @...............
00000030: ffff0010 54300010 ffff0018 ffff001c    ......0T........
nanopi3# md.l 0x34000000
34000000: 45454545 45454545 45454545 45454545    EEEEEEEEEEEEEEEE
34000010: 45454545 45454545 45454545 45454545    EEEEEEEEEEEEEEEE
34000020: 45454545 45454545 45454545 45454545    EEEEEEEEEEEEEEEE
34000030: 45454545 45454545 45454545 45454545    EEEEEEEEEEEEEEEE
And we can read out the whole ROM using U-boot via "md.l 0 5120". For some reason this wants to go on and on forever, but U-boot nicely responds to Control-C and we can very easily cut and paste what we want. From there it is just a matter of a quick ruby program to convert this text into a binary file. From there, we already have the methods worked up to disassemble this.

We do see some recognizable text in the U-boot dump:

000001a0: eafffffa 4558454e 4e204c4c 34355058    ....NEXELL NXP54
000001b0: 52203033 20317665 2074634f 32203620    30 Rev1 Oct  6 2
000001c0: 20343130 353a3332 32343a35 00000000    014 23:55:42....

000043e0: 54414458 42532e41 584e0048 41544144    XDATA.SBH.NXDATA
000043f0: 4c42532e 54414600 54414600 20003233    .SBL.FAT.FAT32.
00004400: 5b3b2c2b 2a225d3d 3f3e3c3a 00007f7c    +,;[=]"*:<>?|...
Look at that first string, "NEXELL NXP5430 Rev1 Oct 6 2014 23:55:42". I wonder what a NXP5430 is? And look at the 2014 date. Here it is 2018 and we are thinking of this as hot new technology. Well, well, well ...

A bit of the disassembled code

Look at the following. These are 32 bit ARM instructions. Just the fact that we see "r0" instead of "x0" is the first tip off. Amazingly enough, the bootrom is running in A32 mode. Perhaps this is selectable by boot option strapping?
       0:       e59ff018        ldr     pc, [pc, #24]   ; 0x20
       4:       e59ff018        ldr     pc, [pc, #24]   ; 0x24
       8:       e59ff018        ldr     pc, [pc, #24]   ; 0x28
       c:       e59ff018        ldr     pc, [pc, #24]   ; 0x2c
      10:       e59ff018        ldr     pc, [pc, #24]   ; 0x30
      14:       eafffffe        b       0x14            ; -- spin
      18:       e59ff018        ldr     pc, [pc, #24]   ; 0x38
      1c:       e59ff018        ldr     pc, [pc, #24]   ; 0x3c
      20:       00000040
      ... ... ...

; clear some bits in the SCTLR register
      40:       ee110f10        mrc     15, 0, r0, cr1, cr0, {0}
      44:       e3c00b0e        bic     r0, r0, #14336  ; 0x3800
      48:       e3c00005        bic     r0, r0, #5
      4c:       ee010f10        mcr     15, 0, r0, cr1, cr0, {0}

Lessons learned

The on chip bootrom runs in 32 bit (A32) ARM mode! Who would have guessed.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org