Skip to content

Instantly share code, notes, and snippets.

@marcnewlin
Created May 23, 2020 13:52
Show Gist options
  • Save marcnewlin/f18824da9ca1c76eabf572a26a5d96ad to your computer and use it in GitHub Desktop.
Save marcnewlin/f18824da9ca1c76eabf572a26a5d96ad to your computer and use it in GitHub Desktop.
script to label ~most of the nRF24LU1P registers/mem-regions in Ghidra
# 0. place this script in your ghidra_script directory
# 1. open the target nRF24LU1P binary in Ghidra
# 2. open the python shell in Ghidra
# 3. `import logitech; l = logitech.logitech(currentProgram); l.do_it()
import ghidra
from ghidra.program.model.symbol import SourceType
class logitech(object):
def __init__(self, currentProgram):
self.currentProgram = currentProgram
self.listing = self.currentProgram.getListing()
self.symtbl = self.currentProgram.getSymbolTable()
self.dtm = self.currentProgram.getDataTypeManager()
self.EXTMEM = self.get_address_space("EXTMEM")
self.CODE = self.get_address_space("CODE")
self.SFR = self.get_address_space("SFR")
self.BITS = self.get_address_space("BITS")
self.INTMEM = self.get_address_space("INTMEM")
def do_it(self):
self.create_regions()
self.apply_sfr_bit_labels()
self.apply_sfr_labels()
self.apply_usb_labels()
self.set_volatility()
def get_address_space(self, name):
return self.currentProgram.getAddressFactory().getAddressSpace(name)
def create_extmem_region(self, name, start, length):
try:
addr = self.EXTMEM.getAddress(start)
block = self.currentProgram.memory.createUninitializedBlock(name, addr, length, False)
block.setRead(True)
block.setWrite(True)
block.setExecute(False)
block.setVolatile(True)
except ghidra.program.model.mem.MemoryConflictException:
print("%s region already exists" % name)
def create_regions(self):
self.create_extmem_region("SRAM", 0x8000, 0x800)
self.create_extmem_region("USB_RAM", 0xC000, 0x800)
def set_volatility(self):
addr = self.BITS.getAddress(0x00)
block = self.currentProgram.memory.getBlock(addr)
block.setVolatile(True)
addr = self.BITS.getAddress(0x80)
block = self.currentProgram.memory.getBlock(addr)
block.setVolatile(True)
addr = self.SFR.getAddress(0x80)
block = self.currentProgram.memory.getBlock(addr)
block.setVolatile(True)
def apply_usb_labels(self):
labels = [
# bulk IN buffers
(0xc700, 0x20, "in0buf", "32 bytes bulk 0 IN buffer"),
(0xc680, 0x20, "in1buf", "32 bytes bulk 1 IN buffer"),
(0xc600, 0x20, "in2buf", "32 bytes bulk 2 IN buffer"),
(0xc580, 0x20, "in3buf", "32 bytes bulk 3 IN buffer"),
(0xc500, 0x20, "in4buf", "32 bytes bulk 4 IN buffer"),
(0xc480, 0x20, "in5buf", "32 bytes bulk 5 IN buffer"),
# bulk OUT buffers
(0xc6c0, 0x20, "out0buf", "32 bytes bulk 0 OUT buffer"),
(0xc640, 0x20, "out1buf", "32 bytes bulk 1 OUT buffer"),
(0xc5c0, 0x20, "out2buf", "32 bytes bulk 2 OUT buffer"),
(0xc540, 0x20, "out3buf", "32 bytes bulk 3 OUT buffer"),
(0xc4c0, 0x20, "out4buf", "32 bytes bulk 4 OUT buffer"),
(0xc440, 0x20, "out5buf", "32 bytes bulk 5 OUT buffer"),
# registers
(0xc760, 0x01, "out8data"),
(0xc768, 0x01, "in8data"),
(0xc770, 0x01, "out8bch"),
(0xc771, 0x01, "out8bcl"),
(0xc781, 0x01, "bout1addr"),
(0xc782, 0x01, "bout2addr"),
(0xc783, 0x01, "bout3addr"),
(0xc784, 0x01, "bout4addr"),
(0xc785, 0x01, "bout5addr"),
(0xc788, 0x01, "binstaddr"),
(0xc789, 0x01, "bin1addr"),
(0xc78a, 0x01, "bin2addr"),
(0xc78b, 0x01, "bin3addr"),
(0xc78c, 0x01, "bin4addr"),
(0xc78d, 0x01, "bin5addr"),
(0xc7a0, 0x01, "isoerr"),
(0xc7a2, 0x01, "zbcout"),
(0xc7a8, 0x01, "ivec"),
(0xc7a9, 0x01, "in_irq"),
(0xc7aa, 0x01, "out_irq"),
(0xc7ab, 0x01, "usbirq"),
(0xc7ac, 0x01, "in_ien"),
(0xc7ad, 0x01, "out_ien"),
(0xc7ae, 0x01, "usbien"),
(0xc7af, 0x01, "usbbav"),
(0xc7b4, 0x01, "ep0cs"),
(0xc7b5, 0x01, "in0bc"),
(0xc7b6, 0x01, "in1cs"),
(0xc7b7, 0x01, "in1bc"),
(0xC7B8, 0x01, "in2cs"),
(0xC7B9, 0x01, "in2bc"),
(0xC7BA, 0x01, "in3cs"),
(0xC7BB, 0x01, "in3bc"),
(0xC7BC, 0x01, "in4cs"),
(0xC7BD, 0x01, "in4bc"),
(0xC7BE, 0x01, "in5cs"),
(0xC7BF, 0x01, "in5bc"),
(0xC7C5, 0x01, "out0bc"),
(0xC7C6, 0x01, "out1cs"),
(0xC7C7, 0x01, "out1bc"),
(0xC7C8, 0x01, "out2cs"),
(0xC7C9, 0x01, "out2bc"),
(0xC7CA, 0x01, "out3cs"),
(0xC7CB, 0x01, "out3bc"),
(0xC7CC, 0x01, "out4cs"),
(0xC7CD, 0x01, "out4bc"),
(0xC7CE, 0x01, "out5cs"),
(0xC7CF, 0x01, "out5bc"),
(0xC7D6, 0x01, "usbcs"),
(0xC7D7, 0x01, "togctl"),
(0xC7D8, 0x01, "usbfrml"),
(0xC7D9, 0x01, "usbfrmh"),
(0xC7DB, 0x01, "fnaddr"),
(0xC7DD, 0x01, "usbpair"),
(0xC7DE, 0x01, "inbulkval"),
(0xC7DF, 0x01, "outbulkval"),
(0xC7E0, 0x01, "inisoval"),
(0xC7E1, 0x01, "outisoval"),
(0xC7E2, 0x01, "isostaddr"),
(0xC7E3, 0x01, "isosize"),
(0xC7E8, 0x01, "setupbuf"),
(0xC7E9, 0x01, "setupbuf"),
(0xC7EA, 0x01, "setupbuf"),
(0xC7EB, 0x01, "setupbuf"),
(0xC7EC, 0x01, "setupbuf"),
(0xC7ED, 0x01, "setupbuf"),
(0xC7EE, 0x01, "setupbuf"),
(0xC7EF, 0x01, "setupbuf"),
(0xC7F0, 0x01, "out8addr"),
(0xC7F8, 0x01, "in8addr"),
]
for label in labels:
addr = self.EXTMEM.getAddress(label[0])
length = label[1]
name = label[2]
if len(label) == 4:
desc = label[3]
else:
desc = ""
print(label)
sym = list(self.symtbl.getSymbols(addr))
if len(sym) == 0:
sym = [self.symtbl.createSymbol(addr, name, SourceType.USER_DEFINED)]
assert(len(sym) == 1)
sym = sym[0]
sym.setName(name, SourceType.USER_DEFINED)
if len(label) == 4:
cu = self.listing.getCodeUnitAt(addr)
cu.setComment(cu.PRE_COMMENT, None)
cu.setComment(cu.PLATE_COMMENT, None)
cu.setComment(cu.REPEATABLE_COMMENT, desc)
def apply_sfr_bit_labels(self):
labels = [
# P0
(0x80, "P0.D0", "GPIO P0.D0"),
(0x81, "P0.D1", "GPIO P0.D1"),
(0x82, "P0.D2", "GPIO P0.D2"),
(0x83, "P0.D3", "GPIO P0.D3"),
(0x84, "P0.D4", "GPIO P0.D4"),
(0x85, "P0.D5", "GPIO P0.D5"),
(0x86, None),
(0x87, None),
# TCON
(0x88, "it0", "External interrupt 0 type control. 1: falling edge, 0: low level"),
(0x89, "ie0", "External interrupt 0 flag. Set by hardware."),
(0x8a, "it1", "External interrupt 1 type control. 1: falling edge, 0: low level"),
(0x8b, "ie1", "External interrupt 1 flag. Set by hardware."),
(0x8c, "tr0", "Timer 0 Run control. If cleared, Timer 0 stops."),
(0x8d, "tf0", "Timer 0 overflow flag. Set by hardware when Timer 0 overflows"),
(0x8e, "tr1", "Timer 1 Run control. If cleared, Timer 1 stops."),
(0x8f, "tf1", "Timer 1 overflow flag. Set by hardware when Timer1 overflows."),
# RFCON
(0x90, "rfce", "RF CE 1: enabled 0: disabled"),
(0x91, "rfcsn", "RF SPI CSN 0: enabled 1: disabled"),
(0x92, "rfcken", "RF Clock Enable (16MHz)"),
(0x93, None),
(0x94, None),
(0x95, None),
(0x96, None),
(0x97, None),
# S0CON
(0x98, None),
(0x99, None),
(0x9a, None),
(0x9b, None),
(0x9c, None),
(0x9d, None),
(0x9e, None),
(0x9f, None),
# USBCON
(0xa0, None),
(0xa1, None),
(0xa2, None),
(0xa3, None),
(0xa4, None),
(0xa5, "suspend", "1: USB is suspended. This bit acknowledges USBSLP=1, after a delay of up to 32us."),
(0xa6, "wu", "1: wakeup USB, must be cleared before setting USBSLP."),
(0xa7, "swrst", "1: reset USB"),
# IEN0
(0xa8, "P0.3_interrupt_enable"),
(0xa9, "Timer0_overflow_interrupt_enable"),
(0xaa, "P0.4_interrupt_enable"),
(0xab, "Timer1_overflow_interrupt_enable"),
(0xac, "serial_port_interrupt_enable"),
(0xad, "Timer2_interrupt_enable"),
(0xae, "reserved", "Not used."),
(0xaf, "global_interrupts_enable"),
(0xb0, None),
(0xb1, None),
(0xb2, None),
(0xb3, None),
(0xb4, None),
(0xb5, None),
(0xb6, None),
(0xb7, None),
# IEN1
(0xb8, "rf_spi_ready_enable", "1: RF SPI ready enable"),
(0xb9, "rf_interrupt_enable", "1: RF interrupt enable"),
(0xba, "master_or_slave_spi_interrupt_ready_enable", "1: Master or Slave SPI ready interrupt enable"),
(0xbb, "usb_wakeup_interrupt_enable"),
(0xbc, "usb_interrupt_enable"),
(0xbd, "wakeup_interrupt_enable"),
(0xbe, None),
(0xbf, None),
# IRCON
(0xc0, "rf_spi_interrupt_flag", "RF SPI interrupt flag"),
(0xc1, "rf_interrupt_flag", "RF interrupt flag"),
(0xc2, "master_slave_spi_interrupt_flag", "Master or Slave SPI interrupt flag"),
(0xc3, "usb_wakeup_interrupt_flag", "USB wakeup interrupt flag"),
(0xc4, "usb_interrupt_flag", "USB interrupt flag"),
(0xc5, "wakeup_interrupt_flag", "Wakeup interrupt flag"),
(0xc6, "timer2_overflow_flag", "Timer 2 overflow flag"),
(0xc7, "timer2_external_reload_flag", "Timer 2 external reload flag"),
(0xc8, None),
(0xc9, None),
(0xca, None),
(0xcb, None),
(0xcc, None),
(0xcd, None),
(0xce, None),
(0xcf, None),
(0xd0, None),
(0xd1, None),
(0xd2, None),
(0xd3, None),
(0xd4, None),
(0xd5, None),
(0xd6, None),
(0xd7, None),
(0xd8, None),
(0xd9, None),
(0xda, None),
(0xdb, None),
(0xdc, None),
(0xdd, None),
(0xde, None),
(0xdf, None),
# ACC
(0xe0, "acc.0", "accumulator"),
(0xe1, "acc.1", "accumulator"),
(0xe2, "acc.2", "accumulator"),
(0xe3, "acc.3", "accumulator"),
(0xe4, "acc.4", "accumulator"),
(0xe5, "acc.5", "accumulator"),
(0xe6, "acc.6", "accumulator"),
(0xe7, "acc.7", "accumulator"),
# AESCS
(0xe8, "go", "Set by SW to '1' to start operation. SW can poll this signal to check if AES block is busy. Automatically reset by HW when operation is completed. An encrypt or decrypt operation takes about 45 Cclk cycles."),
(0xe9, "decr", "0: Encrypt, 1: Decrypt"),
(0xea, None),
(0xeb, None),
(0xec, None),
(0xed, None),
(0xee, None),
(0xef, None),
(0xf0, None),
(0xf1, None),
(0xf2, None),
(0xf3, None),
(0xf4, None),
(0xf5, None),
(0xf6, None),
(0xf7, None),
# FSR
(0xf8, "reserved", "Reserved, read as 0."),
(0xf9, "RDISIP", "SPI read-back disable of infopage. 1: read back disable"),
(0xfa, "RDISMB", "SPI read-back disable of main block. 1: read back disable"),
(0xfb, "INFEN", "Infopage enable. 1: enable"),
(0xfc, "RDYN", "Flash interface ready. 0: ready"),
(0xfd, "WEN", "Write enable. 1: enable"),
(0xfe, "STP", "1: Start from protected program memory"),
(0xff, "DBG", "1: Debug enabled, 0: Debug disabled, can be set by MCU")
]
for label in labels:
addr = self.BITS.getAddress(label[0])
name = "UNDEFINED_SFR_BIT_0x%02x" % label[0]
print(label)
sym = list(self.symtbl.getSymbols(addr))
if len(sym) == 0:
sym = [self.symtbl.createSymbol(addr, name, SourceType.USER_DEFINED)]
assert(len(sym) == 1)
sym = sym[0]
if label[1] is not None:
name = label[1]
sym.setName(name, SourceType.USER_DEFINED)
if len(label) == 3:
description = label[2]
cu = self.listing.getCodeUnitAt(addr)
cu.setComment(cu.PRE_COMMENT, None)
cu.setComment(cu.PLATE_COMMENT, None)
cu.setComment(cu.REPEATABLE_COMMENT, description)
def apply_sfr_labels(self):
labels = [
(0x80, "P0"),
(0x81, "SP"),
(0x82, "DPL"),
(0x83, "DPH"),
(0x84, "DPL1"),
(0x85, "DPH1"),
(0x86, None),
(0x87, "PCON"),
(0x88, "TCON"),
(0x89, "TMOD"),
(0x8a, "TL0"),
(0x8b, "TL1"),
(0x8c, "TH0"),
(0x8d, "TH1"),
(0x8e, "CKCON"),
(0x8f, None),
(0x90, "RFCON"),
(0x91, None),
(0x92, "DPS"),
(0x93, None),
(0x94, "P0DIR"),
(0x95, "P0ALT"),
(0x96, None),
(0x97, None),
(0x98, "S0CON"),
(0x99, "S0BUF"),
(0x9a, None),
(0x9b, None),
(0x9c, None),
(0x9d, None),
(0x9e, None),
(0x9f, None),
(0xa0, "USBCON"),
(0xa1, None),
(0xa2, None),
(0xa3, "CLKCTL"),
(0xa4, "PWRDWN"),
(0xa5, "WUCONF"),
(0xa6, "INTEXP"),
(0xa7, None),
(0xa8, "IEN0"),
(0xa9, "IP0"),
(0xaa, "S0RELL"),
(0xab, "REGXH"),
(0xac, "REGXL"),
(0xad, "REGXC"),
(0xae, None),
(0xaf, None),
(0xb0, None),
(0xb1, "RSTRES"),
(0xb2, "SMDAT"),
(0xb3, "SMCTRL"),
(0xb4, None),
(0xb5, "TICKDV"),
(0xb6, None),
(0xb7, None),
(0xb8, "IEN1"),
(0xb9, "IP1"),
(0xba, "S0RELH"),
(0xbb, None),
(0xbc, "SSCONF"),
(0xbd, "SSDAT"),
(0xbe, "SSSTAT"),
(0xbf, None),
(0xc0, "IRCON"),
(0xc1, "CCEN"),
(0xc2, "CCL1"),
(0xc3, "4CCH1"),
(0xc4, "CCL2"),
(0xc5, "CCH2"),
(0xc6, "CCL3"),
(0xc7, "CCH3"),
(0xc8, "T2CON"),
(0xc9, "P0EXP"),
(0xca, "CRCL"),
(0xcb, "CRCH"),
(0xcc, "TL2"),
(0xcd, "TH2"),
(0xce, None),
(0xcf, None),
(0xd0, "PSW"),
(0xd1, None),
(0xd2, None),
(0xd3, None),
(0xd4, None),
(0xd5, None),
(0xd6, None),
(0xd7, None),
(0xd8, "WDCON"),
(0xd9, "USBSLP"),
(0xda, None),
(0xdb, None),
(0xdc, None),
(0xdd, None),
(0xde, None),
(0xdf, None),
(0xe0, "ACC"),
(0xe1, None),
(0xe2, None),
(0xe3, None),
(0xe4, None),
(0xe5, "RFDAT"),
(0xe6, "RFCTL"),
(0xe7, None),
(0xe8, "AESCS"),
(0xe9, "MD0"),
(0xea, "MD1"),
(0xeb, "MD2"),
(0xec, "MD3"),
(0xed, "MD4"),
(0xee, "MD5"),
(0xef, "ARCON"),
(0xf0, "B"),
(0xf1, "AESKIN"),
(0xf2, "AESIV"),
(0xf3, "AESD"),
(0xf4, None),
(0xf5, "AESIA1"),
(0xf6, "AESIA2"),
(0xf7, None),
(0xf8, "FSR"),
(0xf9, "FPCR"),
(0xfa, "FCR"),
(0xfb, None),
(0xfc, None),
(0xfd, None),
(0xfe, None),
(0xff, None),
]
for label in labels:
addr = self.SFR.getAddress(label[0])
name = "UNDEFINED_SFR_0x%02x" % label[0]
print(label)
sym = list(self.symtbl.getSymbols(addr))
if len(sym) == 0:
sym = [self.symtbl.createSymbol(addr, name, SourceType.USER_DEFINED)]
assert(len(sym) == 1)
sym = sym[0]
if label[1] is not None:
name = label[1]
sym.setName(name, SourceType.USER_DEFINED)
def rename_symbol(self, addr, name):
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment