ircjunk/mini210 hacks

Back to dir listing...

13.07.2023

There was someone on allegrolokalnie who had two of these mini210 for 25zł each. I bought two of them and will be playing with linux. They run S5PV210 CPUs, which are based on an ARM Cortex A8 core (ARMv7-A architecture)

Resources for later:

U-Boot forks

Others

Manufacutrer's distribution DVD downloaded from their onedrive via here

Support is in mainline kernel: mach-s5pv210

Vendor compiler from the DVD: arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz. Alas no u-boot source code or bootloader. Or I have not found it yet. [26.07.23] [30.07.23 note: Manufacturer uses Superboot and provides a binary file that seems to work]

26.07.23

There is GCC4 in manufacturer's DVD A. There is no bootloader there. The manufacturer's DVD has baremetal examples. They are even compiled too.

I've translated the document here and started the precompiled 1.leds_s example. It indeed does run.

Steps to reproduce

cd FriendlyARM-210-DVD-A/No OS(裸机程序)/bin/1.leds_s
sudo dd if=210.bin of=/dev/sdb seek=1
[sudo] hasło użytkownika poplar: 
32+0 przeczytanych rekordów
32+0 zapisanych rekordów
skopiowane 16384 bajtów (16 kB, 16 KiB), 0,0193907 s, 845 kB/s

After inserting the card into the SD slot, flipping the switch S2 to "SDBOOT" position and booting the board, the 4 leds flash.

I have then verified that the bundled GCC can reproduce the same effect:

poplar@poplar:~/prog/mini210/FriendlyARM-210-DVD-A/No OS(裸机程序)/src$ cp -r 1.leds_s/ ../../../
poplar@poplar:~/prog/mini210/1.leds_s$ export PATH=/opt/FriendlyARM/toolschain/4.5.1/bin/:$PATH
poplar@poplar:~/prog/mini210/1.leds_s$ make
arm-linux-gcc -o start.o start.S -c
arm-linux-ld -Ttext 0x0 -o led.elf start.o
arm-linux-objcopy -O binary led.elf led.bin
arm-linux-objdump -D led.elf > led_elf.dis
gcc mkv210_image.c -o mkmini210
./mkmini210 led.bin 210.bin
poplar@poplar:~/prog/mini210/1.leds_s$

Blast it onto the SD card:

poplar@poplar:~/prog/mini210/1.leds_s$ sudo dd if=210.bin of=/dev/sdb seek=1
32+0 przeczytanych rekordów
32+0 zapisanych rekordów
skopiowane 16384 bajtów (16 kB, 16 KiB), 0,0291652 s, 562 kB/s

After I put the card in the board the leds example booted up just like the precompiled one. Good!

Further examples use BL1.bin and BL2.bin which are presumably first and second stage bootloaders:

Compared with the code in the previous chapter, the code in this chapter has been greatly modified. First, the whole project is divided into two directories: BL1 and BL2. The code under the directory BL1 will be compiled and linked into a file named BL1.bin, and the code under the directory BL2 will be compiled and linked into a file named BL2.bin. . Among them, the link address of the BL1.bin file is 0 (the position-independent code is used, and the program can run in any available memory), and the link address of the BL2.bin file is 0x23E00000 (the position-independent code is not used, all programs must be at that address to function properly). BL1.bin needs to be programmed to sector 1 of the sd card, and BL2.bin needs to be programmed to sector 49 of the sd card. The reason for this programming will be given in the following program explanation. The complete For the programming process, please refer to the programming steps in Section 4 of this chapter. The running process of the whole program is roughly as follows: after the system is powered on, first copy the BL1. Copy BL2.bin at sector 49 in the sd card to address 0x23E00000 of DRAM, and finally jump to this address to continue running.

From the translated document, page 29. BL1 is PIC code for initializing DRAM. BL2 is the second stage bootloader.

26.07.23, documentation and net smurfing

Some kernel: android_kernel210 and uboot from the same user uboot_smdk210 (readme dated 2008)

AliExpress listing that comes with a CD with uboot sources: OK210 -> Leads to forum with CD download link. Translated download links

OK210 development board users close disk A link:
http://pan.baidu.com/s/1sjC3Y5B password: neqt
OK210 Development Board User CD B Link:
http://pan.baidu.com/s/1bn2NfjT Password: 1s1w
OK210 Development Board User CD C Link:
http://pan.baidu.com/s/1pJqnzvl Password: mryy

TODO: download via the usual baidu service

Superboot, the vendor bootloader, is described here. \镁光NANDFlash的更新说明.pdf describes how to use Superboot to boot a zImage+rootfs. superboot210.bin can be found in the main directory of the B DVD. B directory contains ready made Linux, Android and WinCE images with Superboot config.

It appears here that uboot is able to create the bl1 file and is merged into mainline.

Uboot could likely be booted as BL2. The samsung iROM boot note talks about how to do it... The linked BL1 copies the U-boot from nand to dram and then just jumps to it: like this

#define UBOOT_PHY_BASE      0x23E00000 /* For V210 */
void(*run_uboot)(void) = UBOOT_PHY_BASE;

30.07.23, u-boot build attempts

Blew dvbd/images/Superboot210.bin to sector 1+ of the sd card, no signs of life. Boot error code: 60%, 50%, 10% (SDMMC checksum error, SDMMC error, UART boot error)

Blew dvdb/images/Linux/rootfs_mini210_256m.img to sector 1+ of the sd card.. XPWMOUT0 was 60% high for a while

`XPWMOUT0` is available on R194 and Q3, it is driving the beeper via Q3. The application note lists the PWM duty cycle relating to error codes:

pwm error codes

60% duty cycle means SDMMC boot checksum error.

I have made a mistake and confused skip= and seek= options of dd.

After blowing Superboot210.bin to the SD card:

sudo dd if=Superboot210.bin of=/dev/sdb seek=1

I am greeted by the bootloader:

Booting from SD
ERROR: Media attach failed
ACTION AND OS must be defined

Let's try to build one of the u-boot's. I will go with gotobootloader/u-boot-s5pv210 because I already have it downloaded. Now that I have a working toolchain gcc4 it should build OK.

$ make qt210_config CC=arm-linux-gcc
Generating include/autoconf.mk
cc1: error: unrecognized command line option "-fstack-usage"
Generating include/autoconf.mk.dep
cc1: error: unrecognized command line option "-fstack-usage"
Configuring for qt210 board...
$ make CC=arm-linux-gcc
                            fails...

Stuck on what seems to be ld bug.

Trying the sourcelink repo SourceLink/S5PV210. Untar'd 14-uboot/u-boot-2016.11-6.tar.gz which is a bzip2 archive.

$ make smdkv210_defconfig CC=arm-none-linux-gnueabi-gcc LD=arm-none-linux-gnueabi-ld
#
# configuration written to .config
#
poplar@poplar:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11$ make menuconfig
scripts/kconfig/mconf  Kconfig
configuration written to .config

*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.
poplar@poplar:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11$ make smdkv210_defconfig CC=arm-none-linux-gnueabi-gcc LD=arm-none-linux-gnueabi-ld
poplar@poplar:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11$ make CC=arm-none-linux-gnueabi-gcc LD=arm-none-linux-gnueabi-ld
[ ... snip ...]
  LD      spl/dts/built-in.o
  LD      spl/fs/built-in.o
  LDS     spl/u-boot-spl.lds
  LD      spl/u-boot-spl
  OBJCOPY spl/u-boot-spl-nodtb.bin
  COPY    spl/u-boot-spl.bin
./tools/mksource210spl  spl/u-boot-spl.bin spl/smdkv210-spl.bin
cp ./spl/smdkv210-spl.bin ./tmp.bin
truncate ./tmp.bin -c -s 16K
cat ./u-boot.bin >> ./tmp.bin
mv ./tmp.bin ./u-boot-all.bin
cp ./u-boot-all.bin /work/nfs_root
cp: nie można utworzyć zwykłego pliku '/work/nfs_root': Nie ma takiego pliku ani katalogu
make: *** [Makefile:838: combine] Błąd 1
poplar@poplar:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11$ ls
api        doc       lib          snapshot.commit  u-boot.cfg
arch       drivers   Licenses     spl              u-boot-dtb.bin
board      dts       MAINTAINERS  System.map       u-boot.lds
cmd        examples  Makefile     test             u-boot.map
common     fs        net          tools            u-boot-nodtb.bin
config.mk  include   post         u-boot           u-boot.srec
configs    Kbuild    README       u-boot-all.bin   u-boot.sym
disk       Kconfig   scripts      u-boot.bin
poplar@poplar:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11$ file u-boot
u-boot: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /usr/lib/ld.so.1, with debug_info, not stripped
poplar@poplar:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11$ file u-boot.bin 
u-boot.bin: data

u-boot.bin is just the uboot. u-boot-all.bin is BL1 + uboot, ready to be blown to SD card.

However this fork is explicitly said in the readme to not support sd/mmc boot.

Exynos4-sdk uboot fork. This seems to be older and it will likely need the same sha1 fix and the other fixes like the gotobootloader/u-boot-s5pv210. It might crash ld as well.

Building: make CC=arm-none-linux-gnueabi-gcc LD=arm-none-linux-gnueabi-ld CROSS_COMPILE=/opt/FriendlyARM/toolschain/4.5.1/bin/arm-none-linux-gnueabi-

This has built a u-boot.bin which needs the SPL.. i will try to merge it with exising SPL-equipped image. That is, u-boot-all.bin from the previous source tree written to sd-card and then u-boot.bin from this one written at file offset 0x4000+1sector.

