mmiogrok/dvf/xmlmeta.py

230 lines
9.1 KiB
Python
Executable File

#!/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))