Subversion Repositories freemyipod

Rev

Rev 139 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 139 Rev 171
Line 1... Line 1...
1
#!/usr/bin/env python
1
#!/usr/bin/env python
2
#
2
#
3
#
3
#
4
#    Copyright 2010 TheSeven, benedikt93
4
#    Copyright 2010 TheSeven, benedikt93, Farthen
5
#
5
#
6
#
6
#
7
#    This file is part of emBIOS.
7
#    This file is part of emBIOS.
8
#
8
#
9
#    emBIOS is free software: you can redistribute it and/or
9
#    emBIOS is free software: you can redistribute it and/or
Line 19... Line 19...
19
#    You should have received a copy of the GNU General Public License
19
#    You should have received a copy of the GNU General Public License
20
#    along with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
20
#    along with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
21
#
21
#
22
#
22
#
23
 
23
 
24
# note: handles commands 1 to 20
-
 
25
 
-
 
26
import sys
24
import sys
-
 
25
import os
-
 
26
import inspect
27
import time
27
import re
-
 
28
 
28
import libembios
29
import libembios
-
 
30
from libembios import Error
29
import struct
31
import libembiosdata
30
 
32
 
-
 
33
class NotImplementedError(Error):
-
 
34
    pass
31
 
35
 
32
def usage():
36
class ArgumentError(Error):
33
  print ""
37
    pass
34
  print "Please provide a command and (if needed) parameters as command line arguments"
38
 
35
  print ""
39
class ArgumentTypeError(Error):
36
  print "Available commands:"
40
    def __init__(self, expected, seen=False):
37
  print ""
41
        self.expected = expected
38
  print "  getinfo <infotype>"
42
        self.seen = seen
39
  print "    Get info on the running emBIOS."
43
    def __str__(self):
40
  print "    <infotype> may be either off 'version', 'packetsize', 'usermemrange'."
44
        if self.seen:
41
  print ""
45
            return "Expected " + str(self.expected) + " but saw " + str(self.seen)
42
  print "  reset <force>"
46
        else:
43
  print "    Resets the device"
47
            return "Expected " + str(self.expected) + ", but saw something else"
44
  print "    If <force> is 1, the reset will be forced, otherwise it will be gracefully,"
48
 
45
  print "    which may take some time."
49
 
46
  print ""
50
def usage(errormsg=None, specific=False):
47
  print "  poweroff <force>"
51
    """
48
  print "    Powers the device off"
52
        Prints the usage information.
49
  print "    If <force> is 1, the poweroff will be forced, otherwise it will be gracefully,"
53
        It is auto generated from various places.
50
  print "    which may take some time."
54
    """
51
  print ""
55
    logger = Logger()
52
  print ""
56
    cmddict= Commandline.cmddict
53
  print "  uploadfile <offset> <file> <usedma> <freezescheduler>"
57
    doc = {}
54
  print "    Uploads a file to the iPod"
58
    # This sorts the output of various internal functions
55
  print "      <offset>: the address to upload the file to"
59
    # and puts everything in easy readable form
56
  print "      <file>: the path to the file"
60
    for function in cmddict:
57
  print "      <usedma>: if 0, DMA will not be used when uploading the file,"
61
        function = cmddict[function].func
58
  print "          otherwise it will be used. It can be omitted, default is then 1"
62
        docinfo = {}
59
  print "      <freezescheduler>: if not 0, the scheduler will be frozen during DMA access"
63
        name = function.__name__
60
  print "          to prevent non-consistent data after the transfer."
64
        args = inspect.getargspec(function)[0]
61
  print "          It can be omitted, default is then 0"
65
        docinfo['varargs'] = False
62
  print ""
66
        if inspect.getargspec(function)[1]:
63
  print "  downloadfile <offset> <size> <file> <usedma> <freezescheduler>"
67
            docinfo['varargs'] = True
64
  print "    Uploads a file to the iPod"
68
        kwargvalues = inspect.getargspec(function)[3]
65
  print "      <offset>: the address to upload the file to"
69
        kwargs = {}
66
  print "      <size>: the number of bytes to be read"
70
        if args:
67
  print "      <file>: the path to the file"
71
            if kwargvalues:
68
  print "      <usedma>: if 0, DMA will not be used when downloading the file,"
72
                argnum = len(args) - len(kwargvalues)
69
  print "          otherwise it will be used. It can be omitted, default is then 1"
73
                kwargnum = len(kwargvalues)
70
  print "      <freezescheduler>: if not 0, the scheduler will be frozen during DMA access"
74
                kwargs = dict(zip(args[argnum:], kwargvalues))
71
  print "          to prevent non-consistent data after the transfer"
75
            else:
72
  print "          It can be omitted, default is then 0"
76
                argnum = len(args)
73
  print ""
77
        else:
74
  print "  uploadint <offset> <data>"
78
            argnum = 0
75
  print "    Uploads a single integer to the iPod"
79
        docinfo['args'] = args[1:argnum]
76
  print "      <offset>: the address to upload the integer to"
80
        docinfo['kwargs'] = kwargs
77
  print "      <data>: the integer to upload"
81
        if function.__doc__:
78
  print ""
82
            # strip unneccessary whitespace
79
  print "  downloadint <offset>"
83
            docinfo['documentation'] = re.sub(r'\n        ', '\n', function.__doc__)
80
  print "    Downloads a single integer from the iPod and prints it to the console window"
84
        else:
81
  print "      <offset>: the address to download the integer from"
85
            docinfo['documentation'] = None
82
  print ""
86
        doc[name] = docinfo
