Boot fails with self-build u-boot

you can use my uboots bootdevice-detection like this:

as you see there i also tried setting an environment-variable :slight_smile:

This code is not in 2019-01-bri-r2 branch I was basing my work on. FWIS it is in bpi-r2_v5 branch. Anyway I prefer to have direct comparison like “if itest.l *81dffff0 == 434d4d65 ; ...” in uEnv rather than relying on custom command in u-boot that is not available in upstream version. It is just more portable this way - one less patch to care about when porting to more recent version.

right, i have not put this part to upstream (and inside newer branches), because i did not need this before…it was only a test for me :slight_smile:

the other code testing for emmc-string in Memory was from me, but currently only used for determining device for saveenv

Frank, I’m wondering about the magic behind the address 0x81DFFFF0 that you use to determine if it was eMMC or SD card the device had booted from. Looks like this detection is not that reliable:

[Dram_Buffer] MAX_TEE_DRAM_SIZE: 0
Boot from eMMC!!
[PLFM] Init Boot Device: OK(0)

...

 bootloader load uboot ,the address of uboot is 81E00000
[PART]partition name UBOOT
[PART]partition start block 0x200
[PART]partition size 0x80000
[PART]partition blks 0x400
[PART]partition flags 0x0
[PART]partition name 0x8
[bean] part->startblk(0x200) bdev->blksz(0x200) part->part_id(8) hdr(0xFFB50000)
[BlkDev.c 101 ]partition block size 0x200 ,blks:0xE90000
[BlkDev.c 101 ]partition block erase size 0x200

[PART] load "UBOOT" from 0x0000000000050000 (dev) to 0x81E00000 (mem) [SUCCESS]
[PART] load speed: 10462KB/s, 300000 bytes, 28ms
[BT_SD_PG] device info 0x8590 0x8A00 0xCB01 0x102

...

[PLFM] boot reason: 0
[PLFM] boot mode: 0
[PLFM] META COM0: 0
[PLFM] <0xFFB7CC10>: 0x0
[PLFM] boot time: 2013ms
[PLFM] DDR reserve mode: enable = 0, success = 0

[BLDR] jump to 0x81E00000
[BLDR] <0x81E00000>=0xEA0000B8
[BLDR] <0x81E00004>=0xE59FF014


U-Boot 2019.01 (Jan 30 2019 - 12:21:02 +0000)

CPU:   MediaTek MT7623 E3
DRAM:  2 GiB
MMC:   mmc@11230000: 0, mmc@11240000: 1
Loading Environment from MMC... Boot From SD(id:1)

MMC: no card present

As you can see here I boot the board from the eMMC but u-boot thinks that is was booted from SD - and that’s because of this:

BPI-R2> md 0x81DFFFF0
81dffff0: ffffffff ffffffff ffffffff ffffffff    ................

It is not the first time I see it fail. Sometimes I was getting “eMMC” at this offset even when I was booting from SD. That’s why I’m wondering about the “detection magic” - what was the reasoning behind using this offset as an information source?

I took the offset from jackzengs implementation

But simplyfied the code to make it compatible with upstream uboot. In my tests i got the right value,but you need a powercycle to boot from the other device…on reboot it remembers bootdevice…

I don’t know a better way…also i know no way to get boot-switch position and cannot test it. maybe this is for bootswitch, but i have no such board: https://github.com/BPI-SINOVOIP/BPI-R2-bsp/commit/2bf5f720c99db45ee551176a4f2a44f622fcf8a9

maybe this is interferring with your board, have you tested with switch on SD?

Uh oh, it looks like a hackish hack. g_mmc_devid is an extern that is defined in common/env_mmc.c (which is patched in “Save uboot envs to where it boot from” change) so it is initialized to 0 if at 0x81DFFFF0 there’s a “eMMC” or to 1 if not. And the “hackish” I mean that this change hardcodes dev to always be 0 or 1 no matter what was the actual device number passed to the mmc command. I.e. this change breaks mmc command in unobvious way and makes either SD card or eMMC unavailable from u-boot,

As for boot switch “detection” - my experiments with different preloaders seem to show that the contents of the memory at address 0x81DFFFF0 is set to “eMMC” by some versions of preloaders to indicate that u-boot is loaded from the eMMC. It has no direct relation to the position of the boot switch. If a preloader of such kind is written to the SD card you still would be getting “eMMC” at memory 0x81DFFFF0 despite the fact that boot switch is set to SD and preloader was loader from this SD card. We need something else to detect the real position of the boot switch. I may speculate here that probably boot switch is connected to some gpio line on the MT7623n and the state of this line is used by the in-chip hardcoded firmware “pre-pre-loader” to determine if attempt to boot from SD card should be skipped or not. If that’s the case than in theory we may read the state of this gpio line and get our answer. But this is a speculation and more info from vendor (or further investigation) is needed to be able to solve this.

