Inconsistent MAC address on PB2

Hello everyone,

After successfully setting up an external physical Ethernet interface alongside the RNDIS USB, I discovered that the Pocketbeagle 2 uses a randomized MAC address for eth0 and hardcoded MAC address for usb0.

/usr/bin/bb-setup-mac-address

        #Some devices are showing a blank mac_addr0 [00:00:00:00:00:00], let's fix that up...
        if [ "x${is_valid}" = "x" ] ; then
                echo "${log} mac came up 00:00:00:00:00:00 fixing..."
                mac_addr0="1C:BA:8C:A2:ED:68"
                echo "${log} eth0: ${mac_addr0}"
        fi

I implemented a workaround, but I’d appreciate any feedback or cleaner solution from others. @RobertCNelson @giuliomoro

  • First change: Improved MAC retrieval:

Instead of fetching the MAC from where the driver usually stores it, I read it directly from the hardware registers and validate it using the existing is_mac_valid function. If the MAC is invalid, it falls back to a hardcoded value as before.

/usr/bin/bb-setup-mac-address

get_mac_addr () {
        unset mac_addr0
        unset is_valid

        #PocketBeagle2
        #Read values from memory addresses
        mac1=$(echo "$(devmem2 0x43000200)" | grep 'Read at address' | awk '{print $NF}')
        mac2=$(echo "$(devmem2 0x43000204)" | grep 'Read at address' | awk '{print $NF}')

        #Format the last two bytes from mac2 and the first four bytes from mac1
        last_two=$(printf "%04X" $mac2 | sed 's/../&:/g; s/:$//')
        first_four=$(printf "%08X" $mac1 | sed 's/../&:/g; s/:$//')

        mac_addr0="$last_two:$first_four"
        echo "${log} ethernet@8000000: ${mac_addr0}"
        is_mac_valid

        #Some devices are showing a blank mac_addr0 [00:00:00:00:00:00], let's fix that up...
        if [ "x${is_valid}" = "x" ] ; then
                echo "${log} mac came up 00:00:00:00:00:00 fixing..."
                mac_addr0="1C:BA:8C:A2:ED:68"
                echo "${log} eth0: ${mac_addr0}"
        fi
}
  • Second change: Generate systemd Network Config

I added a new function to dynamically write the systemd network configuration for eth0, linking it to the retrieved MAC address:

write_default_bb_mac_addr_eth0 () {
        echo "# /usr/bin/bb-setup-mac-addr driven file" > /etc/systemd/network/eth0.network
        echo "[Match]" >> /etc/systemd/network/eth0.network
        echo "Name=eth0" >> /etc/systemd/network/eth0.network
        echo "[Link]" >> /etc/systemd/network/eth0.network
        echo "MACAddress=${mac_addr0}" >> /etc/systemd/network/eth0.network
        echo "[Network]" >> /etc/systemd/network/eth0.network
        echo "DHCP=yes" >> /etc/systemd/network/eth0.network
} 
  • Third change: Integrate with Setup Flow

I added a call to the new function right after write_default_bb_mac_addr in the main setup sequence:

get_mac_addr
process_base
generate_usb0_host_addr
generate_usb0_dev_addr
generate_usb1_host_addr
generate_usb1_dev_addr
write_default_bb_mac_addr
write_default_bb_mac_addr_eth0
update_default_hostapd
  • Final Step: Force MAC Setup and Network Restart

To ensure everything takes effect, I modified /usr/bin/bb-start-acm-ncm-rndis-old-gadget to explicitly call the setup script and restart the systemd-networkd service:

#Based off:
#https://github.com/beagleboard/meta-beagleboard/blob/master/meta-beagleboard-extras/recipes-support/usb-gadget/gadget-init/g-ether-load.sh

/usr/bin/bb-setup-mac-address
systemctl restart systemd-networkd

if [ -f /etc/default/bb-mac-addr ] ; then
        . /etc/default/bb-mac-addr
elif [ -f /usr/bin/bb-setup-mac-address ] ; then
        /usr/bin/bb-setup-mac-address
        sync
        . /etc/default/bb-mac-addr
fi

Thank you for your time and feedback!

Sergi

1 Like

Hi,
I am not using the RDNIS but the ECN; however, they are similar.

