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 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
- 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
- Prepare a files overlay:
- files/etc/uci-defaults/ptp.defaults
uci batch <<EOF set dhcp.@dnsmasq[0].domainneeded=0 set dhcp.@dnsmasq[0].boguspriv=0 set dhcp.@dnsmasq[0].localise_queries=0 set dhcp.@dnsmasq[0].expandhosts=0 set dhcp.@dnsmasq[0].nohosts=0 add_list dhcp.@dnsmasq[0].notinterface=eth0 commit dhcp delete network.globals del_list network.@device[0].ports=eth0 set network.lan.ipaddr=192.168.11.1 set network.lan.ip6assign=64 set network.wan=interface set network.wan.proto=dhcp set network.wan.device=eth0 set network.wan6=interface set network.wan6.device='@wan' set network.wan6.proto='dhcpv6' set network.wan6.reqprefix='60' commit network set system.@system[0].hostname=recovery set system.@system[0].timezone='PST8PDT,M3.2.0,M11.1.0' commit system set wireless.radio0.disabled=0 set wireless.radio1.disabled=0 set wireless.default_radio0.ssid=RECOVERY set wireless.default_radio1.ssid=RECOVERY commit wireless EOF
- files/etc/dropbear/dropbear_rsa_host_key
- files/etc/dropbear/dropbear_ed25519_host_key
- Stable host keys (rsa and ed25519) so that ssh'ing to the "bootstrap" device won't trigger a balk from ssh when connecting over the network.
- files/usr/bin/fetch_image.sh
user=grabber dest=dest.mr24 fname=openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin scp ${user}@${dest}:mr24/images/${fname} /tmp/
- files/root/.ssh/known_hosts
- This is the host public key for dest.mr24 so that we aren't queried on every device
- 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.
- files/etc/uci-defaults/ptp.defaults
Preparing the OpenWrt firmware
This part depends on the intention for the device, PTP gateway or Dumb AP, or whatever. This is up to you to figure out and, naturally, can change as your needs change.
Installation steps
- To open an MR24, first remove 6 screws from around the circumference of the plastic case. The screws are T-6 torx head screws, pretty small, don't lose them ;-). It is a little tricky to free the plastic covers, there are three catches on each long edge and two on each short edge. Starting near the ethernet connector on the long edge with a guitar pick or something similar eventually worked for me.
- Once the plastic is removed, you need to remove 4 phillips head screws holding the circuit board to the steel backing plate. Once freed, you will want to rest the board with the antenna down, but suspended in a way that the delicate antenna bits are not bent.
- So that the devices do not succeed in phoning home to Meraki World Headquarters, it is recommended to not connect ethernet to the device until you have managed to stop the device at a u-boot prompt.
- With the antenna down, and the ethernet jack facing you, the serial console (3.3V TTL) 4 pin header is located at J2 on the right edge about 2/3 of the way to the back, also labelled UART. Only the three closest pins should be connected (from nearest: BLACK (GND), GREEN (board's RX, cable's TX), WHITE (board's TX, cable's RX), NC. Do NOT connect the red wire (it is the 5V USB supply voltage, the NC pin will probably have 3.3V supplied by the board. Again DO NOT connect the red wire from the serial cable.
- Configure your serial console software. Russell uses GNU Screen from linux. Plug in your USB-serial 3.3V TTL console cable to your computer, and check "dmesg | tail" to see how the usb-serial device enumerated itself. If it's the only one, it will probably be ttyUSB0. In that case, you can start a console session with: screen /dev/ttyUSB0 115200. It is nice to keep a record of your doings, so turn on logging with: C-a H (if this is your only screen window, your log file will appear in screenlog.0.
- Attach a 12V power supply to the barrel jack or 48V PoE. Watch the device begin to boot.
- To stop at a u-boot prompt, start pressing the space bar very early. It only pauses for 1 second, but it will recognize a space hit a bit early. You should see something like this:
U-Boot 2010.06-00036-g4e1a276 Meraki MR24 (May 11 2012 - 16:57:49) CPU: AMCC PowerPC UNKNOWN (PVR=12c41c82) at 800 MHz (PLB=200 OPB=100 EBC=100) Bootstrap Option H - Boot ROM Location I2C (Addr 0x52), booting from NAND 32 kB I-Cache 32 kB D-Cache Board: MR24 - Meraki MR24 Cloud Managed Access Point ============================ BoardID: 0 0 POE-PWR_DET Status: 0 ADAPTER_DET Status: 1 Reset Button Status: 1 ============================ SDR0_PERCLK=0x40000300 I2C: ready DRAM: 128 MiB I2C write: failed 4 NAND: 32 MiB Configure Max Payload 256B PCIE0: successfully set as root-complex 03 00 168c 0030 0280 ff 02 02 111d 8039 0604 00 04 00 168c 0030 0280 ff 02 03 111d 8039 0604 00 01 00 111d 8039 0604 00 I2C read: failed 4 I2C write: failed 4 I2C read: failed 4 I2C read: failed 4 I2C write: failed 4 Net: ppc_4xx_eth0 RESET is un-pushed Set serverpath and run meraki_netboot to netboot Hit any key to stop autoboot: 0
- For your own reference, type the commands:
help
andprintenv
If you mess anything up, you can probably restore things by re-entering some of the u-boot environment variables. You will need two images, an initramfs image and a squashfs-sysupgrade image. You can either obtain these from Russell or perhaps the OpenWrt snapshots, or you can build them yourself. The initramfs image needs to be relatively small in order to fit within some size constraints. It is also used as a recovery image, so something small and simple is preferred. Russell built his vanilla images with the following starting OpenWrt .config file.
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_kmod-lib-crc-ccitt is not set # CONFIG_PACKAGE_kmod-ppp is not set # CONFIG_PACKAGE_ppp is not set
Also, you can obtain a files overlay to go with it (recommended) here. The tarball should be unpacked from the OpenWrt build tree at $TOPDIR, so that you get files like $TOPDIR/files/etc/uci-defaults/ptp.defaults. Once unpacked, you can look at the files and modify them as desired. For more details on how to build OpenWrt, see the appropriate documentation or ask Russell lots of questions.
- You will need a TFTP server to provide the initramfs image to the device. Russell uses the hpa-tftpd package on a Debian/Ubuntu box. Put your initramfs image, which is named "openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin" in the TFTP servers directory.
- From the u-boot prompt, do a test boot of the initramfs image. First, plug in the ethernet cable in such a way that the TFTP server will be reachable. Then apply the following temporary changes to the u-boot environment (they won't be saved until you give u-boot the command: "saveenv"). Substitute IP addresses that make sense for you. The "ipaddr" variable is for the MR24, "serverip" is for your TFTP server.
setenv ipaddr 192.168.80.49 setenv serverip 192.168.80.7 setenv meraki_bootfile openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin
You can do another printenv to make sure they were set properly. Now try booting your initramfs image like so:setenv netloadmethod tftpboot; setenv bootargs console=ttyS0,${baudrate} rootfstype=squashfs mtdoops.mtddev=oops; run meraki_load_net meraki_checkpart meraki_bootlinux
or the whole thing as two lines:setenv ipaddr 192.168.80.49; setenv serverip 192.168.80.7; setenv meraki_bootfile openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin; setenv netloadmethod tftpboot; setenv bootargs console=ttyS0,${baudrate} rootfstype=squashfs mtdoops.mtddev=oops run meraki_load_net meraki_checkpart meraki_bootlinux
You should see something like this:Waiting for PHY auto negotiation to complete.... done ENET Speed is 1000 Mbps - FULL duplex connection (EMAC0) Using ppc_4xx_eth0 device TFTP from server 192.168.80.7; our IP address is 192.168.80.49 Filename 'openwrt-apm821xx-nand-meraki_mr24-initramfs-kernel.bin'. Load address: 0xc00000 Loading: ################################################################# ################################################################# ################################################################# ################################################################# ####################################################### done Bytes transferred = 4613120 (466400 hex) ## Booting kernel from Legacy Image at 00c10000 ... Image Name: POWERPC OpenWrt Linux-4.14.20 Created: 2018-02-22 22:40:16 UTC Image Type: PowerPC Linux Kernel Image (lzma compressed) Data Size: 1751563 Bytes = 1.7 MiB Load Address: 00000000 Entry Point: 00000000 Verifying Checksum ... OK ## Loading init Ramdisk from Legacy Image at 00e00000 ... Image Name: DEVICE_meraki_mr24 rootfs Created: 2018-02-22 22:40:16 UTC Image Type: PowerPC Linux RAMDisk Image (gzip compressed) Data Size: 2484765 Bytes = 2.4 MiB Load Address: 00000000 Entry Point: 00000000 Verifying Checksum ... OK ## Flattened Device Tree blob at 00c00400 Booting using the fdt blob at 0xc00400 Uncompressing Kernel Image ... OK Loading Ramdisk to 07910000, end 07b6ea1d ... OK [ 0.000000] Linux version 4.14.20 (openwrt@hawg) (gcc version 5.5.0 (OpenWrt GCC 5.5.0 r6156-6873cf4f63)) #0 Thu Feb 22 22:40:16 2018 [ 0.000000] Found initrd at 0xc7910000:0xc7b6ea1d [ 0.000000] Using PowerPC 44x Platform machine description [ 0.000000] bootconsole [udbg0] enabled [ 0.000000] ----------------------------------------------------- [ 0.000000] phys_mem_size = 0x8000000 [ 0.000000] dcache_bsize = 0x20 [ 0.000000] icache_bsize = 0x20 [ 0.000000] cpu_features = 0x0000000010100040 [ 0.000000] possible = 0x0000000030100040 [ 0.000000] always = 0x0000000000100000 [ 0.000000] cpu_user_features = 0x8c008000 0x00000000 [ 0.000000] mmu_features = 0x00000008 [ 0.000000] ----------------------------------------------------- [ 0.000000] Zone ranges: [ 0.000000] DMA [mem 0x0000000000000000-0x0000000007ffffff] [ 0.000000] Normal empty [ 0.000000] Movable zone start for each node [ 0.000000] Early memory node ranges [ 0.000000] node 0: [mem 0x0000000000000000-0x0000000007ffffff] [ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000007ffffff] [ 0.000000] MMU: Allocated 1088 bytes of context maps for 255 contexts [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 32512 [ 0.000000] Kernel command line: console=ttyS0,115200 rootfstype=squashfs mtdoops.mtddev=oops [ 0.000000] PID hash table entries: 512 (order: -1, 2048 bytes) [ 0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) [ 0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) [ 0.000000] Memory: 122080K/131072K available (3708K kernel code, 192K rwdata, 976K rodata, 176K init, 234K bss, 8992K reserved, 0K cma-reserved) [...]
- Press enter to get a shell prompt, then grab some images and write them off to a persistent storage somewhere to preserve the original state, should you ever want to compare or restore.
for i in 0 1 2 ; do dd if=/dev/mtdblock$i of=/tmp/mtdblock$i.img ; done scp /tmp/mtdblock*.img <myusername>@<myhost>:<mypath>/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* <myusername>@<myhost>:<mypath>/mr24/stock01/
- 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. - Boot into the initramfs again:
run tftpboot_openwrt
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
- 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@<mr24-ipaddr>:/tmp/ scp bin/targets/apm821xx/nand/openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.tar root@<mr24-ipaddr>:/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.
- 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
- 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
- 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
- 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
- Prepare a files overlay:
- files/etc/uci-defaults/ptp.defaults
uci batch <<EOF set system.@system[0].hostname=bootstrap commit system delete network.globals delete network.lan set network.pub=interface set network.pub.ifname=eth0 set network.pub.proto=dhcp commit network EOF
- files/etc/dropbear/dropbear_rsa_host_key
- files/etc/dropbear/dropbear_ed25519_host_key
- Stable host keys (rsa and ed25519) so that ssh'ing to the "bootstrap" device won't trigger a balk from ssh when connecting over the network.
- files/etc/meraki.ubootenv
bootdelay 1 baudrate 115200 loads_echo 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 bootcmd run meraki_boot 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 factory_boot 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} ver U-Boot 2010.06-00036-g4e1a276 Meraki MR24 (May 11 2012 - 16:57:49)
- files/etc/openwrt.ubootenv
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
- files/etc/combined.ubootenv
- Concatenation of files/etc/meraki.ubootenv and files/etc/openwrt.ubootenv
- files/usr/bin/backup-mtd
macaddr=$(cat /sys/class/net/eth0/address | tr -d ':') user=grabber dest=dest.mr24 ssh ${user}@${dest} mkdir mr24/$macaddr fw_printenv | sed 's/=/ /' > /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
- files/usr/bin/install-recovery
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
- files/usr/bin/fetch_image.sh
user=grabber dest=dest.mr24 fname=openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin scp ${user}@${dest}:mr24/images/${fname} /tmp/
- files/root/.ssh/known_hosts This is the host public key for dest.mr24 so that we aren't queried on every device
- 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.
- files/etc/uci-defaults/ptp.defaults
- After the bootstrap image is created, you will need to prepare the three files that will be served to the MR24 over TFTP:
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
- 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
- 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
- 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.
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
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.- Create the directory that will house the TFTP blobs:
# mkdir -p /srv/tftp
- Place the three files:
- uImage
- bluestone.dtb
- 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:
sudo adduser grabber
sudo su - grabber
ssh-keygen -t ed25519 -- this is mainly just to create the .ssh directory with the correct permissions
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
mkdir -p mr24/images
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
- Attach an ethernet cable from the TFTP server to the MR24 to be installed.
- With a straightened paper clip or similar device, press and hold the reset button.
- Plug in 12V power to the MR24 and continue holding the reset button for approximately 8-10 seconds.
- 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.
- 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.
- Ssh to the indicated address:
# ssh root@${ipaddr}
No password is required at this stage. - 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.
- 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
- Fetch the recovery firmware and prepare the ubi with the /usr/bin/install-recovery script (see above):
- 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
- Reboot into recovery firmware:
# reboot
- 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:user=grabber dest=dest.mr24 fname=openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin scp ${user}@${dest}:mr24/images/${fname} /tmp/
Use sysupgrade to install the normal OpenWrt firmware:
# sysupgrade -v -n /tmp/openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin
- 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.
- 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.
- 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.
- (A) kernel 4.4.21 : Sat Sep 17 19:43:29 2016 -- LEDE (old u-boot-env variables);
- (B) kernel 4.9.20 : Tue Apr 04 13:06:14 2017 -- LEDE (old u-boot-env variables);
(C) kernel 4.14.20 : Thu Feb 22 22:40:16 2018 -- OpenWrt (old u-boot-env variables);
(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.
- With power off, hold reset button, apply power, after 5 seconds release.
- Alternative if you can't reach the reset button:
- Log in to the normal firmware
Check ubi volumes: ubinfo -a
Remove the kernel ubi volume, which should force booting from the Recovery Firmware: ubirmvol /dev/ubi0 -N kernel
- Alternative if you can't reach the reset button:
Watch for the DHCP lease request from the MR24 with logread -f
- 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:
Connect wirelessly to the "OpenWrt" network
SSH to the MR24 over wifi: ssh root@192.168.1.1
Stop the firewall: /etc/init.d/firewall stop
To avoid conflicting networks, change the MR24's LAN: uci set network.lan.ipaddr=192.168.2.1
Restart the network: /etc/init.d/network restart
- 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/
- Log in to the MR24's Recovery Firmware
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.
Check the ubi volumes with ubinfo -a, and note the index of the existing "recovery" volume, we will call it: M
- 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. - 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:
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
Watch for the DHCP lease request from the MR24 with logread -f
Copy the clean environment "script" onto the MR24: scp /tmp/uboot.env cat:/tmp/ where "cat" is placeholder name of the rebooted MR24
Login to "cat": ssh cat
Find the lede environment variables you want to remove: fw_printenv | grep lede | cut -d= -f1 > /tmp/lede.env
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
Apply the final.env: fw_setenv -s /tmp/final.env
Check the resulting u-boot environment with fw_printenv
Force booting the new Recovery Firmware by removing the "kernel" ubi volume: ubirmvol /dev/ubi0 -N kernel
- Now continue with the normal steps
Reboot the MR24 and close the ssh session: reboot ; exit
Watch for the DHCP lease from the newly flashed firmware with logread -f
Login to the new Recovery Firmware: ssh recovery (note, no password is needed)
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
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)
Use sysupgrade to flash to final firmware: sysupgrade -v -n /tmp/openwrt-apm821xx-nand-meraki_mr24-squashfs-sysupgrade.bin
Watch for the DHCP lease from the newly flashed firmware with logread -f
- 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.