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
 
171 farthen 29
class Error(Exception):
30
    def __init__(self, value=None):
31
        self.value = value
32
    def __str__(self):
33
        if self.value != None:
34
            return repr(self.value)
56 benedikt93 35
 
171 farthen 36
class ArgumentError(Error):
37
    pass
56 benedikt93 38
 
171 farthen 39
class DeviceNotFoundError(Error):
40
    pass
56 benedikt93 41
 
171 farthen 42
class DeviceError(Error):
43
    pass
56 benedikt93 44
 
171 farthen 45
class SendError(Error):
46
    pass
56 benedikt93 47
 
171 farthen 48
class ReceiveError(Error):
49
    pass
56 benedikt93 50
 
51
 
171 farthen 52
class Bunch(dict):
56 benedikt93 53
    """
171 farthen 54
        This is a dict whose items can also be accessed with
55
        bunchinstance.something.
56 benedikt93 56
    """
171 farthen 57
    def __init__(self, **kw):
58
        dict.__init__(self, kw)
59
        self.__dict__ = self
56 benedikt93 60
 
171 farthen 61
    def __getstate__(self):
62
        return self
56 benedikt93 63
 
171 farthen 64
    def __setstate__(self, state):
65
        self.update(state)
66
        self.__dict__ = self
56 benedikt93 67
 
68
 
171 farthen 69
class Embios(object):
70
    def __init__(self):
71
        self.lib = Lib(self)
56 benedikt93 72
 
171 farthen 73
    @staticmethod
74
    def _alignsplit(addr, size, blksize, align):
75
        end = addr + size
76
        if addr & (align - 1):
77
            bodyaddr = (addr + min(size, blksize)) & ~(align - 1)
78
        else: bodyaddr = addr
79
        headsize = bodyaddr - addr
80
        if (size - headsize) & (align - 1):
81
            tailaddr = (end - min(end - bodyaddr, blksize) + align - 1) & ~(align - 1)
82
        else: tailaddr = end
83
        tailsize = end - tailaddr
84
        return (headsize, tailaddr - bodyaddr, tailsize)
56 benedikt93 85
 
171 farthen 86
    def getversioninfo(self):
87
        """ This returns the emBIOS version and device information. """
88
        return self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
56 benedikt93 89
 
171 farthen 90
    def getpacketsizeinfo(self):
91
        """ This returns the emBIOS max packet size information.
92
            It also sets the properties of the device object accordingly.
93
        """
94
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
95
        self.lib.dev.packetsizelimit['cout'] = resp.coutmax
96
        self.lib.dev.packetsizelimit['cin'] = resp.cinmax
97
        self.lib.dev.packetsizelimit['din'] = resp.dinmax
98
        self.lib.dev.packetsizelimit['dout'] = resp.doutmax
99
        return resp
56 benedikt93 100
 
171 farthen 101
    def getusermemrange(self):
102
        """ This returns the memory range the user has access to. """
103
        return self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
56 benedikt93 104
 
171 farthen 105
    def reset(self, force=False):
106
        """ Reboot the device """
107
        if force:
108
            return self.lib.monitorcommand(struct.pack("IIII", 2, 0, 0, 0))
109
        else:
110
            return self.lib.monitorcommand(struct.pack("IIII", 2, 1, 0, 0), "III", (None, None, None))
56 benedikt93 111
 
171 farthen 112
    def poweroff(self, force=False):
113
        """ Powers the device off. """
114
        if force:
115
            return self.lib.monitorcommand(struct.pack("IIII", 3, 0, 0, 0))
116
        else:
117
            return self.lib.monitorcommand(struct.pack("IIII", 3, 1, 0, 0), "III", (None, None, None))
56 benedikt93 118
 
171 farthen 119
    def read(self, addr, size):
120
        """ Reads the memory from location 'addr' with size 'size'
121
            from the device. This cares about too long packages
122
            and decides whether to use DMA or not.
123
        """
124
        if not self.lib.connected:
125
            self.lib.connect()
126
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
127
        din_maxsize = self.lib.dev.packetsizelimit["din"]
128
        data = ""
129
        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
130
        if headsize != 0:
131
            data += self.readmem(addr, headsize)
132
            addr += headsize
133
        while bodysize > 0:
134
            if bodysize >= 2 * cin_maxsize:
135
                readsize = min(bodysize, din_maxsize)
