230 lines
9.1 KiB
Python
230 lines
9.1 KiB
Python
|
#!/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<<bits)-1
|
||
|
negb = mask
|
||
|
posb = mask
|
||
|
|
||
|
for b in l:
|
||
|
i = int.from_bytes(b, byteorder='big')
|
||
|
posb = posb & i
|
||
|
negb = (negb & ~i) & mask
|
||
|
|
||
|
negb = (~negb & mask).to_bytes(16, byteorder='big')
|
||
|
posb = posb.to_bytes(16, byteorder='big')
|
||
|
#negb = ''.join("%02x"%x for x in negb)
|
||
|
#posb = ''.join("%02x"%x for x in posb)
|
||
|
return (negb, posb)
|
||
|
|
||
|
|
||
|
def parsedvf(path: str, is78k: bool) -> 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))
|
||
|
|