From S1MP3 Wiki
Jump to: navigation, search

The 1st-stage bootloader

The 1st-stage bootstrap or bootloader code contains 8kb or 16kb (v9) of code which gets executed from Z80 (internal) address 0x8000 on every power-up. It contains two functional parts:

Execution flow chart

  • detect NAND flash and load first 16K bytes (BREC) into ZRAM1 or IPMM (v9)
  • if all went right, pass execution to it (jp 0x0000), or otherwise
  • enter ADFU Recovery Mode on any error

Disassembly of 3.x BROM (initial portion)

; ---------------------------------------------------------------------------
                org     0000h
ZRAM1:          ds      4000h                     ; 0000: ZRAM1
URAM:           ds      13h                       ; 4000: ZRAM2
URAM_SUB:       ds      0EEDh                     ; 4013: SUB
URAM_STACK:                                       ; 4F00: STACK
; ---------------------------------------------------------------------------
                org     8000h
ENTRY:          jp      init                      ; ENTRYPOINT ON POWER-ON
; ---------------------------------------------------------------------------
                db 0, 30h, 0, 51h, 0Ch, 20h, 3, 3, 2, 0D6h, 10h, 51h, 0FFh
szActos:        db "Actos@Actions", 0, 0, 0
szGongee:       db "Gongee.Zhang", 0, 0, 0, 0
; ---------------------------------------------------------------------------
init:           ld      a, 0A2h                   ; enable watchdog (1.4sec)
                out     (4Eh), a                  ; .
                ld      a, 1                      ; unlock A15 (bootmode)
                out     (4), a                    ; .
                di                                ; disable interrupts
                im      1                         ; set interrupt mode 1
                xor     a                         ; mask-out interrupts
                out     (27h), a                  ; .
                ld      a, 80h                    ; enable PLL1
                out     (42h), a                  ; .
                in      a, (70h)                  ; map B1+B2 to URAM
                or      30h                       ; .
                out     (70h), a                  ; .
                ld      a, 0F7h                   ; page in ZRAM2
                out     (5), a                    ; .
                ld      sp, URAM_STACK            ; .
                ld      a, 10h                    ; select MCU clock source
                out     (0), a                    ; .

                ld      hl, brec_loader           ; memcopy (3kb)
                ld      de, URAM                  ; .
                ld      bc, 0C00h                 ; .
                ldir                              ; .
                call    URAM_SUB                  ; call copied code
                and     a                         ; returned zero/success?
                jp      z, ZRAM1                  ;   yes -> execute brec

                ld      hl, adfu_mode             ; memcopy (3kb)
                ld      de, ZRAM1                 ; .
                ld      bc, 0C00h                 ; .
                ldir                              ; .
                ld      sp, 100h                  ; init stack
                jp      ZRAM1                     ; jump into ZRAM1
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
                org     8100h
brec_loader:    ;...
                org     9000h
adfu_mode:      ;...
; ---------------------------------------------------------------------------

Disassembly of ACU7513 (v9) BROM (initial portion)

  • Note: ATJ2093H BROM whose code is discussed in FLASHLDR and HARDADFU has the same loader code here, with different header (changes noted)*
; ACU7513 BROM
org 8000h
X8000:	jp	X8030    ; processor starts executing here
db 0,48,128,136,136      ; version?
db 20h,6,4,20h           ; date 2006-04-20 ? (one 2093H had 2005-12-40 here)
dw 10d6h                 ; vendor ID 10d6
dw 0ff79h                ; PID? (the 2093H has FF61)
org 8030h
; start here
X8030:	ld	a,3eh    ; ???
	out	(0ddh),a ; ???
	ld	a,0a2h   ; watchdog 1.4s
	out	(4eh),a
	ld	a,1
	out	(4),a    ; A15 off
	im	1
	xor	a
	out	(27h),a ; disable all interrupts
	ld	a,85h
	out	(40h),a ; enable HOSC with default settings
	ld	b,8
X8048:	djnz	X8048   ; wait for HOSC to startup and stabilize
	in	a,(4eh)
	or	8
	out	(4eh),a ; clear watchdog
	in	a,(4)
	or	8
	out	(4),a ; select HOSC for DMA clock
	ld	a,0
	out	(3dh),a ; DMA clock = HOSC/1
	ld	a,10h
	out	(0),a  ; select HOSC for MCU clock
; Now we are running at full speed (24MHz). All the code above executed
; at the power-on-default 32KHz (LOSC) clock.
	ld	sp,X2000 ; setup stack
	ld	hl,X8100 ; src =  8100
	ld	de,X0400 ; dest = 0400
	ld	bc,X0e00 ; 3.5KB
	ldir    ; copy flash loader
	in	a,(4eh)
	or	8
	out	(4eh),a ; watchdog
	call	X0403   ; try loading BREC into IPMM
	and	a
	jp	nz,X8094 ; not successful, go ADFU
	in	a,(4eh)
	or	8
	out	(4eh),a ; watchdog
	ld	a,0f1h
	out	(5),a ; map in IPMM
	ld	sp,X7ff0 ; new stack (currently in IPMM)
	ld	hl,X4000 ; loaded BREC starts here
	ld	de,X0000 ; down to 0
	ld	bc,X3fc0 ; 16K-64 bytes
	ldir    ; copy BREC
	jp	X0000 ; go to it
; enter ADFU mode
X8094:	in	a,(4eh)
	or	8
	out	(4eh),a ; watchdog
	ld	hl,X9d00 ; location of ADFU code
	ld	de,X0000
	ld	bc,X0c00 ; 3KB
	ldir    ; copy ADFU server
	ld	sp,X0100 ; new stack
	xor	a
	out	(27h),a ; disable all interrupts
	jp	X0000 ; execute ADFU
; ----
org 8100h
; here is the flash loader proper, designed to be run from 0400
; ...
; ----
org 9d00h
; here is the ADFU server proper, designed to be run from 0000
; ...
; ----


This portion is responsible for loading the first 16K of the flash, which contains the BREC, into memory. The code provides an operational example of how to use the flash controller and is relatively simple (compared to that in the BREC). It can be analogized with the loader in the PC's BIOS, i.e. its only function is to load the initial bootstrap code from mass storage and execute it. However, because of the subtle differences in NAND organization, it is comparably more complex.

The ROM portion loads FLASHLDR into ZRAM starting at 0400. It is 3.5KB in length, occupying the area from 0400 to 11FF.

See FLASHLDR for more information.


Named hard ADFU because its code is stored in ROM, unlike soft ADFU (ADFU.AP) which is invoked from within ACTOS to do firmware upgrade. Hard ADFU mode is likely how manufacturers initially load the firmware onto the device, and is a "last resort" fallback to recover a bricked device; since the code is stored in (presumably) ROM, unless the hardware is damaged hard ADFU mode will always succeed.

The ROM portion loads HARDADFU into ZRAM starting at 0000. It is 3KB in length, occupying the area from 0000 to 0BFF.

See HARDADFU for more information.

Related Pages

  • BROM, the physical memory holding the 1st-stage bootloader
  • NAND, the physical memory holding the 2nd-stage bootloader
  • BREC, the 2nd-stage bootloader code
  • TROM, ??