136
                data += self.readdma(addr, readsize)
137
            else:
138
                readsize = min(bodysize, cin_maxsize)
139
                data += self.readmem(addr, readsize)
140
            addr += readsize
141
            bodysize -= readsize
142
        if tailsize != 0:
143
            data += self.readmem(addr, tailsize)
144
        return data
56 benedikt93 145
 
171 farthen 146
    def write(self, addr, data):
147
        """ Writes the data in 'data' to the location 'addr'
148
            in the memory of the device. This cares about too long packages
149
            and decides whether to use DMA or not.
150
        """
151
        if not self.lib.connected:
152
            self.lib.connect()
153
        cout_maxsize = self.lib.dev.packetsizelimit["cout"] - 0x10
154
        dout_maxsize = self.lib.dev.packetsizelimit["dout"]
155
        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
156
        offset = 0
157
        if headsize != 0:
158
            self.writemem(addr, headsize)
159
            offset += headsize
160
            addr += headsize
161
        while bodysize > 0:
162
            if bodysize >= 2 * cout_maxsize:
163
                writesize = min(bodysize, dout_maxsize)
164
                self.writedma(addr, data[offset:offset+writesize])
165
            else:
166
                writesize = min(bodysize, cout_maxsize)
167
                self.writemem(addr, data[offset:offset+writesize])
168
            offset += writesize
169
            addr += writesize
170
            bodysize -= writesize
171
        if tailsize != 0:
172
            self.writemem(addr, data[offset:offset+tailsize])
173
        return data
56 benedikt93 174
 
171 farthen 175
    def readmem(self, addr, size):
176
        """ Reads the memory from location 'addr' with size 'size'
177
            from the device.
178
        """
179
        resp = self.lib.monitorcommand(struct.pack("IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
180
        return resp.data
181
 
182
    def writemem(self, addr, data):
183
        """ Writes the data in 'data' to the location 'addr'
184
            in the memory of the device.
185
        """
186
        return self.lib.monitorcommand(struct.pack("IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
56 benedikt93 187
 
171 farthen 188
    def readdma(self, addr, size):
189
        """ Reads the memory from location 'addr' with size 'size'
190
            from the device. This uses DMA and the data in endpoint.
191
        """
192
        self.lib.monitorcommand(struct.pack("IIII", 6, addr, size, 0), "III", (None, None, None))
193
        return struct.unpack("%ds" % size, self.lib.dev.din(size))[0]
56 benedikt93 194
 
171 farthen 195
    def writedma(self, addr, data):
196
        """ Writes the data in 'data' to the location 'addr'
197
            in the memory of the device. This uses DMA and the data out endpoint.
198
        """
199
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
200
        return self.lib.dev.dout(data)
56 benedikt93 201
 
173 farthen 202
    def readstring(self, addr, maxlength = 256):
203
        """ Reads a zero terminated string from memory 
204
            Reads only a maximum of 'maxlength' chars.
205
        """
206
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
207
        string = ""
208
        while (len(string) < maxlength or maxlength < 0):
209
            data = self.readmem(addr, min(maxlength - len(string), cin_maxsize))
210
            length = data.find("\0")
211
            if length >= 0:
212
                string += data[:length]
213
                break
214
            else:
215
                string += data
216
            addr += cin_maxsize
217
        return string
218
 
171 farthen 219
    def i2cread(self, index, slaveaddr, startaddr, size):
220
        """ Reads data from an i2c slave """
56 benedikt93 221
 
171 farthen 222
    def i2cwrite(self, index, slaveaddr, startaddr, data):
223
        """ Writes data to an i2c slave """
56 benedikt93 224
 
171 farthen 225
    def usbcread(self, size):
226
        """ Reads data with size 'size' from the USB console """
56 benedikt93 227
 
171 farthen 228
    def usbcwrite(self, data):
229
        """ Writes data to the USB console """
56 benedikt93 230
 
171 farthen 231
    def cread(self, size, bitmask):
232
        """ Reads data with the specified size from the device consoles
233
            identified with the specified bitmask
234
        """
56 benedikt93 235
 
171 farthen 236
    def cwrite(self, data):
237
        """ Writes data to the device consoles 
238
            identified with the specified bitmask.
239
        """
56 benedikt93 240
 
171 farthen 241
    def cflush(self, bitmask):
242
        """ Flushes the consoles specified with 'bitmask' """
243
        return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None))
56 benedikt93 244
 
173 farthen 245
    def getprocinfo(self):
171 farthen 246
        """ Gets current state of the scheduler """
173 farthen 247
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
248
        # Get the size
249
        schedulerstate = self.lockscheduler()
250
        resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "tablesize", None))
