Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 benedikt93 1
#!/usr/bin/env python
2
#
3
#
171 farthen 4
#    Copyright 2010 TheSeven, benedikt93, Farthen
56 benedikt93 5
#
6
#
7
#    This file is part of emBIOS.
8
#
9
#    emBIOS is free software: you can redistribute it and/or
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
#
14
#    emBIOS is distributed in the hope that it will be useful,
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
#
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/>.
21
#
22
#
23
 
24
import sys
25
import struct
171 farthen 26
import usb.core
27
import libembiosdata
56 benedikt93 28
 
396 farthen 29
from misc import Bunch, Error
394 farthen 30
from functools import wraps
31
 
171 farthen 32
class ArgumentError(Error):
33
    pass
56 benedikt93 34
 
171 farthen 35
class DeviceNotFoundError(Error):
36
    pass
56 benedikt93 37
 
171 farthen 38
class DeviceError(Error):
39
    pass
56 benedikt93 40
 
171 farthen 41
class SendError(Error):
42
    pass
56 benedikt93 43
 
171 farthen 44
class ReceiveError(Error):
45
    pass
56 benedikt93 46
 
47
 
394 farthen 48
def command(timeout = None):
49
    """
50
        Decorator for all commands.
51
        It adds the "timeout" variable to all commands.
52
        It also provides the possibility to set the timeout directly in the decorator.
53
        It also includes some dirty hacks to not learn from.
54
    """
55
    time = timeout # dirty hack because otherwise it would raise a scoping problem.
56
                   # The reason is probably because I suck but I can't find any good explanation of this.
57
    def decorator(func):
58
        @wraps(func)
59
        def wrapper(*args, **kwargs):
60
            # precommand stuff
61
            self = args[0] # little cheat as it expects self being always the first argument
62
            timeout = None
63
            if "timeout" in kwargs.keys():
64
                timeout = kwargs['timeout']
65
            elif time is not None:
66
                timeout = time
67
            if timeout is not None:
68
                oldtimeout = self.lib.dev.timeout
69
                self.lib.dev.timeout = timeout
70
            # function call
71
            ret = func(*args)
72
            # postcommand stuff
73
            if timeout is not None:
74
                self.lib.dev.timeout = oldtimeout
75
            return ret
396 farthen 76
        func._command = True
77
        wrapper.func = func
394 farthen 78
        return wrapper
79
    return decorator
80
 
81
 
171 farthen 82
class Embios(object):
176 farthen 83
    """
84
        Class for all embios functions.
394 farthen 85
        They all get the "@command()" decorator.
86
        This decorator has a timeout variable that can be set to change the
87
        device timeout for the duration of the function.
88
        It also adds a "timeout" argument to every function to access this
89
        feature from external. So DON'T EVER use a parameter called 'timeout'
90
        in your commands. Variables are ok.
176 farthen 91
    """
171 farthen 92
    def __init__(self):
176 farthen 93
        self.lib = Lib()
343 farthen 94
 
95
        self.getversioninfo()
176 farthen 96
        self.getpacketsizeinfo()
343 farthen 97
        self.getusermemrange()
56 benedikt93 98
 
171 farthen 99
    @staticmethod
100
    def _alignsplit(addr, size, blksize, align):
177 farthen 101
        if size <= blksize: return (size, 0, 0)
171 farthen 102
        end = addr + size
103
        if addr & (align - 1):
104
            bodyaddr = (addr + min(size, blksize)) & ~(align - 1)
105
        else: bodyaddr = addr
106
        headsize = bodyaddr - addr
107
        if (size - headsize) & (align - 1):
108
            tailaddr = (end - min(end - bodyaddr, blksize) + align - 1) & ~(align - 1)
109
        else: tailaddr = end
110
        tailsize = end - tailaddr
111
        return (headsize, tailaddr - bodyaddr, tailsize)
56 benedikt93 112
 
394 farthen 113
    @command()
178 farthen 114
    def _readmem(self, addr, size):
115
        """ Reads the memory from location 'addr' with size 'size'
116
            from the device.
117
        """