P.S. Or there’s an easiest fix (from my PoV): vendor might provide us with yet another preloader binary that always loads u-boot from SD card and always set memory at address 0x81DFFFF0 to some predefined value like "SD ". Such preloader coupled with already available preloader that always loads u-boot from eMMC and always put “eMMC” to that memory address would allow us to reliably determine the source u-boot was loaded from which is sufficient for our needs. The only rule to follow then would be to place “SD card always” preloader to SD cards and “eMMC always” preloader to eMMC and that will seal the deal.

1 Like

thank you for your investigation. I have a board without this switch but maybe here the gpio-line is soldered to sd-position.

In my tests my detection works…have i used differen preloaders?

afair i used debian-image to create my own (erased boot/root-partitions and leave preloader,other bootheaders,uboot). On emmc i used BPI-R2-EMMC-boot0-DDR1600-0k-0905.img.gz which should not set emmc-string based on your findings.

Btw. Read out switch does not represent boot-device…if switch is on SD and no (bootable) sd is inserted r2 will boot from emmc and your gpio-state shows wrong position

That’s worrying. I will try to re-test with this preloader this evening - it might be me messing something up while testing.

Yep, it was me messing up, but rather than messing up while testing I messed up while copying text from LibreOffice Writer to browser window. BPI-R2-EMMC-boot0-DDR1600-0k-0905.img behave the same way as mtk-bpi-r2-preloader-emmc.bin, not mtk-bpi-r2-preloader-sd.bin. I.e. it always looks for u-boot on the eMMC and initializes memory at 0x81DFFFF0 to “eMMC”.

To be quite frank it all depends on the definition of the boot device. For example if we’ve got SD card inserted that is missing preloader but has proper u-boot, on eMMC we’ve got preloader but do not have u-boot and boot switch is set to eMMC - what should we call “a boot device” for this case? SoC will start up into mtk bootrom which will load preloader from eMMC (enforced by the boot switch position) then preloader will look for u-boot on SD card, load it from there and execute it. Was the eMMC a boot device? Or was it SD? Or both?

My view on this is that we should always treat u-boot source as a boot device as one of the main reasons we need to know what was the boot device is to determine where to look for and where to store u-boot env. “Easiest fix” I described earlier fits this approach nicely. Or as a best case scenario would be vendor to provide us with the source code and build instructions for preloader (should be something similar to this repo; useful references 1, 2, 3). This way we will be able to implement what we want ourselves and be sure what is where and why.

We will not get source of preloader because this is NDA…

Why not just use BPI-R2-EMMC-boot0-DDR1600-0k-0905.img for emmc and one of the others (which do not write emmc-string) for sdcard…and all works as expected

Not really. SD only preloaders that are available now do not touch memory at address 0x81DFFFF0. It means that if the board was booted once with eMMC preloader and then this memory location wasn’t changed by linux then if the next boot without power cycle would happen from SD card with “SD only” preloader we will still have “eMMC” at that location despite the fact we booted from SD.

P.S. Although we may workaround the situation by having two different u-boot builds (SD and eMMC) or we may reset this memory location to, say, 0x00000000, in u-boot after checking for eMMC boot flag. Will test the second approach on my boards today’s evening and report back the results.

Well, I’m almost ready to give up :frowning:. Frank, may I ask you to perform the following test:

  1. Write mtk-bpi-r2-preloader-emmc.bin to eMMC and mtk-bpi-r2-preloader-sd.bin to SD card.
  2. Do not insert SD card, boot from eMMC into u-boot. Check that md 0x81dffff0 reports “eMMC”.
  3. Insert SD card and press reset button (or run reset). Check that there’s “Load u-boot from SD Card...” in the preloader boot log.
  4. Check what’s the output of the md 0x81dffff0. Expected result: “eMMC”.
  5. Execute mw.l 0x81dffff0 0x0. Then re-check the output of the md 0x81dffff0. Expected result: 0x00000000.
  6. Press reset button or execute “reset”. Check that there’s “Load u-boot from SD Card...” in the preloader boot log.
  7. Check what’s the output of the md 0x81dffff0.

My expectations were that as we had reset memory to 0x00000000 at pt.5 and then rebooted board using “SD-card only” preloader then memory at address 0x81dffff0 will be left untouched and thus be equal to 0x00000000 we had set it to. But experiments on my board show that this location gets set to “eMMC” by something (preloader? bootrom?) despite the fact that board booted from SD and “SD-only” preloader was used.

