Unable to boot Beaglebone Black from eMMC

I am working on booting a Beaglebone Black with a custom system. But am unable to get it to boot and am seeing an error I haven’t encountered before.

I have updated all the references from /dev/mmcblk0 to /dev/mmcblk1 as well as 0:11:1, 0:21:2, 0:31:3 in the various files.

I built a uSD card with Debian, copied the .fw file with the custom system and then did a fwup -d /dev/mmcblk1 -t complete

The boot looks good right up until Unknown command ‘bootefi’ - try ‘help’ which appears to be a command that is maybe newer then the uBoot with Nerves?? So the uBoot packaged with the fw bundle is not being installed on the eMMC?? But maybe this is just a red herring… since the boot continue on.

FYI: Once completed I plan to document this and provide a patch/script to ease everyone’s pain in flashing the BBBs eMMC.

Here is the diff of the custom system:

diff --git a/fwup-ops.conf b/fwup-ops.conf
index cfed45a..65e066b 100644
--- a/fwup-ops.conf
+++ b/fwup-ops.conf
@@ -146,22 +146,22 @@ task revert.wrongplatform {
 # Run "fwup /usr/share/fwup/ops.fw -t status -d /dev/rootdisk0 -q -U" to check the status.
 ##
 task status.aa {
-    require-path-on-device("/", "/dev/mmcblk0p2")
+    require-path-on-device("/", "/dev/mmcblk1p2")
     require-uboot-variable(uboot-env, "nerves_fw_active", "a")
     on-init { info("a") }
 }
 task status.ab {
-    require-path-on-device("/", "/dev/mmcblk0p2")
+    require-path-on-device("/", "/dev/mmcblk1p2")
     require-uboot-variable(uboot-env, "nerves_fw_active", "b")
     on-init { info("a->b") }
 }
 task status.bb {
-    require-path-on-device("/", "/dev/mmcblk0p3")
+    require-path-on-device("/", "/dev/mmcblk1p3")
     require-uboot-variable(uboot-env, "nerves_fw_active", "b")
     on-init { info("b") }
 }
 task status.ba {
-    require-path-on-device("/", "/dev/mmcblk0p3")
+    require-path-on-device("/", "/dev/mmcblk1p3")
     require-uboot-variable(uboot-env, "nerves_fw_active", "a")
     on-init { info("b->a") }
 }
diff --git a/fwup_include/fwup-common.conf b/fwup_include/fwup-common.conf
index 5b81a4e..fdbd300 100644
--- a/fwup_include/fwup-common.conf
+++ b/fwup_include/fwup-common.conf
@@ -15,8 +15,8 @@ define(NERVES_FW_PLATFORM, "bbb")
 define(NERVES_FW_ARCHITECTURE, "arm")
 define(NERVES_FW_AUTHOR, "Big Cove LLC")
 
-define(NERVES_FW_DEVPATH, "/dev/mmcblk0")
-define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk0p4") # Linux part number is 1-based
+define(NERVES_FW_DEVPATH, "/dev/mmcblk1")
+define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk1p4") # Linux part number is 1-based
 define(NERVES_FW_APPLICATION_PART0_FSTYPE, "f2fs")
 define(NERVES_FW_APPLICATION_PART0_TARGET, "/root")
 define(NERVES_PROVISIONING, "${NERVES_SYSTEM}/images/fwup_include/provisioning.conf")
diff --git a/rootfs_overlay/etc/erlinit.config b/rootfs_overlay/etc/erlinit.config
index 3794fd0..efa2294 100644
--- a/rootfs_overlay/etc/erlinit.config
+++ b/rootfs_overlay/etc/erlinit.config
@@ -60,8 +60,8 @@
 #       the history is loaded. If this mount fails due to corruption, etc.,
 #       nerves_runtime will auto-format it. Your applications will need to handle
 #       initializing any expected files and folders.
--m /dev/mmcblk0p1:/mnt/boot:vfat:ro,nodev,noexec,nosuid:
--m /dev/mmcblk0p4:/root:f2fs:nodev:
+-m /dev/mmcblk1p1:/mnt/boot:vfat:ro,nodev,noexec,nosuid:
+-m /dev/mmcblk1p4:/root:f2fs:nodev:
 -m tmpfs:/sys/fs/cgroup:tmpfs:nodev,noexec,nosuid:mode=755,size=1024k
 -m cpu:/sys/fs/cgroup/cpu:cgroup:nodev,noexec,nosuid:cpu
 -m memory:/sys/fs/cgroup/memory:cgroup:nodev,noexec,nosuid:memory
diff --git a/rootfs_overlay/etc/fw_env.config b/rootfs_overlay/etc/fw_env.config
index 465b66f..ab148a2 100644
--- a/rootfs_overlay/etc/fw_env.config
+++ b/rootfs_overlay/etc/fw_env.config
@@ -3,4 +3,4 @@
 # See fwup.conf for offset and size
 
 # Device name  Device offset   Env. size       Flash sector size       Number of sectors
-/dev/mmcblk0   0x100000        0x20000         0x200                   256
+/dev/mmcblk1   0x100000        0x20000         0x200                   256
diff --git a/uboot/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch b/uboot/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
index b463e47..006a285 100644
--- a/uboot/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
+++ b/uboot/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
@@ -1007,7 +1007,7 @@ index 00000000..a9d8f28d
 +              "echo Trying to boot Linux from eMMC ...; " \
 +              "setenv mmcdev 1; " \
 +              "setenv bootpart 1:2; " \
-+              "setenv mmcroot /dev/mmcblk0p2 rw; " \
++              "setenv mmcroot /dev/mmcblk1p2 rw; " \
 +              "run mmcboot;\0" \
 +      "emmc_android_boot=" \
 +              "setenv mmcdev 1; " \
diff --git a/uboot/uboot.env b/uboot/uboot.env
index 7d34ce0..1b8821f 100644
--- a/uboot/uboot.env
+++ b/uboot/uboot.env
@@ -89,11 +89,11 @@ nerves_init=\
     fi;\
     setenv bootfile zImage.${nerves_fw_active};\
     if test ${nerves_fw_active} = "a"; then\
-        setenv uenv_root /dev/mmcblk0p2;\
-        setenv bootpart 0:2;\
+        setenv uenv_root /dev/mmcblk1p2;\
+        setenv bootpart 1:2;\
     else\
-        setenv uenv_root /dev/mmcblk0p3;\
-        setenv bootpart 0:3;\
+        setenv uenv_root /dev/mmcblk1p3;\
+        setenv bootpart 1:3;\
     fi
 
 #
@@ -122,7 +122,7 @@ fdtdir=/boot
 fdtfile=undefined
 devtype=mmc
 # squashfs support is slow, so always load the kernel from FAT (FIXME)
-kernel_bootpart=0:1
+kernel_bootpart=1:1
 
 # Allocate memory for calls to dma_alloc_coherent. USB WiFi adapters
 # use this.

Here are the logs from two boots (Debian and Nerves):

####### Booting Nerves from eMMC ########
U-Boot SPL 2021.10 (Jul 13 2024 - 11:43:20 +0000)
Trying to boot from MMC2


U-Boot 2021.10 (Jul 13 2024 - 11:43:20 +0000)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM:  512 MiB
Reset Source: Power-on reset has occurred.
RTC 32KCLK Source: External.
WDT:   Started with servicing (60s timeout)
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from MMC… *** Warning - No block device, using default environment

Board: BeagleBone Black
<ethaddr> not set. Validating first E-fuse MAC
BeagleBone Black:
BeagleBone Cape EEPROM: no EEPROM at address: 0x54
BeagleBone Cape EEPROM: no EEPROM at address: 0x55
BeagleBone Cape EEPROM: no EEPROM at address: 0x56
BeagleBone Cape EEPROM: no EEPROM at address: 0x57
Net:   eth2: ethernet@4a100000
board_name=[A335BNLT] …
board_rev=[000C] …
switch to partitions #0, OK
mmc1(part 0) is current device
Scanning mmc 1:1…
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
Unknown command ‘bootefi’ - try ‘help’
switch to partitions #0, OK
mmc1(part 0) is current device
Checking for: /uEnv.txt …
Checking for: /boot/uEnv.txt …
Bad magic number for SquashFS image.
Bad magic number for SquashFS image.
** Invalid partition 5 **
Couldn’t find partition mmc 1:5
** Invalid partition 6 **
Couldn’t find partition mmc 1:6
** Invalid partition 7 **
Couldn’t find partition mmc 1:7
=> 
######### BOOTING DEBIAN ON eMMC ##########

U-Boot SPL 2022.04-ge0d31da5 (Aug 04 2023 - 18:48:26 +0000)
Trying to boot from MMC2


U-Boot 2022.04-ge0d31da5 (Aug 04 2023 - 18:48:26 +0000)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM:  512 MiB
Reset Source: Power-on reset has occurred.
RTC 32KCLK Source: External.
Core:  150 devices, 14 uclasses, devicetree: separate
WDT:   Started wdt@44e35000 with servicing (60s timeout)
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from EXT4… Board: BeagleBone Black
<ethaddr> not set. Validating first E-fuse MAC
BeagleBone Black:
BeagleBone Cape EEPROM: no EEPROM at address: 0x54
BeagleBone Cape EEPROM: no EEPROM at address: 0x55
BeagleBone Cape EEPROM: no EEPROM at address: 0x56
BeagleBone Cape EEPROM: no EEPROM at address: 0x57
Net:   eth2: ethernet@4a100000, eth3: usb_ether
Press SPACE to abort autoboot in 0 seconds
board_name=[A335BNLT] …
board_rev=[000C] …
gpio: pin 56 (gpio 56) value is 0
gpio: pin 55 (gpio 55) value is 0
gpio: pin 54 (gpio 54) value is 0
gpio: pin 53 (gpio 53) value is 1
switch to partitions #0, OK
mmc1(part 0) is current device
Scanning mmc 1:1…
libfdt fdt_check_header(): FDT_ERR_BADMAGIC
e7e[re[999;999He[6ne8Scanning disk mmc@48060000.blk…
Disk mmc@48060000.blk not ready
Scanning disk mmc@481d8000.blk…
Found 2 disks
No EFI system partition
BootOrder not defined
EFI boot manager: Cannot load any image
gpio: pin 56 (gpio 56) value is 0
gpio: pin 55 (gpio 55) value is 0
gpio: pin 54 (gpio 54) value is 0
gpio: pin 53 (gpio 53) value is 1
switch to partitions #0, OK
mmc1(part 0) is current device
gpio: pin 54 (gpio 54) value is 1
Checking for: /uEnv.txt …
Checking for: /boot/uEnv.txt …
gpio: pin 55 (gpio 55) value is 1
1737 bytes read in 3 ms (565.4 KiB/s)
Loaded environment from /boot/uEnv.txt
Checking if uname_r is set in /boot/uEnv.txt…
gpio: pin 56 (gpio 56) value is 1
Running uname_boot …
loading /boot/vmlinuz-5.10.168-ti-r71 …
11342336 bytes read in 715 ms (15.1 MiB/s)
debug: [enable_uboot_overlays=1] …
debug: [enable_uboot_cape_universal=1] …
debug: [uboot_base_dtb_univ=am335x-boneblack-uboot-univ.dtb] …
uboot_overlays: [uboot_base_dtb=am335x-boneblack-uboot-univ.dtb] …
uboot_overlays: Switching too: dtb=am335x-boneblack-uboot-univ.dtb …
loading /boot/dtbs/5.10.168-ti-r71/am335x-boneblack-uboot-univ.dtb …
210757 bytes read in 17 ms (11.8 MiB/s)
Found 0 extension board(s).
uboot_overlays: [fdt_buffer=0x60000] …
uboot_overlays: loading /boot/dtbs/5.10.168-ti-r71/overlays/BB-ADC-00A0.dtbo …
645 bytes read in 4 ms (157.2 KiB/s)
uboot_overlays: loading /lib/firmware/BB-BONE-AUDI-02-00A0.dtbo …
3404 bytes read in 9 ms (369.1 KiB/s)
uboot_overlays: loading /boot/dtbs/5.10.168-ti-r71/overlays/BB-BONE-eMMC1-01-00A0.dtbo …
1605 bytes read in 4 ms (391.6 KiB/s)
uboot_overlays: uboot loading of [BB-HDMI-TDA998x-00A0.dtbo] disabled by /boot/uEnv.txt [disable_uboot_overlay_video=1]…
loading /boot/initrd.img-5.10.168-ti-r71 …
7719588 bytes read in 493 ms (14.9 MiB/s)
debug: [console=ttyS0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk1p1 ro rootfstype=ext4 rootwait coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet] …
debug: [bootz 0x82000000 0x88080000:75caa4 88000000] …
Kernel image @ 0x82000000 [ 0x000000 - 0xad1200 ]
## Flattened Device Tree blob at 88000000
   Booting using the fdt blob at 0x88000000
   Loading Ramdisk to 8f8a3000, end 8ffffaa4 … OK
   Loading Device Tree to 8f80b000, end 8f8a2fff … OK

Starting kernel …

[    0.152114] l3-aon-clkctrl:0000:0: failed to disable
[    9.645852] debugfs: Directory ‘49000000.dma’ with parent ‘dmaengine’ already present!
[    9.678658] gpio-of-helper ocp:cape-universal: Failed to get gpio property of ‘P8_03’
[    9.678686] gpio-of-helper ocp:cape-universal: Failed to create gpio entry
[   10.091984] mdio_bus 4a101000.mdio: mii_bus 4a101000.mdio couldn’t get reset GPIO
[   10.284377] omap_voltage_late_init: Voltage driver support not added


Debian GNU/Linux 11 BeagleBone ttyS0

BeagleBoard.org Debian Bullseye IoT Image 2023-09-02
Support: https://bbb.io/debian
default username:password is [debian:temppwd]

BeagleBone login:
1 Like

A quick update:

First, thank you to @fhunleth for the pointers which got me unstuck!

Additionally, I was able to get this working and now have an easy way to flash the eMMC on BBBs. I have created two repositories to show how this all works. There is a new Nerves System Nerves System BBB eMMC that can only run on the eMMC. There is also a Flashing Repo that without any modification will flash an “empty” Nerves project onto the eMMC. Then you can use OTA update methods from then on.

After this is “proved out” for a little bit I would like to see this brought into the official Nerves repos and I see a few of ways to do this:

  1. Change the existing nerves_system_bbb to only support eMMC booting. Actually there could be documentation for uSD support but would not be the default.
  2. Add documentation/script to modify the nerves_system_bbb to target the eMMC. This complicates the system maintenance but is maybe viable.
  3. Add an additional system nerves_system_bbb_emmc. This would require maintaining an additional system.

Please let me know if you use any of this and if it works or doesn’t work for you and your thoughts on long term support.

Since the official Nerves systems are used for an out-of-the box experience, and most people needing eMMC are probably changing the device tree and other things that require forking the repo, I think option 1 should be avoided.

Option 2 sounds favorable, and there may be ways not to complicate the system too much. For example, a lot of the changes look like they’re to config files. Borrowing from Linux practices, both configurations could be added, with eMMC commented out. To make the eMMC config easier to find, it could be tagged with a value that’s easily found with rgrep.

# BBB-EMMC: Use `mmcblk1p1` for eMMC boot, `mmcblk0p1` for SD boot
-m /dev/mmcblk0p1:/mnt/boot:vfat:ro,nodev,noexec,nosuid:
#-m /dev/mmcblk1p1:/mnt/boot:vfat:ro,nodev,noexec,nosuid:

This comment may be easy enough to understand that the commented code isn’t required.

Since fwup can both define variables and include other files, one or both of these methods could be used to switch between the SD and eMMC fwup configs. Another way could be to add a Buildroot package in the BBB Nerves system that adds a setting for SD/eMMC fwup configs, and then copy the corresponding ones to BINARIES_DIR based on that setting. Then remove copying the fwup config from post-build.sh.

The U-Boot defconfig changes could either go in the readme, or create uboot-emmc.defconfig and uboot-emmc.env, which can easily be changed in nerves_defconfig (BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE and BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE).

Hopefully this approach leverages the existing tooling, avoids complex scripting, and keeps the maintenance burden low.