118
        resp = self.lib.monitorcommand(struct.pack("IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
119
        return resp.data
394 farthen 120
 
121
    @command()
178 farthen 122
    def _writemem(self, addr, data):
123
        """ Writes the data in 'data' to the location 'addr'
124
            in the memory of the device.
125
        """
126
        return self.lib.monitorcommand(struct.pack("IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
127
 
394 farthen 128
    @command()
178 farthen 129
    def _readdma(self, addr, size):
130
        """ Reads the memory from location 'addr' with size 'size'
131
            from the device. This uses DMA and the data in endpoint.
132
        """
133
        self.lib.monitorcommand(struct.pack("IIII", 6, addr, size, 0), "III", (None, None, None))
134
        return struct.unpack("%ds" % size, self.lib.dev.din(size))[0]
135
 
394 farthen 136
    @command()
178 farthen 137
    def _writedma(self, addr, data):
138
        """ Writes the data in 'data' to the location 'addr'
139
            in the memory of the device. This uses DMA and the data out endpoint.
140
        """
141
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
142
        return self.lib.dev.dout(data)
143
 
394 farthen 144
    @command()
171 farthen 145
    def getversioninfo(self):
146
        """ This returns the emBIOS version and device information. """
342 farthen 147
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
148
        self.lib.dev.version.revision = resp.revision
149
        self.lib.dev.version.majorv = resp.majorv
150
        self.lib.dev.version.minorv = resp.minorv
151
        self.lib.dev.version.patchv = resp.patchv
152
        self.lib.dev.swtypeid = resp.swtypeid
153
        self.lib.dev.hwtypeid = resp.hwtypeid
154
        return resp
56 benedikt93 155
 
394 farthen 156
    @command()
171 farthen 157
    def getpacketsizeinfo(self):
158
        """ This returns the emBIOS max packet size information.
159
            It also sets the properties of the device object accordingly.
160
        """
161
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
343 farthen 162
        self.lib.dev.packetsizelimit.cout = resp.coutmax
163
        self.lib.dev.packetsizelimit.cin = resp.cinmax
164
        self.lib.dev.packetsizelimit.din = resp.dinmax
165
        self.lib.dev.packetsizelimit.dout = resp.doutmax
171 farthen 166
        return resp
56 benedikt93 167
 
394 farthen 168
    @command()
171 farthen 169
    def getusermemrange(self):
170
        """ This returns the memory range the user has access to. """
342 farthen 171
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
172
        self.lib.dev.usermem.lower = resp.lower
173
        self.lib.dev.usermem.upper = resp.upper
174
        return resp
56 benedikt93 175
 
394 farthen 176
    @command()
171 farthen 177
    def reset(self, force=False):
178
        """ Reboot the device """
179
        if force:
180
            return self.lib.monitorcommand(struct.pack("IIII", 2, 0, 0, 0))
181
        else:
182
            return self.lib.monitorcommand(struct.pack("IIII", 2, 1, 0, 0), "III", (None, None, None))
56 benedikt93 183
 
394 farthen 184
    @command()
171 farthen 185
    def poweroff(self, force=False):
186
        """ Powers the device off. """
187
        if force:
188
            return self.lib.monitorcommand(struct.pack("IIII", 3, 0, 0, 0))
189
        else:
190
            return self.lib.monitorcommand(struct.pack("IIII", 3, 1, 0, 0), "III", (None, None, None))
56 benedikt93 191
 
394 farthen 192
    @command()
171 farthen 193
    def read(self, addr, size):
194
        """ Reads the memory from location 'addr' with size 'size'
195
            from the device. This cares about too long packages
196
            and decides whether to use DMA or not.
197
        """
343 farthen 198
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
199
        din_maxsize = self.lib.dev.packetsizelimit.din
171 farthen 200
        data = ""
201
        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
202
        if headsize != 0:
178 farthen 203
            data += self._readmem(addr, headsize)
171 farthen 204
            addr += headsize
205
        while bodysize > 0:
206
            if bodysize >= 2 * cin_maxsize:
207
                readsize = min(bodysize, din_maxsize)
178 farthen 208
                data += self._readdma(addr, readsize)
171 farthen 209
            else:
210
                readsize = min(bodysize, cin_maxsize)
178 farthen 211
                data += self._readmem(addr, readsize)
171 farthen 212
            addr += readsize
213
            bodysize -= readsize
214
        if tailsize != 0:
178 farthen 215
            data += self._readmem(addr, tailsize)
171 farthen 216
        return data
56 benedikt93 217
 
394 farthen 218
    @command()
171 farthen 219
    def write(self, addr, data):
220
        """ Writes the data in 'data' to the location 'addr'
221
            in the memory of the device. This cares about too long packages
222
            and decides whether to use DMA or not.
223
        """
343 farthen 224
        cout_maxsize = self.lib.dev.packetsizelimit.cout - self.lib.headersize
225
        dout_maxsize = self.lib.dev.packetsizelimit.dout
171 farthen 226
        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
227
        offset = 0
228
        if headsize != 0:
178 farthen 229
            self._writemem(addr, data[offset:offset+headsize])
171 farthen 230
            offset += headsize
231
            addr += headsize
232
        while bodysize > 0:
233
            if bodysize >= 2 * cout_maxsize:
234
                writesize = min(bodysize, dout_maxsize)
178 farthen 235
                self._writedma(addr, data[offset:offset+writesize])
171 farthen 236
            else:
237
                writesize = min(bodysize, cout_maxsize)
178 farthen 238
                self._writemem(addr, data[offset:offset+writesize])
171 farthen 239
            offset += writesize
240
            addr += writesize
241
            bodysize -= writesize
242
        if tailsize != 0:
178 farthen 243
            self._writemem(addr, data[offset:offset+tailsize])
171 farthen 244
        return data
56 benedikt93 245
 
394 farthen 246
    @command()
173 farthen 247
    def readstring(self, addr, maxlength = 256):
248
        """ Reads a zero terminated string from memory 
249
            Reads only a maximum of 'maxlength' chars.
250
        """
343 farthen 251
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
173 farthen 252
        string = ""
253
        while (len(string) < maxlength or maxlength < 0):
178 farthen 254
            data = self._readmem(addr, min(maxlength - len(string), cin_maxsize))
173 farthen 255
            length = data.find("\0")
256
            if length >= 0:
257
                string += data[:length]
258
                break
259
            else:
260
                string += data
261
            addr += cin_maxsize
262
        return string
263
 
394 farthen 264
    @command()
171 farthen 265
    def i2cread(self, index, slaveaddr, startaddr, size):
266
        """ Reads data from an i2c slave """
236 farthen 267
        data = ""
268
        for i in range(size):
269
            resp = self.lib.monitorcommand(struct.pack("IBBBBII", 8, index, slaveaddr, startaddr + i, 1, 0, 0), "III1s", (None, None, None, "data"))
270
            data += resp.data
271
        return data
56 benedikt93 272
 
394 farthen 273
    @command()
171 farthen 274
    def i2cwrite(self, index, slaveaddr, startaddr, data):
275
        """ Writes data to an i2c slave """
176 farthen 276
        size = len(data)
277
        if size > 256 or size < 1:
341 farthen 278
            raise ArgumentError("Size must be a number between 1 and 256")
176 farthen 279
        if size == 256:
280
            size = 0
215 theseven 281
        return self.lib.monitorcommand(struct.pack("IBBBBII%ds" % size, 9, index, slaveaddr, startaddr, size, 0, 0, data), "III", (None, None, None))
56 benedikt93 282
 
394 farthen 283
    @command()
176 farthen 284
    def usbcread(self):
285
        """ Reads one packet with the maximal cin size """
343 farthen 286
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
176 farthen 287
        resp = self.lib.monitorcommand(struct.pack("IIII", 10, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("validsize", "buffersize", "queuesize", "data"))
288
        resp.data = resp.data[:resp.validsize]
289
        resp.maxsize = cin_maxsize
290
        return resp
56 benedikt93 291
 
394 farthen 292
    @command()
171 farthen 293
    def usbcwrite(self, data):
294
        """ Writes data to the USB console """
343 farthen 295
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
176 farthen 296
        size = len(data)
297
        while len(data) > 0:
298
            writesize = min(cin_maxsize, len(data))
299
            resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 11, writesize, 0, 0, data[:writesize]), "III", ("validsize", "buffersize", "freesize"))
300
            data = data[resp.validsize:]
301
        return size
56 benedikt93 302
 
394 farthen 303
    @command()
176 farthen 304
    def cread(self, bitmask=0x1):
305
        """ Reads one packet with the maximal cin size from the device consoles
171 farthen 306
            identified with the specified bitmask
307
        """
343 farthen 308
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
217 theseven 309
        resp = self.lib.monitorcommand(struct.pack("IIII", 13, bitmask, cin_maxsize, 0), "III%ds" % cin_maxsize, ("size", None, None))
176 farthen 310
        resp.data = resp.data[size:]
311
        resp.maxsize = cin_maxsize
312
        return resp
394 farthen 313
 
314
    @command()
176 farthen 315
    def cwrite(self, data, bitmask=0x1):
171 farthen 316
        """ Writes data to the device consoles 
317
            identified with the specified bitmask.
318
        """
343 farthen 319
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
176 farthen 320
        size = len(data)
321
        while len(data) > 0:
322
            writesize = min(cin_maxsize, len(data))
217 theseven 323
            resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 12, bitmask, writesize, 0, data[:writesize]), "III", (None, None, None))
176 farthen 324
            data = data[writesize:]
325
        return size
56 benedikt93 326
 
394 farthen 327
    @command()
171 farthen 328
    def cflush(self, bitmask):
329
        """ Flushes the consoles specified with 'bitmask' """
330
        return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None))
