mpc85xx: Patch HiveAP 330 u-boot to fix boot
authorMartin Kennedy <hurricos@gmail.com>
Wed, 22 Dec 2021 18:08:33 +0000 (13:08 -0500)
committerChristian Lamparter <chunkeey@gmail.com>
Sat, 19 Feb 2022 18:20:29 +0000 (19:20 +0100)
When Kernel 5.10 was enabled for mpc85xx, the kernel once again became too
large upon decompression (>7MB or so) to decompress itself on boot (see
FS#4110[1]).

There have been many attempts to fix booting from a compressed kernel on
the HiveAP-330:

b683f1c36d8a ("mpc85xx: Use gzip compressed kernel on HiveAP-330")
98089bb8ba82 ("mpc85xx: Use uncompressed kernel on the HiveAP-330")
26cb167a5ca7 ("mpc85xx: Fix Aerohive HiveAP-330 initramfs image")

We can no longer compress the kernel due to size, and the stock bootloader
does not support any other types of compression. Since an uncompressed
kernel no longer fits in the 8MiB kernel partition at 0x2840000, we need to
patch u-boot to autoboot by running variable which isn't set by the
bootloader on each autoboot.

This commit repartitions the HiveAP, requiring a new COMPAT_VERSION,
and uses the DEVICE_COMPAT_MESSAGE to guide the user to patch u-boot,
which changes the variable run on boot to be `owrt_boot`; the user can
then set the value of that variable appropriately.

The following has been documented in the device's OpenWrt wiki page:
<https://openwrt.org/toh/aerohive/hiveap-330>. Please look there
first/too for more information.

The from-stock and upgrade from a previous installation now becomes:

0) setup a network with a dhcp server and a tftp server at serverip
(192.168.1.101) with the initramfs image in the servers root directory.

1) Hook into UART (9600 baud) and enter U-Boot. You may need to enter
a password of administrator or AhNf?d@ta06 if prompted. If the password
doesn't work. Try reseting the device by pressing and holding the reset
button with the stock OS.

2) Once in U-Boot, set the new owrt_boot and tftp+boot the initramfs image:
   Use copy and paste!

 # fw_setenv owrt_boot 'setenv bootargs \"console=ttyS0,$baudrate\";bootm 0xEC040000 - 0xEC000000'
 # save
 # dhcp
 # setenv bootargs console=ttyS0,$baudrate
 # tftpboot 0x1000000 192.168.1.101:openwrt-mpc85xx-p1020-aerohive_hiveap-330-initramfs-kernel.bin
 # bootm

3) Once openwrt booted:
carefully copy and paste this into the root shell. One step at a time

  # 3.0 install kmod-mtd-rw from the internet and load it

  opkg update; opkg install kmod-mtd-rw
  insmod mtd-rw i_want_a_brick=y

  # 3.1 create scripts that modifies uboot

cat <<- "EOF" > /tmp/uboot-update.sh
  . /lib/functions/system.sh
  cp "/dev/mtd$(find_mtd_index 'u-boot')" /tmp/uboot
  cp /tmp/uboot /tmp/uboot_patched
  ofs=$(strings -n80 -td < /tmp/uboot | grep '^ [0-9]* setenv bootargs.*cp\.l' | cut -f2 -d' ')
  for off in $ofs; do
    printf "run owrt_boot;            " | dd of=/tmp/uboot_patched bs=1 seek=${off} conv=notrunc
  done
  md5sum /tmp/uboot*
EOF

  # 3.2 run the script to do the modification

  sh /tmp/uboot-update.sh

  # verify that /tmp/uboot and /tmp/uboot_patched are good
  #
  # my uboot was: (is printed during boot)
  # U-Boot 2009.11 (Jan 12 2017 - 00:27:25), Build: jenkins-HiveOS-Honolulu_AP350_Rel-245
  #
  # d84b45a2e8aca60d630fbd422efc6b39  /tmp/uboot
  # 6dc420f24c2028b9cf7f0c62c0c7f692  /tmp/uboot_patched
  # 98ebc7e7480ce9148cd2799357a844b0  /tmp/uboot-update.sh <-- just for reference

  # 3.3 this produces the /tmp/u-boot_patched file.

  mtd write /tmp/uboot_patched u-boot

