From 21852821c5e98cc0f7396160a24fbaf60c83c972 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Mon, 6 Nov 2017 17:59:36 +0000 Subject: [PATCH] dfu: Add ChipID quirks for various XMEGA parts This also adds an *almost* throw-away python script to import the chip-ids from the default conf file from the avrdude project. I've imported it here in case we have to start caring about different page sizes or application offsets. --- plugins/dfu/contrib/parse-avrdude-conf.py | 178 ++++++++++++++++++++++ plugins/dfu/dfu.quirk | 108 +++++++++++++ 2 files changed, 286 insertions(+) create mode 100755 plugins/dfu/contrib/parse-avrdude-conf.py diff --git a/plugins/dfu/contrib/parse-avrdude-conf.py b/plugins/dfu/contrib/parse-avrdude-conf.py new file mode 100755 index 000000000..ad8b60236 --- /dev/null +++ b/plugins/dfu/contrib/parse-avrdude-conf.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +""" This parses avrdude.conf and generates quirks for fwupd """ + +# pylint: disable=wrong-import-position,pointless-string-statement + +""" + Licensed under the GNU General Public License Version 2 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + +""" + +import sys +from difflib import SequenceMatcher + +# finds a part using the ID +def _find_part_by_id(parts, part_id): + for part in parts: + if 'id' not in part: + continue + if part['id'] == part_id: + return part + return None + +# finds a memory layout for a part, climbing up the tree to the parent if reqd. +def _find_mem_layout(parts, part): + if 'memory-application' in part: + memory_flash = part['memory-application'] + if memory_flash: + return memory_flash + + #look at the parent + if 'parent' in part: + parent = _find_part_by_id(parts, part['parent']) + if parent: + return _find_mem_layout(parts, parent) + print('no parent ', part['parent'], 'found for', part['id']) + return None + +# parses the weird syntax of avrdude.conf and makes lots of nested dictionaries +def _parse_parts(fn_source): + print("reading", fn_source) + + part = None + memory_id = None + parts = [] + + for line in open(fn_source).readlines(): + + # try to clean up crazy syntax + line = line.replace('\n', '') + if line.endswith(';'): + line = line[:-1] + + # ignore blank lines + line = line.rstrip() + if not line: + continue + + # count how many spaces deep this is + lvl = 0 + for char in line: + if char != ' ': + break + lvl = lvl + 1 + + # ignore comments + line = line.strip() + if line[0] == '#': + continue + + # level 0 of hell + if lvl == 0: + if line.startswith('part'): + memory_id = None + part = {} + parts.append(part) + if line.startswith('part parent '): + part['parent'] = line[13:].replace('"', '') + continue + + # level 4 of hell + if lvl == 4: + if line.startswith('memory'): + memory_id = 'memory-' + line[7:].replace('"', '') + part[memory_id] = {} + continue + split = line.split('=') + if len(split) != 2: + print('ignoring', line) + continue + part[split[0].strip()] = split[1].strip().replace('"', '') + continue + + # level 8 of hell + if lvl == 8: + if memory_id: + split = line.split('=') + if len(split) != 2: + continue + memory = part[memory_id] + memory[split[0].strip()] = split[1].strip() + continue + return parts + +def _get_longest_substring(s1, s2): + match = SequenceMatcher(None, s1, s2).find_longest_match(0, len(s1), 0, len(s2)) + return s2[match.b: match.b + match.size] + +# writes important data to the quirks file +def _write_quirks(parts, fn_destination): + outp = [] + + results = {} + + for part in parts: + + # ignore meta parts with deprecated names + if 'desc' not in part: + continue + if 'signature' not in part: + continue + + # find the layout + mem_part = _find_mem_layout(parts, part) + if not mem_part: + print("no memory layout for", part['desc']) + continue + if not 'size' in mem_part: + print("no memory size for", part['desc']) + continue + if mem_part['size'].startswith('0x'): + size = int(mem_part['size'], 16) + else: + size = int(mem_part['size'], 10) + + # output the line for the quirk + chip_id = '0x' + part['signature'].replace('0x', '').replace(' ', '') + mem_layout = '@Flash/0x0/1*%.0iKg' % int(size / 1024) + + # merge duplicate quirks + if chip_id in results: + result = results[chip_id] + result['desc'] = _get_longest_substring(result['desc'], part['desc']) + else: + result = {} + result['desc'] = part['desc'] + result['size'] = size + result['mem_layout'] = mem_layout + results[chip_id] = result + + for chip_id in results: + result = results[chip_id] + outp.append('# ' + result['desc'] + ' size:0x%x' % result['size'] + '\n') + outp.append(chip_id + '=' + result['mem_layout'] + '\n\n') + + # write file + print("writing", fn_destination) + open(fn_destination, 'w').writelines(outp) + +if __name__ == '__main__': + if len(sys.argv) != 3: + print("USAGE: %s avrdude.conf tmp.quirk" % sys.argv[0]) + sys.exit(1) + + all_parts = _parse_parts(sys.argv[1]) + _write_quirks(all_parts, sys.argv[2]) diff --git a/plugins/dfu/dfu.quirk b/plugins/dfu/dfu.quirk index 1335ce84e..a8117ea46 100644 --- a/plugins/dfu/dfu.quirk +++ b/plugins/dfu/dfu.quirk @@ -78,3 +78,111 @@ USB\VID_0B0E&PID_2456=0B0E0971 # AT32UC3A3 is BL @0x2000, Size: 0x40000 0x58200204=@Flash/0x2000/1*248Kg + +# ATxmega16A4 size:0x4000 +0x1e9441=@Flash/0x0/1*16Kg + +# ATxmega16C4 size:0x4000 +0x1e9544=@Flash/0x0/1*16Kg + +# ATxmega16D4 size:0x4000 +0x1e9442=@Flash/0x0/1*16Kg + +# ATxmega32A4 size:0x8000 +0x1e9541=@Flash/0x0/1*32Kg + +# ATxmega32C4 size:0x8000 +0x1e9443=@Flash/0x0/1*32Kg + +# ATxmega32D4 size:0x8000 +0x1e9542=@Flash/0x0/1*32Kg + +# ATxmega64A4 size:0x10000 +0x1e9646=@Flash/0x0/1*64Kg + +# ATxmega64C3 size:0x10000 +0x1e9649=@Flash/0x0/1*64Kg + +# ATxmega64D3 size:0x10000 +0x1e964a=@Flash/0x0/1*64Kg + +# ATxmega64D4 size:0x10000 +0x1e9647=@Flash/0x0/1*64Kg + +# ATxmega64A1 size:0x10000 +0x1e964e=@Flash/0x0/1*64Kg + +# ATxmega64A3 size:0x10000 +0x1e9642=@Flash/0x0/1*64Kg + +# ATxmega64B1 size:0x10000 +0x1e9652=@Flash/0x0/1*64Kg + +# ATxmega64B3 size:0x10000 +0x1e9651=@Flash/0x0/1*64Kg + +# ATxmega128C3 size:0x20000 +0x1e9752=@Flash/0x0/1*128Kg + +# ATxmega128D3 size:0x20000 +0x1e9748=@Flash/0x0/1*128Kg + +# ATxmega128D4 size:0x20000 +0x1e9747=@Flash/0x0/1*128Kg + +# ATxmega128A1 size:0x20000 +0x1e974c=@Flash/0x0/1*128Kg + +# ATxmega128A1revD size:0x20000 +0x1e9741=@Flash/0x0/1*128Kg + +# ATxmega128A3 size:0x20000 +0x1e9742=@Flash/0x0/1*128Kg + +# ATxmega128A4 size:0x20000 +0x1e9746=@Flash/0x0/1*128Kg + +# ATxmega128B1 size:0x20000 +0x1e974d=@Flash/0x0/1*128Kg + +# ATxmega128B3 size:0x20000 +0x1e974b=@Flash/0x0/1*128Kg + +# ATxmega192C3 size:0x30000 +0x1e9751=@Flash/0x0/1*192Kg + +# ATxmega192D3 size:0x30000 +0x1e9749=@Flash/0x0/1*192Kg + +# ATxmega192A1 size:0x30000 +0x1e974e=@Flash/0x0/1*192Kg + +# ATxmega192A3 size:0x30000 +0x1e9744=@Flash/0x0/1*192Kg + +# ATxmega256 size:0x40000 +0x1e9846=@Flash/0x0/1*256Kg + +# ATxmega256D3 size:0x40000 +0x1e9844=@Flash/0x0/1*256Kg + +# ATxmega256A3 size:0x40000 +0x1e9842=@Flash/0x0/1*256Kg + +# ATxmega256A3B size:0x40000 +0x1e9843=@Flash/0x0/1*256Kg + +# ATxmega384C3 size:0x60000 +0x1e9845=@Flash/0x0/1*384Kg + +# ATxmega384D3 size:0x60000 +0x1e9847=@Flash/0x0/1*384Kg + +# ATxmega8E5 size:0x2000 +0x1e9341=@Flash/0x0/1*8Kg + +# ATxmega16E5 size:0x4000 +0x1e9445=@Flash/0x0/1*16Kg + +# ATxmega32E5 size:0x8000 +0x1e954c=@Flash/0x0/1*32Kg