freemyipod r207 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r206‎ | r207 | r208 >
Date:15:42, 7 September 2010
Author:theseven
Status:new
Tags:
Comment:
Add embiosldr.py to svn
Modified paths:
  • /embios/trunk/tools/embiosldr.py (added) (history)
  • /embios/trunk/tools/libembiosldr.py (added) (history)

Diff [purge]

Index: embios/trunk/tools/embiosldr.py
@@ -0,0 +1,80 @@
 2+#!/usr/bin/env python
 3+#
 4+#
 5+# Copyright 2010 TheSeven
 6+#
 7+#
 8+# This file is part of emBIOS.
 9+#
 10+# emBIOS is free software: you can redistribute it and/or
 11+# modify it under the terms of the GNU General Public License as
 12+# published by the Free Software Foundation, either version 2 of the
 13+# License, or (at your option) any later version.
 14+#
 15+# emBIOS is distributed in the hope that it will be useful,
 16+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 18+# See the GNU General Public License for more details.
 19+#
 20+# You should have received a copy of the GNU General Public License along
 21+# with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 22+#
 23+#
 24+
 25+
 26+import sys
 27+import time
 28+import libembiosldr
 29+
 30+
 31+def usage():
 32+ print ""
 33+ print "Please provide a command and (if needed) parameters as command line arguments"
 34+ print ""
 35+ print "Available commands:"
 36+ print ""
 37+ print " upload <address> <file>"
 38+ print " Uploads the specified file to the specified memory address on the device."
 39+ print ""
 40+ print " download <address> <size> <file>"
 41+ print " Downloads <size> bytes of data from the specified address on the device,"
 42+ print " and stores it in the specified file."
 43+ print ""
 44+ print " execute <address> <stack>"
 45+ print " Executes code at the specified address in the device's memory."
 46+ print " The stack pointer will be set to <stack> before jumping to <address>."
 47+ print " iBugger will probably lose control of the device,"
 48+ print " if the code isn't explicitly written for it."
 49+ print ""
 50+ print " run <file>"
 51+ print " Loads the specified file to 0x08000000 (SDRAM) and executes it."
 52+ print " This is what you usually want to do."
 53+ print ""
 54+ print "All numbers are hexadecimal!"
 55+ exit(2)
 56+
 57+
 58+def parsecommand(dev, argv):
 59+ if len(argv) < 2: usage()
 60+
 61+ elif argv[1] == "upload":
 62+ if len(argv) != 4: usage()
 63+ dev.upload(int(argv[2], 16), argv[3])
 64+
 65+ elif argv[1] == "download":
 66+ if len(argv) != 5: usage()
 67+ dev.download(int(argv[2], 16), int(argv[3], 16), argv[4])
 68+
 69+ elif argv[1] == "execute":
 70+ if len(argv) != 4: usage()
 71+ dev.execute(int(argv[2], 16), int(argv[3], 16))
 72+
 73+ elif argv[1] == "run":
 74+ if len(argv) != 3: usage()
 75+ dev.run(argv[2])
 76+
 77+ else: usage()
 78+
 79+
 80+dev = libembiosldr.embiosldr()
 81+parsecommand(dev, sys.argv)