83
  print ""
87
 
84
  print "  i2crecv <bus> <slave> <addr> <size>"
88
    if not specific:
85
  print "    Reads data from an I2C device"
89
        logger.log("Please provide a command and (if needed) parameters as command line arguments\n\n")
86
  print "      <bus> the bus index"
90
        logger.log("Available commands:\n\n")
87
  print "      <slave> the slave address"
-
 
88
  print "      <addr> the start address on the I2C device"
-
 
89
  print "      <size> the number of bytes to read"
-
 
90
  print ""
-
 
91
  print "  i2csend <bus> <slave> <addr> <db1> <db2> ... <dbN>"
-
 
92
  print "    Writes data to an I2C device"
-
 
93
  print "      <bus> the bus index"
-
 
94
  print "      <slave> the slave address"
-
 
95
  print "      <addr> the start address on the I2C device"
-
 
96
  print "      <db1> ... <dbN> the data in single bytes, seperated by whitespaces,"
-
 
97
  print "                      eg. 0x37 0x56 0x45 0x12"
-
 
98
  print ""
-
 
99
  print ""
-
 
100
  print "  readusbconsole <size> <outtype> <file>"
-
 
101
  print "    Reads data from the USB console."
-
 
102
  print "      <size>: the number of bytes to read"
-
 
103
  print "      <outtype>: defines how to output the result:"
-
 
104
  print "        'file': writes the result to file <file>"
-
 
105
  print "        'printstring': writes the result as string to the console window"
-
 
106
  print "        'printhex': writes the result in hexedit notation to the console window"
-
 
107
  print "      <file>: the file to write the result to, can be omitted"
-
 
108
  print "               if <outtype> is not 'file'"
-
 
109
  print ""
-
 
110
  print "  writeusbconsole file <file> <offset> <length>"
-
 
111
  print "    Writes the file <file> to the USB console."
-
 
112
  print "      Optional params <offset> <length>: specify the range in <file> to write"
-
 
113
  print "  writeusbconsole direct <i1> <i2> ... <iN>"
-
 
114
  print "    Writes the integers <i1> ... <iN> to the USB console."
-
 
115
  print "  writeusbconsole string <str>"
-
 
116
  print "    Writes the string <str> to the USB console."
-
 
117
  print ""
-
 
118
  print "  readdevconsole <bitmask> <size> <outtype> <file>"
-
 
119
  print "    Reads data from one or more of the device's consoles."
-
 
120
  print "      <bitmask>: the bitmask of the consoles to read from"
-
 
121
  print "      <size>: the number of bytes to read"
-
 
122
  print "      <outtype>: defines how to output the result:"
-
 
123
  print "        'file': writes the result to file <file>"
-
 
124
  print "        'printstring': writes the result as string to the console window"
-
 
125
  print "        'printhex': writes the result in hexedit notation to the console window"
-
 
126
  print "      <file>: the file to write the result to, can be omitted"
-
 
127
  print "               if <outtype> is not 'file'"
-
 
128
  print ""
-
 
129
  print "  writedevconsole file <bitmask> <file> <offset> <length>"
-
 
130
  print "    Writes the file <file> to the device consoles specified by <bitmask>"
-
 
131
  print "      Optional params <offset> <length>: specify the range in <file> to write"
-
 
132
  print "  writedevconsole direct <bitmask> <i1> <i2> ... <iN>"
-
 
133
  print "    Writes the integers <i1> ... <iN> to the device consoles specified"
-
 
134
  print "                         by <bitmask>"
-
 
135
  print "  writedevconsole string <bitmask> <str>"
-
 
136
  print "    Writes the string <str> to the device consoles specified by <bitmask>"
-
 
137
  print ""
-
 
138
  print "  flushconsolebuffers <bitmask>"
-
 
139
  print "    flushes one or more of the device consoles' buffers."
-
 
140
  print "      <bitmask>: the bitmask of the consoles to be flushed"
-
 
141
  print ""
-
 
142
  print ""
-
 
143
  print "  getprocessinformation / getprocinfo"
-
 
144
  print "    Fetches data on the currently running processes"
-
 
145
  print "     ATTENTION: this function will be print the information to the console window."
-
 
146
  print "                If several threads are running this might overflow the window,"
-
 
147
  print "                causing not everything to be shown."
-
 
148
  print ""
-
 
149
  print "  lockscheduler"
-
 
150
  print "    Locks (freezes) the scheduler"
-
 
151
  print ""
-
 
152
  print "  unlockscheduler"
-
 
153
  print "    Unlocks the scheduler"
-
 
154
  print ""
-
 
155
  print "  suspendthread <threadid>"
-
 
156
  print "    Suspends/resumes the thread with thread ID <threadid>"
-
 
157
  print ""
-
 
158
  print "  resumethread <threadid>"
-
 
159
  print "    Resumes the thread with thread ID <threadid>"
-
 
160
  print ""
-
 
161
  print "  killthread <threadid>"
-
 
162
  print "    Kills the thread with thread ID <threadid>"
-
 
163
  print ""
-
 
164
  print "  createthread <namepointer> <entrypoint> <stackpointer> <stacksize> <type> <priority> <state>"
-
 
165
  print "    Creates a new thread and returns its thread ID"
-
 
166
  print "      <namepointer> a pointer to the thread's name"
-
 
167
  print "      <entrypoint> a pointer to the entrypoint of the thread"
-
 
168
  print "      <stackpointer> a pointer to the stack of the thread"
-
 
169
  print "      <stacksize> the size of the thread's stack"
-
 
