My favorites | Sign in
Project Home Downloads Wiki Issues Source
Checkout   Browse   Changes    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import os, zipfile, sys, tempfile, shutil, plistlib, traceback

def recursive_zip(zipf, basePath, zipPath=""):
for fname in os.listdir(os.path.join(basePath, zipPath)):
izPath = os.path.join(zipPath, fname)
iPath = os.path.join(basePath, izPath)
if os.path.isfile(iPath):
zipf.write(iPath, izPath, zipfile.ZIP_DEFLATED)
elif os.path.isdir(iPath):
recursive_zip(zipf, basePath, izPath)

def fix_ramdisk_dict(ramdisks):
ramdisks["User"] = ramdisks["Update"]
del ramdisks["Update"]

def fix_build_manifest(ipswDir):
buildManifestPlist = os.path.join(ipswDir, "BuildManifest.plist")
if not os.path.exists(buildManifestPlist):
print "No BuildManifest file"
return

buildManifest = plistlib.readPlist(buildManifestPlist)

buildIdentities = buildManifest["BuildIdentities"]

assert len(buildIdentities) == 2

restoreIndex = -1
updateIndex = -1

for i in range(len(buildIdentities)):
biInfo = buildIdentities[i]["Info"]
print "Build identity %i: %s" % (i, biInfo["RestoreBehavior"])
if biInfo["RestoreBehavior"] == "Erase":
restoreIndex = i
elif biInfo["RestoreBehavior"] == "Update":
updateIndex = i

assert (restoreIndex + updateIndex == 1)

buildIdentities.pop(restoreIndex)
updateBiInfo = buildIdentities[0]["Info"];

assert "Update" == updateBiInfo["RestoreBehavior"]
updateBiInfo["RestoreBehavior"] = "Erase";

assert "UpdateRamDisk" == updateBiInfo["VariantContents"]["RestoreRamDisk"]
updateBiInfo["VariantContents"]["RestoreRamDisk"] = "CustomerRamDisk"

plistlib.writePlist(buildManifest, buildManifestPlist)

print "Written BuildManifest.plist"


def make_upgrade_only(ipswDir):
restorePlist = os.path.join(ipswDir, "Restore.plist")
restore = plistlib.readPlist(restorePlist)

restoreRamDisks = restore["RestoreRamDisks"]

print "Update RD: %s, restore RD: %s" % (restoreRamDisks["Update"], restoreRamDisks["User"])

updateRamdisk = restoreRamDisks["Update"]
restoreRamdisk = restoreRamDisks["User"]

os.remove(os.path.join(ipswDir, restoreRamdisk))
print "Deleted RESTORE ramdisk file: %s" % restoreRamdisk

fix_ramdisk_dict(restoreRamDisks)

for platformName, platInfo in restore["RamDisksByPlatform"].items():
print "Platform: %s, update RD: %s, restore RD: %s" % (platformName, platInfo["Update"], platInfo["User"])
fix_ramdisk_dict(platInfo)

plistlib.writePlist(restore, restorePlist)
print "Written Restore.plist"

fix_build_manifest(ipswDir)

def has_build_manifest(ipsw):
try:
ipsw.getinfo("BuildManifest.plist")
return True
except KeyError:
return False

def main():
if len(sys.argv) <= 1:
print "Usage: %s <ipsw file>" % sys.argv[0]
return

origIpsw = sys.argv[1]

print "Original IPSW file: %s" % origIpsw
if not zipfile.is_zipfile(origIpsw):
print "Not a valid IPSW file:", origIpsw
return
try:
ipsw = zipfile.ZipFile(origIpsw)
except:
print "Failed to open", origIpsw
return

if not has_build_manifest(ipsw):
print "IPSW for an unsupported device: BuildManifest.plist missing!"
return

tempDir = tempfile.mkdtemp()
print "Unpacking to %s ..." % tempDir
ipsw.extractall(tempDir)
ipsw.close()

make_upgrade_only(tempDir)

newPath = os.path.split(origIpsw)
newIpsw = os.path.join(newPath[0], "UPG_" + newPath[1])
print "Packing upgrade-only IPSW to %s ..." % newIpsw
ipswUp = zipfile.ZipFile(newIpsw, mode='w')
recursive_zip(ipswUp, tempDir)
ipswUp.close()

print "Cleaning up"
shutil.rmtree(tempDir)

if __name__ == '__main__':
try:
main()
print
print "Press Enter to exit."
blah = raw_input()
except:
traceback.print_exc()
print >>sys.stderr
print >>sys.stderr, "Press Enter to exit."
blah = raw_input()

Change log

r22 by msft.guy on Jul 26, 2010   Diff
Initial rev
Go to: 
Project members, sign in to write a code review

Older revisions

All revisions of this file

File info

Size: 4266 bytes, 136 lines
Powered by Google Project Hosting