diff --git a/target/linux/mvebu/cortexa53/base-files/etc/board.d/05_compat_version b/target/linux/mvebu/cortexa53/base-files/etc/board.d/05_compat_version new file mode 100644 index 0000000000..5a8f31e6a7 --- /dev/null +++ b/target/linux/mvebu/cortexa53/base-files/etc/board.d/05_compat_version @@ -0,0 +1,15 @@ +. /lib/functions.sh +. /lib/functions/uci-defaults.sh + +board_config_update + +case "$(board_name)" in + methode,udpu|\ + methode,edpu) + ucidef_set_compat_version "2.0" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/mvebu/cortexa53/base-files/etc/init.d/bootcount b/target/linux/mvebu/cortexa53/base-files/etc/init.d/bootcount new file mode 100755 index 0000000000..6ebf8eddf6 --- /dev/null +++ b/target/linux/mvebu/cortexa53/base-files/etc/init.d/bootcount @@ -0,0 +1,12 @@ +#!/bin/sh /etc/rc.common + +START=99 + +boot() { + case $(board_name) in + methode,udpu|\ + methode,edpu) + fw_setenv bootcount 0 + ;; + esac +} diff --git a/target/linux/mvebu/cortexa53/base-files/lib/preinit/82_uDPU b/target/linux/mvebu/cortexa53/base-files/lib/preinit/82_uDPU deleted file mode 100644 index 1c72d0fe66..0000000000 --- a/target/linux/mvebu/cortexa53/base-files/lib/preinit/82_uDPU +++ /dev/null @@ -1,49 +0,0 @@ -# -# Copyright (C) 2014-2019 OpenWrt.org -# Copyright (C) 2016 LEDE-Project.org -# - -preinit_mount_udpu() { - . /lib/functions.sh - . /lib/upgrade/common.sh - - case $(board_name) in - methode,udpu|\ - methode,edpu) - # Check which device is detected - [ -b "/dev/mmcblk0" ] && mmcdev="/dev/mmcblk0" || mmcdev="/dev/mmcblk1" - - if [ -b "${mmcdev}p4" ]; then - mkdir /misc - mount -o compress_algorithm=zstd -t f2fs ${mmcdev}p4 /misc - [ -f "/misc/$BACKUP_FILE" ] && { - echo "- Restoring configuration files -" - tar xzf "/misc/$BACKUP_FILE" -C / - rm -f "/misc/$BACKUP_FILE" - 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 diff --git a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh index f77f15ecab..7ddb516762 100755 --- a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh +++ b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/platform.sh @@ -35,7 +35,37 @@ platform_do_upgrade() { ;; methode,udpu|\ methode,edpu) - platform_do_upgrade_uDPU "$1" + [ "$(rootfs_type)" = "tmpfs" ] && { + local firmware_active="$(fw_printenv -n bootactive)" + case "$firmware_active" in + 1) + CI_KERNPART="kernel_2" + CI_ROOTPART="rootfs_2" + fw_setenv bootactive 2 + ;; + 2) + CI_KERNPART="kernel_1" + CI_ROOTPART="rootfs_1" + fw_setenv bootactive 1 + ;; + esac + } + + local root="$(cmdline_get_var root)" + case "$root" in + /dev/mmcblk*p2) + CI_KERNPART="kernel_2" + CI_ROOTPART="rootfs_2" + fw_setenv bootactive 2 + ;; + /dev/mmcblk*p4) + CI_KERNPART="kernel_1" + CI_ROOTPART="rootfs_1" + fw_setenv bootactive 1 + ;; + esac + + emmc_do_upgrade "$1" ;; *) default_do_upgrade "$1" @@ -54,7 +84,7 @@ platform_copy_config() { ;; methode,udpu|\ methode,edpu) - platform_copy_config_uDPU + emmc_copy_config ;; esac } diff --git a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/uDPU.sh b/target/linux/mvebu/cortexa53/base-files/lib/upgrade/uDPU.sh deleted file mode 100644 index a8d803ff59..0000000000 --- a/target/linux/mvebu/cortexa53/base-files/lib/upgrade/uDPU.sh +++ /dev/null @@ -1,162 +0,0 @@ -udpu_check_emmc() { -# 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 -} - -udpu_part_prep() { - if grep -q "$1" /proc/mounts; then - mounted_part="$(grep -m 1 $1 /proc/mounts | awk '{print $2}')" - umount "$mounted_part" - grep -woq "$mounted_part" /proc/mounts && umount -l "$mounted_part" - fi -} - -udpu_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" - udpu_part_prep ${emmc_dev}p4 - if mkfs.f2fs -q -l misc -O extra_attr,compression ${emmc_dev}p4; then - printf "/misc partition formated successfully\n" - else - printf "/misc partition formatting failed\n" - fi - - udpu_do_initial_setup - else - printf "Partition table looks ok\n" - fi -} - -udpu_do_misc_prep() { - if ! grep -woq /misc /proc/mounts; then - mkdir -p /misc - - # If the mount fails, try to reformat partition - # Leaving possiblity for multiple iterations - if ! mount ${emmc_dev}p4 /misc; then - printf "Error while mounting /misc, trying to reformat..\n" - - format_count=0 - while [ "$format_count" -lt "1" ]; do - udpu_part_prep ${emmc_dev}p4 - mkfs.f2fs -q -l misc -O extra_attr,compression ${emmc_dev}p4 - if ! mount ${emmc_dev}p4 /misc; 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 -} - -udpu_do_initial_setup() { - # Prepare /recovery parition - udpu_part_prep ${emmc_dev}p2 - mkfs.ext4 -qF ${emmc_dev}p2 2>&1 /dev/null - - # Prepare /boot partition - udpu_part_prep ${emmc_dev}p1 - mkfs.ext4 -qF ${emmc_dev}p1 2>&1 /dev/null - - # Prepare /root partition - printf "Formating /root partition, this may take a while..\n" - udpu_part_prep ${emmc_dev}p3 - mkfs.f2fs -q -l rootfs -O extra_attr,compression ${emmc_dev}p3 && printf "/root partition reformated\n" -} - -udpu_do_regular_upgrade() { - # Clean /boot partition - mfks.ext4 is not available in chroot - grep -woq /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 -woq /dev/root /proc/mounts && umount / - mkdir -p /tmp/rootpart - mount ${emmc_dev}p3 /tmp/rootpart - rm -rf /tmp/rootpart/* -} - -platform_do_upgrade_uDPU() { - udpu_check_emmc - - # Prepare and extract firmware on /misc partition - udpu_do_misc_prep - - [ -f "/misc/firmware" ] && rm -r /misc/firmware - mkdir -p /misc/firmware - tar xzf "$1" -C /misc/firmware/ - - udpu_do_regular_upgrade - - printf "Updating /boot partition\n" - if tar xzf /misc/firmware/boot.tgz -C /tmp/boot; then - printf "/boot partition updated successfully\n" - else - printf "/boot partition update failed\n" - fi - sync - - printf "Updating /root partition\n" - if tar xzf /misc/firmware/rootfs.tgz -C /tmp/rootpart; then - printf "/root partition updated successfully\n" - else - printf "/root partition update failed\n" - fi - 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 -q "${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 "$UPGRADE_BACKUP" ]; then - cp -f "$UPGRADE_BACKUP" "/misc/$BACKUP_FILE" - sync - fi -} diff --git a/target/linux/mvebu/cortexa53/target.mk b/target/linux/mvebu/cortexa53/target.mk index fcf658c398..48c8b7f021 100644 --- a/target/linux/mvebu/cortexa53/target.mk +++ b/target/linux/mvebu/cortexa53/target.mk @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk ARCH:=aarch64 BOARDNAME:=Marvell Armada 3700LP (ARM64) CPU_TYPE:=cortex-a53 -FEATURES+=ext4 +FEATURES+=ext4 emmc DEFAULT_PACKAGES+=e2fsprogs ethtool mkf2fs partx-utils KERNELNAME:=Image dtbs diff --git a/target/linux/mvebu/image/Makefile b/target/linux/mvebu/image/Makefile index a1fa4b9f8d..db933a075b 100644 --- a/target/linux/mvebu/image/Makefile +++ b/target/linux/mvebu/image/Makefile @@ -136,19 +136,6 @@ define Build/sdcard-img-ext4 83 $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS) endef -define Build/uDPU-firmware - (rm -fR $@-fw; mkdir -p $@-fw) - $(CP) $(BIN_DIR)/$(KERNEL_INITRAMFS_IMAGE) $@-fw/recovery.itb - $(CP) $(IMAGE_ROOTFS) $@-fw/rootfs.tgz - $(CP) $@-boot.scr $@-fw/boot.scr - $(TAR) -czp --numeric-owner --owner=0 --group=0 --sort=name \ - $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \ - -f $@-fw/boot.tgz -C $@.boot . - $(TAR) -czp --numeric-owner --owner=0 --group=0 --sort=name \ - $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \ - -f $(KDIR_TMP)/$(DEVICE_IMG_PREFIX)-firmware.tgz -C $@-fw . -endef - define Device/FitImage KERNEL_SUFFIX := -uImage.itb KERNEL = kernel-bin | gzip | fit gzip $$(KDIR)/image-$$(DEVICE_DTS).dtb diff --git a/target/linux/mvebu/image/cortexa53.mk b/target/linux/mvebu/image/cortexa53.mk index 65e64ac512..f4c99caaa0 100644 --- a/target/linux/mvebu/image/cortexa53.mk +++ b/target/linux/mvebu/image/cortexa53.mk @@ -97,19 +97,46 @@ define Device/marvell_armada-3720-db endef TARGET_DEVICES += marvell_armada-3720-db +define Build/methode-gpt-emmc + cp $@ $@.tmp 2>/dev/null || true + ptgen -g -o $@.tmp -l 1024 \ + -t 0x2e -N kernel_1 -r -B -p 32M@1M \ + -t 0x2e -N rootfs_1 -r -p 1536M@33M \ + -t 0x2e -N kernel_2 -r -B -p 32M@1569M \ + -t 0x2e -N rootfs_2 -r -p 1536M@1601M + cat $@.tmp >> $@ + rm $@.tmp +endef + +define Build/append-boot-part + dd if=$@.bootimg bs=32M conv=sync >> $@ +endef + +define Device/eMMC-methode + DEVICE_DTS_DIR := $(DTS_DIR)/marvell + KERNEL_NAME := Image + KERNEL := kernel-bin + KERNEL_LOADADDR := 0x00800000 + DEVICE_PACKAGES += kmod-i2c-pxa kmod-hwmon-lm75 kmod-dsa-mv88e6xxx + DEVICE_COMPAT_VERSION := 2.0 + DEVICE_COMPAT_MESSAGE := Partition layout and image format was changed. \ + Upgrade requires reinstallation from initramfs. + FILESYSTEMS := squashfs + IMAGES := sysupgrade.bin emmc-gpt.img.gz + IMAGE/sysupgrade.bin := boot-scr | boot-img-ext4 | sysupgrade-tar kernel=$$$$@.bootimg | append-metadata + IMAGE/emmc-gpt.img.gz := methode-gpt-emmc |\ + pad-to 1M | boot-scr | boot-img-ext4 | append-boot-part |\ + pad-to 33M | append-rootfs |\ + gzip + BOOT_SCRIPT := udpu +endef + define Device/methode_udpu - $(call Device/Default-arm64) + $(call Device/eMMC-methode) $(call Device/FitImage) DEVICE_VENDOR := Methode DEVICE_MODEL := micro-DPU (uDPU) DEVICE_DTS := armada-3720-uDPU - KERNEL_LOADADDR := 0x00800000 - DEVICE_PACKAGES += f2fs-tools fdisk kmod-i2c-pxa kmod-hwmon-lm75 kmod-dsa-mv88e6xxx - DEVICE_IMG_NAME = $$(DEVICE_IMG_PREFIX)-$$(2) - FILESYSTEMS := targz - IMAGES := firmware.tgz - IMAGE/firmware.tgz := boot-scr | boot-img-ext4 | uDPU-firmware | append-metadata - BOOT_SCRIPT := udpu endef TARGET_DEVICES += methode_udpu diff --git a/target/linux/mvebu/image/udpu.bootscript b/target/linux/mvebu/image/udpu.bootscript index 741254e460..51eab7e381 100644 --- a/target/linux/mvebu/image/udpu.bootscript +++ b/target/linux/mvebu/image/udpu.bootscript @@ -8,26 +8,67 @@ 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 +# Check if bootactive variable exists and if not, default to 1 +if test -z "${bootactive}"; then + setenv bootactive 1 +fi + +# Check if bootcount variable exists and if not, default to 0 +if test -z "${bootcount}"; then + setenv bootcount 0 +fi + +if itest ${bootcount} > 2; then + if itest ${bootactive} == 2; then + setenv bootactive 1 + else + setenv bootactive 2 + fi + + setenv bootcount 0 +fi + +# Find A/B firmware to boot +if itest ${bootactive} == 2; then + setenv kernelpart 3 + setenv rootfspart 4 +else + setenv kernelpart 1 + setenv rootfspart 2 +fi + +setenv rootdev 'root=/dev/mmcblk'${mmcdev}'p'${rootfspart} + # Set the variables if necessary if test ${kernel_addr_r}; then setenv kernel_addr_r 0x5000000 fi -setenv console 'rootfs_mount_options.compress_algorithm=zstd' -setenv bootargs ${console} $rootdev rw rootwait +echo 'Booting firmware:' ${bootactive} -load mmc ${mmcdev}:1 ${kernel_addr_r} Image +if itest ${bootcount} == 0; then + setenv bootcount 1 +elif itest ${bootcount} == 1; then + setenv bootcount 2 +elif itest ${bootcount} == 2; then + setenv bootcount 3 +else + setenv bootcount 4 +fi + +env save + +setenv bootargs $rootdev rootwait fstools_overlay_compression_type=zstd + +load mmc ${mmcdev}:${kernelpart} ${kernel_addr_r} Image bootm ${kernel_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} +# If booting fails before kernel is loaded then reboot +# so the bootcount can trigger a slot switch. +echo 'Booting firmware:' ${bootactive} 'failed, rebooting' +reset