170
  print "      <type> the thread type, vaild are: 0 => user thread, 1 => system thread"
-
 
171
  print "      <priority> the priority of the thread, from 1 to 255"
-
 
172
  print "      <state> the thread's initial state, valid are: 1 => ready, 0 => suspended"
-
 
173
  print ""
-
 
174
  print "  execimage <offset>"
-
 
175
  print "    Executes the emBIOS executable image at <offset>."
-
 
176
  print ""
-
 
177
  print "  execfirmware <offset>"
-
 
178
  print "    Executes the firmware image at the specified address <offset>."
-
 
179
  print ""
-
 
180
  print ""
-
 
181
  print "  readrawbootflash <addr_bootflsh> <addr_mem> <size>"
-
 
182
  print "    Reads <size> bytes from bootflash to memory."
-
 
183
  print "      <addr_bootflsh>: the address in bootflash to read from"
-
 
184
  print "      <addr_mem>: the address in memory to copy the data to"
-
 
185
  print ""
-
 
186
  print "  writerawbootflash <addr_mem> <addr_bootflsh> <size>"
-
 
187
  print "    Writes <size> bytes from memory to bootflash."
-
 
188
  print "    Don't call this unless you really know what you're doing."
-
 
189
  print "      <addr_mem>: the address in memory to copy the data from"
-
 
190
  print "      <addr_bootflsh>: the address in bootflash to write to"
-
 
191
  print ""
-
 
192
  print ""
-
 
193
  print "  flushcaches"
-
 
194
  print "    Flushes the CPUs data and instruction caches."
-
 
195
  print ""
-
 
196
  print "All numbers are hexadecimal!"
-
 
197
  exit(2)
-
 
198
 
-
 
199
 
-
 
200
def parsecommand(dev, argv):
-
 
201
  if len(argv) < 2: usage()
-
 
202
 
-
 
203
  elif argv[1] == "getinfo":
-
 
204
    if len(argv) != 3: usage()
-
 
205
    dev.getinfo(argv[2])
-
 
206
  
-
 
207
  elif argv[1] == "reset":
-
 
208
    if len(argv) != 3: usage()
-
 
209
    dev.reset(int(argv[2]), 16)
-
 
210
  
-
 
211
  elif argv[1] == "poweroff":
-
 
212
    if len(argv) != 3: usage()
-
 
213
    dev.poweroff(int(argv[2]), 16)
-
 
214
 
-
 
215
    
-
 
216
  elif argv[1] == "uploadfile":
-
 
217
    if len(argv) < 4 or len(argv) > 6: usage()
-
 
218
    if len(argv) > 4:
-
 
219
      usedma = int(argv[4], 16)
-
 
220
      if len(argv) > 5:
-
 
221
        freezesched = int(argv[5], 16)
-
 
222
      else:
-
 
223
        freezesched = 0
-
 
224
    else:
-
 
225
      freezesched = 0
-
 
226
      usedma = 1
-
 
227
    dev.uploadfile(int(argv[2], 16), argv[3], usedma, freezesched)
-
 
228
  
-
 
229
  elif argv[1] == "downloadfile":
-
 
230
    if len(argv) < 5 or len(argv) > 7: usage()
-
 
231
    if len(argv) > 5:
-
 
232
      usedma = int(argv[5], 16)
-
 
233
      if len(argv) > 6:
-
 
234
        freezesched = int(argv[6], 16)
-
 
235
      else:
-
 
236
        freezesched = 0
-
 
237
    else:
91
    else:
238
      freezesched = 0
92
        logger.log("\n")
239
      usedma = 1
-
 
240
    dev.downloadfile(int(argv[2], 16), int(argv[3], 16), argv[4], usedma, freezesched)
-
 
241
  
-
 
242
  elif argv[1] == "uploadint":
93
    for function in sorted(doc.items()):
243
    if len(argv) != 4: usage()
94
        function = function[0]
244
    dev.uploadint(int(argv[2], 16), int(argv[3], 16))
95
        if specific == False or specific == function:
245
  
-
 
246
  elif argv[1] == "downloadint":
-
 
247
    if len(argv) != 3: usage()
96
            logger.log("  " + function + " ")
248
    dev.downloadint(int(argv[2], 16))
97
            for arg in doc[function]['args']:
249
  
-
 
250
  
-
 
251
  elif argv[1] == "i2cread":
-
 
252
    if len(argv) != 6: usage()
-
 
253
    dev.i2crecv(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16), int(argv[5], 16))
-
 
254
    
-
 
255
  elif argv[1] == "i2csend":
-
 
256
    if len(argv) < 6: usage()
98
                logger.log("<" + arg + "> ")
257
    data = ""
-
 
258
    ptr = 5
-
 
259
    while ptr < len(argv):
99
            if doc[function]['kwargs']:
260
      data += struct.pack("<B", int(argv[ptr], 16))
100
                for kwarg in doc[function]['kwargs']:
261
      ptr += 1
-
 
262
    dev.i2csend(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16), data)
101
                    logger.log("[" + kwarg + "] ")
263
  
-
 
264
  
-
 
265
  elif argv[1] == "readusbconsole":
102
            if doc[function]['varargs']:
266
    if len(argv) not in [4, 5]: usage()
103
                logger.log("<db1> ... <dbN>")
267
    if len(argv) == 4: argv[4] = ""
104
            if doc[function]['documentation']:
268
    dev.readusbcon(int(argv[2], 16), argv[3], argv[4])
105
                logger.log(doc[function]['documentation']+"\n")
269
  
-
 