56 benedikt93 331
 
394 farthen 332
    @command()
173 farthen 333
    def getprocinfo(self):
171 farthen 334
        """ Gets current state of the scheduler """
343 farthen 335
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
173 farthen 336
        # Get the size
337
        schedulerstate = self.lockscheduler()
338
        resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "tablesize", None))
339
        tablesize = resp.tablesize
340
        size = tablesize
341
        structver = resp.structver
342
        offset = 0
343
        data = ""
344
        while size > 0:
345
            if size > cin_maxsize:
346
                readsize = cin_maxsize
347
            else:
348
                readsize = size
349
            resp = self.lib.monitorcommand(struct.pack("IIII", 15, offset, readsize, 0), "III%ds" % readsize, ("structver", "tablesize", None, "data"))
350
            data += resp.data
351
            offset += readsize
352
            size -= readsize
353
        self.lockscheduler(schedulerstate)
354
        threadstructsize = 120
355
        registersize = 32
356
        if len(data) % threadstructsize != 0:
357
            raise DeviceError("The thread struct is not a multiple of "+str(threadsturcsize)+"!")
358
        threadcount = len(data) / threadstructsize
359
        threads = []
360
        id = 0
361
        for thread in range(threadcount):
362
            offset = threadstructsize * thread
363
            threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
364
            info = Bunch()
365
            info.id = id
366
            state = threaddata[17]
367
            info.state = libembiosdata.thread_state[state]
368
            if info.state == "THREAD_FREE":
369
                id += 1
370
                continue
371
            info.regs = Bunch()
372
            for register in range(16):
373
                info.regs["r"+str(register)] = threaddata[register]
374
            info.regs.cpsr = threaddata[16]
375
            info.nameptr = threaddata[18]
376
            if info.nameptr == 0:
377
                info.name = "Thread %d" % info.id
378
            else:
379
                info.name = self.readstring(info.nameptr)
380
            info.cputime_current = threaddata[19]
381
            info.cputime_total = threaddata[20]
382
            info.startusec = threaddata[21]
383
            info.queue_next_ptr = threaddata[22]
384
            info.timeout = threaddata[23]
385
            info.blocked_since = threaddata[24]
386
            info.blocked_by_ptr = threaddata[25]
387
            info.stackaddr = threaddata[26]
388
            info.err_no = threaddata[27]
389
            info.block_type = libembiosdata.thread_block[threaddata[28]]
390
            info.type = libembiosdata.thread_type[threaddata[29]]
391
            info.priority = threaddata[30]
392
            info.cpuload = threaddata[31]
393
            threads.append(info)
394
            id += 1
395
        return threads
56 benedikt93 396
 
394 farthen 397
    @command()
173 farthen 398
    def lockscheduler(self, freeze=True):
171 farthen 399
        """ Freezes/Unfreezes the scheduler """
173 farthen 400
        resp = self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
401
        return True if resp.before == 1 else False
67 benedikt93 402
 
394 farthen 403
    @command()
173 farthen 404
    def unlockscheduler(self):
171 farthen 405
        """ Unfreezes the scheduler """
406
        return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
56 benedikt93 407
 
394 farthen 408
    @command()
171 farthen 409
    def suspendthread(self, id, suspend=True):
410
        """ Suspends the thread with the specified id """
173 farthen 411
        resp = self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None))
412
        return True if resp.before == 1 else False
56 benedikt93 413
 
394 farthen 414
    @command()
173 farthen 415
    def resumethread(self, id):
416
        """ Resumes the thread with the specified id """
171 farthen 417
        return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
56 benedikt93 418
 
394 farthen 419
    @command()
171 farthen 420
    def killthread(self, id):
421
        """ Kills the thread with the specified id """
422
        return self.lib.monitorcommand(struct.pack("IIII", 18, id, 0, 0), "III", ("before", None, None))
56 benedikt93 423
 
394 farthen 424
    @command()
171 farthen 425
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
426
        """ Creates a thread with the specified attributes """
427
        if threadtype == "user":
428
            threadtype = 0
429
        elif threadtype == "system":
430
            threadtype = 1
431
        else:
341 farthen 432
            raise ArgumentError("Threadtype must be either 'system' or 'user'")
171 farthen 433
        if priority > 256 or priority < 0:
341 farthen 434
            raise ArgumentError("Priority must be a number between 0 and 256")
171 farthen 435
        if state == "ready":
436
            state = 0
437
        elif state == "suspended":
438
            state = 1
439
        else:
341 farthen 440
            raise ArgumentError("State must be either 'ready' or 'suspended'")
171 farthen 441
        resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None))
442
        if resp.id < 0:
443
            raise DeviceError("The device returned the error code "+str(resp.id))
444
        return resp
56 benedikt93 445
 
394 farthen 446
    @command()
172 farthen 447
    def flushcaches(self):
171 farthen 448
        """ Flushes the CPU instruction and data cache """
449
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
56 benedikt93 450
 
394 farthen 451
    @command()
172 farthen 452
    def execimage(self, addr):
171 farthen 453
        """ Runs the emBIOS app at 'addr' """
346 theseven 454
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("rc", None, None))
56 benedikt93 455
 
394 farthen 456
    @command()
238 farthen 457
    def run(self, app):
458
        """ Uploads and runs the emBIOS app in the string 'app' """
459
        try:
460
            appheader = struct.unpack("<8sIIIIIIIIII", app[:48])
461
        except struct.error:
341 farthen 462
            raise ArgumentError("The specified app is not an emBIOS application")
238 farthen 463
        header = appheader[0]
464
        if header != "emBIexec":
341 farthen 465
            raise ArgumentError("The specified app is not an emBIOS application")
238 farthen 466
        baseaddr = appheader[2]
467
        threadnameptr = appheader[8]
468
        nameptr = threadnameptr - baseaddr
469
        name = ""
470
        while True:
471
            char = app[nameptr:nameptr+1]
472
            try:
473
                if ord(char) == 0:
474
                    break
475
            except TypeError:
341 farthen 476
                raise ArgumentError("The specified app is not an emBIOS application")
238 farthen 477
            name += char
478
            nameptr += 1
479
        usermem = self.getusermemrange()
480
        if usermem.lower > baseaddr or usermem.upper < baseaddr + len(app):
481
            raise ArgumentError("The baseaddress of the specified emBIOS application is out of range of the user memory range on the device. Are you sure that this application is compatible with your device?")
482
        self.write(baseaddr, app)
483
        self.execimage(baseaddr)
484
        return Bunch(baseaddr=baseaddr, name=name)
485
 
395 farthen 486
    @command(timeout = 5000)
171 farthen 487
    def bootflashread(self, memaddr, flashaddr, size):
488
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
489
            to the memory at addr 'memaddr'
490
        """
174 farthen 491
        return self.lib.monitorcommand(struct.pack("IIII", 22, memaddr, flashaddr, size), "III", (None, None, None))
82 benedikt93 492
 
395 farthen 493
    @command(timeout = 30000)
171 farthen 494
    def bootflashwrite(self, memaddr, flashaddr, size):
495
        """ Copies the data in the memory at 'memaddr' of the specified size
496
            to the boot flash at addr 'flashaddr'
497
        """
174 farthen 498
        return self.lib.monitorcommand(struct.pack("IIII", 23, memaddr, flashaddr, size), "III", (None, None, None))
56 benedikt93 499
 
394 farthen 500
    @command()
171 farthen 501
    def execfirmware(self, addr):
502
        """ Executes the firmware at 'addr' and passes all control to it. """
269 farthen 503
        return self.lib.monitorcommand(struct.pack("IIII", 24, addr, 0, 0))
56 benedikt93 504
 
395 farthen 505
    @command(timeout = 30000)
171 farthen 506
    def aesencrypt(self, addr, size, keyindex):
507
        """ Encrypts the buffer at 'addr' with the specified size
508
            with the hardware AES key index 'keyindex'
509
        """
510
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 1, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 511
 
395 farthen 512
    @command(timeout = 30000)
171 farthen 513
    def aesdecrypt(self, addr, size, keyindex):
514
        """ Decrypts the buffer at 'addr' with the specified size
515
            with the hardware AES key index 'keyindex'
516
        """
517
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 0, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 518
 
395 farthen 519
    @command(timeout = 30000)
171 farthen 520
    def hmac_sha1(self, addr, size, destination):
521
        """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
522
        return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
56 benedikt93 523
 
394 farthen 524
    @command()
227 theseven 525
    def ipodnano2g_getnandinfo(self):
526
        """ Target-specific function: ipodnano2g
527
            Gathers some information about the NAND chip used
528
        """
346 theseven 529
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 530
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IHHHH", ("type", "pagesperblock", "banks", "userblocks", "blocks"))
531
 
395 farthen 532
    @command(timeout = 30000)
227 theseven 533
    def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
534
        """ Target-specific function: ipodnano2g
535
            Reads data from the NAND chip into memory
536
        """
346 theseven 537
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 538
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0002, addr | (0x80000000 if doecc != 0 else 0) | (0x40000000 if checkempty != 0 else 0), start, count), "III", (None, None, None))
539
 
395 farthen 540
    @command(timeout = 30000)
227 theseven 541
    def ipodnano2g_nandwrite(self, addr, start, count, doecc):
542
        """ Target-specific function: ipodnano2g
543
            Writes data to the NAND chip
544
        """
346 theseven 545
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 546
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0003, addr | (0x80000000 if doecc != 0 else 0), start, count), "III", (None, None, None))
547
 
395 farthen 548
    @command(timeout = 30000)
227 theseven 549
    def ipodnano2g_nanderase(self, addr, start, count):
550
        """ Target-specific function: ipodnano2g
551
            Erases blocks on the NAND chip and stores the results to memory
552
        """
346 theseven 553
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 554
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0004, addr, start, count), "III", (None, None, None))
555
 
394 farthen 556
    @command()
346 theseven 557
    def ipodclassic_gethddinfo(self):
558
        """ Target-specific function: ipodclassic
559
            Gather information about the hard disk drive
560
        """
561
        if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
562
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IQQII", ("identifyptr", "totalsectors", "virtualsectors", "bbtptr", "bbtsize"))
563
 
395 farthen 564
    @command(timeout = 30000)
346 theseven 565
    def ipodclassic_hddaccess(self, type, sector, count, addr):
566
        """ Target-specific function: ipodclassic
567
            Access the hard disk, type = 0 (read) / 1 (write)
568
        """
569
        if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
570
        rc = self.lib.monitorcommand(struct.pack("IIQIIII", 0xffff0002, type, sector, count, addr, 0, 0), "III", ("rc", None, None))
571
        if (rc > 0x80000000):
