Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '''
- Simple dirty script to convert Freescale/NXP "Update Command List" files
- ("ucl2.xml", used by MfgTool) to POSIX shell script (.sh).
- '''
- from __future__ import print_function
- import sys
- import xml.etree.ElementTree
- import re
- import os
- import argparse
- #from subprocess import call
- try: # python 2
- import ConfigParser as configparser
- except ImportError: # assume python >= 3
- import configparser
- def eprint(*args, **kwargs):
- print(*args, file=sys.stderr, **kwargs)
- g_uclVars = {}
- g_uclFiles = {}
- '''
- ucl2.xml format:
- <CMD> type:
- "pull" - Does UtpRead(body, file) transaction.
- "push" - Does UtpWrite(body, file) transaction.
- "drop" - Does UtpCommand(body) then waits for device to disconnect.
- "boot" - Finds configured device, forces it to "body" device and downloads "file".
- "find" - Waits for "timeout" seconds for the "body" device to connect.
- "show" - Parse and show device info in "file".
- '''
- shhdr = '''
- UTP_COM_DEV="$1"
- assert_file() {
- if [ ! -f "$1" ]; then
- echo "E: File '$1' do not exist" 1>&2
- exit 1
- fi
- }
- utpcmd() {
- ./utp_com -d "$UTP_COM_DEV" -c "$@"
- }
- verbose() {
- if [ "$VERBOSE" -gt 2 ]; then
- echo "$1"
- fi
- }
- '''
- class MfgVars():
- SH_VAR_PREFIX = 'IMX_CFG_'
- VAR_UCL_TAG = 'VAR'
- def __init__(self):
- self.shVars = {}
- self.uclVars = {}
- self.optVars = {}
- def addCfgIni(self, cfgIniFile):
- cfgp = configparser.ConfigParser()
- cfgp.read(cfgIniFile)
- for sect in cfgp.sections():
- for key, val in cfgp.items(sect):
- sectlw = sect.lower()
- if sectlw == 'variable':
- self.uclVars[key] = val
- else:
- sectAndKey = '{}_{}'.format(sectlw, key)
- self.optVars[sectAndKey] = val
- def addCliArg(self, keyValStr):
- toks = keyValStr.split('=')
- assert(len(toks) == 2)
- #eprint("E: Bad key-value string'
- key = toks[0]
- val = toks[1]
- self.uclVars[key] = val
- def getShDecl(self):
- s = ''
- s += '# --- Variables from MfgTool "cfg.ini" ----\n'
- for k in sorted(self.optVars):
- shvd = self.uclToSh(k, '', refFmt=False)
- s += '{}="{}"\n'.format(shvd, self.optVars[k])
- for k in sorted(self.uclVars):
- shvd = self.uclToSh(k, refFmt=False)
- s += '{}="{}"\n'.format(shvd, self.uclVars[k])
- return s
- def uclToSh(self, uclVar, xprefix='VAR', refFmt=True):
- if uclVar.startswith('%') and uclVar.endswith('%'):
- uclVar = uclVar[1:-1] # remove first and last
- uclVar = uclVar.upper()
- shName = self.SH_VAR_PREFIX
- if xprefix: shName += xprefix + '_'
- shName += uclVar
- return '${{{}}}'.format(shName) if refFmt else shName
- def strReplaceUclToSh(self, s, expand=False):
- # replace mfgtool '%variable%' with shell/bash '${VARIABLE}'
- for m in re.finditer(r'\%([a-zA-Z0-9_]*?)\%', s):
- uclVarx = m.group(0) # i.e. "%variable%"
- uclVar = m.group(1)
- if expand:
- newVar = self.uclVars[uclVar]
- else:
- newVar = self.uclToSh(uclVar)
- #eprint('I: Replacing "{}" with "{}"'.format(mfgVar, shVar))
- s = s.replace(uclVarx, newVar)
- return s
- class MfgUclCmd():
- def __init__(self):
- pass
- class MfgUpdateCommandList():
- ''' Update Command List '''
- def __init__(self, xmlListObj, mfgVars=None):
- self.name = xmlListObj.get('name')
- self.mfgVars = mfgVars if mfgVars else MfgVars()
- self.utpFiles = {}
- self.utpCmds = []
- self.initCmds = []
- self.initFiles = {}
- self.initUboot = None
- for cmd in xmlListObj.findall('CMD'):
- #self.utpCmds.append(
- self.parseXmlCmd(cmd)
- def parseXmlCmd(self, cmd, addSrcComments=True, targetDevice='MX7D'):
- #<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
- s = ''
- a = cmd.attrib
- if addSrcComments:
- s += '# ucl2: {}\n'.format(a)
- cmdInfo = cmd.text.strip() if cmd.text else ''
- afile = None
- if a['state'] == 'BootStrap':
- assert(len(self.utpCmds) == 0) # should not be mixed in order
- s += '# {}\n'.format(cmdInfo)
- if 'file' in a:
- afile = self.mfgVars.strReplaceUclToSh(a['file'], expand=True)
- self.initFiles[afile] = a['file']
- if a['type'] == 'boot':
- s += '# Note; only dcd as first step (setup ram)\n'
- s += '{}:dcd\n'.format(afile)
- self.initUboot = afile
- elif a['type'] == 'load':
- assert(afile)
- if afile in self.initFiles:
- pass
- ifdevs = a['ifdev'].split()
- if targetDevice in ifdevs:
- s += '# assumes target device(s) {}\n'.format(ifdevs)
- s += '{}:dcd\n'.format(afile, a['address'])
- else:
- eprint('I: Ignored due to ifdev: {}'.format(a))
- elif a['type'] == 'jump':
- s += '# Note, to make this boot, the clear_dcd field seems necessary\n'
- s += '{}:clear_dcd,load,plug,jump header\n'.format(self.initUboot)
- else:
- eprint('W: Unknown BootStrap type:"{}"'.format(a['type']))
- self.initCmds.append(s)
- elif a['state'] == 'Updater':
- s += 'echo_verbose "{}"\n'.format(cmdInfo)
- if 'file' in a:
- afile = '${FILES_DIR}/' + self.mfgVars.strReplaceUclToSh(a['file'])
- self.utpFiles[afile] = a['file']
- if 'body' in a:
- s += 'utpcmd "{}"'.format(self.sanitizeCmdStr(a['body']))
- else:
- s += '# WARNING: ignoring <CMD> as no "body"\n'
- return s
- if afile:
- s += ' -f "{}"'.format(afile)
- self.utpCmds.append(s + '\n')
- else:
- s += '# WARNING: ignoring <CMD> as "state" != "Updater"\n'
- return s
- return s
- def sanitizeCmdStr(self, s):
- s = s.strip()
- pre = '$ '
- if s.startswith(pre):
- s = s[len(pre):]
- else:
- pre = ''
- s = s.replace('$', '\\$')
- s = self.mfgVars.strReplaceUclToSh(s) #after dollar esscape
- return pre + s
- def getShFiles(self):
- s = ''
- s += '# ---- Files used -----\n'
- for f in self.utpFiles:
- s += 'assert_file "{}"\n'.format(f)
- return s
- def getInitConf(self):
- return'\n'.join(self.initCmds)
- def getShCmds(self):
- return'\n'.join(self.utpCmds)
- def getSh(self):
- s = ''
- s += '# ==== LIST: "{}" =================\n'.format(self.name)
- s += self.mfgVars.getShDecl() + '\n'
- s += self.getShFiles() + '\n'
- s += self.getShCmds() + '\n'
- s += '# ----imx loader conf -----\n'
- s += self.getInitConf() + '\n'
- return s
- # mgtool usage: [program] [arguments] [settings]=[values]
- # -s --setting Specify any UCL keywords.
- # -p --ports Specify the number of boards connected.
- # -o --profilepath Specify path to Profiles directory.
- # -c --profile Specify the profile to use.
- # -l --list Specify command list.
- # -x --noexit Wait for further connections upon finishing all operations.
- # -h --help Display this help information.
- def main():
- from argparse import RawTextHelpFormatter
- ap = argparse.ArgumentParser(
- formatter_class=RawTextHelpFormatter,
- description='Convert MfgTool ucl2.xml and cfg.ini to shell script',
- epilog= '')
- ap.add_argument('--cfgini', type=str, default=None, metavar='FILE',
- help='Path to cfg.ini')
- ap.add_argument('--uclxml', type=str, default=None, metavar='FILE',
- help='Path to ucl2.xml')
- ap.add_argument('-l','--list', type=str, default=None, metavar='NAME',
- help='Name on list in the ucl2.xml file.')
- ap.add_argument('-x', '--noexit', action='store_true',
- help='mfgtool compatible dummy. (does nothing)')
- ap.add_argument('-p', '--ports', metavar='N',
- help='Specify the number of boards connected.'\
- 'mfgtool compatible dummy (does nothing).')
- ap.add_argument('-o', '--profilepath', metavar='DIR',
- help='Specify path to Profiles directory.'\
- 'mfgtool compatible dummy (does nothing).')
- ap.add_argument('-c', '--profile', metavar='NAME',
- help='Specify the profile to use. '\
- 'mfgtool compatible (does nothing).')
- ap.add_argument('-s', '--setting', metavar='"KEY=VAL"', action='append',
- default=[],
- help='Specify UCL variable. overrides entries in cfi.ini. '\
- 'mfgtool compatible (does nothing)')
- args = ap.parse_args()
- #return print(args)
- if args.cfgini == None and args.uclxml == None:
- eprint('E: no arguments')
- exit(1)
- mfgVars = MfgVars()
- if args.cfgini != None:
- mfgVars.addCfgIni(args.cfgini)
- elif os.path.isfile('cfg.ini'):
- mfgVars.addCfgIni('cfg.ini')
- for kvs in args.setting:
- mfgVars.addCliArg(kvs)
- if args.uclxml != None:
- if not os.path.isfile(args.uclxml):
- eprint('E: file "{}" do not exist'.format(args.uclxml))
- exit(1)
- etree = xml.etree.ElementTree.parse(args.uclxml).getroot()
- for cmdList in etree.findall('LIST'):
- cmdListName = cmdList.get('name')
- if args.list != None and args.list == cmdListName:
- mfgUcl = MfgUpdateCommandList(cmdList, mfgVars)
- print(mfgUcl.getSh())
- else:
- eprint('I: Ignoring list "{}"\n'.format(cmdListName))
- main()
Add Comment
Please, Sign In to add comment