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