Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
82 benedikt93 1
#!/usr/bin/env python
64 benedikt93 2
#
3
#
171 farthen 4
#    Copyright 2010 TheSeven, benedikt93, Farthen
64 benedikt93 5
#
6
#
82 benedikt93 7
#    This file is part of emBIOS.
64 benedikt93 8
#
82 benedikt93 9
#    emBIOS is free software: you can redistribute it and/or
64 benedikt93 10
#    modify it under the terms of the GNU General Public License as
11
#    published by the Free Software Foundation, either version 2 of the
12
#    License, or (at your option) any later version.
13
#
82 benedikt93 14
#    emBIOS is distributed in the hope that it will be useful,
64 benedikt93 15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
#    See the GNU General Public License for more details.
18
#
82 benedikt93 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/>.
64 benedikt93 21
#
22
#
23
 
171 farthen 24
import sys
25
import os
26
import inspect
27
import re
176 farthen 28
import time
64 benedikt93 29
 
176 farthen 30
from functools import wraps
31
 
64 benedikt93 32
import libembios
171 farthen 33
from libembios import Error
34
import libembiosdata
64 benedikt93 35
 
171 farthen 36
class NotImplementedError(Error):
37
    pass
64 benedikt93 38
 
171 farthen 39
class ArgumentError(Error):
40
    pass
64 benedikt93 41
 
171 farthen 42
class ArgumentTypeError(Error):
43
    def __init__(self, expected, seen=False):
44
        self.expected = expected
45
        self.seen = seen
46
    def __str__(self):
47
        if self.seen:
48
            return "Expected " + str(self.expected) + " but saw " + str(self.seen)
49
        else:
50
            return "Expected " + str(self.expected) + ", but saw something else"
64 benedikt93 51
 
52
 
171 farthen 53
def usage(errormsg=None, specific=False):
54
    """
55
        Prints the usage information.
56
        It is auto generated from various places.
57
    """
58
    logger = Logger()
59
    cmddict= Commandline.cmddict
60
    doc = {}
61
    # This sorts the output of various internal functions
62
    # and puts everything in easy readable form
63
    for function in cmddict:
64
        function = cmddict[function].func
65
        docinfo = {}
66
        name = function.__name__
67
        args = inspect.getargspec(function)[0]
68
        docinfo['varargs'] = False
69
        if inspect.getargspec(function)[1]:
70
            docinfo['varargs'] = True
71
        kwargvalues = inspect.getargspec(function)[3]
72
        kwargs = {}
73
        if args:
74
            if kwargvalues:
75
                argnum = len(args) - len(kwargvalues)
76
                kwargnum = len(kwargvalues)
77
                kwargs = dict(zip(args[argnum:], kwargvalues))
78
            else:
79
                argnum = len(args)
80
        else:
81
            argnum = 0
82
        docinfo['args'] = args[1:argnum]
83
        docinfo['kwargs'] = kwargs
84
        if function.__doc__:
85
            # strip unneccessary whitespace
86
            docinfo['documentation'] = re.sub(r'\n        ', '\n', function.__doc__)
87
        else:
88
            docinfo['documentation'] = None
89
        doc[name] = docinfo
64 benedikt93 90
 
171 farthen 91
    if not specific:
92
        logger.log("Please provide a command and (if needed) parameters as command line arguments\n\n")
93
        logger.log("Available commands:\n\n")
82 benedikt93 94
    else:
171 farthen 95
        logger.log("\n")
96
    for function in sorted(doc.items()):
97
        function = function[0]
98
        if specific == False or specific == function:
99
            logger.log("  " + function + " ")
100
            for arg in doc[function]['args']:
101
                logger.log("<" + arg + "> ")
102
            if doc[function]['kwargs']:
103
                for kwarg in doc[function]['kwargs']:
104
                    logger.log("[" + kwarg + "] ")
105
            if doc[function]['varargs']:
106
                logger.log("<db1> ... <dbN>")
