Unlike how I usually treat software tools I work with, my attitude towards U-boot is “if it works, never mind how and why”. Trying to understand the gory details of U-boot has never been very rewarding. Things work or break more or less randomly, depending on which git revision is checked out. Someone sent a patch fixing this and breaking that, and then someone else sent another patch.
So this is my story: After upgrading the Linux kernel from 3.3 to 3.12 (both having a strong Xilinx flavor, as the target is a Zynq board), but kept an old version of U-boot, I ran through the drill that usually makes the kernel boot:
zynq-uboot> fatload mmc 0 0x8000 zImage reading zImage 2797680 bytes read zynq-uboot> fatload mmc 0 0x1000000 devicetree.dtb reading devicetree.dtb 5827 bytes read zynq-uboot> go 0x8000 ## Starting application at 0x00008000 ... Error: unrecognized/unsupported machine ID (r1 = 0x1fb5662c). Available machine support: ID (hex) NAME ffffffff Generic DT based system ffffffff Xilinx Zynq Platform Please check your kernel config and/or bootloader.
So the kernel didn’t boot. Looking at the way I attempted to kick it off, one may wonder how it worked at all with kernel v3.3. But one can’t argue with the fact that it used to boot.
The first thing to understand about this error message, is that it’s fatally misleading. The real problem is that the device tree blob isn’t found by the kernel, so it reverts to looking for a machine ID in r1. And r1 just has some value. The error message comes from a piece of boot code that is never reached, if the device tree is found and used.
Now, let’s try to understand the logic behind the sequence of commands: The first command loaded the zImage into a known place in memory, 0x8000. One could ask why I didn’t use uImage. Well, why should I? zImage works, and that’s the classic way to boot a kernel.
The device tree blob is then loaded to address 0x10000000.
And then comes the fun part: U-boot just jumps to 0x8000, the beginning of the image. I think I recall that one can put zImage anywhere in memory, and it will take it from there.
But how does the kernel know that the device tree is at 0x10000000? Beats me. I suppose it’s hardcoded somewhere. But hey, it worked! At least on older kernels. And on U-boot 2012.10 and older (but not 2013.10).
For the newer kernel (say, 3.12), a completely different spell should be cast. Something like this (using U-Boot 2012.10 or 2013.10):
zynq-uboot> fatload mmc 0 0x3000000 uImage reading uImage 3054976 bytes read zynq-uboot> fatload mmc 0 0x2A00000 devicetree.dtb reading devicetree.dtb 7863 bytes read zynq-uboot> bootm 0x3000000 - 0x2A00000 ## Booting kernel from Legacy Image at 03000000 ... Image Name: Linux-3.12.0-1.3-xilinx Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 3054912 Bytes = 2.9 MiB Load Address: 00008000 Entry Point: 00008000 Verifying Checksum ... OK ## Flattened Device Tree blob at 02a00000 Booting using the fdt blob at 0x02a00000 Loading Kernel Image ... OK OK Loading Device Tree to 1fb4f000, end 1fb53eb6 ... OK Starting kernel ... Uncompressing Linux... done, booting the kernel. Booting Linux on physical CPU 0x0 [ ... kernel boots, bliss and happiness ... ]
OK, so I twisted it all around. All of the sudden, I use an uImage, rather than zImage. Why? Because bootm works with uImage, and bootz wasn’t supported by that specific U-boot version (or configuration, I’m not really sure).
The addresses I loaded into are different too, and I’m not sure it matters. What surely matters, is that bootm was explicitly given the address of the device tree blob, and therefore passed that through a register to the kernel. So in this case, it’s pretty obvious how the kernel finds what’s where.
Ah, but there’s a twist. The latter, bootm-based method didn’t work on the 3.3 kernel. In fact, I got a very similar error message when I tried that.
As I said in the beginning, I never cared dive deep into U-boot. So all I’m saying is — if you encounter an error message like the one above, just try the other magic spell, and hope for good.
And if someone known more about what happened in the connection between U-boot and Linux somewhere in 2012, or has a link to some mailing list discussion where this was decided upon, please comment below. :)