270
  elif argv[1] == "writeusbconsole":
-
 
271
    if len(argv) < 4: usage()
-
 
272
    
106
    
273
    if argv[2] == "file":
-
 
274
      f = open(argv[3], "rb")
-
 
275
      data = f.read()
107
    logger.log("\n")
276
      
108
 
277
      if len(argv) > 4:
-
 
278
        offset = int(argv[4], 16)
-
 
279
      else:
109
    if errormsg:
280
        offset = 0
-
 
281
      if len(argv) > 5:
-
 
282
        size = int(argv[5], 16)
110
        logger.error(str(errormsg)+"\n")
283
      else:
111
    exit(2)
284
        size = len(data)
-
 
285
      if len(argv) > 6: usage()
-
 
286
      
-
 
287
      dev.writeusbcon(data, 0, offset, size)
-
 
288
      
-
 
289
    if argv[2] == "direct":
-
 
290
      data = ""
-
 
291
      ptr = 3
-
 
292
      while ptr < len(argv):
-
 
293
        data += struct.pack("<I", int(argv[ptr], 16))
-
 
294
        ptr += 1
-
 
295
      dev.writeusbcon(data)
-
 
296
      
-
 
297
    if argv[2] == "string":
-
 
298
      if len(argv) > 4: usage()
-
 
299
      dev.writeusbcon(argv[3])
-
 
300
    
-
 
301
    else: usage()
-
 
302
  
112
 
303
  elif argv[1] == "readdevconsole":
-
 
304
    if len(argv) not in [5, 6]: usage()
-
 
305
    if len(argv) == 5: argv[5] = ""
-
 
306
    dev.readusbcon(int(argv[2], 16), int(argv[3], 16), argv[4], argv[5])
-
 
307
  
113
 
308
  elif argv[1] == "writedevconsole":
-
 
309
    if len(argv) < 5: usage()
-
 
310
    
-
 
311
    if argv[2] == "file":
-
 
312
      f = open(argv[4], "rb")
-
 
313
      data = f.read()
114
class Logger(object):
314
      
115
    """
315
      if len(argv) > 5:
-
 
316
        offset = int(argv[5], 16)
-
 
317
      else:
-
 
318
        offset = 0
-
 
319
      if len(argv) > 6:
-
 
320
        size = int(argv[6], 16)
116
        Simple stdout logger.
321
      else:
-
 
322
        size = len(data)
-
 
323
      if len(argv) > 7: usage()
-
 
324
      
-
 
325
      dev.writeusbcon(int(argv[3], 16), data, 0, offset, size)
117
        Loglevel 4 is most verbose, Loglevel 0 only say something if there is an error.
326
      
118
    """
327
    if argv[2] == "direct":
-
 
328
      data = ""
-
 
329
      ptr = 4
-
 
330
      while ptr < len(argv):
119
    def __init__(self):
331
        data += struct.pack("<I", int(argv[ptr], 16))
120
        # Possible values: 0 (only errors), 1 (warnings), 2 (info, recommended for production use), 3 and more (debug)
332
        ptr += 1
121
        self.loglevel = 3
333
      dev.writeusbcon(int(argv[3], 16), data)
-
 
334
      
122
        
335
    if argv[2] == "string":
123
    def log(self, text):
336
      if len(argv) > 5: usage()
124
        sys.stdout.write(text)
337
      dev.writedevcon(int(argv[3], 16), argv[4])
-
 
338
    
125
    
339
    else: usage()
126
    def debug(self, text):
340
  
-
 
341
  elif argv[1] == "flushconsolebuffers":
-
 
342
    if len(argv) != 3: usage()
127
        if self.loglevel >= 3:
343
    dev.flushconsolebuffers(int(argv[2], 16))
-
 
344
   
-
 
345
   
-
 
346
  elif argv[1] == "getprocessinformation" or argv[1] == "getprocinfo":
-
 
347
    if len(argv) != 2: usage()
-
 
348
    dev.getprocinfo()
128
            self.log(text)
349
    
129
    
350
  elif argv[1] == "lockscheduler":
-
 
351
    if len(argv) != 2: usage()
-
 
352
    dev.freezescheduler(1)
130
    def info(self, text):
353
    
-
 
354
  elif argv[1] == "unlockscheduler":
-
 
355
    if len(argv) != 2: usage()
131
        if self.loglevel >= 2:
356
    dev.freezescheduler(0)
132
            self.log(text)
357
    
-
 
358
  elif argv[1] == "suspendthread":
-
 
359
    if len(argv) != 3: usage()
-
 
360
    dev.suspendthread(1, int(argv[2], 16))
-
 
361
    
-
 
362
  elif argv[1] == "resumethread":
-
 
363
    if len(argv) != 3: usage()
-
 
364
    dev.suspendthread(0, int(argv[2], 16))
-
 
365
    
-
 
366
  elif argv[1] == "killthread":
-
 
367
    if len(argv) != 3: usage()
-
 
368
    dev.killthread(int(argv[2], 16))
-
 
369
    
-
 
370
  elif argv[1] == "createthread":
-
 
371
    if len(argv) != 9: usage()
-
 
372
    dev.createthread(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16), int(argv[5], 16), int(argv[6], 16), int(argv[7], 16), int(argv[8], 16))
-
 
373
    
-
 
374
  elif argv[1] == "execimage":
-
 
375
    if len(argv) != 3: usage()
-
 
376
    dev.execimage(int(argv[2], 16))
-
 
377
    
133
    
378
  elif argv[1] == "execfirmware":
-
 
379
    if len(argv) != 3: usage()