Index: embios/trunk/tools/libembiosldr.py
@@ -0,0 +1,177 @@
 2+#!/usr/bin/env python
 3+#
 4+#
 5+# Copyright 2010 TheSeven
 6+#
 7+#
 8+# This file is part of emBIOS.
 9+#
 10+# emBIOS is free software: you can redistribute it and/or
 11+# modify it under the terms of the GNU General Public License as
 12+# published by the Free Software Foundation, either version 2 of the
 13+# License, or (at your option) any later version.
 14+#
 15+# emBIOS is distributed in the hope that it will be useful,
 16+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 18+# See the GNU General Public License for more details.
 19+#
 20+# You should have received a copy of the GNU General Public License along
 21+# with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 22+#
 23+#
 24+
 25+
 26+import sys
 27+import math
 28+import struct
 29+import time
 30+import usb
 31+
 32+
 33+class embiosldr:
 34+ def __init__(self, generation = 0):
 35+ busses = usb.busses()
 36+
 37+ for bus in busses:
 38+ devices = bus.devices
 39+ for dev in devices:
 40+ if dev.idVendor == 0xffff and dev.idProduct == 0xe112:
 41+ handle = dev.open()
 42+ handle.setConfiguration(1)
 43+ handle.claimInterface(0)
 44+ if generation in [0, 2]:
 45+ self.devtype = 2;
 46+ self.maxin = 528;
 47+ self.maxout = 528
 48+ self.handle = handle
 49+ print("Connected to emBIOS Loader Recovery Mode on iPod Nano 2G, USB version %s" % dev.deviceVersion)
 50+ return
 51+ handle.releaseInterface()
 52+
 53+ raise Exception("Could not find specified device (generation = %d)" % generation)
 54+
 55+
 56+ @staticmethod
 57+ def __myprint(data):
 58+ sys.stdout.write(data)
 59+ sys.stdout.flush()
 60+
 61+
 62+ @staticmethod
 63+ def __getbulk(handle, endpoint, size):
 64+ data = handle.bulkRead(endpoint, size, 1000)
 65+ return struct.pack("%dB" % len(data), *data)
 66+
 67+
 68+ @staticmethod
 69+ def __checkstatus(data):
 70+ errorcode = struct.unpack("<I", data[:4])[0]
 71+ if errorcode == 1:
 72+ # everything went fine
 73+ return
 74+ elif errorcode == 2:
 75+ print("\nError: Device doesn't support this function!")
 76+ raise Exception("Device doesn't support this function!")
 77+ else:
 78+ print("\nUnknown error %d" % errorcode)
 79+ raise Exception("Unknown error %d" % errorcode)
 80+
 81+
 82+ def __readstatus(self):
 83+ return self.__getbulk(self.handle, 0x83, 0x10)
 84+
 85+
 86+ @staticmethod
 87+ def devtype2name(devtype):
 88+ if devtype == 2: return "iPod Nano 2G"
 89+ else: return "UNKNOWN (%8x)" % devtype
 90+
 91+
 92+ def write(self, offset, data, *range):
 93+ if offset & 3 != 0 or len(data) & 3 != 0:
 94+ raise Exception("Unaligned data write!")
 95+
 96+ boffset = 0
 97+ size = len(data)
 98+ if len(range) > 0:
 99+ boffset = range[0]
 100+ if len(range) > 1:
 101+ size = range[1]
 102+
 103+ maxblk = self.maxout - 0x10
 104+
 105+ while True:
 106+ blocklen = size
 107+ if blocklen == 0: break
 108+ if blocklen > maxblk: blocklen = maxblk
 109+ self.handle.bulkWrite(4, struct.pack("<IIII", 2, offset, int(blocklen / 4), 0) \
 110+ + data[boffset:boffset+blocklen])
 111+ self.__checkstatus(self.__readstatus())
 112+ offset += blocklen
 113+ boffset += blocklen
 114+ size -= blocklen
 115+
 116+
 117+ def read(self, offset, size):
 118+ if offset & 3 != 0 or size & 3 != 0:
 119+ raise Exception("Unaligned data read!")
 120+
 121+ maxblk = self.maxin - 0x10
 122+
 123+ data = ""
 124+
 125+ while True:
 126+ blocklen = size
 127+ if blocklen == 0: break
 128+ if blocklen > maxblk: blocklen = maxblk
 129+ self.handle.bulkWrite(4, struct.pack("<IIII", 1, offset, int(blocklen / 4), 0))
 130+ block = self.__getbulk(self.handle, 0x83, 0x10 + blocklen)
 131+ self.__checkstatus(block)
 132+ offset += blocklen
 133+ data += block[0x10:]
 134+ size -= blocklen
 135+
 136+ return data
 137+
 138+
 139+ def execute(self, addr, stack):
 140+ self.__myprint("Passing control to code at 0x%8x..." % addr)
 141+ self.handle.bulkWrite(4, struct.pack("<IIII", 0, addr, stack, 0))
 142+ self.__myprint(" done\n")
 143+
 144+
 145+ def upload(self, offset, file):
 146+ self.__myprint("Uploading %s to 0x%8x..." % (file, offset))
 147+ f = open(file, "rb")
 148+
 149+ while True:
 150+ data = f.read(65536)
 151+ if data == "": break
 152+ self.write(offset, data)
 153+ offset += len(data)
 154+ self.__myprint(".")
 155+
 156+ self.__myprint(" done\n")
 157+
 158+
 159+ def download(self, offset, size, file):
 160+ self.__myprint("Downloading 0x%x bytes from 0x%8x to %s..." % (size, offset, file))
 161+ f = open(file, "wb")
 162+
 163+ while True:
 164+ blocklen = size
 165+ if blocklen == 0: break
 166+ if blocklen > 65536: blocklen = 65536
 167+ f.write(self.read(offset, blocklen))
 168+ offset += blocklen
 169+ size -= blocklen
 170+ self.__myprint(".")
 171+
 172+ self.__myprint(" done\n")
 173+
 174+
 175+ def run(self, file):
 176+ self.upload(0x08000000, file)
 177+ self.execute(0x08000000, 0x0a000000)
 178+