Guest User

Untitled

a guest
May 20th, 2018
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.83 KB | None | 0 0
  1. '''
  2. Simple dirty script to convert Freescale/NXP "Update Command List" files
  3. ("ucl2.xml", used by MfgTool) to POSIX shell script (.sh).
  4.  
  5. '''
  6. from __future__ import print_function
  7. import sys
  8.  
  9. import xml.etree.ElementTree
  10. import re
  11. import os
  12. import argparse
  13. #from subprocess import call
  14.  
  15. try: # python 2
  16. import ConfigParser as configparser
  17. except ImportError: # assume python >= 3
  18. import configparser
  19.  
  20.  
  21. def eprint(*args, **kwargs):
  22. print(*args, file=sys.stderr, **kwargs)
  23.  
  24. g_uclVars = {}
  25. g_uclFiles = {}
  26.  
  27. '''
  28. ucl2.xml format:
  29.  
  30. <CMD> type:
  31. "pull" - Does UtpRead(body, file) transaction.
  32. "push" - Does UtpWrite(body, file) transaction.
  33. "drop" - Does UtpCommand(body) then waits for device to disconnect.
  34. "boot" - Finds configured device, forces it to "body" device and downloads "file".
  35. "find" - Waits for "timeout" seconds for the "body" device to connect.
  36. "show" - Parse and show device info in "file".
  37.  
  38. '''
  39.  
  40. shhdr = '''
  41. UTP_COM_DEV="$1"
  42.  
  43. assert_file() {
  44. if [ ! -f "$1" ]; then
  45. echo "E: File '$1' do not exist" 1>&2
  46. exit 1
  47. fi
  48. }
  49.  
  50. utpcmd() {
  51. ./utp_com -d "$UTP_COM_DEV" -c "$@"
  52. }
  53.  
  54. verbose() {
  55. if [ "$VERBOSE" -gt 2 ]; then
  56. echo "$1"
  57. fi
  58. }
  59. '''
  60.  
  61. class MfgVars():
  62.  
  63. SH_VAR_PREFIX = 'IMX_CFG_'
  64. VAR_UCL_TAG = 'VAR'
  65.  
  66. def __init__(self):
  67. self.shVars = {}
  68. self.uclVars = {}
  69. self.optVars = {}
  70.  
  71. def addCfgIni(self, cfgIniFile):
  72. cfgp = configparser.ConfigParser()
  73. cfgp.read(cfgIniFile)
  74. for sect in cfgp.sections():
  75. for key, val in cfgp.items(sect):
  76. sectlw = sect.lower()
  77. if sectlw == 'variable':
  78. self.uclVars[key] = val
  79. else:
  80. sectAndKey = '{}_{}'.format(sectlw, key)
  81. self.optVars[sectAndKey] = val
  82.  
  83. def addCliArg(self, keyValStr):
  84. toks = keyValStr.split('=')
  85. assert(len(toks) == 2)
  86. #eprint("E: Bad key-value string'
  87. key = toks[0]
  88. val = toks[1]
  89. self.uclVars[key] = val
  90.  
  91.  
  92. def getShDecl(self):
  93. s = ''
  94. s += '# --- Variables from MfgTool "cfg.ini" ----\n'
  95. for k in sorted(self.optVars):
  96. shvd = self.uclToSh(k, '', refFmt=False)
  97. s += '{}="{}"\n'.format(shvd, self.optVars[k])
  98.  
  99. for k in sorted(self.uclVars):
  100. shvd = self.uclToSh(k, refFmt=False)
  101. s += '{}="{}"\n'.format(shvd, self.uclVars[k])
  102.  
  103. return s
  104.  
  105. def uclToSh(self, uclVar, xprefix='VAR', refFmt=True):
  106. if uclVar.startswith('%') and uclVar.endswith('%'):
  107. uclVar = uclVar[1:-1] # remove first and last
  108. uclVar = uclVar.upper()
  109. shName = self.SH_VAR_PREFIX
  110. if xprefix: shName += xprefix + '_'
  111. shName += uclVar
  112.  
  113. return '${{{}}}'.format(shName) if refFmt else shName
  114.  
  115. def strReplaceUclToSh(self, s, expand=False):
  116. # replace mfgtool '%variable%' with shell/bash '${VARIABLE}'
  117. for m in re.finditer(r'\%([a-zA-Z0-9_]*?)\%', s):
  118. uclVarx = m.group(0) # i.e. "%variable%"
  119. uclVar = m.group(1)
  120. if expand:
  121. newVar = self.uclVars[uclVar]
  122. else:
  123. newVar = self.uclToSh(uclVar)
  124. #eprint('I: Replacing "{}" with "{}"'.format(mfgVar, shVar))
  125. s = s.replace(uclVarx, newVar)
  126. return s
  127.  
  128. class MfgUclCmd():
  129. def __init__(self):
  130. pass
  131.  
  132. class MfgUpdateCommandList():
  133. ''' Update Command List '''
  134. def __init__(self, xmlListObj, mfgVars=None):
  135. self.name = xmlListObj.get('name')
  136. self.mfgVars = mfgVars if mfgVars else MfgVars()
  137. self.utpFiles = {}
  138. self.utpCmds = []
  139. self.initCmds = []
  140. self.initFiles = {}
  141. self.initUboot = None
  142.  
  143. for cmd in xmlListObj.findall('CMD'):
  144. #self.utpCmds.append(
  145. self.parseXmlCmd(cmd)
  146.  
  147.  
  148. def parseXmlCmd(self, cmd, addSrcComments=True, targetDevice='MX7D'):
  149. #<CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
  150.  
  151. s = ''
  152. a = cmd.attrib
  153. if addSrcComments:
  154. s += '# ucl2: {}\n'.format(a)
  155.  
  156. cmdInfo = cmd.text.strip() if cmd.text else ''
  157.  
  158. afile = None
  159.  
  160. if a['state'] == 'BootStrap':
  161. assert(len(self.utpCmds) == 0) # should not be mixed in order
  162. s += '# {}\n'.format(cmdInfo)
  163.  
  164. if 'file' in a:
  165. afile = self.mfgVars.strReplaceUclToSh(a['file'], expand=True)
  166. self.initFiles[afile] = a['file']
  167.  
  168. if a['type'] == 'boot':
  169. s += '# Note; only dcd as first step (setup ram)\n'
  170. s += '{}:dcd\n'.format(afile)
  171. self.initUboot = afile
  172.  
  173. elif a['type'] == 'load':
  174. assert(afile)
  175. if afile in self.initFiles:
  176. pass
  177.  
  178. ifdevs = a['ifdev'].split()
  179. if targetDevice in ifdevs:
  180. s += '# assumes target device(s) {}\n'.format(ifdevs)
  181. s += '{}:dcd\n'.format(afile, a['address'])
  182. else:
  183. eprint('I: Ignored due to ifdev: {}'.format(a))
  184.  
  185. elif a['type'] == 'jump':
  186. s += '# Note, to make this boot, the clear_dcd field seems necessary\n'
  187. s += '{}:clear_dcd,load,plug,jump header\n'.format(self.initUboot)
  188.  
  189. else:
  190. eprint('W: Unknown BootStrap type:"{}"'.format(a['type']))
  191.  
  192. self.initCmds.append(s)
  193.  
  194. elif a['state'] == 'Updater':
  195.  
  196. s += 'echo_verbose "{}"\n'.format(cmdInfo)
  197.  
  198. if 'file' in a:
  199. afile = '${FILES_DIR}/' + self.mfgVars.strReplaceUclToSh(a['file'])
  200. self.utpFiles[afile] = a['file']
  201.  
  202. if 'body' in a:
  203. s += 'utpcmd "{}"'.format(self.sanitizeCmdStr(a['body']))
  204. else:
  205. s += '# WARNING: ignoring <CMD> as no "body"\n'
  206. return s
  207. if afile:
  208. s += ' -f "{}"'.format(afile)
  209.  
  210. self.utpCmds.append(s + '\n')
  211. else:
  212. s += '# WARNING: ignoring <CMD> as "state" != "Updater"\n'
  213. return s
  214.  
  215.  
  216. return s
  217.  
  218.  
  219. def sanitizeCmdStr(self, s):
  220. s = s.strip()
  221. pre = '$ '
  222. if s.startswith(pre):
  223. s = s[len(pre):]
  224. else:
  225. pre = ''
  226. s = s.replace('$', '\\$')
  227. s = self.mfgVars.strReplaceUclToSh(s) #after dollar esscape
  228. return pre + s
  229.  
  230.  
  231. def getShFiles(self):
  232. s = ''
  233. s += '# ---- Files used -----\n'
  234. for f in self.utpFiles:
  235. s += 'assert_file "{}"\n'.format(f)
  236. return s
  237.  
  238. def getInitConf(self):
  239. return'\n'.join(self.initCmds)
  240.  
  241. def getShCmds(self):
  242. return'\n'.join(self.utpCmds)
  243.  
  244. def getSh(self):
  245. s = ''
  246.  
  247. s += '# ==== LIST: "{}" =================\n'.format(self.name)
  248. s += self.mfgVars.getShDecl() + '\n'
  249. s += self.getShFiles() + '\n'
  250. s += self.getShCmds() + '\n'
  251. s += '# ----imx loader conf -----\n'
  252. s += self.getInitConf() + '\n'
  253. return s
  254.  
  255. # mgtool usage: [program] [arguments] [settings]=[values]
  256. # -s --setting Specify any UCL keywords.
  257. # -p --ports Specify the number of boards connected.
  258. # -o --profilepath Specify path to Profiles directory.
  259. # -c --profile Specify the profile to use.
  260. # -l --list Specify command list.
  261. # -x --noexit Wait for further connections upon finishing all operations.
  262. # -h --help Display this help information.
  263.  
  264. def main():
  265. from argparse import RawTextHelpFormatter
  266. ap = argparse.ArgumentParser(
  267. formatter_class=RawTextHelpFormatter,
  268. description='Convert MfgTool ucl2.xml and cfg.ini to shell script',
  269. epilog= '')
  270.  
  271. ap.add_argument('--cfgini', type=str, default=None, metavar='FILE',
  272. help='Path to cfg.ini')
  273.  
  274. ap.add_argument('--uclxml', type=str, default=None, metavar='FILE',
  275. help='Path to ucl2.xml')
  276.  
  277. ap.add_argument('-l','--list', type=str, default=None, metavar='NAME',
  278. help='Name on list in the ucl2.xml file.')
  279.  
  280. ap.add_argument('-x', '--noexit', action='store_true',
  281. help='mfgtool compatible dummy. (does nothing)')
  282.  
  283. ap.add_argument('-p', '--ports', metavar='N',
  284. help='Specify the number of boards connected.'\
  285. 'mfgtool compatible dummy (does nothing).')
  286.  
  287. ap.add_argument('-o', '--profilepath', metavar='DIR',
  288. help='Specify path to Profiles directory.'\
  289. 'mfgtool compatible dummy (does nothing).')
  290.  
  291. ap.add_argument('-c', '--profile', metavar='NAME',
  292. help='Specify the profile to use. '\
  293. 'mfgtool compatible (does nothing).')
  294.  
  295. ap.add_argument('-s', '--setting', metavar='"KEY=VAL"', action='append',
  296. default=[],
  297. help='Specify UCL variable. overrides entries in cfi.ini. '\
  298. 'mfgtool compatible (does nothing)')
  299.  
  300. args = ap.parse_args()
  301. #return print(args)
  302.  
  303. if args.cfgini == None and args.uclxml == None:
  304. eprint('E: no arguments')
  305. exit(1)
  306.  
  307. mfgVars = MfgVars()
  308.  
  309. if args.cfgini != None:
  310. mfgVars.addCfgIni(args.cfgini)
  311. elif os.path.isfile('cfg.ini'):
  312. mfgVars.addCfgIni('cfg.ini')
  313.  
  314. for kvs in args.setting:
  315. mfgVars.addCliArg(kvs)
  316.  
  317. if args.uclxml != None:
  318. if not os.path.isfile(args.uclxml):
  319. eprint('E: file "{}" do not exist'.format(args.uclxml))
  320. exit(1)
  321.  
  322.  
  323. etree = xml.etree.ElementTree.parse(args.uclxml).getroot()
  324. for cmdList in etree.findall('LIST'):
  325. cmdListName = cmdList.get('name')
  326.  
  327. if args.list != None and args.list == cmdListName:
  328. mfgUcl = MfgUpdateCommandList(cmdList, mfgVars)
  329. print(mfgUcl.getSh())
  330.  
  331. else:
  332. eprint('I: Ignoring list "{}"\n'.format(cmdListName))
  333.  
  334.  
  335. main()
Add Comment
Please, Sign In to add comment