= Installing OpenWrt on a Cisco Meraki MR24 = RussellSenior and PersonalTelco have separately purchased a bunch of these. The following is a description of how to get an OpenWrt image on them as of 2022-08-01, using Russell's method. The instructions here are mostly derived from [[https://github.com/riptidewave93/Openwrt-MR24|here]], but adapted and refined a little bit. ------ <> ------ == Description == The Meraki MR24 is a dual-band, single-ethernet router using a PPC cpu and two ath9k radios with 3x3 MIMO channels. It draws about 7.4 watts, 0.156 amps, at 48V PoE. The MR24 is intended for wall mounting and has a steel backing plate. == Overview == The Meraki MR24 has 32MB of NAND flash. It is formatted as follows: * 0x000000000000-0x000000150000 : "u-boot" * 0x000000150000-0x000000160000 : "u-boot-env" * 0x000000160000-0x000000170000 : "u-boot-env-redundant" * 0x000000170000-0x000000180000 : "oops" * 0x000000180000-0x000002000000 : "ubi" The general idea is to install two different operating systems: * one is a pared down "recovery" firmware, that includes an initramfs root filesystem. This implies that it has no persistent storage filesystem. The u-boot environment is modified so that it only boots into the recovery firmware when the reset button is held as it is booting. It is installed into one ubi partition. * the other is the normal OpenWrt system, and is installed into three separate ubi partitions: kernel, rootfs (read-only squashfs), rootfs_data (read/write ubifs) Two methods for accomplishing this goal ("serial console" and "factory_boot" ) are now presented. == Instructions for serial console install == In this process, the case is opened and u-boot is manipulated from the serial console. Two MR24 firmwares need to be built: * recovery: A kernel-initramfs.bin to be written to a recovery ubi volume. It will be configured to boot if the reset is held while the device is powered on. * regular: A regular squashfs-sysupgrade.bin that boots from flash normally (i.e. without the reset button held) as desired for the application. Two machines are needed: * a TFTP server: to serve an kernel-initramfs.bin to allow flashing the recovery and regular firmware images; * an ssh server: to receive flash backups and host recovery and regular firmware images; === Preparing the recovery firmware === 1. Pare down a .config to a minimum: {{{ CONFIG_TARGET_apm821xx=y CONFIG_TARGET_apm821xx_nand=y CONFIG_TARGET_apm821xx_nand_DEVICE_meraki_mr24=y CONFIG_DEVEL=y CONFIG_BUILD_LOG=y # CONFIG_PACKAGE_ppp is not set # CONFIG_PACKAGE_firewall4 is not set # CONFIG_PACKAGE_kmod-nft-offload is not set CONFIG_PACKAGE_uboot-envtools=y }}} 1. Prepare a files overlay: 1. files/etc/uci-defaults/ptp.defaults {{{ #!/bin/sh uci batch <@:/mr24/stock01/ rm /tmp/mtdblock*.img ubinfo -a > /tmp/ubinfo.txt for i in 0 1 2 3 ; do dd if=/dev/ubi0_$i of=/tmp/ubi0_$i.img ; done scp /tmp/ubi* @:/mr24/stock01/ }}} 1. Now reboot to a u-boot prompt again (you might want to disconnect ethernet until you are sure you have a u-boot prompt). You may want to do a power cycle too, in order to clear the previous setenv's you have done. Make sure you've got your initramfs and squashfs-sysupgrade images ready. At the u-boot prompt, you are going to create some new environment variables and to repoint the regular boot command at the openwrt version: {{{ setenv openwrt_loadaddr c00000 setenv openwrt_loadaddr_kernel c10000 setenv openwrt_loadaddr_ramdisk e00000 setenv openwrt_loadaddr_fdt c00400 setenv openwrt_ubi ubi part ubi setenv openwrt_checkpart meraki checkpart \${openwrt_loadaddr} setenv openwrt_bootlinux bootm \${openwrt_loadaddr_kernel} \${openwrt_loadaddr_ramdisk} \${openwrt_loadaddr_fdt} setenv openwrt_load1 ubi read \${openwrt_loadaddr} kernel setenv openwrt_load2 ubi read \${openwrt_loadaddr} recovery setenv openwrt_bootkernel bootm \${openwrt_loadaddr_kernel} - \${openwrt_loadaddr_fdt} setenv openwrt_bootargs setenv bootargs console=ttyS0,\${baudrate} rootfstype=squashfs mtdoops.mtddev=oops setenv openwrt_boot run openwrt_ubi openwrt_bootargs\; run openwrt_load1 openwrt_checkpart openwrt_bootkernel\; run openwrt_load2 openwrt_checkpart openwrt_bootlinux setenv bootcmd run openwrt_boot setenv ipaddr 192.168.80.49 setenv serverip 192.168.80.7 setenv openwrt_bootfile openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin setenv tftpboot_openwrt run openwrt_bootargs\; tftpboot \${openwrt_loadaddr} \${serverpath}\${openwrt_bootfile}\; run openwrt_checkpart openwrt_bootlinux setenv factory_boot run openwrt_bootargs openwrt_ubi\; ubi read \${openwrt_loadaddr} recovery\; run openwrt_checkpart openwrt_bootlinux saveenv }}} or, in fewer lines: {{{ setenv openwrt_loadaddr c00000; setenv openwrt_loadaddr_kernel c10000; setenv openwrt_loadaddr_ramdisk e00000; setenv openwrt_loadaddr_fdt c00400; setenv openwrt_ubi ubi part ubi; setenv openwrt_checkpart meraki checkpart \${openwrt_loadaddr} setenv openwrt_bootlinux bootm \${openwrt_loadaddr_kernel} \${openwrt_loadaddr_ramdisk} \${openwrt_loadaddr_fdt}; setenv openwrt_load1 ubi read \${openwrt_loadaddr} kernel; setenv openwrt_load2 ubi read \${openwrt_loadaddr} recovery setenv openwrt_bootkernel bootm \${openwrt_loadaddr_kernel} - \${openwrt_loadaddr_fdt}; setenv openwrt_bootargs setenv bootargs console=ttyS0,\${baudrate} rootfstype=squashfs mtdoops.mtddev=oops setenv openwrt_boot run openwrt_ubi openwrt_bootargs\; run openwrt_load1 openwrt_checkpart openwrt_bootkernel\; run openwrt_load2 openwrt_checkpart openwrt_bootlinux; setenv bootcmd run openwrt_boot; setenv ipaddr 192.168.80.49; setenv serverip 192.168.80.7 setenv openwrt_bootfile openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin; setenv tftpboot_openwrt run openwrt_bootargs\; tftpboot \${openwrt_loadaddr} \${serverpath}\${openwrt_bootfile}\; run openwrt_checkpart openwrt_bootlinux setenv factory_boot run openwrt_bootargs openwrt_ubi\; ubi read \${openwrt_loadaddr} recovery\; run openwrt_checkpart openwrt_bootlinux; saveenv }}} Up to now, you have not changed anything on flash, but the change in "bootcmd" means you won't boot the meraki firmware anymore. We are about to change things substantially, so hold tight. 1. Boot into the initramfs again: {{{ run tftpboot_openwrt }}} 1. At the OpenWrt shell prompt, carefully do the following: {{{ ubinfo /dev/ubi0 -N board-config }}} Check to make sure that the Volume ID for board-config is 2. If so, first make a copy of the board-config partition to a file in /tmp/, then remove all the ubi volumes, then create a new one and write the board-config image back: {{{ dd if=/dev/ubi0_2 of=/tmp/board-config.img ubirmvol /dev/ubi0 -N part1 ubirmvol /dev/ubi0 -N part2 ubirmvol /dev/ubi0 -N storage ubirmvol /dev/ubi0 -N board-config ubimkvol /dev/ubi0 -s 24KiB -N board-config ubiupdatevol /dev/ubi0_0 /tmp/board-config.img }}} 1. Copy an initramfs image and the sysupgrade image to the MR24's /tmp/ directory (using scp, either pushing or pulling), e.g., from your build machine: {{{ scp bin/targets/apm821xx/nand/openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin root@:/tmp/ scp bin/targets/apm821xx/nand/openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.tar root@:/tmp/ }}} Note that the squashfs-sysupgrade image does not need to be the same vanilla build as the initramfs, and can be a full FooCab build. You can use the vanilla version as a proof of concept, and then sysupgrade from that to arbitrary other sysupgrade images. Obviously, this doesn't replace the "recovery" image, flashed in the next step, but that's okay. 1. On the MR24, check the size of the initramfs image, then if less than 5MB, you can create a recovery ubi partition: {{{ ls -alh /tmp/openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin ubimkvol /dev/ubi0 -s 5MiB -N recovery ubiupdatevol /dev/ubi0_1 /tmp/openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin }}} 1. Now do a sysupgrade from the initramfs, using the squashfs image: {{{ sysupgrade -v -n /tmp/openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.tar }}} When it is done, it will reboot and hopefully boot back to a familiar looking OpenWrt, this time from flash. You might want to reboot a few times to make sure things went okay. == Instructions for factory_boot install == This method exploits the Meraki MR24 out-of-the-box uboot environment variables to enable a TFTP boot into a bootstrap OpenWrt image, from which the uboot environment can be modified, and the ubi volumes updated over an ssh session without the need to open the case, thus substantially speeding up the operation. Three MR24 firmwares need to be built: * bootstrap: A initramfs.bin that provides the components needed to boot from the stock u-boot configuration. * recovery (same as for the serial console install, described previously) * regular (same as for the serial console install, described previously) Two machines are needed: * a TFTP server: to serve components needed for the factory bootstrap. Note that this needs to be set up in a specific way to work with the original u-boot configuration! * an ssh server: to receive flash backups and host recovery and regular firmware images; === Preparing the bootstrap firmware === 1. Disable read-only on the u-boot-env partitions (both of them!) in the device tree source in: target/linux/apm821xx/dts/meraki-mr24.dts 1. Pare down a .config to a minimum: {{{ CONFIG_TARGET_apm821xx=y CONFIG_TARGET_apm821xx_nand=y CONFIG_TARGET_apm821xx_nand_DEVICE_meraki_mr24=y CONFIG_DEVEL=y CONFIG_BUILD_LOG=y # CONFIG_BUSYBOX_DEFAULT_FEATURE_IPV6 is not set # CONFIG_DRIVER_11N_SUPPORT is not set # CONFIG_IPV6 is not set # CONFIG_KERNEL_IPV6 is not set # CONFIG_LUCI_CSSTIDY is not set # CONFIG_LUCI_JSMIN is not set # CONFIG_PACKAGE_dnsmasq is not set # CONFIG_PACKAGE_hostapd-common is not set # CONFIG_PACKAGE_iw is not set # CONFIG_PACKAGE_iwinfo is not set # CONFIG_PACKAGE_jansson is not set # CONFIG_PACKAGE_kmod-ath is not set # CONFIG_PACKAGE_kmod-ath9k is not set # CONFIG_PACKAGE_kmod-cfg80211 is not set # CONFIG_PACKAGE_kmod-crypto-aead is not set # CONFIG_PACKAGE_kmod-crypto-ccm is not set # CONFIG_PACKAGE_kmod-crypto-cmac is not set # CONFIG_PACKAGE_kmod-crypto-crc32c is not set # CONFIG_PACKAGE_kmod-crypto-ctr is not set # CONFIG_PACKAGE_kmod-crypto-gcm is not set # CONFIG_PACKAGE_kmod-crypto-gf128 is not set # CONFIG_PACKAGE_kmod-crypto-ghash is not set # CONFIG_PACKAGE_kmod-crypto-hash is not set # CONFIG_PACKAGE_kmod-crypto-hmac is not set # CONFIG_PACKAGE_kmod-crypto-manager is not set # CONFIG_PACKAGE_kmod-crypto-null is not set # CONFIG_PACKAGE_kmod-crypto-rng is not set # CONFIG_PACKAGE_kmod-crypto-seqiv is not set # CONFIG_PACKAGE_kmod-crypto-sha256 is not set # CONFIG_PACKAGE_kmod-gpio-button-hotplug is not set # CONFIG_PACKAGE_kmod-i2c-core is not set # CONFIG_PACKAGE_kmod-lib-crc-ccitt is not set # CONFIG_PACKAGE_kmod-lib-crc32c is not set # CONFIG_PACKAGE_kmod-mac80211 is not set # CONFIG_PACKAGE_kmod-nf-conntrack is not set # CONFIG_PACKAGE_kmod-nf-flow is not set # CONFIG_PACKAGE_kmod-nf-log is not set # CONFIG_PACKAGE_kmod-nf-nat is not set # CONFIG_PACKAGE_kmod-nf-reject is not set # CONFIG_PACKAGE_kmod-nfnetlink is not set # CONFIG_PACKAGE_kmod-nft-core is not set # CONFIG_PACKAGE_kmod-nft-fib is not set # CONFIG_PACKAGE_kmod-nft-nat is not set # CONFIG_PACKAGE_kmod-ppp is not set # CONFIG_PACKAGE_libiwinfo is not set # CONFIG_PACKAGE_libmnl is not set # CONFIG_PACKAGE_libnftnl is not set # CONFIG_PACKAGE_libucode is not set # CONFIG_PACKAGE_libustream-wolfssl is not set # CONFIG_PACKAGE_libwolfssl is not set # CONFIG_PACKAGE_nftables-json is not set # CONFIG_PACKAGE_ppp is not set # CONFIG_PACKAGE_ucode is not set # CONFIG_PACKAGE_wireless-regdb is not set # CONFIG_PACKAGE_wpad-basic-wolfssl is not set CONFIG_TARGET_ROOTFS_CPIOGZ=y # CONFIG_TARGET_ROOTFS_SQUASHFS is not set # CONFIG_WPA_WOLFSSL is not set }}} 1. Prepare a files overlay: 1. files/etc/uci-defaults/ptp.defaults {{{ #!/bin/sh uci batch < /tmp/ubootenv.txt scp /tmp/ubootenv.txt ${user}@${dest}:mr24/$macaddr/ for i in 0 1 2 3 4 ; do dd if=/dev/mtdblock$i of=/tmp/mtdblock$i.img bs=16k conv=noerror scp /tmp/mtdblock$i.img ${user}@${dest}:mr24/$macaddr/ rm /tmp/mtdblock$i.img done ubinfo -a > /tmp/ubinfo.txt scp /tmp/ubinfo.txt ${user}@${dest}:mr24/$macaddr/ for i in 0 1 2 3 ; do dd if=/dev/ubi0_$i of=/tmp/ubi0_$i.img bs=15872 scp /tmp/ubi0_$i.img ${user}@${dest}:mr24/$macaddr/ rm /tmp/ubi0_$i.img done }}} 1. files/usr/bin/install-recovery {{{ #!/bin/sh user=grabber dest=dest.mr24 fname=openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin scp ${user}@${dest}:mr24/images/${fname} /tmp/ if [ -f "/tmp/${fname}" ]; then size=$(ls -l /tmp/${fname} | awk '{ print $5 }') ubirmvol /dev/ubi0 -N part1 ubirmvol /dev/ubi0 -N part2 ubirmvol /dev/ubi0 -N storage if ! ubinfo /dev/ubi0 -N recovery 2>/dev/null > /dev/null ; then ubimkvol /dev/ubi0 -s ${size} -N recovery fi volid=$(ubinfo /dev/ubi0 -N recovery | awk '$0 ~ /Volume ID/ { print $3 }') volsz=$(cat /sys/devices/virtual/ubi/ubi0/ubi0_${volid}/data_bytes) if [ "$size" -gt "$volsz" ]; then ubirsvol /dev/ubi0 -N recovery -s ${size} fi ubiupdatevol /dev/ubi0_${volid} /tmp/${fname} sync exit 0 else exit 1 fi }}} 1. files/usr/bin/fetch_image.sh {{{ #!/bin/sh user=grabber dest=dest.mr24 fname=openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin scp ${user}@${dest}:mr24/images/${fname} /tmp/ }}} 1. files/root/.ssh/known_hosts This is the host public key for dest.mr24 so that we aren't queried on every device 1. files/root/.ssh/id_dropbear A dropbear ssh private key to allow access a remote server "dest.mr24" without needing a password (add the public key to the remote server's user grabber's .ssh/authorized_keys. 1. After the bootstrap image is created, you will need to prepare the three files that will be served to the MR24 over TFTP: 1. uImage -- this is just the renamed initramfs binary that OpenWrt builds for you {{{ $ ln bin/targets/apm821xx/nand/openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin bin/targets/apm821xx/nand/uImage }}} 1. bluestone.dtb -- this can be extracted from a initramfs.bin. Find the dtb magic number in a resulting initramfs: {{{ $ binwalk bin/targets/apm821xx/nand/uImage DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 uImage header, header size: 64 bytes, header CRC: 0x767534D2, created: 2022-08-08 07:17:37, image size: 3840204 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0x7C3D55D1, OS: Linux, CPU: PowerPC, image type: Multi-File Image, compression type: lzma, image name: "mr24 initramfs" 80 0x50 LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 9385248 bytes 3775756 0x399D0C Flattened device tree, size: 64512 bytes, version: 17 }}} for me, this was at an offset of 3775756 bytes, the 64512 byte dtd blob was extracted like this: {{{ $ dd if=bin/targets/apm821xx/nand/uImage bs=3775756 skip=1 count=1 | dd bs=64512 count=1 of=bin/targets/apm821xx/nand/bluestone.dtb }}} 1. uRamdisk -- Due to limitations of the vendor u-boot-env, uRamdisk needs to be 2MB or less. The uRamdisk file needs a uImage header, which can be generated something like this: {{{ $ staging_dir/host/bin/mkimage -A powerpc -T ramdisk -O linux -d bin/targets/apm821xx/nand/openwrt-apm821xx-nand-rootfs.cpio.gz bin/targets/apm821xx/nand/uRamdisk }}} === Setting up the TFTP server === 1. I used a Buffalo WZR600DHP router, partly because it has a prodigious amount of NOR flash (32MB) that would allow holding the payloads without extra or external storage. 1. On top of standard OpenWrt, I installed the package atftpd. If you build it into your Buffalo firmware, this init script should be enabled automatically, but if you install from a package repository, you'll need to manually enable it, e.g.: {{{ # /etc/init.d/atftpd enable }}} 1. The Meraki u-boot environment assumes a serverip of 192.168.1.101, and an ipaddr of 192.168.1.1. The ipaddr isn't important to the TFTP server, but the server address most definitely is. You can set the LAN ip address of your OpenWrt TFTP server with a command like: {{{ # uci set network.lan.ipaddr=192.168.1.101 # uci commit network }}} Make sure the network the TFTP server's WAN port is plugged into has a different network than 192.168.1.0/24 or your routing won't work. 1. Create the directory that will house the TFTP blobs: {{{ # mkdir -p /srv/tftp }}} 1. Place the three files: 1. uImage 1. bluestone.dtb 1. uRamdisk into /srv/tftp === Set up the backup/firmware host === To make the process run smoothly, we need an ssh host that can install the public key corresponding to the one installed in the bootstrap and recovery MR24 images. We create a temporary account on the ssh host "grabber", where we can write backups and fetch the recovery image during the bootstrap phase, and where we can fetch the firmware (of your choice) that is installed on the MR24. On an Ubuntu 20.04 machine: 1. {{{sudo adduser grabber}}} 1. {{{sudo su - grabber}}} 1. {{{ssh-keygen -t ed25519}}} -- this is mainly just to create the .ssh directory with the correct permissions 1. {{{vi .ssh/authorized_keys}}} --- and insert the public key corresponding to the dropbear private key included in the bootstrap and recovery images. You can obtain the public key using {{{dropbearkey -f /root/.ssh/id_dropbear -y}}} and you'll see a line that looks like: {{{ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHDHgF0DNo9+ykxaTcF2KCItlco75qa6yGFJHlaBaDo4 root@recovery}}} 1. {{{mkdir -p mr24/images}}} 1. Place the recovery firmware {{{openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin}}} and the final firmware {{{openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin}}} in mr24/images === Installation steps === 1. Attach an ethernet cable from the TFTP server to the MR24 to be installed. 1. With a straightened paper clip or similar device, press and hold the reset button. 1. Plug in 12V power to the MR24 and continue holding the reset button for approximately 8-10 seconds. 1. The MR24 should fetch the kernel, dtb and initramfs from the TFTP server and boot. If doing this for the first time, it is wise to disassemble the device and attach a serial console to enable intervention at the u-boot console, if needed. However, note that with the default u-boot environment, the serial console will not function after the tftp'd kernel boots. 1. Examine the DHCP leases on the network where the MR24 was plugged in. The MR24 uses a preconfigured ipaddr while in u-boot and tftp'ing, but the booted operating system will used DHCP to request a lease. The DHCP leases will indicate which address it was allocated. 1. Ssh to the indicated address: {{{ # ssh root@${ipaddr} }}} No password is required at this stage. 1. Save backups of the flash using the backup-mtd script (see above): {{{ # backup-mtd }}} Check to make sure the results make sense. This is your only chance to preserve the original configuration, you may need this later down the road to reconstruct state. It is a '''''REALLY GOOD IDEA''''' to keep these copies and to make sure they are complete. 1. Examine the ubi, it will look something like this: {{{ # ubinfo -a UBI version: 1 Count of UBI devices: 1 UBI control device major/minor: 10:59 Present UBI devices: ubi0 ubi0 Volumes count: 4 Logical eraseblock size: 15872 bytes, 15.5 KiB Total amount of logical eraseblocks: 1952 (30982144 bytes, 29.5 MiB) Amount of available logical eraseblocks: 243 (3856896 bytes, 3.6 MiB) Maximum count of volumes 92 Count of bad physical eraseblocks: 0 Count of reserved physical eraseblocks: 40 Current maximum erase counter value: 2976 Minimum input/output unit size: 512 bytes Character device major/minor: 251:0 Present volumes: 0, 1, 2, 3 Volume ID: 0 (on ubi0) Type: dynamic Alignment: 1 Size: 567 LEBs (8999424 bytes, 8.5 MiB) State: OK Name: part1 Character device major/minor: 251:1 ----------------------------------- Volume ID: 1 (on ubi0) Type: dynamic Alignment: 1 Size: 567 LEBs (8999424 bytes, 8.5 MiB) State: OK Name: part2 Character device major/minor: 251:2 ----------------------------------- Volume ID: 2 (on ubi0) Type: dynamic Alignment: 1 Size: 2 LEBs (31744 bytes, 31.0 KiB) State: OK Name: board-config Character device major/minor: 251:3 ----------------------------------- Volume ID: 3 (on ubi0) Type: dynamic Alignment: 1 Size: 529 LEBs (8396288 bytes, 8.0 MiB) State: OK Name: storage Character device major/minor: 251:4 }}} 1. Fetch the recovery firmware and prepare the ubi with the /usr/bin/install-recovery script (see above): 1. Check the state of the u-boot environment: {{{ # fw_printenv Warning: Bad CRC, using default environment bootcmd=bootp; setenv bootargs root=/dev/nfs nfsroot=${serverip}:${rootpath} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off; bootm bootdelay=5 baudrate=115200 }}} If you see the "Bad CRC", then use the combined.ubootenv you prepared earlier, to write a full u-boot environment: {{{ # fw_setenv -s /etc/combined.ubootenv Warning: Bad CRC, using default environment }}} and then check the result: {{{ # fw_printenv bootdelay=1 baudrate=115200 preboot=echo;echo Set serverpath and run meraki_netboot to netboot;echo nload=${netloadmethod} 600000 ${serverpath}u-boot-nand.bin nupdate=nand erase 0 0x00170000 ;nand write 600000 0 0x00100000 nupd=run nload nupdate kernel_addr=fc000000 fdt_addr=fc1e0000 ramdisk_addr=fc200000 pciconfighost=1 pcie_mode=RP:RP netdev=eth0 netloadmethod=dhcp ethact=ppc_4xx_eth0 ethaddr=00:01:73:01:23:41 boardtype=pcie mtd_addr_r=0x4000000 kernel_size=0x400000 fdt_size=0x25000 meraki_bootargs=setenv bootargs root=/dev/ram console=ttyS0,${baudrate} ubi.mtd=ubi MERAKI_BOARD=mr24 mtdoops.mtddev=oops ${extra_bootargs} meraki_bootfile=mr24.bin meraki_bootlinux=bootm ${meraki_loadaddr_kernel} ${meraki_loadaddr_ramdisk} ${meraki_loadaddr_fdt} meraki_boot=run meraki_ubi meraki_bootargs ; run meraki_load1 meraki_checkpart meraki_bootlinux; run meraki_load2 meraki_bootlinux meraki_checkpart=meraki checkpart ${meraki_loadaddr} meraki_netboot=run meraki_load_net meraki_bootargs meraki_bootlinux meraki_loadaddr=c00000 meraki_loadaddr_kernel=c10000 meraki_loadaddr_fdt=c00400 meraki_loadaddr_ramdisk=e00000 meraki_load1=ubi read ${meraki_loadaddr} part1 meraki_load2=ubi read ${meraki_loadaddr} part2 meraki_load_net=${netloadmethod} ${meraki_loadaddr} ${serverpath}${meraki_bootfile} meraki_ubi=ubi part ubi meraki_ubifile=mr24-ubi.bin meraki_ubi_loadfile=${netloadmethod} 600000 ${serverpath}${meraki_ubifile} meraki_ubi_update_nand=nand erase 0x00180000 0x01e80000 ; nand write 600000 0x00180000 ${filesize} meraki_ubi_update=run meraki_ubi_loadfile meraki_ubi_update_nand meraki_update_part1=run meraki_ubi meraki_load_net meraki_write1 meraki_update_part2=run meraki_ubi meraki_load_net meraki_write2 meraki_write1=ubi write ${meraki_loadaddr} part1 ${filesize} meraki_write2=ubi write ${meraki_loadaddr} part2 ${filesize} mtdids=nand0=nand0 mtdparts=mtdparts=nand0:0x00170000@0(firmware),0x00010000@0x00170000(panic),0x01e80000@0x00180000(ubi) ipaddr=192.168.1.1 serverip=192.168.1.101 gatewayip=192.168.1.1 netmask=255.255.255.0 factory_cmdline=setenv bootargs root=/dev/ram ramdisk_size=${factory_ramdisk_size} rw ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1 console=ttyS1,${baudrate} factory_ramdisk_file=uRamdisk factory_bootfile=uImage factory_fdt_file=bluestone.dtb factory_kernel_addr_r=0x600000 factory_fdt_addr_r=0xa00000 factory_mtd_addr_r=0x4000000 factory_ramdisk_size=0x200000 ver=U-Boot 2010.06-00036-g4e1a276 Meraki MR24 (May 11 2012 - 16:57:49) openwrt_load=ubi read ${meraki_loadaddr} kernel openwrt_recovery=ubi read ${meraki_loadaddr} recovery;bootm ${meraki_loadaddr} openwrt_bootkernel=bootm ${meraki_loadaddr_kernel} - ${meraki_loadaddr_fdt} openwrt_bootargs=setenv bootargs console=ttyS0,${baudrate} rootfstype=squashfs mtdoops.mtddev=oops openwrt_boot=run meraki_ubi openwrt_bootargs;run openwrt_load meraki_checkpart openwrt_bootkernel;run openwrt_recovery openwrt_bootfile=openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin openwrt_tftp=tftpboot ${meraki_loadaddr} ${openwrt_bootfile};run openwrt_bootargs;bootm ${fileaddr} bootcmd=run openwrt_boot factory_boot_orig=tftp ${factory_kernel_addr_r} ${factory_bootfile};tftp ${factory_fdt_addr_r} ${factory_fdt_file};tftp ${factory_mtd_addr_r} ${factory_ramdisk_file};run factory_cmdline;bootm ${factory_kernel_addr_r} ${factory_mtd_addr_r} ${factory_fdt_addr_r} factory_boot=run meraki_ubi;run openwrt_bootargs;run openwrt_recovery }}} 1. Reboot into recovery firmware: {{{ # reboot }}} 1. Look for the DHCP lease of the device and log in to the recover firmware, and fetch the sysupgrade.bin firmware. For some reason the DNS lookup for the name dest.mr24 which works in the bootstrap firmware does not work in the recovery firmware, so add a line to /etc/hosts with the appropriate ip address, e.g.: {{{ echo 192.168.80.12 dest.mr24 >> /etc/hosts }}} and then run fetch_image2.sh: {{{ #!/bin/sh user=grabber dest=dest.mr24 fname=openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin scp ${user}@${dest}:mr24/images/${fname} /tmp/ }}} 1. Use sysupgrade to install the normal OpenWrt firmware: {{{ # sysupgrade -v -n /tmp/openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin }}} 1. The MR24 will install the firmware and reboot. Look for dhcp leases again and try ssh'ing into the device to confirm success. Try a "factory_boot" with the reset button pressed at power-on to confirm the recovery firmware works as well. 1. If something went wrong and you can't get access to the device, you will need to open the device to get access to the u-boot prompt. Recovery should be possible from there, though that is left as an exercise for the reader. Hopefully, enough artifacts have been collected to recover. If the u-boot environment is lost or hopelessly mangled, you might be able to erase the blocks where the u-boot environment usually lives to recover (note the address ranges, from dmesg): {{{ [ 1.493402] nand: device found, Manufacturer ID: 0xad, Chip ID: 0x75 [ 1.602330] 0x000000000000-0x000000150000 : "u-boot" [ 1.603070] 0x000000150000-0x000000160000 : "u-boot-env" [ 1.603622] 0x000000160000-0x000000170000 : "u-boot-env-redundant" [ 1.604132] 0x000000170000-0x000000180000 : "oops" [ 1.604680] 0x000000180000-0x000002000000 : "ubi" }}} '''''DO NOT ERASE THE WRONG THINGS.''''' 1. Having completed the installation of MR24's, disable logins to the grabber account and move the backups somewhere safe for longterm storage. = Updating Recovery Firmware = Over the course of acquiring MR24's, a variety of recovery firmwares have been installed. 1. (A) kernel 4.4.21 : Sat Sep 17 19:43:29 2016 -- LEDE (old u-boot-env variables); 1. (B) kernel 4.9.20 : Tue Apr 04 13:06:14 2017 -- LEDE (old u-boot-env variables); 1. (C) kernel 4.14.20 : Thu Feb 22 22:40:16 2018 -- OpenWrt (old u-boot-env variables); 1. (D) kernel 4.19.72 : Sat Sep 14 17:38:48 2019 -- OpenWrt (SSID: OpenWrt currrent u-boot-env variables, includes a firewall which makes it unreachable from ethernet side); As time has passed, shortcomings have been observed in older Recovery Firmware, and corrected in a new Recovery Firmware. The following instructions provide a guide for updating the Recovery Firmware to on MR24s based on the peculiarites in the exsting versions. It assumes that the factory_boot router is available, you are logged into it, and that two firmwares: the replacement {{{recovery.bin}}} and a full featured (including fw_printenv/fw_setenv) normal squashfs-sysupgrade {{{final.bin}}}, and a uboot.env (the combined.ubootenv) are located on the factory_boot router in its {{{/tmp}}} directory. 1. With power off, hold reset button, apply power, after 5 seconds release. 1. Alternative if you can't reach the reset button: 1. Log in to the normal firmware 1. Check ubi volumes: {{{ubinfo -a}}} 1. Remove the kernel ubi volume, which should force booting from the Recovery Firmware: {{{ubirmvol /dev/ubi0 -N kernel}}} 1. Watch for the DHCP lease request from the MR24 with {{{logread -f}}} 1. If you notice no hostname is advertised on the DHCP lease, you may have firmware (C), in which case you have additional problems, including the firewall is active and won't allow connections from the ethernet side and the LAN side of the MR24 configuration has a conflicting network (192.168.1.0/24). To work around: 1. Connect wirelessly to the "OpenWrt" network 1. SSH to the MR24 over wifi: {{{ssh root@192.168.1.1}}} 1. Stop the firewall: {{{/etc/init.d/firewall stop}}} 1. To avoid conflicting networks, change the MR24's LAN: {{{uci set network.lan.ipaddr=192.168.2.1}}} 1. Restart the network: {{{/etc/init.d/network restart}}} 1. From the factory_boot router, copy all the potentially required files (you may need to adapt the hostname depending on the Recovery Firmware version): {{{ scp /tmp/recovery.bin /tmp/final.bin /tmp/uboot.env recovery:/tmp/ }}} 1. Log in to the MR24's Recovery Firmware 1. Check version using {{{uname -a}}}, try running fw_printenv, and check the SSID with {{{iwinfo}}} to held identify what is running, you will need this information soon. 1. Check the ubi volumes with {{{ubinfo -a}}}, and note the index of the existing "recovery" volume, we will call it: M 1. Apply the following changes: {{{ ubirmvol /dev/ubi0 -N rootfs_data ubirmvol /dev/ubi0 -N rootfs ubirmvol /dev/ubi0 -N kernel ubirsvol /dev/ubi0 -S 345 -N recovery ubiupdatevol /dev/ubi0_M /tmp/recovery.bin }}} Note ubi0_M where M is the ubi volume index. 1. If the Recovery Firmware is (A) or (B) or possibly (C), the u-boot environment won't successfully boot the new recovery.bin without changes and we need to work around that. The key thing is whether fw_printenv/fw_setenv works and whether there are any "lede" items in the u-boot environment. If there are lede items in the u-boot environment (or if, like (A) and (B), you can't tell), then rebooting now will lead to a brick. Instead: 1. Flash a regular firmware you login to and run fw_printenv/fw_setenv, with: {{{sysupgrade -v -n /tmp/final.bin}}}, and the MR24 should reboot into the "final.bin" firmware 1. Watch for the DHCP lease request from the MR24 with {{{logread -f}}} 1. Copy the clean environment "script" onto the MR24: {{{scp /tmp/uboot.env cat:/tmp/}}} where "cat" is placeholder name of the rebooted MR24 1. Login to "cat": {{{ssh cat}}} 1. Find the lede environment variables you want to remove: {{{fw_printenv | grep lede | cut -d= -f1 > /tmp/lede.env}}} 1. Concatenate the lede environment variables (since we remove the assignment value from each line, they'll be deleted in the next step) with the desired environment: {{{cat /tmp/lede.env /tmp/uboot-env > /tmp/final.env}}} 1. Apply the final.env: {{{fw_setenv -s /tmp/final.env}}} 1. Check the resulting u-boot environment with {{{fw_printenv}}} 1. Force booting the new Recovery Firmware by removing the "kernel" ubi volume: {{{ubirmvol /dev/ubi0 -N kernel}}} 1. Now continue with the normal steps 1. Reboot the MR24 and close the ssh session: {{{reboot ; exit}}} 1. Watch for the DHCP lease from the newly flashed firmware with {{{logread -f}}} 1. Login to the new Recovery Firmware: {{{ssh recovery}}} (note, no password is needed) 1. For some reason, at this stage, DNS resolution doesn't work for the firmware hosting machine (dest.mr24, from the earlier instructions, so setup a /etc/hosts record: {{{echo 192.168.80.12 dest.mr24 >> /etc/hosts}}} 1. Use the script builtin to the new Recovery Firmware to fetch the new final firmware from dest.mr24: {{{fetch_image2.sh}}} (you will need to accept the host key of the dest.mr24) 1. Use sysupgrade to flash to final firmware: {{{sysupgrade -v -n /tmp/openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin}}} 1. Watch for the DHCP lease from the newly flashed firmware with {{{logread -f}}} 1. You are done! If you are super careful, you may be able to replace the Recovery Firmware without touching the device, but you will need the MR24 to be accessible over the network. If the MR24 is the gateway device, the Recovery Firmware is not going to have a VPN tunnel, so you will at least need to be on-site. ---- [CategoryHardware] [CategoryVendor]