CSS Styles

Tuesday, May 11, 2021

Linux - Kernel Version

Source

# Extract
 gzip -dc ../initrd.gz | cpio -idmv --no-absolute-filenames

# Rebuild
 find . | cpio -o -H newc | gzip -9 > ../initrd.gz

XZ Base (Redhat)

# Extract
 xz -dc ../initrd.img | cpio -idmv --no-absolute-filenames

# Rebuild
 find . | cpio -o -H newc | xz -9 > ../initrd.img

Other Distros

Kernel 目錄下 Makefile 的前幾行, 記錄著版本資訊。
以下面的內容為例, 其版本號碼為 2.6.36.2。

 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 36
 EXTRAVERSION = .2

Friday, May 7, 2021

Linux chroot - Active Firmware Image Update

In embedded system firmware update for active image requires additional process to accomplish it. To save the cost and maximize the usage of non-volatile memory, the content of flash is not fully loaded into RAM, instead is used at runtime, so called MTD (Memory Technology Device) in Linux. Since MTD is in use and supposedly not to be changed arbitrarily unless disconnected from all tasks and not accessible further.

Here comes an example which BMC updates the active image itself under Linux console with AMI based firmware.


Copy Firmware to Target

wget <URL>/<firmware> -P /tmp # under BMC console in this case
Any methods which can copy file to target, says ftp, sftp, tftp, scp, rsync, ssh, nc, native or cloud files sharing.

Commands under Target Console

Ensure root privilege (option)

id uid=0(root) gid=0(sysadmin) groups=0(sysadmin)

Identify firmware active image number (option)

method 1 (The booted image number is at the end of output line)
cat /proc/cmdline root=/dev/mtdblock3 ro ip=none mem=496M console=ttyS4,115200 rootfstype=cramfs bigphysarea=8192 bootlogo=2b80040 imagebooted=1

method 2 (AMI IPMI OEM command to read the active image number)
ipmitool -H 127.0.0.1 -U admin -P admin raw 0x32 0x8f 7 1

Stop tasks which may interfere process as possible (not required for inactive image)

for i in ad av c d ext fl hd ipm l mc pa procp redf redisr rm rs sy ti ua up vm; do
  for j in /etc/init.d/$i*; do [ -e $j ] && $j stop; done
done
killall udhcpc dhcp6c
Ignore tasks which are protected and can't be stopped, see if everything OK or not.

Build root filesystem in RAM and switch to it (not required for inactive image)

mkdir -p /tmp/rootfs/usr
cd /tmp/rootfs
cp -a /bin /sbin /lib /tmp .
cp -a /usr/bin /usr/sbin /usr/lib /usr/local usr
for i in dev sys var proc etc run; do mkdir -p $i; mount --rbind /$i $i; done
chroot /tmp/rootfs /bin/bash

Update firmware through MTD interface (tools may be diffrent on other platforms)

method 1 (flash_erase + dd)
flash_erase /dev/mtd0 0 1024 # 64KB/block, 1024*64KB=64MB, quicker than mtd_debug
dd if=/tmp/<firmware> of=/dev/mtd0 bs=1M seek=0

method 2 (mtd_debug)
f=/tmp/<firmware>
mtd_debug erase /dev/mtd0 0 0x4000000 # 3~5 mins or even longer, platform dependent
mtd_debug write /dev/mtd0 0 `stat -c%s $f` $f
In this case of 64MB firmware image size, 0x0000000 is the 1st image offset and 0x4000000 is the 2nd image offset.

Reboot

reboot # shutdown -rfn now
Booting from which image is determined by boot policy.
AMI IPMI OEM command can specify booting image number, example for image number 1: raw 0x32 0x8f 1 1.


Sunday, May 2, 2021

Linux - Device-to-Bus Mapping

Block Device Bus



ls -l /sys/block



Net Device Bus



ls -l /sys/class/net



IPMI Device Bus



ls -l /sys/class/ipmi



Other Device Buses



Most links of devices can be found under /sys/class.

Thursday, April 29, 2021

Linux initrd - Customization

Extraction -> Customization -> Rebuilding

- commands issued under the temporary working directory.
- switch to root if required like mknod needs privilege.