251
        tablesize = resp.tablesize
252
        size = tablesize
253
        structver = resp.structver
254
        offset = 0
255
        data = ""
256
        while size > 0:
257
            if size > cin_maxsize:
258
                readsize = cin_maxsize
259
            else:
260
                readsize = size
261
            resp = self.lib.monitorcommand(struct.pack("IIII", 15, offset, readsize, 0), "III%ds" % readsize, ("structver", "tablesize", None, "data"))
262
            data += resp.data
263
            offset += readsize
264
            size -= readsize
265
        self.lockscheduler(schedulerstate)
266
        threadstructsize = 120
267
        registersize = 32
268
        if len(data) % threadstructsize != 0:
269
            raise DeviceError("The thread struct is not a multiple of "+str(threadsturcsize)+"!")
270
        threadcount = len(data) / threadstructsize
271
        threads = []
272
        id = 0
273
        for thread in range(threadcount):
274
            offset = threadstructsize * thread
275
            threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
276
            info = Bunch()
277
            info.id = id
278
            state = threaddata[17]
279
            info.state = libembiosdata.thread_state[state]
280
            if info.state == "THREAD_FREE":
281
                id += 1
282
                continue
283
            info.regs = Bunch()
284
            for register in range(16):
285
                info.regs["r"+str(register)] = threaddata[register]
286
            info.regs.cpsr = threaddata[16]
287
            info.nameptr = threaddata[18]
288
            if info.nameptr == 0:
289
                info.name = "Thread %d" % info.id
290
            else:
291
                info.name = self.readstring(info.nameptr)
292
            info.cputime_current = threaddata[19]
293
            info.cputime_total = threaddata[20]
294
            info.startusec = threaddata[21]
295
            info.queue_next_ptr = threaddata[22]
296
            info.timeout = threaddata[23]
297
            info.blocked_since = threaddata[24]
298
            info.blocked_by_ptr = threaddata[25]
299
            info.stackaddr = threaddata[26]
300
            info.err_no = threaddata[27]
301
            info.block_type = libembiosdata.thread_block[threaddata[28]]
302
            info.type = libembiosdata.thread_type[threaddata[29]]
303
            info.priority = threaddata[30]
304
            info.cpuload = threaddata[31]
305
            threads.append(info)
306
            id += 1
307
        return threads
308
 
309
 
310
        return self.lib.monitorcommand(struct.pack("IIII", 15, offset, size, 0), "III%ds" % size, ("structver", "tablesize", None, "data"))
56 benedikt93 311
 
173 farthen 312
    def lockscheduler(self, freeze=True):
171 farthen 313
        """ Freezes/Unfreezes the scheduler """
173 farthen 314
        resp = self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
315
        return True if resp.before == 1 else False
67 benedikt93 316
 
173 farthen 317
    def unlockscheduler(self):
171 farthen 318
        """ Unfreezes the scheduler """
319
        return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
56 benedikt93 320
 
171 farthen 321
    def suspendthread(self, id, suspend=True):
322
        """ Suspends the thread with the specified id """
173 farthen 323
        resp = self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None))
324
        return True if resp.before == 1 else False
56 benedikt93 325
 
173 farthen 326
    def resumethread(self, id):
327
        """ Resumes the thread with the specified id """
171 farthen 328
        return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
56 benedikt93 329
 
171 farthen 330
    def killthread(self, id):
331
        """ Kills the thread with the specified id """
332
        return self.lib.monitorcommand(struct.pack("IIII", 18, id, 0, 0), "III", ("before", None, None))
56 benedikt93 333
 
171 farthen 334
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
335
        """ Creates a thread with the specified attributes """
336
        if threadtype == "user":
337
            threadtype = 0
338
        elif threadtype == "system":
339
            threadtype = 1
340
        else:
341
            raise SyntaxError("Threadtype must be either 'system' or 'user'")
342
        if priority > 256 or priority < 0:
343
            raise SyntaxError("Priority must be a number between 0 and 256")
