#!/bin/sh # som-recover-nrf91 -- bring an Emcraft SOM-NRF9151 whose debug access is locked # (APPROTECT) back to an installed, booting release, from a brintOS machine, # over SWD through a J-Link: the station's `nrfutil device recover` plus the # install that follows it, in one openocd session. # # * The CTRL-AP's ERASEALL is the only way into a locked nRF91x1. It erases # the flash and the whole UICR, and the access port then stays open only # until the next pin, power or watchdog reset: a release whose firmware # opens it at boot (NCS's NRF_APPROTECT_USE_UICR, which 2.0-122's b0, # MCUboot and TF-M are built with) does so only when UICR.APPROTECT and UICR.SECUREAPPROTECT both read # 0x50FA50FA, and an erased UICR reads 0xFFFFFFFF. So both words are written # right after the erase, before anything else, and the release goes in whole, # its UICR records (b0's key hashes) included. # * openocd's nrf91_recover resets the chip after the erase through the # CTRL-AP. That is a soft reset, which Nordic's own procedure calls for; it # does not lock the port again. Nothing else here resets the chip until the # image is written and verified, and that reset is a soft one too. # * The KMU's key-slot part of the UICR (from 0x400) reads back erased until # the chip is reset, so a UICR page written back is verified up to 0x400 in # the erase session, and whole once the chip has reset. # * UICR.ERASEPROTECT (0x00FF8030) is never written: once set, ERASEALL is # refused and a locked chip cannot be recovered from a debugger at all. # # Exit status: 0 PASS, 1 FAIL, 2 usage, 4 the board is in use by another # command (som-lock: the lock som-program-nrf91, som-test-nrf91 and som-console # share), so nothing was done. A recover has no stop request: once started, it # runs to its end. set -u PROG=som-recover-nrf91 SCRIPTS="${SOM_OPENOCD_SCRIPTS:-/usr/share/openocd/scripts}" BOARD_CFG="${SOM_BOARD_CFG:-$SCRIPTS/board/emcraft-som-nrf9151.cfg}" FW_DIR=/usr/share/brintos-som/nrf9151 FLASH_SIZE=0x100000 CTRL_AP_IDR=0x12880000 image="" app="" uicr_file="" speed="" adapter="" yes=0 force=0 dry_run=0 ocd_ran=0 usage() { printf '%s\n' \ "usage: $PROG (--app NAME | --image FILE.hex) [--uicr FILE] [--speed KHZ]" \ " [--adapter NAME] [--force] [--yes] [--dry-run]" \ "" \ " --app NAME the release to install after the erase: $(ls "$FW_DIR" 2>/dev/null | tr '\n' ' ')" \ " --image FILE an Intel HEX to install instead; its UICR records are written" \ " --uicr FILE a 4 KiB UICR page saved from this board (e.g. its golden backup)," \ " written back instead of the image's UICR records" \ " --yes erase: everything on the chip goes, the UICR included" \ " --force recover a chip whose debug access is open (it does not need" \ " it: som-program-nrf91 installs and keeps the UICR); its flash" \ " and UICR are backed up first" \ " --dry-run resolve and report, touch no hardware" \ "" \ "Backup (with --force): to \$SOM_BACKUP_DIR, default /tmp." \ "A run that fails keeps openocd's output in \${TMPDIR:-/tmp}/$PROG-