Skip to content

Instantly share code, notes, and snippets.

@jamchamb
Last active June 22, 2023 07:06
Show Gist options
  • Save jamchamb/b2892a22ac0760346d4d617fedf9b541 to your computer and use it in GitHub Desktop.
Save jamchamb/b2892a22ac0760346d4d617fedf9b541 to your computer and use it in GitHub Desktop.
GreatFET script for dumping nRF24LE1 firmware (https://jamchamb.net/2021/05/29/dumping-k360-firmware.html)
#!/usr/bin/python3
import argparse
import hexdump
import struct
import time
from greatfet import GreatFET
def reset(gf, reset_pin):
"""Pulse the reset pin low"""
reset_pin.low()
time.sleep(0.001)
reset_pin.high()
time.sleep(0.001)
def read_fsr(gf):
fsr = gf.spi.transmit([0x05], receive_length=1)
return ord(fsr)
def write_fsr(gf, fsr):
fsr &= 0xff
gf.spi.transmit([0x01, fsr])
def read_fpcr(gf):
fpcr = gf.spi.transmit([0x89], receive_length=1)
return ord(fpcr)
def read_flash(gf, address, count):
command = struct.pack('>BH', 0x03, address)
data = gf.spi.transmit(
command,
receive_length=count)
return data
def get_infoblock(gf):
flash_stat_reg = read_fsr(gf)
# INFEN is bit 3 (2^3)
write_fsr(gf, flash_stat_reg | 8)
time.sleep(0.001)
# Checking it back doesn't seem to reflect the change
infoblock = read_flash(gf, 0, 512)
# Unset INFEN bit
write_fsr(gf, flash_stat_reg & (~8 & 0xff))
return infoblock
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--dump', type=str, help='dump flash to file')
parser.add_argument('--infopage', type=str, help='dump infopage to file')
args = parser.parse_args()
gf = GreatFET()
reset_pin = gf.gpio.get_pin('J1_P4')
prog_pin = gf.gpio.get_pin('J1_P6')
# Reset is active low
reset_pin.high()
# Enter prog mode
prog_pin.high()
time.sleep(0.01)
reset(gf, reset_pin)
# check flash protect register
flash_stat_reg = read_fsr(gf)
print(f'flash status register: {flash_stat_reg:#02x}')
check_protect_reg = read_fpcr(gf)
print(f'flash protect register: {check_protect_reg:#02x}')
# Get the InfoBlock
infoblock = get_infoblock(gf)
print('InfoBlock content:')
hexdump.hexdump(infoblock)
if args.infopage is not None:
with open(args.infopage, 'wb') as ipfile:
ipfile.write(infoblock)
flash_readprotect = infoblock[0x23]
readprotect_enabled = flash_readprotect != 0xff
debug_setting = infoblock[0x24]
hwdebug_enabled = debug_setting != 0xff
print(f'Flash readback protection: {readprotect_enabled} ({flash_readprotect:02x})')
print(f'HW debug enabled: {hwdebug_enabled} ({debug_setting:02x})')
if args.dump is not None:
if readprotect_enabled:
print('warning: flash readback protect enabled')
with open(args.dump, 'wb') as dump_file:
all_data = read_flash(gf, 0, 18432)
dump_file.write(all_data)
print(f'wrote flash dump to {args.dump}')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment