#!/usr/bin/env python3 import os, struct, sys import json, xml, xml.etree import xml.etree.ElementTree as ET from typing import * import dvfparse from dvfparse import Dvf, DvfMI, DvfVN, DvfSN class DRec(NamedTuple): path: str magic: bytes name: str bromsize: int class XRec(NamedTuple): #path: str # is mostly prodname anyway nickname: str # "product series" prodname: str proddispname: str dvfname: str romsz: int ramsz: int npins: int dvf: DRec def get_common_masks(l: List[bytes]) -> (bytes, bytes): #return (l[:10], l[:10]) bits = 16*8 mask = (1< DRec: typ = Dvf.MCU_RL78G13 if is78k: typ = Dvf.MCU_78K0R if "78K0R" in path else Dvf.MCU_78K0 data = None with open(path, "rb") as f: data = f.read() magic = data[0x24:0x34] name = data[0x34:0x44] name = name.strip(b'\0').decode('utf-8') #print(filename) dvf = Dvf.parse(data, typ) mi = dvf.sections[dvfparse.name2int('MI')] brom_size = None for m in mi: if m.mreg_type == 0x28: # bootrom brom_size = m.addr_end - m.addr_start + 1 break #mag1 = ''.join("%02x"%x for x in magic[:10]) #mag2 = ''.join("%02x"%x for x in magic[10:]) #d2 = stuff.setdefault(mag1, {}) #d3 = d2.setdefault(name[:6], {}) #d3.setdefault(mag2, []).append((name, brom_size)) #magic = ''.join("%02x"%x for x in magic) return DRec(os.path.split(path)[-1], magic, name, brom_size) def parsexml(basepath: str, is78k: bool) -> Sequence[XRec]: xmlfile = basepath + "_Productlist.xml" xmlroot = ET.parse(xmlfile).getroot() curnick, curprod, curproddisp, curdvf, currom, curram, curpins = \ None, None, None, None, None, None, None for node in xmlroot[1]: if node.tag == 'Nickname': if curnick is not None: ext = "78K" if is78k else "DVF" if is78k: if "78K0R" in curnick: root2 = basepath + "0R" elif "78K0" in curnick: root2 = basepath + "0" else: assert False, curnick else: root2 = basepath dvfdir = root2 + "/Devicefile/" assert curprod filename = "%s_common.xml" % curprod filepath = "%s/%s" % (root2, filename) if curdvf is not None: pass#assert curdvf in {"DFR5F100", "DF780495", "DF780547", "DF780893", "DF780893", "DF780893__V110", "DF781009", "DF781009__V101"}, curdvf #if curdvf is None or curdvf == 'DFR5F100': #try: xml2 = ET.parse(filepath).getroot() dvfi = xml2.find("DEVICEFILEINFORMATION") folder = dvfi.find("DeviceFileInformationFolderName").text filen = dvfi.find("DeviceFileInformationFileName").text folder = folder or "Devicefile" curdvf = "%s/%s/%s" % (root2, folder, filen) #print("curdvf:%s"% curdvf) #except Exception: curdvf = None if curdvf is None: #print("curprod: %s"%curprod) curdvf = "%s/D%s.%s" % (dvfdir, curprod, ext) # shrug #else: # if is78k: # if "78K0R" in curnick: pass # elif "78K0" in curnick: curdvf = curdvf.replace("DF78", "DF") # print("curdvf k:%s"% curdvf, locals()) # curdvf = "%s/%s.%s" % (dvfdir, curdvf, ext) yield XRec(curnick, curprod, curproddisp, os.path.split(curdvf)[-1], currom, curram, curpins, parsedvf(curdvf, is78k)) curnick, curprod, curproddisp, curdvf, currom, curram, curpins = \ None, None, None, None, None, None, None curnick = node.text else: curnick = node.text if node.tag == 'ProductName': curprod = node.text if node.tag == 'ROMSize': currom = int(node.text or "0") if node.tag == 'RAMSize': curram = int(node.text or "0") if node.tag == 'DeviceFileProductName': curdvf = node.text if node.tag == 'ProductDisplayName': curproddisp = node.text if node.tag == 'PinCount': curpins = int(node.text or "0") if __name__ == '__main__': root_rl = sys.argv[1] xmls_rl = list(parsexml(root_rl, False)) xmls_rl.append(XRec("RL78/L1C", "R5F111PJ", "R5F111PJ", None, 256, 16*1024, 100, parsedvf(root_rl+"/Devicefile/DR5F111PJ.DVF", False))) xmld_rl = {} for x in xmls_rl: l = xmld_rl.setdefault(x.nickname, []).append(x) root_k = sys.argv[2] xmls_k = list(parsexml(root_k, True)) xmls_k.append(XRec('78K0R/UPD78F8069', "UPD78F806964", "UPD78F8069_64", None, 128+16, 8*1024, 64, parsedvf(root_k+"0R/Devicefile/DF806964.78K", True))) xmld_k = {} for x in xmls_k: l = xmld_k.setdefault(x.nickname, []).append(x) #print(json.dumps(xmld_rl, sort_keys=True, indent=4)) #print(json.dumps(xmld_k , sort_keys=True, indent=4)) # verify that all DVF files on disk are used! def dictl(ps, useset: bool=False): if useset: d = {} for x, y in ps: d.setdefault(x, set()).add(y) return dict((x, list(y)) for x, y in d.items()) else: d = {} for x, y in ps: d.setdefault(x, []).append(y) return d """ unk_rl, unk_k0, unk_k0r = [], [], [] for entry in os.scandir(root_rl+"/Devicefile"): if not any(any(entry.name == y.dvf.path for y in x) for x in xmld_rl.values()): unk_rl.append(entry.name) for entry in os.scandir(root_k+"0/Devicefile"): if not any(any(entry.name == y.dvf.path for y in x) for x in xmld_k.values()): unk_k0.append(entry.name) for entry in os.scandir(root_k+"0R/Devicefile"): if not any(any(entry.name == y.dvf.path for y in x) for x in xmld_k.values()): unk_k0r.append(entry.name) print(unk_rl) print(unk_k0) print(unk_k0r) """ """ maskd = {} for k, l in xmld_k.items(): mask = get_common_masks([x.dvf.magic for x in l]) maskd.setdefault(str(mask[1][:10]), []).append(k) for k, l in xmld_rl.items(): mask = get_common_masks([x.dvf.magic for x in l]) maskd.setdefault(str(mask[1][:10]), []).append(k) print(json.dumps(maskd, sort_keys=True, indent=4)) """ """ print() k78k0_bytes = sum([[l.dvf.magic for l in v] for k, v in xmld_k.items() if "78K0R" not in k], start=[]) k78k0r_bytes = sum([[l.dvf.magic for l in v] for k, v in xmld_k.items() if "78K0R" in k], start=[]) k78k_bytes = sum([[l.dvf.magic for l in v] for k, v in xmld_k.items()], start=[]) rl78s1_bytes = sum([[l.dvf.magic for l in v] for k, v in xmld_rl.items() if all(x not in k for x in {"G23","F24","FGIC"})], start=[]) rl78s2_bytes = sum([[l.dvf.magic for l in v] for k, v in xmld_rl.items() if any(x in k for x in {"G23","F24","FGIC"})], start=[]) rl78_bytes = sum([[l.dvf.magic for l in v] for k, v in xmld_rl.items()], start=[]) print("78K0", get_common_masks(k78k0_bytes)) print("78K0R", get_common_masks(k78k0r_bytes)) print("78K", get_common_masks(k78k_bytes)) print("RL78/x1y", get_common_masks(rl78s1_bytes)) print("RL78/x2y", get_common_masks(rl78s2_bytes)) print("RL78", get_common_masks(rl78_bytes)) """ k78k0_bytes = dictl(sum([[(repr(l.dvf.magic[:10]), l.nickname) for l in v] for k, v in xmld_k.items() if "78K0R" not in k], start=[]), True) k78k0r_bytes = dictl(sum([[(repr(l.dvf.magic[:10]), l.nickname) for l in v] for k, v in xmld_k.items() if "78K0R" in k], start=[]), True) k78k_bytes = dictl(sum([[(repr(l.dvf.magic[:10]), l.nickname) for l in v] for k, v in xmld_k.items()], start=[]), True) rl78s1_bytes = dictl(sum([[(repr(l.dvf.magic[:10]), l.nickname) for l in v] for k, v in xmld_rl.items() if all(x not in k for x in {"G23","F24","FGIC"})], start=[]), True) rl78s2_bytes = dictl(sum([[(repr(l.dvf.magic[:10]), l.nickname) for l in v] for k, v in xmld_rl.items() if any(x in k for x in {"G23","F24","FGIC"})], start=[]), True) rl78_bytes = dictl(sum([[(repr(l.dvf.magic[:10]), l.nickname) for l in v] for k, v in xmld_rl.items()], start=[]), True) print("78K0", json.dumps(k78k0_bytes, sort_keys=True, indent=4)) print("78K0R", json.dumps(k78k0r_bytes, sort_keys=True, indent=4)) #print("78K", json.dumps(k78k_bytes, sort_keys=True, indent=4)) print("RL78/x1y", json.dumps(rl78s1_bytes, sort_keys=True, indent=4)) print("RL78/x2y", json.dumps(rl78s2_bytes, sort_keys=True, indent=4)) #print("RL78", json.dumps(rl78_bytes, sort_keys=True, indent=4))