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())
328
        self.logger.info("done\n")
176 farthen 329
 
171 farthen 330
    @command
331
    def downloadfile(self, addr, size, filename):
332
        """
333
            Uploads a file to the device
334
            <offset>: the address to upload the file to
335
            <size>: the number of bytes to be read
336
            <filename>: the path to the file
337
        """
338
        addr = self._hexint(addr)
339
        size = self._hexint(size)
340
        try:
341
            f = open(filename, 'wb')
342
        except IOError:
343
            raise ArgumentError("Can not open file for write!")
173 farthen 344
        self.logger.info("Reading data from address "+self._hex(addr)+" with the size "+self._hex(size)+" to '"+filename+"'...")
171 farthen 345
        with f:
346
            f.write(self.embios.read(addr, size))
347
        self.logger.info("done\n")
348
 
349
    @command
350
    def uploadint(self, addr, integer):
351
        """
352
            Uploads a single integer to the device
353
            <offset>: the address to upload the integer to
354
            <data>: the integer to upload
355
        """
356
        addr = self._hexint(addr)
357
        integer = self._hexint(integer)
358
        if integer > 0xFFFFFFFF:
359
            raise ArgumentError("Specified integer too long")
360
        data = chr(integer)
361
        self.embios.writemem(addr, data)
173 farthen 362
        self.logger.info("Integer '"+self._hex(integer)+"' written successfully to "+self._hex(addr))
171 farthen 363
 
364
    @command
365
    def downloadint(self, addr):
366
        """
367
            Downloads a single integer from the device and prints it to the console window
368
            <offset>: the address to download the integer from
369
        """
370
        addr = self._hexint(addr)
371
        data = self.embios.readmem(addr, 1)
372
        integer = ord(data)
173 farthen 373
        self.logger.info("Integer '"+self._hex(integer)+"' read from address "+self._hex(addr))
171 farthen 374
 
375
    @command
176 farthen 376
    def i2cread(self, bus, slave, addr, size):
171 farthen 377
        """
378
            Reads data from an I2C device
379
            <bus> the bus index
380
            <slave> the slave address
381
            <addr> the start address on the I2C device
382
            <size> the number of bytes to read
383
        """
384
        bus = self._hexint(bus)
385
        slave = self._hexint(slave)
386
        addr = self._hexint(addr)
387
        size = self._hexint(size)
176 farthen 388
        self.embios.i2cread(bus, slave, addr, size)
171 farthen 389
 
390
    @command
176 farthen 391
    def i2cwrite(self, bus, slave, addr, *args):
171 farthen 392
        """
393
            Writes data to an I2C device
394
            <bus> the bus index
395
            <slave> the slave address
396
            <addr> the start address on the I2C device
176 farthen 397
            <db1> ... <dbN> the data in single bytes, encoded in hex,
398
                seperated by whitespaces, eg. 37 56 45 12
171 farthen 399
        """
400
        bus = self._hexint(bus)
401
        slave = self._hexint(slave)
402
        addr = self._hexint(addr)
176 farthen 403
        data = ""
171 farthen 404
        for arg in args:
176 farthen 405
            data += chr(self._hexint(arg))
406
        self.embios.i2cwrite(bus, slave, addr, data)
171 farthen 407
 
408
    @command
176 farthen 409
    def console(self):
171 farthen 410
        """
176 farthen 411
            Reads data from the USB console continuously
171 farthen 412
        """
176 farthen 413
        while True:
414
            resp = self.embios.usbcread()
415
            self.logger.log(resp.data)
416
            time.sleep(0.1 / resp.maxsize * (resp.maxsize - len(resp.data)))
171 farthen 417
 
418
    @command
176 farthen 419
    def writeusbconsole(self, *args):
171 farthen 420
        """
176 farthen 421
            Writes the string <db1> ... <dbN> to the USB console.
171 farthen 422
        """
176 farthen 423
        text = ""
424
        for word in args:
425
            text += word + " "
426
        text = text[:-1]
427
        self.logger.info("Writing '"+text+"' to the usb console\n")
428
        self.embios.usbcwrite(text)
171 farthen 429
 
430
    @command
176 farthen 431
    def readdevconsole(self, bitmask):
171 farthen 432
        """
176 farthen 433
            Reads data continuously from one or more of the device's consoles.
434
            <bitmask>: the bitmask of the consoles to read from.
171 farthen 435
        """
436
        bitmask = self._hexint(bitmask)
176 farthen 437
        while True:
438
            resp = self.embios.cread()
439
            self.logger.log(resp.data)
440
            time.sleep(0.1 / resp.maxsize * (resp.maxsize - len(resp.data)))
441
 
171 farthen 442
    @command
176 farthen 443
    def writedevconsole(self, bitmask, *args):
171 farthen 444
        """
176 farthen 445
            Writes the string <db1> ... <dbN> to one or more of the device's consoles.
446
            <bitmask>: the bitmask of the consoles to write to
171 farthen 447
        """
448
        bitmask = self._hexint(bitmask)