3) scp over the sysupgrade file to /tmp/ and run sysupgrade to flash OpenWrt:

  sysupgrade -n /tmp/openwrt-mpc85xx-p1020-aerohive_hiveap-330-squashfs-sysupgrade.bin

4) after the reboot, you are good to go.

Other notes:

- Note that after this sysupgrade, the AP will be unavailable for 7 minutes
  to reformat flash. The tri-color LED does not blink in any way to
  indicate this, though there is no risk in interrupting this process,
  other than the jffs2 reformat being reset.

- Add a uci-default to fix the compat version. This will prevent updates
  from previous versions without going through the installation process.

- Enable CONFIG_MTD_SPLIT_UIMAGE_FW and adjust partitioning to combine
  the kernel and rootfs into a single dts partition to maximize storage
  space, though in practice the kernel can grow no larger than 16MiB due
  to constraints of the older mpc85xx u-boot platform.

- Because of that limit, KERNEL_SIZE has been raised to 16m.

- A .tar.gz of the u-boot source for the AP330 (a.k.a. Goldengate) can
  be found here[2].

- The stock-jffs2 partition is also removed to make more space -- this
  is possible only now that it is no longer split away from the rootfs.

- the console-override is gone. The device will now get the console
  through the bootargs. This has the advantage that you can set a different
  baudrate in uboot and the linux kernel will stick with it!

- due to the repartitioning, the partition layout and names got a makeover.

- the initramfs+fdt method is now combined into a MultiImage initramfs.
  The separate fdt download is no longer needed.

- added uboot-envtools to the mpc85xx target. All targets have uboot and
  this way its available in the initramfs.

[1]: https://bugs.openwrt.org/index.php?do=details&task_id=4110
[2]: magnet:?xt=urn:btih:e53b27006979afb632af5935fa0f2affaa822a59

Tested-by: Martin Kennedy <hurricos@gmail.com>
Signed-off-by: Martin Kennedy <hurricos@gmail.com>
(rewrote parts of the commit message, Initramfs-MultiImage,
dropped bootargs-override, added wiki entry + link, uboot-envtools)
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
package/boot/uboot-envtools/files/mpc85xx
target/linux/mpc85xx/Makefile
target/linux/mpc85xx/base-files/etc/uci-defaults/05_fix-compat-version [new file with mode: 0644]
target/linux/mpc85xx/files/arch/powerpc/boot/dts/hiveap-330.dts
target/linux/mpc85xx/image/p1020.mk
target/linux/mpc85xx/p1020/config-default

index 004ec241316906433b51794168e291115b14f7dc..df6e5f670bb3299214ab29544e5d120b44c2082e 100644 (file)
@@ -12,6 +12,9 @@ ocedo,panda)
        ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x20000" "0x20000"
        ubootenv_add_uci_config "/dev/mtd2" "0x0" "0x20000" "0x20000"
        ;;
+aerohive,hiveap-330)
+       ubootenv_add_uci_config "$(find_mtd_part 'u-boot-env')" "0x0" "0x20000" "0x10000"
+       ;;
 esac
 
 config_load ubootenv
index b89bfc3ed158003e6c62e88d367df5180447978b..6bf096740e48b3041aa97143c642fe038415db8c 100644 (file)
@@ -19,6 +19,7 @@ include $(INCLUDE_DIR)/target.mk
 
 DEFAULT_PACKAGES += \
        kmod-input-core kmod-input-gpio-keys kmod-button-hotplug \
-       kmod-leds-gpio swconfig kmod-ath9k wpad-basic-wolfssl kmod-usb2
+       kmod-leds-gpio swconfig kmod-ath9k wpad-basic-wolfssl kmod-usb2 \
+       uboot-envtools
 
 $(eval $(call BuildTarget))
