mvebu: uDPU: add sysupgrade support

This patch adds sysupgrade, uboot-env and networking support
for Methode uDPU device.

Device features 4 partitions:

-----------------------------------------
|  boot   | recovery  | rootfs |  misc  |
| (ext4)  |  (ext4)   | (fsf2) | (f2fs) |
_________________________________________

Idea was to use f2fs only but the u-boot currently lacks support
so first 2 partition are ext4 to be u-boot readable, and this was
a reason why custom build and sysupgrade sections were required.

On the sysupgrade, boot and rootfs partitions are updated, firmare
image and user configuration is saved on the misc partition and if
the upgrade was successfull, recovery partition will be updated on
after the reboot from preinit script. If the sysupgrade fails for any
reason, device will fallback to recovery initramfs image.

Signed-off-by: Vladimir Vid <vladimir.vid@sartura.hr>
This commit is contained in:
Vladimir Vid 2019-07-22 13:08:18 +02:00 committed by Luka Perkov
parent 52cbe6b9c0
commit 7dff6a8c89
8 changed files with 264 additions and 4 deletions

View File

@ -36,6 +36,9 @@ linksys,rango|\
linksys,venom)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x20000" "0x20000"
;;
methode,udpu)
ubootenv_add_uci_config "/dev/mtd0" "0x180000" "0x10000" "0x10000"
;;
esac
config_load ubootenv

View File

@ -49,7 +49,7 @@ marvell,armada-3720-db)
marvell,axp-gp)
ucidef_set_interface_lan "eth0 eth1 eth2 eth3"
;;
methode,uDPU)
methode,udpu)
ucidef_set_interfaces_lan_wan "eth1" "eth0"
;;
solidrun,clearfog*a1)

View File

@ -0,0 +1,48 @@
#
# Copyright (C) 2014-2019 OpenWrt.org
# Copyright (C) 2016 LEDE-Project.org
#
preinit_mount_udpu() {
. /lib/functions.sh
case $(board_name) in
methode,udpu)
# Check which device is detected
[ -b "/dev/mmcblk0" ] && mmcdev="/dev/mmcblk0" || mmcdev="/dev/mmcblk1"
if [ -b "${mmcdev}p4" ]; then
mkdir /misc
mount -t f2fs ${mmcdev}p4 /misc
[ -f "/misc/sysupgrade.tgz" ] && {
echo "- Restoring configuration files -"
tar xzf /misc/sysupgrade.tgz -C /
rm -f /misc/sysupgrade.tgz
sync
}
[ -f "/misc/firmware/recovery.itb" ] && {
echo "- Updating /recovery partition -"
mkfs.ext4 -q ${mmcdev}p2 | echo y &> /dev/null
mkdir -p /tmp/recovery
mount ${mmcdev}p2 /tmp/recovery
cp /misc/firmware/recovery.itb /tmp/recovery
[ -f "/misc/firmware/boot.scr" ] && \
cp /misc/firmware/boot.scr /tmp/recovery
sync
umount /tmp/recovery
rm -rf /tmp/recovery
# Replace previous backup with the new one
[ -d "/misc/firmware_old" ] && rm -rf /misc/firmware_old
[ -d "/misc/firmware" ] && mv /misc/firmware /misc/firmware_old
}
fi
# Legacy support - if rootfs was booted, instruct u-boot to keep the current root dev
[ "$(df | grep /dev/root)" ] && fw_setenv root_ok '2'
;;
esac
}
boot_hook_add preinit_main preinit_mount_udpu

View File

@ -28,6 +28,9 @@ platform_do_upgrade() {
marvell,armada8040-mcbin|solidrun,clearfog-base-a1|solidrun,clearfog-pro-a1)
platform_do_upgrade_sdcard "$1"
;;
methode,udpu)
platform_do_upgrade_uDPU "$1"
;;
*)
default_do_upgrade "$1"
;;
@ -42,5 +45,8 @@ platform_copy_config() {
marvell,armada8040-mcbin|solidrun,clearfog-base-a1|solidrun,clearfog-pro-a1)
platform_copy_config_sdcard
;;
methode,udpu)
platform_copy_config_uDPU
;;
esac
}

View File

