X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=firmware%2Fsaleae-logic16%2Fsigrok-fwextract-saleae-logic16;h=460bfb105dd89ed76ef359d7faf5984710c6304f;hb=b06d8227299bc4fb1662a894a6cec7c6de2d32c1;hp=62d66a1843febc805f033d66fa5344e77c0c2959;hpb=08a979afc74f56b6b23a129a89406a2949ccaefe;p=sigrok-util.git diff --git a/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 b/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 index 62d66a1..460bfb1 100755 --- a/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 +++ b/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 @@ -47,6 +47,15 @@ class searcher: raise Exception('Needle not found in haystack') this.skip(pos - this.offset) + def look_for_either(this, needle1, needle2): + pos1 = this.data.find(needle1, this.offset) + pos2 = this.data.find(needle2, this.offset) + if pos1 < 0 and pos2 < 0: + raise Exception('Needle not found in haystack') + if pos1 < 0 or pos2 < pos1: + pos1 = pos2 + this.skip(pos1 - this.offset) + def __init__(this, data, addr): this.data = data this.baseaddr = addr @@ -69,7 +78,7 @@ def search_plt_64(plt, addr): def find_hex_file_lines_constructor_32(text, hex_file_lines_got, got_plt): while True: - text.look_for(b'\x8b\xbb') # mov offs32(%ebx),%edi + text.look_for_either(b'\x8b\xbb', b'\x8b\xb3') # mov offs32(%ebx),{%edi,%esi} offs = struct.unpack(' 0: if text.peek(2) == b'\x8d\x45': # lea offs8(%ebp),%eax text.skip(3) elif text.peek(2) == b'\x8d\x85': # lea offs32(%ebp),%eax text.skip(6) - if text.peek(1) == b'\xbe': # mov $imm32,%esi + if text.peek(1) == (b'\xbf' if esi else b'\xbe'): # mov $imm32,%esi text.skip(5) - elif text.peek(2) == b'\x31\xf6': # xor %esi,%esi + elif text.peek(2) == (b'\x31\xff' if esi else b'\x31\xf6'): # xor %esi,%esi text.skip(2) if text.peek(4) == b'\x89\x44\x24\x08': # mov %eax,0x8(%esp) text.skip(4) @@ -107,17 +119,17 @@ def parse_hex_file_lines_constructor_32(text, basic_string_plt, got_plt, lines): ('0x%x' % text.address)) if text.peek(4) == b'\x89\x44\x24\x04': # mov %eax,0x4(%esp) text.skip(4) - if text.peek(3) == b'\x89\x3c\x24': # mov %edi,(%esp) + if text.peek(3) == (b'\x89\x34\x24' if esi else b'\x89\x3c\x24'): # mov %edi,(%esp) offs = 0 text.skip(3) - elif text.peek(2) == b'\x8d\x47': # lea offs8(%edi),%eax + elif text.peek(2) == (b'\x8d\x46' if esi else b'\x8d\x47'): # lea offs8(%edi),%eax offs = struct.unpack(' (len(lines) << 2) or (offs & 3) != 0: raise Exception('Invalid offset %d' % offs) @@ -170,6 +182,10 @@ def parse_hex_file_lines_constructor_64(text, basic_string_plt, lines): else: raise Exception('Expected lea offs(%rbp),%rdi @ ' + ('0x%x' % text.address)) + if text.peek(1) == b'\xbb': # mov $imm32,%ebx + text.skip(5) + elif text.peek(2) == b'\x31\xdb': # xor %ebx,%ebx + text.skip(2) if offs < 0 or offs > (len(lines) << 3) or (offs & 7) != 0: raise Exception('Invalid offset %d' % offs) index = offs >> 3 @@ -278,6 +294,44 @@ def extract_fx2_firmware(elf, symname, filename): f.close() print("saved %d bytes to %s" % (len(blob), filename)) +def extract_fx2_firmware_single(elf, symname, filename): + if not symname in elf.dynsym: + return False + hex = bytes.decode(elf.load_symbol(elf.dynsym[symname])) + if hex[-1] == '\0': + hex = hex[:-1] + blob = ihex_to_binary(hex.split(';')) + f = open(filename, 'wb') + f.write(blob) + f.close() + print("saved %d bytes to %s" % (len(blob), filename)) + return True + +def extract_fx3_firmware(elf, symname, filename): + index = 0 + blobs = [] + while True: + sym = elf.dynsym.get(symname + '_' + str(index)) + if not sym: + break + index += 1 + hex = bytes.decode(elf.load_symbol(sym)) + if hex[-1] == '\0': + hex = hex[:-1] + for part in hex.split(';'): + if not part: + continue + if part[0] != ':': + raise Exception('ihex line does not start with ":"') + blobs.append(bytes.fromhex(part[1:])) + if not blobs: + return + with open(filename, 'wb') as f: + for blob in blobs: + f.write(blob) + print("saved %d bytes from %d blobs to %s" % (sum(map(len, blobs)), + len(blobs), filename)) + def extract_symbol(elf, symname, filename): blob = elf.load_symbol(elf.dynsym[symname]) f = open(filename, 'wb') @@ -285,6 +339,11 @@ def extract_symbol(elf, symname, filename): f.close() print("saved %d bytes to %s" % (len(blob), filename)) +def try_extract_symbol(elf, symname, filename): + if not symname in elf.dynsym: + return + extract_symbol(elf, symname, filename) + def extract_bitstream(elf, lv): extract_symbol(elf, 'gLogic16Lv' + lv + 'CompressedBitstream', 'saleae-logic16-fpga-' + lv + '.bitstream') @@ -306,8 +365,13 @@ try: elf = parseelf.elf(filename) if elf.ehdr['e_machine'] != 3 and elf.ehdr['e_machine'] != 62: raise Exception('Unsupported e_machine') - extract_fx2_firmware(elf, 'gLogic16HexFileLines', 'saleae-logic16-fx2.fw') + if not extract_fx2_firmware_single(elf, 'Logic16FirmwareStrings', 'saleae-logic16-fx2.fw'): + extract_fx2_firmware(elf, 'gLogic16HexFileLines', 'saleae-logic16-fx2.fw') extract_bitstream(elf, '18') extract_bitstream(elf, '33') + extract_fx3_firmware(elf, 'LogicPro16FirmwareStrings', 'saleae-logicpro16-fx3.fw') + extract_fx3_firmware(elf, 'LogicPro8FirmwareStrings', 'saleae-logicpro8-fx3.fw') + try_extract_symbol(elf, 'gLogicPro16CompressedBitstream', 'saleae-logicpro16-fpga.bitstream') + try_extract_symbol(elf, 'gLogicProCompressedBitstream', 'saleae-logicpro8-fpga.bitstream') except Exception as e: print("Error: %s" % str(e))