GZ Based (Debian)

Extraction

gzip -dc ../initrd.gz | cpio -idmv --no-absolute-filenames

Rebuilding

find . | cpio -o -H newc | gzip -9 > ../initrd.gz

XZ Based (Redhat)

Extraction

xz -dc ../initrd.img | cpio -idmv --no-absolute-filenames

Rebuilding

find . | cpio -o -H newc | xz -9 > ../initrd.img

Other Distros

Analyze file format then do extraction and rebuilding accordingly.


Monday, April 19, 2021

Network - BMC as a Router

vNIC  virtual NIC over USB created by BMC FW, says AMI MegaRAC
<==>  ip forward and iptables

BMC Setup


Basic Configuration

nicip() { i=`ip a s dev $1 | grep "inet "`; i=${i/*inet }; echo ${i%% *}; }
bwan=eth0 # bmc wan to network
blan=usb0 # bmc lan to host
bwanip=`nicip $bwan` # bmc wan ip/prefix
blanip=`nicip $blan` # bmc lan ip/prefix
hosti=`{ i=${blanip%/*}; [ ${i##*.} = 1 ] && j=2 || j=1; echo ${i%.*}.$j; }` # referred host ip


Routing Option - Simple, implicit rules (ephemeral ports) unsupported

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o $bwan -j MASQUERADE


Routing Option - Full, works for tftp

bwani0=<ip in same $bwanip domain> # 2nd bmc wan ip, assigned manually
echo 1 > /proc/sys/net/ipv4/ip_forward
ip a a $bwani0/${bwanip#*/} dev $bwan
iptables -t nat -A POSTROUTING -j SNAT -s $hosti --to $bwani0
iptables -t nat -A PREROUTING -j DNAT -d $bwani0 --to $hosti


# optional domain check

ipa2d() { i=${1%/*} n=; for j in 24 16 8 0; do n=$((n+${i%%.*}*2**j)); i=${i#*.}; done; echo $n; }
msk2d() { echo $((2**32-2**(32-${1#*/}))); }
dom2d() { echo $((`ipa2d $1` & `msk2d $1`)); }
[ `dom2d $bwanip` = `dom2d $bwani0/${bwanip#*/}` ] || echo different domain


# optional function to convert prefix to address

prefix2addr() {
 n=${1#*/} s=
 for i in 0 1 2 3; do d=8; [ $n -lt 8 ] && d=$n; s=$s$((256-2**(8-d))).; n=$((n-d)); done
 echo ${s%.}
}
prefix2addr $blanip


Host Setup


Generic Configuration (values are environment and requirement dependent)

namevaluenotes
niceth0NIC name in UEFI, could be different in OS 
ip169.254.0.1host IP address, refer to $hosti in BMC 
prefix16host subnet mask in prefix notation, refer to ${blanip#*/}in BMC
netmask255.255.0.0host subnet mask in address notation, refer to prefix2addr $blanip
gateway169.254.0.17host gateway address, refer to ${blanip%/*} in BMC
dns8.8.8.8Google DNS


U-Boot

setenv ethact eth0
setenv ipaddr 169.254.0.1
setenv gatewapip 169.254.0.17
setenv netmask 255.255.0.0
setenv dnsip 8.8.8.8


UEFI Shell

ifconfig -s eth0 static 169.254.0.1 255.255.0.0 169.254.0.17 dns 8.8.8.8


UEFI Grub2 (requires cdc_ether supported)

net_add_dns 8.8.8.8
net_add_route default 0.0.0.0/0 gw 169.254.0.17
net_add_addr eth0 efinet0 169.254.0.1


Linux based OS

nic=`ls /sys/bus/usb/drivers/cdc_ether/*/net` # host nic to bmc

: ' # may be required in Redhat based distros
sudo nmcli con down $nic >&/dev/null # get rid of NetworkManager control
sudo systemctl stop NetworkManager
sudo systemctl stop firewalld # get rid of firewall control
'

sudo ip addr add 169.254.0.1/16 dev $nic
sudo ip link set $nic up
sudo ip route add default via 169.254.0.17
sudo sh -c "echo nameserver 8.8.8.8 >> /etc/resolv.conf"