344
        if state == "ready":
345
            state = 0
346
        elif state == "suspended":
347
            state = 1
348
        else:
349
            raise SyntaxError("State must be either 'ready' or 'suspended'")
350
        resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None))
351
        if resp.id < 0:
352
            raise DeviceError("The device returned the error code "+str(resp.id))
353
        return resp
56 benedikt93 354
 
172 farthen 355
    def flushcaches(self):
171 farthen 356
        """ Flushes the CPU instruction and data cache """
357
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
56 benedikt93 358
 
172 farthen 359
    def execimage(self, addr):
171 farthen 360
        """ Runs the emBIOS app at 'addr' """
361
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("excecimage", None, None))
56 benedikt93 362
 
171 farthen 363
    def bootflashread(self, memaddr, flashaddr, size):
364
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
365
            to the memory at addr 'memaddr'
366
        """
174 farthen 367
        return self.lib.monitorcommand(struct.pack("IIII", 22, memaddr, flashaddr, size), "III", (None, None, None))
82 benedikt93 368
 
171 farthen 369
    def bootflashwrite(self, memaddr, flashaddr, size):
370
        """ Copies the data in the memory at 'memaddr' of the specified size
371
            to the boot flash at addr 'flashaddr'
372
        """
174 farthen 373
        return self.lib.monitorcommand(struct.pack("IIII", 23, memaddr, flashaddr, size), "III", (None, None, None))
56 benedikt93 374
 
171 farthen 375
    def execfirmware(self, addr):
376
        """ Executes the firmware at 'addr' and passes all control to it. """
377
        return self.lib.monitorcommand(struct.pack("IIII", 24, addr, 0, 0), "III", (None, None, None))
56 benedikt93 378
 
171 farthen 379
    def aesencrypt(self, addr, size, keyindex):
380
        """ Encrypts the buffer at 'addr' with the specified size
381
            with the hardware AES key index 'keyindex'
382
        """
383
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 1, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 384
 
171 farthen 385
    def aesdecrypt(self, addr, size, keyindex):
386
        """ Decrypts the buffer at 'addr' with the specified size
387
            with the hardware AES key index 'keyindex'
388
        """
389
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 0, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 390
 
171 farthen 391
    def hmac_sha1(self, addr, size, destination):
392
        """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
393
        return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
56 benedikt93 394
 
395
 
171 farthen 396
class Lib(object):
397
    def __init__(self, embios):
398
        self.idVendor = 0xFFFF
399
        self.idProduct = 0xE000
400
 
401
        self.embios = embios
402
        self.connected = False
56 benedikt93 403
 
171 farthen 404
    def connect(self):
405
        self.dev = Dev(self.idVendor, self.idProduct)
406
        self.connected = True
407
        self.embios.getpacketsizeinfo()
56 benedikt93 408
 
171 farthen 409
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
410
        if not self.connected:
411
            self.connect()
412
        self.dev.cout(cmd)
413
        if rcvdatatypes:
414
            rcvdatatypes = "I" + rcvdatatypes # add the response
415
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
416
            data = struct.unpack(rcvdatatypes, data)
417
            response = data[0]
418
            if libembiosdata.responsecodes[response] == "ok":
419
                if rcvstruct:
420
                    datadict = Bunch()
421
                    counter = 1 # start with 1, 0 is the id
422
                    for item in rcvstruct:
423
                        if item != None: # else the data is undefined
424
                            datadict[item] = data[counter]
425
                        counter += 1
426
                    return datadict
427
                else:
428
                    return data
429
            elif libembiosdata.responsecodes[response] == "unsupported":
430
                raise DeviceError("The device does not support this command.")
431
            elif libembiosdata.responsecodes[response] == "invalid":
432
                raise DeviceError("Invalid command! This should NOT happen!")
433
            elif libembiosdata.responsecodes[response] == "busy":
434
                raise DeviceError("Device busy")
56 benedikt93 435
 
436
 
171 farthen 437
class Dev(object):
438
    def __init__(self, idVendor, idProduct):
439
        self.idVendor = idVendor
440
        self.idProduct = idProduct
67 benedikt93 441
 
171 farthen 442
        self.interface = 0
443
        self.timeout = 100
119 benedikt93 444
 
171 farthen 445
        self.connect()
446
        self.findEndpoints()
447
 