@ -0,0 +1,152 @@
# uDPU uses combined ext4 and f2fs partitions.
# partition layout:
# 1. boot (ext4)
# 2. recovery (ext4)
# 3. rootfs (f2fs)
# 4. misc (f2fs)
# Check which device is available, depending on the board revision
if [ -b "/dev/mmcblk1" ]; then
emmc_dev=/dev/mmcblk1
elif [ -b "/dev/mmcblk0" ]; then
emmc_dev=/dev/mmcblk0
else
echo "Cannot detect eMMC flash, aborting.."
exit 1
fi
part_prep() {
if [ "$(grep $1 /proc/mounts)" ]; then
mounted_part="$(grep $1 /proc/mounts | awk '{print $2}' | head -1)"
umount $mounted_part
[ "$(grep -wo $mounted_part /proc/mounts)" ] && umount -l $mounted_part
fi
}
do_part_check() {
local emmc_parts="1 2 3 4"
local part_valid="1"
# Check if the block devices exist
for num in ${emmc_parts}; do
[[ ! -b ${emmc_dev}p${num} ]] && part_valid="0"
done
# If partitions are missing create a new partition table
if [ "$part_valid" != "1" ]; then
printf "Invalid partition table, creating a new one\n"
printf "o\nn\np\n1\n\n+256M\nn\np\n2\n\n+256M\nn\np\n3\n\n+1536M\nn\np\n\n\nw\n" | fdisk -W always $emmc_dev > /dev/null 2>&1
# Format the /misc part right away as we will need it for the firmware
printf "Formating /misc partition, this make take a while..\n"
part_prep ${emmc_dev}p4
mkfs.f2fs -q -l misc ${emmc_dev}p4
[ $? -eq 0 ] && printf "/misc partition formated successfully\n" || printf "/misc partition formatting failed\n"
do_initial_setup
else
printf "Partition table looks ok\n"
fi
}
do_misc_prep() {
if [ ! "$(grep -wo /misc /proc/mounts)" ]; then
mkdir -p /misc
mount ${emmc_dev}p4 /misc
# If the mount fails, try to reformat partition
# Leaving possiblity for multiple iterations
if [ $? -ne 0 ]; then
printf "Error while mounting /misc, trying to reformat..\n"
format_count=0
while [ "$format_count" -lt "1" ]; do
part_prep ${emmc_dev}p4
mkfs.f2fs -q -l misc ${emmc_dev}p4
mount ${emmc_dev}p4 /misc
if [ $? -ne 0 ]; then
umount -l /misc
printf "Failed while mounting /misc\n"
format_count=$((format_count +1))
else
printf "Mounted /misc successfully\n"
break
fi
done
fi
fi
}
do_initial_setup() {
# Prepare /recovery parition
part_prep ${emmc_dev}p2
mkfs.ext4 -q ${emmc_dev}p2 | echo y &> /dev/null
# Prepare /boot partition
part_prep ${emmc_dev}p1
mkfs.ext4 -q ${emmc_dev}p1 | echo y &> /dev/null
# Prepare /root partition
printf "Formating /root partition, this may take a while..\n"
part_prep ${emmc_dev}p3
mkfs.f2fs -q -l rootfs ${emmc_dev}p3
[ $? -eq 0 ] && printf "/root partition reformated\n"
}
do_regular_upgrade() {
# Clean /boot partition - mfks.ext4 is not available in chroot
[ "$(grep -wo /boot /proc/mounts)" ] && umount /boot
mkdir -p /tmp/boot
mount ${emmc_dev}p1 /tmp/boot
rm -rf /tmp/boot/*
# Clean /root partition - mkfs.f2fs is not available in chroot
[ "$(grep -wo /dev/root /proc/mounts)" ] && umount /
mkdir -p /tmp/rootpart
mount ${emmc_dev}p3 /tmp/rootpart
rm -rf /tmp/rootpart/*
}
platform_do_upgrade_uDPU() {
# Prepare and extract firmware on /misc partition
do_misc_prep
[ -f "/misc/firmware" ] && rm -r /misc/firmware
mkdir -p /misc/firmware
tar xzf "$1" -C /misc/firmware/
do_regular_upgrade
printf "Updating /boot partition\n"
tar xzf /misc/firmware/boot.tgz -C /tmp/boot
[ $? -eq 0 ] && printf "/boot partition updated successfully\n" || printf "/boot partition update failed\n"
sync
printf "Updating /root partition\n"
tar xzf /misc/firmware/rootfs.tgz -C /tmp/rootpart
[ $? -eq 0 ] && printf "/root partition updated successfully\n" || printf "/root partition update failed\n"
sync
# Saving configuration files over sysupgrade
platform_copy_config_uDPU
# Remove tmp mounts
tmp_parts=$(grep "${emmc_dev}" /proc/mounts | awk '{print $2}')
for part in ${tmp_parts}; do
umount $part
# Force umount is necessary
[ "$(grep "${part}" /proc/mounts)" ] && umount -l $part
done
# Sysupgrade complains about /tmp and /dev, so we can detach them here
umount -l /tmp
umount -l /dev
}
platform_copy_config_uDPU() {
# Config is saved on the /misc partition and copied on the rootfs after the reboot
if [ -f "/tmp/sysupgrade.tgz" ]; then
cp -f /tmp/sysupgrade.tgz /misc
sync
fi
}

View File

@ -68,6 +68,15 @@ define Build/omnia-medkit-initramfs
--file=$@ -C $(dir $(IMAGE_KERNEL))boot/ .
endef
define Build/uDPU-firmware
(rm -fR $@-fw; mkdir -p $@-fw)
$(CP) $(BIN_DIR)/$(IMAGE_PREFIX)-initramfs.itb $@-fw/recovery.itb
$(CP) $@-boot.scr $@-fw/boot.scr
(cd $(TARGET_DIR); $(TAR) -cvzf $@-fw/rootfs.tgz .)
(cd $@.boot; $(TAR) -cvzf $@-fw/boot.tgz .)
(cd $@-fw; $(TAR) -cvzf $(KDIR_TMP)/$(IMAGE_PREFIX)-firmware.tgz .)
endef
define Device/Default
PROFILES := Default
BOARD_NAME = $$(DEVICE_DTS)

View File

@ -35,7 +35,7 @@ define Device/marvell_armada-3720-db
endef
TARGET_DEVICES += marvell_armada-3720-db
define Device/methode_uDPU
define Device/methode_udpu
$(call Device/Default-arm64)
DEVICE_TITLE := Methode micro-DPU (uDPU)
DEVICE_DTS := armada-3720-uDPU
@ -44,8 +44,12 @@ define Device/methode_uDPU
KERNEL_INITRAMFS_SUFFIX := .itb
DEVICE_PACKAGES := f2fs-tools e2fsprogs fdisk ethtool kmod-usb2 kmod-usb3 \
kmod-e100 kmod-e1000 kmod-e1000e kmod-igb kmod-ixgbevf \
kmod-mdio-gpio kmod-switch-mvsw61xx
kmod-mdio-gpio kmod-switch-mvsw61xx kmod-i2c-pxa
IMAGE_NAME = $$(IMAGE_PREFIX)-$$(2)
IMAGES := firmware.tgz
IMAGE/firmware.tgz := boot-scr | boot-img-ext4 | uDPU-firmware | append-metadata
BOOT_SCRIPT := udpu
endef
TARGET_DEVICES += methode_uDPU
TARGET_DEVICES += methode_udpu
endif

View File

@ -0,0 +1,38 @@
# Bootscript for Methode uDPU device
# Device and variables may vary between different revisions
# of device, so we need to make sure everything is set correctly.
# Set the LED's correctly
gpio clear 12; gpio clear 40; gpio clear 45;
# Find eMMC device,
if mmc dev 0; then
setenv mmcdev 0
setenv rootdev 'root=/dev/mmcblk0p3'
elif mmc dev 1; then
setenv mmcdev 1
setenv rootdev 'root=/dev/mmcblk1p3'
fi
# Set the variables if necessary
if test ${kernel_addr_r}; then
setenv kernel_addr_r 0x5000000
fi
if test ${fdt_add_r}; then
setenv fdt_addr_r 0x4f00000
fi
setenv console 'console=ttyMV0,115200 earlycon=ar3700_uart,0xd0012000'
setenv bootargs ${console} $rootdev rw rootwait
load mmc ${mmcdev}:1 ${fdt_addr_r} @DTB@.dtb
load mmc ${mmcdev}:1 ${kernel_addr_r} Image
booti ${kernel_addr_r} - ${fdt_addr_r}
# If the boot command fails, fallback to recovery image
echo '-- Boot failed, falling back to the recovery image --'
setenv bootargs $console
load mmc ${mmcdev}:2 ${kernel_addr_r} recovery.itb
bootm ${kernel_addr_r}