Have you tried to set up the mac address directly via gadget_fs, you need to mount configfs,

Here is the documentation:

Also make sure your mac address’ first byte is even.

1 Like

I’ve been hacking and trying different things to get u-boot to pass this value thru..

I’m thinking of just using devmen2 (well teh k3conf version)..

k3conf read 0x43000200 32 | grep -v '|'
k3conf read 0x43000204 32 | grep -v '|'
root@am6232-pb2-85:~# k3conf read 0x43000200 32 | grep 'Value at addr ' | awk '{print $NF}'
0x4b121cf

root@am6232-pb2-85:~# k3conf read 0x43000204 32 | grep 'Value at addr ' | awk '{print $NF}'
0xdcbe
#!/bin/bash

mac1=$(k3conf read 0x43000200 32 | grep 'Value at addr ' | awk '{print $NF}')
mac2=$(k3conf read 0x43000204 32 | grep 'Value at addr ' | awk '{print $NF}')

echo ${mac1}
echo ${mac2}

#Format the last two bytes from mac2 and the first four bytes from mac1
last_two=$(printf "%04X" $mac2 | sed 's/../&:/g; s/:$//')
first_four=$(printf "%08X" $mac1 | sed 's/../&:/g; s/:$//')

echo ${last_two}
echo ${first_four}

mac_addr0="$last_two:$first_four"
echo "${log} ethernet@8000000: ${mac_addr0}"
root@am6232-pb2-85:~# ./test.sh 
0x4b121cf
0xdcbe
DC:BE
04:B1:21:CF
 ethernet@8000000: DC:BE:04:B1:21:CF

and pushed… generic-sys-mods (1.20250905.0) · beagleboard/repos-arm64@f0d83c5 · GitHub

So much nicer to see!

[   20.894316] configfs-gadget.g_multi gadget.0: HOST MAC dc:be:04:b1:21:d1
[   20.894352] configfs-gadget.g_multi gadget.0: MAC dc:be:04:b1:21:d2
[   20.895611] configfs-gadget.g_multi gadget.0: HOST MAC dc:be:04:b1:21:d3
[   20.895641] configfs-gadget.g_multi gadget.0: MAC dc:be:04:b1:21:d4

thanks @Sergi_D1

Regards,

1 Like

Hello @RobertCNelson,

Sorry for the late response. I’ve been a bit busy lately.

This is the modified U-Boot version:

#ifdef FDT_SEQ_MACADDR_FROM_ENV
			nodeoff = fdt_path_offset(fdt, path);
			fdt_prop = fdt_get_property(fdt, nodeoff, "status",
						    NULL);
			if (fdt_prop && !strcmp(fdt_prop->data, "disabled"))
				continue;
			i++;
#endif
			tmp = env_get(mac);
			if (!tmp) {
				val1 = *(volatile uint32_t *)0x43000200;
				val2 = *(volatile uint32_t *)0x43000204;
				mac_addr[0] = (val2 >>  8) & 0xFF; 
				mac_addr[1] = (val2 >>  0) & 0xFF;  
				mac_addr[2] = (val1 >> 24) & 0xFF;  
				mac_addr[3] = (val1 >> 16) & 0xFF;  
				mac_addr[4] = (val1 >> 8)  & 0xFF;
				mac_addr[5] = (val1 >> 0)  & 0xFF;
			}else{
				for (j = 0; j < 6; j++) {
				mac_addr[j] = tmp ?
					      hextoul(tmp, &end) : 0;
				if (tmp)
					tmp = (*end) ? end + 1 : end;
				}
			}
			do_fixup_by_path(fdt, path, "mac-address",
					 &mac_addr, 6, 0);
			do_fixup_by_path(fdt, path, "local-mac-address",
					 &mac_addr, 6, 1);
		}
	}
}

DT

Node hex dump of the address
image

With the original Linux files from my build Linux pocketbeagle-2 6.12.24-ti-arm64-r43 #1 SMP PREEMPT_RT Wed Jun 25 00:21:23 UTC 2025 aarch64 GNU/Linux it’s working as expected.

The interfaces receive their MAC address based on the SoC, consistent with the original /usr/bin/bb-setup-mac-address

Thank you,
Sergi