diff --git a/target/linux/mpc85xx/base-files/etc/uci-defaults/05_fix-compat-version b/target/linux/mpc85xx/base-files/etc/uci-defaults/05_fix-compat-version
new file mode 100644 (file)
index 0000000..253c229
--- /dev/null
@@ -0,0 +1,11 @@
+. /lib/functions.sh
+. /lib/functions/system.sh
+
+case "$(board_name)" in
+aerohive,hiveap-330)
+       uci set system.@system[0].compat_version="2.0"
+       uci commit system
+       ;;
+esac
+
+exit 0
index 9eb6e2613a650b1f34a3c7bb039a0de95224702c..359b123bc620b5f9cdbcd81794e5f9ce4e5c130c 100644 (file)
                label-mac-device = &enet0;
        };
 
-       chosen {
-               bootargs-override = "console=ttyS0,9600";
-       };
-
        memory {
                device_type = "memory";
        };
                                #address-cells = <1>;
                                #size-cells = <1>;
 
+                               firmware@0 {
+                                       reg = <0x0 0x3f00000>;
+                                       label = "firmware";
+                                       /*
+                                        * This unknown/invalid compatible prevents
+                                        * openwrt's mtdsplit_fit to go off a tangent if it
+                                        * finds a magic value inside the uncompressed kernel
+                                        * at a blocksized aligned place.
+                                        */
+                                       compatible = "areohive,hiveap-330-image";
+                               };
+
                                partition@0 {
                                        reg = <0x0 0x40000>;
                                        label = "dtb";
                                };
 
                                partition@40000 {
-                                       reg = <0x40000 0x40000>;
-                                       label = "initrd";
-                               };
-
-                               partition@80000 {
-                                       reg = <0x80000 0x27c0000>;
-                                       label = "rootfs";
-                               };
-
-                               partition@2840000 {
-                                       reg = <0x2840000 0x800000>;
+                                       compatible = "openwrt,uimage", "denx,uimage";
+                                       reg = <0x40000 0x3ec0000>;
                                        label = "kernel";
                                };
 
-                               partition@3040000 {
-                                       reg = <0x3040000 0xec0000>;
-                                       label = "stock-jffs2";
-                                       read-only;
-                               };
-
-                               hwinfo: partition@3f00000 {
+                               partition@3f00000 {
                                        reg = <0x3f00000 0x20000>;
                                        label = "hw-info";
                                        read-only;
+
+                                       compatible = "nvmem-cells";
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       macaddr_hwinfo_0: macaddr@0 {
+                                               reg = <0x0 0x6>;
+                                       };
                                };
 
                                partition@3f20000 {
                                        label = "u-boot";
                                        read-only;
                                };
-
-                               firmware@0 {
-                                       reg = <0x0 0x3040000>;
-                                       label = "firmware";
-                               };
                        };
                };
        };
        };
 };
 /include/ "fsl/p1020si-post.dtsi"
-
-&hwinfo {
-       compatible = "nvmem-cells";
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       macaddr_hwinfo_0: macaddr@0 {
-               reg = <0x0 0x6>;
-       };
-};
index a127723e897d7055f07f286824433c964ca8c3aa..fff2c3931f826410e2afa3a6af0670caa773e4d6 100644 (file)
@@ -1,17 +1,58 @@
+define Build/MultiImage
+        rm -rf $@.fakerd $@.new
+
+        dd if=/dev/zero of=$@.fakerd bs=32 count=1 conv=sync
+
+        -$(STAGING_DIR_HOST)/bin/mkimage -A $(LINUX_KARCH) -O linux -T multi -C $(1)  \
+               -a $(KERNEL_LOADADDR) -e $(KERNEL_ENTRY) -n '$(BOARD_NAME) initramfs' \
+               -d $@:$@.fakerd:$(KDIR)/image-$(firstword $(DEVICE_DTS)).dtb $@.new
+        mv $@.new $@
+        rm -rf $@.fakerd
+endef
+
 define Device/aerohive_hiveap-330
   DEVICE_VENDOR := Aerohive
   DEVICE_MODEL := HiveAP-330
   DEVICE_PACKAGES := kmod-tpm-i2c-atmel
   BLOCKSIZE := 128k
