board-descriptor: add python script for bd stuff

We had a boar-descriptor module, this script could replace that. It will
access directly to the eeprom
This commit is contained in:
Stefan Eichenberger 2016-07-04 19:30:50 +02:00
parent 4ba63fcae7
commit 9d406de448
5 changed files with 416 additions and 0 deletions

View File

@ -0,0 +1,36 @@
SUMMARY = "Boarddescriptor Tool"
DESCRIPTION = "Read and write from/to the boarddescriptor"
AUTHOR = "Stefan Eichenberger (stefan.eichenberger@netmodule.com)"
SECTION = "core"
LICENSE = "GPLv2+"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
PR = "r0"
RDEPENDS_${PN} = "python-json"
SRC_URI = " \
file://bd.py \
file://descriptor.py \
file://config.json \
file://bd.json \
"
S = "${WORKDIR}"
FILES_${PN} = " \
${bindir}/* \
${libdir}/* \
${sysconfdir}/* \
"
do_install () {
install -d ${D}${bindir}
install -m 0755 bd.py ${D}${bindir}/bd
install -d ${D}${libdir}/python2.7/
install -m 0644 descriptor.py ${D}${libdir}/python2.7/
install -d ${D}${sysconfdir}/bd
install -m 0644 *.json ${D}${sysconfdir}/bd/
}

View File

@ -0,0 +1,62 @@
{
"serial": {"id": 1, "type": "String"},
"production_date": {"id": 2, "type": "Date"},
"hw_ver": {"id": 3, "type": "UInt8"},
"hw_rel": {"id": 4, "type": "UInt8"},
"prod_name": {"id": 5, "type": "String"},
"prod_variant": {"id": 6, "type": "UInt16"},
"prod_compatibility": {"id": 7, "type": "String"},
"eth_mac": {"id": 8, "type": "MAC"},
"ip_addr": {"id": 9, "type": "IPV4"},
"ip_netmask": {"id": 10, "type": "IPV4"},
"ip_gateway": {"id": 11, "type": "IPV4"},
"usb_device_id": {"id": 12, "type": "UInt16"},
"usb_vendor_id": {"id": 13, "type": "UInt16"},
"ram_size": {"id": 14, "type": "UInt32"},
"ram_size64": { "id": 15, "type": "UInt64"},
"flash_size": { "id": 16, "type": "UInt32"},
"flash_size64": { "id": 17, "type": "UInt64"},
"eeprom_size": { "id": 18, "type": "UInt32"},
"nv_ram_size": { "id": 19, "type": "UInt32"},
"cpu_base_clk": { "id": 20, "type": "UInt32"},
"cpu_core_clk": { "id": 21, "type": "UInt32"},
"cpu_bus_clk": { "id": 22, "type": "UInt32"},
"ram_clk": { "id": 23, "type": "UInt32"},
"partition": { "id": 24, "type": "Partition"},
"partition64": { "id": 25, "type": "Partition64"},
"lcd_type": { "id": 26, "type": "UInt16"},
"lcd_backlight": { "id": 27, "type": "UInt8"},
"lcd_contrast": { "id": 28, "type": "UInt8"},
"touch_type": { "id": 29, "type": "UInt16"},
"manufacturer_id": { "id": 30, "type": "String"},
"hmac-sha1-4": { "id": 31, "type": "Hash"},
"fpga_info": { "id": 32, "type": "UInt32"},
"ui_adapter_type": { "id": 4096, "type": "UInt16"},
"hw_flavor": { "id": 4097, "type": "UInt32"},
"voltage": { "id": 4098, "type": "UInt8"},
"pd_module0": { "id": 4100, "type": "String"},
"pd_module1": { "id": 4101, "type": "String"},
"pd_module2": { "id": 4102, "type": "String"},
"pd_module3": { "id": 4103, "type": "String"},
"pd_module4": { "id": 4104, "type": "String"},
"pd_module5": { "id": 4105, "type": "String"},
"pd_phy0": { "id": 4110, "type": "String"},
"pd_phy1": { "id": 4111, "type": "String"},
"pd_dio": { "id": 4120, "type": "String"},
"pd_serial": { "id": 4121, "type": "String"},
"pd_sim": { "id": 4122, "type": "String"},
"pd_led": { "id": 4123, "type": "String"},
"pd_usbhost": { "id": 4124, "type": "String"},
"boot_part": { "id": 32768, "type": "UInt8"},
"factory_reset": { "id": 32769, "type": "UInt8"}
}