176 farthen 449
        text = ""
450
        for word in args:
451
            text += word + " "
452
        text = text[:-1]
453
        self.logger.info("Writing '"+text+"' to the device consoles identified with "+self._hex(bitmask)+"\n")
454
        self.embios.cwrite(text, bitmask)
171 farthen 455
 
456
    @command
457
    def flushconsolebuffers(self, bitmask):
458
        """
459
            flushes one or more of the device consoles' buffers.
460
            <bitmask>: the bitmask of the consoles to be flushed
461
        """
462
        bitmask = self._hexint(bitmask)
463
        raise NotImplementedError
464
 
465
    @command
466
    def getprocinfo(self):
467
        """
468
            Fetches data on the currently running processes
469
        """
173 farthen 470
        import datetime
471
        threads = self.embios.getprocinfo()
472
        self.logger.info("The device has "+str(len(threads))+" running threads:\n\n")
473
        for thread in threads:
474
            self.logger.info("  "+thread.name+":\n")
475
            self.logger.info("    Thread id: "+str(thread.id)+"\n")
476
            self.logger.info("    Thread type: "+thread.type+"\n")
477
            self.logger.info("    Thread state: "+thread.state+"\n")
478
            self.logger.info("    Priority: "+str(thread.priority)+"/256\n")
479
            self.logger.info("    CPU time (total): "+str(datetime.timedelta(microseconds=thread.cputime_total))+"\n")
480
            self.logger.info("    Stack address: "+self._hex(thread.stackaddr)+"\n")
481
            self.logger.info("    Registers:\n")
482
            for register in range(16):
483
                self.logger.info("      r"+str(register)+": "+self._hex(thread.regs["r"+str(register)])+"\n")
484
            self.logger.info("      cpsr: "+self._hex(thread.regs.cpsr))
485
            self.logger.info("\n")
486
 
171 farthen 487
    @command
488
    def lockscheduler(self):
489
        """
490
            Locks (freezes) the scheduler
491
        """
176 farthen 492
        self.logger.info("Will now lock scheduler\n")
173 farthen 493
        self.embios.lockscheduler()
171 farthen 494
 
495
    @command
496
    def unlockscheduler(self):
497
        """
498
            Unlocks (unfreezes) the scheduler
499
        """
176 farthen 500
        self.logger.info("Will now unlock scheduler\n")
173 farthen 501
        self.embios.unlockscheduler()
171 farthen 502
 
503
    @command
504
    def suspendthread(self, threadid):
505
        """
506
            Suspends/resumes the thread with thread ID <threadid>
507
        """
508
        threadid = self._hexint(threadid)
173 farthen 509
        self.embios.resumethread(threadid)
171 farthen 510
 
511
    @command
512
    def resumethread(self, threadid):
513
        """
514
            Resumes the thread with thread ID <threadid>
515
        """
516
        threadid = self._hexint(threadid)
173 farthen 517
        self.embios.resumethread(threadid)
171 farthen 518
 
519
    @command
520
    def killthread(self, threadid):
521
        """
522
            Kills the thread with thread ID <threadid>
523
        """
524
        threadid = self._hexint(threadid)
173 farthen 525
        self.embios.killthread(threadid)
171 farthen 526
 
527
    @command
528
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
529
        """
530
            Creates a new thread and returns its thread ID
531
            <namepointer> a pointer to the thread's name
532
            <entrypoint> a pointer to the entrypoint of the thread
533
            <stackpointer> a pointer to the stack of the thread
534
            <stacksize> the size of the thread's stack
535
            <type> the thread type, vaild are: 0 => user thread, 1 => system thread
536
            <priority> the priority of the thread, from 1 to 255
537
            <state> the thread's initial state, valid are: 1 => ready, 0 => suspended
538
        """
539
        nameptr = self._hexint(nameptr)
540
        entrypoint = self._hexint(entrypoint)
541
        stackpointer = self._hexint(stackpointer)
542
        stacksize = self._hexint(stacksize)
543
        priority = self._hexint(priority)
544
        self.embios.createthread(nameptr, entrypoint, stackptr, stacksize, type, priority, state)
172 farthen 545
 
546
    @command
547
    def run(self, filename):
548
        """
173 farthen 549
            Uploads the emBIOS application <filename> to
550
            the beginning of the user memory and executes it
172 farthen 551
        """
176 farthen 552
        #self.execimage(addr)
553
        raise NotImplementedError
171 farthen 554
 
555
    @command
173 farthen 556
    def execimage(self, addr):
171 farthen 557
        """
173 farthen 558
            Executes the emBIOS application at <addr>.
171 farthen 559
        """
172 farthen 560
        addr = self._hexint(addr)
173 farthen 561
        self.logger.info("Starting emBIOS app at "+self._hex(addr)+"\n")
172 farthen 562
        self.embios.execimage(addr)
176 farthen 563
 
171 farthen 564
    @command
176 farthen 565
    def flushcaches(self):
171 farthen 566
        """
176 farthen 567
            Flushes the CPUs data and instruction caches.
568
        """