572
            raise DeviceError("HDD access (type=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (type, sector, count, addr, rc))
573
 
394 farthen 574
    @command()
346 theseven 575
    def ipodclassic_writebbt(self, bbt, tempaddr):
576
        """ Target-specific function: ipodclassic
577
            Write hard drive bad block table
578
        """
579
        if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
580
        try:
581
            bbtheader = struct.unpack("<8s2024sQII512I", bbt[:4096])
582
        except struct.error:
583
            raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
584
        if bbtheader[0] != "emBIbbth":
585
            raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
586
        virtualsectors = bbtheader[2]
587
        bbtsectors = bbtheader[3]
588
        self.write(tempaddr, bbt)
589
        sector = 0
590
        count = 1
591
        offset = 0
592
        for i in range(bbtsectors):
593
            if bbtheader[4][i] == sector + count:
594
                count = count + 1
595
            else:
596
                self.ipodclassic_hddaccess(1, sector, count, tempaddr + offset)
597
                offset = offset + count * 4096
598
                sector = bbtheader[4][i]
599
                count = 1
600
        self.ipodclassic_hddaccess(1, sector, count, tempaddr + offset)
601
 
394 farthen 602
    @command()
379 theseven 603
    def storage_get_info(self, volume):
346 theseven 604
        """ Get information about a storage device """
379 theseven 605
        result = self.lib.monitorcommand(struct.pack("IIII", 27, volume, 0, 0), "IIIIIIII", ("version", None, None, "sectorsize", "numsectors", "vendorptr", "productptr", "revisionptr"))
346 theseven 606
        if result.version != 1:
607
            raise ValueError("Unknown version of storage_info struct: %d" % result.version)
379 theseven 608
        result.vendor = self.readstring(result.vendorptr)
609
        result.product = self.readstring(result.productptr)
610
        result.revision = self.readstring(result.revisionptr)
346 theseven 611
        return result
612
 
395 farthen 613
    @command(timeout = 50000)
346 theseven 614
    def storage_read_sectors_md(self, volume, sector, count, addr):
615
        """ Read sectors from as storage device """
616
        result = self.lib.monitorcommand(struct.pack("IIQIIII", 28, volume, sector, count, addr, 0, 0), "III", ("rc", None, None, None))
617
        if result.rc > 0x80000000:
618
            raise DeviceError("storage_read_sectors_md(volume=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (volume, sector, count, addr, rc))
394 farthen 619
 
395 farthen 620
    @command(timeout = 50000)
346 theseven 621
    def storage_write_sectors_md(self, volume, sector, count, addr):
622
        """ Read sectors from as storage device """
623
        result = self.lib.monitorcommand(struct.pack("IIQIIII", 29, volume, sector, count, addr, 0, 0), "III", ("rc", None, None, None))
624
        if result.rc > 0x80000000:
625
            raise DeviceError("storage_read_sectors_md(volume=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (volume, sector, count, addr, rc))
394 farthen 626
 
395 farthen 627
    @command(timeout = 30000)
346 theseven 628
    def file_open(self, filename, mode):
629
        """ Opens a file and returns the handle """
630
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(filename), 30, mode, 0, 0, filename, 0), "III", ("fd", None, None))
631
        if result.fd > 0x80000000:
632
            raise DeviceError("file_open(filename=\"%s\", mode=0x%X) failed with RC=0x%08X, errno=%d" % (filename, mode, result.fd, self.errno()))
633
        return result.fd
634
 
395 farthen 635
    @command(timeout = 30000)
346 theseven 636
    def file_size(self, fd):
637
        """ Gets the size of a file referenced by a handle """
638
        result = self.lib.monitorcommand(struct.pack("IIII", 31, fd, 0, 0), "III", ("size", None, None))
639
        if result.size > 0x80000000:
640
            raise DeviceError("file_size(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.size, self.errno()))
641
        return result.size
394 farthen 642
 
395 farthen 643
    @command(timeout = 30000)
346 theseven 644
    def file_read(self, fd, addr, size):
645
        """ Reads data from a file referenced by a handle """
646
        result = self.lib.monitorcommand(struct.pack("IIII", 32, fd, addr, size), "III", ("rc", None, None))
647
        if result.rc > 0x80000000:
648
            raise DeviceError("file_read(fd=%d, addr=0x%08X, size=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, addr, size, result.rc, self.errno()))
649
        return result.rc
394 farthen 650
 
395 farthen 651
    @command(timeout = 30000)
346 theseven 652
    def file_write(self, fd, addr, size):
653
        """ Writes data from a file referenced by a handle """
654
        result = self.lib.monitorcommand(struct.pack("IIII", 33, fd, addr, size), "III", ("rc", None, None))
655
        if result.rc > 0x80000000:
656
            raise DeviceError("file_write(fd=%d, addr=0x%08X, size=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, addr, size, result.rc, self.errno()))
657
        return result.rc
658
 
395 farthen 659
    @command(timeout = 30000)
346 theseven 660
    def file_seek(self, fd, offset, whence):
661
        """ Seeks the file handle to the specified position in the file """
662
        result = self.lib.monitorcommand(struct.pack("IIII", 34, fd, offset, whence), "III", ("rc", None, None))
663
        if result.rc > 0x80000000:
664
            raise DeviceError("file_seek(fd=%d, offset=0x%08X, whence=%d) failed with RC=0x%08X, errno=%d" % (fd, offset, whence, result.rc, self.errno()))
665
        return result.rc
666
 
395 farthen 667
    @command(timeout = 30000)
346 theseven 668
    def file_truncate(self, fd, length):
669
        """ Truncates a file referenced by a handle to a specified length """
670
        result = self.lib.monitorcommand(struct.pack("IIII", 35, fd, offset, 0), "III", ("rc", None, None))
671
        if result.rc > 0x80000000:
672
            raise DeviceError("file_truncate(fd=%d, length=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, length, result.rc, self.errno()))
673
        return result.rc
674
 
395 farthen 675
    @command(timeout = 30000)
346 theseven 676
    def file_sync(self, fd):
677
        """ Flushes a file handles' buffers """
678
        result = self.lib.monitorcommand(struct.pack("IIII", 36, fd, 0, 0), "III", ("rc", None, None))
679
        if result.rc > 0x80000000:
680
            raise DeviceError("file_sync(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.rc, self.errno()))
681
        return result.rc
682
 
395 farthen 683
    @command(timeout = 30000)
346 theseven 684
    def file_close(self, fd):
685
        """ Closes a file handle """
686
        result = self.lib.monitorcommand(struct.pack("IIII", 37, fd, 0, 0), "III", ("rc", None, None))
687
        if result.rc > 0x80000000:
688
            raise DeviceError("file_close(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.rc, self.errno()))
689
        return result.rc
690
 
395 farthen 691
    @command(timeout = 30000)
346 theseven 692
    def file_close_all(self):
693
        """ Closes all file handles opened through the debugger """
694
        result = self.lib.monitorcommand(struct.pack("IIII", 38, 0, 0, 0), "III", ("rc", None, None))
695
        if result.rc > 0x80000000:
696
            raise DeviceError("file_close_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
697
        return result.rc
698
 
395 farthen 699
    @command(timeout = 30000)
346 theseven 700
    def file_kill_all(self):
701
        """ Kills all file handles (in the whole system) """
702
        result = self.lib.monitorcommand(struct.pack("IIII", 39, 0, 0, 0), "III", ("rc", None, None))
703
        if result.rc > 0x80000000:
704
            raise DeviceError("file_kill_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
705
        return result.rc
706
 
395 farthen 707
    @command(timeout = 30000)
346 theseven 708
    def file_unlink(self, filename):
709
        """ Removes a file """
710
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(filename), 40, 0, 0, 0, filename, 0), "III", ("rc", None, None))
711
        if result.rc > 0x80000000:
712
            raise DeviceError("file_unlink(filename=\"%s\") failed with RC=0x%08X, errno=%d" % (filename, result.rc, self.errno()))
713
        return result.rc
714
 
395 farthen 715
    @command(timeout = 30000)
346 theseven 716
    def file_rename(self, oldname, newname):
717
        """ Renames a file """
718
        result = self.lib.monitorcommand(struct.pack("IIII248s%dsB" % min(247, len(newname)), 41, 0, 0, 0, oldname, newname, 0), "III", ("rc", None, None))
719
        if result.rc > 0x80000000:
720
            raise DeviceError("file_rename(oldname=\"%s\", newname=\"%s\") failed with RC=0x%08X, errno=%d" % (oldname, newname, result.rc, self.errno()))
721
        return result.rc
722
 
395 farthen 723
    @command(timeout = 30000)
346 theseven 724
    def dir_open(self, dirname):
725
        """ Opens a directory and returns the handle """
726
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 42, 0, 0, 0, dirname, 0), "III", ("handle", None, None))
727
        if result.handle == 0:
728
            raise DeviceError("dir_open(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.handle, self.errno()))
729
        return result.handle
730
 
395 farthen 731
    @command(timeout = 30000)
346 theseven 732
    def dir_read(self, handle):
733
        """ Reads the next entry from a directory """
734
        result = self.lib.monitorcommand(struct.pack("IIII", 43, handle, 0, 0), "III", ("version", "maxpath", "ptr"))
735
        if result.ptr == 0:
736
            raise DeviceError("dir_read(handle=0x%08X) failed with RC=0x%08X, errno=%d" % (handle, result.ptr, self.errno()))
737
        if result.version != 1:
738
            raise ValueError("Unknown version of dirent struct: %d" % result.version)
739
        dirent = self.read(result.ptr, result.maxpath + 16)
740
        ret = Bunch()
741
        (ret.name, ret.attributes, ret.size, ret.startcluster, ret.wrtdate, ret.wrttime) = struct.unpack("%dsIIIHH" % result.maxpath, dirent)
742
        ret.name = ret.name[:ret.name.index('\x00')]
743
        return ret
744
 
395 farthen 745
    @command(timeout = 30000)
346 theseven 746
    def dir_close(self, handle):
747
        """ Closes a directory handle """
748
        result = self.lib.monitorcommand(struct.pack("IIII", 44, handle, 0, 0), "III", ("rc", None, None))
749
        if result.rc > 0x80000000:
750
            raise DeviceError("dir_close(handle=0x%08X) failed with RC=0x%08X, errno=%d" % (handle, result.rc, self.errno()))
751
        return result.rc
752
 
395 farthen 753
    @command(timeout = 30000)
346 theseven 754
    def dir_close_all(self):
755
        """ Closes all directory handles opened through the debugger """
756
        result = self.lib.monitorcommand(struct.pack("IIII", 45, 0, 0, 0), "III", ("rc", None, None))
757
        if result.rc > 0x80000000:
758
            raise DeviceError("dir_close_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
759
        return result.rc
760
 
395 farthen 761
    @command(timeout = 30000)
346 theseven 762
    def dir_kill_all(self):
763
        """ Kills all directory handles (in the whole system) """
764
        result = self.lib.monitorcommand(struct.pack("IIII", 46, 0, 0, 0), "III", ("rc", None, None))
765
        if result.rc > 0x80000000:
766
            raise DeviceError("dir_kill_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
767
        return result.rc
768
 
395 farthen 769
    @command(timeout = 30000)
346 theseven 770
    def dir_create(self, dirname):
771
        """ Creates a directory """
772
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 47, 0, 0, 0, dirname, 0), "III", ("rc", None, None))
773
        if result.rc > 0x80000000:
774
            raise DeviceError("dir_create(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
775
        return result.rc
776
 
395 farthen 777
    @command(timeout = 30000)
346 theseven 778
    def dir_remove(self, dirname):
779
        """ Removes an (empty) directory """
780
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 48, 0, 0, 0, dirname, 0), "III", ("rc", None, None))
781
        if result.rc > 0x80000000:
782
            raise DeviceError("dir_remove(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
783
        return result.rc
784
 
394 farthen 785
    @command()
346 theseven 786
    def errno(self):
787
        """ Returns the number of the last error that happened """
788
        result = self.lib.monitorcommand(struct.pack("IIII", 49, 0, 0, 0), "III", ("errno", None, None))
789
        return result.errno
790
 
394 farthen 791
    @command()
346 theseven 792
    def disk_mount(self, volume):
793
        """ Mounts a volume """
794
        result = self.lib.monitorcommand(struct.pack("IIII", 50, volume, 0, 0), "III", ("rc", None, None))
795
        if result.rc > 0x80000000:
796
            raise DeviceError("disk_mount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
797
        return result.rc
798
 
394 farthen 799
    @command()
346 theseven 800
    def disk_unmount(self, volume):
801
        """ Unmounts a volume """
802
        result = self.lib.monitorcommand(struct.pack("IIII", 51, volume, 0, 0), "III", ("rc", None, None))
803
        if result.rc > 0x80000000:
804
            raise DeviceError("disk_unmount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
805
        return result.rc
806
 
807
 
171 farthen 808
class Lib(object):
176 farthen 809
    def __init__(self):
171 farthen 810
        self.idVendor = 0xFFFF
811
        self.idProduct = 0xE000
176 farthen 812
 
813
        self.headersize = 0x10
814
 
815
        self.connect()
56 benedikt93 816
 
171 farthen 817
    def connect(self):
818
        self.dev = Dev(self.idVendor, self.idProduct)
819
        self.connected = True
56 benedikt93 820
 
171 farthen 821
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
269 farthen 822
        writelen = self.dev.cout(cmd)
171 farthen 823
        if rcvdatatypes:
824
            rcvdatatypes = "I" + rcvdatatypes # add the response
825
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
826
            data = struct.unpack(rcvdatatypes, data)
827
            response = data[0]
828
            if libembiosdata.responsecodes[response] == "ok":
829
                if rcvstruct:
830
                    datadict = Bunch()
831
                    counter = 1 # start with 1, 0 is the id
832
                    for item in rcvstruct:
833
                        if item != None: # else the data is undefined
834
                            datadict[item] = data[counter]
835
                        counter += 1
836
                    return datadict
837
                else:
838
                    return data
839
            elif libembiosdata.responsecodes[response] == "unsupported":
840
                raise DeviceError("The device does not support this command.")
841
            elif libembiosdata.responsecodes[response] == "invalid":
842
                raise DeviceError("Invalid command! This should NOT happen!")
843
            elif libembiosdata.responsecodes[response] == "busy":
844
                raise DeviceError("Device busy")
269 farthen 845
        else:
846
            return writelen
56 benedikt93 847
 
848
 
171 farthen 849
class Dev(object):
850
    def __init__(self, idVendor, idProduct):
851
        self.idVendor = idVendor
852
        self.idProduct = idProduct
67 benedikt93 853
 
171 farthen 854
        self.interface = 0
855
        self.timeout = 100
176 farthen 856
 
171 farthen 857
        self.connect()
858
        self.findEndpoints()
859
 
342 farthen 860
 
861
        # Device properties
343 farthen 862
        self.packetsizelimit = Bunch()
863
        self.packetsizelimit.cout = None
864
        self.packetsizelimit.cin = None
865
        self.packetsizelimit.dout = None
866
        self.packetsizelimit.din = None
342 farthen 867
 
343 farthen 868
        self.version = Bunch()
342 farthen 869
        self.version.revision = None
870
        self.version.majorv = None
871
        self.version.minorv = None
872
        self.version.patchv = None
873
        self.swtypeid = None
874
        self.hwtypeid = None
875
 
343 farthen 876
        self.usermem = Bunch()
342 farthen 877
        self.usermem.lower = None
878
        self.usermem.upper = None
56 benedikt93 879
 
171 farthen 880
    def __del__(self):
881
        self.disconnect()
56 benedikt93 882
 
171 farthen 883
    def findEndpoints(self):
884
        epcounter = 0
343 farthen 885
        self.endpoint = Bunch()
171 farthen 886
        for cfg in self.dev:
887
            for intf in cfg:
888
                for ep in intf:
889
                    if epcounter == 0:
343 farthen 890
                        self.endpoint.cout = ep.bEndpointAddress
171 farthen 891
                    elif epcounter == 1:
343 farthen 892
                        self.endpoint.cin = ep.bEndpointAddress
171 farthen 893
                    elif epcounter == 2:
343 farthen 894
                        self.endpoint.dout = ep.bEndpointAddress
171 farthen 895
                    elif epcounter == 3:
343 farthen 896
                        self.endpoint.din = ep.bEndpointAddress
171 farthen 897
                    epcounter += 1
898
        if epcounter <= 3:
899
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
56 benedikt93 900
 
171 farthen 901
    def connect(self):
902
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
903
        if self.dev is None:
904
            raise DeviceNotFoundError()
905
        self.dev.set_configuration()
56 benedikt93 906
 
171 farthen 907
    def disconnect(self):
908
        pass
102 benedikt93 909
 
171 farthen 910
    def send(self, endpoint, data):
911
        size = self.dev.write(endpoint, data, self.interface, self.timeout)
912
        if size != len(data):
176 farthen 913
            raise SendError("Not all data was written!")
171 farthen 914
        return len
102 benedikt93 915
 
171 farthen 916
    def receive(self, endpoint, size):
917
        read = self.dev.read(endpoint, size, self.interface, self.timeout)
918
        if len(read) != size:
176 farthen 919
            raise ReceiveError("Requested size and read size don't match!")
171 farthen 920
        return read
56 benedikt93 921
 
171 farthen 922
    def cout(self, data):
343 farthen 923
        if self.packetsizelimit.cout and len(data) > self.packetsizelimit.cout:
171 farthen 924
            raise SendError("Packet too big")
343 farthen 925
        return self.send(self.endpoint.cout, data)
94 benedikt93 926
 
171 farthen 927
    def cin(self, size):
343 farthen 928
        if self.packetsizelimit.cin and size > self.packetsizelimit.cin:
171 farthen 929
            raise ReceiveError("Packet too big")
343 farthen 930
        return self.receive(self.endpoint.cin, size)
94 benedikt93 931
 
171 farthen 932
    def dout(self, data):
343 farthen 933
        if self.packetsizelimit.dout and len(data) > self.packetsizelimit.dout:
171 farthen 934
            raise SendError("Packet too big")
343 farthen 935
        return self.send(self.endpoint.dout, data)
94 benedikt93 936
 
171 farthen 937
    def din(self, size):
343 farthen 938
        if self.packetsizelimit.din and size > self.packetsizelimit.din:
171 farthen 939
            raise ReceiveError("Packet too big")
343 farthen 940
        return self.receive(self.endpoint.din, size)
56 benedikt93 941
 
96 benedikt93 942
 
171 farthen 943
if __name__ == "__main__":
396 farthen 944
    from misc import Logger
945
    logger = Logger()
946
    if sys.argv[1] == "test":
947
        # Some tests
948
        import sys
949
        embios = Embios()
950
        resp = embios.getversioninfo()
951
        logger.log("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
952
                         "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
953
        resp = embios.getusermemrange()
954
        logger.log("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
955
        memaddr = resp.lower
956
        maxlen = resp.upper - resp.lower
957
        f = open("./embios.py", "rb")
958
        logger.log("Loading test file (embios.py) to send over USB...\n")
959
        datastr = f.read()[:maxlen]
960
        logger.log("Sending data...\n")
961
        embios.write(memaddr, datastr)
962
        logger.log("Encrypting data with the hardware key...\n")
963
        embios.aesencrypt(memaddr, len(datastr), 0)
964
        logger.log("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
965
        f = open("./libembios-test-encrypted.bin", "wb")
966
        f.write(embios.read(memaddr, len(datastr)))
967
        logger.log("Decrypting the data again...\n")
968
        embios.aesdecrypt(memaddr, len(datastr), 0)
969
        logger.log("Reading data back from device...\n")
970
        readdata = embios.read(memaddr, len(datastr))
971
        if readdata == datastr:
972
            logger.log("Data matches!")
973
        else:
974
            logger.log("Data does NOT match. Something went wrong")
975
 
976
    elif sys.argv[1] == "gendoc":
977
        # Generates Documentation
978
        from misc import gendoc
979
        logger.log("Generating documentation\n")
980
        cmddict = {}
981
        for attr, value in Embios.__dict__.iteritems():
982
            if getattr(value, 'func', False):
983
                if getattr(value.func, '_command', False):
984
                    cmddict[value.func.__name__] = value
985
        logger.log(gendoc(cmddict))