Resolving SIMATIC IOT2050 Advanced UUID Conflict on SD Card Boot

David Krause14 min read
PLC HardwareSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

1. Problem Summary

On the SIMATIC IOT2050 Advanced (MLFB 6ES7647-0BA00-1YA2), an attempt to boot Industrial OS (IndOS) from an SD card while the same IndOS image remains installed on the internal eMMC triggers a hard stop in SE-Boot/U-Boot. The boot process prints ** uuid conflict: 109a8c08-01 ** inside the uuid conflict check begin/end block, halts before Linux handover, and the STAT LED stays solid red. Booting the official Example Image (Debian) from the same SD card does not trigger the check, which proves the conflict is image-specific, not hardware-related.

The check is a deliberate safety mechanism in SE-Boot that detects two root file systems with identical partition UUIDs and refuses to mount the duplicate. It exists to prevent two identically-provisioned OS instances from being mounted on the same node and corrupting each other, but it blocks legitimate field-replacement workflows where the eMMC must be retired.

Affected hardware: SIMATIC IOT2050 Advanced, MLFB 6ES7647-0BA00-1YA2 (PG-IOT-BASIC-DK1 / IOT2050-ADVANCED board variant).
Affected firmware: SE-Boot D01.00.00.09 with U-Boot 2019.01-V01.00.00.2 (build Mar 18 2020). The check is present on every published SE-Boot variant for the IOT2050 Advanced.
Trigger condition: Two bootable media (eMMC + SD, or eMMC + USB) containing the same IndOS image with matching rootfs PARTUUIDs.

2. Device Identification and Firmware Inventory

Capture the full banner on the UART console (115200 8N1) before troubleshooting. The values below identify the affected firmware state in this case:

Field Value
Board IOT2050-ADVANCED
MLFB 6ES7647-0BA00-1YA2
SKU SE
SE-Boot version D01.00.00.09-0-g9827cee9-0x0000
Build date 20200317
U-Boot 2019.01-V01.00.00.2-0-g8e86139 (Mar 18 2020)
BL31 (ATF) v2.1(release):v2.1-421-g996d37930-dirty
OP-TEE 3.6.0-16-ge260ea8d-dev (gcc 8.3.0, Debian 8.3.0-2)
SYSFW ABI 2.9 [version: 19] [19.12.1-v2019.12a (Terrific Lla]
AVS class 0 [1100 1200 1200]
DRAM 2 GiB
Device UUID (DUT) F4DA45F37027464ABB6382BD740784D5
A5E A5E452229880AA05
MAC[0] 8c-f3-19-34-8b-05
MAC[1] 8c-f3-19-34-8b-06
Security ID 0x5125e53f-0x842e215d
Security policy soft
Board serial N8BU0177

The hardware identification is from the SE-Boot banner; the SE-Boot/U-Boot pairing is the firmware layer that performs the UUID check. The Device UUID in the banner is the hardware UUID of the SoM and is unrelated to the rootfs PARTUUID that causes the conflict.

3. Root Cause: Why the UUID Check Triggers

The conflict is not a true UUID collision in the cryptographic sense. The probability of an accidental UUID v4 collision is approximately 1 in 2^122 per draw — the odds are effectively zero for two independent generations on the same device, and even for two devices worldwide the chances of accidental duplication are negligible as described in the Universally unique identifier reference and the tc39 proposal-uuid issue #15 discussion on UUID v1 vs. v4 collision probability.

The IOT2050 SE-Boot UUID check is a different mechanism: it reads the GPT PARTUUID of the rootfs partition on every bootable device (mmc0, mmc1, usb0, usb1, usb2) and aborts if two of them share the same PARTUUID. The 109a8c08-01 string in the error is the GPT partition GUID of the IndOS rootfs partition. When Siemens ships the IndOS image, the same image is cloned bit-for-bit onto every SD card and every eMMC pre-installed on the device. Because the partition table is part of the image, the PARTUUID of the rootfs is identical across every media containing that image.

Concretely, the U-Boot script runs roughly as follows during boot:

  1. Read the active boot target from boot_targets U-Boot environment (default: usb0 usb1 usb2 mmc0 mmc1 after the field change).
  2. Iterate over the configured targets and read the GPT partuuid of partition 1 (rootfs) on each.
  3. Compare all collected PARTUUIDs; if any pair matches, print ** uuid conflict: <partuuid> ** and halt before bootcmd runs.

This is why swapping the SD card between two IOT2050 units does not resolve the issue — the conflict is between the SD card and the eMMC on the same unit, not between the two units.

Key distinction: The rootfs PARTUUID (e.g. 109a8c08-01) is the value the SE-Boot script compares. The Device UUID (e.g. F4DA45F37027464ABB6382BD740784D5) printed in the banner is a hardware identifier burned into the SoM and is not used in this check. Do not confuse the two.

4. The Boot Sequence and UUID Check Location

Understanding where the check fires helps you choose the right workaround. The complete boot chain on the IOT2050 Advanced is:

  1. ROM on AM6548 SoC loads SE-Boot (BL1/BL2) from SPI NOR (w25q128, 16 MiB).
  2. SE-Boot verifies the signature chain (PK, custMpk, SHA-256/RSA-4096) and loads BL31 (ATF), OP-TEE, and U-Boot.
  3. U-Boot SPL (2019.01-V01.00.00.2) initializes DDR and re-enters U-Boot proper.
  4. U-Boot reads environment from SPI flash, scans boot targets, and runs uuid_conflict_check from conf-iot2050-advanced.
  5. If the check passes, U-Boot loads the kernel, dtb, and rootfs from the selected device and hands control to Linux.

The conflict check sits between U-Boot environment load and kernel boot. There is no Linux-level fix that can rescue the boot; the halt happens before bootcmd runs, which is why systemctl enable regen-rootfs-uuid-on-first-boot cannot help — it is a Linux systemd unit, and Linux never starts.

5. Service Stick Wizard and Image Layout

The Service Stick is a USB stick with the Siemens service image used to write OS images to the IOT2050. The wizard performs these operations:

  • Detects IOT2050 over USB-CDC Ethernet.
  • Reads the target MLFB and SKU to select the correct image family (Basic vs. Advanced).
  • Writes the image to the selected media using dd + GPT partition copy, preserving the original PARTUUID of the cloned image.
  • Optionally expands the rootfs partition and filesystem to fill the target media.

Because the wizard does not regenerate the rootfs PARTUUID by default, every IndOS write — whether to eMMC or to SD card — produces a media with the same 109a8c08-01 PARTUUID. This is the design assumption behind the SE-Boot conflict check: the bootloader assumes a unique PARTUUID per device is normal and treats a duplicate as an error condition.

The Example Image (Debian) does not trigger the conflict because it uses a different rootfs PARTUUID scheme that is regenerated by the Example Image's first-boot script, so two writes of the Example Image on two media do not collide.

6. Solution A: Clear the Internal eMMC Memory

The supported resolution is to remove IndOS from the eMMC so that only one IndOS instance exists at a time. Perform the following steps. The procedure requires the UART cable (Siemens 6AV7670-0XA00-0AA0 or compatible 3.3 V TTL USB-UART at 115200 8N1) and the Service Stick.

6.1 Prerequisites

  • Functional IndOS image already booted from internal eMMC (the system that prints the Failed to enable unit: Unit file regen-rootfs-uuid-on-first-boot.service does not exist message).
  • IndOS installed and verified on the target SD card.
  • Boot order set to usb0 usb1 usb2 mmc0 mmc1 in U-Boot environment.
  • Service Stick available for re-installation.
  • Console access via PuTTY or equivalent at 115200 8N1.

6.2 Procedure

  1. Power off the IOT2050 and leave the SD card with IndOS inserted.
  2. Power on while pressing Esc or any key to interrupt autoboot and enter the U-Boot prompt.
  3. Verify boot targets:
    fw_printenv boot_targets
    Expected output: boot_targets=usb0 usb1 usb2 mmc0 mmc1. If not set, run:
    fw_setenv boot_targets usb0 usb1 usb2 mmc0 mmc1
  4. Reset the device and boot back into the eMMC IndOS (you may need to physically remove the SD card to force eMMC boot, or temporarily change boot_targets to mmc0).
  5. From the eMMC IndOS shell, identify the eMMC device:
    lsblk -o NAME,SIZE,MODEL,PARTUUID
    Confirm that the eMMC is /dev/mmcblk0 with the offending rootfs PARTUUID 109a8c08-01.
  6. Wipe the GPT and rootfs on the eMMC so the SE-Boot script can no longer read a matching PARTUUID:
    sudo dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=50 status=progress
    This zeroes the first 50 MiB (well past the GPT backup at the end of the disk) and breaks the partition table.
  7. Optionally, to be thorough, wipe the GPT backup at the end:
    sudo sgdisk --zap-all /dev/mmcblk0
  8. Verify the eMMC is no longer readable:
    sudo blkid /dev/mmcblk0p1 should return nothing.
  9. Power off, re-insert the SD card with IndOS, and boot normally.
  10. Confirm the SE-Boot UUID check passes:
    Console should now show ====== uuid conflict check begin ====== and ====== uuid conflict check end ====== without a ** uuid conflict line.

6.3 What NOT to Do

  • Do not attempt to run systemctl enable regen-rootfs-uuid-on-first-boot. This unit does not exist on IndOS images as shipped. The service was a Linux-level idea proposed by some users, but the conflict fires before Linux starts, so the unit can never execute.
  • Do not swap SD cards between two IOT2050 units hoping the error changes. The error follows the image PARTUUID, not the hardware UUID.
  • Do not flash a custom U-Boot binary to disable the check. SE-Boot is signed; an unsigned image is rejected by the ROM and the device will not boot.
Data loss warning: Wiping the eMMC is irreversible. Confirm that your application configuration, certificates, and project files are all on the SD card before issuing dd or sgdisk --zap-all.

7. Solution B: Use the Example Image as a Bridge

If you cannot boot from eMMC at all — for example, because the eMMC is already corrupted — boot the Example Image from the SD card and use it to clear the eMMC.

  1. Create a bootable Example Image SD card with the Service Stick wizard by selecting Example Image instead of Industrial OS.
  2. Boot the IOT2050 from the Example Image. SE-Boot does not report a UUID conflict because the Example Image rootfs uses a regenerated PARTUUID.
  3. Log in as root (no password on first boot) over SSH or the UART console.
  4. Wipe the eMMC rootfs partition:
    dd if=/dev/zero of=/dev/mmcblk0p1 bs=1M followed by sgdisk --zap-all /dev/mmcblk0 to destroy the GPT.
  5. Power off, swap the SD card for the IndOS image, and boot normally.

This path is useful when the eMMC IndOS is unreachable but you still have a working Example Image write. Always validate that the SD card boots cleanly first with the Example Image before assuming the hardware is good.

8. Hardware Swap Strategy (Field Replacement)

The original use case — keeping the application on an SD card so a fitter can swap a defective IOT2050 by moving the SD card — is achievable, but it requires a one-time commissioning step on every replacement unit. Document the following procedure for the field fitter.

8.1 First-time commissioning of a replacement IOT2050

  1. Receive a new SIMATIC IOT2050 Advanced (same MLFB).
  2. Insert the Service Stick and the application SD card (with IndOS).
  3. Use the Service Stick wizard to install IndOS on the SD card (this writes the same image to a fresh SD card if needed).
  4. Boot once from the SD card, accept the failure, and boot the Example Image from a second SD card.
  5. From the Example Image, wipe the eMMC as described in Solution B.
  6. Remove the Example Image SD card, leave the application SD card inserted, and reboot.
  7. Verify normal operation.

8.2 Field swap procedure (for the fitter)

  1. Power off the defective IOT2050.
  2. Pull the SD card from the defective unit.
  3. Insert the SD card into the pre-commissioned spare IOT2050.
  4. Power on. The unit boots directly from the SD card with no further configuration.
Friendly advice: Pre-commission the spare unit with a wiped eMMC before storing it. A fitter should never need to run dd, sgdisk, or any shell command on the spare unit. The only action is "insert SD card, power on."

9. Boot Order Configuration Reference

The U-Boot environment variable boot_targets controls the search order used by SE-Boot and by U-Boot's bootcmd. The factory default is mmc1 mmc0 usb0 usb1 usb2. The field-recommended order, with USB first to ease Service Stick recovery, is shown below.

Priority Target Device Notes
1 usb0 USB 3.0 port X60 Service Stick
2 usb1 USB 3.0 port X61 Optional second USB
3 usb2 USB 2.0 internal / debug Internal header
4 mmc0 SD card slot External SD
5 mmc1 eMMC Onboard eMMC

Setting is persistent in SPI flash:

fw_setenv boot_targets usb0 usb1 usb2 mmc0 mmc1
fw_printenv boot_targets (verify)

To force the next boot from a specific media without changing the default order, set boot_once in U-Boot before boot:

setenv boot_once mmc1
boot

10. Verification Procedure

After clearing the eMMC, verify a clean boot from the SD card:

  1. Power on with the SD card inserted.
  2. Watch the UART console. The expected sequence is:
    ====== uuid conflict check begin ======
    switch to partitions #0, OK
    mmc1(part 0) is current device
    switch to partitions #0, OK
    mmc0 is current device
    ====== uuid conflict check end ======
  3. The check block must not contain a ** uuid conflict line.
  4. Continue to watch for Starting kernel ..., then the IndOS systemd banner.
  5. Log in and verify:
    lsblk -o NAME,SIZE,MODEL,PARTUUID,MOUNTPOINT
    The mounted rootfs should be /dev/mmcblk1p1 (SD card), and /dev/mmcblk0 should show no partitions (or, if you only zeroed the start, no mountable filesystem).
  6. Check that the IOT2050 Ethernet interfaces are up:
    ip link show should show eth0 with MAC 8c-f3-19-34-8b-05 and eth1 with 8c-f3-19-34-8b-06 (values from your hardware banner).

11. Troubleshooting Matrix

Symptom Likely cause Action
** uuid conflict: 109a8c08-01 ** in SE-Boot Same IndOS image on eMMC and SD card Wipe eMMC rootfs (Section 6.2)
STAT LED red, no console output Image on SD card corrupted or wrong SKU Re-flash with Service Stick, verify Advanced vs. Basic selection
Example Image boots, IndOS does not IndOS-specific PARTUUID collision Confirm IndOS is installed on both media and clear one
Failed to enable unit: Unit file regen-rootfs-uuid-on-first-boot.service does not exist Unit never shipped in IndOS Ignore the unit; conflict is solved by eMMC wipe, not systemd
Loading Environment from SPI Flash... OK followed by immediate halt boot_targets empty or invalid Reset environment: env default -a; saveenv in U-Boot
Boot hangs after resetting USB... USB stick drawing too much current Remove unpowered hubs; use a single short USB cable
Console reports Hash integrity ... sha256,rsa4096:custMpk+ OK but no U-Boot SPI flash image mismatch Reflash SE-Boot via Service Stick in rescue mode
SF: Detected w25q128 missing SPI NOR failed or unseated RMA the unit; do not attempt field repair of the NOR

12. Diagnostic Commands Quick Reference

Environment Command Purpose
U-Boot fw_printenv Dump all environment variables
U-Boot fw_setenv boot_targets usb0 usb1 usb2 mmc0 mmc1 Set boot search order
U-Boot env default -a; saveenv Reset environment to defaults
U-Boot part uuid mmc0 1 Read PARTUUID of partition 1 on mmc0
Linux lsblk -o NAME,SIZE,MODEL,PARTUUID,MOUNTPOINT Show all block devices and their PARTUUIDs
Linux blkid Show filesystem UUIDs (different from PARTUUID)
Linux sgdisk --zap-all /dev/mmcblk0 Destroy GPT on eMMC
Linux dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=50 Wipe first 50 MiB of eMMC
Linux cat /proc/cmdline Confirm root= parameter points at the right PARTUUID
Linux journalctl -b -p err Show boot-time errors only

13. Related SE-Boot Behavior Notes

  • Security policy "soft": Visible in the banner. The IOT2050 Advanced runs in soft-policy mode by default; secure boot keys are present but enforcement is permissive. A custom U-Boot can still be flashed, but it must be signed with the custMpk chain.
  • AVS class 0: Adaptive Voltage Scaling disabled; the SoC runs at fixed OPP. This is normal for IOT2050 Advanced and unrelated to the UUID check.
  • OP-TEE 3.6.0: Trusted OS is loaded but not invoked by the conflict script. The check is pure U-Boot logic.
  • Two identical devices: The Device UUID (e.g. F4DA45F37027464ABB6382BD740784D5) is unique per SoM. The conflict error never prints the Device UUID; it prints the rootfs PARTUUID. If you see the Device UUID in the error, you are looking at a different problem (e.g., duplicate MAC, security ID).

14. Long-Term Field-Service Recommendations

  1. Standardize on a single IndOS version across the fleet. Mixing IndOS V1.x and V2.x across eMMC and SD card can produce additional SE-Boot incompatibilities.
  2. Label every SD card with the IOT2050 MLFB, IndOS version, and last commissioning date.
  3. Keep one spare IOT2050 Advanced per site, pre-commissioned (eMMC wiped) and stored in an ESD bag.
  4. Document the wipe procedure in the maintenance manual so the swap can be performed by a fitter without IT escalation.
  5. Periodically re-verify that the spare unit still boots its SD card (battery discharge in storage can corrupt SD cards over multi-year intervals).

What does the error "uuid conflict: 109a8c08-01" actually mean?

The string 109a8c08-01 is the GPT PARTUUID of the Industrial OS rootfs partition. SE-Boot detected the same PARTUUID on two bootable media (typically eMMC and SD card) and halted the boot to prevent mounting duplicate rootfs instances.

Will systemd unit regen-rootfs-uuid-on-first-boot fix the conflict?

No. The conflict fires inside U-Boot before Linux starts, so no systemd unit can run. The unit regen-rootfs-uuid-on-first-boot.service is not shipped in the IndOS image. The supported fix is to wipe the rootfs on the eMMC (dd + sgdisk --zap-all) so only one IndOS instance remains.

Does the conflict also affect the SIMATIC IOT2050 Basic?

The SE-Boot UUID check is implemented on both the Basic and Advanced SKUs of the IOT2050. Any combination of two identical IndOS images on eMMC plus a second media (SD or USB) will trigger the same conflict on the Basic variant. The wipe procedure is identical.

Can I disable the UUID check by modifying U-Boot environment?

No. The check is compiled into the SE-Boot/U-Boot binary stored in SPI flash and is signed. There is no U-Boot environment variable that skips it. Any attempt to reflash a custom SE-Boot image without a valid custMpk signature will be rejected by the ROM bootloader and the IOT2050 will not boot.

Why does the Example Image boot from the same SD card without the error?

The Debian-based Example Image regenerates the rootfs PARTUUID on first boot, so two writes of the Example Image on two different media do not share a PARTUUID. Industrial OS images do not perform this regeneration, which is why a fresh Example Image write on each media avoids the conflict entirely.

Back to blog