View File

@ -0,0 +1,86 @@
#!/usr/bin/python
from optparse import OptionParser
import json
import sys
def read_config(config_file):
fd = open(config_file, "r")
config = fd.read()
fd.close()
return json.loads(config)
def read_all(bd):
for key, value in bd.items():
print ("{0}: {1}".format(key, value))
def read_key(bd, key):
print(bd[key])
def main():
import descriptor
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-c", "--config", action="store", type="string",
dest="config",
help="Configuration file to load",
default="/etc/bd/config.json")
parser.add_option("-a", "--read-all", action="store_true", dest="read_all",
help="Read everything from the boarddescriptors",
default=False)
parser.add_option("-r", "--read-key", action="store", dest="read_key",
type="string",
help="Read key from the boarddescritpors",
default=None)
parser.add_option("-w", "--write-key", action="store", dest="write_key",
type="string",
help="Try to write key to boarddescriptor",
default=None)
parser.add_option("-v", "--write-value", action="store", dest="write_val",
type="string",
help="Value to write if -w (must be specified)",
default=None)
(options, args) = parser.parse_args()
config = read_config(options.config)
# Read the tag -> name -> type list
fd = open(config["tag_list"], "r")
config_table = fd.read()
bd = {}
descs = []
for eeprom in config["eeprom"]:
for valid_bd in eeprom["valid_bds"]:
desc = descriptor.Descriptor(eeprom["path"], valid_bd["start"],
valid_bd["size"], config_table)
desc.read()
bd.update(desc.get_list())
descs.append(desc)
if options.read_all:
read_all(bd)
if options.read_key is not None:
read_key(bd, options.read_key)
if options.write_key is not None:
if options.write_val is None:
print("No value write specified, please set -v")
sys.exit(10)
for desc in descs:
desc.set(options.write_key, options.write_val)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,10 @@
{
"tag_list": "/etc/bd/bd.json",
"eeprom": [
{ "path": "/sys/bus/i2c/devices/0-0050/eeprom", "valid_bds": [
{"name": "info", "start": 0, "size": 1024},
{"name": "settings", "start": 1536, "size": 512}
]
}
]
}

View File