107
            if doc[function]['documentation']:
108
                logger.log(doc[function]['documentation']+"\n")
64 benedikt93 109
 
171 farthen 110
    logger.log("\n")
111
 
112
    if errormsg:
113
        logger.error(str(errormsg)+"\n")
114
    exit(2)
115
 
116
 
117
class Logger(object):
118
    """
119
        Simple stdout logger.
120
        Loglevel 4 is most verbose, Loglevel 0 only say something if there is an error.
121
    """
122
    def __init__(self):
123
        # Possible values: 0 (only errors), 1 (warnings), 2 (info, recommended for production use), 3 and more (debug)
124
        self.loglevel = 3
125
 
126
    def log(self, text):
127
        sys.stdout.write(text)
67 benedikt93 128
 
171 farthen 129
    def debug(self, text):
130
        if self.loglevel >= 3:
131
            self.log(text)
119 benedikt93 132
 
171 farthen 133
    def info(self, text):
134
        if self.loglevel >= 2:
135
            self.log(text)
82 benedikt93 136
 
171 farthen 137
    def warning(self, text):
138
        if self.loglevel >= 1:
139
            self.log("WARNING: " + text)
119 benedikt93 140
 
171 farthen 141
    def error(self, text):
142
        self.log("ERROR: " + text)
143
 
144
 
145
def command(func):
146
    """
147
        Decorator for all commands.
148
        The decorated function is called with (self, all, other, arguments, ...)
149
    """
176 farthen 150
    @wraps(func)
172 farthen 151
    def decorator(*args):
171 farthen 152
        return func(args[0], *args[1:])
153
    func._command = True
154
    decorator.func = func
155
    return decorator
156
 
157
 
158
def commandClass(cls):
159
    """
160
        Decorator for the class. Sets the self.cmddict of the class
161
        to all functions decorated with @command
162
    """
163
    cls.cmddict = {}
164
    for attr, value in cls.__dict__.iteritems():
165
        if getattr(value, 'func', False):
166
            if getattr(value.func, '_command', False):
167
                cls.cmddict[value.func.__name__] = value
168
    return cls
169
 
170
 
171
@commandClass
172
class Commandline(object):
173
    """
174
        If you want to create a new commandline function you just need to
175
        create a function with the name of it in this class and decorate
176
        it with the decorator @command. If you don't want to call the desired
177
        function (wrong arguments etc) just raise ArgumentError with or
178
        without an error message or raise ArgumentCountError
179
    """
180
    def __init__(self):
181
        self.logger = Logger()
182
        try:
183
            self.embios = libembios.Embios()
184
        except libembios.DeviceNotFoundError:
185
            self.logger.error("No emBIOS device found!")
176 farthen 186
            exit(1)
187
        self.getinfo("version")
171 farthen 188
 
189
    def _parsecommand(self, func, args):
190
        # adds self to the commandline args.
191
        # this is needed because the functions need access to their class.
192
        args.insert(0, self)
193
        if func in self.cmddict:
194
            try:
172 farthen 195
                self.cmddict[func](*args)
171 farthen 196
            except ArgumentError, e:
176 farthen 197
                usage(e, specific=func)
171 farthen 198
            except ArgumentError:
176 farthen 199
                usage("Syntax Error in function '" + func + "'", specific=func)
171 farthen 200
            except ArgumentTypeError, e:
176 farthen 201
                usage(e, specific=func)
171 farthen 202
            except NotImplementedError:
203
                self.logger.error("This function is not implemented yet!")
204
            except libembios.DeviceError, e:
205
                self.logger.error(str(e))
176 farthen 206
            except ValueError:
207
                usage(specific=func)
171 farthen 208
            except TypeError, e:
209
                if str(e).split(" ", 1)[0] == func + "()":
210
                    self.logger.error(usage("Argument Error in '" + func + "': Wrong argument count", specific=func))
211
                else:
212
                    raise