-  KERNEL := kernel-bin | gzip | uImage gzip
-  KERNEL_SIZE := 8m
-  KERNEL_INITRAMFS := copy-file $(KDIR)/vmlinux-initramfs | uImage none
-  IMAGES := fdt.bin sysupgrade.bin
-  IMAGE/fdt.bin := append-dtb
-  IMAGE/sysupgrade.bin := append-dtb | pad-to 256k | check-size 256k | \
-       append-uImage-fakehdr ramdisk | pad-to 256k | check-size 512k | \
-       append-rootfs | pad-rootfs $$(BLOCKSIZE) | pad-to 41216k | check-size 41216k | \
-       append-kernel | append-metadata
+  KERNEL := kernel-bin | uImage none
+  KERNEL_INITRAMFS := kernel-bin | MultiImage none
+  KERNEL_SIZE := 16m
+  IMAGES := sysupgrade.bin
+  IMAGE/sysupgrade.bin := append-dtb | pad-to 256k | append-kernel | \
+       append-rootfs | pad-rootfs | check-size | append-metadata
+  IMAGE_SIZE = 63m
+  DEVICE_COMPAT_VERSION := 2.0
+  DEVICE_COMPAT_MESSAGE := \n$\
+    !The partitioning of the HiveAP 330 has changed! \n$\
+    To upgrade, please take a look at the install instructions over \
+    at the device's wiki: <https://openwrt.org/toh/aerohive/hiveap-330> \n$\
+    An abridged version for the console is provided here for comfort. \n$\
+    Run the following script into a shell on the device and retry this \
+    sysupgrade again: \n$\
+    cat <<- "EOF" > /tmp/uboot-fix.sh; sh /tmp/uboot-fix.sh \n$\
+    . /lib/functions.sh \n$\
+    . /lib/functions/system.sh \n$\
+    opkg update && opkg install uboot-envtools kmod-mtd-rw || exit 2 \n$\
+    insmod mtd-rw i_want_a_brick=y || exit 3 \n$\
+    echo "/dev/mtd$$$$(find_mtd_index u-boot-env) 0x0 0x20000 0x10000" > "/etc/fw_env.config" \n$\
+    fw_setenv owrt_boot 'setenv bootargs console=ttyS0,9600;bootm 0xEC040000 - 0xEC000000' \n$\
+    cp "/dev/mtd$$$$(find_mtd_index 'u-boot')" /tmp/uboot \n$\
+    cp /tmp/uboot /tmp/uboot_patched \n$\
+    strings -td < /tmp/uboot | grep '^ *[0-9]* *\\(run owrt_boot\\|setenv bootargs\\).*cp\\.l' | \n$\
+       awk '{print $$$$1}' | \n$\
+       while read offset; do \n$\
+         echo -n "run owrt_boot;            " | dd of=/tmp/uboot_patched bs=1 seek=$$$${offset} conv=notrunc \n$\
+       done \n$\
+       mtd write /tmp/uboot_patched u-boot \n$\
+       uci set system.@system[0].compat_version=2.0; uci commit; \n$\
+    EOF \n$\
+    \n$\
+    Note that if this fails, you will need to use the serial console \n$\
+    to re-install OpenWrt. \n$\
+    Note that after this sysupgrade, the AP will be unavailable for 7 \n$\
+    minutes to reformat flash."
+
 endef
 TARGET_DEVICES += aerohive_hiveap-330
 
@@ -28,7 +69,7 @@ TARGET_DEVICES += enterasys_ws-ap3710i
 define Device/ocedo_panda
   DEVICE_VENDOR := OCEDO
   DEVICE_MODEL := Panda
-  DEVICE_PACKAGES := kmod-rtc-ds1307 uboot-envtools
+  DEVICE_PACKAGES := kmod-rtc-ds1307
   KERNEL = kernel-bin | gzip | fit gzip $(KDIR)/image-$$(DEVICE_DTS).dtb
   PAGESIZE := 2048
   SUBPAGESIZE := 512
index d0bf77076882ba682b5bc476f0d6276b15f58c2a..31fce8b60ab529140f6a66bfb53cad1f66b14df5 100644 (file)
@@ -24,6 +24,7 @@ CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_SPLIT_FIRMWARE=y
 CONFIG_MTD_SPLIT_FIT_FW=y
+CONFIG_MTD_SPLIT_UIMAGE_FW=y
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_BEB_LIMIT=20
 CONFIG_MTD_UBI_BLOCK=y