-
 
380
    dev.execfirmware(int(argv[2], 16))
134
    def warning(self, text):
381
    
-
 
382
  elif argv[1] == "readrawbootflash":
-
 
383
    if len(argv) != 5: usage()
-
 
384
    dev.readrawbootflash(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16))
-
 
385
    
-
 
386
  elif argv[1] == "writerawbootflash":
-
 
387
    if len(argv) != 5: usage()
135
        if self.loglevel >= 1:
388
    dev.writerawbootflash(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16))
-
 
389
 
-
 
390
 
-
 
391
  elif argv[1] == "flushcaches":
-
 
392
    if len(argv) != 2: usage()
136
            self.log("WARNING: " + text)
393
    dev.flushcaches()
-
 
394
    
137
    
-
 
138
    def error(self, text):
-
 
139
        self.log("ERROR: " + text)
-
 
140
 
-
 
141
 
-
 
142
def command(func):
-
 
143
    """
-
 
144
        Decorator for all commands.
-
 
145
        The decorated function is called with (self, all, other, arguments, ...)
-
 
146
    """
-
 
147
    def decorator(args):
-
 
148
        return func(args[0], *args[1:])
-
 
149
    func._command = True
-
 
150
    decorator.func = func
-
 
151
    return decorator
-
 
152
 
-
 
153
 
-
 
154
def commandClass(cls):
-
 
155
    """
-
 
156
        Decorator for the class. Sets the self.cmddict of the class
-
 
157
        to all functions decorated with @command
-
 
158
    """
-
 
159
    cls.cmddict = {}
-
 
160
    for attr, value in cls.__dict__.iteritems():
-
 
161
        if getattr(value, 'func', False):
-
 
162
            if getattr(value.func, '_command', False):
-
 
163
                cls.cmddict[value.func.__name__] = value
-
 
164
    return cls
-
 
165
 
-
 
166
 
-
 
167
@commandClass
-
 
168
class Commandline(object):
-
 
169
    """
-
 
170
        If you want to create a new commandline function you just need to
-
 
171
        create a function with the name of it in this class and decorate
-
 
172
        it with the decorator @command. If you don't want to call the desired
-
 
173
        function (wrong arguments etc) just raise ArgumentError with or
-
 
174
        without an error message or raise ArgumentCountError
-
 
175
    """
-
 
176
    def __init__(self):
-
 
177
        self.logger = Logger()
-
 
178
        try:
-
 
179
            self.embios = libembios.Embios()
-
 
180
        except libembios.DeviceNotFoundError:
-
 
181
            self.logger.error("No emBIOS device found!")
395
  else: usage()
182
            end(1)
-
 
183
        
-
 
184
    def _parsecommand(self, func, args):
-
 
185
        # adds self to the commandline args.
-
 
186
        # this is needed because the functions need access to their class.
-
 
187
        args.insert(0, self)
-
 
188
        if func in self.cmddict:
-
 
189
            try:
-
 
190
                self.cmddict[func](args)
-
 
191
            except ArgumentError, e:
-
 
192
                usage(e)
-
 
193
            except ArgumentError:
-
 
194
                usage("Syntax Error in function '" + func + "'")
-
 
195
            except ArgumentTypeError, e:
-
 
196
                usage(e)
-
 
197
            except NotImplementedError:
-
 
198
                self.logger.error("This function is not implemented yet!")
-
 
199
            except libembios.DeviceError, e:
-
 
200
                self.logger.error(str(e))
-
 
201
            except TypeError, e:
-
 
202
                if str(e).split(" ", 1)[0] == func + "()":
-
 
203
                    self.logger.error(usage("Argument Error in '" + func + "': Wrong argument count", specific=func))
-
 
204
                else:
-
 
205
                    raise
-
 
206
        else:
-
 
207
            usage("No such command")
-
 
208
    
-
 
209
    @staticmethod
-
 
210
    def _bool(something):
-
 
211
        """
-
 
212
            Converts quite everything into bool.
-
 
213
        """
-
 
214
        if type(something) == bool:
-
 
215
            return something
-
 
216
        elif type(something) == int or type(something) == long:
-
 
217
            return bool(something)
-
 
218
        elif type(something == str):
-
 
219
            truelist = ['true', '1', 't', 'y', 'yes']
-
 
220
            falselist = ['false', '0', 'f', 'n', 'no']
-
 
221
            if something.lower() in truelist:
-
 
222
                return True
-
 
223
            elif something.lower() in falselist:
-
 
224
                return False
-
 
225
        raise ArgumentTypeError("bool", "'"+str(something)+"'")
-
 
226
 
-
 
227
    @staticmethod
-
 
228
    def _hexint(something):
-
 
229
        """
-
 
230
            Converts quite everything to a hexadecimal represented integer.
-
 
231
            This works for default arguments too, because it returns
-
 
232
            None when it found that it got a NoneType object.
-
 
233
        """
-
 
234
        if type(something) == int or type(something) == long:
-
 
235
            return something
-
 
236
        elif type(something) == str:
-
 
237
            try:
-
 
238
                return int(something, 16)
-
 
239
            except ValueError:
-
 
240
                raise ArgumentTypeError("hexadecimal coded integer", "'"+str(something)+"'")
-
 
241
        elif type(something) == NoneType:
-
 
242
            return None
-
 
243
        else:
-
 
244
            raise ArgumentTypeError("hexadecimal coded integer", "'"+str(something)+"'")
-
 
245
 
-
 
246
    @staticmethod
-
 
247
    def _strcheck(string, values):
-
 
