Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision Next revisionBoth sides next revision | ||
| toh:meraki:mr18:jtag [2020/04/12 17:50] – [JTAG connection (OpenOCD)] mh | toh:meraki:mr18:jtag [2021/09/06 23:21] – [Uploading a kernel] dddamion | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Meraki MR18 installation using JTAG and OpenOCD ====== | ====== Meraki MR18 installation using JTAG and OpenOCD ====== | ||
| - | A modern firmware prevents installation of the Meraki MR18 using its own firmware, and therefore upgrading the device to OpenWRT | + | A modern firmware prevents installation of the Meraki MR18 using its own firmware, and therefore upgrading the device to OpenWrt |
| * Disassemble the unit to access the UART | * Disassemble the unit to access the UART | ||
| * Solder some pins to allow access to the JTAG | * Solder some pins to allow access to the JTAG | ||
| * Connect both of these interfaces to a Raspberry Pi | * Connect both of these interfaces to a Raspberry Pi | ||
| - | * Upload an installation kernel into the device' | + | * Upload an installation kernel into the device' |
| - | * Use the running kernel to carry out regular | + | * Use the running kernel to carry out regular |
| + | |||
| + | {{: | ||
| ==== Disassembly ==== | ==== Disassembly ==== | ||
| Line 21: | Line 23: | ||
| At this point is recommended to remove the metal cover on the mainboard which has the antennae attached. This is to allow access to the underside of the mainboard for soldering. To do this, unplug each of the antennae carefully, unscrew the two small screws (top-left and bottom-right) and slide the cover. | At this point is recommended to remove the metal cover on the mainboard which has the antennae attached. This is to allow access to the underside of the mainboard for soldering. To do this, unplug each of the antennae carefully, unscrew the two small screws (top-left and bottom-right) and slide the cover. | ||
| - | For the purposes of this exercise, we only need a subset of the pins on one row: nTRST, TDI, TDO, TMS, TCK. We can also skip the ' | + | For the purposes of this exercise, we only need a subset of the pins on one row: nTRST, TDI, TDO, TMS, TCK. We can also skip the ' |
| - | Using only one row of pins is to our advantage. If we were to solder a connector vertically on both rows they will protrude with the case, preventing re-assembly or, worse, shorting on the case. Instead, we can solder | + | Using only one row of pins is to our advantage. If we were to solder a connector vertically on both rows they will protrude with the case, preventing re-assembly or, worse, shorting on the case. Instead, we can solder |
| With access to the underside of the board (from removing the metal cover) it's easy and clean to solder to the 5 pins needed; you may even want to solder all 7 on that row if you want to experiment later with the reset pins. It's recommended to solder and position just one pin to hold everything in place, before doing the rest. | With access to the underside of the board (from removing the metal cover) it's easy and clean to solder to the 5 pins needed; you may even want to solder all 7 on that row if you want to experiment later with the reset pins. It's recommended to solder and position just one pin to hold everything in place, before doing the rest. | ||
| + | {{: | ||
| + | {{: | ||
| ==== Serial connection ==== | ==== Serial connection ==== | ||
| Line 40: | Line 44: | ||
| </ | </ | ||
| - | Now locate the UART on the MR18, which already has some pins soldered. In our illustration, | + | Now locate the UART on the MR18, which already has some pins soldered. In our illustration, |
| + | |||
| + | {{: | ||
| Connect these to the Raspberry Pi's own UART using jumper wire: | Connect these to the Raspberry Pi's own UART using jumper wire: | ||
| Line 51: | Line 57: | ||
| Note that TX and RX are symmetrical; | Note that TX and RX are symmetrical; | ||
| - | We can now view the console of the MR18. Run the following command on the Raspberry Pi: | + | We can now view the console of the MR18. Run the following command on the Raspberry Pi. |
| < | < | ||
| $ sudo apt install picocom | $ sudo apt install picocom | ||
| - | $ sudo picocom --baud 115200 / | + | $ sudo picocom --baud 115200 |
| </ | </ | ||
| and now connect power to the device; you should see the boot logs. Leave this running in a terminal; it survives reboots of the MR18 and gives a live display on what the device is doing, which you'll need later. | and now connect power to the device; you should see the boot logs. Leave this running in a terminal; it survives reboots of the MR18 and gives a live display on what the device is doing, which you'll need later. | ||
| - | If you have any problem here, check that TX and RX are round the correct way. Some of the existing | + | If you have any problem here, check that TX and RX are round the correct way. Information on the [[toh: |
| ==== JTAG connection (OpenOCD) ==== | ==== JTAG connection (OpenOCD) ==== | ||
| - | Identify pin 1 on the JTAG because it has the square (not circular) solder pad and is the left-most pin when looking at the board from the direction we opened it. | + | Identify pin 1 on the JTAG because it has the square (not circular) solder pad and is the left-most pin in this illustratation: |
| + | |||
| + | {{: | ||
| Connect the Raspberry Pi to the device' | Connect the Raspberry Pi to the device' | ||
| Line 75: | Line 83: | ||
| | 26 | JTAG 1 | nTRST | | | 26 | JTAG 1 | nTRST | | ||
| - | The actual mapping is derived from the description in OpenOCD' | + | The actual mapping is derived from the description in OpenOCD' |
| < | < | ||
| $ apt install openocd | $ apt install openocd | ||
| $ cd ~ | $ cd ~ | ||
| - | $ cp / | + | $ cp / |
| </ | </ | ||
| Line 87: | Line 95: | ||
| < | < | ||
| bcm2835gpio_trst_num 7 | bcm2835gpio_trst_num 7 | ||
| + | </ | ||
| + | |||
| + | Note that the raspberrypi-native.cfg is written for the Raspberry Pi models 1 and zero. Modify the peripheral address and speed coefficients to match your Raspberry Pi model as follow: | ||
| + | |||
| + | RPI 1A/A+/B/B+ with 700 MHz base clock | ||
| + | < | ||
| + | bcm2835gpio_peripheral_base 0x20000000 | ||
| + | bcm2835gpio_speed_coeffs 113714 28 | ||
| + | </ | ||
| + | |||
| + | RPI 2B with 900 MHz base clock | ||
| + | < | ||
| + | bcm2835gpio_peripheral_base 0x3E000000 | ||
| + | bcm2835gpio_speed_coeffs 146203 36 | ||
| + | </ | ||
| + | |||
| + | RPI 3B with 1200 MHz base clock | ||
| + | < | ||
| + | bcm2835gpio_peripheral_base 0x3E000000 | ||
| + | bcm2835gpio_speed_coeffs 194938 48 | ||
| + | </ | ||
| + | |||
| + | RPI 3B+ with 1400 MHz base clock (despite the higher clock seems to be the same as RPi 3B) | ||
| + | < | ||
| + | bcm2835gpio_peripheral_base 0x3E000000 | ||
| + | bcm2835gpio_speed_coeffs 194938 48 | ||
| + | </ | ||
| + | |||
| + | RPI 4 with 1500 MHz base clock | ||
| + | < | ||
| + | bcm2835gpio_peripheral_base 0xFE000000 | ||
| + | bcm2835gpio_speed_coeffs 236181 60 | ||
| </ | </ | ||
| Line 136: | Line 176: | ||
| Download the kernel from | Download the kernel from | ||
| - | [[https:// | + | [[https:// |
| Our plan to upload this code into the RAM of the device, and then point the CPU at it to execute, much like a bootloader would. | Our plan to upload this code into the RAM of the device, and then point the CPU at it to execute, much like a bootloader would. | ||
| - | Firstly, we need to catch the boot process early. This is important, as we need to boot our own kernel before any hardware peripherals in the device have begun to initialise. | + | Firstly, we need to catch the boot process early. This is important, as we need to boot our own kernel before any hardware peripherals in the device have begun to initialize, but late enough that the processor has been set up correctly by the existing Meraki bootloader. |
| + | |||
| + | On some devices this time window is very small. | ||
| + | Reports show the place to interrupt the boot process is during '' | ||
| + | |||
| + | [[https:// | ||
| + | Note: It appears to be impossible to get the correct timing if using POE. | ||
| Provide power to the MR18 and at that exact moment, run OpenOCD: | Provide power to the MR18 and at that exact moment, run OpenOCD: | ||
| Line 150: | Line 196: | ||
| We're looking to interrupt the device very early in its boot sequence. You should be able to ' | We're looking to interrupt the device very early in its boot sequence. You should be able to ' | ||
| - | Now execute the following commands, one by one, by hand on the OpenOCD command line: | + | Now execute the following commands, one by one, by hand on the OpenOCD command line which is started by connecting into the running OpenOCD process: |
| < | < | ||
| Line 157: | Line 203: | ||
| </ | </ | ||
| - | First, disable the hardware watchdog, which will re-set the device automatically if it thinks the Cisco operating system has crashed (as is the case when the device is halted): | + | First, disable the hardware watchdog, which normally is there to re-set the device automatically if it thinks the Cisco operating system has crashed (and it will detect this when the device is halted): |
| < | < | ||
| Line 166: | Line 212: | ||
| < | < | ||
| - | > load_image | + | > load_image openwrt-ar71xx-nand-mr18-initramfs-kernel.bin 0x8005FC00 |
| + | </ | ||
| + | It should return something along the lines of: | ||
| + | '' | ||
| + | < | ||
| > verify_image openwrt-ar71xx-nand-mr18-initramfs-kernel.bin 0x8005FC00 | > verify_image openwrt-ar71xx-nand-mr18-initramfs-kernel.bin 0x8005FC00 | ||
| </ | </ | ||
| + | Again you should be able to see something like this: | ||
| + | '' | ||
| Now reset some registers and execute the kernel: | Now reset some registers and execute the kernel: | ||
| Line 180: | Line 232: | ||
| </ | </ | ||
| - | You should see, immediately on your serial console, the booting of the Linux kernel for OpenWRT. | + | You should see, immediately on your serial console, the booting of the Linux kernel for OpenWrt. |
| === Troubleshooting === | === Troubleshooting === | ||
| - | I found the process above can be someone | + | I found the process above can be somewhat |
| + | |||
| + | < | ||
| + | halt | ||
| + | resume 0x80060000 | ||
| + | </ | ||
| + | |||
| + | If this still doesn' | ||
| * Make sure you're halting with OpenOCD straight after powering the MR18 on, not too late. | * Make sure you're halting with OpenOCD straight after powering the MR18 on, not too late. | ||
| * Executing the commands in the telnet connection by hand (not scripted) seemed to help, and also gives a feel for what's happening. | * Executing the commands in the telnet connection by hand (not scripted) seemed to help, and also gives a feel for what's happening. | ||
| * Don't forgot to reset the registers before " | * Don't forgot to reset the registers before " | ||
| - | * If you don't see the kernel boot straight away, you can try a second time immediately without having to start again. Try "halt; resume 0x80060000" | ||
| - | |||
| - | The issue is likely to be that we're not resetting some register or memory, so the results are non-deterministic. It would be good to automate more of this process to 100% reliability; | ||
| - | Thankfully, you only need to boot like this once per device, so if you got it to work just once, then continue to the next step. | + | The issue is likely to be that we're not resetting some register or memory, so the results are non-deterministic. It would be good to automate more of this process to 100% reliability by understanding this. But, for now it may be ok; you only need to boot like this once per device, so if you got it to work just once, then continue to the next step. |
| - | ==== Installing OpenWRT permanantly | + | ==== Flashing OpenWrt |
| - | The device is now running | + | The device is now running |
| - | On your PC, download the latest | + | On your PC, download the latest |
| Now, disconnect your PC from the internet and connect it to the ethernet of the device. The device acts as a DHCP server as if it were to provide internet access. | Now, disconnect your PC from the internet and connect it to the ethernet of the device. The device acts as a DHCP server as if it were to provide internet access. | ||
| Line 209: | Line 265: | ||
| - "Flash new firmware image" using the file just downloaded. | - "Flash new firmware image" using the file just downloaded. | ||
| - | Wait for the device to reboot of its own accord, and verify that OpenWRT | + | Wait for the device to reboot of its own accord, and verify that OpenWrt |
| ==== Reassembly ==== | ==== Reassembly ==== | ||
| - | You now have a working MR18 with OpenWRT | + | You now have a working MR18 with OpenWrt |
| ==== Notes ==== | ==== Notes ==== | ||
| Line 221: | Line 277: | ||
| === Installation using " | === Installation using " | ||
| - | This didn't appear to work, so falling back to the web interface is necessary. The output is: | + | For the sake of automation it would have been nice to do the installation on the command line. But this didn't appear to work, so falling back to the web interface is necessary. The output is: |
| < | < | ||