Index: embios/trunk/tools/misc.py |
— | — | @@ -0,0 +1,185 @@ |
| 2 | +#!/usr/bin/env python
|
| 3 | +#
|
| 4 | +#
|
| 5 | +# Copyright 2010 TheSeven, benedikt93, Farthen
|
| 6 | +#
|
| 7 | +#
|
| 8 | +# This file is part of emBIOS.
|
| 9 | +#
|
| 10 | +# emBIOS is free software: you can redistribute it and/or
|
| 11 | +# modify it under the terms of the GNU General Public License as
|
| 12 | +# published by the Free Software Foundation, either version 2 of the
|
| 13 | +# License, or (at your option) any later version.
|
| 14 | +#
|
| 15 | +# emBIOS is distributed in the hope that it will be useful,
|
| 16 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 17 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 18 | +# See the GNU General Public License for more details.
|
| 19 | +#
|
| 20 | +# You should have received a copy of the GNU General Public License
|
| 21 | +# along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 22 | +#
|
| 23 | +#
|
| 24 | +
|
| 25 | +"""
|
| 26 | + This file includes some reusable functions and classes that might be useful
|
| 27 | + to all python scripts
|
| 28 | +"""
|
| 29 | +
|
| 30 | +import sys
|
| 31 | +
|
| 32 | +class Logger(object):
|
| 33 | + """
|
| 34 | + Simple stdout logger.
|
| 35 | + Loglevel 4 is most verbose, Loglevel 0: Only say something if there is an error.
|
| 36 | + The log function doesn't care about the loglevel and always logs to stdout.
|
| 37 | + """
|
| 38 | + def __init__(self):
|
| 39 | + # Possible values: 0 (only errors), 1 (warnings), 2 (info, recommended for production use), 3 and more (debug)
|
| 40 | + self.loglevel = 3
|
| 41 | +
|
| 42 | + def log(self, text, indent = 0, target = "stdout"):
|
| 43 | + text = (indent * " ") + text
|
| 44 | + text = text.replace("\n", "\n" + (indent * " "), text.count("\n") - 1)
|
| 45 | + if target == "stdout":
|
| 46 | + sys.stdout.write(text)
|
| 47 | + elif target == "string":
|
| 48 | + return text
|
| 49 | +
|
| 50 | + def debug(self, text, indent = 0, target = "stdout"):
|
| 51 | + if self.loglevel >= 3:
|
| 52 | + self.log("DEBUG: " + text, indent, target)
|
| 53 | +
|
| 54 | + def info(self, text, indent = 0, target = "stdout"):
|
| 55 | + if self.loglevel >= 2:
|
| 56 | + self.log(text, indent, target)
|
| 57 | +
|
| 58 | + def warn(self, text, indent = 0, target = "stdout"):
|
| 59 | + if self.loglevel >= 1:
|
| 60 | + self.log("WARNING: " + text, indent, target)
|
| 61 | +
|
| 62 | + def error(self, text, indent = 0, target = "stdout"):
|
| 63 | + self.log("ERROR: " + text, indent, target)
|
| 64 | +
|
| 65 | +
|
| 66 | +class Bunch(dict):
|
| 67 | + """
|
| 68 | + This is a dict whose items can also be accessed with
|
| 69 | + bunchinstance.something.
|
| 70 | + """
|
| 71 | + def __init__(self, **kw):
|
| 72 | + dict.__init__(self, kw)
|
| 73 | + self.__dict__ = self
|
| 74 | +
|
| 75 | + def __getstate__(self):
|
| 76 | + return self
|
| 77 | +
|
| 78 | + def __setstate__(self, state):
|
| 79 | + self.update(state)
|
| 80 | + self.__dict__ = self
|
| 81 | +
|
| 82 | +
|
| 83 | +class Error(Exception):
|
| 84 | + def __init__(self, value=None):
|
| 85 | + self.value = value
|
| 86 | + def __str__(self):
|
| 87 | + if self.value != None:
|
| 88 | + return repr(self.value)
|
| 89 | +
|
| 90 | +
|
| 91 | +def trimdoc(docstring):
|
| 92 | + """
|
| 93 | + Trims whitespace from docstrings
|
| 94 | + """
|
| 95 | + if not docstring:
|
| 96 | + return ''
|
| 97 | + # Convert tabs to spaces (following the normal Python rules)
|
| 98 | + # and split into a list of lines:
|
| 99 | + lines = docstring.expandtabs().splitlines()
|
| 100 | + # Determine minimum indentation (first line doesn't count):
|
| 101 | + indent = sys.maxint
|
| 102 | + for line in lines[1:]:
|
| 103 | + stripped = line.lstrip()
|
| 104 | + if stripped:
|
| 105 | + indent = min(indent, len(line) - len(stripped))
|
| 106 | + # Remove indentation (first line is special):
|
| 107 | + trimmed = [lines[0].strip()]
|
| 108 | + if indent < sys.maxint:
|
| 109 | + for line in lines[1:]:
|
| 110 | + trimmed.append(line[indent:].rstrip())
|
| 111 | + # Strip off trailing and leading blank lines:
|
| 112 | + while trimmed and not trimmed[-1]:
|
| 113 | + trimmed.pop()
|
| 114 | + while trimmed and not trimmed[0]:
|
| 115 | + trimmed.pop(0)
|
| 116 | + # Return a single string:
|
| 117 | + return '\n'.join(trimmed)
|
| 118 | +
|
| 119 | +
|
| 120 | +def getfuncdoc(funcdict):
|
| 121 | + """
|
| 122 | + Extracts important information from a dict of functions like the
|
| 123 | + docstring and arguments and returns them in a human readable format
|
| 124 | + """
|
| 125 | + import inspect
|
| 126 | + import re
|
| 127 | + functions = Bunch()
|
| 128 | + for function in funcdict:
|
| 129 | + function = funcdict[function].func
|
| 130 | + docinfo = Bunch()
|
| 131 | + name = function.__name__
|
| 132 | + args = inspect.getargspec(function)[0]
|
| 133 | + docinfo['varargs'] = False
|
| 134 | + if inspect.getargspec(function)[1]:
|
| 135 | + docinfo['varargs'] = True
|
| 136 | + kwargvalues = inspect.getargspec(function)[3]
|
| 137 | + kwargs = Bunch()
|
| 138 | + if args:
|
| 139 | + if kwargvalues:
|
| 140 | + argnum = len(args) - len(kwargvalues)
|
| 141 | + kwargnum = len(kwargvalues)
|
| 142 | + kwargs = dict(zip(args[argnum:], kwargvalues))
|
| 143 | + else:
|
| 144 | + argnum = len(args)
|
| 145 | + else:
|
| 146 | + argnum = 0
|
| 147 | + docinfo['args'] = args[1:argnum]
|
| 148 | + docinfo['kwargs'] = kwargs
|
| 149 | + if function.__doc__:
|
| 150 | + # strip unneccessary whitespace
|
| 151 | + docinfo['documentation'] = trimdoc(function.__doc__)
|
| 152 | + else:
|
| 153 | + docinfo['documentation'] = None
|
| 154 | + functions[name] = docinfo
|
| 155 | + return functions
|
| 156 | +
|
| 157 | +
|
| 158 | +def gendoc(funcdict, indentwidth = 4, logtarget = "string"):
|
| 159 | + logger = Logger()
|
| 160 | + doc = getfuncdoc(funcdict)
|
| 161 | + ret = ""
|
| 162 | + for function in sorted(doc.items()):
|
| 163 | + function = function[0]
|
| 164 | + ret += logger.log("def " + function + "(", target = logtarget)
|
| 165 | + counter = 0
|
| 166 | + if doc[function]['args']:
|
| 167 | + for arg in doc[function]['args']:
|
| 168 | + if counter > 0:
|
| 169 | + sys.stdout.write(", ")
|
| 170 | + counter += 1
|
| 171 | + ret += logger.log(arg, target = logtarget)
|
| 172 | + if doc[function]['kwargs']:
|
| 173 | + for kwarg, kwargvalue in doc[function]['kwargs'].items():
|
| 174 | + if counter > 0:
|
| 175 | + sys.stdout.write(", ")
|
| 176 | + counter += 1
|
| 177 | + ret += logger.log(kwarg + "=" + str(kwargvalue), target = logtarget)
|
| 178 | + if doc[function]['varargs']:
|
| 179 | + ret += logger.log("*argv", target = logtarget)
|
| 180 | + ret += logger.log("):\n", target = logtarget)
|
| 181 | + if doc[function]['documentation']:
|
| 182 | + ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)
|
| 183 | + ret += logger.log(trimdoc(doc[function]['documentation']) + "\n", indent = 2 * indentwidth, target = logtarget)
|
| 184 | + ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)
|
| 185 | + ret += logger.log("\n", target = logtarget)
|
| 186 | + return ret |
\ No newline at end of file |
Index: embios/trunk/tools/embios.py |
— | — | @@ -23,8 +23,6 @@ |
24 | 24 |
|
25 | 25 | import sys
|
26 | 26 | import os
|
27 | | -import inspect
|
28 | | -import re
|
29 | 27 | import time
|
30 | 28 | import struct
|
31 | 29 | import locale
|
— | — | @@ -32,8 +30,8 @@ |
33 | 31 | from functools import wraps
|
34 | 32 |
|
35 | 33 | import libembios
|
36 | | -from libembios import Error
|
37 | 34 | import libembiosdata
|
| 35 | +from misc import Error, Logger, getfuncdoc
|
38 | 36 |
|
39 | 37 |
|
40 | 38 | class NotImplementedError(Error):
|
— | — | @@ -59,38 +57,8 @@ |
60 | 58 | It is auto generated from various places.
|
61 | 59 | """
|
62 | 60 | logger = Logger()
|
63 | | - cmddict= Commandline.cmddict
|
64 | | - doc = {}
|
65 | | - # This sorts the output of various internal functions
|
66 | | - # and puts everything in easy readable form
|
67 | | - for function in cmddict:
|
68 | | - function = cmddict[function].func
|
69 | | - docinfo = {}
|
70 | | - name = function.__name__
|
71 | | - args = inspect.getargspec(function)[0]
|
72 | | - docinfo['varargs'] = False
|
73 | | - if inspect.getargspec(function)[1]:
|
74 | | - docinfo['varargs'] = True
|
75 | | - kwargvalues = inspect.getargspec(function)[3]
|
76 | | - kwargs = {}
|
77 | | - if args:
|
78 | | - if kwargvalues:
|
79 | | - argnum = len(args) - len(kwargvalues)
|
80 | | - kwargnum = len(kwargvalues)
|
81 | | - kwargs = dict(zip(args[argnum:], kwargvalues))
|
82 | | - else:
|
83 | | - argnum = len(args)
|
84 | | - else:
|
85 | | - argnum = 0
|
86 | | - docinfo['args'] = args[1:argnum]
|
87 | | - docinfo['kwargs'] = kwargs
|
88 | | - if function.__doc__:
|
89 | | - # strip unneccessary whitespace
|
90 | | - docinfo['documentation'] = re.sub(r'\n ', '\n', function.__doc__)
|
91 | | - else:
|
92 | | - docinfo['documentation'] = None
|
93 | | - doc[name] = docinfo
|
94 | | -
|
| 61 | + cmddict = Commandline.cmddict
|
| 62 | + doc = getfuncdoc(cmddict)
|
95 | 63 | if not specific:
|
96 | 64 | logger.log("Please provide a command and (if needed) parameters as command line arguments\n\n")
|
97 | 65 | logger.log("Available commands:\n\n")
|
— | — | @@ -99,7 +67,7 @@ |
100 | 68 | for function in sorted(doc.items()):
|
101 | 69 | function = function[0]
|
102 | 70 | if specific == False or specific == function:
|
103 | | - logger.log(" " + function + " ")
|
| 71 | + logger.log(function + " ", 2)
|
104 | 72 | for arg in doc[function]['args']:
|
105 | 73 | logger.log("<" + arg + "> ")
|
106 | 74 | if doc[function]['kwargs']:
|
— | — | @@ -107,9 +75,10 @@ |
108 | 76 | logger.log("[" + kwarg + "] ")
|
109 | 77 | if doc[function]['varargs']:
|
110 | 78 | logger.log("<db1> ... <dbN>")
|
| 79 | + logger.log("\n")
|
111 | 80 | if doc[function]['documentation']:
|
112 | | - logger.log(doc[function]['documentation']+"\n")
|
113 | | -
|
| 81 | + logger.log(doc[function]['documentation']+"\n", 4)
|
| 82 | + logger.log("\n")
|
114 | 83 | logger.log("\n")
|
115 | 84 |
|
116 | 85 | if errormsg:
|
— | — | @@ -117,35 +86,6 @@ |
118 | 87 | exit(2)
|
119 | 88 |
|
120 | 89 |
|
121 | | -class Logger(object):
|
122 | | - """
|
123 | | - Simple stdout logger.
|
124 | | - Loglevel 4 is most verbose, Loglevel 0: Only say something if there is an error.
|
125 | | - The log function doesn't care about the loglevel and always logs to stdout.
|
126 | | - """
|
127 | | - def __init__(self):
|
128 | | - # Possible values: 0 (only errors), 1 (warnings), 2 (info, recommended for production use), 3 and more (debug)
|
129 | | - self.loglevel = 3
|
130 | | -
|
131 | | - def log(self, text):
|
132 | | - sys.stdout.write(text)
|
133 | | -
|
134 | | - def debug(self, text):
|
135 | | - if self.loglevel >= 3:
|
136 | | - self.log("DEBUG: " + text)
|
137 | | -
|
138 | | - def info(self, text):
|
139 | | - if self.loglevel >= 2:
|
140 | | - self.log(text)
|
141 | | -
|
142 | | - def warn(self, text):
|
143 | | - if self.loglevel >= 1:
|
144 | | - self.log("WARNING: " + text)
|
145 | | -
|
146 | | - def error(self, text):
|
147 | | - self.log("ERROR: " + text)
|
148 | | -
|
149 | | -
|
150 | 90 | def command(func):
|
151 | 91 | """
|
152 | 92 | Decorator for all commands.
|
— | — | @@ -506,17 +446,17 @@ |
507 | 447 | % (len(threads), cpuload * 100, coreload * 100, threadload * 100))
|
508 | 448 | self.logger.info("Thread dump:\n")
|
509 | 449 | for thread in threads:
|
510 | | - self.logger.info(" "+thread.name+":\n")
|
511 | | - self.logger.info(" Thread id: " + str(thread.id)+"\n")
|
512 | | - self.logger.info(" Thread type: " + thread.type+"\n")
|
513 | | - self.logger.info(" Thread state: " + thread.state+"\n")
|
514 | | - self.logger.info(" Block type: " + thread.block_type+"\n")
|
515 | | - self.logger.info(" Blocked by: " + self._hex(thread.blocked_by_ptr)+"\n")
|
516 | | - self.logger.info(" Priority: " + str(thread.priority)+"/255\n")
|
517 | | - self.logger.info(" Current CPU load: %.1f%%\n" % ((thread.cpuload * 100) / 255.))
|
518 | | - self.logger.info(" CPU time (total): "+str(datetime.timedelta(microseconds = thread.cputime_total))+"\n")
|
519 | | - self.logger.info(" Stack address: " + self._hex(thread.stackaddr)+"\n")
|
520 | | - self.logger.info(" Registers:\n")
|
| 450 | + self.logger.info(thread.name+":\n", 2)
|
| 451 | + self.logger.info("Thread id: " + str(thread.id)+"\n", 4)
|
| 452 | + self.logger.info("Thread type: " + thread.type+"\n", 4)
|
| 453 | + self.logger.info("Thread state: " + thread.state+"\n", 4)
|
| 454 | + self.logger.info("Block type: " + thread.block_type+"\n", 4)
|
| 455 | + self.logger.info("Blocked by: " + self._hex(thread.blocked_by_ptr)+"\n", 4)
|
| 456 | + self.logger.info("Priority: " + str(thread.priority)+"/255\n", 4)
|
| 457 | + self.logger.info("Current CPU load: %.1f%%\n" % ((thread.cpuload * 100) / 255.), 4)
|
| 458 | + self.logger.info("CPU time (total): "+str(datetime.timedelta(microseconds = thread.cputime_total))+"\n", 4)
|
| 459 | + self.logger.info("Stack address: " + self._hex(thread.stackaddr)+"\n", 4)
|
| 460 | + self.logger.info("Registers:\n", 4)
|
521 | 461 | for registerrange in range(4):
|
522 | 462 | self.logger.info(" ")
|
523 | 463 | for register in range(registerrange, 16, 4):
|
— | — | @@ -523,7 +463,7 @@ |
524 | 464 | registerrepr = "r"+str(register)
|
525 | 465 | self.logger.info("{0:3s}: 0x{1:08X} ".format(registerrepr, thread.regs["r"+str(register)]))
|
526 | 466 | self.logger.info("\n")
|
527 | | - self.logger.info(" cpsr: 0x{0:08X}".format(thread.regs.cpsr))
|
| 467 | + self.logger.info("cpsr: 0x{0:08X}".format(thread.regs.cpsr), 6)
|
528 | 468 | self.logger.info("\n")
|
529 | 469 |
|
530 | 470 | @command
|
Index: embios/trunk/tools/libembios.py |
— | — | @@ -26,15 +26,9 @@ |
27 | 27 | import usb.core
|
28 | 28 | import libembiosdata
|
29 | 29 |
|
| 30 | +from misc import Bunch, Error
|
30 | 31 | from functools import wraps
|
31 | 32 |
|
32 | | -class Error(Exception):
|
33 | | - def __init__(self, value=None):
|
34 | | - self.value = value
|
35 | | - def __str__(self):
|
36 | | - if self.value != None:
|
37 | | - return repr(self.value)
|
38 | | -
|
39 | 33 | class ArgumentError(Error):
|
40 | 34 | pass
|
41 | 35 |
|
— | — | @@ -49,25 +43,8 @@ |
50 | 44 |
|
51 | 45 | class ReceiveError(Error):
|
52 | 46 | pass
|
53 | | -
|
54 | | -
|
55 | | -class Bunch(dict):
|
56 | | - """
|
57 | | - This is a dict whose items can also be accessed with
|
58 | | - bunchinstance.something.
|
59 | | - """
|
60 | | - def __init__(self, **kw):
|
61 | | - dict.__init__(self, kw)
|
62 | | - self.__dict__ = self
|
63 | 47 |
|
64 | | - def __getstate__(self):
|
65 | | - return self
|
66 | | -
|
67 | | - def __setstate__(self, state):
|
68 | | - self.update(state)
|
69 | | - self.__dict__ = self
|
70 | 48 |
|
71 | | -
|
72 | 49 | def command(timeout = None):
|
73 | 50 | """
|
74 | 51 | Decorator for all commands.
|
— | — | @@ -96,6 +73,8 @@ |
97 | 74 | if timeout is not None:
|
98 | 75 | self.lib.dev.timeout = oldtimeout
|
99 | 76 | return ret
|
| 77 | + func._command = True
|
| 78 | + wrapper.func = func
|
100 | 79 | return wrapper
|
101 | 80 | return decorator
|
102 | 81 |
|
— | — | @@ -962,31 +941,45 @@ |
963 | 942 |
|
964 | 943 |
|
965 | 944 | if __name__ == "__main__":
|
966 | | - # Some tests
|
967 | | - import sys
|
968 | | - embios = Embios()
|
969 | | - resp = embios.getversioninfo()
|
970 | | - sys.stdout.write("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) +
|
971 | | - "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
|
972 | | - resp = embios.getusermemrange()
|
973 | | - sys.stdout.write("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
|
974 | | - memaddr = resp.lower
|
975 | | - maxlen = resp.upper - resp.lower
|
976 | | - f = open("./embios.py", "rb")
|
977 | | - sys.stdout.write("Loading test file (embios.py) to send over USB...\n")
|
978 | | - datastr = f.read()[:maxlen]
|
979 | | - sys.stdout.write("Sending data...\n")
|
980 | | - embios.write(memaddr, datastr)
|
981 | | - sys.stdout.write("Encrypting data with the hardware key...\n")
|
982 | | - embios.aesencrypt(memaddr, len(datastr), 0)
|
983 | | - sys.stdout.write("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
|
984 | | - f = open("./libembios-test-encrypted.bin", "wb")
|
985 | | - f.write(embios.read(memaddr, len(datastr)))
|
986 | | - sys.stdout.write("Decrypting the data again...\n")
|
987 | | - embios.aesdecrypt(memaddr, len(datastr), 0)
|
988 | | - sys.stdout.write("Reading data back from device...\n")
|
989 | | - readdata = embios.read(memaddr, len(datastr))
|
990 | | - if readdata == datastr:
|
991 | | - sys.stdout.write("Data matches!")
|
992 | | - else:
|
993 | | - sys.stdout.write("Data does NOT match. Something went wrong") |
\ No newline at end of file |
| 945 | + from misc import Logger
|
| 946 | + logger = Logger()
|
| 947 | + if sys.argv[1] == "test":
|
| 948 | + # Some tests
|
| 949 | + import sys
|
| 950 | + embios = Embios()
|
| 951 | + resp = embios.getversioninfo()
|
| 952 | + logger.log("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) +
|
| 953 | + "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
|
| 954 | + resp = embios.getusermemrange()
|
| 955 | + logger.log("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
|
| 956 | + memaddr = resp.lower
|
| 957 | + maxlen = resp.upper - resp.lower
|
| 958 | + f = open("./embios.py", "rb")
|
| 959 | + logger.log("Loading test file (embios.py) to send over USB...\n")
|
| 960 | + datastr = f.read()[:maxlen]
|
| 961 | + logger.log("Sending data...\n")
|
| 962 | + embios.write(memaddr, datastr)
|
| 963 | + logger.log("Encrypting data with the hardware key...\n")
|
| 964 | + embios.aesencrypt(memaddr, len(datastr), 0)
|
| 965 | + logger.log("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
|
| 966 | + f = open("./libembios-test-encrypted.bin", "wb")
|
| 967 | + f.write(embios.read(memaddr, len(datastr)))
|
| 968 | + logger.log("Decrypting the data again...\n")
|
| 969 | + embios.aesdecrypt(memaddr, len(datastr), 0)
|
| 970 | + logger.log("Reading data back from device...\n")
|
| 971 | + readdata = embios.read(memaddr, len(datastr))
|
| 972 | + if readdata == datastr:
|
| 973 | + logger.log("Data matches!")
|
| 974 | + else:
|
| 975 | + logger.log("Data does NOT match. Something went wrong")
|
| 976 | +
|
| 977 | + elif sys.argv[1] == "gendoc":
|
| 978 | + # Generates Documentation
|
| 979 | + from misc import gendoc
|
| 980 | + logger.log("Generating documentation\n")
|
| 981 | + cmddict = {}
|
| 982 | + for attr, value in Embios.__dict__.iteritems():
|
| 983 | + if getattr(value, 'func', False):
|
| 984 | + if getattr(value.func, '_command', False):
|
| 985 | + cmddict[value.func.__name__] = value
|
| 986 | + logger.log(gendoc(cmddict)) |
\ No newline at end of file |