248
        if string in values:
-
 
249
            return string
-
 
250
        else:
-
 
251
            expected = ""
-
 
252
            for item in values:
-
 
253
                expected += "'" + item + "', "
-
 
254
            expected = expected[:-2]
-
 
255
            raise ArgumentTypeError("one out of " + expected, "'" + string + "'")
-
 
256
    
-
 
257
    
-
 
258
    @command
-
 
259
    def getinfo(self, infotype):
-
 
260
        """
-
 
261
            Get info on the running emBIOS.
-
 
262
            <infotype> may be either of 'version', 'packetsize', 'usermemrange'.
-
 
263
        """
-
 
264
        if infotype == "version":
-
 
265
            resp = self.embios.getversioninfo()
-
 
266
            self.logger.info(libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) +
-
 
267
                             "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
-
 
268
        elif infotype == "packetsize":
-
 
269
            resp = self.embios.getpacketsizeinfo()
-
 
270
            self.logger.info("Maximum packet sizes: "+str(resp))
-
 
271
        elif infotype == "usermemrange":
-
 
272
            resp = self.embios.getusermemrange()
-
 
273
            self.logger.info("The user memory range is "+hex(resp.lower)+" - "+hex(resp.upper-1))
-
 
274
        else:
-
 
275
            raise ArgumentTypeError("one out of 'version', 'packetsize', 'usermemrange'", infotype)
-
 
276
    
-
 
277
    @command
-
 
278
    def reset(self, force=False):
-
 
279
        """
-
 
280
            Resets the device"
-
 
281
            If <force> is 1, the reset will be forced, otherwise it will be gracefully,
-
 
282
            which may take some time.
-
 
283
        """
-
 
284
        force = self._bool(force)
-
 
285
        if force: self.logger.info("Resetting forcefully...\n")
-
 
286
        else: self.logger.info("Resetting...\n")
-
 
287
        self.embios.reset(force)
-
 
288
    
-
 
289
    @command
-
 
290
    def poweroff(self, force=False):
-
 
291
        """
-
 
292
            Powers the device off
-
 
293
            If <force> is 1, the poweroff will be forced, otherwise it will be gracefully,
-
 
294
            which may take some time.
-
 
295
        """
-
 
296
        force = self._bool(force)
-
 
297
        if force: self.logger.info("Resetting forcefully...\n")
-
 
298
        else: self.logger.info("Resetting...\n")
-
 
299
        self.embios.reset(force)
-
 
300
    
-
 
301
    @command
-
 
302
    def uploadfile(self, addr, filename):
-
 
303
        """
-
 
304
            Uploads a file to the device
-
 
305
            <offset>: the address to upload the file to
-
 
306
            <filename>: the path to the file
-
 
307
        """
-
 
308
        addr = self._hexint(addr)
-
 
309
        try:
-
 
310
            f = open(filename, 'rb')
-
 
311
        except IOError:
-
 
312
            raise ArgumentError("File not readable. Does it exist?")
-
 
313
        self.logger.info("Writing file '"+filename+"' to memory at "+hex(addr)+"...")
-
 
314
        with f:
-
 
315
            self.embios.write(addr, f.read())
-
 
316
        self.logger.info("done\n")
-
 
317
        
-
 
318
        
-
 
319
 
-
 
320
    @command
-
 
321
    def downloadfile(self, addr, size, filename):
-
 
322
        """
-
 
323
            Uploads a file to the device
-
 
324
            <offset>: the address to upload the file to
-
 
325
            <size>: the number of bytes to be read
-
 
326
            <filename>: the path to the file
-
 
327
        """
-
 
328
        addr = self._hexint(addr)
-
 
329
        size = self._hexint(size)
-
 
330
        try:
-
 
331
            f = open(filename, 'wb')
-
 
332
        except IOError:
-
 
333
            raise ArgumentError("Can not open file for write!")
-
 
334
        self.logger.info("Reading data from address "+hex(addr)+" with the size "+hex(size)+" to '"+filename+"'...")
-
 
335
        with f:
-
 
336
            f.write(self.embios.read(addr, size))
-
 
337
        self.logger.info("done\n")
-
 
338
 
-
 
339
    @command
-
 
340
    def uploadint(self, addr, integer):
-
 
341
        """
-
 
342
            Uploads a single integer to the device
-
 
343
            <offset>: the address to upload the integer to
-
 
344
            <data>: the integer to upload
-
 
345
        """
-
 
346
        addr = self._hexint(addr)
-
 
347
        integer = self._hexint(integer)
-
 
348
        if integer > 0xFFFFFFFF:
-
 
349
            raise ArgumentError("Specified integer too long")
-
 
350
        data = chr(integer)
-
 
351
        self.embios.writemem(addr, data)
-
 
352
        self.logger.info("Integer '"+hex(integer)+"' written successfully to "+hex(addr))
-
 
353
 
-
 
354
    @command
-
 
355
    def downloadint(self, addr):
-
 
356
        """
-
 
357
            Downloads a single integer from the device and prints it to the console window
-
 
358
            <offset>: the address to download the integer from
-
 
359
        """
-
 
360
        addr = self._hexint(addr)
-
 
361
        data = self.embios.readmem(addr, 1)
-
 
362
        integer = ord(data)
-
 
363
        self.logger.info("Integer '"+hex(integer)+"' read from address "+hex(addr))
-
 
364
 
-
 
365
    @command
-
 
366
    def i2crecv(self, bus, slave, addr, size):
-
 