@ -0,0 +1,222 @@
import json
def _array_to_int(data):
# This one works for python2.7 and python3
import codecs
return int(codecs.encode(data, "hex"), 16)
def _array_to_string(data):
return data.decode("utf-8")
def _array_to_hash(data):
return bytearray(data)
def _array_to_mac(data):
return ':'.join('%02x' % b for b in data)
_string_to_type = {
"String": _array_to_string,
"Date": _array_to_string,
"UInt8": _array_to_int,
"UInt16": _array_to_int,
"UInt32": _array_to_int,
"UInt64": _array_to_int,
"MAC": _array_to_mac,
"IPV4": _array_to_string,
"Parition": _array_to_string,
"Parition64": _array_to_string,
"Hash": _array_to_hash
}
def _string_to_array(data):
return bytearray(data, "utf8")
def _uint_to_array(data, format):
value = int(data)
import struct
return struct.pack(format, value)
def _uint8_to_array(data):
return _uint_to_array(data, "B")
def _uint16_to_array(data):
return _uint_to_array(data, "H")
def _uint32_to_array(data):
return _uint_to_array(data, "L")
def _uint64_to_array(data):
return _uint_to_array(data, "Q")
def _not_supported_yet(data):
raise NotImplementedError("Setting this type is not supported yet")
_type_to_value = {
"String": _string_to_array,
"Date": _string_to_array,
"UInt8": _uint8_to_array,
"UInt16": _uint16_to_array,
"UInt32": _uint32_to_array,
"UInt64": _uint64_to_array,
"MAC": _not_supported_yet,
"IPV4": _string_to_array,
"Parition": _string_to_array,
"Parition64": _string_to_array,
"Hash": _not_supported_yet
}
class _Tlv:
def __init__(self, tag, length, value, pos):
self.tag = tag
self.length = length
self.value = value
self.pos = pos
class _BdRaw:
def _verify_checksum(self, data, should_sum):
is_sum = sum(data) & 0xffff
if is_sum != should_sum:
raise ValueError("Checksum does not match (should: {0}, is: {1}"
.format(should_sum, is_sum))
def _get_hw(self, data):
return (data[0] << 8) + data[1]
def _read_binary(self, data):
i = 0
self.id = data[i:i + 4]
i += 4
self.buffer_len = self._get_hw(data[i:])
i += 2
self.checksum = self._get_hw(data[i:])
i += 2
j = 0
self.tlvs = []
while i < self.buffer_len + 8:
# Zero means end of bd
tag = self._get_hw(data[i:i + 2])
i += 2
if tag == 0:
i -= 2
break
length = self._get_hw(data[i:i + 2])
i += 2
value = data[i: i + length]
self.tlvs.append(_Tlv(tag, length, value, i))
i += length
j += 1
return i
def __init__(self, data):
self.is_writable = False
data_length = self._read_binary(data)
if self.checksum != 0:
self._verify_checksum(data[8:data_length], self.checksum)
else:
self.is_writable = True
class _BdParsed:
def __init__(self, strtype, value):
self.value = self._value_type(strtype, value)
def _value_type(self, strtype, value):
for key, fun in _string_to_type.items():
if key == strtype:
return fun(value)
class Descriptor:
def __init__(self, file, offset, max_size, config_table):
self.file = file
self.offset = offset
self.max_size = max_size
self.config_table = json.loads(config_table)
def _read_raw_bd(self):
fd = open(self.file, "rb")
fd.seek(self.offset)
data = fd.read(self.max_size)
fd.close()
# python2.7 reads string instead of bytearray
if type(data) is str:
data = bytearray(data)
return _BdRaw(data)
def _get_name_value(self, tlv):
for key, value in self.config_table.items():
if tlv.tag == value["id"]:
parsed = _BdParsed(value["type"], tlv.value)
return key, parsed.value
def _parse_data(self, bdraw):
bdparsed = {}
tlv_by_name = {}
for tlv in bdraw.tlvs:
name, value = self._get_name_value(tlv)
bdparsed[name] = value
tlv_by_name[name] = tlv
return bdparsed, tlv_by_name
def read(self):
self.bdraw = self._read_raw_bd()
self.bdparsed, self.tlv_by_name = self._parse_data(self.bdraw)
def get_list(self):
return self.bdparsed
def get(self, name):
return self.bdparsed[name]
def _write_bd(self, pos, data, maxlen):
fd = open(self.file, "r+b")
fd.seek(self.offset + pos, 0)
fd.write(data[0:maxlen])
fd.close()
def _do_set(self, name, value, tlv):
for key, config_item in self.config_table.items():
if tlv.tag == config_item["id"]:
type = config_item["type"]
break
if type is None:
raise ValueError("Could not found tag type")
for key, fun in _type_to_value.items():
if key == type:
self._write_bd(tlv.pos, fun(value), tlv.length)
def set(self, name, value):
if self.tlv_by_name is None:
raise ImportError("Descriptor not read yet, run read_all first")
tlv = self.tlv_by_name.get(name)
if tlv is None:
return False
if not self.bd.is_writable:
raise IOError("This operation is not permitted on \
this descriptor (ro)")
self._do_set(name, value, tlv)
return True