mpc85xx: Patch HiveAP 330 u-boot to fix boot

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:

- b683f1c36d ("mpc85xx: Use gzip compressed kernel on HiveAP-330")
- 98089bb8ba ("mpc85xx: Use uncompressed kernel on the HiveAP-330")
- 26cb167a5c ("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>
This commit is contained in:
Martin Kennedy 2021-12-22 13:08:33 -05:00 committed by Christian Lamparter
parent fbb8e1ef45
commit cfe79f2eb8
6 changed files with 91 additions and 48 deletions

View 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

View 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))

View File

@ -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

View File

@ -22,10 +22,6 @@
label-mac-device = &enet0;
};
chosen {
bootargs-override = "console=ttyS0,9600";
};
memory {
device_type = "memory";
};
@ -47,36 +43,41 @@
#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 {
@ -101,11 +102,6 @@
label = "u-boot";
read-only;
};
firmware@0 {
reg = <0x0 0x3040000>;
label = "firmware";
};
};
};
};
@ -242,13 +238,3 @@
};
};
/include/ "fsl/p1020si-post.dtsi"
&hwinfo {
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
macaddr_hwinfo_0: macaddr@0 {
reg = <0x0 0x6>;
};
};

View 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

View 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