Some embedded boards are manufactured in quantity. In a such situation it’s common to require that each board is uniquely identified for production/sales/maintenance tracking. Serial number is a common solution. The question is where to store the serial number ? I usually recommend to store it in the /etc/hostname
file because it make it widely available to all applications and will be display in most log files. If the board have something like a network interface, chance are that you need to assign an unique address to it using the device tree. So I wondering if it’s possible set the hostname as a serial number from the device tree too. I was unable to find something like this on the internet, so I started thinking how can I do that.
Adding the ‘hostname
‘ node on the device tree is really trivial. Just add the following line in the <board.dts
> file corresponding to the hardware:
hostname = "board-123456";
Then run ‘make
<board.dts
>’ from the Linux kernel source tree to get a new <board.dtb
> file. Once you boot the Linux kernel with this new <board.dtb
> file, you must get the ‘hostname
‘ entry in the sysfs
filesystem. This allow to do this:
# cat /sys/firmware/devicetree/base/hostname
board-123456
The next step is to setup the Linux hostname at boot time to the value of the device tree ‘hostname
‘ node. At first I was thinking that this will need a kernel patch since the device tree is maintained into the kernel and that the hostname value is stored into the ‘nodename
‘ field of the kernel’s ‘uts
‘ namespace. Until I realize that the hostname command will maybe accept to read the /sys/firmware/devicetree/base/hostname
file and correctly set the hostname, even is the buffer returned by the sysfs
contain a zero byte at the end. I try it and it worked fine:
# hostname -F /sys/firmware/devicetree/base/hostname
# hostname
board-123456
Inspecting the uname call using ‘strace hostname
‘ showed that the zero suffix was correctly ignored:
uname({sys="Linux", node="board-123456", ...}) = 0
Since the hostname command is already called early in the system initialization process to set the hostname to the content of the /etc/hostname
file, the simplest solution is to replace the /etc/hostname
file by a symbolic link to the /sys/firmware/devicetree/base/hostname
file:
# ln -fs /sys/firmware/devicetree/base/hostname /etc/
To get this working the sysfs
filesystem need to be mounted before the call to the hostname command. Fortunately this is the case at least in Debian jessie using systemd, but I am almost certain that this will also work with systemvinit.
So simple after all. I hope this hack will work on others distributions too.