569
        self.logger.info("Flushing CPU data and instruction caches...")
570
        self.embios.flushcaches()
571
        self.logger.info("done\n")
572
 
573
    @command
574
    def readbootflash(self, addr_flash, addr_mem, size):
575
        """
171 farthen 576
            Reads <size> bytes from bootflash to memory.
577
            <addr_bootflsh>: the address in bootflash to read from
578
            <addr_mem>: the address in memory to copy the data to
579
        """
580
        addr_flash = self._hexint(addr_flash)
581
        addr_mem = self._hexint(addr_mem)
582
        size = self._hexint(size)
174 farthen 583
        self.logger.info("Dumping boot flash addresses "+self._hex(addr_flash)+" - "+
584
                         hex(addr_flash+size)+" to "+self._hex(addr_mem)+" - "+self._hex(addr_mem+size)+"\n")
585
        self.embios.bootflashread(addr_flash, addr_mem, size)
176 farthen 586
 
171 farthen 587
    @command
176 farthen 588
    def writebootflash(self, addr_flash, addr_mem, size, force=False):
171 farthen 589
        """
590
            Writes <size> bytes from memory to bootflash.
591
            ATTENTION: Don't call this unless you really know what you're doing!
592
            This may BRICK your device (unless it has a good recovery option)
593
            <addr_mem>: the address in memory to copy the data from
594
            <addr_bootflsh>: the address in bootflash to write to
174 farthen 595
            <force>: Use this flag to suppress the 5 seconds delay
171 farthen 596
        """
597
        addr_flash = self._hexint(addr_flash)
598
        addr_mem = self._hexint(addr_mem)
599
        size = self._hexint(size)
174 farthen 600
        force = self._bool(force)
601
        self.logger.info("Writing boot flash from the memory in "+self._hex(addr_mem)+" - "+
602
                         hex(addr_mem+size)+" to "+self._hex(addr_flash)+" - "+self._hex(addr_flash+size)+"\n")
603
        if force == False:
604
            self.logger.info("If this was not what you intended press Ctrl-C NOW")
176 farthen 605
            for i in range(10):
174 farthen 606
                self.logger.info(".")
607
                time.sleep(1)
608
            self.logger.info("\n")
609
        self.embios.bootflashwrite(addr_flash, addr_mem, size)
176 farthen 610
 
171 farthen 611
    @command
176 farthen 612
    def runfirmware(self, addr, filename):
171 farthen 613
        """
176 farthen 614
            Uploads the firmware in 'filename' to the beginning of the
615
            user memory and executes it
171 farthen 616
        """
176 farthen 617
        addr = self._hexint(addr)
618
        self.uploadfile(addr, filename)
619
        self.execfirmware(addr)
64 benedikt93 620
 
171 farthen 621
    @command
176 farthen 622
    def execfirmware(self, addr):
623
        """
624
            Executes the firmware at addr
625
        """
626
        addr = self._hexint(addr)
627
        self.logger.info("Running firmware at "+self._hex(addr)+". Bye.")
628
        self.embios.execfirmware(addr)
629
 
630
    @command
171 farthen 631
    def aesencrypt(self, addr, size, keyindex):
632
        """
172 farthen 633
            Encrypts a buffer using a hardware key
171 farthen 634
        """
635
        addr = self._hexint(addr)
636
        size = self._hexint(size)
637
        keyindex = self._hexint(keyindex)
638
        self.embios.aesencrypt(addr, size, keyindex)
82 benedikt93 639
 
171 farthen 640
    @command
641
    def aesdecrypt(self, addr, size, keyindex):
642
        """
172 farthen 643
            Decrypts a buffer using a hardware key
171 farthen 644
        """
645
        addr = self._hexint(addr)
646
        size = self._hexint(size)
647
        keyindex = self._hexint(keyindex)
648
        self.embios.aesdecrypt(addr, size, keyindex)
172 farthen 649
 
650
    @command
651
    def hmac_sha1(self, addr, size, destination):
652
        """
653
            Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination'
654
        """
655
        addr = self._hexint(addr)
656
        size = self._hexint(size)
657
        destination = self._hexint(destination)
658
        sha1size = 0x14
173 farthen 659
        self.logger.info("Generating hmac-sha1 hash from the buffer at "+self._hex(addr)+" with the size "+self._hex(size)+
660
                         " and saving it to "+self._hex(destination)+" - "+self._hex(destination+sha1size)+"...")
172 farthen 661
        self.embios.hmac_sha1(addr, size, destination)
662
        self.logger.info("done\n")
663
        data = self.embios.readmem(destination, sha1size)
664
        hash = ord(data)
173 farthen 665
        self.logger.info("The generated hash is "+self._hex(hash))
64 benedikt93 666
 
171 farthen 667
if __name__ == "__main__":
668
    if len(sys.argv) < 2:
669
        usage("No command specified")
670
    interface = Commandline()
671
    interface._parsecommand(sys.argv[1], sys.argv[2:])