A UART Boot adventure
From dead SD slot to UART boot December 2025, I need a small board for my N2K testbed, something like a BeagleBoneBlack. Since these boards are pretty much indestructible, I decide to buy one second-hand for next to nothing. I find one at a giveaway price because the SD slot is dysfunctional. No problem, I have the gear for soldering/desoldering and the slot costs about 5 euros. It’s an Industrial BB Black. No real use for it in my workshop, but it doesn’t hurt. So I buy the industrial BBB for about ten euros and a new SD slot. Objective: replace the SD slot and boot a fresh system. The board looks in excellent condition, and there’s no sign that the SD slot is dead, at least to the naked eye. Because at boot, it’s impossible to boot from the SD card. The ROM code boots over UART. Even by pressing on the slot, no SD card is detected. I then replace the SD slot. SD card type: Even after soldering the new slot, impossible to boot from the SD card. Attempt with a classic Debian image, with an MLO and u-boot.img extracted from an image that works on my other BeagleBone Black. Nothing works, the SD card won’t be recognized. I change the SD card, same result: the ROM didn’t find a valid image on SD/eMMC, it switches to UART boot and emits ‘C’ (XMODEM). SD slots have a pin dedicated to SD card detection. Maybe this one is dysfunctional. I find the relevant pin in the BBB doc and I see that it correctly goes to ground when the card is inserted. So it’s working fine. Hypotheses: is the SD slot badly soldered or defective? Or is the problem elsewhere? Despite the new solder and an SD card prepared with love, the result is final: the serial console remains silent at startup (or doesn’t display the bootloader). The SD slot is still not operational. Instead of obsessing over the hardware, I decide to bypass the problem: if the board won’t read the SD, I’m going to inject the code directly into its veins via UART. As for my probes, I now use tio, which is very handy. I like to know what’s happening on the serial port when I transfer data. For that, So we have socat holding the /dev/ttyUSB0 in a sandwich and creating an interface on /tmp/vtty that tio will use. OK, so everything is ready to launch the XMODEM/YMODEM protocol. I created my u-boot image and its SPL with official u-boot tools, using I use The transfer is successful. But on the socat side, we see messages from the CPU signaling serial failures. I manage to initialize the sending procedure of the u-boot image by My tio config seems correct: 115200 baud, 8 data bits, 1 stop bit, no parity. After checking my power supply, switching to my lab supply, changing cables, doing a meticulous check of the solder joints, I decide to dig deeper into the injected file. Since a hexdump is always instructive, I decide to dissect the head of the MLO. Interesting. We clearly see some kind of header, relatively empty lines, many identical lines [0x20 to 0x40], [0x50 to 0x200]. But above all, a visual break: at line 0x200, life begins. An entry point, then A simple search for The processor didn’t reject the If it’s not the MLO that we must send to the ROM code, I’ll have to find the messenger. After some well-targeted research, I come across the Texas Instruments doc about OK, u-boot is alive! My SD card is well recognized and the eMMC is empty. Perfect! I looked for a complex solution when the acronym was whispering that I wasn’t on the right device: indeed MLO stands for MultiMediaCard Load Object. MMCs are for SD cards and eMMCs. My mistake was mixing up UART boot and SD boot, and therefore using the MLO as a raw SPL. And this was confirmed by several LLMs (Claude Code, Gemini and Grok). As for the SD card, the mystery remains: the hardware was working, but the ROM code refused to load this MLO from the SD, even though it was valid. This first UART boot brought me a lot. Here are the lessons I’ve learned: Beware of AI for low-level: Models often confuse use cases (SD vs UART). Know what you’re sending: Always ask “Who’s going to read this file?” (A file system or the RAM directly?). The importance of raw logs: Without the serial port, the board would have ended up in the trash. Docs & Logs are the only truths. Next step: get a “ROM-native” SD boot. The SD is readable (U-Boot sees mmc 0), so I’m going to test a forced SD boot with eMMC neutralized and a reconstructed FAT where MLO is copied first, to check for a ROM constraint rather than a hardware problem.The board
Reception and first boot
SD card build
MLC 8GB Gigastone, quite robust on my various builds. They’ve never let me down.sudo mkfs.vfat -F 32 -n "BOOT_SD" /dev/sdc1
mkfs.fat 4.2 (2021-01-31)
sudo mkfs.ext4 -L "ROOT_SD" /dev/sdc2
mke2fs 1.47.3 (8-Jul-2025)
Creating filesystem with 1924608 4k blocks and 481440 inodes
Filesystem UUID: 0a157080-1f28-410c-9fdc-21849815d136
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
Allocating group tables: done
Writing inode tables: done
Creating journal (16384 blocks):
done
Writing superblocks and filesystem accounting information: done
sudo mount /dev/sdc1 /mnt/alpha
file MLO
MLO: data
du -sh MLO
96K MLO
file u-boot.img
u-boot.img: Device Tree Blob version 17, size=3708, boot CPU=0, string block size=150, DT structure block size=3500
du -sh u-boot.img
1.4M u-boot.img
sudo cp MLO /mnt/alpha
sudo cp u-boot.img /mnt/alpha
sync /mnt/alpha
sudo umount /mnt/*
sudo fdisk -l /dev/sdc
Disk /dev/sdc: 7.44 GiB, 7989100544 bytes, 15603712 sectors
Disk model: Mass-Storage
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7d7ae755
Device Boot Start End Sectors Size Id Type
/dev/sdc1 * 2048 206847 204800 100M c W95 FAT32 (LBA)
/dev/sdc2 206848 15603711 15396864 7.3G 83 Linux
False victory
Preparing the ground for UART
socat is perfect. It creates a middleman quite simply. The only problem is that it releases the targeted port with difficulty. It’s sometimes necessary to make it spit it out with fuser -k -9 <serial port>.[BBB UART] <---> [/dev/ttyUSB0] <---> [SOCAT] <---> [/tmp/vtty] <---> [TIO]socat
socat -v /dev/ttyUSB0,raw,echo=0 PTY,link=/tmp/vtty,raw,echo=0,unlink-early=1,unlink-close=1
C> 2026/02/11 15:15:56.000376128 length=1 from=0 to=0
C> 2026/02/11 15:15:57.000176133 length=1 from=1 to=1
C> 2026/02/11 15:15:57.000459264 length=1 from=2 to=2
C> 2026/02/11 15:15:57.000859289 length=1 from=3 to=3tio
tio -b 115200 /tmp/vtty
[15:16:05.858] tio c43d2f6
[15:16:05.858] Press ctrl-a q to quit
[15:16:05.858] Connected to /tmp/vtty
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCThe wall
am335x_evm_defconfig and the arm-linux-gnueabihf toolchain. tio perfectly integrates XMODEM and YMODEM protocols. I then move to my u-boot folder and launch the hostilities.XMODEM-CRC send and select the MLO file, which serves as my SPL when I boot with my SDs or when I flash to eMMC.tio -b 115200 /tmp/vtty
[10:00:06.585] tio c43d2f6
[10:00:06.585] Press ctrl-a q to quit
[10:00:06.585] Connected to /tmp/vtty
CCCCC
[10:00:08.525] Please enter which X modem protocol to use:
[10:00:08.525] (0) XMODEM-1K send
[10:00:08.525] (1) XMODEM-CRC send
[10:00:08.525] (2) XMODEM-CRC receive
[10:00:09.237] Send file with XMODEM-CRC
[10:00:10.949] Sending file 'MLO'
[10:00:10.949] Press any key to abort transfer
................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................|
[10:00:23.952] Done
.j.].|..........n6~UNt^...>....Bypassing DPLL failed 0x%x
.DPLL locking failed for 0x%x
.Clock enable failed for 0x%p idlest 0x%x
._.> 2026/02/12 10:00:21.000648910 length=1 from=870 to=870
.< 2026/02/12 10:00:21.000648993 length=133 from=82220 to=82352
.k.DDR3 H/W leveling incomplete with errors
.ti-musb-peripheral.ti-musb-host.gpio_omap.i2c_omap.ns16550_serial.resetting ...
.A335B..> 2026/02/12 10:00:21.000665928 length=1 from=871 to=871
.< 2026/02/12 10:00:21.000666032 length=133 from=82353 to=82485
.l.ONE.A33515BB.SKU#02.A335X_SK.A335BNLT.A335PBGL.A335_ICE.Bad EEPROM or unknown board, cannot configure pinmux..No AC power, switc.}> 2026/02/12 10:00:21.000682981 length=1 from=872 to=872
.< 2026/02/12 10:00:21.000683062 length=133 from=82486 to=82618
.m.hing to default OPP
.ti_i2c_eeprom_init failed
.boot_os.1.5.00A1.tps65217_reg_write failure
.tps65217_voltage_update failure
.BBU.> 2026/02/12 10:00:21.000699980 length=1 from=873 to=873
.< 2026/02/12 10:00:21.000700082 length=133 from=82619 to=82751
.n.G1.ddr_vtt_en.am335x-evm.am335x-bone.am335x-boneblack.am335x-pocketbeagle.am335x-evmsk.am335x-bonegreen.am335x-icev2.am335x-sanc.A> 2026/02/12 10:00:21.000716995 length=1 from=874 to=874
.< 2026/02/12 10:00:21.000717086 length=133 from=82752 to=82884
.o.loud-bbe-lite.am335x-sancloud-bbe-extended-wifi.am335x-sancloud-bbe.omap_hsmmc.eth_cpsw.ti,am3352-cpsw-phy-sel.cpsw,am33xx.fdt_r..> 2026/02/12 10:00:21.000733999 length=1 from=875 to=875
.< 2026/02/12 10:00:21.000734084 length=133 from=82885 to=83017
.p.oot: %s
.SPL: fdt_shrink_to_minimum err - %d
.SPL: arch_fixup_fdt err - %d
.U-Boot.Trying to boot from %s
.SPL: Unsupported BootM.> 2026/02/12 10:00:21.000750990 length=1 from=876 to=876
.< 2026/02/12 10:00:21.000751074 length=133 from=83018 to=83150
.q. Device!
.SPL: failed to boot from all boot devices
.
U-Boot SPL 2024.01 (Feb 11 2026 - 11:56:32 +0000)
.Can't load %s: No load %y> 2026/02/12 10:00:21.000768120 length=1 from=877 to=877
.< 2026/02/12 10:00:21.000768219 length=133 from=83151 to=83283
.r.address and no buffer
.%s: Skip load '%s': image size is 0!
.Cannot get image data/size
.fdt./images.kernel.loadables.%s: can't .l> 2026/02/12 10:00:21.000785619 length=1 from=878 to=878
.< 2026/02/12 10:00:21.000785757 length=133 from=83284 to=83416
.s.load image loadables index %d (ret = %d)
.load_simple_fit.spl_load_simple_fit.spl: ymodem err - %s
.Loaded %lu bytes
.UART.The E.F> 2026/02/12 10:00:21.000802844 length=1 from=879 to=879
.< 2026/02/12 10:00:21.000802942 length=133 from=83417 to=83549
.t.xpected Linux image was not found. Please check your NAND configuration.
.Trying to start u-boot now...
.NAND.yes.autoload.No Et.9> 2026/02/12 10:00:21.000820149 length=1 from=880 to=880
.< 2026/02/12 10:00:21.000820239 length=133 from=83550 to=83682
.u.hernet devices found
.ethact.Problem booting with BOOTP
.usb_ether.USB eth.eth device.architecture.compression.operating system.!4> 2026/02/12 10:00:21.000837199 length=1 from=881 to=881
YMODEM on the serial port via tio, but no follow-up and especially, no sign of life on socat, except for the console inputs. As can be read in the boot attempt, the SPL dies and fails to initialize the memory needed for u-boot.img.The click
hexdump -C MLO | head -n 20
00000000 40 00 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 |@...............|
00000010 00 00 00 00 43 48 53 45 54 54 49 4e 47 53 00 00 |....CHSETTINGS..|
00000020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000040 c1 c0 c0 c0 00 01 00 00 00 00 00 00 00 00 00 00 |................|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000200 d8 75 01 00 00 04 2f 40 0f 00 00 ea 14 f0 9f e5 |.u..../@........|
00000210 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................|
00000220 14 f0 9f e5 14 f0 9f e5 40 04 2f 40 40 04 2f 40 |........@./@@./@|
00000230 40 04 2f 40 40 04 2f 40 40 04 2f 40 40 04 2f 40 |@./@@./@@./@@./@|
00000240 40 04 2f 40 ef be ad de fe ff ff ea 2d 03 00 ea |@./@........-...|
00000250 00 00 0f e1 1f 10 00 e2 1a 00 31 e3 1f 00 c0 13 |..........1.....|
00000260 13 00 80 13 c0 00 80 e3 00 f0 29 e1 10 0f 11 ee |..........).....|
00000270 02 0a c0 e3 10 0f 01 ee 98 00 9f e5 10 0f 0c ee |................|
00000280 06 00 00 eb 22 00 00 eb 1e 04 00 eb 15 0f 07 ee |...."...........|
14 f0 9f e5 patterns that remind me of assembly.CHSETTINGS on Kagi was enough to land on a Texas Instruments forum mentioning the 0x200-byte header. So it’s confirmed, MLO is not UART friendly. https://e2e.ti.com/support/processors-group/processors/f/processors-forum/207888/description-of-the-chsettings-headerMLO file, it tried to execute the graphic/binary header as code!Cutting the header
u-boot and UART. Marvelous! And we can read: “In some cases we support loading SPL and U-Boot over the console UART. You will need to use the spl/u-boot-spl.bin and u-boot.img files to boot.” The Uart ROM expects u-boot-spl.bin and not MLO, which is a MultiMediaCard Load Object. MLO is nothing more than u-boot-spl.bin to which a header has been added. A simple fd -HI -e bin u-boot-spl command allows me to locate the u-boot-spl.bin. The rest is absolutely smooth.[10:02:28.843] Connected to /tmp/vtty
CCCCCCCCCCCCCCCC
[10:15:04.937] Please enter which X modem protocol to use:
[10:15:04.937] (0) XMODEM-1K send
[10:15:04.937] (1) XMODEM-CRC send
[10:15:04.937] (2) XMODEM-CRC receive
[10:15:05.956] Send file with XMODEM-CRC
[10:15:12.937] Sending file 'spl/u-boot-spl.bin'
[10:15:12.937] Press any key to abort transfer
............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................|
[10:15:25.855] Done
U-Boot SPL 2024.01 (Feb 11 2026 - 11:56:32 +0000)
Trying to boot from UART
CC
[10:15:42.173] Send file with YMODEM
[10:15:46.120] Sending file 'u-boot.img'
[10:15:46.120] Press any key to abort transfer
............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................|
[10:18:04.924] Done
Loaded 1452836 bytes
U-Boot 2024.01 (Feb 11 2026 - 11:56:32 +0000)
CPU : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM: 512 MiB
Core: 160 devices, 18 uclasses, devicetree: separate
WDT: Started wdt@44e35000 with servicing every 1000ms (60s timeout)
NAND: 0 MiB
MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from FAT... ** Bad device specification mmc 0 **
<ethaddr> not set. Validating first E-fuse MAC
Net: eth2: ethernet@4a100000using musb-hdrc, OUT ep1out IN ep1in STATUS ep2in
MAC de:ad:be:ef:00:01
HOST MAC de:ad:be:ef:00:00
RNDIS ready
, eth3: usb_ether
Hit any key to stop autoboot: 0
...
=>=> mmc info
Device: OMAP SD/MMC
Manufacturer ID: fe
OEM: 4e
Name: P1XXXX
Bus Speed: 48000000
Mode: MMC High Speed (52MHz)
Rd Block Len: 512
MMC version 4.5
High Capacity: Yes
Capacity: 3.6 GiB
Bus Width: 8-bit
Erase Group Size: 512 KiB
User Capacity: 3.6 GiB
Boot Capacity: 16 MiB ENH
RPMB Capacity: 128 KiB ENH
Boot area 0 is not write protected
Boot area 1 is not write protected
=> ls mmc 1:1
0 file(s), 0 dir(s)
=> ls mmc 1:2
<DIR> 4096 .
<DIR> 4096 ..
<DIR> 16384 lost+found
=> mmc dev 0
switch to partitions #0, OK
mmc0 is current device
=> mmc info
Device: OMAP SD/MMC
Manufacturer ID: 0
OEM: 3432
Name: 00000
Bus Speed: 48000000
Mode: SD High Speed (50MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 7.4 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
=> ls mmc 0:0
=> ls mmc 0:1
70112 am335x-boneblack.dtb
66650 am335x-bone.dtb
66878 am335x-bonegreen.dtb
extlinux/
110016 MLO
1450036 u-boot.img
8632336 zImage
6 file(s), 1 dir(s)
=>
Conclusion