176 farthen 213
            except libembios.usb.core.USBError:
214
                self.logger.error("Problem with USB connection.")
171 farthen 215
        else:
216
            usage("No such command")
67 benedikt93 217
 
171 farthen 218
    @staticmethod
219
    def _bool(something):
220
        """
221
            Converts quite everything into bool.
222
        """
223
        if type(something) == bool:
224
            return something
225
        elif type(something) == int or type(something) == long:
226
            return bool(something)
227
        elif type(something == str):
228
            truelist = ['true', '1', 't', 'y', 'yes']
229
            falselist = ['false', '0', 'f', 'n', 'no']
230
            if something.lower() in truelist:
231
                return True
232
            elif something.lower() in falselist:
233
                return False
234
        raise ArgumentTypeError("bool", "'"+str(something)+"'")
235
 
236
    @staticmethod
237
    def _hexint(something):
238
        """
239
            Converts quite everything to a hexadecimal represented integer.
240
            This works for default arguments too, because it returns
241
            None when it found that it got a NoneType object.
242
        """
243
        if type(something) == int or type(something) == long:
244
            return something
245
        elif type(something) == str:
246
            try:
247
                return int(something, 16)
248
            except ValueError:
249
                raise ArgumentTypeError("hexadecimal coded integer", "'"+str(something)+"'")
250
        elif type(something) == NoneType:
251
            return None
252
        else:
253
            raise ArgumentTypeError("hexadecimal coded integer", "'"+str(something)+"'")
254
 
255
    @staticmethod
256
    def _strcheck(string, values):
257
        if string in values:
258
            return string
259
        else:
260
            expected = ""
261
            for item in values:
262
                expected += "'" + item + "', "
263
            expected = expected[:-2]
264
            raise ArgumentTypeError("one out of " + expected, "'" + string + "'")
64 benedikt93 265
 
173 farthen 266
    @staticmethod
267
    def _hex(integer):
268
        return "0x%x" % integer
64 benedikt93 269
 
171 farthen 270
    @command
271
    def getinfo(self, infotype):
272
        """
273
            Get info on the running emBIOS.
274
            <infotype> may be either of 'version', 'packetsize', 'usermemrange'.
275
        """
276
        if infotype == "version":
277
            resp = self.embios.getversioninfo()
172 farthen 278
            self.logger.info("Connected to "+libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) +
171 farthen 279
                             "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
280
        elif infotype == "packetsize":
281
            resp = self.embios.getpacketsizeinfo()
282
            self.logger.info("Maximum packet sizes: "+str(resp))
283
        elif infotype == "usermemrange":
284
            resp = self.embios.getusermemrange()
173 farthen 285
            self.logger.info("The user memory range is "+self._hex(resp.lower)+" - "+self._hex(resp.upper-1))
171 farthen 286
        else:
287
            raise ArgumentTypeError("one out of 'version', 'packetsize', 'usermemrange'", infotype)
64 benedikt93 288
 
171 farthen 289
    @command
290
    def reset(self, force=False):
291
        """
292
            Resets the device"
293
            If <force> is 1, the reset 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)
64 benedikt93 300
 
171 farthen 301
    @command
302
    def poweroff(self, force=False):
303
        """
304
            Powers the device off
305
            If <force> is 1, the poweroff will be forced, otherwise it will be gracefully,
306
            which may take some time.
307
        """
308
        force = self._bool(force)
309
        if force: self.logger.info("Resetting forcefully...\n")
310
        else: self.logger.info("Resetting...\n")
311
        self.embios.reset(force)
64 benedikt93 312
 
171 farthen 313
    @command
314
    def uploadfile(self, addr, filename):
315
        """
316
            Uploads a file to the device
317
            <offset>: the address to upload the file to
318
            <filename>: the path to the file