448
        self.packetsizelimit = {}
449
        self.packetsizelimit['cout'] = None
450
        self.packetsizelimit['cin'] = None
451
        self.packetsizelimit['dout'] = None
452
        self.packetsizelimit['din'] = None
56 benedikt93 453
 
171 farthen 454
    def __del__(self):
455
        self.disconnect()
56 benedikt93 456
 
171 farthen 457
    def findEndpoints(self):
458
        epcounter = 0
459
        self.endpoint = {}
460
        for cfg in self.dev:
461
            for intf in cfg:
462
                for ep in intf:
463
                    if epcounter == 0:
464
                        self.endpoint['cout'] = ep.bEndpointAddress
465
                    elif epcounter == 1:
466
                        self.endpoint['cin'] = ep.bEndpointAddress
467
                    elif epcounter == 2:
468
                        self.endpoint['dout'] = ep.bEndpointAddress
469
                    elif epcounter == 3:
470
                        self.endpoint['din'] = ep.bEndpointAddress
471
                    epcounter += 1
472
        if epcounter <= 3:
473
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
56 benedikt93 474
 
171 farthen 475
    def connect(self):
476
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
477
        if self.dev is None:
478
            raise DeviceNotFoundError()
479
        self.dev.set_configuration()
56 benedikt93 480
 
171 farthen 481
    def disconnect(self):
482
        pass
102 benedikt93 483
 
171 farthen 484
    def send(self, endpoint, data):
485
        size = self.dev.write(endpoint, data, self.interface, self.timeout)
486
        if size != len(data):
487
            raise SendError
488
        return len
102 benedikt93 489
 
171 farthen 490
    def receive(self, endpoint, size):
491
        read = self.dev.read(endpoint, size, self.interface, self.timeout)
492
        if len(read) != size:
493
            raise ReceiveError
494
        return read
56 benedikt93 495
 
171 farthen 496
    def cout(self, data):
497
        if self.packetsizelimit['cout'] and len(data) > self.packetsizelimit['cout']:
498
            raise SendError("Packet too big")
499
        return self.send(self.endpoint['cout'], data)
94 benedikt93 500
 
171 farthen 501
    def cin(self, size):
502
        if self.packetsizelimit['cin'] and size > self.packetsizelimit['cin']:
503
            raise ReceiveError("Packet too big")
504
        return self.receive(self.endpoint['cin'], size)
94 benedikt93 505
 
171 farthen 506
    def dout(self, data):
507
        if self.packetsizelimit['dout'] and len(data) > self.packetsizelimit['dout']:
508
            raise SendError("Packet too big")
509
        return self.send(self.endpoint['dout'], data)
94 benedikt93 510
 
171 farthen 511
    def din(self, size):
512
        if self.packetsizelimit['din'] and size > self.packetsizelimit['din']:
513
            raise ReceiveError("Packet too big")
514
        return self.receive(self.endpoint['din'], size)
56 benedikt93 515
 
96 benedikt93 516
 
171 farthen 517
if __name__ == "__main__":
518
    # Some tests
519
    import sys
520
    embios = Embios()
521
    resp = embios.getversioninfo()
522
    sys.stdout.write("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
523
                     "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
524
    resp = embios.getusermemrange()
525
    sys.stdout.write("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
526
    memaddr = resp.lower
527
    maxlen = resp.upper - resp.lower
528
    f = open("./embios.py", "rb")
529
    sys.stdout.write("Loading test file (embios.py) to send over USB...\n")
530
    datastr = f.read()[:maxlen]
531
    sys.stdout.write("Sending data...\n")
532
    embios.write(memaddr, datastr)
533
    sys.stdout.write("Encrypting data with the hardware key...\n")
534
    embios.aesencrypt(memaddr, len(datastr), 0)
535
    sys.stdout.write("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
536
    f = open("./libembios-test-encrypted.bin", "wb")
537
    f.write(embios.read(memaddr, len(datastr)))
538
    sys.stdout.write("Decrypting the data again...\n")
539
    embios.aesdecrypt(memaddr, len(datastr), 0)
540
    sys.stdout.write("Reading data back from device...\n")
541
    readdata = embios.read(memaddr, len(datastr))
542
    if readdata == datastr:
543
        sys.stdout.write("Data matches!")
544
    else:
545
        sys.stdout.write("Data does NOT match. Something got wrong")