367
        """
-
 
368
            Reads data from an I2C device
-
 
369
            <bus> the bus index
-
 
370
            <slave> the slave address
-
 
371
            <addr> the start address on the I2C device
-
 
372
            <size> the number of bytes to read
-
 
373
        """
-
 
374
        bus = self._hexint(bus)
-
 
375
        slave = self._hexint(slave)
-
 
376
        addr = self._hexint(addr)
-
 
377
        size = self._hexint(size)
-
 
378
        raise NotImplementedError
-
 
379
 
-
 
380
    @command
-
 
381
    def i2csend(self, bus, slave, addr, *args):
-
 
382
        """
-
 
383
            Writes data to an I2C device
-
 
384
            <bus> the bus index
-
 
385
            <slave> the slave address
-
 
386
            <addr> the start address on the I2C device
-
 
387
            <db1> ... <dbN> the data in single bytes, seperated by whitespaces,
-
 
388
                eg. 0x37 0x56 0x45 0x12
-
 
389
        """
-
 
390
        bus = self._hexint(bus)
-
 
391
        slave = self._hexint(slave)
-
 
392
        addr = self._hexint(addr)
-
 
393
        data = []
-
 
394
        for arg in args:
-
 
395
            data.append(self._hexint(arg))
-
 
396
        raise NotImplementedError
-
 
397
 
-
 
398
    @command
-
 
399
    def readusbconsole(self, size, outtype):
-
 
400
        """
-
 
401
            Reads data from the USB console.
-
 
402
            <size>: the number of bytes to read
-
 
403
            <outtype>: defines how to output the result:
-
 
404
                'file': writes the result to file <file>
-
 
405
                'printstring': writes the result as string to the console window
-
 
406
                'printhex': writes the result in hexedit notation to the console window
-
 
407
            <file>: the file to write the result to, can be omitted
-
 
408
                if <outtype> is not 'file'
-
 
409
        """
-
 
410
        size = self._hexint(size)
-
 
411
        raise NotImplementedError
-
 
412
        
-
 
413
 
-
 
414
    @command
-
 
415
    def writeusbconsole_file(self, file, offset=0, length=None):
-
 
416
        """
-
 
417
            Writes the file <file> to the USB console.
-
 
418
            Optional params <offset> <length>: specify the range in <file> to write
-
 
419
        """
-
 
420
        # We don't care about file here, this is done when opening it
-
 
421
        offset = self._hexint(offset)
-
 
422
        length = self._hexint(length)
-
 
423
        raise NotImplementedError
-
 
424
 
-
 
425
    @command
-
 
426
    def writeusbconsole_direct(self, *args):
-
 
427
        """
-
 
428
            Writes the strings <db1> ... <dbN> to the USB console."
-
 
429
        """
-
 
430
        raise NotImplementedError
-
 
431
 
-
 
432
    @command
-
 
433
    def readdevconsole(self, bitmask, size, outtype, file=None):
-
 
434
        """
-
 
435
            Reads data from one or more of the device's consoles.
-
 
436
            <bitmask>: the bitmask of the consoles to read from
-
 
437
            <size>: the number of bytes to read
-
 
438
            <outtype>: defines how to output the result:
-
 
439
                'file': writes the result to file <file>
-
 
440
                'printstring': writes the result as string to the console window
-
 
441
                'printhex': writes the result in hexedit notation to the console window
-
 
442
            <file>: the file to write the result to, can be omitted
-
 
443
                if <outtype> is not 'file'
-
 
444
        """
-
 
445
        bitmask = self._hexint(bitmask)
-
 
446
        size = self._hexint(size)
-
 
447
        outtype = self._strcheck(['file', 'printstring', 'printhex'])
-
 
448
        raise NotImplementedError
-
 
449
 
-
 
450
    @command
-
 
451
    def writedevconsole_file(self, bitmask, file, offset=0, length=None):
-
 
452
        """
-
 
453
            Writes the file <file> to the device consoles specified by <bitmask>
-
 
454
            Optional params <offset> <length>: specify the range in <file> to write
-
 
455
        """
-
 
456
        bitmask = self._hexint(bitmask)
-
 
457
        # We don't care about file here, this is done when opening it
-
 
458
        offset = self._hexint(offset)
-
 
459
        length = self._hexint(length)
-
 
460
        raise NotImplementedError
-
 
461
 
-
 
462
    @command
-
 
463
    def writedevconsole_direct(self, bitmask, *args):
-
 
464
        """
-
 
465
            Writes the integers <db1> ... <dbN> to the device consoles specified
-
 
466
            by <bitmask>
-
 
467
        """
-
 
468
        bitmask = self._hexint(bitmask)
-
 
469
        data = []
-
 
470
        for arg in args:
-
 
471
            data.append(self._hexint(arg))
-
 
472
        raise NotImplementedError
-
 
473
 
-
 
474
    @command
-
 
475
    def flushconsolebuffers(self, bitmask):
-
 
476
        """
-
 
477
            flushes one or more of the device consoles' buffers.
-
 
478
            <bitmask>: the bitmask of the consoles to be flushed
-
 
479
        """
-
 
480
        bitmask = self._hexint(bitmask)
-
 
481
        raise NotImplementedError
-
 
482
 
-
 
483
    @command
-
 
484
    def getprocinfo(self):
-
 
485
        """
-
 
486
            Fetches data on the currently running processes
-
 
487
            ATTENTION: this function will be print the information to the console window.
-
 
488
                If several threads are running this might overflow the window,
-
 
489
                causing not everything to be shown.
-
 
490
        """
-
 
491
        raise NotImplementedError
-
 
492
 
-
 