poplar@poplar:~/prog/mini210/exynos4/uboot-master$ cp ../../S5PV210-master/14-uboot/u-boot-2016.11/spl/smdkv210-spl.bin .
poplar@poplar:~/prog/mini210/exynos4/uboot-master$ truncate smdkv210-spl.bin -c -s 16K
poplar@poplar:~/prog/mini210/exynos4/uboot-master$ cp smdkv210-spl.bin u-boot-all.bin
$ cat u-boot.bin >> u-boot-all.bin 
poplar@poplar:~/prog/mini210/exynos4/uboot-master$ sudo dd if=u-boot-all.bin of=/dev/sdb seek=1
[sudo] hasło użytkownika poplar: 
572+1 przeczytanych rekordów
572+1 zapisanych rekordów
skopiowane 293236 bajtów (293 kB, 286 KiB), 0,175408 s, 1,7 MB/s
poplar@poplar:~/prog/mini210/exynos4/uboot-master$

Im getting a weird error. I don't know what it is because I dont have JTAG on this. I feel like this u-boot does not support SPL booting like that.

Perhaps I can boot that u-boot which does not support sd/mmc (SourceLink) with Superboot and then use that for booting Linux?

07.09.2023

I found this PDF which mentions S5PV210 CPU as supported. It seems to be a manual for some debugger. I only skimmed it with ^F but it is a lead. debugger_arm.pdf

23:19 < polprog> hi, ive got a board with an arm cortex a8 (s5pv210) and id like to use opencd with it.. it autodetects one 
         tap but im not sure what kind of tap is it
23:19 < polprog> Info : JTAG tap: s5pv210.tap tap/device found: 0x1ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x1)
23:20 < polprog> I'm looking at files for ti omap in a BeagleBone and it has three taps, one of them is the DAP used for 
         debugging
23:20 < polprog> what do i need to know to get access to the DAP?
23:21 < PaulFertser> polprog: TI parts are known to lack DAP info ROM tables so you need to manually provide debug base etc, 
             you should be able to find them in the datasheet/reference manual.
23:22 < PaulFertser> polprog: probably you can find config files for some other jtag software and infer needed values from it.
23:25 < polprog> allright, and then based on that I define the taps in my config file for this cpu?
23:25 < polprog> (its the only device in the chain)
23:26 < PaulFertser> polprog: you likely have just one JTAG tap (according to results of autodetection) and then this TAP is 
             used as a transport for ARM debug protocols, so you define a DAP on top of it, and then a target CPU on 
             top of DAP.
23:28 < polprog> got it, thanks!
23:28 < polprog> ill ask questions when i find how some other debugger does it with this cpu
23:29 < PaulFertser> polprog: you can probably just experiment based on data used for similar targets
23:31 < polprog> thats my approach too but the only similar thing i see is samsung_s3*.cfg
23:31 < polprog> ill take a look at these files
23:33 < polprog> these are 920t or 7tdmi or 11 cores
23:34 < polprog> s3c4510.cfg looks the most similar, its arm7tdmi
23:34 < PaulFertser> polprog: just try minimal config. This part might have proper DAP ROM table so might be able to 
                     autodetect dbgbase.
23:34 < PaulFertser> polprog: try defining dap on top of this tap and then cortex_a target.
23:35 < PaulFertser> polprog: like imx51.cfg but without other taps
23:37 < polprog> Info : s5pv210.cpu: hardware has 6 breakpoints, 2 watchpoints
23:38 < polprog> is this from the config or from the DAP ROM?
23:41 < PaulFertser> polprog: very good
23:41 < PaulFertser> polprog: that's from examination of the debug unit that was connected to thanks to info from DAP tables.
23:41 < polprog> i got the romtable under 'dap info'
23:41 < polprog> fantastic

That's correct. Thanks to PaulFerster's suggestion to use the imx51 config i made this .cfg file which eventually gets me access to the memory and registers via gdb.

This is the s5pv210.cfg config file:

if { [info exists CHIPNAME] } {
   set _CHIPNAME $CHIPNAME
} else {
   set _CHIPNAME s5pv210
}

# CoreSight Debug Access Port
if { [info exists DAP_TAPID] } {
   set _DAP_TAPID $DAP_TAPID
} else {
   set _DAP_TAPID 0x1ba00477
}

jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf \
        -expected-id $_DAP_TAPID



set _TARGETNAME $_CHIPNAME.cpu
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu

target create $_TARGETNAME cortex_a -dap $_CHIPNAME.dap

And this is how I call oocd:

openocd -f /usr/share/openocd/scripts/interface/jlink.cfg \
-f s5pv210.cfg \
-c "transport select jtag" \
-c "adapter speed 10" \
-c "init" \
-c "scan_chain"


$ ./oocd.sh 
Open On-Chip Debugger 0.11.0-rc2
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Warn : Transport "jtag" was already selected
jtag
adapter speed: 10 kHz

Info : J-Link ARM V8 compiled Dec  1 2009 11:42:48
Info : Hardware version: 8.00
Info : VTarget = 3.319 V
Info : clock speed 10 kHz
Info : JTAG tap: s5pv210.cpu tap/device found: 0x1ba00477 (mfg: 0x23b (ARM Ltd), part: 0xba00, ver: 0x1)
Info : s5pv210.cpu: hardware has 6 breakpoints, 2 watchpoints
Info : starting gdb server for s5pv210.cpu on 3333
Info : Listening on port 3333 for gdb connections
   TapName             Enabled  IdCode     Expected   IrLen IrCap IrMask
-- ------------------- -------- ---------- ---------- ----- ----- ------
 0 s5pv210.cpu            Y     0x1ba00477 0x1ba00477     4 0x01  0x0f

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

Now I can use gdb-multiarch to connect to the CPU:

(gdb) tar ext :3333
Remote debugging using :3333
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
0xc017d14c in ?? ()
(gdb) x/16i $pc
=> 0xc017d14c:  mov pc, lr
   0xc017d150:  mrc 15, 0, r3, cr0, cr0, {1}
   0xc017d154:  lsr r3, r3, #16
   0xc017d158:  and r3, r3, #15
   0xc017d15c:  mov r2, #4
   0xc017d160:  lsl r2, r2, r3
   0xc017d164:  mcr 15, 0, r0, cr7, cr10, {1}
   0xc017d168:  add r0, r0, r2
   0xc017d16c:  subs    r1, r1, r2
   0xc017d170:  bhi 0xc017d164
   0xc017d174:  dsb sy
   0xc017d178:  mov pc, lr
   0xc017d17c:  mov r2, #0
   0xc017d180:  ldr r1, [r1, #368]  ; 0x170
   0xc017d184:  orr r0, r0, #89 ; 0x59
   0xc017d188:  mcr 15, 0, r2, cr13, cr0, {1}
(gdb)

Fuck yeah

Fuck yeah

SoC user manual is in dvda/Datasheet/S5PV210_UM_REV1.1.pdf

08.09.23

I've assembed an adapter from the serial port header to hook up the ft4232hl board. I'm testing the exynos u-boot fork. With gdb working i can examine where the board gets stuck.

Exynos U-boot debugging

Reaching nowhere and with little debug capabilities I decided to check the whole chain.

The BL1 from the card that I am using, smdkv210-spl.bin loads the code from SD card sector 49 onwards to address 0x2000_2200. I tested this by creating a file inf_loop.bin that contains 4 bytes, fe ff ff eb (bl 0), and burned the BL1 file to sector 1 onwards and the inf_loop file to sector 49. The debugger shows that the code is stuck at address 0x2000_2200. And the memory contents match. This also shows that this particular BL1 does not validate check sums.

08.09.23, 23:59

I've hacked up a new board config in the exynos4 uboot tree. The new board is called mini210 and the most important part is in board/samsung/mini210/config.mk:

CONFIG_SYS_TEXT_BASE = 0x20002200

This is where the BL1 will load the shit and jump to. This cause the board to emit "OK" from the lowlevel_init.S file.

sudo dd if=    of=/dev/sdb seek=1          # Blow bl1  - only once per card
sudo dd if=u-boot.bin of=/dev/sdb seek=49  # Blow u-boot
# Uboot can be built with `make mini210` provided that the path is set OK.

Immediately after that OK print it jumps to load_uboot which is a procedure later in the file. The procedure checks if the code needs to be relocated.

load_uboot:
    push {lr}

    /* when we already run in ram, we don't need to relocate U-Boot.
     * and actually, memory controller must be configured before U-Boot
     * is running in ram.
     */
    ldr r0, =0xff000fff
    bic r1, pc, r0      /* r0 <- current base addr of code */
    ldr r2, _TEXT_BASE      /* r1 <- original base addr in ram */
    bic r2, r2, r0      /* r0 <- current base addr of code */
    cmp     r1, r2                  /* compare r0, r1                  */
    beq     after_copy      /* r0 == r1 then skip flash copy   */

#if defined(CONFIG_EVT1)
    /* If BL1 was copied from SD/MMC CH2 */
    ldr r0, =0xD0037488
    ldr r1, [r0]
    ldr r2, =0xEB200000
    cmp r1, r2
    beq     mmcsd_boot
#endif

    ldr r0, =INF_REG_BASE
    ldr r1, [r0, #INF_REG3_OFFSET]
    cmp r1, #BOOT_NAND      /* 0x0 => boot device is nand */
    beq nand_boot
    cmp r1, #BOOT_ONENAND   /* 0x1 => boot device is onenand */
    beq onenand_boot
    cmp     r1, #BOOT_MMCSD
    beq     mmcsd_boot
    cmp     r1, #BOOT_EMMC
    beq     emmc_boot
    cmp     r1, #BOOT_NOR
    beq     nor_boot
    cmp     r1, #BOOT_SEC_DEV
    beq     mmcsd_boot

CONFIG_EVT1 is defined, so the ifdef is placed. 0xD0037488 is the address of the iROM variable V210_SDMMC_BASE, "Current boot channel." (from iROM app note. 0xEB2000000 is ELFIN_HSMMC_2_BASE (morons have that as a constant in arch/arm/include/asm/arch-s5pv210/cpu.h but had to put a magic number in there)

todo: examine what is 0xD0037488 for this board and which HSMMC it uses! Alternatively disable CONFIG_EVT1, i have no idea what it does.

todo: examine how to jump to uboot

Useful note: https://m2m-tele.com/blog/2021/10/24/u-boot-initialization-sequence/

10.09.23

Examining where the fault occurs. The current status is that the exynox u-boot fork, after my modifications, emits the OK prompt. Then the board gets into a fault state. Im unable to set breakpoints, but i can halt the board and single step instructions. I'm debugging it by regenerating u-boot versions with infinite loops where i want to put the breakpoint, recompile, flash to SD and then halt the board to examine register state.

Going after the inf loop when the debugger attaches can be done with resume address .

Currently trying to locate the fault. Is it in load_uboot?

   0x200028d0 <load_uboot>:     stmfd   sp!, {lr}
   0x200028d4 <dbgloop>:        bl      0x200028d4 <dbgloop>
   0x200028d8 <dbgloop+4>:      ldr     r0, [pc, #792]  ; 0x20002bf8 <phy_last_jump+60>
   0x200028dc <dbgloop+8>:      bic     r1, pc, r0
   0x200028e0 <dbgloop+12>:     ldr     r2, [pc, #-648] ; 0x20002660 <_TEXT_BASE>
   0x200028e4 <dbgloop+16>:     bic     r2, r2, r0
   0x200028e8 <dbgloop+20>:     cmp     r1, r2
=> 0x200028ec <dbgloop+24>:     beq     0x2000295c <after_copy>

s5pv210.cpu rev 2, partnum c08, arch f, variant 2, implementor 41
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x600001d3 pc: 0x200028e8
MMU: disabled, D-Cache: disabled, I-Cache: enabled
> reg r2
r2 (/32): 0x00002000

> reg r1
r1 (/32): 0x00002000

>

r1 == r2, so beq will be taken. We go to after_copy

0x2000295c <after_copy>:     ldmfd   sp!, {pc}

ldmfd loads a previous pc from stack and rolls sp back to where it was. next pc value is 0x20002860 - we are back to lowlevel_init:

0x20002860 <lowlevel_init+152>:      bl      0x20002b60 <enable_mmu>

entering procedure enable_mmu (..2b60)

(gdb) x/16i enable_mmu
   0x20002b60 <enable_mmu>:     ldr     r5, [pc, #268]  ; 0x20002c74 <phy_last_jump+184>
   0x20002b64 <enable_mmu+4>:   mcr     15, 0, r5, cr3, cr0, {0}
   0x20002b68 <enable_mmu+8>:   ldr     r0, [pc, #264]  ; 0x20002c78 <phy_last_jump+188>
   0x20002b6c <enable_mmu+12>:  ldr     r1, [pc, #264]  ; 0x20002c7c <phy_last_jump+192>
   0x20002b70 <enable_mmu+16>:  ldr     r2, [pc, #264]  ; 0x20002c80 <phy_last_jump+196>
   0x20002b74 <enable_mmu+20>:  bic     r0, r0, r2
   0x20002b78 <enable_mmu+24>:  orr     r1, r0, r1
   0x20002b7c <enable_mmu+28>:  mcr     15, 0, r1, cr2, cr0, {0}   ;; __ allright up to here! __
   0x20002b80 <mmu_on>:         mrc     15, 0, r0, cr1, cr0, {0}
   0x20002b84 <mmu_on+4>:       orr     r0, r0, #1
   0x20002b88 <mmu_on+8>:       mcr     15, 0, r0, cr1, cr0, {0}   ;; Fault emitted here, or is it? The CPU is in ARM state.
   0x20002b8c <mmu_on+12>:      nop     {0}
   0x20002b90 <mmu_on+16>:      nop     {0}
   0x20002b94 <mmu_on+20>:      nop     {0}
   0x20002b98 <mmu_on+24>:      nop     {0}
   0x20002b9c <mmu_on+28>:      mov     pc, lr

So the u-boot early init code crashes on writing back to coprocessor when enabling MMU. In ARM state the pc is the value of the current instruction address +8 (so, 2 insns ahead). This means the fault is tripped at the mrc instruction at 20002b80.

side quest: in this state it is possible to read the memory at 0x0000_0000 which is the iROM. Can we dump it?

21.09.23

Setting up the tree on Almiraj - i've installed the toolchain compiler arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz on almiraj and copied the mini210/ tree to it.

Unformtunately after a make clean the build did not succeed.

I had to fix the following things:

Apparently

find . -iname Makefile -exec touch \{\} \;

has fixed that and similar errors ... do the makefiles need to be fucking newer for make to actually read them?

After this, the exynos4/u-boot-master tree built correctly.

In the evening I tried to get the reset working, alas no dice.

What works is to halt the target and resume <addr>, so my infinite loop at uboot start must be left there for now.

I managed to dump iROM. It's 64kB. Attempting to read over 0x0001_0000 results in a data abort.

> dump_image irom.bin 0x0000000 0x10000
dumped 65536 bytes in 3.987809s (16.049 KiB/s)
> dump_image irom1m.bin 0x0000000 0x100000
data abort at 0x00010000, dfsr = 0x00000008

> dump_image irom.bin 0x0000000 0x10010   
data abort at 0x00010000, dfsr = 0x00000008

>

iROM is also mapped from 0xD000_0000 upwards - lets see if we get the same 64kB and then error

> dump_image irom.bin 0xD0000000 0x10010
data abort at 0xd0010000, dfsr = 0x00000008

>

All files have the same sha1sum.

$ sha1sum irom*
1dc4afa153b0d03094c95f7762714d54af0b25c8  irom0000.bin
1dc4afa153b0d03094c95f7762714d54af0b25c8  irom1m.bin
1dc4afa153b0d03094c95f7762714d54af0b25c8  irom.bin

    ┌─< 0x00000000      2a0000ea       b 0xb0
        0x000000b0      c8009fe5       ldr r0, [0x00000180]        ; [0x180:4]=0
        0x000000b4      100f0cee       mcr p15, 0, r0, c12, c0, 0
        0x000000b8      0000e0e3       mvn r0, 0
        0x000000bc      500f01ee       mcr p15, 0, r0, c1, c0, 2
        0x000000c0      0101a0e3       mov r0, 0x40000000
        0x000000c4      100ae8ee       vmsr fpexc, r0
        0x000000c8      b4009fe5       ldr r0, [0x00000184]        ; [0x184:4]=0xe2700000
        0x000000cc      0010a0e3       mov r1, 0
        0x000000d0      001080e5       str r1, [r0]
        0x000000d4      100f11ee       mrc p15, 0, r0, c1, c0, 0
        0x000000d8      010a80e3       orr r0, r0, 0x1000
        0x000000dc      100f01ee       mcr p15, 0, r0, c1, c0, 0
        0x000000e0      a0009fe5       ldr r0, [0x00000188]        ; [0x188:4]=0xd0020010
        0x000000e4      a0209fe5       ldr r2, [0x0000018c]        ; [0x18c:4]=0xe010a000
        0x000000e8      001092e5       ldr r1, [r2]
        0x000000ec      9c209fe5       ldr r2, [0x00000190]        ; [0x190:4]=0xe010c020
        0x000000f0      003092e5       ldr r3, [r2]
        0x000000f4      98209fe5       ldr r2, [0x00000194]        ; [0x194:4]=0xe010c034
        0x000000f8      004092e5       ldr r4, [r2]
        0x000000fc      020711e3       tst r1, 0x80000
        0x00000100      00f0a011       movne pc, r0

They contain valid and sensible arm-thumb instructions. Some strings:

0x00000458 Insert an OTG cable into the connector!
0x00007ffc Nor Check Sum Error
0x00008014 Uart negotiation Error
0x00008030 Uart Check Sum Error
0x00008048 Uart Data Length Over
0x00008060 Nand RnB Detect Error
0x00008078 Nand ECC Error
0x0000808c Nand Check Sum Error
0x000080a4 OND Check Sum Error
0x000080bc NO Boot Image
0x000080cc SD Init Error
0x000080dc SD checksum Error
0x000080f0 Secure Fail Error
0x00008338 eSSD Init Error
0x0000834c Enumeration TimeOut Error
0x00008368 No input Clock Error
0x00008380 Non Device Mode Error
0x00008398 eSSD Check Sum Error

0x0000c820  0403 0904 1603 5300 7900 7300 7400 6500  ......S.y.s.t.e.
0x0000c830  6d00 2000 4d00 4300 5500 2a03 5300 4500  m. .M.C.U.*.S.E.
0x0000c840  4300 2000 5300 3500 5000 4300 3100 3100  C. .S.5.P.C.1.1.
0x0000c850  3000 2000 5400 6500 7300 7400 2000 4200  0. .T.e.s.t. .B.
0x0000c860  2f00 4400 4600 0000 3200 0000 1e00 0000  /.D.F...2.......

22.09.23, 23.09.23

I've imported the currently used BL1 to ghidra. It's quite small. The first thing it does is setting up the MMU. Ghidra decodes ARM Cortex coprocessor acccess nicely. It has some issues with decoding the first few instructions, that radare does not have.

The core implements ARMv7-A architecture, therefore we are using the VMSA memory architecture: Reference manual.

                         LAB_00000070                                    XREF[1]:     00000010(j)  
    00000070 12 00 00 ea     b          LAB_000000c0
                         LAB_000000c0                                    XREF[1]:     00000070(j)  
    000000c0 eb ff ff ea     b          FUN_00000074
                         **************************************************************
                         *                                                            *
                         *  FUNCTION                                                  *
                         **************************************************************
                         undefined FUN_00000074()
                           assume LRset = 0x0
                           assume TMode = 0x0
         undefined         r0:1           <RETURN>
                         FUN_00000074                                    XREF[1]:     FUN_00000050:000000c0(c)  
    00000074 00 00 0f e1     mrs        r0,cpsr                          @ r0 <- current program state register
    00000078 1f 10 00 e2     and        r1,r0,#0x1f                      @ r1 <- CPSR & 0x1f ; r1 = operating mode
    0000007c 1a 00 31 e3     teq        r1,#0x1a                         @ r1 ?= 0x1a        ; operating mode 1A = hypervisor
    00000080 1f 00 c0 13     bicne      r0,r0,#0x1f                      @ if ne, r0 <- r0 & ~0x1f ; clear mode
    00000084 13 00 80 13     orrne      r0,r0,#0x13                      @ if ne, r0 <- r0 |  0x13 ; set mode 13 = supervisor
    00000088 c0 00 80 e3     orr        r0,r0,#0xc0                      @ r0 <- r0 | 0xc0         ; set mask F,I = mark IRQ, FIQ
    0000008c 00 f0 29 e1     msr        cpsr_cf,r0                       @ CSPR <- r0        ; set new CSPR
             @ This code above disables FIQ and IRQ. If the CPU is not n hypervisor mode, sets supervisor mode.

             @ MMU setup
             @ P15 registers are desribed in reference manual section B3.17
             @   MRC:    Cop to ARM,    MCR: ARM to COP
             @   mcr/mrc   <coproc>, {#}<opc1>, <Rt>, <CRn>, <CRm>{, {#}<opc2>}
             @             p15          0x00     --   cr1     cr0    0x00       SCTRL, System Control Register
             @             p15          0x00     --   cr12    cr0    0x00       VBAR,  Vector Base Addres Register
             @             p15          0x00     --   cr7     cr5    0x00       ICIALLU, Invalidate all instruction caches to PoU
             @             p15          0x00     --   cr7     cr10   0x04       CP15DMB, Data Memory Barrier operation
             @             p15          0x00     --   cr7     cr5    0x04       CP15ISB, Instruction Synchronization Barrier operation

    00000090 10 0f 11 ee     mrc        p15,0x0,r0,cr1,cr0,0x0    @ r0 <- SCTRL
    00000094 02 0a c0 e3     bic        r0,r0,#0x2000             @ r0 <- r0 & ~0x02000
    00000098 10 0f 01 ee     mcr        p15,0x0,r0,cr1,cr0,0x0    @ SCTLR <- r0 ; Unset bit 13: Low exception vectors, base address 0x00000000, remapable
    0000009c 78 00 9f e5     ldr        r0,[DAT_0000011c]         @ r0 <- u32 (0x11c)
    000000a0 10 0f 0c ee     mcr        p15,0x0,r0,cr12,cr0,0x0   @ VBAR <- DAT_0000011c; Load address of vector base addr reg; Remap vectors
    000000a4 06 00 00 eb     bl         FUN_000000c4                                     undefined FUN_000000c4()
    000000a8 1a 00 00 eb     bl         thunk_FUN_00000128                               undefined thunk_FUN_00000128()
    000000ac 1b 00 00 eb     bl         FUN_00000120                                     undefined FUN_00000120()
    000000b0 15 0f 07 ee     mcr        p15,0x0,r0,cr7,cr5,0x0    @ ICIALLU  ; synchronize
    000000b4 9a 0f 07 ee     mcr        p15,0x0,r0,cr7,cr10,0x4   @ CP15DMB  ; data memory barrier
    000000b8 95 0f 07 ee     mcr        p15,0x0,r0,cr7,cr5,0x4    @ CP15ISB  ; instruction sync barrier
    000000bc 1e ff 2f e1     bx         lr                        @ jump to lr.


void FUN_00000074(void){
  uint uVar1;
  undefined4 uVar2;
  undefined4 in_cr0;
  undefined4 in_cr12;

  uVar1 = coproc_movefrom_Control();                        // Disable fiq, irq. Set supervisor mode if not hypervisor
  coproc_moveto_Control(uVar1 & 0xffffdfff);                // 
  coprocessor_moveto(0xf,0,0,DAT_0000011c,in_cr12,in_cr0);  // Remap vectors 
  FUN_000000c4(DAT_0000011c);               // validate decompiler
  thunk_FUN_00000128();                     //  ..
  uVar2 = FUN_00000120();                   //  ..
  coproc_moveto_Invalidate_Entire_Instruction(uVar2);  //see disasm above
  coproc_moveto_Data_Synchronization(uVar2);
  coproc_moveto_Flush_Prefetch_Buffer(uVar2);
  return;
}

I will decode what the three functions called inside do later.

I just realized that the SPL i took is actually built from the code in the other uboot tree, so I should build that uboot, since I confirmed the SPL is working. There is no point in trying to adjust the exynos fork to use the other fork's SPL.

The SPL was taken from the S5PV210-master/14-uboot/u-boot-2016.11/ tree.

[2116][polprog@almiraj:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11]$ export PATH=/opt/FriendlyARM/toolschain/4.5.1/bin/:$PATH
[2117][polprog@almiraj:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11]$ make smdkv210_defconfig CC=arm-none-linux-gnueabi-gcc LD=arm-none-linux-gnueabi-ld
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
#
# configuration written to .config
#
[2117][polprog@almiraj:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11]$ make smdkv210_defconfig CC=arm-none-linux-gnueabi-gcc LD=arm-none-linux-gnueabi-ld
          [ ... snip ... ]
  CC      examples/standalone/hello_world.o
  LD      examples/standalone/hello_world
  OBJCOPY examples/standalone/hello_world.srec
  OBJCOPY examples/standalone/hello_world.bin
  LDS     u-boot.lds
  LD      u-boot
arm-none-linux-gnueabi-ld: warning: creating a DT_TEXTREL in object.
  OBJCOPY u-boot.srec
  OBJCOPY u-boot-nodtb.bin
./scripts/dtc-version.sh: linia 17: dtc: nie znaleziono polecenia
./scripts/dtc-version.sh: linia 18: dtc: nie znaleziono polecenia
*** Your dtc is too old, please upgrade to dtc 1.4 or newer
make: *** [Makefile:1396: checkdtc] Błąd 1
[2118][polprog@almiraj:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11]$ dtc
bash: dtc: nie znaleziono polecenia
[2119][polprog@almiraj:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11]$ sudo apt install device-tree-compiler
   [ went OK ]
[2117][polprog@almiraj:~/prog/mini210/S5PV210-master/14-uboot/u-boot-2016.11]$ make smdkv210_defconfig CC=arm-none-linux-gnueabi-gcc LD=arm-none-linux-gnueabi-ld
    [ ... snip ... ]
  CC      spl/board/samsung/smdkv210/smdkv210.o
  AS      spl/board/samsung/smdkv210/lowlevel_init.o
  LD      spl/board/samsung/smdkv210/built-in.o
  LD      spl/board/samsung/common/built-in.o
  CC      spl/common/init/board_init.o
  LD      spl/common/init/built-in.o
  LD      spl/drivers/built-in.o
  LD      spl/dts/built-in.o
  LD      spl/fs/built-in.o
  LDS     spl/u-boot-spl.lds
  LD      spl/u-boot-spl
  OBJCOPY spl/u-boot-spl-nodtb.bin
  COPY    spl/u-boot-spl.bin
./tools/mksource210spl  spl/u-boot-spl.bin spl/smdkv210-spl.bin
cp ./spl/smdkv210-spl.bin ./tmp.bin
truncate ./tmp.bin -c -s 16K
cat ./u-boot.bin >> ./tmp.bin
mv ./tmp.bin ./u-boot-all.bin
cp ./u-boot-all.bin /work/nfs_root
cp: nie można utworzyć zwykłego pliku '/work/nfs_root': Nie ma takiego pliku ani katalogu
make: *** [Makefile:838: combine] Błąd 1

The tree compiled okay - nfs_root error is due to some garbage hardcoded by sourcelink in the main Makefile (line 833)

Let's try to boot the created binary file and see where it stops using JTAG...

Similar to the exynos one, this u-boot outputs something on CON3 and then jumps into somewhere - halting it with jtag showed it happily executing instructions around 0x1d6a3ad8

0x1d6a3ad8 in ?? ()
(gdb) x/16i $px
Value can't be converted to integer.
(gdb) x/16i $pc
=> 0x1d6a3ad8:  andeq   r0, r0, r0
   0x1d6a3adc:  andeq   r0, r0, r0
   0x1d6a3ae0:  andeq   r0, r0, r0
   0x1d6a3ae4:  andeq   r0, r0, r0
   0x1d6a3ae8:  andeq   r0, r0, r0
   0x1d6a3aec:  andeq   r0, r0, r0
   0x1d6a3af0:  andeq   r0, r0, r0
   0x1d6a3af4:  andeq   r0, r0, r0
   0x1d6a3af8:  andeq   r0, r0, r0
   0x1d6a3afc:  andeq   r0, r0, r0
   0x1d6a3b00:  andeq   r0, r0, r0
   0x1d6a3b04:  andeq   r0, r0, r0
   0x1d6a3b08:  andeq   r0, r0, r0
   0x1d6a3b0c:  andeq   r0, r0, r0
   0x1d6a3b10:  andeq   r0, r0, r0
   0x1d6a3b14:  andeq   r0, r0, r0

After blowing u-boot-all.bin onto the sd card

$ sudo dd if=u-boot-all.bin of=/dev/sdd seek=1 status=progress

board emits something on CON3 (uart2), which seems to be configured as the console similar to the exynos fork. I cant get the baudrate right, likely because the configured clock speed is wrong, but this is very promising.

Having some issues with the new bootloader i placed a loop very early in the code (arch/arm/cpu/armv7/start.S:save_boot_params). The loop landed at u-boot.bin offset 0x350, u-boot-all.bin offset 0xc0, and CPU memory offset 0xd00200c0. This means that u-boot-all.bin is loaded into 0xd0020000. This is in IRAM, which makes sense, since iROM loads this from SD card. Now the loaded PIC code (SPL) has to load something from the SD card. Time to place another loop in the code that is in BL2.

u-boot boot sequence:

d0020000  b loc.reset                        start.S
d0020060  reset
d00200b0  save_boot_params (empty proc) 
d0020064  save_boot_params_ret
 * set supervisor mode *
d0020094  bl cpu_init_cp15 d00200b4
d0020098  bl cpu_init_crit
 d0020108  lowlevel_init                     cache_v7_asm.S
            clock_init      
            ddr_init
          bl _main
          bl copy_bl2_to_ram                 smdkv210.c    !!! plik C, ale nie mamy stosu!!!





0xd0020000      160000ea       b loc.reset                 ; cache.c:15 {    ; [01] -r-x section size 1768 named .text      
;-- reset
0xd0020060      120000ea       b sym.save_boot_params      ; start.S:40  b save_boot_params  
;-- save_boot_params
0xd00200b0      ebffffea       b loc.save_boot_params_ret  ; start.S:117  b save_boot_params_ret  @ back to my caller 
;-- save_boot_params_ret
    ;; Inicjalizacja - disables FIQ and IRQ. If the CPU is not n hypervisor mode, sets supervisor mode.
0xd0020094      060000eb       bl sym.cpu_init_cp15        ; start.S:82  bl cpu_init_cp15 ;[1]
0xd0020098      1a0000eb       bl sym.cpu_init_crit        ; start.S:84  bl cpu_init_crit ;[2]
  ;-- cpu_init_crit:   
  0xd0020108      040000ea       b loc.lowlevel_init         ; start.S:294  b lowlevel_init  @ go setup pll,mux,memory
  ;-- lowlevel_init:
  0xd0020120      0e90a0e1       mov sb, lr                  ; cache_v7_asm.S:138  bgt inval_levels
  0xd0020124      060000eb       bl sym.clock_init           ; cache_v7_asm.S:140  mov r10, #0    @ swith back to cache level 0 ;[2]
  0xd0020128      4c0000eb       bl sym.ddr_init             ; cache_v7_asm.S:141  mcr p15, 2, r10, c0, c0, 0  @ select current cache level in cssr ;[3]
  0xd002012c      08009fe5       ldr r0, [0xd002013c]        ; cache_v7_asm.S:142  dsb st    ; [0xd002013c:4]=0xe0200000
  0xd0020130      08109fe5       ldr r1, [0xd0020140]        ; cache_v7_asm.S:143  isb    ; [0xd0020140:4]=0x22222222
  0xd0020134      001080e5       str r1, [r0]                ; cache_v7_asm.S:144  bx lr
  0xd0020138      09f0a0e1       mov pc, sb                  ; cache_v7_asm.S:148  ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} )
0xd002009c      1b0000eb       bl sym._main                ; start.S:88  bl _main ;[3] 
  ;-- _main
  0xd0020118      2b0100eb       bl sym.copy_bl2_to_ram      ; cache_v7_asm.S:136  add r10, r10, #2   @ increment cache number ;[1]
  ;-- copy_bl2_to_ram:
  0xd00205cc      0e32a0e3       mov r3, 0xe0000000          ; smdkv210.c:227 }
  0xd00205d0      043093e5       ldr r3, [r3, 4]  
  0xd00205d4      73402de9       push {r0, r1, r4, r5, r6, lr} ; smdkv210.c:230 {

I've placed a while(1); at the beginning of copy_bl2_to_ram() (boards/samsung/smdkv210 )and checked that the CPU gets there. Now to see if it goes on.

ill stop here since this is a complicated procedure. perhaps I can make up some function that initializes UART based on that assembly which was printing OK in the exynos uboot and add some printf debugging because the JTAG is still fucked.

24.09.23

Bulding u-boot with verbose mode on (show compiler command lines): make V=1

I pasted uart_asm_init from exynos' forks's lowlevel_init.S (board/samsung/smdkv210/) into the S5PV210-master fork's lowlevel_init.S. Some defines needed to be fixed up, i did that.

There are two macros left, UART_UBRDIV_VAL and UART_UDIVSLOT_VAL. They are hardcoded in the exynos fork in include/configs/smdkv210.h. Ive gotta calculate their values for the 24MHz clock on the mini210.

The contents of the exynos values are controlled by the clock config:

#if defined(CONFIG_CLK_533_133_100_100)
#define UART_UBRDIV_VAL     26
#define UART_UDIVSLOT_VAL   0x0808
#else
#define UART_UBRDIV_VAL     34
#define UART_UDIVSLOT_VAL   0xDDDD
#endif

26.09.23

UART baud rate gen

The registers in lowlevel_init.S:uart_asm_init are being set as follows:

UFCON    =    0x0
UMCON    =    0x0
ULCON    =    0x3
UCON     = 0x03c5          -> UCONn[10] = 0b0: PCLK is the clock source
UBRDIV   = UART_UBRDIV_VAL
UDIVSLOT = UART_UDIVSLOT_VAL

What is PCLK? Seems to be some external clock. UART is in PSYS clock domain (Fig 3-1).

Lickily it's set in board/samsung/smdkv210/smdkv210.c:clock_init

The PSYS clock is set to MCLKPLL = FOUT_MPLL,
FOUT_MPLL = 667MHz (P = 12, M = 667, S = 1) in MPLL_CON0

FOUT = MDIV X FIN / (PDIV × 2^(SDIV-1) )

so for our case FOUT = 667 *FIN / 12 * 2^0, = FIN * 667/12 =~ 55.5833

PLL clock feeds are muxed between XXTI and XusbXTI, the mux is controlled by XOM[0] pin. XOM[0] = 0 -> PLLs fed from XXTI (Fig 3-3, page 361)

In our case XOM[0] = 0 according to schematic, and so it is on the PCB.

XXTI = 24MHz here, so this is the default, therefore MOUT_PSYS = 667MHz. What is the PCLK then? it's MOUT_PSYS *1/DIV_HCLKP * 1/DIV_HCLKP

And according to comments PCLK_PSYS = 66MHz just like the default

PCLK generation

What is the UART divider? page 879:

DIV_VAL = UBRDIVn + (num of 1's in UDIVSLOTn)/16
DIV_VAL = (PCLK / (bps x 16)) −1

So for 115200 bps we have to set DIV_VAL to 66e6 / (16*115200) -1 = 34.80 == 35

for UBRDIV = 34 and UDIVSLOT = 0xDDDD we get

DIV_VAL = 34 + 12/16 = 34.75, close enough. Within 1% actually.

So these are the values: UBRDIV = 34 and UDIVSLOT = 0xDDDD.

I've called uart_asm_init from inside lowlevel_init and the board prints the 'O'. I then print 'k' from the end of copy_bl2_to_ram:

    *((volatile int*)(S5PV210_UART_BASE + 0x20 )) = 0x6b6b6b6b; // print k on uart 0

UART Works

28.09.23

Now that UART works and so does copy_bl2_to_ram, we trace teh execution further. This is the end of SPL:

arch/arc/cpu/armv7/start.S: end of reset
-----------------------------------------------
        /* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl  cpu_init_cp15
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
    bl  cpu_init_crit
#endif
#endif

    bl  _main


arch/arm/lib/crt0.S:
----------------------------
ENTRY(_MAIN)

/* modied by Sourcelink */
#ifdef CONFIG_SPL_BUILD
    bl  copy_bl2_to_ram             /* 拷贝BL2到DDR */                /* Copy BL2 to DDR */
    ldr pc, =CONFIG_SYS_SDRAM_BASE  /* 跳转到DDR的起始地址执行BL2 */  /* Jump to the starting address of DDR to execute BL2 */
#else
    bl  board_init_f
#endif

ifdef tells us that we will come back here again in the second stage, where board_init_f will be called.

For reference, this is the part in r2. r2 -aarm -b32 -B0xd0020000 spl/u-boot-spl

;-- cpu_init_crit:                                                                                                           
        ┌─< 0xd0020108      020000ea       b loc.lowlevel_init         ; start.S:294  b lowlevel_init  @ go setup pll,mux,memory         
        │   0xd002010c      00000000       andeq r0, r0, r0            ; cache_v7_asm.S:132  bge inval_loop2                             
        │   ;-- _main:                                                                                                                   
        │   0xd0020110      450100eb       bl sym.copy_bl2_to_ram      ; start.S:294  b lowlevel_init  @ go setup pll,mux,memory ;[1]    
        │   0xd0020114      02f2a0e3       mov pc, 0x20000000          ; cache_v7_asm.S:134  bge inval_loop1                             
        │   ;-- lowlevel_init:                                                                                                           
        └─> 0xd0020118      0e90a0e1       mov sb, lr                  ; cache_v7_asm.S:136  add r10, r10, #2   @ increment cache number
            0xd002011c      200000eb       bl sym.clock_init           ; cache_v7_asm.S:137  cmp r3, r10 ;[2]                            
            0xd0020120      660000eb       bl sym.ddr_init             ; cache_v7_asm.S:138  bgt inval_levels ;[3]                       
            0xd0020124      030000eb       bl loc.uart_asm_init        ; cache_v7_asm.S:140  mov r10, #0    @ swith back to cache level 
            0xd0020128      58009fe5       ldr r0, [0xd0020188]        ; cache_v7_asm.S:141  mcr p15, 2, r10, c0, c0, 0  @ select curren
            0xd002012c      58109fe5       ldr r1, [0xd002018c]        ; cache_v7_asm.S:142  dsb st    ; [0xd002018c:4]=0x22222222       
            0xd0020130      001080e5       str r1, [r0]                ; cache_v7_asm.S:143  isb                                         
            0xd0020134      09f0a0e1       mov pc, sb                  ; cache_v7_asm.S:144  bx lr

I want to put a breakpoint here to check if the address actually contains runnable code. The jump is to CONFIG_SYS_SDRAM_BASE which is 0x2000_0000, and is where copy_bl2_to_ram jumps, and it's also the u-boot second stage (./u-boot ELF) text base, but I want to check it anyway.

I put the loop in crt0.S:

#ifdef CONFIG_SPL_BUILD
    bl  copy_bl2_to_ram /* 拷贝BL2到DDR */ /* Copy BL2 to DDR */
loop:   b loop    /* mod polprog */
    ldr pc, =CONFIG_SYS_SDRAM_BASE  /* 跳转到DDR的起始地址执行BL2 */ /* Jump to the starting address of DDR to execute BL2 */
#else
    bl  board_init_f
#endif



(gdb) tar ext :3333
Remote debugging using :3333
0xd0020124 in ?? ()
(gdb) x/8i $pc
=> 0xd0020124:  b   0xd0020124
   0xd0020128:  mov pc, #536870912  ; 0x20000000

The loop works. What is the memory at 0x2000_0000? It's empty:

(gdb) x/16i 0x20000000
   0x20000000:  andeq   r0, r0, r0
   0x20000004:  andeq   r0, r0, r0
   0x20000008:  andeq   r0, r0, r0
   0x2000000c:  andeq   r0, r0, r0
   0x20000010:  andeq   r0, r0, r0
   0x20000014:  andeq   r0, r0, r0
   0x20000018:  andeq   r0, r0, r0
   0x2000001c:  andeq   r0, r0, r0
   0x20000020:  andeq   r0, r0, r0
   0x20000024:  andeq   r0, r0, r0
   0x20000028:  andeq   r0, r0, r0
   0x2000002c:  andeq   r0, r0, r0
   0x20000030:  andeq   r0, r0, r0
   0x20000034:  andeq   r0, r0, r0
   0x20000038:  andeq   r0, r0, r0
   0x2000003c:  andeq   r0, r0, r0

Just to make sure I'll dump with oocd...

> halt
MPIDR not in multiprocessor format
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x200001d3 pc: 0xd0020124
MMU: disabled, D-Cache: disabled, I-Cache: enabled
> mdw phys 0x20000000 64
0x20000000: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000040: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000080: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x200000a0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x200000c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x200000e0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Similarly it's full of zeros. But writing to it seems to work

> mww phys 0x20000000 0xebfffffe 1
> mdw phys 0x20000000 64          
0x20000000: ebfffffe 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000040: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x20000080: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x200000a0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x200000c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x200000e0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

And after restarting gdb for good measure I can read out the instruction

(gdb) x/4i 0x20000000
   0x20000000:  bl  0x20000000
   0x20000004:  andeq   r0, r0, r0
   0x20000008:  andeq   r0, r0, r0
   0x2000000c:  andeq   r0, r0, r0

The chip can execute from ram correctly, which means the RAM works:

> resume 0x20000000
> halt
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x200001d3 pc: 0x20000000
MMU: disabled, D-Cache: disabled, I-Cache: enabled

There must be an issue with the BL2 copy routine then. I should debug that.

I decided to try and load the second stage via jtag.

> halt
MPIDR not in multiprocessor format
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x200001d3 pc: 0xd0020124
MMU: disabled, D-Cache: disabled, I-Cache: enabled
> load_image u-boot-2016.11/u-boot.bin 0x20000000 bin
299548 bytes written at address 0x20000000
downloaded 299548 bytes in 110.032898s (2.659 KiB/s)
> mdw phys 0x20000000 32                             
0x20000000: ea0000be e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 
0x20000020: 20000060 200000c0 20000120 20000180 200001e0 20000240 200002a0 deadbeef 
0x20000040: 0badc0de e320f000 e320f000 e320f000 e320f000 e320f000 e320f000 e320f000 
0x20000060: e51fd028 e58de000 e14fe000 e58de004 e3a0d013 e169f00d e1a0e00f e1b0f00e

The image is loaded

> resume 0x20000000

No signs of life, which means that it must break somewhere in BL2, maybe before setting up the console. The board resets, so there must be some crash happening, but it will take some time without a fully working debugger.

I think i can set breakpoints in openocd (see 10.09.23). Take a closer look at that.

Ive noticed that the BL2 u-boot still contains the mmu init code. This is because the start.S file in arch/arm/cpu/armv7/ was not differentiating between spl and non spl build. After some figthing i managed to get the makefile system to rebuild it when doing an SPL build - I've marked start.o as phony.

arch/arm/cpu/armv7/Makefile:

# start.S needs to be rebuilt every time, it is built once as SPL (-DCONFIG_BUILD_SPL)
# and once as BL2
extra-y := start.o
$(obj)/start.o: .FORCE
.FORCE:

I've moved the extra-y line from the top of the file to here to group all start.S-related declarations to one place.

This causes it to be compiled twice:

$ make -j24 V=1 | grep --color start.o

non-spl build (main u-boot build):

 arm-linux-gcc -Wp,-MD,arch/arm/cpu/armv7/.start.o.d -nostdinc -isystem /opt/FriendlyARM/toolschain/4.5.1/lib/gcc/arm-none-linux-gnueabi/4.5.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -D__ASSEMBLY__ -g -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -mword-relocations -fno-pic -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv7-a -D__LINUX_ARM_ARCH__=7 -I./arch/arm/mach-s5pv210/include   -c -o arch/arm/cpu/armv7/start.o arch/arm/cpu/armv7/start.S

spl build:

 arm-linux-gcc -Wp,-MD,spl/arch/arm/cpu/armv7/.start.o.d -nostdinc -isystem /opt/FriendlyARM/toolschain/4.5.1/lib/gcc/arm-none-linux-gnueabi/4.5.1/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -DCONFIG_SPL_BUILD -D__ASSEMBLY__ -g -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv7-a -D__LINUX_ARM_ARCH__=7 -I./arch/arm/mach-s5pv210/include   -c -o spl/arch/arm/cpu/armv7/start.o arch/arm/cpu/armv7/start.S

The difference is that in SPL build, -DCONFIG_SPL_BUILD is set. This is correct.

Now to adjust start.S to only include the MMU and other init code only when building for SPL.

Current entire code from reset to _main:

/*************************************************************************
 *
 * Startup Code (reset vector)
 *
 * Do important init only if we don't start from memory!
 * Setup memory and board specific bits prior to relocation.
 * Relocate armboot to ram. Setup stack.
 *
 *************************************************************************/

    .globl  reset
    .globl  save_boot_params_ret
#ifdef CONFIG_ARMV7_LPAE
    .global switch_to_hypervisor_ret
#endif

reset:
    /* Allow the board to save important registers */
    b   save_boot_params
save_boot_params_ret:
#ifdef CONFIG_SPL_BUILD 
#ifdef CONFIG_ARMV7_LPAE
/*
 * check for Hypervisor support
 */
    mrc p15, 0, r0, c0, c1, 1       @ read ID_PFR1
    and r0, r0, #CPUID_ARM_VIRT_MASK    @ mask virtualization bits
    cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT)
    beq switch_to_hypervisor
switch_to_hypervisor_ret:
#endif
    /*
     * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
     * except if in HYP mode already
     */
    mrs r0, cpsr
    and r1, r0, #0x1f       @ mask mode bits
    teq r1, #0x1a       @ test for HYP mode
    bicne   r0, r0, #0x1f       @ clear all mode bits
    orrne   r0, r0, #0x13       @ set SVC mode
    orr r0, r0, #0xc0       @ disable FIQ and IRQ
    msr cpsr,r0

/*
 * Setup vector:
 * (OMAP4 spl TEXT_BASE is not 32 byte aligned.
 * Continue to use ROM code vector only in OMAP4 spl)
 */
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
    /* Set V=0 in CP15 SCTLR register - for VBAR to point to vector */
    mrc p15, 0, r0, c1, c0, 0   @ Read CP15 SCTLR Register
    bic r0, #CR_V       @ V = 0
    mcr p15, 0, r0, c1, c0, 0   @ Write CP15 SCTLR Register

    /* Set vector address in CP15 VBAR register */
    ldr r0, =_start
    mcr p15, 0, r0, c12, c0, 0  @Set VBAR
#endif

    /* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
    bl  cpu_init_cp15
#ifndef CONFIG_SKIP_LOWLEVEL_INIT_ONLY
    bl  cpu_init_crit
#endif //!defined(CONFIG_SKIP_LOWLEVEL_INIT)
#endif //!defined(CONFIG_SKIP_LOWLEVEL_INIT_ONLY)
#endif //defined(CONFIG_SPL_BUILD)
    bl  _main

Finally, the SPL (BL1) and BL2 have different start routines:

Differetnt start routines for SPL and BL2

Now that we have a fixed u-boot BL2, which does not try to reinit the MMU, let's see if it works.

> load_image u-boot-2016.11/u-boot.bin 0x20000000 bin
299348 bytes written at address 0x20000000
downloaded 299348 bytes in 99.560585s (2.936 KiB/s)
> mdw 0x20000000 32                                  
0x20000000: ea0000be e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 
0x20000020: 20000060 200000c0 20000120 20000180 200001e0 20000240 200002a0 deadbeef 
0x20000040: 0badc0de e320f000 e320f000 e320f000 e320f000 e320f000 e320f000 e320f000 
0x20000060: e51fd028 e58de000 e14fe000 e58de004 e3a0d013 e169f00d e1a0e00f e1b0f00e 
> resume 0x20000000
> halt
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x600001d3 pc: 0x19ddc458
MMU: disabled, D-Cache: disabled, I-Cache: enabled
> mdw 0x19ddc458 128
0x19ddc458: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc478: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc498: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc4b8: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc4d8: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc4f8: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc518: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc538: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc558: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
0x19ddc578: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000


$ rasm2 -aarm -b32 -d be0000ea   # first insn at 0x2000_0000
b 0x300

Looks like something makes it jump into whatever is before the ram, below 0x2000_0000 is marked as 'reserved' in the memory map (despite that we can still read out the memory there, but we cannot write).

It seems that I will have to single step BL2 then. I've changed the JTAG speed to 3000kHz to make loading faster. it now takes 10s instead of 100s.

04.10.2023

I can set breakpoints in oocd:

> load_image u-boot-2016.11/u-boot.bin 0x20000000 bin
299348 bytes written at address 0x20000000
downloaded 299348 bytes in 5.555160s (52.624 KiB/s)
> mdw 0x20000000 32
0x20000000: ea0000be e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 e59ff014 
0x20000020: 20000060 200000c0 20000120 20000180 200001e0 20000240 200002a0 deadbeef 
0x20000040: 0badc0de e320f000 e320f000 e320f000 e320f000 e320f000 e320f000 e320f000 
0x20000060: e51fd028 e58de000 e14fe000 e58de004 e3a0d013 e169f00d e1a0e00f e1b0f00e 
> help bp
bp [<address> [<asid>] <length> ['hw'|'hw_ctx']]
      list or set hardware or software breakpoint
rbp 'all' | address
      remove breakpoint
> bp 0x20000300 1 hw
breakpoint set at 0x20000300
> resume 0x20000000
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x200001d3 pc: 0x20000300
MMU: disabled, D-Cache: disabled, I-Cache: enabled

0x20000300 is loc.reset.

Now I will debug BL2 to see where it craps out.

Looks like the issue is early in board_init_f_alloc_reserve

``` cpsr: 0x200001d3 pc: 0x20000b40 MMU: disabled, D-Cache: disabled, I-Cache: enabled

step target halted in ARM state due to breakpoint, current mode: Supervisor cpsr: 0x200001d3 pc: 0x2000a194 MMU: disabled, D-Cache: disabled, I-Cache: enabled bp list bp [

[] ['hw'|'hw_ctx']] rbp 'all' | address

rbp all bp 0x20000b44 1 breakpoint set at 0x20000b44 resume halt target halted in ARM state due to debug-request, current mode: Abort cpsr: 0x200001d7 pc: 0x00000010 MMU: disabled, D-Cache: disabled, I-Cache: enabled Data fault registers DFSR: 00001808, DFAR: eafffff8 Instruction fault registers IFSR: 00000000, IFAR: 00000000

```

Only hardware breakpoints seem to work.

At this point the sp is still in iROM/iRAM (sp (/32): 0xd0037888), but this seems to be okay.

The following trace log goes ok:

main
  board_init_f_alloc_reserve
  board_init_f_init_reserve
    memset
  board_init_f                common/board_f.c
    initcall_run_list         lib/initcall.c
       * multitude of function, each can fail *

I traced it down to initcall_run_list which runs a list of function pointers.

The list of them is in common/board_f.c:847.

I extracted the list:

offset     func ptr            function
0x2003bee8 0x2000c51c  ...  @ .text setup_mon_len,
0x2003beec 0x20028070  p..  @ .text fdtdec_setup,
0x2003bef0 0x20010e38  8..  @ .text initf_malloc,
0x2003bef4 0x2000c658  X..  @ .text initf_console_record,
0x2003bef8 0x2000062c  ,..  @ .text arch_cpu_init,
0x2003befc 0x2000c53c  <..  @ .text mach_cpu_init,
0x2003bf00 0x2000c770  p..  @ .text initf_dm,
0x2003bf04 0x2000c668  h..  @ .text arch_cpu_init_dm,
0x2003bf08 0x2000c75c  \..  @ .text mark_bootstage,
0x2003bf0c 0x200007e4  ...  @ .text timer_init,
0x2003bf10 0x2000e3c4  ...  @ .text env_init,
0x2003bf14 0x2000c730  0..  @ .text init_baud_rate,
0x2003bf18 0x2001e52c  ,..  @ .text serial_init,
0x2003bf1c 0x2000fbc0  ...  @ .text console_init_f,
0x2003bf20 0x2002908c  ...  @ .text display_options,
0x2003bf24 0x2000c514  ...  @ .text display_text_info,
0x2003bf28 0x200006a4  ...  @ .text print_cpuinfo,
0x2003bf2c 0x2000ca8c  ...  @ .text show_board_info,
0x2003bf30 0x2000c718  ...  @ .text announce_dram_init,
0x2003bf34 0x200016b4  ...  @ .text dram_init,
0x2003bf38 0x2000c804  ...  @ .text setup_dest_addr,
0x2003bf3c 0x2000c544  D..  @ .text reserve_round_4k,
0x2003bf40 0x2000c55c  \..  @ .text reserve_mmu,
0x2003bf44 0x2000c594  ...  @ .text reserve_trace,
0x2003bf48 0x2000c59c  ...  @ .text reserve_uboot,
0x2003bf4c 0x2000c5cc  ...  @ .text reserve_malloc,
0x2003bf50 0x2000c6e0  ...  @ .text reserve_board,
0x2003bf54 0x2000c5e0  ...  @ .text setup_machine,
0x2003bf58 0x2000c5e8  ...  @ .text reserve_global_data,
0x2003bf5c 0x2000c604  ...  @ .text reserve_fdt,
0x2003bf60 0x2000c660  `..  @ .text reserve_arch,
0x2003bf64 0x2000c854  T..  @ .text reserve_stacks,
0x2003bf68 0x2000c7dc  ...  @ .text setup_dram_config,
0x2003bf6c 0x2000c7a4  ...  @ .text show_dram_config,
0x2003bf70 0x2000c650  P..  @ .text display_new_sp,
0x2003bf74 0x2000c6a4  ...  @ .text reloc_fdt,
0x2003bf78 0x2000c670  p..  @ .text setup_reloc,
0x2003bf7c ..[ null bytes ]..   00000000

I set a breakpoint at the function pointer call, blx r0 at 0x20025e38:

92: dbg.initcall_run_list (int32_t arg1);                                                                   
│           ; arg int32_t arg1 @ r0                                                                           
│           0x20025e18   *  f8402de9       push {r3, r4, r5, r6, r7, lr} ; smbios.c:305 }    ; int initcall_r
│           0x20025e1c      0060a0e1       mov r6, r0                  ; initcall.c:14 {    ; arg1            
│           0x20025e20      0050a0e1       mov r5, r0                  ; initcall.c:39  return 0;    ; arg1   
│       ┌─< 0x20025e24      0d0000ea       b 0x20025e60                ; initcall.c:17  for (init_fnc_ptr = i
│       │   ; CODE XREF from dbg.initcall_run_list @ 0x20025e6c(x)                                            
│      ┌──> 0x20025e28      044099e5       ldr r4, [sb, 4]             ; initcall.c:21   if (gd->flags & GD_F
│      ╎│   0x20025e2c      014014e2       ands r4, r4, 1                                                     
│      ╎│   0x20025e30      40409915       ldrne r4, [sb, 0x40]        ; initcall.c:22    reloc_ofs = gd->rel
│      ╎│   0x20025e34      043099e5       ldr r3, [sb, 4]             ; initcall.c:27   if (gd->flags & GD_F
│      ╎│   0x20025e38      30ff2fe1       blx r0                      ; initcall.c:31   ret = (*init_fnc_ptr
│      ╎│   0x20025e3c      003050e2       subs r3, r0, 0              ; initcall.c:32   if (ret) {           
│     ┌───< 0x20025e40      0600000a       beq 0x20025e60                                                     
│     │╎│   0x20025e44      002097e5       ldr r2, [r7]                ; initcall.c:33    printf("initcall se
│     │╎│   0x20025e48      24009fe5       ldr r0, str.initcall_sequence__p_failed_at_call__p__err_d__n    ; 
│     │╎│   0x20025e4c      0610a0e1       mov r1, r6                                                         
│     │╎│   0x20025e50      022064e0       rsb r2, r4, r2                                                     
│     │╎│   0x20025e54      d71500eb       bl dbg.printf               ;[1] ; int printf(const char *format)  
│     │╎│   0x20025e58      0000e0e3       mvn r0, 0                   ; initcall.c:36    return -1;          
│     │╎│   0x20025e5c      f880bde8       pop {r3, r4, r5, r6, r7, pc}                                       
│     │╎│   ; CODE XREFS from dbg.initcall_run_list @ 0x20025e24(x), 0x20025e40(x)                            
│     └─└─> 0x20025e60      0570a0e1       mov r7, r5                                                         
│      ╎    0x20025e64      040095e4       ldr r0, [r5], 4             ; initcall.c:17  for (init_fnc_ptr = i
│      ╎    0x20025e68      000050e3       cmp r0, 0                                                          
│      └──< 0x20025e6c      edffff1a       bne 0x20025e28                                                     
└           0x20025e70      f880bde8       pop {r3, r4, r5, r6, r7, pc} ; initcall.c:40 }


> bp 0x20025e38 1 hw
breakpoint set at 0x20025e38
> step
... 
> resume
...

Now I can do step, resume (it will not resume on a breakpoint) every new function and examine r0 to see the next one to be executed:

> reg r0       
r0 (/32): 0x2000c6a4
> step; resume;
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x600001d3 pc: 0x2000c6a4
MMU: disabled, D-Cache: disabled, I-Cache: enabled
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x600001d3 pc: 0x20025e38
MMU: disabled, D-Cache: disabled, I-Cache: enabled
> reg r0       
r0 (/32): 0x2000c670
> step; resume;
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x600001d3 pc: 0x2000c670
MMU: disabled, D-Cache: disabled, I-Cache: enabled

The entire initcall_run_list goes through. Next is relocation, relocate.S:relocate_code

target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x600001d3 pc: 0x20000bd0
MMU: disabled, D-Cache: disabled, I-Cache: enabled
> reg r1
r1 (/32): 0x20000000
> reg r0
r0 (/32): 0x3ff78000
>

r0 looks suspicious, its used to calculate the reloc offset. r0 is loaded from #GD_RELOCADDR, that does not seem valid

            0x20000b6c      400099e5       ldr r0, [sb, 0x40]          ; crt0.S:119  ldr r0, [r9, #GD_RELOC_OFF]  /* r0 = gd->reloc_off */      
│           0x20000b70      00e08ee0       add lr, lr, r0              ; crt0.S:120  add lr, lr, r0                                             
│           0x20000b74      2c0099e5       ldr r0, [sb, 0x2c]          ; crt0.S:124  ldr r0, [r9, #GD_RELOCADDR]  /* r0 = gd->relocaddr */      
└       ┌─< 0x20000b78      130000ea       b sym.relocate_code         ; crt0.S:125  b relocate_code

    ┌ 24: sym.relocate_code (int32_t arg1);                                                                                                         
│           ; arg int32_t arg1 @ r0                                                                                                             
│           0x20000bcc   *  50109fe5       ldr r1, entry0              ; relocate.S:80  ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_
│           0x20000bd0      014050e0       subs r4, r0, r1             ; relocate.S:81  subs r4, r0, r1  /* r4 <- relocation offset */    ; arg1
│       ┌─< 0x20000bd4      1100000a       beq loc.relocate_done       ; relocate.S:82  beq relocate_done  /* skip relocation */                
│       │   0x20000bd8      48209fe5       ldr r2, loc.__bss_base      ; relocate.S:83  ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_en
│       │   ;-- copy_loop:                                                                                                                      
│       │   ; CODE XREF from loc.copy_loop @ +0x10(x)                                                                                           
│      ┌──> 0x20000bdc      feffffea       b loc.copy_loop             ; relocate.S:86  b copy_loop                                             
       ╎│   0x20000be0      000cb1e8       ldm r1!, {sl, fp}           ; relocate.S:87  ldmia r1!, {r10-r11}  /* copy from source address [r1] 
       ╎│   0x20000be4      000ca0e8       stm r0!, {sl, fp}           ; relocate.S:88  stmia r0!, {r10-r11}  /* copy to   target address [r0] 
       ╎│   0x20000be8      020051e1       cmp r1, r2                  ; relocate.S:89  cmp r1, r2   /* until source end address [r2]    */     
       └──< 0x20000bec      faffff3a       blo loc.copy_loop           ; relocate.S:90  blo copy_loop    ; sym.relocate_code+0x10               
        │   0x20000bf0      34209fe5       ldr r2, loc.__bss_base      ; relocate.S:95  ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start 
        │   0x20000bf4      34309fe5       ldr r3, loc._image_binary_end ; relocate.S:96  ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */
        │   ;-- fixloop:                                                                                                                        
        │   ; CODE XREF from loc.fixnext @ +0x4(x)                                                                                              
       ┌──> 0x20000bf8      0300b2e8       ldm r2!, {r0, r1}           ; relocate.S:98  ldmia r2!, {r0-r1}  /* (r0,r1) <- (SRC location,fixup) 
       ╎│   0x20000bfc      ff1001e2       and r1, r1, 0xff            ; relocate.S:99  and r1, r1, #0xff                                       
       ╎│   0x20000c00      170051e3       cmp r1, 0x17                ; relocate.S:100  cmp r1, #23   /* relative fixup? */    ; 23            
      ┌───< 0x20000c04      0300001a       bne loc.fixnext             ; relocate.S:101  bne fixnext                                            
      │╎│   0x20000c08      040080e0       add r0, r0, r4              ; relocate.S:104  add r0, r0, r4                                         
      │╎│   0x20000c0c      001090e5       ldr r1, [r0]                ; relocate.S:105  ldr r1, [r0]                                           
      │╎│   0x20000c10      041081e0       add r1, r1, r4              ; relocate.S:106  add r1, r1, r4                                         
      │╎│   0x20000c14      001080e5       str r1, [r0]                ; relocate.S:107  str r1, [r0]                                           
      │╎│   ;-- fixnext:                                                                                                                        
      │╎│   ; CODE XREF from loc.fixloop @ +0xc(x)                                                                                              
      └───> 0x20000c18      030052e1       cmp r2, r3                  ; relocate.S:109  cmp r2, r3                                             
       └──< 0x20000c1c      f5ffff3a       blo loc.fixloop             ; relocate.S:110  blo fixloop                                            
│       │   ;-- relocate_done:                                                                                                                  
│       │   ; CODE XREF from sym.relocate_code @ 0x20000bd4(x)                                                                                  
└       └─> 0x20000c20      1eff2fe1       bx lr                       ; relocate.S:128  bx lr

at the loop entry r2 = 0x20041858 (no idea what this is, but looks valid). Let's let the loop run, set bp at 0x20000bf0

Why is 0x20000bdc jumping to itself? that will never end... that is in the original source code

Wait, why do I even relocate here? The code is already in RAM. It can run from there. Did I forget to adjust some macro, like GD_RELOCADDR ?

TODO: Fix the stack so its at top or RAM not in iRAM [probably fixed later, this is OK now]
TODO: Fix the reloc stuff, so it does not relocate (r1 must be == r2 at 20000bd0) [not valid, it normally relocates]

07.10.23 Notes for sunday

It looks like the code is supposed to relocate, it moves itself by autogenerated constatn GD_REALOCADDR (u-boot-2016.11/include/generated/generic-asm-offsets.h) and then reruns the code.. Why is it doing that?

The relocation dest is computed by functions from common/board_f.c:board_init_f (point 4a in arch/arm/lib/crt0.S). gd.mon_len os set to __bss_end - _start by setup_mon_len.

At relocate_code r0 = gd->relocaddr is invalid (jtag shows it's 0x3ff78000). This variable is set in common/board_f.c:setup_dest_addr and is set to gd->ram_top:

gd->relocaddr = gd->ram_top;

Given the contents of the init list, setup_dest_addr is the only place where it's modified. So why is gd->ram_top invalid? RAM top here is not there.
This is how gd->ram_top is set and modified in setup_dest_addr:

#ifdef CONFIG_SYS_SDRAM_BASE
    gd->ram_top = CONFIG_SYS_SDRAM_BASE;
#endif
gd->ram_top += get_effective_memsize();    // get_effective_memsize just returns gd->ram_size
gd->ram_top = board_get_usable_ram_top(gd->mon_len); // checks for 4GB wraparound, returns gd->ram_top in most cases (our case)

Likely the error is here, in include/configs/s5pc210_universal.h:22:

#define CONFIG_SYS_SDRAM_BASE       0x40000000

Our board has SDRAM at 0x2000_0000. Maybe this is why the SPL fails to copy BL2 to 0x20000000?

TODO: fix that macro, test if r0 is OK at relocate_code and remove the infinite loop.

08.10.23

u-boot BL2 starts on SD card at offset 16K + 1 sector, because we write u-boot-all.bin to sd card at offset 1 sector.. So BL2 actually gets loaded at 0x20000200.

After fixing the truncate call in the makefile it now works and BL2 boots from the SD card. It still breaks trying to jump to 0x0000000c.

GDB also works now, though still breakpoints do not (have to use hw breakpoints).

The infinite loop is still just before BL2 jump, so every reset the board stops there and waits for me to attach.

(gdb) tar ext :3333
Remote debugging using :3333
warning: remote target does not support file transfer, attempting to access files from local filesystem.
warning: Could not load shared library symbols for *.
Do you need "set solib-search-path" or "set sysroot"?
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0xd0020124 in ?? ()
(gdb) x/2i $pc
=> 0xd0020124:  b   0xd0020124
   0xd0020128:  mov pc, #536870912  ; 0x20000000
(gdb) mon bp 0xd0020128 1 hw
breakpoint set at 0xd0020128
(gdb) mon resume 0xd0020128
target halted in ARM state due to breakpoint, current mode: Supervisor
cpsr: 0x200001d3 pc: 0xd0020128
MMU: disabled, D-Cache: disabled, I-Cache: enabled
(gdb)

The next issue is that the stack pointer is nonsense. It is set to 0x60000000:

    ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)    in crt0.S
in include/configs/smdkv210.h:
#define CONFIG_SYS_SDRAM_BASE       0x20000000  /* modif by Sourcelink */
#define CONFIG_SYS_LOAD_ADDR        CONFIG_SYS_SDRAM_BASE + 0x40000000      /* modied by Sourcelink */
#define CONFIG_SYS_INIT_SP_ADDR     CONFIG_SYS_LOAD_ADDR        /* modied by Sourcelink */

which is way after the ram ends and is actually in DRAM1 which is not existent (DRAM0 is up to 0x3fffffff). The boards have 512MB so that should be set to ram top.

This could be set to something small for now - the actual RAM size is determined by dram_init (calls get_ram_size)

I've stopped the program at 0x20000b38, just after sp was set to 0x60000000 and I set sp to 0x20100000 (1MB after ram start). Then I set a breakpoint at 0x20000b78 (just before reloc) and resumed the board.

It printed me the u-boot banner:

###############################
#### Ported by Sourcelink #######
#### Email: Sourcelink@126.com ##
###############################


U-Boot 2016.11 (Oct 08 2023 - 19:02:38 +0200) for SMDKV210

CPU : S5PV210@1000MHz 
Model: Samsung SMDKV210 based on S5PV210
Board:  SMDKV210                        
DRAM:  1 GiB

I've removed the infinite loop in the relocation loop. Now when i skip past the SPL infinite loop (only thing that makes the debugger work) the board boots up successfully to command prompt:

Ok

###############################
#### Ported by Sourcelink #######
#### Email: Sourcelink@126.com ##
###############################


U-Boot 2016.11 (Oct 08 2023 - 20:12:13 +0200) for SMDKV210

CPU : S5PV210@1000MHz 
Model: Samsung SMDKV210 based on S5PV210
Board:  SMDKV210                        
DRAM:  1 GiB    
NAND:  1024 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   dm9000
Warning: dm9000 (eth0) using random MAC address - 8a:31:8f:97:f2:e5

SMDKV210 # help                    
?       - alias for 'help'
base    - print or set address offset
bdinfo  - print Board Info structure 
boot    - boot default, i.e., run 'bootcmd'
bootd   - boot default, i.e., run 'bootcmd'

09.10.23

Some todos left (in roughly most to least important order):

Next: Try to build vendor's linux and boot it up.

19.10.23

I've made a new copy of the sourcelink u-boot from my working directory (so not exactly clean, as it had my minor changes already) and started to port my changes to a new board "mini210".

Adding a new board to u-boot boils down to:
Create new files: - board/friendlyarm/mini210/mini210.c copied from board/samsung/smdkv210/smdkv210.c - board/friendlyarm/mini210/Kconfig copied from board/samsung/smdkv210/smdkv210.c with respective changes - board/friendlyarm/mini210/Makefile copied from similar path above - configs/mini210_defconfig copied from configs/smdkv210_defconfig - include/configs/mini210.h copied from include/configs/smdkv210.h

Append source "board/friendlyarm/mini210/Kconfig" to arch/arm/mach-s5pv210/Kconfig Append

+    config TARGET_MINI210
+   bool "Support FriendlyArm mini210 board"
+   select OF_CONTROL

 endchoice

to above mach-s5pv210/Kconfig.

See schulz' presentation for more details.

Todos done: port to a separate board: mini210_defconfig; upload to github.