319
        """
320
        addr = self._hexint(addr)
321
        try:
322
            f = open(filename, 'rb')
323
        except IOError:
324
            raise ArgumentError("File not readable. Does it exist?")
173 farthen 325
        self.logger.info("Writing file '"+filename+"' to memory at "+self._hex(addr)+"...")
171 farthen 326
        with f:
327
            self.embios.write(addr, f.read())
178 farthen 328
        f.close()
171 farthen 329
        self.logger.info("done\n")
176 farthen 330
 
171 farthen 331
    @command
332
    def downloadfile(self, addr, size, filename):
333
        """
334
            Uploads a file to the device
335
            <offset>: the address to upload the file to
336
            <size>: the number of bytes to be read
337
            <filename>: the path to the file
338
        """
339
        addr = self._hexint(addr)
340
        size = self._hexint(size)
341
        try:
342
            f = open(filename, 'wb')
343
        except IOError:
344
            raise ArgumentError("Can not open file for write!")
173 farthen 345
        self.logger.info("Reading data from address "+self._hex(addr)+" with the size "+self._hex(size)+" to '"+filename+"'...")
171 farthen 346
        with f:
347
            f.write(self.embios.read(addr, size))
178 farthen 348
        f.close()
171 farthen 349
        self.logger.info("done\n")
350
 
351
    @command
352
    def uploadint(self, addr, integer):
353
        """
354
            Uploads a single integer to the device
355
            <offset>: the address to upload the integer to
356
            <data>: the integer to upload
357
        """
358
        addr = self._hexint(addr)
359
        integer = self._hexint(integer)
360
        if integer > 0xFFFFFFFF:
361
            raise ArgumentError("Specified integer too long")
362
        data = chr(integer)
178 farthen 363
        self.embios.write(addr, data)
173 farthen 364
        self.logger.info("Integer '"+self._hex(integer)+"' written successfully to "+self._hex(addr))
171 farthen 365
 
366
    @command
367
    def downloadint(self, addr):
368
        """
369
            Downloads a single integer from the device and prints it to the console window
370
            <offset>: the address to download the integer from
371
        """
372
        addr = self._hexint(addr)
178 farthen 373
        data = self.embios.read(addr, 1)
171 farthen 374
        integer = ord(data)
173 farthen 375
        self.logger.info("Integer '"+self._hex(integer)+"' read from address "+self._hex(addr))
171 farthen 376
 
377
    @command
176 farthen 378
    def i2cread(self, bus, slave, addr, size):
171 farthen 379
        """
380
            Reads data from an I2C device
381
            <bus> the bus index
382
            <slave> the slave address
383
            <addr> the start address on the I2C device
384
            <size> the number of bytes to read
385
        """
386
        bus = self._hexint(bus)
387
        slave = self._hexint(slave)
388
        addr = self._hexint(addr)
389
        size = self._hexint(size)
176 farthen 390
        self.embios.i2cread(bus, slave, addr, size)
171 farthen 391
 
392
    @command
176 farthen 393
    def i2cwrite(self, bus, slave, addr, *args):
171 farthen 394
        """
395
            Writes data to an I2C device
396
            <bus> the bus index
397
            <slave> the slave address
398
            <addr> the start address on the I2C device
176 farthen 399
            <db1> ... <dbN> the data in single bytes, encoded in hex,
400
                seperated by whitespaces, eg. 37 56 45 12
171 farthen 401
        """
402
        bus = self._hexint(bus)
403
        slave = self._hexint(slave)
404
        addr = self._hexint(addr)
176 farthen 405
        data = ""
171 farthen 406
        for arg in args:
176 farthen 407
            data += chr(self._hexint(arg))
408
        self.embios.i2cwrite(bus, slave, addr, data)
171 farthen 409
 
410
    @command
176 farthen 411
    def console(self):
171 farthen 412
        """
176 farthen 413
            Reads data from the USB console continuously
171 farthen 414
        """
176 farthen 415
        while True:
416
            resp = self.embios.usbcread()
417
            self.logger.log(resp.data)
418
            time.sleep(0.1 / resp.maxsize * (resp.maxsize - len(resp.data)))
171 farthen 419
 
420
    @command
176 farthen 421
    def writeusbconsole(self, *args):
171 farthen 422
        """
