· 2 years ago · Dec 02, 2022, 06:50 AM
1#!/usr/bin/python
2#===========================================================================
3
4# This script parses "partition.xml" and creates numerous output files
5# specifically, partition.bin, rawprogram.xml
6
7# REFERENCES
8
9# $Header: //components/rel/config.glue/8.0/storage/ptool.py#4 $
10# $DateTime: 2017/04/28 21:47:00 $
11# $Author: pwbldsvc $
12
13# when who what, where, why
14# -------- --- -------------------------------------------------------
15# 2016-04-05 wek Grow the last partition if the configuration option says so.
16# 2015-08-04 wek Bring in multiple changes done to ptool, for example, handle 4k sector size.
17# 2013-04-01 ah Fixed rawprogram0_BLANK.xml to have correct size on last partition if GROW='true'
18# 2012-08-20 ah Allow "uniqueguid" in partition.xml
19# 2012-08-16 ah Fixed bug if PERFORMANCE_BOUNDARY_IN_KB wasn't specified
20# 2012-08-14 ah PERFORMANCE_BOUNDARY_IN_KB can now be an individual partition tag
21# 2012-07-06 ah More user friendly with ShowPartitionExample()
22# 2012-04-30 ah GPT Attributes bits corrected
23# 2012-02-24 ah Much cleaner code - fixes for configurable sector sizes
24# 2012-02-15 ah Minor fix when 'SECTOR_SIZE_IN_BYTES' is not defined
25# 2012-01-13 ah Fixed bug where rawprogram.xml was reporting numsectors off by 1
26# 2011-11-22 ah Added SECTOR_SIZE_IN_BYTES option (defaults to 512)
27# 2011-11-17 ah Added force128 partitions, option -k
28# 2011-11-14 ah Enabled zeroout tag for GPT
29# 2011-10-19 ah Not allowing empty <physical_partition> tags in partition.xml - makes multiple PHY partitions work
30# 2011-09-23 ah GPT num partitions in table not fixed to 128, respecting partition table attributes now
31# 2011-08-12 ah Added ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY, WRITE_PROTECT_GPT_PARTITION_TABLE
32# 2011-08-11 ah Added Unique GUID option or Sequential -g (default is unique)
33# 2011-08-09 ah Fix alignment issue for WPG<64MB - Fixed GPT off by 1 sector issue
34# 2011-08-04 ah Now allowing -t option to specify output directory for files
35# 2011-07-26 ah Much better error message if GUID invalid, fixed 'grow' partition size (patch)
36# 2011-07-21 ah Major revision, using getopt(), auto-discovering GPT or MBR
37# 2011-07-13 ah Corrected sparse support
38# 2011-06-01 ah Added sparse support for GPT - corrected size of last partition
39# 2011-05-26 ah Adds "zeroout" tag (wiping GPT) and "sparse" file support
40# 2011-05-21 ab Undoing hack for boot to wipe out sector 1
41# 2011-05-17 ah removing GPT sectors is simpler now, compatible with 8960 tz.mbn issue
42# 2011-05-06 ah MBR partition tables now nuke any trace of GPT (request from boot team)
43# 2011-04-26 ah temporarily removed 'start_byte_hex':szStartByte for QPST compatibility
44# 2011-03-23 ah ensured last partition is size 0 for rawprogram.xml
45# 2011-03-22 ah rawprogram for GPT for 'grow' partition, since mjsdload.cmm couldn't handle big number
46# 2011-03-22 ah Corrected final disk size patch (off by 1 sector), corrected GPT labels (uni-code)
47# 2011-03-18 ah Fixed default bug for DISK_SIGNATURE, align_wpb -> align
48# 2011-03-16 ah New DISK_SIGNATURE tag added for MBR partitions, Split partition0.bin into
49# MBR0.bin and EBR0.bin, Corrected bug in backup GPT DISK patching
50# 2011-03-10 ah Removes loadpt.cmm, splits partition0.bin to MBR0.bin, EBR0.bin
51# 2011-03-09 ah Much more error checking, cleaner, adds "align_wpb" tag
52# 2011-02-14 ah Added patching of DISK for GPT
53# 2011-02-02 ah Allow MBR Type to be specified as "4C" or "0x4C"
54# 2011-25-01 ah Outputs "patch.xml" as well, allows more optimal partition alignment
55# 2010-12-01 ah Matching QPST, all EXT partitions 64MB aligned (configurable actually)
56# More error checking, Removed CHS option, GPT output is 2 files (primary and backup)
57# 2010-10-26 ah better error checking, corrected typo on physical_partition for > 0
58# 2010-10-25 ah adds GPT, CFILE output, various other features
59# 2010-10-08 ah released to remove compile errors of missing PERL script modules
60
61# Copyright (c) 2007-2016
62# Qualcomm Technologies Incorporated.
63# All Rights Reserved.
64# Qualcomm Confidential and Proprietary
65# ===========================================================================*/
66
67import sys,os,getopt
68import random,math
69import re
70import struct
71from types import *
72from time import sleep
73
74if sys.version_info < (2,5):
75 sys.stdout.write("\n\nERROR: This script needs Python version 2.5 or greater, detected as ")
76 print sys.version_info
77 sys.exit() # error
78
79from xml.etree import ElementTree as ET
80#from elementtree.ElementTree import ElementTree
81from xml.etree.ElementTree import Element, SubElement, Comment, tostring
82from xml.dom import minidom
83
84OutputFolder = ""
85
86LastPartitionBeginsAt = 0
87HashInstructions = {}
88tempVar = 5
89
90NumPhyPartitions = 0
91PartitionCollection = [] # An array of Partition objects. Partition is a hash of information about partition
92PhyPartition = {} # An array of PartitionCollection objects
93
94MinSectorsNeeded = 0
95# Ex. PhyPartition[0] holds the PartitionCollection that holds all the info for partitions in PHY partition 0
96
97AvailablePartitions = {}
98XMLFile = "module_common.py"
99
100ExtendedPartitionBegins= 0
101instructions = []
102HashStruct = {}
103
104StructPartitions = []
105StructAdditionalFields = []
106AllPartitions = {}
107
108PARTITION_SYSTEM_GUID = 0x3BC93EC9A0004BBA11D2F81FC12A7328
109PARTITION_MSFT_RESERVED_GUID= 0xAE1502F02DF97D814DB80B5CE3C9E316
110PARTITION_BASIC_DATA_GUID = 0xC79926B7B668C0874433B9E5EBD0A0A2
111
112SECTOR_SIZE_IN_BYTES = 512 # This can be over ridden in the partition.xml file
113
114PrimaryGPT = [0]*17408 # This gets redefined later based on SECTOR_SIZE_IN_BYTES This is LBA 0 to 33 (34 sectors total) (start of disk)
115BackupGPT = [0]*16896 # This gets redefined later based on SECTOR_SIZE_IN_BYTES This is LBA-33 to -1 (33 sectors total) (end of disk)
116
117EmptyGPT = [0]*17408 # This gets redefined later based on SECTOR_SIZE_IN_BYTES This is LBA 0 to 33 (34 sectors total) (start of disk)
118
119PrimaryGPTNumLBAs=len(PrimaryGPT)/SECTOR_SIZE_IN_BYTES
120BackupGPTNumLBAs =len(BackupGPT)/SECTOR_SIZE_IN_BYTES
121
122## Note that these HashInstructions are updated by the XML file
123
124HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] = 64*1024
125HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = True
126HashInstructions['DISK_SIGNATURE'] = 0x0
127
128MBR = [0]*SECTOR_SIZE_IN_BYTES
129EBR = [0]*SECTOR_SIZE_IN_BYTES
130
131hash_w = [{'start_sector':0,'num_sectors':(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES),
132 'end_sector':(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)-1,'physical_partition_number':0,'boundary_num':0,'num_boundaries_covered':1}]
133NumWPregions = 0
134
135def ShowPartitionExample():
136 print "Your \"partition.xml\" file needs to look like something like this below"
137 print "\t(i.e. notice the *multiple* physical_partition tags)\n"
138 print "<!-- This is physical partition 0 -->"
139 print "<physical_partition>"
140 print " <partition label=\"SBL1\" size_in_kb=\"100\" type=\"DEA0BA2C-CBDD-4805-B4F9-F428251C3E98\" filename=\"sbl1.mbn\"/>"
141 print "</physical_partition>"
142 print " "
143 print "<!-- This is physical partition 1 -->"
144 print "<physical_partition>"
145 print " <partition label=\"SBL2\" size_in_kb=\"200\" type=\"8C6B52AD-8A9E-4398-AD09-AE916E53AE2D\" filename=\"sbl2.mbn\"/>"
146 print "</physical_partition>"
147
148def ConvertKBtoSectors(x):
149 ## 1KB / SECTOR_SIZE_IN_BYTES normally means return 2 (i.e. with SECTOR_SIZE_IN_BYTES=512)
150 ## 2KB / SECTOR_SIZE_IN_BYTES normally means return 4 (i.e. with SECTOR_SIZE_IN_BYTES=512)
151 return int((x*1024)/SECTOR_SIZE_IN_BYTES)
152
153def UpdatePatch(StartSector,ByteOffset,PHYPartition,size_in_bytes,szvalue,szfilename,szwhat):
154 global PatchesXML
155
156 SubElement(PatchesXML, 'patch', {'start_sector':StartSector, 'byte_offset':ByteOffset,
157 'physical_partition_number':str(PHYPartition), 'size_in_bytes':str(size_in_bytes),
158 'value':szvalue, 'filename':szfilename, 'SECTOR_SIZE_IN_BYTES':str(SECTOR_SIZE_IN_BYTES), 'what':szwhat })
159
160
161def UpdateRawProgram(RawProgramXML, StartSector, size_in_KB, PHYPartition, file_sector_offset, num_partition_sectors, filename, sparse, label,readbackverify='false', partofsingleimage='false'):
162 if StartSector<0:
163 szStartSector = "NUM_DISK_SECTORS%d." % StartSector ## as in NUM_DISK_SECTORS-33 since %d=-33
164 szStartByte = "(%d*NUM_DISK_SECTORS)%d." % (SECTOR_SIZE_IN_BYTES,StartSector*SECTOR_SIZE_IN_BYTES)
165 else:
166 #print "\nTo be here means StartSector>0"
167 #print "UpdateRawProgram StartSector=",StartSector
168 #print "StartSector=",type(StartSector)
169 #print "-----------------------------------------"
170
171 szStartByte = str(hex(StartSector*SECTOR_SIZE_IN_BYTES))
172 szStartSector = str(StartSector)
173
174 #import pdb; pdb.set_trace()
175
176 if num_partition_sectors<=0:
177 #print "*"*78
178 #print "WARNING: num_partition_sectors is %d for '%s' PHYPartition=%d, setting it to 0" % (num_partition_sectors,label,PHYPartition)
179 #print "\tThis can happen if you only have 1 partition and thus it is the grow partition"
180 num_partition_sectors = 0
181 size_in_KB = 0
182
183 if erasefirst:
184 if label!="cdt":
185 SubElement(RawProgramXML, 'erase', {'start_sector':szStartSector, 'physical_partition_number':str(PHYPartition),
186 'num_partition_sectors':str(num_partition_sectors), 'filename':filename,
187 'SECTOR_SIZE_IN_BYTES':str(SECTOR_SIZE_IN_BYTES) })
188
189
190 SubElement(RawProgramXML, 'program', {'start_sector':szStartSector, 'size_in_KB':str(size_in_KB), 'physical_partition_number':str(PHYPartition), 'partofsingleimage':partofsingleimage,
191 'file_sector_offset':str(file_sector_offset), 'num_partition_sectors':str(num_partition_sectors), 'readbackverify':readbackverify,
192 'filename':filename, 'sparse':sparse, 'start_byte_hex':szStartByte, 'SECTOR_SIZE_IN_BYTES':str(SECTOR_SIZE_IN_BYTES), 'label':label })
193
194
195 #iter = RawProgramXML.getiterator()
196 #for element in iter:
197 # print "\nElement:" , element.tag, " : ", element.text # thins like image,primary,extended etc
198 # if element.keys():
199 # print "\tAttributes:"
200
201 # for name, value in element.items():
202 # print "\t\tName: '%s'=>'%s' " % (name,value)
203
204
205 #import pdb; pdb.set_trace()
206
207
208
209def PrintBigWarning(sz):
210 print "\t _ "
211 print "\t (_) "
212 print "\t__ ____ _ _ __ _ __ _ _ __ __ _ "
213 print "\t\\ \\ /\\ / / _` | '__| '_ \\| | '_ \\ / _` |"
214 print "\t \\ V V / (_| | | | | | | | | | | (_| |"
215 print "\t \\_/\\_/ \\__,_|_| |_| |_|_|_| |_|\\__, |"
216 print "\t __/ |"
217 print "\t |___/ \n"
218
219 if len(sz)>0:
220 print sz
221
222def ValidGUIDForm(GUID):
223
224 if type(GUID) is not str:
225 GUID = str(GUID)
226
227 print "Testing if GUID=",GUID
228
229 m = re.search("0x([a-fA-F\d]{32})$", GUID) #0xC79926B7B668C0874433B9E5EBD0A0A2
230 if type(m) is not NoneType:
231 return True
232
233 m = re.search("([a-fA-F\d]{8})-([a-fA-F\d]{4})-([a-fA-F\d]{4})-([a-fA-F\d]{2})([a-fA-F\d]{2})-([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})", GUID)
234 if type(m) is not NoneType:
235 return True
236
237 print "GUID does not match regular expression"
238
239 return False
240
241def ValidateTYPE(Type):
242 # for type I must support the original "4C" and if they put "0x4C"
243
244 if type(Type) is int:
245 if Type>=0 and Type<=255:
246 return Type
247
248 if type(Type) is not str:
249 Type = str(Type)
250
251 m = re.search("^(0x)?([a-fA-F\d][a-fA-F\d]?)$", Type)
252 if type(m) is NoneType:
253 print "\tWARNING: Type \"%s\" is not in the form 0x4C" % Type
254 sys.exit(1)
255 else:
256 #print m.group(2)
257 #print "---------"
258 #print "\tType is \"0x%X\"" % Type
259 return int(m.group(2),16)
260
261def ValidateGUID(GUID):
262
263 if type(GUID) is not str:
264 GUID = str(GUID)
265
266 print "Looking to validate GUID=",GUID
267
268 m = re.search("0x([a-fA-F\d]{32})$", GUID) #0xC79926B7B668C0874433B9E5EBD0A0A2
269 if type(m) is not NoneType:
270 tempGUID = int(m.group(1),16)
271 print "\tGUID \"%s\"" % GUID
272
273 if tempGUID == PARTITION_SYSTEM_GUID:
274 print "\tPARTITION_SYSTEM_GUID detected\n"
275 elif tempGUID == PARTITION_MSFT_RESERVED_GUID:
276 print "\tPARTITION_MSFT_RESERVED_GUID detected\n"
277 elif tempGUID == PARTITION_BASIC_DATA_GUID:
278 print "\tPARTITION_BASIC_DATA_GUID detected\n"
279 else:
280 print "\tUNKNOWN PARTITION_GUID detected\n"
281
282 return tempGUID
283
284 else:
285 #ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 --> #0x C7 99 26 B7 B6 68 C087 4433 B9E5 EBD0A0A2
286 m = re.search("([a-fA-F\d]{8})-([a-fA-F\d]{4})-([a-fA-F\d]{4})-([a-fA-F\d]{2})([a-fA-F\d]{2})-([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})", GUID)
287 if type(m) is not NoneType:
288 print "Found more advanced type"
289 tempGUID = (int(m.group(4),16)<<64) | (int(m.group(3),16)<<48) | (int(m.group(2),16)<<32) | int(m.group(1),16)
290 tempGUID|= (int(m.group(8),16)<<96) | (int(m.group(7),16)<<88) | (int(m.group(6),16)<<80) | (int(m.group(5),16)<<72)
291 tempGUID|= (int(m.group(11),16)<<120)| (int(m.group(10),16)<<112)| (int(m.group(9),16)<<104)
292 print "** CONVERTED GUID \"%s\" is FOUND --> 0x%X" % (GUID,tempGUID)
293 return tempGUID
294 else:
295 print "\nWARNING: "+"-"*78
296 print "*"*78
297 print "WARNING: GUID \"%s\" is not in the form ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" % GUID
298 print "*"*78
299 print "WARNING"+"-"*78+"\n"
300 print "Converted to PARTITION_BASIC_DATA_GUID (0xC79926B7B668C0874433B9E5EBD0A0A2)\n"
301 return PARTITION_BASIC_DATA_GUID
302
303def EnsureDirectoryExists(filename):
304 dir = os.path.dirname(filename)
305
306 try:
307 os.stat(dir)
308 except:
309 os.makedirs(dir)
310
311def WriteGPT(GPTMAIN, GPTBACKUP, GPTEMPTY):
312 global opfile,PrimaryGPT,BackupGPT,GPTBOTH
313 #for b in PrimaryGPT:
314 # opfile.write(struct.pack("B", b))
315 #for b in BackupGPT:
316 # opfile.write(struct.pack("B", b))
317
318 ofile = open(GPTMAIN, "wb")
319 for b in PrimaryGPT:
320 ofile.write(struct.pack("B", b))
321 ofile.close()
322
323 print "\nCreated \"%s\"\t\t\t<-- Primary GPT partition tables + protective MBR" % GPTMAIN
324
325 ofile = open(GPTBACKUP, "wb")
326 for b in BackupGPT:
327 ofile.write(struct.pack("B", b))
328 ofile.close()
329
330 print "Created \"%s\"\t\t<-- Backup GPT partition tables" % GPTBACKUP
331
332 ofile = open(GPTBOTH, "wb")
333 for b in PrimaryGPT:
334 ofile.write(struct.pack("B", b))
335 for b in BackupGPT:
336 ofile.write(struct.pack("B", b))
337 ofile.close()
338
339 print "Created \"%s\" \t\t<-- you can run 'perl parseGPT.pl %s'" % (GPTBOTH,GPTBOTH)
340
341 ## EmptyGPT is just all 0's, let's fill in the correct data
342 FillInEmptyGPT()
343
344 ofile = open(GPTEMPTY, "wb")
345 for b in EmptyGPT:
346 ofile.write(struct.pack("B", b))
347 ofile.close()
348
349 print "Created \"%s\"\t\t<-- Empty GPT partition table, use to force EDL mode (very useful)" % GPTEMPTY
350
351def FillInEmptyGPT():
352 global EmptyGPT
353
354 i=SECTOR_SIZE_IN_BYTES+16
355 EmptyGPT[0:i] = PrimaryGPT[0:i] ## this copies up to EFI PART, REVISION and HEADER SIZE
356 EmptyGPT[i:i+4] = [0xD6, 0x51, 0x5B, 0x44] # CRC32
357 i+=8
358 EmptyGPT[i:i+1] = [0x01] # Current LBA
359 i+=16
360 EmptyGPT[i:i+1] = [0x22] # First useable LBA
361 i+=16
362 EmptyGPT[i:i+16] = [0x32, 0x1B, 0x10, 0x98, 0xE2, 0xBB, 0xF2, 0x4B, 0xA0, 0x6E, 0x2B, 0xB3, 0x3D, 0x00, 0x0C, 0x20] # DISK GUID
363 i+=16
364 EmptyGPT[i:i+1] = [0x02] # Starting LBA
365 i+=8
366 EmptyGPT[i:i+16] = [0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x87, 0x5D, 0x3C, 0x00, 0x00, 0x00, 0x00] # Num Entries, Size of Array, CRC
367
368 i=2*SECTOR_SIZE_IN_BYTES+16
369 EmptyGPT[i:i+16] = [0x6B, 0xCA, 0x1F, 0xEF, 0x31, 0x26, 0xC9, 0x95, 0x5C, 0x13, 0x61, 0xEB, 0x3F, 0xCF, 0x87, 0xF9] # unique GUID
370 i+=16
371 EmptyGPT[i:i+1] = [0x22] # first LBA
372 i+=8
373 EmptyGPT[i:i+2] = [0x21, 0x02] # last LBA
374 i+=16
375 EmptyGPT[i:i+9] = [0x65, 0x00, 0x6D, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79] # unicode "empty" partition name
376
377
378
379def UpdatePrimaryGPT(value,length,i):
380 global PrimaryGPT
381 for b in range(length):
382 PrimaryGPT[i] = ((value>>(b*8)) & 0xFF) ; i+=1
383 return i
384
385def UpdateBackupGPT(value,length,i):
386 global BackupGPT
387 for b in range(length):
388 BackupGPT[i] = ((value>>(b*8)) & 0xFF) ; i+=1
389 return i
390
391def ShowBackupGPT(sector):
392 global BackupGPT
393 print "Sector: %d" % sector
394 for j in range(32):
395 for i in range(16):
396 sys.stdout.write("%.2X " % BackupGPT[i+j*16+sector*SECTOR_SIZE_IN_BYTES])
397 print " "
398 print " "
399
400def CreateFileOfZeros(filename,num_sectors):
401
402 try:
403 opfile = open(filename, "w+b")
404 except Exception, x:
405 print "ERROR: Could not create '%s', cwd=%s" % (filename,os.getcwd() )
406 print "REASON: %s" % (x)
407 sys.exit(1)
408
409 temp = [0]*(SECTOR_SIZE_IN_BYTES*num_sectors)
410 zeros = struct.pack("%iB"%(SECTOR_SIZE_IN_BYTES*num_sectors),*temp)
411 try:
412 opfile.write(zeros)
413 except Exception, x:
414 print "ERROR: Could not write zeros to '%s'\nREASON: %s" % (filename,x)
415 sys.exit(1)
416
417 try:
418 opfile.close()
419 except Exception, x:
420 print "\tWARNING: Could not close %s" % filename
421 print "REASON: %s" % (x)
422
423 print "Created \"%s\"\t\t<-- full of binary zeros - used by \"wipe\" rawprogram files" % filename
424
425def CreateErasingRawProgramFiles():
426
427 CreateFileOfZeros("zeros_1sector.bin",1)
428 CreateFileOfZeros("zeros_%dsectors.bin" % BackupGPTNumLBAs,BackupGPTNumLBAs)
429
430 ##import pdb; pdb.set_trace()
431 for i in range(8): # PHY partitions 0 to 7 exist (with 4,5,6,7 as GPPs)
432 if i==3:
433 continue # no such PHY partition as of Feb 23, 2012
434 temp = Element('data')
435 temp.append(Comment('NOTE: This is an ** Autogenerated file **'))
436 temp.append(Comment('NOTE: Sector size is %ibytes'%SECTOR_SIZE_IN_BYTES))
437
438 UpdateRawProgram(temp,0, 0.5, i, 0, 1, "zeros_33sectors.bin", "false", "Overwrite MBR sector")
439 UpdateRawProgram(temp,1, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, i, 0, BackupGPTNumLBAs, "zeros_%dsectors.bin" % BackupGPTNumLBAs, "false", "Overwrite Primary GPT Sectors")
440 UpdateRawProgram(temp,-BackupGPTNumLBAs, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, i, 0, BackupGPTNumLBAs, "zeros_%dsectors.bin" % BackupGPTNumLBAs, "false", "Overwrite Backup GPT Sectors")
441
442 RAW_PROGRAM = '%swipe_rawprogram_PHY%d.xml' % (OutputFolder,i)
443
444 opfile = open(RAW_PROGRAM, "w")
445 opfile.write( prettify(temp) )
446 opfile.close()
447 print "Created \"%s\"\t<-- Used to *wipe/erase* partition information" % RAW_PROGRAM
448
449
450NumPartitions = 0
451SizeOfPartitionArray= 0
452
453def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False):
454 global opfile,PhyPartition,PrimaryGPT,BackupGPT,EmptyGPT,RawProgramXML, GPTMAIN, GPTBACKUP, GPTBOTH, RAW_PROGRAM, PATCHES, PrimaryGPTNumLBAs, BackupGPTNumLBAs
455
456 print "\n\nMaking GUID Partitioning Table (GPT)"
457
458 #PrintBanner("instructions")
459
460 #print "\nGoing through partitions listed in XML file"
461
462 ## Step 2. Move through partitions resizing as needed based on WRITE_PROTECT_BOUNDARY_IN_KB
463
464 #print "\n\n--------------------------------------------------------"
465 #print "This is the order of the partitions"
466 # I most likely need to resize at least one partition below to the WRITE_PROTECT_BOUNDARY_IN_KB boundary
467 #for k in range(len(PhyPartition)):
468
469 k = PhysicalPartitionNumber
470
471 GPTMAIN = '%sgpt_main%d.bin' % (OutputFolder,k)
472 GPTEMPTY = '%sgpt_empty%d.bin' % (OutputFolder,k)
473 GPTBACKUP = '%sgpt_backup%d.bin' % (OutputFolder,k)
474 GPTBOTH = '%sgpt_both%d.bin' % (OutputFolder,k)
475 RAW_PROGRAM = '%srawprogram%d.xml' % (OutputFolder,k)
476 RAW_PROGRAM_WIPE_PARTITIONS = '%srawprogram%d_WIPE_PARTITIONS.xml'% (OutputFolder,k)
477 RAW_PROGRAM_BLANK_GPT = '%srawprogram%d_BLANK_GPT.xml'% (OutputFolder,k)
478 PATCHES = '%spatch%i.xml' % (OutputFolder,k)
479
480 #for k in range(1):
481
482 #PrimaryGPT = [0]*(34*SECTOR_SIZE_IN_BYTES) # This is LBA 0 to 33 (34 sectors total) (start of disk)
483 #BackupGPT = [0]*(33*SECTOR_SIZE_IN_BYTES) # This is LBA-33 to -1 (33 sectors total) (end of disk)
484 if SECTOR_SIZE_IN_BYTES==4096:
485 PrimaryGPT = [0]*(1*SECTOR_SIZE_IN_BYTES+1*SECTOR_SIZE_IN_BYTES+4*SECTOR_SIZE_IN_BYTES)
486 BackupGPT = [0]*(1*SECTOR_SIZE_IN_BYTES+4*SECTOR_SIZE_IN_BYTES)
487 EmptyGPT = [0]*(1*SECTOR_SIZE_IN_BYTES+1*SECTOR_SIZE_IN_BYTES+4*SECTOR_SIZE_IN_BYTES)
488 else:
489 PrimaryGPT = [0]*(34*SECTOR_SIZE_IN_BYTES) # This is LBA 0 to 33 (34 sectors total) (start of disk)
490 BackupGPT = [0]*(33*SECTOR_SIZE_IN_BYTES) # This is LBA-33 to -1 (33 sectors total) (end of disk)
491 EmptyGPT = [0]*(34*SECTOR_SIZE_IN_BYTES) # This is LBA 0 to 33 (34 sectors total) (start of disk)
492
493
494 ## ---------------------------------------------------------------------------------
495 ## Step 2. Move through xml definition and figure out partitions sizes
496 ## ---------------------------------------------------------------------------------
497
498 PrimaryGPTNumLBAs=len(PrimaryGPT)/SECTOR_SIZE_IN_BYTES
499 BackupGPTNumLBAs =len(BackupGPT)/SECTOR_SIZE_IN_BYTES
500 i = 2*SECTOR_SIZE_IN_BYTES ## partition arrays begin here
501
502 if (PhyPartition[0][0]['firstlba']) >= 0:
503 FirstLBA = PhyPartition[0][0]['firstlba']
504 print "\nForcing start LBA to %i" % FirstLBA
505 else:
506 FirstLBA = PrimaryGPTNumLBAs
507 LastLBA = FirstLBA ## Make these equal at first
508
509 if HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] is True:
510 UpdateWPhash(FirstLBA, 0) # make sure 1st write protect boundary is setup correctly
511
512 #print "len(PhyPartition)=%d and k=%d" % (len(PhyPartition),k)
513
514 if(k>=len(PhyPartition)):
515 if UserProvided==True:
516 print "\nERROR: PHY Partition %i of %i not found" % (k,len(PhyPartition))
517 print "\nERROR: PHY Partition %i of %i not found\n\n" % (k,len(PhyPartition))
518 ShowPartitionExample()
519 sys.exit()
520 else:
521 print "\nERROR: PHY Partition %i of %i not found\n\n" % (k,len(PhyPartition))
522 return ## Automatically trying to do 0 to 7, and some don't exist, which is to be expected
523
524 SectorsTillNextBoundary = 0
525
526
527 print "\n\nOn PHY Partition %d that has %d partitions" % (k,len(PhyPartition[k]))
528 for j in range(len(PhyPartition[k])):
529 #print "\nPartition name='%s' (readonly=%s)" % (PhyPartition[k][j]['label'], PhyPartition[k][j]['readonly'])
530 #print "\tat sector location %d (%d KB or %.2f MB) and LastLBA=%d" % (FirstLBA,FirstLBA/2,FirstLBA/2048,LastLBA)
531 #print "%d of %d with label %s" %(j,len(PhyPartition[k]),PhyPartition[k][j]['label'])
532
533 print "\n"+"="*78
534 print " _ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-."
535 print " ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )"
536 print " (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\""
537 print "="*78
538
539 if (PhyPartition[k][j]['firstlba']) >= 0:
540 FirstLBA = PhyPartition[k][j]['firstlba']
541 print "\nForcing start LBA to %i" % FirstLBA
542
543 PhyPartition[k][j]['size_in_kb'] = int(PhyPartition[k][j]['size_in_kb'])
544 print "\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%dMB) (%i sectors with %i bytes/sector)" %(j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'],PhyPartition[k][j]['readonly'],PhyPartition[k][j]['size_in_kb'],PhyPartition[k][j]['size_in_kb']/1024,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),SECTOR_SIZE_IN_BYTES)
545
546 if (PhyPartition[k][j]['size_in_kb']*1024)%SECTOR_SIZE_IN_BYTES>0:
547 ## Have a remainder, need to round up to next full sector
548 TempResult = (PhyPartition[k][j]['size_in_kb']*1024)/SECTOR_SIZE_IN_BYTES
549 TempResult +=1
550 PhyPartition[k][j]['size_in_kb'] = (TempResult * SECTOR_SIZE_IN_BYTES)/1024
551
552 ##import pdb; pdb.set_trace() ## verifying sizes
553
554 if HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']>0 and HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is False:
555 PrintBigWarning("WARNING: HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] is %i KB\n\tbut HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is FALSE!!\n\n" % HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'])
556 PrintBigWarning("WARNING: This means partitions will *NOT* be aligned to a HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] of %i KB !!\n\n" % HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'])
557 print "To correct this, partition.xml should look like this\n"
558 print "\t<parser_instructions>"
559 print "\t\tPERFORMANCE_BOUNDARY_IN_KB = %i" % Partition['PERFORMANCE_BOUNDARY_IN_KB']
560 print "\t\tALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY=true"
561 print "\t</parser_instructions>\n\n"
562
563 if HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is True:
564 ## to be here means this partition *must* be on an ALIGN boundary
565 print "\tAlignment is to %iKB" % PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']
566 SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']) ## hi
567 if SectorsTillNextBoundary>0:
568 print "\tSectorsTillNextBoundary=%d, FirstLBA=%d it needs to be moved to be aligned to %d" % (SectorsTillNextBoundary,FirstLBA,FirstLBA + SectorsTillNextBoundary)
569 ##print "\tPhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']=",PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']
570 FirstLBA += SectorsTillNextBoundary
571 else:
572 if PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']>0:
573 print "\tThis partition is *NOT* aligned to a performance boundary\n"
574
575 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0:
576 SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])
577
578 if PhyPartition[k][j]['readonly']=="true":
579 ## to be here means this partition is read-only, so see if we need to move the start
580 if FirstLBA <= hash_w[NumWPregions]["end_sector"]:
581 print "\tWe *don't* need to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])
582 pass
583 else:
584 print "\tFirstLBA (%d) is *not* covered by the end of the WP region (%d),\n\tit needs to be moved to be aligned to %d" % (FirstLBA,hash_w[NumWPregions]["end_sector"],FirstLBA + SectorsTillNextBoundary)
585 FirstLBA += SectorsTillNextBoundary
586
587 else:
588 print "\n\tThis partition is *NOT* readonly"
589 ## to be here means this partition is writeable, so see if we need to move the start
590 if FirstLBA <= hash_w[NumWPregions]["end_sector"]:
591 print "\tWe *need* to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])
592 print "\nhash_w[NumWPregions]['end_sector']=%i" % hash_w[NumWPregions]["end_sector"];
593 print "FirstLBA=%i\n" %FirstLBA;
594 FirstLBA += SectorsTillNextBoundary
595
596 print "\tFirstLBA is now %d" % (FirstLBA)
597 else:
598 #print "Great, We *don't* need to move FirstLBA (%d) since it's *not* covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])
599 pass
600
601 if (j+1) == len(PhyPartition[k]):
602 print "\nTHIS IS THE *LAST* PARTITION"
603
604 if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True:
605
606 print "\nMeans patching instructions go here"
607
608 PhyPartition[k][j]['size_in_kb'] = 0 # infinite huge
609 print "PhyPartition[k][j]['size_in_kb'] set to 0"
610 SectorsRemaining = BackupGPTNumLBAs
611
612 print "LastLBA=",LastLBA
613 print "FirstLBA=",FirstLBA
614
615 # gpt patch - size of last partition ################################################
616 #StartSector = 2*512+40+j*128 ## i.e. skip sector 0 and 1, then it's offset
617 #ByteOffset = str(StartSector%512)
618 #StartSector = str(int(StartSector / 512))
619
620 StartSector = 40+j*128 ## i.e. skip sector 0 and 1, then it's offset
621 ByteOffset = str(StartSector%SECTOR_SIZE_IN_BYTES)
622 StartSector = str(2+int(StartSector / SECTOR_SIZE_IN_BYTES))
623
624 BackupStartSector = 40+j*128
625 ByteOffset = str(BackupStartSector%SECTOR_SIZE_IN_BYTES)
626 BackupStartSector = int(BackupStartSector / SECTOR_SIZE_IN_BYTES)
627
628 ## gpt patch - main gpt partition array
629 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTMAIN),"Update last partition %d '%s' with actual size in Primary Header." % ((j+1),PhyPartition[k][j]['label']))
630 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update last partition %d '%s' with actual size in Primary Header." % ((j+1),PhyPartition[k][j]['label']))
631
632
633 ## gpt patch - backup gpt partition array
634 UpdatePatch(str(BackupStartSector), ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTBACKUP),"Update last partition %d '%s' with actual size in Backup Header." % ((j+1),PhyPartition[k][j]['label']))
635 UpdatePatch("NUM_DISK_SECTORS-%d." % (BackupGPTNumLBAs-BackupStartSector),ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update last partition %d '%s' with actual size in Backup Header." % ((j+1),PhyPartition[k][j]['label']))
636
637 LastLBA = FirstLBA + ConvertKBtoSectors( PhyPartition[k][j]['size_in_kb'] ) ## increase by num sectors, LastLBA inclusive, so add 1 for size
638 if (j+1) != len(PhyPartition[k]):
639 LastLBA -= 1 # inclusive, meaning 0 to 3 is 4 sectors
640
641 #import pdb; pdb.set_trace()
642
643 print "\n\tAt sector location %d with size %.2f MB (%d sectors) and LastLBA=%d (0x%X)" % (FirstLBA,PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),LastLBA,LastLBA)
644
645 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0:
646 AlignedRemainder = FirstLBA % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'];
647 if AlignedRemainder==0:
648 print "\tWPB: This partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])))
649
650 if PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']>0:
651 AlignedRemainder = FirstLBA % PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'];
652 if AlignedRemainder==0:
653 print "\t"+"-"*78
654 print "\tPERF: This partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'])))
655 print "\t"+"-"*78
656
657 if PhyPartition[k][j]['readonly']=="true":
658 UpdateWPhash(FirstLBA, ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']))
659
660 #print Partition.keys()
661 #print Partition.has_key("label")
662 #print "\tsize %i kB (%.2f MB)" % (PhyPartition[k][j]['size_in_kb'], PhyPartition[k][j]['size_in_kb']/1024)
663
664 PartitionTypeGUID = PhyPartition[k][j]['type']
665 print "\nPartitionTypeGUID\t0x%X" % PartitionTypeGUID
666
667 # If the partition is a multiple of 4, it must start on an LBA boundary of size SECTOR_SIZE_IN_BYTES
668# if j%4==0 :
669# # To be here means the partition number is a multiple of 4, so it must start on
670# # an LBA boundary, i.e. LBA2, LBA3 etc.
671# if i%SECTOR_SIZE_IN_BYTES > 0:
672# print "\tWARNING: Location is %i, need to add %i to offset" % (i, SECTOR_SIZE_IN_BYTES-(i%SECTOR_SIZE_IN_BYTES))
673# i += (SECTOR_SIZE_IN_BYTES-(i%SECTOR_SIZE_IN_BYTES))
674#
675# print "\n==============================================================================="
676# print "This partition array entry (%i) is a multiple of 4 and must begin on a boundary of size %i bytes" % (j,SECTOR_SIZE_IN_BYTES)
677# print "This partition array entry is at LBA%i, absolute byte address %i (0x%X)" % (i/SECTOR_SIZE_IN_BYTES,i,i)
678# print "NOTE: LBA0 is protective MBR, LBA1 is Primary GPT Header, LBA2 beginning of Partition Array"
679# print "===============================================================================\n"
680
681 for b in range(16):
682 PrimaryGPT[i] = ((PartitionTypeGUID>>(b*8)) & 0xFF) ; i+=1
683
684 # Unique Partition GUID
685 if sequentialguid == 1:
686 UniquePartitionGUID = j+1
687 else:
688 if PhyPartition[k][j]['uguid'] != "false":
689 UniquePartitionGUID = PhyPartition[k][j]['uguid']
690 else:
691 UniquePartitionGUID = random.randint(0,2**(128))
692
693 print "UniquePartitionGUID\t0x%X" % UniquePartitionGUID
694
695
696 # This HACK section is for verifying with GPARTED, allowing me to put in
697 # whatever uniqueGUID that program came up with
698
699 #if j==0:
700 # UniquePartitionGUID = 0x373C17CF53BC7FB149B85A927ED24483
701 #elif j==1:
702 # UniquePartitionGUID = 0x1D3C4663FC172F904EC7E0C7A8CF84EC
703 #elif j==2:
704 # UniquePartitionGUID = 0x04A9B2AAEF96DAAE465F429D0EF5C6E2
705 #else:
706 # UniquePartitionGUID = 0x4D82D027725FD3AE46AF1C5A28944977
707
708 for b in range(16):
709 PrimaryGPT[i] = ((UniquePartitionGUID>>(b*8)) & 0xFF) ; i+=1
710
711 # First LBA
712 for b in range(8):
713 PrimaryGPT[i] = ((FirstLBA>>(b*8)) & 0xFF) ; i+=1
714
715 # Last LBA
716 for b in range(8):
717 PrimaryGPT[i] = ((LastLBA>>(b*8)) & 0xFF) ; i+=1
718
719 print "**** FirstLBA=%d and LastLBA=%d and size is %i sectors" % (FirstLBA,LastLBA,LastLBA-FirstLBA+1)
720
721 # Attributes
722 Attributes = 0x0
723 #import pdb; pdb.set_trace()
724
725 if PhyPartition[k][j]['readonly']=="true":
726 Attributes |= 1<<60 ## Bit 60 is read only
727 if PhyPartition[k][j]['hidden']=="true":
728 Attributes |= 1<<62
729 if PhyPartition[k][j]['dontautomount']=="true":
730 Attributes |= 1<<63
731 if PhyPartition[k][j]['system']=="true":
732 Attributes |= 1<<0
733 if PhyPartition[k][j]['tries_remaining']>0:
734 Attributes |= PhyPartition[k][j]['tries_remaining']<<52
735 if PhyPartition[k][j]['priority']>0:
736 Attributes |= PhyPartition[k][j]['priority']<<48
737
738 print "Attributes\t\t0x%X" % Attributes
739
740 ##import pdb; pdb.set_trace()
741
742 for b in range(8):
743 PrimaryGPT[i] = ((Attributes>>(b*8)) & 0xFF) ; i+=1
744
745 if len(PhyPartition[k][j]['label'])>36:
746 print "Label %s is more than 36 characters, therefore it's truncated" % PhyPartition[k][j]['label']
747 PhyPartition[k][j]['label'] = PhyPartition[k][j]['label'][0:36]
748
749 #print "LABEL %s and i=%i" % (PhyPartition[k][j]['label'],i)
750 # Partition Name
751 for b in PhyPartition[k][j]['label']:
752 PrimaryGPT[i] = ord(b) ; i+=1
753 PrimaryGPT[i] = 0x00 ; i+=1
754
755 for b in range(36-len(PhyPartition[k][j]['label'])):
756 PrimaryGPT[i] = 0x00 ; i+=1
757 PrimaryGPT[i] = 0x00 ; i+=1
758
759 #for b in range(2):
760 # PrimaryGPT[i] = 0x00 ; i+=1
761 #for b in range(70):
762 # PrimaryGPT[i] = 0x00 ; i+=1
763
764 ##FileToProgram = ""
765 ##FileOffset = 0
766 PartitionLabel = ""
767
768 ## Default for each partition is no file
769 FileToProgram = [""]
770 FileOffset = [0]
771 FilePartitionOffset = [0]
772 FileAppsbin = ["false"]
773 FileSparse = ["false"]
774
775 if 'filename' in PhyPartition[k][j]:
776 ##print "filename exists"
777 #print PhyPartition[k][j]['filename']
778 #print FileToProgram[0]
779
780 # These are all the default values that should be there, including an empty string possibly for filename
781 FileToProgram[0] = PhyPartition[k][j]['filename'][0]
782 FileOffset[0] = PhyPartition[k][j]['fileoffset'][0]
783 FilePartitionOffset[0] = PhyPartition[k][j]['filepartitionoffset'][0]
784 FileAppsbin[0] = PhyPartition[k][j]['appsbin'][0]
785 FileSparse[0] = PhyPartition[k][j]['sparse'][0]
786
787 for z in range(1,len(PhyPartition[k][j]['filename'])):
788 FileToProgram.append( PhyPartition[k][j]['filename'][z] )
789 FileOffset.append( PhyPartition[k][j]['fileoffset'][z] )
790 FilePartitionOffset.append( PhyPartition[k][j]['filepartitionoffset'][z] )
791 FileAppsbin.append( PhyPartition[k][j]['appsbin'][z] )
792 FileSparse.append( PhyPartition[k][j]['sparse'][z] )
793
794 #print PhyPartition[k][j]['fileoffset']
795
796
797 #for z in range(len(FileToProgram)):
798 # print "FileToProgram[",z,"]=",FileToProgram[z]
799 # print "FileOffset[",z,"]=",FileOffset[z]
800 # print " "
801
802
803 if 'label' in PhyPartition[k][j]:
804 PartitionLabel = PhyPartition[k][j]['label']
805
806 for z in range(len(FileToProgram)):
807 #print "===============================%i of %i===========================================" % (z,len(FileToProgram))
808 #print "File: ",FileToProgram[z]
809 #print "Label: ",FileToProgram[z]
810 #print "FilePartitionOffset[z]=",FilePartitionOffset[z]
811 #print "UpdateRawProgram(RawProgramXML,",(FirstLBA+FilePartitionOffset[z]),",",((LastLBA-FirstLBA)*SECTOR_SIZE_IN_BYTES/1024.0),",",PhysicalPartitionNumber,",",FileOffset[z],",",(LastLBA-FirstLBA-FilePartitionOffset[z]),",",(FileToProgram[z]),",", PartitionLabel,")"
812 #print "LastLBA=",LastLBA
813 #print "FirstLBA=",FirstLBA
814 #print "FilePartitionOffset[z]=",FilePartitionOffset[z]
815 UpdateRawProgram(RawProgramXML,
816 FirstLBA+FilePartitionOffset[z], # Start sector
817 ((LastLBA-FirstLBA+1))*SECTOR_SIZE_IN_BYTES/1024.0, # Size in KB
818 PhysicalPartitionNumber,
819 FileOffset[z],
820 LastLBA-FirstLBA+1 - FilePartitionOffset[z], # num_partition_sectors
821 FileToProgram[z],
822 FileSparse[z],
823 PartitionLabel,
824 PhyPartition[k][j]['readbackverify'],
825 PhyPartition[k][j]['partofsingleimage'])
826 if (j+1) == len(PhyPartition[k]):
827 ## last partition, and if GROW was set to True, it will only have a size of 0
828 UpdateRawProgram(RawProgramXML_Wipe,
829 FirstLBA+FilePartitionOffset[z], #Start Sector
830 (ConvertKBtoSectors(PhyPartition[k][j]['original_size_in_kb'])+(LastLBA-FirstLBA)+1)*SECTOR_SIZE_IN_BYTES/1024.0, # Size in KB
831 PhysicalPartitionNumber,
832 FileOffset[z],
833 ConvertKBtoSectors(PhyPartition[k][j]['original_size_in_kb'])+LastLBA-FirstLBA+1-FilePartitionOffset[z],
834 "zeros_33sectors.bin",
835 "false",
836 PartitionLabel,
837 PhyPartition[k][j]['readbackverify'],
838 PhyPartition[k][j]['partofsingleimage'])
839 else:
840 UpdateRawProgram(RawProgramXML_Wipe,
841 FirstLBA+FilePartitionOffset[z], # Start Sector
842 ((LastLBA-FirstLBA)+1)*SECTOR_SIZE_IN_BYTES/1024.0, # Size in KB
843 PhysicalPartitionNumber,
844 FileOffset[z],
845 LastLBA-FirstLBA+1-FilePartitionOffset[z], # num_partition_sectors
846 "zeros_33sectorS.bin",
847 "false",
848 PartitionLabel,
849 PhyPartition[k][j]['readbackverify'],
850 PhyPartition[k][j]['partofsingleimage'])
851
852 if j==0:
853 UpdateRawProgram(RawProgramXML_Blank,0, 33*SECTOR_SIZE_IN_BYTES/1024.0, PhysicalPartitionNumber, FileOffset[z], 33, "gpt_empty%d.bin" % k, "false", "PrimaryGPT", "false", "false")
854
855
856 LastLBA += 1 ## move to the next free sector, also, 0 to 9 inclusive means it's 10
857 ## so below (LastLBA-FirstLBA) must = 10
858
859 FirstLBA = LastLBA # getting ready for next partition, FirstLBA is now where we left off
860
861
862 ## Still working on *this* PHY partition
863
864 ## making protective MBR, all zeros in buffer up until 0x1BE
865
866 i = 0x1BE
867
868 PrimaryGPT[i+0] = 0x00 # not bootable
869 PrimaryGPT[i+1] = 0x00 # head
870 PrimaryGPT[i+2] = 0x01 # sector
871 PrimaryGPT[i+3] = 0x00 # cylinder
872 PrimaryGPT[i+4] = 0xEE # type
873 PrimaryGPT[i+5] = 0xFF # head
874 PrimaryGPT[i+6] = 0xFF # sector
875 PrimaryGPT[i+7] = 0xFF # cylinder
876 PrimaryGPT[i+8:i+8+4] = [0x01,0x00,0x00,0x00] # starting sector
877 PrimaryGPT[i+12:i+12+4] = [0xFF,0xFF,0xFF,0xFF] # starting sector
878
879 PrimaryGPT[440] = (HashInstructions['DISK_SIGNATURE']>>24)&0xFF
880 PrimaryGPT[441] = (HashInstructions['DISK_SIGNATURE']>>16)&0xFF
881 PrimaryGPT[442] = (HashInstructions['DISK_SIGNATURE']>>8)&0xFF
882 PrimaryGPT[443] = (HashInstructions['DISK_SIGNATURE'])&0xFF
883
884 PrimaryGPT[510:512] = [0x55,0xAA] # magic byte for MBR partitioning - always at this location regardless of SECTOR_SIZE_IN_BYTES
885
886 i = SECTOR_SIZE_IN_BYTES
887 ## Signature and Revision and HeaderSize i.e. "EFI PART" and 00 00 01 00 and 5C 00 00 00
888 PrimaryGPT[i:i+16] = [0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54, 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00] ; i+=16
889
890 PrimaryGPT[i:i+4] = [0x00, 0x00, 0x00, 0x00] ; i+=4 ## CRC is zeroed out till calculated later
891 PrimaryGPT[i:i+4] = [0x00, 0x00, 0x00, 0x00] ; i+=4 ## Reserved, set to 0
892
893 CurrentLBA= 1 ; i = UpdatePrimaryGPT(CurrentLBA,8,i)
894 BackupLBA = 0 ; i = UpdatePrimaryGPT(BackupLBA,8,i)
895 FirstLBA = len(PrimaryGPT)/SECTOR_SIZE_IN_BYTES ; i = UpdatePrimaryGPT(FirstLBA,8,i)
896 LastLBA = 0 ; i = UpdatePrimaryGPT(LastLBA,8,i)
897
898 ##print "\n\nBackup GPT is at sector %i" % BackupLBA
899 ##print "Last Usable LBA is at sector %i" % (LastLBA)
900
901 DiskGUID = random.randint(0,2**(128))
902 i = UpdatePrimaryGPT(DiskGUID,16,i)
903
904 PartitionsLBA = 2 ; i = UpdatePrimaryGPT(PartitionsLBA,8,i)
905 NumPartitions = (SECTOR_SIZE_IN_BYTES/128)*int(len(PhyPartition[k])/(SECTOR_SIZE_IN_BYTES/128)) # Want a multiple of (SECTOR_SIZE_IN_BYTES) to fill the sector (avoids gdisk warning)
906 if (len(PhyPartition[k])%(SECTOR_SIZE_IN_BYTES/128))>0:
907 NumPartitions+=(SECTOR_SIZE_IN_BYTES/128)
908
909 if force128partitions == 1:
910 print "\n\nGPT table will list 128 partitions instead of ",NumPartitions
911 print "This makes the output compatible with some older test utilities"
912 NumPartitions = 128
913
914 i = UpdatePrimaryGPT(NumPartitions,4,i) ## (offset 80) Number of partition entries
915 ##NumPartitions = 8 ; i = UpdatePrimaryGPT(NumPartitions,4,i) ## (offset 80) Number of partition entries
916 SizeOfPartitionArray = 128 ; i = UpdatePrimaryGPT(SizeOfPartitionArray,4,i) ## (offset 84) Size of partition entries
917
918 ## Now I can calculate the partitions CRC
919 print "\n\nCalculating CRC with NumPartitions=%i, SizeOfPartitionArray=%i (bytes each) TOTAL LENGTH %d" % (NumPartitions,SizeOfPartitionArray,NumPartitions*SizeOfPartitionArray);
920 ##PartitionsCRC = CalcCRC32(PrimaryGPT[1024:],NumPartitions*SizeOfPartitionArray) ## Each partition entry is 128 bytes
921
922
923 PartitionsPerSector = SECTOR_SIZE_IN_BYTES/128 ## 128 bytes per partition
924
925 if NumPartitions>PartitionsPerSector:
926 SectorsToCalculateCRCOver = NumPartitions/PartitionsPerSector
927 if NumPartitions%PartitionsPerSector:
928 SectorsToCalculateCRCOver+=1
929 else:
930 SectorsToCalculateCRCOver = 1
931
932 PartitionsCRC = CalcCRC32(PrimaryGPT[(2*SECTOR_SIZE_IN_BYTES):],SectorsToCalculateCRCOver * SECTOR_SIZE_IN_BYTES) ## NAND HACK
933
934
935 i = UpdatePrimaryGPT(PartitionsCRC,4,i)
936 print "\n\nCalculated PARTITION CRC is 0x%.8X" % PartitionsCRC
937
938 ## gpt patch - main gpt header - last useable lba
939 ByteOffset = str(48)
940 StartSector = str(1)
941 BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32)
942 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTMAIN), "Update Primary Header with LastUseableLBA.")
943 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update Primary Header with LastUseableLBA.")
944
945 UpdatePatch(BackupStartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTBACKUP), "Update Backup Header with LastUseableLBA.")
946 UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update Backup Header with LastUseableLBA.")
947
948 # gpt patch - location of backup gpt header ##########################################
949 ByteOffset = str(32)
950 StartSector = str(1)
951 ## gpt patch - main gpt header
952 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.",os.path.basename(GPTMAIN), "Update Primary Header with BackupGPT Header Location.")
953 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.","DISK", "Update Primary Header with BackupGPT Header Location.")
954
955 # gpt patch - currentLBA backup header ##########################################
956 ByteOffset = str(24)
957 BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32)
958 ## gpt patch - main gpt header
959 UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.",os.path.basename(GPTBACKUP), "Update Backup Header with CurrentLBA.")
960 UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.","DISK", "Update Backup Header with CurrentLBA.")
961
962 # gpt patch - location of backup gpt header ##########################################
963 ByteOffset = str(72)
964 BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32)
965
966 ## gpt patch - main gpt header
967 UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % BackupGPTNumLBAs,os.path.basename(GPTBACKUP), "Update Backup Header with Partition Array Location.")
968 UpdatePatch("NUM_DISK_SECTORS-1",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % BackupGPTNumLBAs,"DISK", "Update Backup Header with Partition Array Location.")
969
970 # gpt patch - Partition Array CRC ################################################
971 ByteOffset = str(88)
972 StartSector = str(1)
973 BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32)
974
975 ## gpt patch - main gpt header
976 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(2,%d)" % (NumPartitions*SizeOfPartitionArray),os.path.basename(GPTMAIN), "Update Primary Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes)
977 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(2,%d)" % (NumPartitions*SizeOfPartitionArray),"DISK", "Update Primary Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes)
978
979 ## gpt patch - backup gpt header
980 UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,4,"CRC32(0,%d)" % (NumPartitions*SizeOfPartitionArray),os.path.basename(GPTBACKUP), "Update Backup Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes)
981 UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,4,"CRC32(NUM_DISK_SECTORS-%d.,%d)" % (BackupGPTNumLBAs,NumPartitions*SizeOfPartitionArray),"DISK", "Update Backup Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes)
982
983 #print "\nNeed to patch PARTITION ARRAY, @ sector 1, byte offset 88, size=4 bytes, CRC32(2,33)"
984 #print "\nNeed to patch PARTITION ARRAY, @ sector -1, byte offset 88, size=4 bytes, CRC32(2,33)"
985
986 ## Now I can calculate the Header CRC
987 ##print "\nCalculating CRC for Primary Header"
988 CalcHeaderCRC = CalcCRC32(PrimaryGPT[SECTOR_SIZE_IN_BYTES:],92)
989 UpdatePrimaryGPT(CalcHeaderCRC,4,SECTOR_SIZE_IN_BYTES+16)
990 #print "\n\nCalculated HEADER CRC is 0x%.8X" % CalcHeaderCRC
991
992 #print "\nNeed to patch GPT HEADERS in 2 places"
993 #print "\nNeed to patch CRC HEADER, @ sector 1, byte offset 16, size=4 bytes, CRC32(1,1)"
994 #print "\nNeed to patch CRC HEADER, @ sector -1, byte offset 16, size=4 bytes, CRC32(1,1)"
995
996 # gpt patch - Header CRC ################################################
997 ByteOffset = str(16)
998 StartSector = str(1)
999 BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32)
1000
1001 ## gpt patch - main gpt header
1002 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"0",os.path.basename(GPTMAIN), "Zero Out Header CRC in Primary Header.") # zero out old CRC first
1003 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(1,92)",os.path.basename(GPTMAIN), "Update Primary Header with CRC of Primary Header.") # CRC32(start_sector:num_bytes)
1004
1005 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"0", "DISK", "Zero Out Header CRC in Primary Header.") # zero out old CRC first
1006 UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(1,92)","DISK", "Update Primary Header with CRC of Primary Header.") # CRC32(start_sector:num_bytes)
1007
1008 ## gpt patch - backup gpt header
1009 #import pdb; pdb.set_trace()
1010 UpdatePatch(BackupStartSector,ByteOffset,PhysicalPartitionNumber,4,"0",os.path.basename(GPTBACKUP), "Zero Out Header CRC in Backup Header.") # zero out old CRC first
1011 UpdatePatch(BackupStartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(%s,92)" % BackupStartSector,os.path.basename(GPTBACKUP), "Update Backup Header with CRC of Backup Header.") # CRC32(start_sector:num_bytes)
1012
1013 UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,4,"0", "DISK", "Zero Out Header CRC in Backup Header.") # zero out old CRC first
1014 UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,4,"CRC32(NUM_DISK_SECTORS-1.,92)","DISK", "Update Backup Header with CRC of Backup Header.") # CRC32(start_sector:num_bytes)
1015
1016 ## now create the backup GPT partitions
1017 BackupGPT = [0xFF]*(BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES)
1018 BackupGPT[0:] = PrimaryGPT[2*SECTOR_SIZE_IN_BYTES:]
1019
1020 ## now create the backup GPT header
1021
1022 BackupGPT[(BackupGPTNumLBAs-1)*SECTOR_SIZE_IN_BYTES:BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES]= PrimaryGPT[1*SECTOR_SIZE_IN_BYTES:2*SECTOR_SIZE_IN_BYTES] ##BackupGPTNumLBAs=33
1023 #ShowBackupGPT(32)
1024
1025 ## Need to update CurrentLBA, BackupLBA and then recalc CRC for this header
1026
1027 i = (BackupGPTNumLBAs-1)*SECTOR_SIZE_IN_BYTES+8+4+4
1028 CalcHeaderCRC = 0 ; i = UpdateBackupGPT(CalcHeaderCRC,4,i) ## zero out CRC
1029 CalcHeaderCRC = 0 ; i = UpdateBackupGPT(CalcHeaderCRC,4,i) ## reserved 4 zeros
1030 CurrentLBA = 0 ; i = UpdateBackupGPT(CurrentLBA,8,i)
1031 BackupLBA = 1 ; i = UpdateBackupGPT(BackupLBA,8,i)
1032
1033 #print "\n\nBackup GPT is at sector %i" % CurrentLBA
1034 #print "Last Usable LBA is at sector %i" % (CurrentLBA-33)
1035
1036 i += 8+8+16
1037 PartitionsLBA = 0 ; i = UpdateBackupGPT(PartitionsLBA,8,i)
1038 #print "PartitionsLBA = %d (0x%X)" % (PartitionsLBA,PartitionsLBA)
1039
1040 ##print "\nCalculating CRC for Backup Header"
1041 CalcHeaderCRC = CalcCRC32(BackupGPT[(BackupGPTNumLBAs-1)*SECTOR_SIZE_IN_BYTES:],92)
1042 #print "\nCalcHeaderCRC of BackupGPT is 0x%.8X" % CalcHeaderCRC
1043 i = (BackupGPTNumLBAs-1)*SECTOR_SIZE_IN_BYTES+8+4+4
1044 i = UpdateBackupGPT(CalcHeaderCRC,4,i) ## zero out CRC
1045
1046 #ShowBackupGPT(32)
1047
1048 UpdateRawProgram(RawProgramXML,0, PrimaryGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, PhysicalPartitionNumber, 0, PrimaryGPTNumLBAs, os.path.basename(GPTMAIN), 'false', 'PrimaryGPT','false','true')
1049 UpdateRawProgram(RawProgramXML_Wipe,0, 1*SECTOR_SIZE_IN_BYTES/1024.0, PhysicalPartitionNumber, 0, 1, "zeros_33sectors.bin", 'false', 'PrimaryGPT','false','true')
1050 UpdateRawProgram(RawProgramXML_Wipe,1, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, PhysicalPartitionNumber, 0, BackupGPTNumLBAs, "zeros_%dsectors.bin" % BackupGPTNumLBAs, 'false', 'PrimaryGPT','false','true')
1051
1052 #print "szStartSector=%s" % szStartSector
1053
1054 UpdateRawProgram(RawProgramXML,-BackupGPTNumLBAs, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, PhysicalPartitionNumber, 0, BackupGPTNumLBAs, os.path.basename(GPTBACKUP), 'false', 'BackupGPT','false','true')
1055 UpdateRawProgram(RawProgramXML_Wipe,-BackupGPTNumLBAs, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, PhysicalPartitionNumber, 0, BackupGPTNumLBAs, "zeros_%dsectors.bin" % BackupGPTNumLBAs, 'false', 'BackupGPT','false','true')
1056
1057
1058 ##print "szStartSector=%s" % szStartSector
1059
1060
1061 WriteGPT(GPTMAIN, GPTBACKUP, GPTEMPTY)
1062
1063 opfile = open(RAW_PROGRAM, "w")
1064 opfile.write( prettify(RawProgramXML) )
1065 opfile.close()
1066 print "\nCreated \"%s\"\t\t\t<-- YOUR partition information is HERE" % RAW_PROGRAM
1067
1068 opfile = open(RAW_PROGRAM_WIPE_PARTITIONS, "w")
1069 opfile.write( prettify(RawProgramXML_Wipe) )
1070 opfile.close()
1071 print "Created \"%s\"\t<-- Wipe out your images with this file (if needed for testing)" % RAW_PROGRAM_WIPE_PARTITIONS
1072
1073 opfile = open(RAW_PROGRAM_BLANK_GPT, "w")
1074 opfile.write( prettify(RawProgramXML_Blank) )
1075 opfile.close()
1076 print "Created \"%s\"\t\t<-- Valid empty GPT partition table (to force to EDL)" % RAW_PROGRAM_BLANK_GPT
1077
1078 opfile = open(PATCHES, "w") # gpt
1079 opfile.write( prettify(PatchesXML) )
1080 opfile.close()
1081 print "Created \"%s\"\t\t\t\t<-- Tailor your partition tables to YOUR device with this file\n" % PATCHES
1082
1083
1084
1085def AlignVariablesToEqualSigns(sz):
1086 temp = re.sub(r"(\t| )+=","=",sz)
1087 temp = re.sub(r"=(\t| )+","=",temp)
1088 return temp
1089
1090def ReturnArrayFromSpaceSeparatedList(sz):
1091 temp = re.sub(r"\s+|\n"," ",sz)
1092 temp = re.sub(r"^\s+","",temp)
1093 temp = re.sub(r"\s+$","",temp)
1094 return temp.split(' ')
1095
1096def ParseXML(XMLFile):
1097 global OutputToCreate,NumPhyPartitions, PartitionCollection, PhyPartition,MinSectorsNeeded,SECTOR_SIZE_IN_BYTES
1098
1099
1100 root = ET.parse( XMLFile )
1101
1102 #Create an iterator
1103 iter = root.getiterator()
1104
1105 for element in iter:
1106 #print "\nElement:" , element.tag # thins like image,primary,extended etc
1107
1108 if element.tag=="parser_instructions":
1109 instructions = ReturnArrayFromSpaceSeparatedList(AlignVariablesToEqualSigns(element.text))
1110
1111 for element in instructions:
1112 temp = element.split('=')
1113 if len(temp) > 1:
1114 HashInstructions[temp[0].strip()] = temp[1].strip()
1115 #print "HashInstructions['%s'] = %s" % (temp[0].strip(),temp[1].strip())
1116
1117
1118 if 'SECTOR_SIZE_IN_BYTES' in HashInstructions:
1119 if type(HashInstructions['SECTOR_SIZE_IN_BYTES']) is str:
1120 m = re.search("^(\d+)$", HashInstructions['SECTOR_SIZE_IN_BYTES'])
1121 if type(m) is NoneType:
1122 ## we didn't match, so assign deafult
1123 HashInstructions['SECTOR_SIZE_IN_BYTES'] = 512
1124 SECTOR_SIZE_IN_BYTES = 512
1125 else:
1126 HashInstructions['SECTOR_SIZE_IN_BYTES'] = int(HashInstructions['SECTOR_SIZE_IN_BYTES'])
1127 SECTOR_SIZE_IN_BYTES = HashInstructions['SECTOR_SIZE_IN_BYTES']
1128
1129 PrintBigWarning("WARNING: SECTOR_SIZE_IN_BYTES CHANGED <-- This may impact your targets ability to read the partition tables!!")
1130 print "\n\nWARNING: SECTOR_SIZE_IN_BYTES *changed* from 512bytes/sector to %ibytes/sector" % SECTOR_SIZE_IN_BYTES
1131 print "WARNING: SECTOR_SIZE_IN_BYTES *changed* from 512bytes/sector to %ibytes/sector" % SECTOR_SIZE_IN_BYTES
1132 print "WARNING: SECTOR_SIZE_IN_BYTES *changed* from 512bytes/sector to %ibytes/sector\n\n" % SECTOR_SIZE_IN_BYTES
1133 sleep(2)
1134 else:
1135 #print "SECTOR_SIZE_IN_BYTES does not exist"
1136 HashInstructions['SECTOR_SIZE_IN_BYTES'] = 512
1137
1138
1139 if 'WRITE_PROTECT_BOUNDARY_IN_KB' in HashInstructions:
1140 if type(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']) is str:
1141 m = re.search("^(\d+)$", HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])
1142 if type(m) is NoneType:
1143 ## we didn't match, so assign deafult
1144 HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] = 0
1145 else:
1146 HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] = int(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])
1147 else:
1148 #print "WRITE_PROTECT_BOUNDARY_IN_KB does not exist"
1149 HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] = 65536
1150
1151 if 'PERFORMANCE_BOUNDARY_IN_KB' in HashInstructions:
1152 if type(HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']) is str:
1153 m = re.search("^(\d+)$", HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'])
1154 if type(m) is NoneType:
1155 ## we didn't match, so assign deafult
1156 HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] = 0
1157 else:
1158 HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] = int(HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'])
1159 else:
1160 #print "PERFORMANCE_BOUNDARY_IN_KB does not exist"
1161 HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] = 0
1162
1163 if 'GROW_LAST_PARTITION_TO_FILL_DISK' in HashInstructions:
1164 if type(HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']) is str:
1165 m = re.search("^(true)$", HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] ,re.IGNORECASE)
1166 #print type(m)
1167 if type(m) is NoneType:
1168 HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = False # no match
1169 #print "assigned false"
1170 else:
1171 HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = True # matched string true
1172 #print "assigned true"
1173 else:
1174 HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = False
1175
1176 if 'WRITE_PROTECT_GPT_PARTITION_TABLE' in HashInstructions:
1177 if type(HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE']) is str:
1178 m = re.search("^(true)$", HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] ,re.IGNORECASE)
1179 #print type(m)
1180 if type(m) is NoneType:
1181 HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] = False # no match
1182 #print "assigned false"
1183 else:
1184 HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] = True # matched string true
1185 #print "assigned true"
1186 else:
1187 HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] = False
1188
1189 if 'ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY' in HashInstructions:
1190 if type(HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY']) is str:
1191 m = re.search("^(true)$", HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] ,re.IGNORECASE)
1192 #print type(m)
1193 if type(m) is NoneType:
1194 HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] = False # no match
1195 #print "assigned false"
1196 else:
1197 HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] = True # matched string true
1198 #print "assigned true"
1199 else:
1200 HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] = False
1201
1202 if 'USE_GPT_PARTITIONING' in HashInstructions:
1203 if type(HashInstructions['USE_GPT_PARTITIONING']) is str:
1204 m = re.search("^(true)$", HashInstructions['USE_GPT_PARTITIONING'] ,re.IGNORECASE)
1205 #print type(m)
1206 if type(m) is NoneType:
1207 HashInstructions['USE_GPT_PARTITIONING'] = False # no match
1208 #print "assigned false"
1209 else:
1210 HashInstructions['USE_GPT_PARTITIONING'] = True # matched string true
1211 #print "assigned true"
1212 else:
1213 HashInstructions['USE_GPT_PARTITIONING'] = False
1214
1215
1216 if 'DISK_SIGNATURE' in HashInstructions:
1217 if type(HashInstructions['DISK_SIGNATURE']) is str:
1218 m = re.search("^0x([\da-fA-F]+)$", HashInstructions['DISK_SIGNATURE'])
1219 if type(m) is NoneType:
1220 print "WARNING: DISK_SIGNATURE is not formed correctly, expected format is 0x12345678\n"
1221 HashInstructions['DISK_SIGNATURE'] = 0x00000000
1222 else:
1223 HashInstructions['DISK_SIGNATURE'] = int(HashInstructions['DISK_SIGNATURE'],16)
1224 else:
1225 print "DISK_SIGNATURE does not exist"
1226 HashInstructions['DISK_SIGNATURE'] = 0x00000000
1227
1228 if 'ALIGN_BOUNDARY_IN_KB' in HashInstructions:
1229 if type(HashInstructions['ALIGN_BOUNDARY_IN_KB']) is str:
1230 m = re.search("^(\d+)$", HashInstructions['ALIGN_BOUNDARY_IN_KB'])
1231 if type(m) is NoneType:
1232 ## we didn't match, so assign deafult
1233 HashInstructions['ALIGN_BOUNDARY_IN_KB'] = HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']
1234 else:
1235 HashInstructions['ALIGN_BOUNDARY_IN_KB'] = int(HashInstructions['ALIGN_BOUNDARY_IN_KB'])
1236 else:
1237 #print "ALIGN_BOUNDARY_IN_KB does not exist"
1238 HashInstructions['ALIGN_BOUNDARY_IN_KB'] = HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249 root = ET.parse( XMLFile )
1250
1251 #Create an iterator
1252 iter = root.getiterator()
1253
1254 ## Need to count how many partitions
1255 CheckPartitionCount = [0,0,0,0,0,0,0,0]
1256 CurrentPartition = -1
1257
1258 for element in iter:
1259 ##print "\nElement:" , element.tag # thins like image,primary,extended etc
1260 if element.tag == "physical_partition":
1261 CurrentPartition+=1
1262 #print "Now on CurrentPartition=",CurrentPartition
1263 if element.tag == "partition":
1264 CheckPartitionCount[CurrentPartition] += 1
1265 #print "CheckPartitionCount[%d]=%d" % (CurrentPartition,CheckPartitionCount[CurrentPartition])
1266
1267 for p in range(CurrentPartition+1):
1268 print "CheckPartitionCount[%d]=%d" % (p,CheckPartitionCount[p])
1269
1270 CurrentPartition = -1
1271 for element in iter:
1272 #print "\nElement:" , element.tag # thins like image,primary,extended etc
1273
1274 if element.tag=="physical_partition":
1275 # We can have this scenario meaning NumPhyPartitions++ but len(PhyPartition) doesn't increase
1276 # <physical_partition>
1277 # </physical_partition>
1278 # Thus if NumPhyPartitions > len(PhyPartition) by 2, then we need to increase it
1279
1280 NumPhyPartitions += 1
1281 CurrentPartition = 0 ## Using this to count partitions
1282
1283 PartitionCollection = [] # Reset, we've found a new physical partition
1284
1285 if NumPhyPartitions-len(PhyPartition)>=2:
1286 print "\n\n"
1287 print "*"*78
1288 print "ERROR: Empty <physical_partition></physical_partition> tags detected\n"
1289 print "Please replace with"
1290 print "<physical_partition>"
1291 print "<partition label='placeholder' size_in_kb='0' type='00000000-0000-0000-0000-000000000001' bootable='false' readonly='false' filename='' />"
1292 print "</physical_partition>\n"
1293 sys.exit()
1294
1295 print "\nFound a physical_partition, NumPhyPartitions=%d" % NumPhyPartitions
1296 print "\nlen(PhyPartition)=%d" % len(PhyPartition)
1297
1298
1299 elif element.tag=="partition" or element.tag=="primary" or element.tag=="extended":
1300
1301 CurrentPartition+=1
1302
1303 if element.keys():
1304 #print "\tAttributes:"
1305
1306 # Reset all variables to defaults
1307 Partition = {}
1308
1309 # This partition could have more than 1 file, so these are arrays
1310 # However, as I loop through the elements, *if* there is more than 1 file
1311 # it will have it's own <file> tag
1312 Partition['filename'] = [""]
1313 Partition['fileoffset'] = [0]
1314 Partition['appsbin'] = ["false"]
1315 Partition['sparse'] = ["false"]
1316 Partition['filepartitionoffset'] = [0]
1317
1318 Partition['size_in_kb'] = 0
1319 Partition['original_size_in_kb']= 0
1320 Partition["readonly"] = "false"
1321 Partition['label'] = "false"
1322 Partition['type'] = "false"
1323 Partition['uguid'] = "false" ## unique guid
1324 Partition['align'] = "false"
1325 Partition['hidden'] = "false"
1326 Partition['system'] = "false"
1327 Partition['dontautomount'] = "false"
1328 Partition['partofsingleimage'] = "false"
1329 Partition['readbackverify'] = "false"
1330 Partition['tries_remaining'] = 0
1331 Partition['priority'] = 0
1332 Partition['firstlba'] = -1
1333
1334 ##import pdb; pdb.set_trace()
1335
1336 if 'PERFORMANCE_BOUNDARY_IN_KB' in HashInstructions:
1337 Partition['PERFORMANCE_BOUNDARY_IN_KB'] = int(HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'])
1338 else:
1339 Partition['PERFORMANCE_BOUNDARY_IN_KB'] = 0
1340
1341 FileFound = 0
1342
1343 print " "
1344
1345 for name, value in element.items():
1346 #print "\t\tName: '%s'=>'%s' " % (name,value)
1347
1348 if name=='name' or name=='filename' :
1349 Partition['filename'][-1] = value
1350 FileFound = 1
1351 print "Found a file tag '%s'" % value
1352 elif name=='fileoffset':
1353 Partition['fileoffset'][-1] = value
1354 elif name=='label':
1355 Partition['label'] = value
1356 print "LABEL:",value
1357 elif name=='offset' or name=='filepartitionoffset':
1358 Partition['filepartitionoffset'][-1] = int(value)
1359 elif name=='appsbin':
1360 Partition['appsbin'][-1] = value
1361 elif name=='sparse':
1362 Partition['sparse'][-1] = value
1363 elif name=='PERFORMANCE_BOUNDARY_IN_KB':
1364 Partition['PERFORMANCE_BOUNDARY_IN_KB'] = int(value)
1365 elif name=='type':
1366 if ValidGUIDForm(value) is True:
1367 if OutputToCreate is None:
1368 OutputToCreate = "gpt"
1369 elif OutputToCreate is "mbr":
1370 PrintBigError("ERROR: Your partition.xml is possibly corrupt, please check the GUID TYPE field")
1371 Partition['type'] = ValidateGUID(value)
1372
1373 else:
1374 if OutputToCreate is None:
1375 OutputToCreate = "mbr"
1376 elif OutputToCreate is "gpt":
1377 PrintBigError("ERROR: Your partition.xml is possibly corrupt, please check the TYPE field")
1378 Partition['type'] = ValidateTYPE(value)
1379 elif name=='uniqueguid':
1380 if ValidGUIDForm(value) is True:
1381 Partition['uguid'] = ValidateGUID(value)
1382 else:
1383 PrintBigError("ERROR: Your partition.xml is possibly corrupt, please check the TYPE field")
1384 elif name=="triesremaining":
1385 Partition['tries_remaining'] = int(value);
1386 elif name=="priority":
1387 Partition['priority'] = int(value);
1388 elif name=="size":
1389 if len(value)==0:
1390 PrintBigError("\nERROR: Invalid partition size")
1391
1392 ## 'size' means in terms of sectors
1393 TempSizeInBytes = int(value)/2 # force as even number
1394 if TempSizeInBytes<2:
1395 TempSizeInBytes = 2
1396 TempSizeInBytes = TempSizeInBytes*SECTOR_SIZE_IN_BYTES ## either 1K or 8K
1397
1398 Partition["size_in_kb"]=TempSizeInBytes/1024
1399 Partition["original_size_in_kb"]=TempSizeInBytes/1024
1400 elif name=="size_in_kb":
1401 if len(value)==0:
1402 PrintBigError("\nERROR: Invalid partition size")
1403
1404
1405 if value=='0':
1406 if CheckPartitionCount[NumPhyPartitions-1] == CurrentPartition:
1407 ## To be here means they have size_in_kb='0' BUT this is ok since it is the LAST partition
1408 pass
1409 else:
1410 PrintBigError("\nERROR: Invalid size_in_kb='0' detected on partition %d of %d. This is usually a mistake. Did you mean this to be the *last* partition"%(CurrentPartition,CheckPartitionCount[NumPhyPartitions-1]))
1411
1412##timmy
1413
1414 TempSizeInBytes = int(value)*1024
1415 if TempSizeInBytes < SECTOR_SIZE_IN_BYTES:
1416 ## smaller than a sector, which is possible if sector size is 4KB
1417 TempSizeInBytes = SECTOR_SIZE_IN_BYTES
1418 Partition["size_in_kb"]=TempSizeInBytes/1024
1419 Partition["original_size_in_kb"]=TempSizeInBytes/1024
1420 elif name=="firstlba":
1421 Partition["firstlba"]=int(value)
1422 else:
1423 print "Just assigned %s to %s" % (name,value)
1424 Partition[name]=value
1425
1426 # No longer appending blank filename data for Trace32. Programming based on Label now
1427 #if FileFound == 1:
1428 # Partition['filename'].append("")
1429 # Partition['fileoffset'].append(0)
1430 # Partition['filepartitionoffset'].append(0)
1431 # Partition['appsbin'].append("false")
1432 # Partition['sparse'].append("false")
1433
1434
1435
1436 ## done with all the elements, now ensure that size matches with size_in_kb
1437 Partition["size"] = ConvertKBtoSectors(Partition["size_in_kb"]) # Still 512 bytes/sector here since "size" is a legacy field
1438
1439 ## Now add this "Partition" object to the PartitionCollection
1440 ## unless it's the label EXT, which is a left over legacy tag
1441
1442 if Partition['label'] != 'EXT':
1443 #print "\nJust added %s" % Partition['label']
1444 PartitionCollection.append( Partition )
1445
1446 print "="*40
1447 print "storing at %d" % (NumPhyPartitions-1)
1448 ##import pdb; pdb.set_trace()
1449
1450 print "Adding PartitionCollection to \"PhyPartition\" of size %i" % (NumPhyPartitions-1)
1451 PhyPartition[(NumPhyPartitions-1)] = PartitionCollection
1452
1453 #print "\nPartition stored (%i partitions total)" % len(PartitionCollection)
1454
1455 else:
1456 PrintBigError("ERROR: element.tag was partition, primary or extended, but it had no keys!")
1457
1458 elif element.tag=="file":
1459 #print "element.tag=='file' Found a file, NumPhyPartitions=",NumPhyPartitions ## i.e. just a file tag (usually in legacy)
1460 #print PhyPartition[(NumPhyPartitions-1)]
1461 #print "Current partition is \"%s\"\n" % Partition['label']
1462
1463 if element.keys():
1464 for name, value in element.items():
1465 if name=='name' or name=='filename' :
1466 Partition['filename'][-1] = value
1467 if name=='fileoffset':
1468 Partition['fileoffset'][-1] = value
1469 if name=='offset' or name=='filepartitionoffset':
1470 Partition['filepartitionoffset'][-1] = int(value)
1471 if name=='appsbin':
1472 Partition['appsbin'][-1] = value
1473 if name=='sparse':
1474 Partition['sparse'][-1] = value
1475
1476 #Partition[name]=value
1477
1478 #print Partition['filename']
1479 Partition['filename'].append("")
1480 Partition['fileoffset'].append(0)
1481 Partition['filepartitionoffset'].append(0)
1482 Partition['appsbin'].append("false")
1483 Partition['sparse'].append("false")
1484
1485 #try:
1486 # if len(Partition['filename'])>1:
1487 # print "="*78
1488 # print "="*78
1489 # for z in range(len(Partition['filename'])):
1490 # print "Partition['filename'][",z,"]=",Partition['filename'][z]
1491 # print "Partition['fileoffset'][",z,"]=",Partition['fileoffset'][z]
1492 # print "Partition['filepartitionoffset'][",z,"]=",Partition['filepartitionoffset'][z]
1493 # print "Partition['appsbin'][",z,"]=",Partition['appsbin'][z]
1494 # print "Partition['sparse'][",z,"]=",Partition['sparse'][z]
1495 # print "-"*78
1496 # print "="*78
1497 #except:
1498 # print " "
1499 #print "Showing the changes to PartitionCollection"
1500 #print PartitionCollection[-1]
1501
1502
1503 # Must update this if the user has updated WRITE_PROTECT_BOUNDARY_IN_KB in partition.xml
1504 hash_w[NumWPregions]['num_sectors'] = (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)
1505 hash_w[NumWPregions]['end_sector'] = (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)-1
1506
1507 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] == 0:
1508 hash_w[NumWPregions]['num_sectors'] = 0
1509 hash_w[NumWPregions]['end_sector'] = 0
1510 hash_w[NumWPregions]['num_boundaries_covered'] = 0
1511
1512 if OutputToCreate is "gpt" and HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] is False:
1513 hash_w[NumWPregions]['num_sectors'] = 0
1514 hash_w[NumWPregions]['end_sector'] = 0
1515 hash_w[NumWPregions]['num_boundaries_covered'] = 0
1516
1517 print "HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] =%d" % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']
1518 print "HashInstructions['ALIGN_BOUNDARY_IN_KB'] =%d" % HashInstructions['ALIGN_BOUNDARY_IN_KB']
1519 print "HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']=%s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']
1520 print "HashInstructions['DISK_SIGNATURE']=0x%X" % HashInstructions['DISK_SIGNATURE']
1521
1522 #for j in range(len(PhyPartition)):
1523 #for j in range(1):
1524 # print "\n\nPhyPartition[%d] ========================================================= " % (j)
1525 # PrintPartitionCollection( PhyPartition[j] )
1526
1527
1528 print "len(PhyPartition)=",len(PhyPartition)
1529
1530 if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==False:
1531 ## to be here means we're *not* growing final partition, thereore, obey the sizes they've specified
1532 for j in range(len(PhyPartition)):
1533 TempNumPartitions = len(PhyPartition[j])
1534 if TempNumPartitions>4:
1535 MinSectorsNeeded = 1 + (TempNumPartitions-3) # need MBR + TempNumPartitions-3 EBRs
1536 else:
1537 MinSectorsNeeded = 1 # need MBR only
1538
1539 for Partition in PhyPartition[j]:
1540 print "LABEL: '%s' with %d sectors " % (Partition['label'],ConvertKBtoSectors(Partition["size_in_kb"]))
1541
1542 MinSectorsNeeded += ConvertKBtoSectors(Partition["size_in_kb"])
1543
1544 #print "LABEL '%s' with size %d sectors" % (Partition['label'],Partition['size_in_kb']/2)
1545
1546
1547 print "MinSectorsNeeded=%d" % MinSectorsNeeded
1548 #sys.exit() #
1549
1550
1551 if OutputToCreate is 'gpt':
1552 PrintBanner("GPT GUID discovered in XML file, Output will be GPT")
1553 if OutputToCreate is 'mbr':
1554 PrintBanner("MBR type discovered in XML file, Output will be MBR")
1555
1556
1557# PrintPartitionCollection( PhyPartition[0] )
1558def PrintPartitionCollection(PartitionCollection):
1559
1560 #print PartitionCollection
1561
1562 for Partition in PartitionCollection:
1563 print Partition
1564 print " "
1565 for key in Partition:
1566 print key,"\t=>\t",Partition[key]
1567
1568 #for j in range(NumMBRPartitions):
1569
1570def ParseCommandLine():
1571 global XMLFile,OutputToCreate,PhysicalPartitionNumber
1572
1573 print "\nArgs"
1574 for i in range(len(sys.argv)):
1575 print "sys.argv[%d]=%s" % (i,sys.argv[i])
1576
1577 print " "
1578
1579 XMLFile = sys.argv[1];
1580
1581 if len(sys.argv) >= 3:
1582 m = re.search("mbr|gpt", sys.argv[2] )
1583
1584 if type(m) is not NoneType:
1585 OutputToCreate = sys.argv[2]
1586 else:
1587 print "Unrecognized option '%s', only 'mbr' or 'gpt' expected" % sys.argv[2]
1588 else:
1589 print "\nUser *did* not explicitly specify partition table format (i.e. mbr|gpt)"
1590 print "\nWill AUTO-DETECT from file"
1591
1592 if len(sys.argv) >= 4: # Should mean PHY partition was specified
1593 m = re.search("^\d+$", sys.argv[3] )
1594 if type(m) is not NoneType:
1595 PhysicalPartitionNumber = int(sys.argv[3])
1596 print "PhysicalPartitionNumber specified as %d" % PhysicalPartitionNumber
1597 else:
1598 PrintBigError("ERROR: PhysicalPartitionNumber of disk must only contain numbers, '%s' is not valid" % sys.argv[3])
1599
1600 print " "
1601
1602# Updates the WriteProtect hash that is used in creating emmc_lock_regions.xml
1603def UpdateWPhash(Start,Size):
1604 global hash_w,NumWPregions
1605
1606 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']==0:
1607 return
1608
1609 #print "\nUpdateWPhash(%i,%i) and currently NumWPregions=%i" % (Start,Size,NumWPregions)
1610 #print "hash_w[%i]['start_sector']=%i" % (NumWPregions,hash_w[NumWPregions]["start_sector"])
1611 #print "hash_w[%i]['end_sector']=%i" % (NumWPregions,hash_w[NumWPregions]["end_sector"])
1612 #print "hash_w[%i]['num_sectors']=%i" % (NumWPregions,hash_w[NumWPregions]["num_sectors"])
1613
1614 if Start-1 <= hash_w[NumWPregions]["end_sector"]:
1615 #print "\n\tCurrent Write Protect region already covers the start of this partition (start=%i)" % hash_w[NumWPregions]["start_sector"]
1616
1617 if (Start + Size - 1) > hash_w[NumWPregions]["end_sector"]:
1618 print "\n\tCurrent Write Protect region is not big enough at %i sectors, needs to be at least %i sectors" % (hash_w[NumWPregions]["end_sector"]-hash_w[NumWPregions]["start_sector"]+1,Start + Size - 1,)
1619 while (Start + Size - 1) > hash_w[NumWPregions]["end_sector"]:
1620 hash_w[NumWPregions]["num_sectors"] += (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES);
1621 hash_w[NumWPregions]["end_sector"] += (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES);
1622 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0:
1623 hash_w[NumWPregions]["num_boundaries_covered"] = hash_w[NumWPregions]["num_sectors"] / (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)
1624 else:
1625 hash_w[NumWPregions]["num_boundaries_covered"] = 0
1626
1627 print "\t\tend_sector increased to %i sectors" % hash_w[NumWPregions]["end_sector"]
1628 print "\t\tnum_sectors increased to %i sectors" % hash_w[NumWPregions]["num_sectors"]
1629
1630 #print "\n\tCurrent Write Protect region covers this partition (num_sectors=%i)\n" % hash_w[NumWPregions]["num_sectors"]
1631
1632 else:
1633 print "\n\tNew write protect region needed"
1634 #print "\tStart-1\t\t\t\t=%i" % (Start-1)
1635 #print "\tLAST hash_w[NumWPregions][end_sector]=%i\n" % hash_w[NumWPregions]["end_sector"]
1636
1637
1638 NumWPregions+=1;
1639
1640 hash_w.append( {'start_sector':Start,'num_sectors':(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES),'end_sector':Start+(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)-1,'physical_partition_number':0,'boundary_num':0,'num_boundaries_covered':1} )
1641
1642 hash_w[NumWPregions]["boundary_num"] = Start / (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)
1643
1644 while (Start + Size - 1) > hash_w[NumWPregions]["end_sector"]:
1645 #print "\n\tThis region is not big enough though, needs to be %i sectors, but currently only %i" % (Start + Size - 1,hash_w[NumWPregions]["end_sector"])
1646 hash_w[NumWPregions]["num_sectors"] += (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES);
1647 hash_w[NumWPregions]["end_sector"] += (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES);
1648 #print "\t\tend_sector increased to %i sectors" % hash_w[NumWPregions]["end_sector"]
1649 #print "\t\tnum_sectors increased to %i sectors" % hash_w[NumWPregions]["num_sectors"]
1650
1651 hash_w[NumWPregions]["num_boundaries_covered"] = hash_w[NumWPregions]["num_sectors"] / (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)
1652
1653 print "\t\tstart_sector = %i sectors" % hash_w[NumWPregions]["start_sector"]
1654 print "\t\tend_sector = %i sectors" % hash_w[NumWPregions]["end_sector"]
1655 print "\t\tnum_sectors = %i sectors\n" % hash_w[NumWPregions]["num_sectors"]
1656
1657# A8h reflected is 15h, i.e. 10101000 <--> 00010101
1658def reflect(data,nBits):
1659
1660 reflection = 0x00000000
1661 bit = 0
1662
1663 for bit in range(nBits):
1664 if(data & 0x01):
1665 reflection |= (1 << ((nBits - 1) - bit))
1666 data = (data >> 1);
1667
1668 return reflection
1669
1670
1671def CalcCRC32(array,Len):
1672 k = 8; # length of unit (i.e. byte)
1673 MSB = 0;
1674 gx = 0x04C11DB7; # IEEE 32bit polynomial
1675 regs = 0xFFFFFFFF; # init to all ones
1676 regsMask = 0xFFFFFFFF; # ensure only 32 bit answer
1677
1678 print "Calculating CRC over byte length of %i" % Len
1679 print "%s" % HexPrettyPrint(array,Len)
1680
1681 for i in range(Len):
1682 DataByte = array[i]
1683 DataByte = reflect( DataByte, 8 );
1684
1685 for j in range(k):
1686 MSB = DataByte>>(k-1) ## get MSB
1687 MSB &= 1 ## ensure just 1 bit
1688
1689 regsMSB = (regs>>31) & 1
1690
1691 regs = regs<<1 ## shift regs for CRC-CCITT
1692
1693 if regsMSB ^ MSB: ## MSB is a 1
1694 regs = regs ^ gx ## XOR with generator poly
1695
1696 regs = regs & regsMask; ## Mask off excess upper bits
1697
1698 DataByte <<= 1 ## get to next bit
1699
1700
1701 regs = regs & regsMask ## Mask off excess upper bits
1702 ReflectedRegs = reflect(regs,32) ^ 0xFFFFFFFF;
1703
1704 #print "CRC is 0x%.8X\n" % ReflectedRegs
1705
1706 return ReflectedRegs
1707
1708
1709def HexPrettyPrint(data,Length):
1710 szNum = ""
1711 szAsc = ""
1712 digest= ""
1713 P = 16
1714
1715 ## Called during DLOAD and STREAM
1716 #log_info("In HexPrettyPrint() len(data)=%d" % len(data))
1717
1718 ##return " "## hack
1719
1720 try:
1721 if len(data)==0:
1722 return " "
1723 except:
1724 log_debug("Hit Exception in HexPrettyPrint, data is %s" % type(data))
1725 return " "
1726
1727 digest = ""
1728
1729 TempAddress = 0
1730 szHexDump = "\n\tShowing %d bytes\n\t" % (Length)
1731 for i in range(Length):
1732 v = data[i]
1733
1734 if v == 0x7 and i==0 and Length>5:
1735 ## Get next 4 bytes
1736 ##print "Length=",Length
1737 TempAddress = data[i+4]<<24 | data[i+3]<<16 | data[i+2]<<8 | data[i+1]
1738 szHexDump += "Suspected Write, Address would be 0x%.8X\n\t" % (TempAddress)
1739
1740 if i>0 and i % 16==0:
1741 szHexDump += "%-48s\t%s\n\t" % (szNum,szAsc)
1742 szNum = ""
1743 szAsc = ""
1744
1745 ##print "v=",v," type",type(v)
1746 ##import pdb; pdb.set_trace()
1747 #if type(v) is not int: ## HACK
1748 # v = ord(v) ## convert to unsigned char (integers in python)
1749 szNum += "%.2X " % v
1750 if v>=0x20 and v<=0x7E:
1751 szAsc += "%c" % v
1752 else:
1753 szAsc += "."
1754
1755 ##import pdb; pdb.set_trace()
1756
1757 szHexDump += "%-48s\t%s\n%s\n\n" % (szNum,szAsc,digest)
1758
1759 return szHexDump
1760
1761
1762def ReturnLow32bits(var):
1763 return var & 0xFFFFFFFF
1764
1765def ReturnHigh32bits(var):
1766 return (var>>32) & 0xFFFFFFFF
1767
1768def PrintBanner(sz):
1769 print "\n"+"="*78
1770 print sz
1771 print "="*78+"\n"
1772
1773def ShowUsage():
1774 PrintBanner("Basic Usage")
1775 print "python ptool.py -x partition.xml"
1776 PrintBanner("Advanced Usage")
1777 print "%-44s\t\tpython ptool.py -x partition.xml" % ("Basic Usage")
1778 print "%-44s\t\tpython ptool.py -x partition.xml -s c:\windows" % ("Search path to find partition.xml")
1779 print "%-44s\tpython ptool.py -x partition.xml -p 0" % ("Specify PHY Partition 0, (creates rawprogram0.xml)")
1780 print "%-44s\tpython ptool.py -x partition.xml -p 1" % ("Specify PHY Partition 1, (creates rawprogram1.xml)")
1781 print "%-44s\tpython ptool.py -x partition.xml -p 2" % ("Specify PHY Partition 2, (creates rawprogram2.xml)")
1782 print "%-44s\t\tpython ptool.py -x partition.xml -v" % ("Verbose output")
1783 print "%-44s\t\tpython ptool.py -x partition.xml -t c:\\temp" % ("Specify place to put output")
1784
1785def CreateFinalPartitionBin():
1786 global OutputFolder
1787
1788 opfile = open("%spartition.bin" % OutputFolder, "wb")
1789
1790 for i in range(3):
1791 FileName = "%spartition%i.bin" % (OutputFolder,i);
1792 size = 0
1793
1794 if os.path.isfile(FileName):
1795 size = os.path.getsize(FileName)
1796
1797 ipfile = open(FileName, "rb")
1798 temp = ipfile.read()
1799 opfile.write(temp)
1800 ipfile.close()
1801
1802 if size < 8192:
1803 MyArray = [0]*(8192-size)
1804 for b in MyArray:
1805 opfile.write(struct.pack("B", b))
1806
1807 opfile.close()
1808
1809
1810
1811def prettify(elem):
1812 """Return a pretty-printed XML string for the Element.
1813 """
1814 rough_string = ET.tostring(elem, 'utf-8')
1815 reparsed = minidom.parseString(rough_string)
1816 return reparsed.toprettyxml(indent=" ")
1817
1818
1819def UpdatePartitionTable(Bootable,Type,StartSector,Size,Offset,Record):
1820
1821 #print "Size = %i" % Size
1822
1823 if Bootable=="true":
1824 Bootable = 0x80
1825 else:
1826 Bootable = 0x00
1827
1828 Type = ValidateTYPE(Type)
1829
1830 #print "\tAt Offset=0x%.4X (%d) (%d bytes left)" % (Offset,Offset,len(Record)-Offset)
1831
1832 Record[Offset] = Bootable ; Offset+=1
1833
1834 Record[Offset:Offset+3]= [0,0,0] ; Offset+=3
1835
1836 Record[Offset] = Type ; Offset+=1
1837
1838 Record[Offset:Offset+3]= [0,0,0] ; Offset+=3
1839
1840 # First StartSector
1841 for b in range(4):
1842 Record[Offset] = ((StartSector>>(b*8)) & 0xFF) ; Offset+=1
1843
1844 # First StartSector
1845 for b in range(4):
1846 Record[Offset] = ((Size>>(b*8)) & 0xFF) ; Offset+=1
1847
1848 #print "\t\tBoot:0x%.2X, ID:0x%.2X, 0x%.8X, 0x%.8X (%.2fMB)" % (Bootable,Type,StartSector,Size,Size/2048.0)
1849
1850 return Record
1851
1852# This function called first, then calls CreateMasterBootRecord and CreateExtendedBootRecords
1853def CreateMBRPartitionTable(PhysicalPartitionNumber):
1854 global PhyPartition,opfile,RawProgramXML,HashInstructions,ExtendedPartitionBegins,MBR,PARTITIONBIN, MBRBIN, EBRBIN, PATCHES, RAW_PROGRAM
1855
1856 k = PhysicalPartitionNumber
1857
1858 if(k>=len(PhyPartition)):
1859 print "PHY Partition %i of %i not found" % (k,len(PhyPartition))
1860 sys.exit()
1861
1862 NumPartitions = len(PhyPartition[k])
1863
1864 print "\n\nOn PHY Partition %d that has %d partitions" % (k,NumPartitions)
1865
1866 print "\n------------\n"
1867
1868 print "\nFor PHY Partition %i" % k
1869 if(NumPartitions<=4):
1870 print "\tWe can get away with only an MBR";
1871 CreateMasterBootRecord(k, NumPartitions )
1872 else:
1873 print "\tWe will need an MBR and %d EBRs" % (NumPartitions-3)
1874 CreateMasterBootRecord(k, 3 )
1875
1876 ## Now the EXTENDED PARTITION
1877 print "\nAbout to make EBR, FirstLBA=%i, LastLBA=%i" % (FirstLBA,LastLBA)
1878 CreateExtendedBootRecords(k,NumPartitions-3)
1879
1880
1881 PARTITIONBIN = '%spartition%i.bin' % (OutputFolder,k)
1882 MBRBIN = '%sMBR%i.bin' % (OutputFolder,k)
1883 EBRBIN = '%sEBR%i.bin' % (OutputFolder,k)
1884 PATCHES = '%spatch%i.xml' % (OutputFolder,k)
1885 RAW_PROGRAM = '%srawprogram%i.xml' % (OutputFolder,k)
1886
1887 UpdateRawProgram(RawProgramXML,0, 1*SECTOR_SIZE_IN_BYTES/1024.0, k, 0, 1, MBRBIN, 'false', 'MBR')
1888
1889 if(NumPartitions>4):
1890 ## There was more than 4 partitions, so EXT partition had to be used
1891 UpdateRawProgram(RawProgramXML,ExtendedPartitionBegins, (NumPartitions-3)*SECTOR_SIZE_IN_BYTES/1024.0, k, 0, NumPartitions-3, EBRBIN, 'false', 'EXT') # note file offset is 0
1892
1893 print "\nptool.py is running from CWD: ", os.getcwd(), "\n"
1894
1895 opfile = open(PARTITIONBIN, "wb")
1896 WriteMBR()
1897 WriteEBR()
1898 opfile.close()
1899 print "Created \"%s\"" % PARTITIONBIN
1900
1901 opfile = open(MBRBIN, "wb")
1902 WriteMBR()
1903 opfile.close()
1904 print "Created \"%s\"" % MBRBIN
1905
1906 opfile = open(EBRBIN, "wb")
1907 WriteEBR()
1908 opfile.close()
1909 print "Created \"%s\"" % EBRBIN
1910
1911 opfile = open(RAW_PROGRAM, "w")
1912 opfile.write( prettify(RawProgramXML) )
1913 opfile.close()
1914 print "Created \"%s\"" % RAW_PROGRAM
1915
1916 opfile = open(PATCHES, "w")
1917 opfile.write( prettify(PatchesXML) )
1918 opfile.close()
1919 print "Created \"%s\"" % PATCHES
1920
1921 for mydict in hash_w:
1922 #print mydict
1923 SubElement(EmmcLockRegionsXML, 'program', {'start_sector':"%X" % mydict['start_sector'],'start_sector_dec':str(mydict['start_sector']),
1924 'num_sectors':"%X" % mydict['num_sectors'],'num_sectors_dec':str(mydict['num_sectors']),
1925 'boundary_num':str(mydict['boundary_num']),
1926 'num_boundaries_covered':str(mydict['num_boundaries_covered']),
1927 'physical_partition_number':str(mydict['physical_partition_number']) })
1928
1929
1930 SubElement(EmmcLockRegionsXML, 'information', {'WRITE_PROTECT_BOUNDARY_IN_KB':str(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']) })
1931
1932 opfile = open("%semmc_lock_regions.xml" % OutputFolder, "w")
1933
1934 opfile.write( prettify(EmmcLockRegionsXML) )
1935 opfile.close()
1936 print "Created \"%semmc_lock_regions.xml\"" % OutputFolder
1937
1938 print "\nUse msp tool to write this information to SD/eMMC card"
1939 print "\ti.e."
1940
1941 if sys.platform.startswith("linux"):
1942 print "\tsudo python msp.py rawprogram0.xml /dev/sdb <---- where /dev/sdb is assumed to be your SD/eMMC card"
1943 print "\tsudo python msp.py patch0.xml /dev/sdb <---- where /dev/sdb is assumed to be your SD/eMMC card\n\n"
1944 else:
1945 print "\tpython msp.py rawprogram0.xml \\\\.\\PHYSICALDRIVE2 <---- where \\\\.\\PHYSICALDRIVE2 is"
1946 print "\tpython msp.py patch0.xml \\\\.\\PHYSICALDRIVE2 <---- assumed to be your SD/eMMC card\n\n"
1947
1948
1949 # CreateMasterBootRecord(k,len(PhyPartition[k]) )
1950def CreateMasterBootRecord(k,NumMBRPartitions):
1951 global PhyPartition,HashInstructions,MBR,FirstLBA,LastLBA
1952 print "\nInside CreateMasterBootRecord(%d) -------------------------------------" % NumMBRPartitions
1953
1954 MBR = [0]*SECTOR_SIZE_IN_BYTES
1955 MBR[440] = (HashInstructions['DISK_SIGNATURE']>>24)&0xFF
1956 MBR[441] = (HashInstructions['DISK_SIGNATURE']>>16)&0xFF
1957 MBR[442] = (HashInstructions['DISK_SIGNATURE']>>8)&0xFF
1958 MBR[443] = (HashInstructions['DISK_SIGNATURE'])&0xFF
1959
1960 MBR[510:512] = [0x55,0xAA] # magic byte for MBR partitioning - always at this location regardless of SECTOR_SIZE_IN_BYTES
1961
1962 ## These two values used like so 'num_sectors':str(LastLBA-FirstLBA)
1963 FirstLBA = 1 ## the MBR is at 0, Partition 1 is at 1
1964 LastLBA = 1
1965
1966 PartitionSectorSize = 0
1967
1968 #print "\nOn PHY Partition %d that has %d partitions" % (k,len(PhyPartition[k]))
1969 for j in range(NumMBRPartitions): # typically this is 0,1,2
1970
1971 ## ALL MBR partitions are marked as read-only
1972 PhyPartition[k][j]['readonly'] = "true"
1973
1974 PartitionSectorSize = ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']) # in sector form, i.e. 1KB = 2 sectors
1975
1976 print "\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%.2fMB or %i sectors)" % (j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'],
1977 PhyPartition[k][j]['readonly'],PhyPartition[k][j]['size_in_kb'],
1978 PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']))
1979
1980
1981 # Is this sector aligned?
1982 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0:
1983 AlignedRemainder = FirstLBA % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'];
1984
1985 if AlignedRemainder==0:
1986 print "\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])))
1987
1988
1989 # are we on the very last partition, i.e. did user only specify 3 or less partitions?
1990 if (j+1) == len(PhyPartition[k]):
1991 print "\nTHIS IS THE LAST PARTITION"
1992 print "HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = %s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']
1993 if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True:
1994 SectorOffsetPatchBefore = 0
1995 SectorOffsetPatchAfter = 0
1996 ByteOffset = 0x1CA+j*16
1997 UpdatePatch(str(SectorOffsetPatchBefore),str(ByteOffset),k,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA),"partition%d.bin" % k, "Update last partition with actual size.")
1998 UpdatePatch(str(SectorOffsetPatchBefore),str(ByteOffset),k,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA),"MBR%d.bin" % k, "Update last partition with actual size.")
1999 UpdatePatch(str(SectorOffsetPatchAfter), str(ByteOffset),k,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA),"DISK", "Update 'Update last partition with actual size.")
2000
2001 # Update the Write-Protect hash
2002 if PhyPartition[k][j]['readonly']=="true":
2003 UpdateWPhash(FirstLBA, PartitionSectorSize)
2004
2005 LastLBA += PartitionSectorSize ## increase by num sectors, LastLBA inclusive, so add 1 for size
2006
2007 ## Default for each partition is no file
2008 FileToProgram = [""]
2009 FileOffset = [0]
2010 FilePartitionOffset = [0]
2011 FileAppsbin = ["false"]
2012 FileSparse = ["false"]
2013
2014 if 'filename' in PhyPartition[k][j]:
2015 ##print "filename exists"
2016 #print PhyPartition[k][j]['filename']
2017 #print FileToProgram[0]
2018
2019
2020 FileToProgram[0] = PhyPartition[k][j]['filename'][0]
2021 FileOffset[0] = PhyPartition[k][j]['fileoffset'][0]
2022 FilePartitionOffset[0] = PhyPartition[k][j]['filepartitionoffset'][0]
2023 FileAppsbin[0] = PhyPartition[k][j]['appsbin'][0]
2024 FileSparse[0] = PhyPartition[k][j]['sparse'][0]
2025
2026 for z in range(1,len(PhyPartition[k][j]['filename'])):
2027 FileToProgram.append( PhyPartition[k][j]['filename'][z] )
2028 FileOffset.append( PhyPartition[k][j]['fileoffset'][z] )
2029 FilePartitionOffset.append( PhyPartition[k][j]['filepartitionoffset'][z] )
2030 FileAppsbin.append( PhyPartition[k][j]['appsbin'][z] )
2031 FileSparse.append( PhyPartition[k][j]['sparse'][z] )
2032
2033 #print PhyPartition[k][j]['fileoffset']
2034
2035
2036 #for z in range(len(FileToProgram)):
2037 # print "FileToProgram[",z,"]=",FileToProgram[z]
2038 # print "FileOffset[",z,"]=",FileOffset[z]
2039 # print " "
2040
2041 PartitionLabel = ""
2042 Type = ""
2043 Bootable = "false"
2044
2045 ## Now update with the real values
2046 if 'label' in PhyPartition[k][j]:
2047 PartitionLabel = PhyPartition[k][j]['label']
2048 if 'type' in PhyPartition[k][j]:
2049 Type = PhyPartition[k][j]['type']
2050 if 'bootable' in PhyPartition[k][j]:
2051 Bootable = PhyPartition[k][j]['bootable']
2052
2053 ## Now it is time to update the partition table
2054 offset = 0x1BE + (j*16)
2055
2056 MBR = UpdatePartitionTable(Bootable,Type,FirstLBA,PartitionSectorSize,offset,MBR)
2057
2058
2059 for z in range(len(FileToProgram)):
2060 #print "File: ",FileToProgram[z]
2061 #print "FilePartitionOffset[z]=",FilePartitionOffset[z]
2062 UpdateRawProgram(RawProgramXML, FirstLBA+FilePartitionOffset[z], PartitionSectorSize*SECTOR_SIZE_IN_BYTES/1024.0, k, FileOffset[z], PartitionSectorSize-FilePartitionOffset[z], FileToProgram[z], FileSparse[z], PartitionLabel)
2063
2064 FirstLBA = LastLBA # getting ready for next partition, FirstLBA is now where we left off
2065
2066# CreateExtendedBootRecords(k,len(PhyPartition[k])-3)
2067def CreateExtendedBootRecords(k,NumEBRPartitions):
2068 global PhyPartition,HashInstructions,MBR,EBR,FirstLBA,LastLBA,ExtendedPartitionBegins
2069 print "\nInside CreateExtendedBootRecords(%d) -----------------------------------------" % NumEBRPartitions
2070
2071 ## Step 1 is to update the MBR with the size of the EXT partition
2072 ## in which logical partitions will be created
2073
2074 EBROffset = 0
2075
2076 print "EBROffset=",EBROffset
2077
2078 ExtendedPartitionBegins = FirstLBA
2079
2080 if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True:
2081 print "Extended Partition begins at FirstLBA=%i\n" % (ExtendedPartitionBegins)
2082 MBR=UpdatePartitionTable("false","05",FirstLBA,0x0,0x1EE,MBR) ## offset at 0x1EE is the last entry in MBR
2083 else:
2084 print "Extended Partition begins at FirstLBA=%i, size is %i\n" % (ExtendedPartitionBegins,MinSectorsNeeded-FirstLBA)
2085 MBR=UpdatePartitionTable("false","05",FirstLBA,MinSectorsNeeded-FirstLBA,0x1EE,MBR) ## offset at 0x1EE is the last entry in MBR
2086
2087 ## Still patch no matter what, since this can still go on any size card
2088 UpdatePatch('0',str(0x1FA),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(ExtendedPartitionBegins),"partition%d.bin" % k, "Update MBR with the length of the EXT Partition.")
2089 UpdatePatch('0',str(0x1FA),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(ExtendedPartitionBegins),"MBR%d.bin" % k, "Update MBR with the length of the EXT Partition.")
2090 UpdatePatch('0',str(0x1FA),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(ExtendedPartitionBegins),"DISK", "Update MBR with the length of the EXT Partition.")
2091
2092 UpdateWPhash(FirstLBA, NumEBRPartitions)
2093
2094 ## Need to make room for the EBR tables
2095 FirstLBA += NumEBRPartitions
2096 LastLBA += NumEBRPartitions
2097
2098 print "FirstLBA now equals %d since NumEBRPartitions=%d" % (FirstLBA,NumEBRPartitions)
2099
2100 offset = 0 # offset to EBR array which gets EBR.extend( [0]*SECTOR_SIZE_IN_BYTES ) for each EBR
2101 SectorsTillNextBoundary = 0 # reset
2102
2103
2104 # EBROffset is the num sectors from the location of the EBR to the actual logical partition
2105 # and because we group all the EBRs together,
2106 # EBR0 is NumEBRPartitions away from EXT0
2107 # EBR1 is NumEBRPartitions-1+SizeOfEXT0 away from EXT1 and so on
2108 # EBR2 is NumEBRPartitions-2+SizeOfEXT0+SizeOfEXT1 away from EXT2 and so on
2109 # Thus EBROffset is constantly growing
2110
2111 # Also since the EBRs must be write protected, we must ensure that it ends
2112 # on a WP boundary, i.e. HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']
2113
2114 ## NOTE: We only have extended partitions when there are more than 4 partitions
2115 ## meaning 3 primary and then 2 extended. Thus everything here is offset from 3
2116 ## since the first 3 primary partitions were 0,1,2
2117 EBR = []
2118 for j in range(3,(NumEBRPartitions+3)):
2119 SectorsTillNextBoundary = 0
2120 EBR.extend( [0]*SECTOR_SIZE_IN_BYTES )
2121
2122 #print "hash_w[%i]['start_sector']=%i" % (NumWPregions,hash_w[NumWPregions]["start_sector"])
2123 #print "hash_w[%i]['end_sector']=%i" % (NumWPregions,hash_w[NumWPregions]["end_sector"])
2124 #print "hash_w[%i]['num_sectors']=%i" % (NumWPregions,hash_w[NumWPregions]["num_sectors"])
2125
2126 PartitionSectorSize = ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb'])
2127
2128 ##print "\nPartition name='%s' (readonly=%s)" % (PhyPartition[k][j]['label'], PhyPartition[k][j]['readonly'])
2129 print "\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%.2fMB or %i sectors)" %(j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'],PhyPartition[k][j]['readonly'],PhyPartition[k][j]['size_in_kb'],PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']))
2130 print "\tFirstLBA=%d (with size %d sectors) and LastLBA=%d" % (FirstLBA,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),LastLBA)
2131
2132 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0:
2133 SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])
2134
2135 # Only the last partition can be re-sized. Are we on the very last partition?
2136 if (j+1) == len(PhyPartition[k]):
2137 print "\n\tTHIS IS THE LAST PARTITION"
2138
2139 if PhyPartition[k][j]['readonly']=="true":
2140 PhyPartition[k][j]['readonly']="false"
2141 print "\tIt cannot be marked as read-only, it is now set to writeable"
2142
2143 if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True:
2144 ## Here I'd want a patch for this
2145 print "\tHashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = %s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']
2146
2147 print "\njust set LAST PartitionSectorSize = 0 (it was %d)" % PartitionSectorSize
2148 PartitionSectorSize = 0
2149 print "This means the partition table will have a zero in it"
2150 LastPartitionBeginsAt = FirstLBA
2151
2152 NumEBRs = (len(PhyPartition[k])-3)
2153 SectorOffsetPatchBefore = NumEBRs
2154 SectorOffsetPatchAfter = ExtendedPartitionBegins+NumEBRs-1
2155 ByteOffset = 0x1CA
2156
2157 ## Patch no matter what
2158 UpdatePatch(str(SectorOffsetPatchBefore),str(ByteOffset),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA+1),"partition%d.bin" % k, "Update last partition with actual size.")
2159 UpdatePatch(str(SectorOffsetPatchBefore-1),str(ByteOffset),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA+1),"EBR%d.bin" % k, "Update last partition with actual size.")
2160 UpdatePatch(str(SectorOffsetPatchAfter), str(ByteOffset),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA+1),"DISK", "Update last partition with actual size.")
2161
2162
2163 print "\tPhyPartition[k][j]['align']=",PhyPartition[k][j]['align']
2164 print "\tSectorsTillNextBoundary=",SectorsTillNextBoundary
2165
2166 if PhyPartition[k][j]['readonly']=="true":
2167 ## to be here means this partition is read-only, so see if we need to move the start
2168 if FirstLBA <= hash_w[NumWPregions]["end_sector"]:
2169 print "Great, We *don't* need to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])
2170 pass
2171 else:
2172 print "\tFirstLBA (%d) is *not* covered by the end of the WP region (%d),\n\tit needs to be moved to be aligned to %d" % (FirstLBA,hash_w[NumWPregions]["end_sector"],FirstLBA + SectorsTillNextBoundary)
2173 FirstLBA += SectorsTillNextBoundary
2174 elif PhyPartition[k][j]['align']=="true":
2175 ## to be here means this partition *must* be on an ALIGN boundary
2176 SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,HashInstructions['ALIGN_BOUNDARY_IN_KB'])
2177 if SectorsTillNextBoundary>0:
2178 print "\tSectorsTillNextBoundary=%d, FirstLBA=%d it needs to be moved to be aligned to %d" % (SectorsTillNextBoundary,FirstLBA,FirstLBA + SectorsTillNextBoundary)
2179 print "\tHashInstructions['ALIGN_BOUNDARY_IN_KB']=",HashInstructions['ALIGN_BOUNDARY_IN_KB']
2180 FirstLBA += SectorsTillNextBoundary
2181
2182 AlignedRemainder = FirstLBA % HashInstructions['ALIGN_BOUNDARY_IN_KB'];
2183
2184 if AlignedRemainder==0:
2185 print "\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['ALIGN_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['ALIGN_BOUNDARY_IN_KB'])))
2186
2187 else:
2188 print "\n\tThis partition is *NOT* readonly (or does not have align='true')"
2189 ## to be here means this partition is writeable, so see if we need to move the start
2190 if FirstLBA <= hash_w[NumWPregions]["end_sector"]:
2191 print "\tWe *need* to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])
2192 print "\nhash_w[NumWPregions]['end_sector']=%i" % hash_w[NumWPregions]["end_sector"];
2193 print "FirstLBA=%i\n" %FirstLBA;
2194 FirstLBA += SectorsTillNextBoundary
2195
2196 print "\tFirstLBA is now %d" % (FirstLBA)
2197 else:
2198 #print "Great, We *don't* need to move FirstLBA (%d) since it's *not* covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])
2199 pass
2200
2201 if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0:
2202 AlignedRemainder = FirstLBA % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'];
2203
2204 if AlignedRemainder==0:
2205 print "\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])))
2206
2207 if PhyPartition[k][j]['readonly']=="true":
2208 UpdateWPhash(FirstLBA, PartitionSectorSize)
2209
2210 LastLBA = FirstLBA + PartitionSectorSize
2211
2212 print "\n\tFirstLBA=%u, LastLBA=%u, PartitionSectorSize=%u" % (FirstLBA,LastLBA,PartitionSectorSize)
2213
2214 print "\tLastLBA is currently %i sectors" % LastLBA
2215 print "\tCard size of at least %.1fMB needed (%u sectors)" % (LastLBA/2048.0,LastLBA)
2216 PhyPartition[k][j]['size_in_kb'] = PartitionSectorSize/2
2217
2218 ## Default for each partition is no file
2219 FileToProgram = [""]
2220 FileOffset = [0]
2221 FilePartitionOffset = [0]
2222 FileAppsbin = ["false"]
2223 FileSparse = ["false"]
2224
2225 if 'filename' in PhyPartition[k][j]:
2226 ##print "filename exists"
2227 #print PhyPartition[k][j]['filename']
2228 #print FileToProgram[0]
2229
2230 FileToProgram[0] = PhyPartition[k][j]['filename'][0]
2231 FileOffset[0] = PhyPartition[k][j]['fileoffset'][0]
2232 FilePartitionOffset[0] = PhyPartition[k][j]['filepartitionoffset'][0]
2233 FileAppsbin[0] = PhyPartition[k][j]['appsbin'][0]
2234 FileSparse[0] = PhyPartition[k][j]['sparse'][0]
2235
2236 for z in range(1,len(PhyPartition[k][j]['filename'])):
2237 FileToProgram.append( PhyPartition[k][j]['filename'][z] )
2238 FileOffset.append( PhyPartition[k][j]['fileoffset'][z] )
2239 FilePartitionOffset.append( PhyPartition[k][j]['filepartitionoffset'][z] )
2240 FileAppsbin.append( PhyPartition[k][j]['appsbin'][z] )
2241 FileSparse.append( PhyPartition[k][j]['sparse'][z] )
2242
2243 #print PhyPartition[k][j]['fileoffset']
2244
2245
2246 #for z in range(len(FileToProgram)):
2247 # print "FileToProgram[",z,"]=",FileToProgram[z]
2248 # print "FileOffset[",z,"]=",FileOffset[z]
2249 # print " "
2250
2251 PartitionLabel = ""
2252 Type = ""
2253 Bootable = "false"
2254
2255
2256 if 'label' in PhyPartition[k][j]:
2257 PartitionLabel = PhyPartition[k][j]['label']
2258 if 'type' in PhyPartition[k][j]:
2259 Type = PhyPartition[k][j]['type']
2260 if 'bootable' in PhyPartition[k][j]:
2261 Bootable = PhyPartition[k][j]['bootable']
2262
2263
2264 ## Update main logical partition
2265 offset += 0x1BE ## this naturally increments to 0x200, then 0x400 etc
2266
2267 ##UpdatePartitionTable(Bootable,Type,EBROffset,PartitionSectorSize,offset) ; offset +=16
2268 EBR = UpdatePartitionTable(Bootable,Type,FirstLBA-ExtendedPartitionBegins-EBROffset,PartitionSectorSize,offset,EBR) ; offset +=16
2269
2270 ## Update EXT, i.e. are there more partitions to come?
2271 if (j+1) == (NumEBRPartitions+3):
2272 ## No, this is the very last so indicate no more logical partitions
2273 EBR = UpdatePartitionTable("false","00",0,0,offset,EBR) ; offset +=16 ## on last partition, so no more
2274 else:
2275 ## Yes, at least one more, so indicate EXT type of 05
2276 EBR = UpdatePartitionTable("false","05",j-2,1,offset,EBR) ; offset +=16
2277
2278 ## Update last 2 which are always blank
2279 EBR = UpdatePartitionTable("false","00",0,0,offset,EBR) ; offset +=16
2280 EBR = UpdatePartitionTable("false","00",0,0,offset,EBR) ; offset +=16
2281
2282 EBR[offset] = 0x55 ; offset +=1
2283 EBR[offset] = 0xAA ; offset +=1
2284
2285
2286 ## Now update EBROffset
2287 EBROffset += 1 # Each EBR gets us one closer
2288
2289 for z in range(len(FileToProgram)):
2290 #print "File: ",FileToProgram[z]
2291 #print "FilePartitionOffset[z]=",FilePartitionOffset[z]
2292 UpdateRawProgram(RawProgramXML,FirstLBA+FilePartitionOffset[z], PartitionSectorSize*SECTOR_SIZE_IN_BYTES/1024.0, k, FileOffset[z], PartitionSectorSize-FilePartitionOffset[z], FileToProgram[z], FileSparse[z], PartitionLabel)
2293
2294 FirstLBA = LastLBA # getting ready for next partition, FirstLBA is now where we left off
2295
2296
2297 print "\n------------------------------------------------------------------------------"
2298 print " LastLBA is currently %i sectors" % (LastLBA)
2299 print " Card size of at least %.1fMB needed (%u sectors)" % (LastLBA/2048.0,LastLBA)
2300 print "------------------------------------------------------------------------------"
2301
2302def ReturnNumSectorsTillBoundary(CurrentLBA, BoundaryInKB):
2303 #Say BoundaryInKB is 65536 (64MB)
2304 # if SECTOR_SIZE_IN_BYTES=512, BoundaryLBA=131072
2305 # if SECTOR_SIZE_IN_BYTES=4096, BoundaryLBA=16384
2306
2307 #Say were at the 63MB boundary, then
2308 # if SECTOR_SIZE_IN_BYTES=512, CurrentLBA=129024
2309 # if SECTOR_SIZE_IN_BYTES=4096, CurrentLBA=16128
2310
2311 # Distance is then 1MB
2312 # if SECTOR_SIZE_IN_BYTES=512, DistanceLBA=2048 (2048*512=1MB)
2313 # if SECTOR_SIZE_IN_BYTES=4096, DistanceLBA=256 (256*4096=1MB)
2314
2315 ##import pdb; pdb.set_trace()
2316
2317 x = 0
2318 if BoundaryInKB>0:
2319 if (CurrentLBA%ConvertKBtoSectors(BoundaryInKB)) > 0:
2320 x = ConvertKBtoSectors(BoundaryInKB) - (CurrentLBA%ConvertKBtoSectors(BoundaryInKB))
2321
2322 ##print "\tFYI: Increase by %dKB (%d sectors) if you want to align to %i KB boundary at sector %d" % (x/2,x,BoundaryInKB,CurrentLBA+x)
2323 return x
2324
2325
2326def WriteMBR():
2327 global opfile,MBR
2328 for b in MBR:
2329 opfile.write(struct.pack("B", b))
2330
2331def WriteEBR():
2332 global opfile,EBR
2333 for b in EBR:
2334 opfile.write(struct.pack("B", b))
2335
2336def PrintBigError(sz):
2337 print "\t _________________ ___________ "
2338 print "\t| ___| ___ \\ ___ \\ _ | ___ \\"
2339 print "\t| |__ | |_/ / |_/ / | | | |_/ /"
2340 print "\t| __|| /| /| | | | / "
2341 print "\t| |___| |\\ \\| |\\ \\\\ \\_/ / |\\ \\ "
2342 print "\t\\____/\\_| \\_\\_| \\_|\\___/\\_| \\_|\n"
2343
2344 if len(sz)>0:
2345 print sz
2346 sys.exit(1)
2347
2348
2349def find_file(filename, search_paths):
2350 print "\n\n\tLooking for ",filename
2351 print "\t"+"-"*40
2352 for x in search_paths:
2353 print "\tSearching ",x
2354 temp = os.path.join(x, filename)
2355 if os.path.exists(temp):
2356 print "\n\t**Found %s (%i bytes)" % (temp,os.path.getsize(temp))
2357 return temp
2358
2359 ## search cwd last
2360 print "\tSearching ",os.getcwd()
2361 if os.path.exists(filename):
2362 print "\n\t**Found %s (%i bytes)" % (filename,os.path.getsize(filename))
2363 return filename
2364
2365 print "\tCound't find file\n"
2366 return None
2367
2368## ==============================================================================================
2369## ==============================================================================================
2370## ==============================================================================================
2371## =====main()===================================================================================
2372## ==============================================================================================
2373## ==============================================================================================
2374## ==============================================================================================
2375
2376if len(sys.argv) < 2:
2377 CreateErasingRawProgramFiles()
2378 ShowUsage()
2379 sys.exit(); # error
2380
2381print "\nCWD: ", os.getcwd(), "\n"
2382
2383try:
2384 opts, args = getopt.getopt(sys.argv[1:], "x:f:p:s:t:g:k:v:e", ["xml=", "format=", "partition=", "search_path=", "location=", "sequentialguid=", "use128partitions=", "verbose=","erasefirst"])
2385except getopt.GetoptError, err:
2386 # print help information and exit:
2387 print str(err) # will print something like "option -a not recognized"
2388 ShowUsage()
2389 sys.exit(1)
2390
2391XMLFile= "aaron"
2392OutputToCreate = None ## sys.argv[2]
2393PhysicalPartitionNumber = 0 ## sys.argv[3]
2394search_paths = []
2395
2396verbose = False
2397UsingGetOpts = False
2398sequentialguid = 0
2399force128partitions = 0
2400PhysicalPartitionNumber = -1
2401erasefirst = 0
2402
2403for o, a in opts:
2404 if o in ("-x", "--xml"):
2405 UsingGetOpts = True
2406 XMLFile = a
2407 elif o in ("-t", "--location"):
2408 OutputFolder = a
2409 OutputFolder = re.sub(r"\\$","",OutputFolder) # remove final slash if it exists
2410 OutputFolder = re.sub(r"/$","",OutputFolder) # remove final slash if it exists
2411
2412 OutputFolder += "/" # slashes will all be corrected below
2413
2414 if sys.platform.startswith("linux"):
2415 OutputFolder = re.sub(r"\\","/",OutputFolder) # correct slashes
2416 else:
2417 OutputFolder = re.sub(r"/","\\\\",OutputFolder) # correct slashes
2418
2419 print "OutputFolder=",OutputFolder
2420 EnsureDirectoryExists(OutputFolder) # only need to call once
2421
2422 elif o in ("-f", "--format"):
2423 UsingGetOpts = True
2424 OutputToCreate = a
2425 m = re.search("^(mbr|gpt)$", a) #mbr|gpt
2426 if type(m) is NoneType:
2427 PrintBigError("ERROR: Only MBR or GPT is supported")
2428 else:
2429 OutputToCreate = m.group(1)
2430
2431 elif o in ("-s", "--search_path"):
2432 ## also allow seperating commas
2433 for x in a.strip("\n").split(","):
2434 search_paths.append(x)
2435
2436 elif o in ("-k", "--use128partitions"):
2437 ## Force there to be 128 partitions in the partition table
2438 m = re.search("\d", a) #mbr|gpt
2439 if type(m) is NoneType:
2440 force128partitions = 0
2441 else:
2442 force128partitions = 1
2443
2444 elif o in ("-e", "--erasefirst"):
2445 erasefirst = 1;
2446
2447 elif o in ("-g", "--sequentialguid"):
2448 ## also allow seperating commas
2449 m = re.search("\d", a) #mbr|gpt
2450 if type(m) is NoneType:
2451 sequentialguid = 0
2452 else:
2453 sequentialguid = 1
2454
2455 elif o in ("-p", "--partition"):
2456 UsingGetOpts = True
2457 PhysicalPartitionNumber = a
2458 m = re.search("^(\d)$", a) #0|1|2
2459 if type(m) is NoneType:
2460 PrintBigError("ERROR: PhysicalPartitionNumber (-p) must be a number, you supplied *",a,"*")
2461 else:
2462 PhysicalPartitionNumber = int(m.group(1))
2463 elif o in ("-v", "--verbose"):
2464 UsingGetOpts = True
2465 verbose = True
2466 else:
2467 print "o=",o
2468 assert False, "unhandled option"
2469
2470if UsingGetOpts is False:
2471 #ParseCommandLine()
2472 PrintBanner("NEW USAGE - Note this program will auto-detect if it's GPT or MBR")
2473 ShowUsage()
2474 sys.exit(1)
2475
2476print "XMLFile=",XMLFile
2477if len(OutputFolder)>0:
2478 print "OutputFolder=",OutputFolder
2479print "OutputToCreate",OutputToCreate
2480print "PhysicalPartitionNumber",PhysicalPartitionNumber
2481print "verbose",verbose
2482
2483
2484XMLFile = find_file(XMLFile, search_paths)
2485if XMLFile is None:
2486 PrintBigError("ERROR: Could not find file")
2487
2488ParseXML(XMLFile) # parses XMLFile, discovers if GPT or MBR
2489
2490PrintBanner("OutputToCreate ===> '%s'" % OutputToCreate)
2491
2492def InitializeXMLFileVars():
2493 global EmmcLockRegionsXML,RawProgramXML,RawProgramXML_Wipe,PatchesXML,RawProgramXML_Blank,PatchesXML_Blank
2494
2495 EmmcLockRegionsXML = Element('protect')
2496 EmmcLockRegionsXML.append(Comment("NOTE: This is an ** Autogenerated file **"))
2497 EmmcLockRegionsXML.append(Comment('NOTE: Sector size is %ibytes, WRITE_PROTECT_BOUNDARY_IN_KB=%i, WRITE_PROTECT_BOUNDARY_IN_SECTORS=%i' % (SECTOR_SIZE_IN_BYTES,HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']))))
2498 EmmcLockRegionsXML.append(Comment("NOTE: \"num_sectors\" in HEX \"start_sector\" in HEX, i.e. 10 really equals 16 !!"))
2499
2500 RawProgramXML = Element('data')
2501 RawProgramXML.append(Comment('NOTE: This is an ** Autogenerated file **'))
2502 RawProgramXML.append(Comment('NOTE: Sector size is %ibytes'%SECTOR_SIZE_IN_BYTES))
2503
2504 RawProgramXML_Wipe = Element('data')
2505 RawProgramXML_Wipe.append(Comment('NOTE: This is an ** Autogenerated file **'))
2506 RawProgramXML_Wipe.append(Comment('NOTE: Sector size is %ibytes'%SECTOR_SIZE_IN_BYTES))
2507
2508 PatchesXML = Element('patches')
2509 PatchesXML.append(Comment('NOTE: This is an ** Autogenerated file **'))
2510 PatchesXML.append(Comment('NOTE: Patching is in little endian format, i.e. 0xAABBCCDD will look like DD CC BB AA in the file or on disk'))
2511 PatchesXML.append(Comment('NOTE: This file is used by Trace32 - So make sure to add decimals, i.e. 0x10-10=0, *but* 0x10-10.=6.'))
2512
2513 RawProgramXML_Blank = Element('data')
2514 RawProgramXML_Blank.append(Comment('NOTE: This is an ** Autogenerated file **'))
2515 RawProgramXML_Blank.append(Comment('NOTE: This file writes a VALID but EMPTY partition table to sector 0 **'))
2516 RawProgramXML_Blank.append(Comment('NOTE: Sector size is %ibytes'%SECTOR_SIZE_IN_BYTES))
2517
2518 PatchesXML_Blank = Element('patches')
2519 PatchesXML_Blank.append(Comment('NOTE: This is an ** Autogenerated file **'))
2520 PatchesXML_Blank.append(Comment('NOTE: Patching is in little endian format, i.e. 0xAABBCCDD will look like DD CC BB AA in the file or on disk'))
2521 PatchesXML_Blank.append(Comment('NOTE: This file is used by Trace32 - So make sure to add decimals, i.e. 0x10-10=0, *but* 0x10-10.=6.'))
2522
2523if OutputToCreate == "gpt":
2524 if PhysicalPartitionNumber == -1:
2525 for PhysicalPartitionNumber in range(0,len(PhyPartition)): ## where len(PhyPartition) is typically a maximum of 8
2526 InitializeXMLFileVars()
2527 CreateGPTPartitionTable( PhysicalPartitionNumber ) ## wants it in LBA format, i.e. 1KB = 2 sectors of size SECTOR_SIZE_IN_BYTES
2528 CreateErasingRawProgramFiles()
2529 print "\n\nNOTE: All Physical Partitions / LUNs were created since user did not use -p 0 option\n\n"
2530 else:
2531 InitializeXMLFileVars()
2532 CreateGPTPartitionTable( PhysicalPartitionNumber, True ) ## wants it in LBA format, i.e. 1KB = 2 sectors of size SECTOR_SIZE_IN_BYTES
2533 CreateErasingRawProgramFiles()
2534else:
2535 InitializeXMLFileVars()
2536 CreateMBRPartitionTable( PhysicalPartitionNumber )
2537 CreateFinalPartitionBin()
2538
2539
2540
2541