April 18, 2024

EBAZ4205 Bitcoin miner board - Booting (part 2)

In part 1, we discovered that we can shorten up the "trick" to boot into a shell without a password to just the following:
nand read ${kernel_load_address} 0x300000 ${kernel_size}
nand read ${devicetree_load_address} 0x800000 ${devicetree_size}
setenv bootargs 'console=ttyPS0,115200 root=/dev/mtdblock6 rootfstype=jffs2 noinitrd rw rootwait reboot=cold,hard emergency init=/bin/sh'
bootm ${kernel_load_address} - ${devicetree_load_address}
But, why does this work? The real mystery lies in the offset addresses for the "nand read" commands

NAND layout

We have a 1 Mbit nand chip, so 128M of space in our NAND "disk drive". As the kernel boots, we can see this go by:
9 ofpart partitions found on MTD device pl35x-nand
Creating 9 MTD partitions on "pl35x-nand":
0 0x000000000000-0x000000300000 : "nand-fsbl-uboot"
1 0x000000300000-0x000000800000 : "nand-linux"
2 0x000000800000-0x000000820000 : "nand-device-tree"
3 0x000000820000-0x000001220000 : "nand-rootfs"
4 0x000001220000-0x000002220000 : "nand-jffs2"
5 0x000002220000-0x000002a20000 : "nand-bitstream"
6 0x000002a20000-0x000006a20000 : "nand-allrootfs"
7 0x000006a20000-0x000007e00000 : "nand-release"
8 0x000007e00000-0x000008000000 : "nand-reserve"
So, there we have the layout. Notice that the bootargs specifies "mtdblock6" as the root file system
We can get another view of it via:
cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00300000 00020000 "nand-fsbl-uboot"
mtd1: 00500000 00020000 "nand-linux"
mtd2: 00020000 00020000 "nand-device-tree"
mtd3: 00a00000 00020000 "nand-rootfs"
mtd4: 01000000 00020000 "nand-jffs2"
mtd5: 00800000 00020000 "nand-bitstream"
mtd6: 04000000 00020000 "nand-allrootfs"
mtd7: 013e0000 00020000 "nand-release"
mtd8: 00200000 00020000 "nand-reserve"
So, this command copies the kernel from "chunk" 1:
nand read ${kernel_load_address} 0x300000 ${kernel_size}

kernel_load_address=0x2080000
kernel_size=0x500000
And this command copies the FDT from "chunk" 2:
nand read ${devicetree_load_address} 0x800000 ${devicetree_size}

devicetree_load_address=0x2000000
devicetree_size=0x20000

It is worth noting that RAM addresses begin at 0x2000_0000 and 256M will go through 0x2fff_ffff.

A handy fact to understand the NAND sizes (and offsets) is that 1M is 0x10_0000. I put the underscore before four zeros so I don't go crosseyed and make stupid mistakes counting zeros.
So here is a list of sizes:

dev:    size   size (M)  name
mtd0: 00300000 3M   "nand-fsbl-uboot"
mtd1: 00500000 5M   "nand-linux"
mtd2: 00020000 128K "nand-device-tree"
mtd3: 00a00000 10M  "nand-rootfs"
mtd4: 01000000 16M  "nand-jffs2"
mtd5: 00800000 8M   "nand-bitstream"
mtd6: 04000000 64M  "nand-allrootfs"
mtd7: 013e0000 20M- "nand-release"
mtd8: 00200000 2M   "nand-reserve"
As near as I can tell the last two "chunks" are just useless and wasted.

I can do this:

mount -t jffs2 /dev/mtdblock4 /mnt
ls -l /mnt
total 0
drwxr-xr-x    2 1002     root             0 Apr 26  2017 configure
drwxr-xr-x    2 1002     root             0 Jul 21  2010 system
drwxr-xr-x    2 1002     root             0 Jul 21  2010 work0
drwxr-xr-x    2 1002     root             0 Jul 21  2010 work1
Note that this is pretty much what we see in /opt

I have no luck mounting /dev/mtdblock3 -- but it is not just a bunch of zero bytes. It could just be "noise" bytes in the NAND chip, but I wouldn't expect that, I would expect all zeros of 0xff or some such.

What about the u-boot partition?

I presume fsbl stands for "first stage boot loader". We need to look at the documentation from Xilinx for the Zynq chip to learn how it boots. There does not seem to be a two stage process going on, or at least if so it does not announce itself over the serial port.

We do have an 1843 page "technical reference manual" for the Zynq chip. Chapter 6 is over 60 pages and talks about boot. Additionaly it refers to UG821 for software developer documentation.


Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org