176 farthen 423
            Writes the string <db1> ... <dbN> to the USB console.
171 farthen 424
        """
176 farthen 425
        text = ""
426
        for word in args:
427
            text += word + " "
428
        text = text[:-1]
429
        self.logger.info("Writing '"+text+"' to the usb console\n")
430
        self.embios.usbcwrite(text)
171 farthen 431
 
432
    @command
176 farthen 433
    def readdevconsole(self, bitmask):
171 farthen 434
        """
176 farthen 435
            Reads data continuously from one or more of the device's consoles.
436
            <bitmask>: the bitmask of the consoles to read from.
171 farthen 437
        """
438
        bitmask = self._hexint(bitmask)
176 farthen 439
        while True:
440
            resp = self.embios.cread()
441
            self.logger.log(resp.data)
442
            time.sleep(0.1 / resp.maxsize * (resp.maxsize - len(resp.data)))
443
 
171 farthen 444
    @command
176 farthen 445
    def writedevconsole(self, bitmask, *args):
171 farthen 446
        """
176 farthen 447
            Writes the string <db1> ... <dbN> to one or more of the device's consoles.
448
            <bitmask>: the bitmask of the consoles to write to
171 farthen 449
        """
450
        bitmask = self._hexint(bitmask)
176 farthen 451
        text = ""
452
        for word in args:
453
            text += word + " "
454
        text = text[:-1]
455
        self.logger.info("Writing '"+text+"' to the device consoles identified with "+self._hex(bitmask)+"\n")
456
        self.embios.cwrite(text, bitmask)
171 farthen 457
 
458
    @command
459
    def flushconsolebuffers(self, bitmask):
460
        """
461
            flushes one or more of the device consoles' buffers.
462
            <bitmask>: the bitmask of the consoles to be flushed
463
        """
464
        bitmask = self._hexint(bitmask)
465
        raise NotImplementedError
466
 
467
    @command
468
    def getprocinfo(self):
469
        """
470
            Fetches data on the currently running processes
471
        """
173 farthen 472
        import datetime
473
        threads = self.embios.getprocinfo()
474
        self.logger.info("The device has "+str(len(threads))+" running threads:\n\n")
475
        for thread in threads:
476
            self.logger.info("  "+thread.name+":\n")
477
            self.logger.info("    Thread id: "+str(thread.id)+"\n")
478
            self.logger.info("    Thread type: "+thread.type+"\n")
479
            self.logger.info("    Thread state: "+thread.state+"\n")
480
            self.logger.info("    Priority: "+str(thread.priority)+"/256\n")
481
            self.logger.info("    CPU time (total): "+str(datetime.timedelta(microseconds=thread.cputime_total))+"\n")
482
            self.logger.info("    Stack address: "+self._hex(thread.stackaddr)+"\n")
483
            self.logger.info("    Registers:\n")
177 farthen 484
            for registerrange in range(4):
485
                self.logger.info("      ")
486
                for register in range(registerrange, 16, 4):
487
                    registerrepr = "r"+str(register)
488
                    self.logger.info("{:3s}: 0x{:08X}    ".format(registerrepr, thread.regs["r"+str(register)]))
489
                self.logger.info("\n")
490
            self.logger.info("      cpsr: 0x{:08X}".format(thread.regs.cpsr))
173 farthen 491
            self.logger.info("\n")
492
 
171 farthen 493
    @command
494
    def lockscheduler(self):
495
        """
496
            Locks (freezes) the scheduler
497
        """
176 farthen 498
        self.logger.info("Will now lock scheduler\n")
173 farthen 499
        self.embios.lockscheduler()
178 farthen 500
 
171 farthen 501
    @command
502
    def unlockscheduler(self):
503
        """
504
            Unlocks (unfreezes) the scheduler
