If cape EEPROM part number field contains a space+number the number is interpreted as /init runlevel (lol)

Cautionary tale for cape makers. This would almost be amusing if my customers weren’t getting bricked by it.

So these days the cape EEPROM part number field ends up in the kernel command line as an argument to the uboot_detected_capes= parameter, e.g.

Kernel command line: ... bone_capemgr.uboot_capemgr_enabled=1 ... uboot_detected_capes=[cape_part_number] , ...

This has interesting consequences.

My product uses a BBG/BBB and a cape. The original product was called XYZ. We now have a second version and the “marketing” name for it is “XYZ 2” (note the embedded space). So silly me decided to change the code that writes the cape EEPROM to put “XYZ 1” or “XYZ 2” into the part number field instead of the previous “XYZ”. Because, you know, the cape spec says “ASCII characters, up to the maker of the board” (I almost used an underscore instead of a space).

This works fine with Debian 8 which a lot of our users still run (yeah, I know…) Recently I released a D11.9 flasher image so people could upgrade. The “XYZ 2” customers had no problems. The “XYZ 1” customers got bricked.

Incredibly, here’s what’s happening. If there’s a number after the space it’s getting interpreted as the runlevel arg to /init. Because the kernel command line ends up looking like:
Kernel command line: ... uboot_detected_capes=XYZ 1 , ...
And according to Debian man page kernel-command-line(7) the digit “1” is compatibility for systemd.unit=rescue.target. And you know what happens then! That’s right, rescue mode. Serial console only. Ethernet disabled. Bricked.

“2” is okay because it’s compatibility for systemd.unit=runlevel2.target which proceeds, by chance, normally.

Here’s the relevant serial console stuff:

debug: [console=ttyS0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk1p1 ro rootfstype=ext4 rootwait uboot_detected_capes=XYZ 1 , coherent_pool=1M net.ifnames=0 lpj=1990656 
rng_core.default_quality=100 quiet]
[    0.000000] Kernel command line: console=ttyS0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk1p1 ro rootfstype=ext4 rootwait uboot_detected_capes=XYZ 1 , coherent_pool=1M 
net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet
[    9.227312] Run /init as init process
[    9.227328]   with arguments:
[    9.227336]     /init
[    9.227343]     1
[    9.227349]     ,
[    9.227355]   with environment:
[    9.227362]     HOME=/
[    9.227369]     TERM=linux
[    9.227375]     uboot_detected_capes=XYZ
3 Likes