P.S. And it gets even weirder: if I reset memory at 0x81dffff0 to 0x00000000 and then boot to linux instead of reseting the board and only then do a reset (or execute “reboot” in OS shell) - memory at 0x81dffff0 stays at value 0x00000000 instead of being set to “eMMC” by something. I honestly don’t get what’s going on here. I think we need to somehow extract more info from vendor representatives to solve this one.

2: “Load u-boot from eMMC…”

BPI-R2> md 0x81dffff0 
81dffff0: 434d4d65 feef7f7f f9beffff fffffffb    eMMC............

3/4: “Load u-boot from SD Card…”

BPI-R2> md 0x81dffff0
81dffff0: 434d4d65 feef7f7f f9beffff fffffffb    eMMC............

so still emmc…mhm, thats wrong, seems that uboot is loaded from sd, but preloader from emmc or preloader from sdcard does not touch this memory-address (state from previous boot)

5:

BPI-R2> mw.l 0x81dffff0 0x0
BPI-R2> md 0x81dffff0      
81dffff0: 00000000 feef7f7f f9beffff fffffffb    ................

like your expectation

6: after reset again “Load u-boot from SD Card…”

7: oh…

BPI-R2> md 0x81dffff0                                                           
81dffff0: 434d4d65 feef7f7f f9beffff fffffffb    eMMC............

emmc is set again

conclusion, it seem that if first booted from emmc the memory is always set to emmc, but uboot (and maybe preloader) are loaded from sdcard…we still not know if bootrom or preloader setting this memory-position, but it contains the first boot-information after power cycle and will be rewritten after each boot to this.

just a thought…preloader/bootrom set the string to a physical memory-address and give that to uboot, now uboot takes this memory-block and copies it to an own range (around the 0x81dffff0). so uboot does not change the original position of the string…only a copy

i.e.

(uboots) RAM starts at 0x81E00000, like this line shows:

bootloader load uboot ,the address of uboot is 81E00000

and this area does always rewritten by bootrom/preloader with contents from bootmedia and our bootinfo-string which will never changed till a power-cycle. your changes with md are only in ram and do not change the source-string

but i do not know about your last test (loading linux and make a reboot there)…or do you make a real power-reset? maybe reset there triggers bootrom again (watchdog,acpi or similar) to erase the string in emmc

is there any way in uboot to search a string in memory (to get and compare “Load u-boot from …”)?

Yep, that was the conclusion from experiments on my board. I was hoping that it might be me doing something wrong or might be my board being somewhat funky. As your tests show that’s not the case unfortunately for us.

Nope, no power cycle in this test. But in case your theory about string being copied from another place to 0x81dffff0 is correct it might be that linux happens to overwrite the location this string gets copied from and that’s why we this this strange behavior. :thinking: Or - as the SoC used works essentially the same way as Android handhelds do - booting from eMMC might be implemented as a “recovery” or “fastboot” or some other boot mode of such kind. So it might set a flag somewhere in SoC (some internal register or some location in memory) and only reset this flag after linux kernel re-initialize some part of the SoC. We need preloader sources to be able to tell for sure what’s going on here. Or at least get more info from the informed person who has the access to the preloader source.

As for your question about a way in u-boot to search for a string in memory - I’m not experienced enough with u-boot but even if there’s no such thing I’d say that it would be pretty easy to implement it as an additional u-boot command. As an alternative I think that it is even possible to code it in u-boot hash (or is it dash?) shell code but the speed of such solution will be really slow.

Some help from people who are able to test different preloaders is appreciated. What to do:

  1. Take any preloader from this list and install it to resp. boot media. Note the name of preloader you had used and boot media you placed it to (SD or eMMC).
  2. Boot your board into u-boot, good idea would be to capture bootlog. Go to the u-boot command line. Check bootlog to get an idea what was the real bootmedia u-boot was loaded from. Strings to look for: “Load u-boot from SD Card...” or “Load u-boot from eMMC...” or “Boot from SD Card!!” or “Boot from eMMC!!”. Note the string you had found.
  3. In u-boot shell execute “md.b 0x00100048 10”, note the output.
  4. Post the info you had noted to this thread so we can collect and analyze it.

Big thanks to contributors in advance!

We should only use the 2 new preloaders (2019-02-22), because they load entire uboot…

https://github.com/BPI-SINOVOIP/BPI-files/tree/master/SD/100MB.

  • BPI-R2-preloader-DDR1600-20190722-2k.img.gz
  • BPI-R2-EMMC-boot0-DDR1600-20190722-0k.img.gz