505
        """
176 farthen 506
        self.logger.info("Will now unlock scheduler\n")
173 farthen 507
        self.embios.unlockscheduler()
178 farthen 508
 
171 farthen 509
    @command
510
    def suspendthread(self, threadid):
511
        """
512
            Suspends/resumes the thread with thread ID <threadid>
513
        """
514
        threadid = self._hexint(threadid)
173 farthen 515
        self.embios.resumethread(threadid)
171 farthen 516
 
517
    @command
518
    def resumethread(self, threadid):
519
        """
520
            Resumes the thread with thread ID <threadid>
521
        """
522
        threadid = self._hexint(threadid)
173 farthen 523
        self.embios.resumethread(threadid)
171 farthen 524
 
525
    @command
526
    def killthread(self, threadid):
527
        """
528
            Kills the thread with thread ID <threadid>
529
        """
530
        threadid = self._hexint(threadid)
173 farthen 531
        self.embios.killthread(threadid)
171 farthen 532
 
533
    @command
534
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
535
        """
536
            Creates a new thread and returns its thread ID
537
            <namepointer> a pointer to the thread's name
538
            <entrypoint> a pointer to the entrypoint of the thread
539
            <stackpointer> a pointer to the stack of the thread
540
            <stacksize> the size of the thread's stack
541
            <type> the thread type, vaild are: 0 => user thread, 1 => system thread
542
            <priority> the priority of the thread, from 1 to 255
543
            <state> the thread's initial state, valid are: 1 => ready, 0 => suspended
544
        """
545
        nameptr = self._hexint(nameptr)
546
        entrypoint = self._hexint(entrypoint)
547
        stackpointer = self._hexint(stackpointer)
548
        stacksize = self._hexint(stacksize)
549
        priority = self._hexint(priority)
550
        self.embios.createthread(nameptr, entrypoint, stackptr, stacksize, type, priority, state)
172 farthen 551
 
552
    @command
553
    def run(self, filename):
554
        """
173 farthen 555
            Uploads the emBIOS application <filename> to
556
            the beginning of the user memory and executes it
172 farthen 557
        """
176 farthen 558
        #self.execimage(addr)
559
        raise NotImplementedError
171 farthen 560
 
561
    @command
173 farthen 562
    def execimage(self, addr):
171 farthen 563
        """
173 farthen 564
            Executes the emBIOS application at <addr>.
171 farthen 565
        """
172 farthen 566
        addr = self._hexint(addr)
173 farthen 567
        self.logger.info("Starting emBIOS app at "+self._hex(addr)+"\n")
172 farthen 568
        self.embios.execimage(addr)
176 farthen 569
 
171 farthen 570
    @command
176 farthen 571
    def flushcaches(self):
171 farthen 572
        """
176 farthen 573
            Flushes the CPUs data and instruction caches.
574
        """
575
        self.logger.info("Flushing CPU data and instruction caches...")
576
        self.embios.flushcaches()
577
        self.logger.info("done\n")
578
 
579
    @command
580
    def readbootflash(self, addr_flash, addr_mem, size):
581
        """
171 farthen 582
            Reads <size> bytes from bootflash to memory.
583
            <addr_bootflsh>: the address in bootflash to read from
584
            <addr_mem>: the address in memory to copy the data to
585
        """
586
        addr_flash = self._hexint(addr_flash)
587
        addr_mem = self._hexint(addr_mem)
588
        size = self._hexint(size)
174 farthen 589
        self.logger.info("Dumping boot flash addresses "+self._hex(addr_flash)+" - "+
590
                         hex(addr_flash+size)+" to "+self._hex(addr_mem)+" - "+self._hex(addr_mem+size)+"\n")
591
        self.embios.bootflashread(addr_flash, addr_mem, size)
176 farthen 592
 
171 farthen 593
    @command
176 farthen 594
    def writebootflash(self, addr_flash, addr_mem, size, force=False):
171 farthen 595
        """
