Last active
June 22, 2023 07:06
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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