Oh my, @sinovoip, it is an epic fail again! Preloaders in files above are bit to bit identical. And if you ungzip BPI-R2-preloader-DDR1600-20190722-2k.img.gz you get a file named BPI-R2-EMMC-boot0-DDR1600-20190722-2k.img - which is exactly what its name implies - BPI-R2-EMMC-boot0-DDR1600-20190722-0k.img prepended with eMMC boot signatures. @sinovoip, why the level of support provided for R2 has to be this bad?

1 Like

I’d say nope, we shouldn’t. It is OK to use older preloaders as long as u-boot binary size is under 300000.

New preloader behavior w.r.t. boot from eMMC/SD is the same as of BPI-R2-720P-DDR1600-2k.img, i.e.: (1) no “eMMC” string at 0x81dffff0 even when u-boot is loaded from eMMC and (2) it always tries to load u-boot from SD card if any SD card is inserted, no matter the position of hardware boot switch. Point (2) is a show-stopper as it breaks the most useful use case for hw bootswitch. The only point in setting hw switch to eMMC position is to force the board to ignore SD card on boot. Having preloader always trying to load u-boot from SD card no matter what makes it impossible.

P.S. It is especially bad for “board set up at some distant location” case. Forgetting to remove SD card from it will lead to a board hang on the next reboot and user having to drive in there just to eject the SD.

@sinovoip

can you please fix the problems described in preloader?

  • load uboot from device where preloader was loaded (maybe make real emmc/sd-preloaders which each load specific device), but better would be let 1 preloader look from which device it was loaded
  • respect boot-switch (can we read out the boot-switch in uboot?)
  • write a string in memory to determine which device was really used to load uboot
  • if the prior bootdevice is no more available, try the other one (needs to be only done if a device-switch is done like now or if first 2 points are conflicting). i don’t know which is done by hardware and which by preloader (does hardware/bootrom read-out the boot-switch and load bootloader from the selected device?)

Hi Frank,

I’m trying to create a Debian Buster image from scratch but I’m having hard time to load u-boot.

What is the latest u-boot that works fine ?

I tried to compile u-boot from this repository https://github.com/frank-w/u-boot/tree/2019-10-bpi-r2

Cross compilation on Debian Buster x64 VM is fine and I get an u-boot.bin file (325K in size) then I ran the below commands to write the preloader and compiled u-boot

gunzip -c BPI-R2-HEAD440-0k.img.gz | dd of=/dev/loop8 bs=1024 seek=0
gunzip -c BPI-R2-HEAD1-512b.img.gz | dd of=/dev/loop8 bs=512 seek=1
sudo dd if=BPI-R2-preloader-DDR1600-20191024-2k.img of=/dev/loop8 bs=1024 seek=2
sudo dd if=u-boot.bin of=/dev/loop8 bs=1024 seek=320

For the preloader I used the latest from BPI repository https://github.com/BPI-SINOVOIP/BPI-files/blob/master/SD/100MB/BPI-R2-preloader-DDR1600-20191024-2k.img.gz. It seems u-boot does not get loaded. These are the last line from the UART boot where is freezes.

Device APC domain init setup:

 bootloader load uboot ,the address of uboot is 81E00000 
[PART]partition name UBOOT 
[PART]partition start block 0x200 
[PART]partition size 0x80000 
[PART]partition blks 0x400 
[PART]partition flags 0x0 
[PART]partition name 0x8 
[bean] part->startblk(0x200) bdev->blksz(0x200) part->part_id(8) hdr(0xFFB50000)
[BlkDev.c 101 ]partition block size 0x200 ,blks:0x7740000
[BlkDev.c 101 ]partition block erase size 0x200 

[PART] load "UBOOT" from 0x0000000000050000 (dev) to 0x81E00000 (mem) [SUCCESS]
[PART] load speed: 6736KB/s, 524288 bytes, 76ms
[BT_SD_PG] device info 0x8590 0x8A00 0xCB01 0x102
0:dram_rank_size:80000000
[PLFM] md_type[0] = 255 
[PLFM] md_type[1] = 253 

[PLFM] boot reason: 0
[PLFM] boot mode: 0
[PLFM] META COM0: 0
[PLFM] <0xFFB7CC10>: 0x0
[PLFM] boot time: 2950ms
[PLFM] DDR reserve mode: enable = 0, success = 0

[BLDR] jump to 0x81E00000
[BLDR] <0x81E00000>=0x0
[BLDR] <0x81E00004>=0x0

Am I missing something ?