493
    @command
-
 
494
    def lockscheduler(self):
-
 
495
        """
-
 
496
            Locks (freezes) the scheduler
-
 
497
        """
-
 
498
        raise NotImplementedError
-
 
499
 
-
 
500
    @command
-
 
501
    def unlockscheduler(self):
-
 
502
        """
-
 
503
            Unlocks (unfreezes) the scheduler
-
 
504
        """
-
 
505
        raise NotImplementedError
-
 
506
 
-
 
507
    @command
-
 
508
    def suspendthread(self, threadid):
-
 
509
        """
-
 
510
            Suspends/resumes the thread with thread ID <threadid>
-
 
511
        """
-
 
512
        threadid = self._hexint(threadid)
-
 
513
        raise NotImplementedError
-
 
514
 
-
 
515
    @command
-
 
516
    def resumethread(self, threadid):
-
 
517
        """
-
 
518
            Resumes the thread with thread ID <threadid>
-
 
519
        """
-
 
520
        threadid = self._hexint(threadid)
-
 
521
        raise NotImplementedError
-
 
522
 
-
 
523
    @command
-
 
524
    def killthread(self, threadid):
-
 
525
        """
-
 
526
            Kills the thread with thread ID <threadid>
-
 
527
        """
-
 
528
        threadid = self._hexint(threadid)
-
 
529
        raise NotImplementedError
-
 
530
 
-
 
531
    @command
-
 
532
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
-
 
533
        """
-
 
534
            Creates a new thread and returns its thread ID
-
 
535
            <namepointer> a pointer to the thread's name
-
 
536
            <entrypoint> a pointer to the entrypoint of the thread
-
 
537
            <stackpointer> a pointer to the stack of the thread
-
 
538
            <stacksize> the size of the thread's stack
-
 
539
            <type> the thread type, vaild are: 0 => user thread, 1 => system thread
-
 
540
            <priority> the priority of the thread, from 1 to 255
-
 
541
            <state> the thread's initial state, valid are: 1 => ready, 0 => suspended
-
 
542
        """
-
 
543
        nameptr = self._hexint(nameptr)
-
 
544
        entrypoint = self._hexint(entrypoint)
-
 
545
        stackpointer = self._hexint(stackpointer)
-
 
546
        stacksize = self._hexint(stacksize)
-
 
547
        priority = self._hexint(priority)
-
 
548
        self.embios.createthread(nameptr, entrypoint, stackptr, stacksize, type, priority, state)
-
 
549
 
-
 
550
    @command
-
 
551
    def run(self, address):
-
 
552
        """
-
 
553
            Executes the emBIOS application at <address>.
-
 
554
        """
-
 
555
        address = self._hexint(address)
-
 
556
        raise NotImplementedError
-
 
557
 
-
 
558
    @command
-
 
559
    def readrawbootflash(self, addr_flash, addr_mem, size):
-
 
560
        """
-
 
561
            Reads <size> bytes from bootflash to memory.
-
 
562
            <addr_bootflsh>: the address in bootflash to read from
-
 
563
            <addr_mem>: the address in memory to copy the data to
-
 
564
        """
-
 
565
        addr_flash = self._hexint(addr_flash)
-
 
566
        addr_mem = self._hexint(addr_mem)
-
 
567
        size = self._hexint(size)
-
 
568
        raise NotImplementedError
-
 
569
 
-
 
570
    @command
-
 
571
    def writerawbootflash(self, addr_flash, addr_mem, size):
-
 
572
        """
-
 
573
            Writes <size> bytes from memory to bootflash.
-
 
574
            ATTENTION: Don't call this unless you really know what you're doing!
-
 
575
            This may BRICK your device (unless it has a good recovery option)
-
 
576
            <addr_mem>: the address in memory to copy the data from
-
 
577
            <addr_bootflsh>: the address in bootflash to write to
-
 
578
        """
-
 
579
        addr_flash = self._hexint(addr_flash)
-
 
580
        addr_mem = self._hexint(addr_mem)
-
 
581
        size = self._hexint(size)
-
 
582
        raise NotImplementedError
-
 
583
 
-
 
584
    @command
-
 
585
    def flushcaches(self):
-
 
586
        """
-
 
587
            Flushes the CPUs data and instruction caches.
-
 
588
        """
-
 
589
        raise NotImplementedError
-
 
590
    
-
 
591
    @command
-
 
592
    def aesencrypt(self, addr, size, keyindex):
-
 
593
        """
-
 
594
            Encrypt a buffer using a hardware key
-
 
595
        """
-
 
596
        addr = self._hexint(addr)
-
 
597
        size = self._hexint(size)
-
 
598
        keyindex = self._hexint(keyindex)
-
 
599
        self.embios.aesencrypt(addr, size, keyindex)
-
 
600
    
-
 
601
    @command
-
 
602
    def aesdecrypt(self, addr, size, keyindex):
-
 
603
        """
-
 
604
            Decrypt a buffer using a hardware key
-
 
605
        """
-
 
606
        addr = self._hexint(addr)
-
 
607
        size = self._hexint(size)
-
 
608
        keyindex = self._hexint(keyindex)
-
 
609
        self.embios.aesdecrypt(addr, size, keyindex)
396
 
610
 
-
 
611
if __name__ == "__main__":
397
dev = libembios.embios()
612
    if len(sys.argv) < 2:
-
 
613
        usage("No command specified")
-
 
614
    interface = Commandline()
398
parsecommand(dev, sys.argv)
615
    interface._parsecommand(sys.argv[1], sys.argv[2:])
399
616