From 6d203cf3bcc3c50204b7af90c93defaccc73189f Mon Sep 17 00:00:00 2001 From: Dogbert Date: Wed, 5 Dec 2012 10:53:41 -0800 Subject: [PATCH] initial commit --- README.md | 6 +- bootloader.py | 83 +++++++++++ crctable.py | 51 +++++++ msm_apply.py | 82 +++++++++++ msm_unlock.py | 363 ++++++++++++++++++++++++++++++++++++++++++++++++ patch/make.sh | 3 + patch/patch.bin | Bin 0 -> 4047 bytes patch/patch.s | 169 ++++++++++++++++++++++ 8 files changed, 755 insertions(+), 2 deletions(-) create mode 100755 bootloader.py create mode 100755 crctable.py create mode 100755 msm_apply.py create mode 100755 msm_unlock.py create mode 100755 patch/make.sh create mode 100755 patch/patch.bin create mode 100755 patch/patch.s diff --git a/README.md b/README.md index 548ecbd..7f50d83 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ -MSMUnlock -========= \ No newline at end of file +Unlocker for Option GI0225 3G Modems +==================================== +This script will remove the net-/simlock for Option GI0225 Modems. More information here: +http://dogber1.blogspot.com/2010/01/unlocker-for-option-gio225.html diff --git a/bootloader.py b/bootloader.py new file mode 100755 index 0000000..340f71c --- /dev/null +++ b/bootloader.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Copyright 2009: dogbert +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import hashlib, os + +def sha1sum(filename): + return hashlib.sha1(open(filename,'rb').read()).hexdigest() + +def checkUnpatchedBootloader(filename): + return (sha1sum(filename) in ("cbcef9e634999b6b778a04b45b178fec0ea709c9", "e6a537b16f35bf7e4cc207fb157dc5eef73ab3ee", "a2fd786181c3f75dd88395c0badc01e0acd6e086", "53a69d0e0aa8479366bc2378b67bbdc15b63c42a")) + +def checkPatchedBootloader(filename): + return (sha1sum(filename) == "4252e74d48fe60d1173ecd898e2d3cdfd2a96c53") + +def extractBootloader(inFile, outFile, offset): + f = open(inFile, 'rb') + f.seek(offset) + intelHex = f.read(0x18c97) + f.close() + data = '' + for s in intelHex.splitlines(): + if s[0] != ':': + continue + if int(s[1]+s[2],16) < 5: + continue + for i in range(0, (len(s)-11)/2): + data += chr(int(s[i*2+9]+s[i*2+10],16)) + f = open(outFile, 'wb') + f.write(data) + f.close() + return + +def patchBootloader(inFile, outFile, patchFile): + inF = open(inFile, 'rb') + orig = inF.read() + inF.close() + + paF = open(patchFile, 'rb') + patch = paF.read() + paF.close() + + patchedLoader = orig[0:0x89df] + '\x00' + patch[0x9e0:0x9e0+0x110] + patchedLoader += orig[0x89e0+0x110:0x8b14] + '\xe1\x89' + orig[0x8b16:len(orig)] + + outF = open(outFile, 'wb') + outF.write(patchedLoader) + outF.close() + + return + +def getBootloader(): + if not os.path.exists('msm6280.bin'): + if not os.path.exists('Superfire.exe'): + return False + sum = sha1sum('Superfire.exe') + + if sum == 'd584e3fb5bd786bba7d3bcf3391523d88fd6128e': + extractBootloader('Superfire.exe', 'msm6280.bin', 0x9c5cc) + elif sum in ('534ecd8f693cd4d9a89c31d00d17885d3abcb26a', '4ecda86f0816f2641fbfa19c00dd0034108b86b7', 'fef058fbcedcbfb3a77f99812c14815d6b3abd83', '68fd7d98360f2ac2c09a30e6b9d2af9eb6b314b9', 'ff79c921fcd360c3674d57bf07c948b4d528897d'): + extractBootloader('Superfire.exe', 'msm6280.bin', 0x9c44c) + else: + return False + if not os.path.exists('msm6280-patched.bin'): + if not checkUnpatchedBootloader('msm6280.bin'): + return False + patchBootloader('msm6280.bin', 'msm6280-patched.bin', os.path.join('patch','patch.bin')) + return checkPatchedBootloader('msm6280-patched.bin') diff --git a/crctable.py b/crctable.py new file mode 100755 index 0000000..35c4a15 --- /dev/null +++ b/crctable.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# +# Copyright 2009: dogbert +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +crcTable = (0xF078,0xE1F1,0xD36A,0xC2E3,0xB65C,0xA7D5,0x954E,0x84C7, + 0x7C30,0x6DB9,0x5F22,0x4EAB,0x3A14,0x2B9D,0x1906,0x088F, + 0xE0F9,0xF170,0xC3EB,0xD262,0xA6DD,0xB754,0x85CF,0x9446, + 0x6CB1,0x7D38,0x4FA3,0x5E2A,0x2A95,0x3B1C,0x0987,0x180E, + 0xD17A,0xC0F3,0xF268,0xE3E1,0x975E,0x86D7,0xB44C,0xA5C5, + 0x5D32,0x4CBB,0x7E20,0x6FA9,0x1B16,0x0A9F,0x3804,0x298D, + 0xC1FB,0xD072,0xE2E9,0xF360,0x87DF,0x9656,0xA4CD,0xB544, + 0x4DB3,0x5C3A,0x6EA1,0x7F28,0x0B97,0x1A1E,0x2885,0x390C, + 0xB27C,0xA3F5,0x916E,0x80E7,0xF458,0xE5D1,0xD74A,0xC6C3, + 0x3E34,0x2FBD,0x1D26,0x0CAF,0x7810,0x6999,0x5B02,0x4A8B, + 0xA2FD,0xB374,0x81EF,0x9066,0xE4D9,0xF550,0xC7CB,0xD642, + 0x2EB5,0x3F3C,0x0DA7,0x1C2E,0x6891,0x7918,0x4B83,0x5A0A, + 0x937E,0x82F7,0xB06C,0xA1E5,0xD55A,0xC4D3,0xF648,0xE7C1, + 0x1F36,0x0EBF,0x3C24,0x2DAD,0x5912,0x489B,0x7A00,0x6B89, + 0x83FF,0x9276,0xA0ED,0xB164,0xC5DB,0xD452,0xE6C9,0xF740, + 0x0FB7,0x1E3E,0x2CA5,0x3D2C,0x4993,0x581A,0x6A81,0x7B08, + 0x7470,0x65F9,0x5762,0x46EB,0x3254,0x23DD,0x1146,0x00CF, + 0xF838,0xE9B1,0xDB2A,0xCAA3,0xBE1C,0xAF95,0x9D0E,0x8C87, + 0x64F1,0x7578,0x47E3,0x566A,0x22D5,0x335C,0x01C7,0x104E, + 0xE8B9,0xF930,0xCBAB,0xDA22,0xAE9D,0xBF14,0x8D8F,0x9C06, + 0x5572,0x44FB,0x7660,0x67E9,0x1356,0x02DF,0x3044,0x21CD, + 0xD93A,0xC8B3,0xFA28,0xEBA1,0x9F1E,0x8E97,0xBC0C,0xAD85, + 0x45F3,0x547A,0x66E1,0x7768,0x03D7,0x125E,0x20C5,0x314C, + 0xC9BB,0xD832,0xEAA9,0xFB20,0x8F9F,0x9E16,0xAC8D,0xBD04, + 0x3674,0x27FD,0x1566,0x04EF,0x7050,0x61D9,0x5342,0x42CB, + 0xBA3C,0xABB5,0x992E,0x88A7,0xFC18,0xED91,0xDF0A,0xCE83, + 0x26F5,0x377C,0x05E7,0x146E,0x60D1,0x7158,0x43C3,0x524A, + 0xAABD,0xBB34,0x89AF,0x9826,0xEC99,0xFD10,0xCF8B,0xDE02, + 0x1776,0x06FF,0x3464,0x25ED,0x5152,0x40DB,0x7240,0x63C9, + 0x9B3E,0x8AB7,0xB82C,0xA9A5,0xDD1A,0xCC93,0xFE08,0xEF81, + 0x07F7,0x167E,0x24E5,0x356C,0x41D3,0x505A,0x62C1,0x7348, + 0x8BBF,0x9A36,0xA8AD,0xB924,0xCD9B,0xDC12,0xEE89,0xFF00) diff --git a/msm_apply.py b/msm_apply.py new file mode 100755 index 0000000..f705922 --- /dev/null +++ b/msm_apply.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright 2009: dogbert +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import getopt, sys, os, msm_unlock + +def info(): + print "msm_apply.py v1.6" + print "Copyright (c) 2009 dogbert , http://dogber1.blogspot.com" + print "This scripts applies the unlock code of Option 3G modems (Icon 225)." + print "" + +def usage(): + print "Options: -a, --appPort= name of the serial application port (e.g. COM4)" + print " -c, --code= unlock code" + print "Example: msm_apply.py -a COM3 -c 12345678" + +def main(): + info() + try: + opts, args = getopt.getopt(sys.argv[1:], "hc:a:", ["help", "code=", "diagPort="]) + except getopt.GetoptError, err: + print str(err) + usage() + sys.exit(2) + + appPort = None + code = '' + baud = 115200 + Init = True + + for o, a in opts: + if o in ("-c", "--code"): + code = int(a) + if o in ("-a", "--appPort"): + appPort = a + elif o in ("-h", "--help"): + usage() + sys.exit() + + if (os.name == 'nt') and (appPort == None): + print "Searching for serial ports..." + appPort = msm_unlock.findSerialPorts()[0] + + if appPort == None: + print "Failed to find the application port. Please shutdown the device software." + sys.exit(-1) + + print "Application serial port: %s" % appPort + print "" + + if code == '': + print "Please enter the unlock code:" + code = int(raw_input()) + + print "" + print "Unlocking modem..." + if msm_unlock.unlockModem(appPort, code): + print "Unlock successful." + else: + print "ERROR: Unlock unsuccessful" + print "" + print "done." + raw_input() + +if __name__ == "__main__": + main() diff --git a/msm_unlock.py b/msm_unlock.py new file mode 100755 index 0000000..e817476 --- /dev/null +++ b/msm_unlock.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python +# +# Copyright 2009: dogbert +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +import serial, string, os, getopt, sys, crctable, bootloader +from struct import pack, unpack, unpack_from +from time import sleep + +def crc16(s): + crc = 0 + for c in s: + crc = crctable.crcTable[(crc&0xff)^ord(c)] ^ (crc >> 8) + return crc & 0xFFFF + +def readSerial(ser): + while 1: + if ser.inWaiting() > 0: + dumphex(ser.read(ser.inWaiting())) + else: + sleep(0.2) + +def sendRawCommand(ser, command, bufsize=0, timeout=1000, dwnMode=False): + if len(command) > 0: + ser.write(command) + t = 0 + r = "" + while bufsize > 0: + if dwnMode: + r += ser.read(ser.inWaiting()) + if len(r) > 2: + if (ord(r[len(r)-1]) == 0x7e) and (ord(r[len(r)-2]) != 0x7d): + return r + else: + sleep(0.001) + t += 1 + else: + if ser.inWaiting() >= bufsize: + return ser.read(bufsize) + else: + sleep(0.001) + t += 1 + if t > timeout: +# print "timeout (buffer size %d)" % ser.inWaiting() + return "" + +def sendCommand(ser, command, bufsize=0, timeout=1000, dwnMode=False): + if command[0] == "\x7e": + crc = crc16(command[1:len(command)]) + else: + crc = crc16(command) + command = command + pack('H', crc) + + command = command[0] + command[1:len(command)].replace('\x7D', '\x7D\x5D').replace('\x7E', '\x7D\x5E') + command += '\x7E' +# dumphex(command) + r = sendRawCommand(ser, command, bufsize, timeout, dwnMode) + if not r is None: + i = 2 + while i < len(r): + if (r[i] == "\x5D") and (r[i-1] == "\x7D"): + r = r[0:i-1] + "\x7D" + r[i+1:len(r)] + elif (r[i] == "\x5E") and (r[i-1] == "\x7D"): + r = r[0:i-1] + "\x7E" + r[i+1:len(r)] + i += 1 + else: + r = "" + return r + +def dumphex(s): + i = -1 + if s is None: + return + print "dumping %d bytes..." % len(s) + for i in xrange(0,len(s)/16+1): + o = '%08x ' % (i*16) + for j in range(0, 16): + if len(s) > i*16+j: + o += '%02x ' % ord(s[i*16+j]) + else: + o += ' ' + o += ' |' + for j in range(0, 16): + if len(s) > i*16+j: + if (ord(s[i*16+j]) > 0x1F) and (ord(s[i*16+j]) < 0x7F): + o += s[i*16+j] + else: + o += '.' + else: + break + o += '|' + print o + +def getInfo(ser): + return sendCommand(ser, "\x00", 58) + +def enableDwnMode(ser): + command = '\x7e\x3a' + r = sendCommand(ser, command, 4, dwnMode=True) + r = "" + ser.close() +# sleep(0.2) + ser.open() + while len(r) == 0: + command = '\x7e\x0c' + r = sendCommand(ser, command, 12, dwnMode=True, timeout=2000) +# dumphex(r) + if len(r) == 0: + ser.close() + sleep(0.05) + ser.open() + command = '\x7e\x07' + r = sendCommand(ser, command, 11, dwnMode=True, timeout=10000) + print "Download mode activated" + +def dwnResetPhone(ser): + return sendCommand(ser, '\x7e\x0a', 5, dwnMode=True) + +def dwnWriteMem(ser, buffer, address, size): + # little endian ! + command = "\x7e\x0f" + pack('>I', address) + pack('>H', size) + buffer + return sendCommand(ser, command, 5, dwnMode=True) + +def dwnExecute(ser, address): + command = '\x7e\x05' + pack('>I', address) + r = sendCommand(ser, command, timeout=5, dwnMode=True) + +def sendBootloader(ser, bootloader): + enableDwnMode(ser) + sleep(0.2) + + startAddress = 0x800000 + bufferSize = 0x3f9 + address = startAddress + + f = open(bootloader, "rb") + while 1: + buffer = f.read(bufferSize) + r = dwnWriteMem(ser, buffer, address, len(buffer)) + if ord(r[1]) != 0x02: + print "Error while sending bootloader: write memory failed at %08x" % address + return False + sleep(0.1) + address += bufferSize + if len(buffer) < bufferSize: + break + print "Executing bootloader..." + dwnExecute(ser, startAddress) + return True + +def testBootloader(ser): + r = '' + while len(r) < 500: + sleep(0.5) + r = sendCommand(ser, '\x7e\x01' + "QCOM fast download protocol host" + "\x03\x03\x09", 500, timeout=10000, dwnMode=True) + return r[0x2D:r.find('\x00', 0x2D)] + +def readUnlockCode(ser): + r = sendCommand(ser, '\x05\x00\x00\x00\x00\x00', 500, timeout=10000, dwnMode=True) + return r[1:9] + +def getATAnswer(ser): + s = '' + while 1: + s += ser.read() + if s[len(s)-4:len(s)] == 'OK\r\n': + break + sleep(0.05) + if s.find("ERROR") != -1: + return s + return s.splitlines()[2] + +def checkLockStatus(appPort): + ser = serial.Serial(appPort, 115200, timeout=2) + ser.write('ATE\r\n') + getATAnswer(ser) + + locked = False + locks = [ 'PN', 'PU', 'PC', 'PP', 'PF' ] + for i in locks: + ser.write('AT+CLCK="%s",2\r\n' % i) + response = getATAnswer(ser) + if response.find('+CLCK:') != -1: + if (response.split('+CLCK: ')[1][0] == '1'): + print "Lock %s set" % i + locked = True + else: + print "Lock %s is not set" % i + ser.close() + return locked + +def checkSoftwareVersion(appPort): + ser = serial.Serial(appPort, 115200, timeout=2) + ser.write('AT+GMR\r\n') + response = getATAnswer(ser) + ser.close() + return response + +def unlockModem(appPort, unlockCode): + ser = serial.Serial(appPort, 115200, timeout=5) + locks = [ 'PN', 'PU', 'PC', 'PP', 'PF' ] + result = False + for i in locks: + ser.write('AT+CLCK="%s",2\r\n' % i) + response = getATAnswer(ser) + if response.find('+CLCK:') != -1: + if (response.split('+CLCK: ')[1][0] == '1'): + ser.write('AT+CLCK="%s",0,"%08d"\r\n' % (i, unlockCode)) + response = getATAnswer(ser) + if (response.find('OK') != -1): + print "Disabled %s lock" % i + result = True + ser.close() + return result + +def checkAppPort(port): + try: + ser = serial.Serial(port, 115200, timeout=2) + ser.write('\r\nAT+CGSN\r\n') + response = ser.read(13+28) + result = (response.find("DR") != -1) + ser.close() + except serial.SerialException: + result = False + return result + +def checkDiagPort(port): + try: + ser = serial.Serial(port, 115200, timeout=0) + response = getInfo(ser) + result = (response.find("FUJI_NAN") != -1) + ser.close() + except serial.SerialException: + result = False + return result + +def findSerialPorts(): + appPort = None + diagPort = None + for i in range(0, 255): + port = 'COM%d' % i + if (appPort != None) and (diagPort != None): + break + if appPort == None: + if checkAppPort(port): + appPort = port + continue + if diagPort == None: + if checkDiagPort(port): + diagPort = port + return (appPort, diagPort) + +def info(): + print "msm_unlock.py v1.6" + print "Copyright (c) 2009 dogbert , http://dogber1.blogspot.com" + print "This scripts reads the unlock code of Option 3G modems (Icon 225)." + print "" + +def usage(): + print "Options: -a, --appPort= name of the serial application port (e.g. COM4)" + print " -d, --diagPort= name of the serial diagnostics port (e.g. COM5)." + print "" + print "Example: msm_unlock.py -a COM3 -d COM4" + + +def main(): + info() + try: + opts, args = getopt.getopt(sys.argv[1:], "hd:a:", ["help", "appPort=", "diagPort="]) + except getopt.GetoptError, err: + print str(err) + usage() + sys.exit(2) + + diagPort = None + appPort = None + baud = 115200 + Init = True + + for o, a in opts: + if o in ("-d", "--diagPort"): + diagPort = a + if o in ("-a", "--appPort"): + appPort = a + elif o in ("-h", "--help"): + usage() + sys.exit() + + print "Checking bootloader..." + if not bootloader.getBootloader(): + print "ERROR: The bootloader has not been found. Please place a correct file 'Superfire.exe' in this folder." + if (os.name == 'nt'): + raw_input() + sys.exit(-1) + print "Bootloader OK, proceeding..." + print "" + + if (os.name == 'nt') and ((appPort == None) or (diagPort == None)): + print "Searching for serial ports..." + (appPort, diagPort) = findSerialPorts() + + if appPort == None: + print "Failed to find the application port. Please shutdown the device software." + sys.exit(-1) + + if diagPort == None: + print "Failed to find the diagnostics port. Please shutdown the device software." + sys.exit(-1) + + print "Application serial port: %s" % appPort + print "Diagnostics serial port: %s" % diagPort + print "" + + print "Checking software version..." + checkSoftwareVersion(appPort) + + print "Checking netlock status..." + if not checkLockStatus(appPort): + print "Status of the locks unknown/opened. Proceed? (Y/N)" + if raw_input().lower() != 'y': + sys.exit(0) + else: + print "Netlock active" + print "" + + print "Opening diagnostics port..." + ser = serial.Serial(diagPort, baud, timeout=0) + getInfo(ser) + print "Sending bootloader..." + if not sendBootloader(ser, 'msm6280-patched.bin'): + sys.exit(-1) + print "" + + print "Getting flash type..." + s = testBootloader(ser) + print "Flash type: %s" % s + + print "Reading unlock code..." + unlockCode = readUnlockCode(ser) + print "Unlock code: %s" % unlockCode + ser.close() + print "" + print "Write down the code, close this window and wait 30 seconds. Then apply the unlock code using msm_apply.py..." + raw_input() + print "done." + +if __name__ == "__main__": + main() + diff --git a/patch/make.sh b/patch/make.sh new file mode 100755 index 0000000..67f6197 --- /dev/null +++ b/patch/make.sh @@ -0,0 +1,3 @@ +arm-elf-as -mcpu=arm7tdmi patch.s -o patch.o +arm-elf-ld -Ttext 0x8089e0 -o patch.bin patch.o + diff --git a/patch/patch.bin b/patch/patch.bin new file mode 100755 index 0000000000000000000000000000000000000000..b0c391adc385f95643cf03612f3e006ddb29879f GIT binary patch literal 4047 zcmeH~&ubf35XZkOIZiF7v0Ug65<#U}1j!Do~3*+DjAnriifw%+zUkCQ?%)j$u4qee7&1uHm*;Ib++}!HP_sWL$W;TPP zuXMC*-)I@=miq-0g+Dt*3&rk^Hj+5-(#Y27KRTBAmASU?yScuA?sVTRyX8dr(80v? zSSOW7;g`;l<#l7yOdBZP@9f*1T27nmW^OrctQ%ufxp&8n+zPrg{Vd%JePs9UYTIrW zuR+sJqVV^Q_Fe1k%yu%P<=r<9EzC}j{X9Rt|KZ^jX8zj2(PRht@l5YGWHS^uv5l#u zq0MUZC_dSlAkVEOY1>V^R4N%CU7;rL^3m0xBdUS-(H7+UeyffCgErFp+qiwcjl~Iy z5K>euXx@3XB*}gVIOUX@z(&G7ZC83mURW2*({Fj|POu@XMQM&j%y*mb^ z*%3%O&^gjcpcVT0JROd)FPt*z$Aw`4oz0Iur$HRY^O-%A`~hkTIrw>bO(S%1ep(LK z9mv&#z}c`Ec_Zc^CN%hYSR(%h0#11I!g0>R_5A(eke*9r@HOoV%LI+T>{+yDp7h+; zS@Rxx(sPTfX+J%r`DHR52lctyDdHyqbG{|w*+~8mi0uepAif&mD)Cx`E#eO&+#u%n zh=ucSlIC~Hm!5l#41T{t{*sJ)k@)Mx{OS4RGN(SLJMVkXeKf>RnIrMzwDHmSSBH3Nh-ZfQ_z=$#126E6 z>L+mOAL9ghh33VJj#O)x6gK2WwQgf|arI0^IP%!QIzF(UT-#As5Nz4iW(a9 zwd$6Vwoq2HfsciyU^%OoH!9MG_cH;xNj}fi=^KAub451LvSmxyl2=d_^}23~My*aW z9oeX{lk@ontEQ}8LZhj4p*Q^Wf%2E`N9AkKbt+if)F}h>isP`M>*QwJe*z{y$m3w_ YUvV7e&y_Wy1pJgVg%+ag?DF&B86ad-)Bpeg literal 0 HcmV?d00001 diff --git a/patch/patch.s b/patch/patch.s new file mode 100755 index 0000000..b98e2b5 --- /dev/null +++ b/patch/patch.s @@ -0,0 +1,169 @@ +@ +@ Copyright 2009: dogbert +@ +@ This program is free software; you can redistribute it and/or modify +@ it under the terms of the GNU General Public License as published by +@ the Free Software Foundation; either version 2 of the License, or +@ (at your option) any later version. +@ +@ This program is distributed in the hope that it will be useful, +@ but WITHOUT ANY WARRANTY; without even the implied warranty of +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@ GNU General Public License for more details. +@ +@ You should have received a copy of the GNU General Public License +@ along with this program; if not, write to the Free Software +@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@ + +.align 4 +.thumb_func + + push {r1-r7,lr} +@ memclr(output paket) + ldr r0, =(offsetPkt) + mov r1, #(1+9+2+1) + bl memclr + + mov r1, #6 + str r1, [r0] + + ldr r3,=0x1E00000 @ start address + mov r4, #10 @ timeout + ldr r5,=NANDbase1 + ldr r6,=NANDbase2 + ldr r7,=NANDbase3 +start_loop: + str r3, [r6] + +do_read: + sub r4, r4, #1 + mov r0, r4 + cmp r4, #0 + beq next_iteration + + mov r0, #1 + str r0, [r7,#12] + str r0, [r6,#4] + bl wait + ldr r0, [r5] + cmp r0, #0 + beq do_read + ldr r1, [r5,#16] + cmp r1, #0 + bne do_read + lsl r1, r0, #0x10 + lsr r2, r0, #0x10 + lsl r2, r2, #0x10 + cmp r2, r1 + beq do_read + + ldr r1, [r5,#4] + ldr r2, [r5,#8] + eor r0, r2 + ldr r2, [r5,#12] + eor r1, r2 + bl isNumber +next_iteration: + add r3, #0xFF @ try higher address + add r3, #0xFF + add r3, #2 + lsr r2, r3,#0x18 + cmp r2, #0x2 + beq error + mov r4, #10 + cmp r0, #0 + beq start_loop + + ldr r2, =(offsetPkt+1) + str r1, [r2,#4] + ldr r1, [r2] + str r0, [r2] + cmp r1, #0 + beq do_read + + b exit +error: + ldr r2, =error_str + ldr r0, [r2] + ldr r1, [r2,#4] + ldr r2, =(offsetPkt+1) + str r0, [r2] + str r1, [r2,#4] +exit: + mov r3, #9 + ldr r1, =offsetPktLen + str r3, [r1] + ldr r4, =preparePkt + bl call_handler + ldr r4, =sendPkt + bl call_handler + mov r0, #0 + pop {r1-r7,pc} + +@ wait a couple of cycles +wait: + push {r0} + mov r0, #0xff + add r0, r0, r0 + lsl r0, #4 +wait_loop: + sub r0, r0, #1 + cmp r0, #0 + bne wait_loop + pop {r0} + bx lr + +isNumber: + push {r2-r4} + mov r3, r0 + mov r4,#1 +check: + mov r2, #0xff + and r2, r3 + cmp r2, #0x30 + bcc not_a_number + cmp r2, #0x39 + bhi not_a_number + lsr r3, #8 + cmp r3, #0 + bne check + cmp r4, #0 + beq number + mov r4, #0 + mov r3, r1 + b check +not_a_number: + mov r0, #0 +number: + pop {r2-r4} + bx lr + +@ r0 - offset, r1 - length +memclr: + push {r0-r3} + mov r3, #0 +memclr_loop: + str r3, [r0] + add r0, r0, #1 + sub r1, r1, #1 + cmp r1, #0 + bne memclr_loop + pop {r0-r3} + bx lr + +call_handler: + mov pc, r4 + +@ basic definitions +.equ NANDbase1,0x60000000 +.equ NANDbase2,0x60000300 +.equ NANDbase3,0x80005400 +.equ offsetPkt,0x827160 +.equ offsetPktLen,0x80D6F8 +@ functions +.equ preparePkt,0x800710 +.equ sendPkt,0x8052A8 +@strings +error_str: +.ascii "error..."