596
            Writes <size> bytes from memory to bootflash.
597
            ATTENTION: Don't call this unless you really know what you're doing!
598
            This may BRICK your device (unless it has a good recovery option)
599
            <addr_mem>: the address in memory to copy the data from
600
            <addr_bootflsh>: the address in bootflash to write to
174 farthen 601
            <force>: Use this flag to suppress the 5 seconds delay
171 farthen 602
        """
603
        addr_flash = self._hexint(addr_flash)
604
        addr_mem = self._hexint(addr_mem)
605
        size = self._hexint(size)
174 farthen 606
        force = self._bool(force)
607
        self.logger.info("Writing boot flash from the memory in "+self._hex(addr_mem)+" - "+
608
                         hex(addr_mem+size)+" to "+self._hex(addr_flash)+" - "+self._hex(addr_flash+size)+"\n")
609
        if force == False:
610
            self.logger.info("If this was not what you intended press Ctrl-C NOW")
176 farthen 611
            for i in range(10):
174 farthen 612
                self.logger.info(".")
613
                time.sleep(1)
614
            self.logger.info("\n")
615
        self.embios.bootflashwrite(addr_flash, addr_mem, size)
176 farthen 616
 
171 farthen 617
    @command
176 farthen 618
    def runfirmware(self, addr, filename):
171 farthen 619
        """
176 farthen 620
            Uploads the firmware in 'filename' to the beginning of the
621
            user memory and executes it
171 farthen 622
        """
176 farthen 623
        addr = self._hexint(addr)
624
        self.uploadfile(addr, filename)
625
        self.execfirmware(addr)
64 benedikt93 626
 
171 farthen 627
    @command
176 farthen 628
    def execfirmware(self, addr):
629
        """
630
            Executes the firmware at addr
631
        """
632
        addr = self._hexint(addr)
633
        self.logger.info("Running firmware at "+self._hex(addr)+". Bye.")
634
        self.embios.execfirmware(addr)
635
 
636
    @command
171 farthen 637
    def aesencrypt(self, addr, size, keyindex):
638
        """
172 farthen 639
            Encrypts a buffer using a hardware key
171 farthen 640
        """
641
        addr = self._hexint(addr)
642
        size = self._hexint(size)
643
        keyindex = self._hexint(keyindex)
644
        self.embios.aesencrypt(addr, size, keyindex)
82 benedikt93 645
 
171 farthen 646
    @command
647
    def aesdecrypt(self, addr, size, keyindex):
648
        """
172 farthen 649
            Decrypts a buffer using a hardware key
171 farthen 650
        """
651
        addr = self._hexint(addr)
652
        size = self._hexint(size)
653
        keyindex = self._hexint(keyindex)
654
        self.embios.aesdecrypt(addr, size, keyindex)
172 farthen 655
 
656
    @command
657
    def hmac_sha1(self, addr, size, destination):
658
        """
659
            Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination'
660
        """
661
        addr = self._hexint(addr)
662
        size = self._hexint(size)
663
        destination = self._hexint(destination)
664
        sha1size = 0x14
173 farthen 665
        self.logger.info("Generating hmac-sha1 hash from the buffer at "+self._hex(addr)+" with the size "+self._hex(size)+
666
                         " and saving it to "+self._hex(destination)+" - "+self._hex(destination+sha1size)+"...")
172 farthen 667
        self.embios.hmac_sha1(addr, size, destination)
668
        self.logger.info("done\n")
178 farthen 669
        data = self.embios.read(destination, sha1size)
172 farthen 670
        hash = ord(data)
173 farthen 671
        self.logger.info("The generated hash is "+self._hex(hash))
64 benedikt93 672
 
171 farthen 673
if __name__ == "__main__":
674
    if len(sys.argv) < 2:
675
        usage("No command specified")
676
    interface = Commandline()
677
    interface._parsecommand(sys.argv[1], sys.argv[2:])