ipq6018mibib/scripts/msp.py
2025-09-28 10:20:07 +08:00

1864 lines
80 KiB
Python
Executable File

#!/usr/bin/python
#===========================================================================
# This script parses "partition.xml" and creates numerous output files
# specifically, partition.bin, rawprogram.xml
# REFERENCES
# $Header: //components/rel/boot.bf/3.1.1/boot_images/core/storage/tools/ptool/msp.py#1 $
# $DateTime: 2014/09/09 14:47:07 $
# $Author: pwbldsvc $
# when who what, where, why
# -------- --- -------------------------------------------------------
# 2012-03-29 ah Warning message displayed *last* now if warnings happen
# 2012-03-12 ah Better warning if attempting to write to a PHY partition other than 0
# 2012-02-24 ah Much cleaner code - fixes for configurable sector sizes
# 2011-10-19 ah Allow patching of rawprogram files for PHY partitions other than 0
# 2011-09-23 ah Patching now supports NumPartitions that isn't fixed to 128
# 2011-09-21 ah added "msp failed" messages
# 2011-09-07 ah log name change - fixes for Linux os.system
# 2011-08-17 ah If testsparse.py exists, performing additional safety check
# 2011-08-12 ah Better use of noprompt option (-n)
# 2011-08-09 ah -t option specifies output directory for files
# 2011-08-01 ah Bug fix whhen patching DISK
# 2011-07-26 ah Much better error messages
# 2011-07-21 ah Major changes, now using getopt(), patching/writing can be all one step
# 2011-07-13 ah Better error messages for user experience
# 2011-06-01 ah Improved singleimage support for GPT
# 2011-05-26 ah Handles sparse files and "zeroout" tag
# 2011-05-17 ah Removed auto-patching MBR - must manually patch just like in GPT
# 2011-05-02 ah No longer querying for /proc/partitions by default (user must ask now)
# 2011-03-22 ah Enforcing that msp can't patch/write to partitions other than USER
# 2011-03-22 ah Fixed memory bug with large file writing, fixed bug with SINGLEIMAGE creation (i.e. append)
# 2011-03-16 ah Fixed memory bug with large file patching and read/write permissions for
# SCons and singleimage.bin, Now need user input when patching DISK, "sync" command for linux
# 2011-03-09 ah Replaces msp.exe - compatible with Linux and Windows
# does not need cygwin, cleaner code, more error checking
# 2011-02-14 ah Changed 'dd' to 'cat' to avoid error happening on Win7
# 2010-10-26 ah Now "patches" partition table on the fly, adds warnings before nuking drive
# 2010-10-22 ah Used to replace msp.exe - can program cards and singleimages.bin
# Copyright (c) 2007-2010, 2017 Qualcomm Technologies, Inc.
# All Rights Reserved.
# Confidential and Proprietary - Qualcomm Technologies, Inc.
# ===========================================================================*/
import struct, os, sys, getopt
import math,traceback
import re
import codecs
from types import *
import time
from time import sleep
import subprocess as sub
from time import strftime, localtime
from xml.etree import ElementTree as ET
#from elementtree.ElementTree import ElementTree
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from xml.dom import minidom
DiskSectors = 0
BLOCK_SIZE = 0x200
TABLE_ENTRY_0 = 0x1BE
TABLE_ENTRY_1 = 0x1CE
TABLE_ENTRY_2 = 0x1DE
TABLE_ENTRY_3 = 0x1EE
EMMCBLD_MAX_DISK_SIZE_IN_BYTES = (64*1024*1024*1024*1024) # 64TB - Terabytes
MAX_FILE_SIZE_BEFORE_SPLIT = (10*1024*1024)
#MAX_FILE_SIZE_BEFORE_SPLIT = (2048) # testing purposes
ExtendedPartitionBegins = 0
bytes_read = 0
FileNotFoundShowWarning = 0
SECTOR_SIZE = 512
disk_size = None
def reset_device_log():
try:
log_fp = open('log_msp.txt', 'w')
except Exception, x:
print "\nERROR: Can't create the file log_msp.txt"
print "REASON: %s" % x
print "This might be because the file is open and locked"
print "Or because you are running this from a read-only location\n"
sys.exit()
print "\nCREATED log_msp.txt\n"
log_fp.close()
def device_log(message, display=1):
try:
log_fp = open('log_msp.txt', 'a')
except Exception, x:
print "ERROR: could not open 'log_msp.txt'"
print "REASON: %s" % x
return
try:
log_fp.write("%s %s\n" % (strftime("%H:%M:%S", localtime()),message))
except Exception, x:
print "ERROR: could not write to 'log_msp.txt'"
print "REASON: %s" % x
return
if display==1:
print message
log_fp.close()
def ReadSectors(opfile,NumSectors):
try:
return opfile.read(NumSectors*SECTOR_SIZE)
except Exception, x:
PrintBigError("Could not complete the read")
device_log("REASON: %s" % (x))
reset_device_log()
device_log("\nmsp.py is running from CWD: %s\n" % os.getcwd())
def EnsureDirectoryExists(filename):
dir = os.path.dirname(filename)
try:
os.stat(dir)
except Exception, x:
os.makedirs(dir)
def PrintBigWarning(sz):
device_log("\t _ ")
device_log("\t (_) ")
device_log("\t__ ____ _ _ __ _ __ _ _ __ __ _ ")
device_log("\t\\ \\ /\\ / / _` | '__| '_ \\| | '_ \\ / _` |")
device_log("\t \\ V V / (_| | | | | | | | | | | (_| |")
device_log("\t \\_/\\_/ \\__,_|_| |_| |_|_|_| |_|\\__, |")
device_log("\t __/ |")
device_log("\t |___/ \n")
if len(sz)>0:
device_log(sz)
def PrintBigError(sz):
device_log("\t _________________ ___________ ")
device_log("\t| ___| ___ \\ ___ \\ _ | ___ \\")
device_log("\t| |__ | |_/ / |_/ / | | | |_/ /")
device_log("\t| __|| /| /| | | | / ")
device_log("\t| |___| |\\ \\| |\\ \\\\ \\_/ / |\\ \\ ")
device_log("\t\\____/\\_| \\_\\_| \\_|\\___/\\_| \\_|\n")
device_log("\nERROR - ERROR - ERROR - ERROR - ERROR\n")
if len(sz)>0:
device_log(sz)
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
def PrettyPrintArray(bytes_read):
Bytes = struct.unpack("%dB" % len(bytes_read),bytes_read)
for k in range(len(Bytes)/SECTOR_SIZE):
print "-"*78
for j in range(32):
for i in range(16):
sys.stdout.write("%.2X " % Bytes[i+j*16])
sys.stdout.write("\t")
for i in range(16):
sys.stdout.write("%c" % Bytes[i+j*16])
print " "
print " "
def external_call(command, capture_output=True):
errors = None
output = None
try:
if capture_output:
if sys.platform.startswith("linux"):
p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE, shell=True)
else:
p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE)
output, errors = p.communicate()
else:
os.system(command)
except Exception, e:
print output
device_log("Error executing command '%s' (%s)" % (str(command), e))
#clean_up()
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
finally:
#if not output is None:
# device_log("Result: %s" % output)
if (not errors is None) and (not errors == ""):
device_log("Process stderr: %s" % errors)
return output
def HandleNUM_DISK_SECTORS(field):
if type(field) is not str:
#print "returning since this is not a string"
return field
m = re.search("NUM_DISK_SECTORS-(\d+)", field)
if type(m) is not NoneType:
if DiskSizeInBytes > 0 :
field = int((DiskSizeInBytes/SECTOR_SIZE)-int(m.group(1))) # here I know DiskSizeInBytes
else:
field = int((EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE)+int(m.group(1))) # I make this a gigantic number for sorting (PLUS not MINUS here)
if type(field) is not str:
return field
m = re.search("NUM_DISK_SECTORS", field)
if type(m) is not NoneType:
if DiskSizeInBytes > 0 :
field = int((DiskSizeInBytes/SECTOR_SIZE))
else:
field = int((EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE))
if type(field) is not str:
return field
field = int(field)
return field
def ReturnParsedValues(element):
global SECTOR_SIZE
MyDict = { 'filename':'','file_sector_offset':'0','label':'','num_partition_sectors':'0',
'physical_partition_number':'0','size_in_KB':'0','sparse':'false','start_byte_hex':'0x0','start_sector':'0',
'function':'none','arg0':'0','arg1':'0','value':'0','byte_offset':'0','size_in_bytes':'4','SECTOR_SIZE_IN_BYTES':'512' }
for name, value in element.items():
##device_log("\t\tName: '%s'=>'%s' " % (name,value))
MyDict[name]=value
if 'SECTOR_SIZE_IN_BYTES' in MyDict:
SECTOR_SIZE = int(MyDict['SECTOR_SIZE_IN_BYTES'])
if 'num_sectors' in MyDict: ## Legacy name used in original partition.xml
MyDict['num_partition_sectors'] = MyDict['num_sectors']
if 'offset' in MyDict: ## Legacy name used in original partition.xml
MyDict['file_sector_offset'] = MyDict['offset']
MyDict['num_partition_sectors'] = HandleNUM_DISK_SECTORS(MyDict['num_partition_sectors']) # Means field can have 'NUM_DISK_SECTORS-5.' type of contents
MyDict['start_sector'] = HandleNUM_DISK_SECTORS(MyDict['start_sector']) # Means field can have 'NUM_DISK_SECTORS-5.' type of contents
MyDict['file_sector_offset'] = HandleNUM_DISK_SECTORS(MyDict['file_sector_offset']) # Means field can have 'NUM_DISK_SECTORS-5.' type of contents
MyDict['physical_partition_number'] = int(MyDict['physical_partition_number'])
MyDict['byte_offset'] = int(float(MyDict['byte_offset']))
MyDict['size_in_bytes'] = int(float(MyDict['size_in_bytes']))
# These only affect patching
m = re.search("CRC32\((\d+).?,(\d+).?\)", MyDict['value'])
if type(m) is not NoneType:
MyDict['value'] = 0
MyDict['function'] = "CRC32"
MyDict['arg0'] = int(float(m.group(1))) # start_sector
MyDict['arg1'] = int(float(m.group(2))) # len_in_bytes
else:
## above didn't match, so try this
m = re.search("CRC32\((NUM_DISK_SECTORS-\d+).?,(\d+).?\)", MyDict['value'])
if type(m) is not NoneType:
MyDict['value'] = 0
MyDict['function'] = "CRC32"
MyDict['arg0'] = int(float( HandleNUM_DISK_SECTORS(m.group(1)) )) # start_sector
MyDict['arg1'] = int(float(m.group(2))) # len_in_bytes
MyDict['value'] = HandleNUM_DISK_SECTORS(MyDict['value']) # Means field can have 'NUM_DISK_SECTORS-5.' type of contents
return MyDict
def ParseXML(xml_filename): ## this function updates all the global arrays
global WriteArray,PatchArray,ReadArray,MinDiskSizeInSectors
root = ET.parse( xml_filename )
#Create an iterator
iter = root.getiterator()
for element in iter:
#device_log("\nElement: %s" % element.tag)
# Parse out include files
if element.tag=="read":
if element.keys():
ReadArray.append( ReturnParsedValues(element) )
else:
print "ERROR: Your <read> tag is not formed correctly\n"
sys.exit(1)
elif element.tag=="program":
if element.keys():
WriteArray.append( ReturnParsedValues(element) )
else:
print "ERROR: Your <program> tag is not formed correctly\n"
sys.exit(1)
elif element.tag=="patch":
if element.keys():
PatchArray.append( ReturnParsedValues(element) )
else:
print "ERROR: Your <patch> tag is not formed correctly\n"
sys.exit(1)
#print "\n\n-------------READ -----------------------------------\n\n\n"
#for Read in ReadArray:
# print Read
#print "\n\n-------------WRITE -----------------------------------\n\n\n"
#for Write in WriteArray:
# print Write
#print "\n\n-------------PATCH -----------------------------------\n\n\n"
#for Patch in PatchArray:
# print Patch
#print "------------------------------------------------\n\n\n"
def ReturnArrayFromCommaSeparatedList(sz):
temp = re.sub("\s+|\n"," ",sz)
temp = re.sub("^\s+","",temp)
temp = re.sub("\s+$","",temp)
return temp.split(',')
def find_file(filename, search_paths):
device_log("\n\n\tLooking for '%s'"%filename)
device_log("\t"+"-"*40)
for x in search_paths:
#device_log("\tSearching '%s'"%x)
temp = os.path.join(x, filename)
device_log("\tSearching for **%s**" % temp)
if os.path.exists(temp):
device_log("\n\t**Found %s (%i bytes)" % (temp,os.path.getsize(temp)))
return temp
## search cwd last
device_log("\tSearching '%s'"%os.getcwd())
if os.path.exists(filename):
device_log("\n\t**Found %s (%i bytes)" % (filename,os.path.getsize(filename)))
return filename
device_log("\tCound't find file OR perhaps you don't have permission to run os.stat() on this file\n")
return None
def DoubleCheckDiskSize():
if os.path.basename(Filename)=="singleimage.bin":
return
if noprompt is True:
return
if sys.platform.startswith("win"):
device_log("\n\nTesting of OS detected disk size correctly...\n")
Size = AvailablePartitions[Filename]
TrueSize = Size
count = 0
# Windows workaround to get the correct number of sectors
fp = open(Filename, 'rb')
fp.seek(int(Size))
try:
while True:
fp.read(SECTOR_SIZE)
if count % 128 == 0:
sys.stdout.write(".")
count += 1
except Exception, x:
TrueSize = fp.tell()
fp.close()
if TrueSize != Size and Size<=(64*1024*1024*1024):
PrintBigWarning(" ")
device_log("NOTE: This OS has *not* detected the correct size of the disk")
device_log("\nSECTORS: Size=%i, TrueSize=%i, Difference=%i sectors (%s)" % (Size/SECTOR_SIZE,TrueSize/SECTOR_SIZE,(TrueSize-Size)/SECTOR_SIZE,ReturnSizeString(TrueSize-Size)))
device_log("This means the backup GPT header will *not* be located at the true last sector")
device_log("This is only an issue if you care :) It will be off by %s" % ReturnSizeString(TrueSize-Size))
device_log("\nNOTE: This program *can't* write to the end of the disk, OS limitation")
else:
device_log("\n\nAll is well\n")
def PerformRead():
global ReadArray, search_paths, interactive, Filename
device_log("\t _ _ ")
device_log("\t | (_) ")
device_log("\t _ __ ___ __ _ __| |_ _ __ __ _ ")
device_log("\t| '__/ _ \\/ _` |/ _` | | '_ \\ / _` |")
device_log("\t| | | __/ (_| | (_| | | | | | (_| |")
device_log("\t|_| \\___|\\__,_|\\__,_|_|_| |_|\\__, |")
device_log("\t __/ |")
device_log("\t |___/ ")
CurrentSector = 0
for ReadCmd in ReadArray:
##<read filename="dump0.bin" physical_partition_number="0" start_sector="0" num_partition_sectors="34"/>
device_log("\nRead %d sectors (%s) from sector %d and save to '%s'\n" % (ReadCmd['num_partition_sectors'],ReturnSizeString(ReadCmd['num_partition_sectors']*SECTOR_SIZE),ReadCmd['start_sector'],ReadCmd['filename']))
if ReadCmd['physical_partition_number']!=0: ## msp tool can only write to PHY partition 0
device_log("WARNING '%s' for physical_partition_number=%d (only 0 is accessible) THIS MIGHT FAIL" % (ReadCmd['filename'],ReadCmd['physical_partition_number']))
if len(ReadCmd['filename'])==0:
device_log("WARNING filename was not specified, skipping this read")
continue
if ReadCmd['num_partition_sectors']==0:
device_log("WARNING num_partition_sectors was 0, skipping this read")
continue
if interactive is True:
device_log("Do you want to perform this read? (Y|n|q)",0)
loadfile = raw_input("Do you want to perform this read? (Y|n|q)")
if loadfile=='Y' or loadfile=='y' or loadfile=='':
pass
elif loadfile=='q' or loadfile=='Q':
device_log("\nmsp.py exiting by user pressing Q (quit) - Log is log_msp.txt\n\n")
sys.exit()
else:
continue
try:
if os.path.basename(Filename)=="singleimage.bin":
Filename = OutputFolder+os.path.basename(Filename)
opfile = open(Filename, "r+b") ## Filename = '\\.\PHYSICALDRIVE1'
#device_log("Opened '%s', cwd=%s" % (Filename, os.getcwd() ))
except:
PrintBigError("")
device_log("Could not open Filename=%s, cwd=%s" % (Filename, os.getcwd() ))
if sys.platform.startswith("linux"):
print "\t _ ___"
print "\t | | |__ \\"
print "\t ___ _ _ __| | ___ ) |"
print "\t/ __| | | |/ _` |/ _ \\ / /"
print "\t\\__ \\ |_| | (_| | (_) |_|"
print "\t|___/\\__,_|\\__,_|\\___/(_)\n"
device_log("\tDon't forget you need SUDO with this program")
device_log("\tsudo python msp.py partition.xml /dev/sdx (where x is the device node)")
else:
device_log("\t ___ _ _ _ _ _ ___ ")
device_log("\t / _ \\ | | (_) (_) | | | | |__ \\ ")
device_log("\t/ /_\\ \\ __| |_ __ ___ _ _ __ _ ___| |_ _ __ __ _| |_ ___ _ __ ) |")
device_log("\t| _ |/ _` | '_ ` _ \\| | '_ \\| / __| __| '__/ _` | __|/ _ \\| '__| / / ")
device_log("\t| | | | (_| | | | | | | | | | | \\__ \\ |_| | | (_| | |_| (_) | | |_| ")
device_log("\t\\_| |_/\\__,_|_| |_| |_|_|_| |_|_|___/\\__|_| \\__,_|\\__|\\___/|_| (_) \n\n")
device_log("\n"+"-"*78)
device_log("\tThis program needs to be run as Administrator!!")
device_log("-"*78+"\n")
device_log("-"*78)
device_log("\tTo fix, you must open a CMD prompt with \"Run as administrator\"")
device_log("-"*78+"\n")
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit()
device_log("\n\tOpened %s" % Filename)
if ReadCmd['start_sector'] < 0:
device_log("start sector is less than 0 - skipping this instruction, most likely for GPT HACK")
continue
if ReadCmd['start_sector'] > int(DiskSizeInBytes/SECTOR_SIZE):
PrintBigError("")
device_log("\nERROR: Start sector (%i) is BIGGER than the disk (%i sectors)" % (ReadCmd['start_sector'],int(DiskSizeInBytes/SECTOR_SIZE)))
device_log("\nERROR: Your device is TOO SMALL to handle this partition info")
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
try:
opfile.seek(int(ReadCmd['start_sector']*SECTOR_SIZE))
except:
PrintBigError("Could not move to sector %d on %s" % (ReadCmd['start_sector'],Filename))
device_log("\tMoved to sector %d on %s" % (ReadCmd['start_sector'],Filename))
size = int(ReadCmd['num_partition_sectors']*SECTOR_SIZE)
device_log("\tAttempting to read %i bytes" % (size))
try:
bytes_read = opfile.read(size)
except:
PrintBigError("Could not read %d bytes in %s" % (size,ReadCmd['filename']))
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit()
try:
opfile.close()
except:
device_log("\tWARNING: Can't close the file?")
#sys.exit()
pass
try:
ipfile = open(ReadCmd['filename'], "wb")
except:
PrintBigError("Could not create filename=%s, cwd=%s" % (ReadCmd['filename'], os.getcwd() ))
sys.exit(1)
try:
ipfile.write(bytes_read)
except:
PrintBigError("")
device_log("Could not write to %s" % (ReadCmd['filename']))
sys.exit(1)
try:
ipfile.close()
except:
device_log("\tWARNING: Can't close the file?")
#sys.exit()
pass
device_log("\nDone Reading Files\n")
def PerformWrite():
global WriteSorted, LoadSubsetOfFiles, search_paths, interactive, Filename
ThereWereWarnings = 0
device_log("\t _ ")
device_log("\t (_) ")
device_log("\t _ __ _ __ ___ __ _ _ __ __ _ _ __ ___ _ __ ___ _ _ __ __ _ ")
device_log("\t| '_ \\| '__/ _ \\ / _` | '__/ _` | '_ ` _ \\| '_ ` _ \\| | '_ \\ / _` |")
device_log("\t| |_) | | | (_) | (_| | | | (_| | | | | | | | | | | | | | | | (_| |")
device_log("\t| .__/|_| \\___/ \\__, |_| \\__,_|_| |_| |_|_| |_| |_|_|_| |_|\\__, |")
device_log("\t| | __/ | __/ |")
device_log("\t|_| |___/ |___/ ")
CurrentSector = 0
for Write in WriteSorted: # Here Write is a *sorted* entry from rawprogram.xml
if Write['physical_partition_number']!=0: ## msp tool can only write to PHY partition 0
PrintBigWarning("WARNING: '%s' for physical_partition_number=%d (only 0 is accessible) THIS MIGHT FAIL" % (Write['filename'],Write['physical_partition_number']))
device_log("WARNING '%s' for physical_partition_number=%d (only 0 is accessible) THIS MIGHT FAIL" % (Write['filename'],Write['physical_partition_number']))
device_log("WARNING '%s' for physical_partition_number=%d (only 0 is accessible) THIS MIGHT FAIL" % (Write['filename'],Write['physical_partition_number']))
device_log("WARNING '%s' for physical_partition_number=%d (only 0 is accessible) THIS MIGHT FAIL" % (Write['filename'],Write['physical_partition_number']))
if len(Write['filename'])==0:
continue
if LoadSubsetOfFiles is True:
# To be here means user only wants some of the files loaded from rawprogram0.xml
if Write['filename'] in file_list:
#device_log("LOAD: '%s' was specified to be programmed" % Write['filename'])
pass
else:
#device_log("SKIPPING: '%s', it was not specified to be programmed" % Write['filename'])
continue
device_log("\n"+"="*78)
device_log("="*78)
FileWithPath = find_file(Write['filename'], search_paths)
size=0
if FileWithPath is not None:
size = os.path.getsize(FileWithPath)
# to be here the rawprogram.xml file had to have a "filename" entry
device_log("\n'%s' (%s) to partition '%s' at sector %d (at %s)\n" % (Write['filename'],ReturnSizeString(size),Write['label'],Write['start_sector'],ReturnSizeString(Write['start_sector']*SECTOR_SIZE)))
if interactive is True:
device_log("Do you want to load this file? (Y|n|q)",0)
loadfile = raw_input("Do you want to load this file? (Y|n|q)")
if loadfile=='Y' or loadfile=='y' or loadfile=='':
pass
elif loadfile=='q' or loadfile=='Q':
device_log("\nmsp.py exiting by user pressing Q (quit) - Log is log_msp.txt\n\n")
sys.exit()
else:
continue
while FileWithPath is None:
FileNotFoundShowWarning = 1
device_log("\t______ _ _ ___ ")
device_log("\t| ___ \\ | | | | |__ \\ ")
device_log("\t| |_/ /__ _| |_| |__ ) |")
device_log("\t| __// _` | __| '_ \\ / / ")
device_log("\t| | | (_| | |_| | | | |_| ")
device_log("\t\\_| \\__,_|\\__|_| |_| (_) \n\n")
device_log("WARNING: '%s' listed in '%s' not found\n" % (Write['filename'],rawprogram_filename))
if noprompt is True:
device_log("\nUse option -s c:\\path1 -s c:\\path2 etc")
PrintBigError("")
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
device_log("Please provide a path for this file")
device_log("Ex. \\\\somepath\\folder OR c:\\somepath\\folder\n")
device_log("Enter PATH or Q to quit? ",0)
temppath = raw_input("Enter PATH or Q to quit? ")
if temppath=='Q' or temppath=='q' or temppath=='':
device_log("\nmsp.py exiting - user pressed Q (quit) - Log is log_msp.txt\n\n")
sys.exit()
device_log("\n")
FileWithPath = find_file(Write['filename'], [temppath])
size=0
if FileWithPath is not None:
size = os.path.getsize(FileWithPath)
device_log("\nShould this path be used to find other files? (Y|n|q)",0)
temp = raw_input("\nShould this path be used to find other files? (Y|n|q)")
if temp=='Q' or temp=='q':
device_log("\nmsp.py exiting - user pressed Q (quit) - Log is log_msp.txt\n\n")
sys.exit()
elif temp=='Y' or temp=='y' or temp=='':
search_paths.append(temppath)
device_log("\n")
if noprompt is False:
if size==0:
device_log("WARNING: This file is 0 bytes, do you want to load this file? (y|N|q)",0)
loadfile = raw_input("WARNING: This file is 0 bytes, do you want to load this file? (y|N|q)")
if loadfile=='N' or loadfile=='n' or loadfile=='':
continue
elif loadfile=='q' or loadfile=='Q':
device_log("\nmsp.py exiting - user pressed Q (quit) - Log is log_msp.txt\n\n")
sys.exit()
else:
pass
if Write['num_partition_sectors']==0:
Write['num_partition_sectors'] = int(size/SECTOR_SIZE)
if size%SECTOR_SIZE != 0:
Write['num_partition_sectors']+=1 # not an even multiple of SECTOR_SIZE, so ++
##device_log("At start_sector %i (%.2fKB) write %i sectors" % (Write['start_sector'],Write['start_sector']*SECTOR_SIZE/1024.0,Write['num_partition_sectors']))
##device_log("\tsize of \"%s\" is %i bytes" % (Write['filename'],size))
##device_log("\tsize of partition listed in in \"%s\" is %i bytes" % (rawprogram_filename,Write['num_partition_sectors']*SECTOR_SIZE))
## This below happens on files like partition0.bin, where they hold the entire partition table,
## but, only MBR is meant to be written, thus partition0.bin is 9 sectors but MBR is only 1 sector
if size > (Write['num_partition_sectors']*SECTOR_SIZE):
PrintBigWarning("WARNING: This complete image of size %i bytes is too big to fit on this partition of size %i bytes" % (size,Write['num_partition_sectors']*SECTOR_SIZE))
PrintBigWarning("WARNING: Only the first %i bytes of your image will be written\n\n" % (Write['num_partition_sectors']*SECTOR_SIZE))
size = Write['num_partition_sectors']*SECTOR_SIZE
ThereWereWarnings = 1
##device_log("\tAttempting to read %i bytes from \n\t\"%s\" at file_sector_offset %i" % (size,Write['filename'],Write['file_sector_offset']))
#os.getcwd()+"\\"+
try:
ipfile = open(FileWithPath, "rb")
except Exception, x:
PrintBigError("Could not open FileWithPath=%s, cwd=%s\nREASON: %s" % (Write['filename'], os.getcwd(), x ))
device_log("\tAttempting to move to sector %i (file file_sector_offset) in %s" % (Write['file_sector_offset'],Write['filename']))
try:
ipfile.seek(int(Write['file_sector_offset']*SECTOR_SIZE))
except Exception, x:
PrintBigError("Could not move to sector %d in %s\nREASON: %s" % (Write['file_sector_offset'],Write['filename'],x))
device_log("\tAttempting to read %i bytes" % (size))
try:
if size<MAX_FILE_SIZE_BEFORE_SPLIT:
bytes_read = ipfile.read(size)
else:
device_log("File is too large to read all at once, must be broken up")
except Exception, x:
PrintBigError("Could not read %d bytes in %s\nREASON: %s" % (size,Write['filename'],x))
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit()
if size<MAX_FILE_SIZE_BEFORE_SPLIT:
ipfile.close()
if size<MAX_FILE_SIZE_BEFORE_SPLIT:
device_log("\tSuccessfully read %d bytes of %d bytes and closed %s" % (len(bytes_read),size,Write['filename']))
Remainder = len(bytes_read)%SECTOR_SIZE
if Remainder != 0:
device_log("\tbytes_read is not a multiple of SECTOR_SIZE (%d bytes), appending zeros" % SECTOR_SIZE)
Bytes = struct.unpack("%dB" % len(bytes_read),bytes_read) ## unpack returns list, so get index 0
Temp = list(Bytes) + [0x00]*(SECTOR_SIZE-Remainder) # concat
TotalSize = len(Temp)
bytes_read = struct.pack("%dB" % TotalSize, *Temp)
device_log("\tNow len(bytes_read)=%d" % len(bytes_read))
# At this point bytes_read is a multiple of SECTOR_SIZE
#device_log("\t\tNeed to move to location %i (%i bytes) in %s" % (Write['start_sector'],(Write['start_sector']*SECTOR_SIZE),Filename))
#device_log("\t\tPartition['start_sector']*SECTOR_SIZE = %i" % (Write['start_sector']*SECTOR_SIZE))
if (2*DiskSizeInBytes)<Write['start_sector'] and os.path.basename(Filename)!="singleimage.bin":
device_log("2*DiskSizeInBytes=%d" % (2*DiskSizeInBytes))
device_log("Write['start_sector']=%i"%Write['start_sector'])
PrintBigError("Attempting to move to sector %i (%.2f MB) and only %i sectors (%.2f MB) exist (%i difference (%.2f MB) )" % (Write['start_sector'],Write['start_sector']*SECTOR_SIZE/1024.0,2*DiskSizeInBytes,DiskSizeInBytes/1024.0,Write['start_sector']-(2*DiskSizeInBytes),(Write['start_sector']-(2*DiskSizeInBytes))/2048.0))
try:
if os.path.basename(Filename)=="singleimage.bin":
Filename = OutputFolder+os.path.basename(Filename)
opfile = open(Filename, "r+b") ## Filename = '\\.\PHYSICALDRIVE1'
except Exception, x:
PrintBigError("")
device_log("Could not open Filename=%s, cwd=%s" % (Filename, os.getcwd() ))
device_log("REASON: %s" % (x))
if sys.platform.startswith("linux"):
print "\t _ ___"
print "\t | | |__ \\"
print "\t ___ _ _ __| | ___ ) |"
print "\t/ __| | | |/ _` |/ _ \\ / /"
print "\t\\__ \\ |_| | (_| | (_) |_|"
print "\t|___/\\__,_|\\__,_|\\___/(_)\n"
device_log("\tDon't forget you need SUDO with this program")
device_log("\tsudo python msp.py partition.xml /dev/sdx (where x is the device node)")
else:
device_log("\t ___ _ _ _ _ _ ___ ")
device_log("\t / _ \\ | | (_) (_) | | | | |__ \\ ")
device_log("\t/ /_\\ \\ __| |_ __ ___ _ _ __ _ ___| |_ _ __ __ _| |_ ___ _ __ ) |")
device_log("\t| _ |/ _` | '_ ` _ \\| | '_ \\| / __| __| '__/ _` | __|/ _ \\| '__| / / ")
device_log("\t| | | | (_| | | | | | | | | | | \\__ \\ |_| | | (_| | |_| (_) | | |_| ")
device_log("\t\\_| |_/\\__,_|_| |_| |_|_|_| |_|_|___/\\__|_| \\__,_|\\__|\\___/|_| (_) \n\n")
device_log("\n"+"-"*78)
device_log("\tThis program needs to be run as Administrator!!")
device_log("-"*78+"\n")
device_log("-"*78)
device_log("\tTo fix, you must open a CMD prompt with \"Run as administrator\"")
device_log("-"*78+"\n")
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit()
device_log("opfile = open('%s', 'r+b') , cwd=%s" % (Filename, os.getcwd() ))
device_log("\n\tOpened %s" % Filename)
if Write['start_sector'] < 0:
device_log("start sector is less than 0 - skipping this instruction, most likely for GPT HACK")
continue
if Write['start_sector'] > int(DiskSizeInBytes/SECTOR_SIZE):
PrintBigError("")
device_log("\nERROR: Start sector (%i) is BIGGER than the disk (%i sectors)" % (Write['start_sector'],int(DiskSizeInBytes/SECTOR_SIZE)))
device_log("\nERROR: Your device is TOO SMALL to handle this partition info")
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
if int(Write['start_sector']) > 0:
try:
opfile.seek(int(Write['start_sector']*SECTOR_SIZE))
except Exception, x:
PrintBigError("Could not move to sector %d on %s" % (Write['start_sector'],Filename))
device_log("REASON: %s" % (x))
device_log("\tMoved to sector %d on %s" % (Write['start_sector'],Filename))
CurrentSector = Write['start_sector']
##device_log("size=",size)
##device_log("MAX_FILE_SIZE_BEFORE_SPLIT=",MAX_FILE_SIZE_BEFORE_SPLIT)
CurrentSector += (size/SECTOR_SIZE)
if size<MAX_FILE_SIZE_BEFORE_SPLIT:
device_log("\tFile can be written completely.")
device_log("\tCalling opfile.write(bytes_read)")
try:
opfile.write(bytes_read)
except Exception, x:
PrintBigError("")
device_log("Could not write %d bytes to %s" % (len(bytes_read),Filename))
device_log("REASON: %s" % (x))
device_log("\nPlease try removing the medium and re-inserting it")
device_log("Strangly this helps sometimes after writing *new* partition tables\n\n")
#traceback.print_exc(file=sys.stdout)
#traceback.print_exc()
sys.exit(1)
else:
## To be here means I need to break up the file
##device_log("I need to break up this file")
TempSize = size
NumLoop = int(TempSize/MAX_FILE_SIZE_BEFORE_SPLIT)
Remainder = size%MAX_FILE_SIZE_BEFORE_SPLIT
if Remainder>0:
Remainder=1
device_log("\nNeed to break up this file, will loop %d times writing %i bytes each time" % (NumLoop+Remainder,MAX_FILE_SIZE_BEFORE_SPLIT))
TempSize=0
for a in range(NumLoop):
#device_log("read %i bytes" % MAX_FILE_SIZE_BEFORE_SPLIT)
try:
bytes_read = ipfile.read(MAX_FILE_SIZE_BEFORE_SPLIT)
except Exception, x:
PrintBigError("Could not read from %s\nREASON: %s" % (FileWithPath,x))
##device_log("\n\t%i) Packing %i Bytes [%i:%i]" % (a+1,MAX_FILE_SIZE_BEFORE_SPLIT,TempSize,TempSize+MAX_FILE_SIZE_BEFORE_SPLIT))
##bytes_read = struct.pack("%dB" % MAX_FILE_SIZE_BEFORE_SPLIT, *Bytes[TempSize:(TempSize+MAX_FILE_SIZE_BEFORE_SPLIT)])
device_log("\t%.2i) Writing %i Bytes [%i:%i]" % (a+1,MAX_FILE_SIZE_BEFORE_SPLIT,TempSize,TempSize+MAX_FILE_SIZE_BEFORE_SPLIT))
try:
opfile.write(bytes_read)
except Exception, x:
PrintBigError("Could not write to %s\nREASON: %s" % (Filename,x))
TempSize += MAX_FILE_SIZE_BEFORE_SPLIT
##device_log("Out of loop")
a+=1
if Remainder == 1:
# Need to PAD the file to be a multiple of SECTOR_SIZE bytes too
#device_log("\n\t%i) Packing %i Bytes [%i:%i]" % (a,(len(Bytes)-TempSize),TempSize,len(Bytes)))
#bytes_read = struct.pack("%dB" % (len(Bytes)-TempSize), *Bytes[TempSize:len(Bytes)])
device_log("\t%.2i) Writing %i Bytes [%i:%i]" % (a+1,(size-TempSize),TempSize,size))
try:
bytes_read = ipfile.read(size-TempSize)
except Exception, x:
PrintBigError("Could not read from %s\nREASON: %s" % (FileWithPath,x))
##device_log("len(bytes_read)=",len(bytes_read))
Remainder = len(bytes_read)%SECTOR_SIZE
if Remainder != 0:
device_log("\tbytes_read is not a multiple of SECTOR_SIZE (%d bytes), appending zeros" % SECTOR_SIZE)
Bytes = struct.unpack("%dB" % len(bytes_read),bytes_read) ## unpack returns list, so get index 0
Temp = list(Bytes) + [0x00]*(SECTOR_SIZE-Remainder) # concat
TotalSize = len(Temp)
bytes_read = struct.pack("%dB" % TotalSize, *Temp)
device_log("\tNow len(bytes_read)=%d" % len(bytes_read))
# At this point bytes_read is a multiple of SECTOR_SIZE
#device_log("This is the final write")
try:
opfile.write(bytes_read)
except Exception, x:
PrintBigError("Could not write to %s\nREASON: %s" % (Filename,x))
ipfile.close()
if os.path.basename(Filename)=="singleimage.bin":
device_log("\tSingleImageSize %i bytes (%i sectors)" % (CurrentSector*SECTOR_SIZE,CurrentSector))
device_log("\tCurrentSector=%i" % CurrentSector)
device_log("\tDiskSize=%i sectors" % int(DiskSizeInBytes/SECTOR_SIZE))
#device_log("\tWrote %d bytes at sector %d on %s" % (len(bytes_read),Write['start_sector'],Filename))
try:
##print opfile
opfile.close()
except Exception, x:
device_log("\tWARNING: Can't close the file?")
device_log("REASON: %s" % (x))
#sys.exit()
pass
device_log("\n\tWritten with")
device_log("\tpython dd.py --if=%s --bs=%i --count=%i --seek=%i --of=%s" % (FileWithPath,SECTOR_SIZE,int((size-1)/SECTOR_SIZE)+1,Write['start_sector'],Filename))
device_log("\n\tVerify with")
device_log("\tpython dd.py --if=%s --bs=%i --count=%i --skip=%i --of=dump.bin" % (Filename,SECTOR_SIZE,int((size-1)/SECTOR_SIZE)+1,Write['start_sector']))
device_log("\n\tSuccessfully wrote \"%s\" (%s payload) to %s" % (Write['filename'],ReturnSizeString(size),Filename))
#raw_input("Enter something: ")
#if Write['filename']=="sbl3.mbn":
# sys.exit()
if os.path.basename(Filename)=="singleimage.bin":
if CurrentSector < int(DiskSizeInBytes/SECTOR_SIZE):
device_log("\n\nSingleImageSize %i bytes (%i sectors)" % (CurrentSector*SECTOR_SIZE,CurrentSector))
device_log("CurrentSector=%i" % CurrentSector)
device_log("DiskSizeInBytes=%i sectors" % int(DiskSizeInBytes/SECTOR_SIZE))
device_log("\nDone Writing Files\n")
return ThereWereWarnings
def GetPartitions():
global Devices,AvailablePartitions
if sys.platform.startswith("linux"):
#device_log("This is a linux system since sys.platform='%s'" % sys.platform)
device_log("-"*78 )
device_log("\tRemember - DON'T FORGET SUDO")
device_log("\tRemember - DON'T FORGET SUDO")
device_log("\tRemember - DON'T FORGET SUDO")
device_log("-"*78+"\n")
os.system("cat /proc/partitions > temp_partitions.txt")
IN = open("temp_partitions.txt")
output = IN.readlines()
for line in output:
#print line
m = re.search("(\d+) (sd[a-z])$", line)
if type(m) is not NoneType:
Size = int(m.group(1))
Device = "/dev/"+m.group(2)
#device_log("%s\tSize=%d,%.1fMB (%.2fGB) (%iKB)" % (Device,Size,int(Size)/1024.0,int(Size)/(1024.0*1024.0),int(Size))
AvailablePartitions[Device] = Size*1024.0 # linux reports in terms of 1024,
else:
##device_log("This is a windows system since sys.platform='%s'" % sys.platform
device_log("\t ___ _ _ _ _ _ ___ ")
device_log("\t / _ \\ | | (_) (_) | | | | |__ \\ ")
device_log("\t/ /_\\ \\ __| |_ __ ___ _ _ __ _ ___| |_ _ __ __ _| |_ ___ _ __ ) |")
device_log("\t| _ |/ _` | '_ ` _ \\| | '_ \\| / __| __| '__/ _` | __|/ _ \\| '__| / / ")
device_log("\t| | | | (_| | | | | | | | | | | \\__ \\ |_| | | (_| | |_| (_) | | |_| ")
device_log("\t\\_| |_/\\__,_|_| |_| |_|_|_| |_|_|___/\\__|_| \\__,_|\\__|\\___/|_| (_) \n")
device_log("-"*78 )
device_log("\tRemember - Under Win7 you must run this as Administrator")
device_log("-"*78)
response = external_call('wmic DISKDRIVE get DeviceID, MediaType, Model, Size')
m = re.search("Access is denied", response)
if type(m) is not NoneType:
PrintBigError("This computer does not have correct privileges, you need administrator group privilege\n")
device_log("\n"+response)
response = response.replace('\r', '').strip("\n").split("\n")[1:]
for line in response:
m = re.search("(PHYSICALDRIVE\d+).+ (\d+) ", line)
if type(m) is not NoneType:
Size = int(m.group(2)) # size in bytes
Device = "\\\\.\\"+m.group(1) # \\.\PHYSICALDRIVE1
AvailablePartitions[Device] = Size
Devices = AvailablePartitions.keys()
Devices.sort()
device_log("--------------------------------Partitions Detected--------------------------------------")
for device in Devices:
value = AvailablePartitions[device]
if value/(1024.0*1024.0*1024.0) > 31.0:
device_log("%s %s\tsectors:%i <--- Not likely an SD card, careful!" % (device,ReturnSizeString(value),value/SECTOR_SIZE) )
else:
device_log("%s %s\tsectors:%i" % (device,ReturnSizeString(value),value/SECTOR_SIZE))
device_log("-"*78+"\n")
def PerformPatching():
global PatchArray,Patching
device_log("\t _ _ _ ")
device_log("\t | | | | (_) ")
device_log("\t _ __ __ _| |_ ___| |__ _ _ __ __ _ ")
device_log("\t| '_ \\ / _` | __|/ __| '_ \\| | '_ \\ / _` |")
device_log("\t| |_) | (_| | |_| (__| | | | | | | | (_| |")
device_log("\t| .__/ \\__,_|\\__|\\___|_| |_|_|_| |_|\\__, |")
device_log("\t| | __/ |")
device_log("\t|_| |___/ ")
var = 'Y'
if Patching == "DISK":
var = 'N' ## user must authorize this
## PATCHING HAPPENS HERE - PATCHING HAPPENS HERE - PATCHING HAPPENS HERE
for Patch in PatchArray:
if Patch['physical_partition_number']!=0: ## msp tool can only write to PHY partition 0
device_log("WARNING '%s' for physical_partition_number=%d (only 0 is accessible) - THIS MIGHT FAIL" % (Patch['filename'],Patch['physical_partition_number']))
if Patching == "DISK":
## to be here means user wants to patch the actual disk
if Patch['filename'] == "DISK":
pass ## all is well, want to patch DISK, and this is DISK
else:
continue ## this was filename, so skip it
else:
## to be here means were patching files, not the disk
if Patch['filename'] == "DISK":
continue ## want to patch FILES, but this was a DISK, so skip it
else:
pass ## this was filename, so let's patch it
device_log("\n" + "-"*78)
device_log("PATCH: (%s) %s" % (Patch['filename'],Patch['what']))
FileToOpen = Patch['filename']
if noprompt is True:
# means don't bug them, i.e. automation
pass
else:
if var=='N' or var=='n':
device_log("\nWARNING: Are you sure you want to PATCH to '%s' of size %s (y|N) " % (Filename,ReturnSizeString(DiskSizeInBytes)),0)
var = raw_input("\nWARNING: Are you sure you want to PATCH to '%s' of size %s (y|N) " % (Filename,ReturnSizeString(DiskSizeInBytes)))
if var=='Y' or var=='y':
pass
else:
device_log("\nmsp.py exiting - user didn't want to patch - Log is log_msp.txt\n\n")
sys.exit(1)
if Patching=="DISK":
FileWithPath = Filename
else:
FileWithPath = find_file(FileToOpen, search_paths)
while FileWithPath is None:
FileNotFoundShowWarning = 1
device_log("\t______ _ _ ___ ")
device_log("\t| ___ \\ | | | | |__ \\ ")
device_log("\t| |_/ /__ _| |_| |__ ) |")
device_log("\t| __// _` | __| '_ \\ / / ")
device_log("\t| | | (_| | |_| | | | |_| ")
device_log("\t\\_| \\__,_|\\__|_| |_| (_) \n\n")
if rawprogram_filename is None:
device_log("WARNING: '%s' listed in '%s' not found\n" % (FileToOpen,patch_filename))
else:
device_log("WARNING: '%s' listed in '%s' not found\n" % (FileToOpen,rawprogram_filename))
if noprompt is True:
device_log("\nUse option -s c:\\path1 -s c:\\path2 etc")
PrintBigError("")
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
device_log("Please provide a path for this file")
device_log("Ex. \\\\somepath\\folder OR c:\\somepath\\folder\n")
device_log("Enter PATH or Q to quit? ",0)
temppath = raw_input("Enter PATH or Q to quit? ")
if temppath=='Q' or temppath=='q' or temppath=='':
device_log("\nmsp.py exiting - user pressed Q (quit) - Log is log_msp.txt\n\n")
sys.exit()
device_log("\n")
FileWithPath = find_file(Write['filename'], [temppath])
size=0
if FileWithPath is not None:
size = os.path.getsize(FileWithPath)
device_log("\nShould this path be used to find other files? (Y|n|q)",0)
temp = raw_input("\nShould this path be used to find other files? (Y|n|q)")
if temp=='Q' or temp=='q':
device_log("\nmsp.py exiting - user pressed Q (quit) - Log is log_msp.txt\n\n")
sys.exit()
elif temp=='Y' or temp=='y' or temp=='':
search_paths.append(temppath)
device_log("\n" )
try:
opfile = open(FileWithPath, "r+b")
device_log("Opened %s, cwd=%s" % (FileWithPath,os.getcwd() ))
except Exception, x:
PrintBigError("Could not open %s, cwd=%s\nREASON: %s" % (FileWithPath,os.getcwd(),x ))
if Patch['function']=="CRC32":
device_log("\t%s(%u,%u) requested " % (Patch['function'],Patch['arg0'],Patch['arg1']))
PStartSector = int(Patch['arg0'])
PNumSectors = int(Patch['arg1']/SECTOR_SIZE)
if PNumSectors==0 or (Patch['arg1']%SECTOR_SIZE)>0: # i.e. 640/SECTOR_SIZE means read 2 sectors worth
PNumSectors+=1
try:
if Patch['arg0']>64:
device_log("\tPatch['arg0']=%d" % Patch['arg0'])
device_log("\tPatch['arg1']=%d" % Patch['arg1'])
device_log("\tmoving to sector %d-%d (%d)" % (PStartSector,(64-PNumSectors),PStartSector-(64-PNumSectors)))
opfile.seek( int( (PStartSector-(64-PNumSectors) )*SECTOR_SIZE ))
else:
device_log("moving to sector %d (byte location %d)" % (Patch['arg0'],Patch['arg0']*SECTOR_SIZE))
opfile.seek( int(Patch['arg0']*SECTOR_SIZE))
except Exception, x:
PrintBigError("Could not complete move in %s\nREASON: %s" % (FileWithPath,x))
device_log("\tMove Successful ")
try:
if Patch['arg0']>64:
device_log("\tTrying to read %d bytes in %s" % (64*SECTOR_SIZE,FileWithPath))
bytes_read = opfile.read(64*SECTOR_SIZE)
else:
device_log("\tTrying to read %d bytes in %s" % (Patch['arg1'],FileWithPath))
bytes_read = opfile.read(Patch['arg1'])
except Exception, x:
PrintBigError("Could not read in %s\nREASON: %s" % (FileWithPath,x))
device_log("\tlen(bytes_read)=",len(bytes_read))
if Patch['arg0']>64:
Bytes = struct.unpack("%dB" % (64*SECTOR_SIZE),bytes_read) ## unpack returns list, so get index 0
else:
Bytes = struct.unpack("%dB" % Patch['arg1'],bytes_read) ## unpack returns list, so get index 0
if Patch['arg0']>64:
#PStartSector
#PNumSectors
StartByte = (64-PNumSectors)*SECTOR_SIZE
device_log("\tStartByte=%i"%StartByte)
##print "Patch['arg1'] is :",Patch['arg1']
Patch['value'] = CalcCRC32(Bytes[StartByte:],Patch['arg1'])
else:
Patch['value'] = CalcCRC32(Bytes,Patch['arg1'])
device_log("\tCRC32=0x%.8X" % Patch['value'])
# ELSE - patch is not a CRC
if(int(Patch['start_sector'])>0):
try:
if Patch['start_sector']>64:
device_log("moving to %d-63=%d" % (Patch['start_sector'],Patch['start_sector']-63))
opfile.seek( int((Patch['start_sector']-63)*SECTOR_SIZE))
else:
device_log("moving to sector %d (byte location %d)" % (Patch['start_sector'],Patch['start_sector']*SECTOR_SIZE))
opfile.seek(int(Patch['start_sector']*SECTOR_SIZE))
except Exception, x:
PrintBigError("Could not move to sector %d in %s\nREASON: %s" % (Patch['start_sector'],FileWithPath,x))
try:
if Patch['start_sector']>64:
bytes_read = opfile.read(64*SECTOR_SIZE)
if len(bytes_read) != (64*SECTOR_SIZE):
PrintBigError("Didn't get the read size 64*SECTOR_SIZE" % FileWithPath)
else:
bytes_read = opfile.read(SECTOR_SIZE)
if len(bytes_read) != (SECTOR_SIZE):
PrintBigError("Didn't get the read size SECTOR_SIZE in '%s'" % FileWithPath)
except Exception, x:
PrintBigError("Could not read sector %d in %s\nREASON: %s" % (Patch['start_sector'],FileWithPath,x))
device_log("success was able to read len(bytes_read)=%d" % (len(bytes_read)))
# Move back to do the write
try:
if Patch['start_sector']>64:
#device_log("moving to %d-63=%d" % (Patch['start_sector'],Patch['start_sector']-63))
opfile.seek(int((Patch['start_sector']-63)*SECTOR_SIZE))
else:
#device_log("moving to sector %d (byte location %d)" % (Patch['start_sector'],Patch['start_sector']*SECTOR_SIZE))
opfile.seek(int(Patch['start_sector']*SECTOR_SIZE))
except Exception, x:
PrintBigError("Could not move to sector %d in %s\nREASON: %s" % (Patch['start_sector'],FileWithPath,x))
if Patch['value'] < 0:
PrintBigError("Patch value was negative. This means your DISK size is too small")
device_log("At sector %d (0x%X) file_sector_offset %d (0x%X) in %s with %d (0x%X)" % (Patch['start_sector'],Patch['start_sector']*SECTOR_SIZE,Patch['byte_offset'],Patch['byte_offset'],FileWithPath,Patch['value'],Patch['value']))
#Patch['byte_offset']
if Patch['start_sector']>64:
ValueList = list(struct.unpack("%dB"%(64*SECTOR_SIZE),bytes_read))
else:
ValueList = list(struct.unpack("%dB"%SECTOR_SIZE,bytes_read)) # "512B"
#device_log("\nBefore")
#j=0
#sys.stdout.write("%.4X\t "%j)
#for b in ValueList[-512:]:
# sys.stdout.write("%.2X "%b)
# j+=1
# #if j>64:
# # break
# if j%16==0:
# device_log(" ")
# sys.stdout.write("%.4X\t "%j)
device_log("Patch value:%i"%Patch['value'])
for j in range(Patch['size_in_bytes']):
if Patch['start_sector']>64:
#device_log("Applying patch at %d+%d=%d value=0x%.2X" % (63*SECTOR_SIZE,Patch['byte_offset']+j,63*SECTOR_SIZE+j+Patch['byte_offset'],(Patch['value']>>(j*8))&0xFF))
ValueList[63*SECTOR_SIZE+Patch['byte_offset']+j ] = (Patch['value']>>(j*8))&0xFF
sys.stdout.write("%.2X " % (int(Patch['value']>>(j*8)) & 0xFF))
else:
ValueList[Patch['byte_offset']+j ] = (Patch['value']>>(j*8))&0xFF
#import pdb; pdb.set_trace()
sys.stdout.write("%.2X " % (int(Patch['value']>>(j*8)) & 0xFF))
#for b in ValueList:
# sys.stdout.write("%.2X "%b)
#device_log("\nAfter")
#j=0
#sys.stdout.write("%.4X\t "%j)
#for b in ValueList[-512:]:
# sys.stdout.write("%.2X "%b)
# j+=1
# #if j>64:
# # break
# if j%16==0:
# device_log(" ")
# sys.stdout.write("%.4X\t "%j)
#device_log(" ")
if Patch['start_sector']>64:
bytes_read = struct.pack("%dB"%(64*SECTOR_SIZE),*ValueList)
else:
bytes_read = struct.pack("%dB"%SECTOR_SIZE,*ValueList)
device_log("(little endian)")
device_log("committing patch of length %d bytes" % len(bytes_read))
try:
opfile.write(bytes_read)
except Exception, x:
PrintBigError("Could not write %d bytes to %s\nREASON: %s" % (len(bytes_read),FileWithPath,x))
#WriteValue(fd, RawProgramInfo.start_sector, RawProgramInfo.byte_offset, RawProgramInfo.value, RawProgramInfo.size_in_bytes);
try:
opfile.close()
except Exception, x:
device_log("\tWARNING: Could not close %s" % FileWithPath)
device_log("REASON: %s" % (x))
device_log("CLOSED '%s'" % FileWithPath)
if sys.platform.startswith("linux"):
device_log("You're on LINUX! I'm performing a SYNC for you")
os.system("sync")
device_log("PATCH:" , Patch['what'])
device_log("DONE\n")
#if Patch['what']== "Update Backup Header with Write Array Location.":
# sys.exit(0)
device_log("Done patching")
def Usage():
print "Usage: Mass Storage Programmer - destructively writes data to disks!!\n"
sudo = ""
drive= ""
if sys.platform.startswith("linux"):
sudo = "sudo"
drive= "/dev/sdb"
else:
print "\tYou must run as Administrator under Win7\n"
drive="\\\\.\\PHYSICALDRIVE1"
print "%-40s\t python msp.py" % "Display this info"
print "%-40s\t%s python msp.py -r wipe_rawprogram_PHY0.xml -d %s" % ("Wipe partition info (-w)",sudo,drive)
print "\n%-40s\t%s python msp.py -r rawprogram0.xml -d %s" % ("Write a device (-r)",sudo,drive)
print "%-40s\t%s python msp.py -r rawprogram0.xml -d 0" % ("Create a singleimage.bin (-r)",sudo)
print "%-40s\t%s python msp.py -r rawprogram0.xml -d 0 -t c:\\temp" % ("singleimage.bin stored to c:\\temp (-r)",sudo)
print "%-40s\t%s python msp.py -r rawprogram0.xml -d 16777216" % ("Create an 8GB singleimage.bin (-r)",sudo)
print "\n%-40s\t%s python msp.py -n -r rawprogram.xml -d %s" % ("no prompts (-n) i.e. automation",sudo,drive)
print "%-40s\t%s python msp.py -i -r rawprogram.xml -d %s " % ("Interactively choose files (-i)",sudo,drive)
print "%-40s\t%s python msp.py -f sbl1.mbn,sbl2.mbn -r rawprogram.xml -d %s " % ("Specify files from rawprogram.xml (-f)",sudo,drive)
print "%-40s\t%s python msp.py -s c:\windows,d:\ -r rawprogram.xml -d %s " % ("Search this path for files (-s)",sudo,drive)
print "\n%-40s\t%s python msp.py -p patch0.xml -d %s" % ("Patch a device (-p)",sudo,drive)
print "%-40s\t%s python msp.py -p patch0.xml -d singleimage.bin" % ("Patch files to singleimage (-p)",sudo)
print "%-40s\t%s python msp.py -p patch0.xml -d 16777216" % ("PRE-PATCH images for an 8GB disk (-p)",sudo)
print "\n%-40s\t%s python msp.py -r rawprogram0.xml -p patch0.xml -d %s" % ("ALL IN ONE STEP",sudo,drive)
print "\n"+"*"*78
print "Usage: Mass Storage Programmer - destructively writes data to disks!!"
print "*"*78+"\n"
def ReturnSizeString(size):
if size>(1024*1024*1024):
return "%.2f GB" % (size/(1024.0*1024.0*1024.0))
elif size>(1024*1024):
return "%.2f MB" % (size/(1024.0*1024.0))
elif size>(1024):
return "%.2f KB" % (size/(1024.0))
else:
return "%i B" % (size)
# A8h reflected is 15h, i.e. 10101000 <--> 00010101
def reflect(data,nBits):
reflection = 0x00000000
bit = 0
for bit in range(nBits):
if(data & 0x01):
reflection |= (1 << ((nBits - 1) - bit))
data = (data >> 1);
return reflection
def PrintResetDeviceNow():
device_log("\t______ _ ")
device_log("\t| ___ \\ | | ")
device_log("\t| |_/ /___ ___ ___| |_ _ _ ___ _ _ _ __ ")
device_log("\t| // _ | __|/ _ \\ __| | | | |/ _ \\| | | | '__|")
device_log("\t| |\\ \\ __|__ \\ __/ |_ | |_| | (_) | |_| | | ")
device_log("\t\\_| \\_\\___|___/\\___|\\__| \\__, |\\___/ \\__,_|_| ")
device_log("\t __/ | ")
device_log("\t |___/ ")
device_log("\t")
device_log("\t _ _ ")
device_log("\t | | (_) ")
device_log("\t __| | _____ ___ ___ ___ _ __ _____ __")
device_log("\t / _` |/ _ \\ \\ / / |/ __|/ _ \\ | '_ \\ / _ \\ \\ /\\ / /")
device_log("\t| (_| | __/\\ V /| | (__| __/ | | | | (_) \\ V V / ")
device_log("\t \\__,_|\\___| \\_/ |_|\\___|\\___| |_| |_|\\___/ \\_/\\_/ \n")
def TestIfSparse(test_sparse,filetotest):
if test_sparse is None:
PrintBigWarning("WARNING: testsparse.py is not found - Can't test if this file is SPARSE\n")
else:
sz = "python %s -i %s " % (test_sparse,filetotest)
for path in search_paths:
sz += "-s %s " % path
device_log("\n"+"-"*78)
device_log("-"*78)
device_log("Checking if file '%s' is sparse. This is to save you from accidently" % filetotest)
device_log("using a sparse file without *unsparsing* it first. That is, if you copy it over as is")
device_log("it won't work (similar to a ZIP file, you want what is *inside*, not the ZIP file)")
device_log("-"*78)
device_log("-"*78)
#filetotest_temp = find_file(filetotest, search_paths)
#if filetotest_temp is None:
# PrintBigError("Can't located '%s'" % filetotest)
device_log(sz)
response = external_call(sz)
m = re.search("SPARSE FILE DETECTED", response)
if type(m) is not NoneType:
PrintBigError("File is sparse, can't continue - you must run 'python checksparse.py -i rawprogram0.xml'")
def CalcCRC32(array,Len):
k = 8; # length of unit (i.e. byte)
MSB = 0;
gx = 0x04C11DB7; # IEEE 32bit polynomial
regs = 0xFFFFFFFF; # init to all ones
regsMask = 0xFFFFFFFF; # ensure only 32 bit answer
for i in range(Len): # Len=5 ; range(Len) --> [0, 1, 2, 3, 4]
DataByte = array[i]
DataByte = reflect( DataByte, 8 );
for j in range(k):
MSB = DataByte>>(k-1) ## get MSB
MSB &= 1 ## ensure just 1 bit
regsMSB = (regs>>31) & 1
regs = regs<<1 ## shift regs for CRC-CCITT
if regsMSB ^ MSB: ## MSB is a 1
regs = regs ^ gx ## XOR with generator poly
regs = regs & regsMask; ## Mask off excess upper bits
DataByte <<= 1 ## get to next bit
regs = regs & regsMask ## Mask off excess upper bits
ReflectedRegs = reflect(regs,32) ^ 0xFFFFFFFF;
return ReflectedRegs
def ReplaceDiskSizeInSectorsWithRealValue(MyArray):
## At this point I have the real size of DiskSizeInBytes, so let's fill in the blanks if they still exist
for MyDict in MyArray:
if int(MyDict['start_sector']) > 0 and int(MyDict['start_sector'])>(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE):
MyDict['start_sector'] = (DiskSizeInBytes/SECTOR_SIZE)-(int(MyDict['start_sector'])-(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE))
if int(MyDict['num_partition_sectors']) > 0 and int(MyDict['num_partition_sectors'])>(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE):
MyDict['num_partition_sectors'] = (DiskSizeInBytes/SECTOR_SIZE)-(int(MyDict['num_partition_sectors'])-(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE))
if int(MyDict['file_sector_offset']) > 0 and int(MyDict['file_sector_offset'])>(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE):
MyDict['file_sector_offset'] = (DiskSizeInBytes/SECTOR_SIZE)-(int(MyDict['file_sector_offset'])-(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE))
if int(MyDict['value']) > 0 and int(MyDict['value'])>(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE):
MyDict['value'] = (DiskSizeInBytes/SECTOR_SIZE)-(int(MyDict['value'])-(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE))
def CalculateMinDiskSize():
OldMinDiskSizeInSectors = 0
MinDiskSizeInSectors = 0
#Calculate the MinDiskSizeInSectors. This is a 2 step process
# Once for normal partitions
for Write in WriteSorted:
if int(Write['start_sector']) > 0 and int(Write['start_sector'])<(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE):
MinDiskSizeInSectors = (int(Write['start_sector']) + int(Write['num_partition_sectors']))
if OldMinDiskSizeInSectors != MinDiskSizeInSectors:
device_log("MinDiskSizeInSectors=%i sectors (%.2fMB)" % (MinDiskSizeInSectors,MinDiskSizeInSectors*SECTOR_SIZE/(1024.0*1024.0)))
OldMinDiskSizeInSectors = MinDiskSizeInSectors
print "----------------------"
# second time is for NUM_DISK_SECTORS-33 type of scenarios, since they will currently have
# my made up value of EMMCBLD_MAX_DISK_SIZE_IN_BYTES+start_sector
for Write in WriteSorted:
if int(Write['start_sector']) > 0 and int(Write['start_sector'])>(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE):
MinDiskSizeInSectors += int(Write['start_sector'])-(EMMCBLD_MAX_DISK_SIZE_IN_BYTES/SECTOR_SIZE)
if OldMinDiskSizeInSectors != MinDiskSizeInSectors:
device_log("MinDiskSizeInSectors=%i sectors (%.2fMB)" % (MinDiskSizeInSectors,MinDiskSizeInSectors*SECTOR_SIZE/(1024*1024.0)))
OldMinDiskSizeInSectors = MinDiskSizeInSectors
return MinDiskSizeInSectors
## ==============================================================================================
## ==============================================================================================
## ==============================================================================================
## =====main()===================================================================================
## ==============================================================================================
## ==============================================================================================
## ==============================================================================================
AvailablePartitions = {}
try:
opts, args = getopt.getopt(sys.argv[1:], "r:p:d:ins:f:t:vb:", ["rawprogram=", "patch=", "dest=","noprompt=", "interactive=", "search_path=","file=","location=","verbose","sectorsize"])
except getopt.GetoptError, err:
# print help information and exit:
Usage()
PrintBigError(str(err))
test_sparse = None
dd = None
xml_filename = None
rawprogram_filename = None
patch_filename = None
disk_name = None
search_paths = []
file_list = []
LoadSubsetOfFiles = False
interactive = False
noprompt = False
verbose = False
Operation = 0
OPERATION_PROGRAM = 2
OPERATION_PATCH = 4
OPERATION_READ = 8
Patching = "FILES"
OutputFolder = ""
Filename = "singleimage.bin"
DiskSizeInBytes = 0
MinDiskSizeInSectors = 0
Usage()
#GetPartitions()
for o, a in opts:
if o in ("-r", "--rawprogram"):
rawprogram_filename = a
# Operation |= OPERATION_PROGRAM ## assumed here. It will be corrected later
elif o in ("-b","--sectorsize"):
SECTOR_SIZE = int(a)
elif o in ("-t", "--location"):
OutputFolder = a
OutputFolder = re.sub(r"\\$","",OutputFolder) # remove final slash if it exists
OutputFolder = re.sub(r"/$","",OutputFolder) # remove final slash if it exists
OutputFolder += "/" # slashes will all be corrected below
if sys.platform.startswith("linux"):
OutputFolder = re.sub(r"\\","/",OutputFolder) # correct slashes
else:
OutputFolder = re.sub(r"/","\\\\",OutputFolder) # correct slashes
device_log("OutputFolder='%s'"%OutputFolder)
EnsureDirectoryExists(OutputFolder) # only need to call once
Filename = OutputFolder + Filename
elif o in ("-p", "--patch"):
patch_filename = a
Operation |= OPERATION_PATCH
elif o in ("-d", "--dest"):
disk_name = a
# if a number was specified, it's size in sectors and we're making a singleimage.bin
# otherwise, a drive /dev/sdb or something was specified
m = re.search("^(\d+)$", disk_name)
if type(m) is not NoneType:
## to be here means they specified a number must be making a single image or patching files
Patching = "FILES"
Filename = OutputFolder + "singleimage.bin"
DiskSizeInBytes = int(int(m.group(1))*SECTOR_SIZE) # comes in as sectors, we now know the size of DiskSizeInBytes, could also be size 0!!
else:
## to be here means they didn't specify a number, thus a device
Filename = disk_name
Patching = "DISK"
ValidDiskName = False
# User can also specify the singleimage.bin name, and I can treat that like it's the disk
GetPartitions()
if sys.platform.startswith("linux"):
m = re.search("/dev/sd[a-z]", disk_name)
if type(m) is not NoneType:
ValidDiskName = True
else:
m = re.search("(PHYSICALDRIVE\d+)", disk_name)
if type(m) is not NoneType:
ValidDiskName = True
Filename = "\\\\.\\"+m.group(1)
if ValidDiskName:
if Filename not in Devices:
PrintBigError("%s does not exist" % Filename)
DiskSizeInBytes = AvailablePartitions[Filename]
else:
# To be here means user did this possibly "-d singleimage.bin", i.e. to patch the singleimage.bin
try:
DiskSizeInBytes = os.path.getsize(disk_name) # and thus singleimage.bin must already exist
except Exception, x:
PrintBigError("")
device_log("Can't get size of %s" % Filename)
device_log("REASON: %s" % (x))
Usage()
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit()
elif o in ("-i", "--interactive"):
interactive = True
elif o in ("-n", "--noprompt"):
noprompt = True
elif o in ("-v", "--verbose"):
verbose = True
elif o in ("-s", "--search_path"):
## also allow seperating commas
for x in a.strip("\n").split(","):
search_paths.append(x)
elif o in ("-f", "--file_list"):
## also allow seperating files by commas, i.e. -f sbl1.mbn,slb2.mbn,etc
LoadSubsetOfFiles = True
for x in a.strip("\n").split(","):
file_list.append(x)
else:
assert False, "unhandled option"
if Operation==0: ## Means nothing was specified above
GetPartitions()
device_log("\nmsp.py exiting - Only showed options and drives detected - Log is log_msp.txt\n\n")
if verbose is True:
device_log("\nMass Storage Programmer (msp.py) VERSION 1.0\n");
sys.exit(1)
device_log("\nSearch Paths")
device_log(search_paths)
device_log("\nFiles")
device_log(file_list)
if disk_name is None:
if sys.platform.startswith("linux"):
device_log("Don't forget to specify your drive, EX '-d /dev/sdb' OR '-d 0' to create a singleimage");
else:
device_log("Don't foreget to specify your drive, EX '-d \\.\PHYSICALDRIVE1' OR '-d 0' to create a singleimage");
PrintBigError("You must specify a DISK, option -d")
if (Operation & OPERATION_PROGRAM) > 0:
if rawprogram_filename is None:
PrintBigError("You must specify an \"rawprogram\" XML file for option -r")
else:
rawprogram_filename = find_file(rawprogram_filename, search_paths)
if rawprogram_filename is None:
PrintBigError("You must specify an \"rawprogram\" XML file for option -r")
if (Operation & OPERATION_PATCH) > 0:
if patch_filename is None:
PrintBigError("You must specify an \"patch\" XML file for option -p")
else:
patch_filename = find_file(patch_filename, search_paths)
if patch_filename is None:
PrintBigError("You must specify an \"patch\" XML file for option -p")
NumPhyPartitions = 0
WriteArray = []
ReadArray = []
PatchArray = []
PhyPartition = {} # Main HASH that holds all the partition info
## At this point DiskSizeInBytes is either known or equal to 0
if rawprogram_filename is not None:
ParseXML(rawprogram_filename)
Operation = 0
if len(WriteArray)>0:
pass
# Operation |= OPERATION_PROGRAM
if len(ReadArray)>0:
Operation |= OPERATION_READ
if DiskSizeInBytes>0:
if DiskSizeInBytes<int(MinDiskSizeInSectors)*SECTOR_SIZE:
PrintBigError("")
device_log("\nERROR: Current eMMC/SD card is too small to program these partitions")
device_log(" Need at least %s" % ReturnSizeString(int(MinDiskSizeInSectors)))
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
## rawprogram0.xml is random in terms of start_sector. It's important for
## making the single image that we first write at sector 0, then 100, then 200 etc
## i.e. writing 200, then going back to write 100 is more complicated, so SORT
## Step 1. Sort all the start sectors where there's a file to program
PartitionStartSector = []
for Write in WriteArray:
if Write['filename']=="":
#device_log("no filename for label '%s'"%Write['label'])
continue
m = re.search("\.ext4$", Write['filename'])
if type(m) is not NoneType:
TestIfSparse(test_sparse,Write['filename'])
if 'sparse' in Write:
m = re.search("true", Write['sparse'],re.IGNORECASE)
if type(m) is not NoneType:
PrintBigError("")
device_log("Your rawprogram.xml file indicates that this is a sparse image, can't continue")
device_log("You must first run \"python checksparse.py -i rawprogram0.xml -s C:\\path1 -s C:\\path2\"")
device_log("This will modify rawprogram0.xml to be able to handle the sparse image(s)")
device_log("Also, you *must* specify the various paths to the sparse images and they need to be")
device_log("opened and parsed. Then you can run msp.py again to program.")
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit(1)
PartitionStartSector.append( Write["start_sector"] )
PartitionStartSector.sort() # This will make the negative values first
## Step 2. Create a "WriteSorted" based on PartitionStartSector
WriteSorted = []
Count = 0
while 1 and (Operation & OPERATION_PROGRAM) > 0:
for Write in WriteArray:
#device_log("---------------- with start_sector = %i and PartitionStartSector[%i]=%i" % (Write["start_sector"],Count,PartitionStartSector[Count]))
if Write['filename']=="":
continue
if Write["start_sector"] == PartitionStartSector[Count]:
##device_log("FOUND, len(PartitionStartSector)=%d and len(WriteSorted)=%d" % (len(PartitionStartSector),len(WriteSorted)))
# To be here means I found the *next* start_sector in order, i.e. 0,100,200 etc
WriteSorted.append( Write )
Count += 1 # now go to next sorted entry
if len(WriteSorted) == len(PartitionStartSector):
break # we're done, both arrays are the same size
if len(WriteSorted) == len(PartitionStartSector):
break # we're done, both arrays are the same size
MinDiskSizeInSectors = CalculateMinDiskSize()
print "MinDiskSizeInSectors=",MinDiskSizeInSectors
print "DiskSizeInSectors =",DiskSizeInBytes/SECTOR_SIZE
if DiskSizeInBytes==0:
DiskSizeInBytes = int(MinDiskSizeInSectors)*SECTOR_SIZE
if DiskSizeInBytes == 0:
PrintBigError("")
device_log("Something went wrong, couldn't determine size of disk?")
if sys.platform.startswith("linux"):
device_log("Did you remember to specify your drive, EX '-d /dev/sdb'");
else:
device_log("Did you remember to specify your drive, EX '-d \\.\PHYSICALDRIVE1'");
device_log("\nmsp.py failed - Log is log_msp.txt\n\n")
sys.exit()
device_log("\nDiskSizeInBytes was set to 0, DiskSizeInBytes will be %s (%d sectors)" % (ReturnSizeString(DiskSizeInBytes),int(DiskSizeInBytes/SECTOR_SIZE)))
if patch_filename is not None:
Operation |= OPERATION_PATCH
ParseXML(patch_filename)
ReplaceDiskSizeInSectorsWithRealValue(WriteSorted)
ReplaceDiskSizeInSectorsWithRealValue(ReadArray)
ReplaceDiskSizeInSectorsWithRealValue(PatchArray)
if (Operation & OPERATION_PROGRAM) > 0:
# Can we test for sparse images?
test_sparse = find_file("testsparse.py", search_paths)
if os.path.basename(Filename)=="singleimage.bin":
## Wipe out any old singleimage
try:
opfile = open(Filename, "wb")
except Exception, x:
print "REASON: %s" % x
print "\nERROR: Can't delete old singleimage.bin. Is it open??"
sys.exit()
opfile.close()
device_log("\nProgramming %s of size %s" % (Filename,ReturnSizeString(DiskSizeInBytes)))
if noprompt is False:
if (DiskSizeInBytes/(1024.0*1024.0))>100:
device_log("\nThis will be a LARGE singleimage.bin, it will take a long time, Do you want to continue? (Y|n)",0)
var = raw_input("\nThis will be a LARGE singleimage.bin, it will take a long time, Do you want to continue? (Y|n)")
if var=='Y' or var=='y' or var=='':
pass
else:
device_log("\nmsp.py exiting - User didn't want to continue - Log is log_msp.txt\n\n")
sys.exit()
else:
if noprompt is True:
# means don't bug them, i.e. automation
pass
else:
device_log("\nWARNING: Are you sure you want to write to '%s' of size %s (y|N) " % (Filename,ReturnSizeString(DiskSizeInBytes)),0)
var = raw_input("\nWARNING: Are you sure you want to write to '%s' of size %s (y|N) " % (Filename,ReturnSizeString(DiskSizeInBytes)))
if var=='Y' or var=='y':
pass
else:
device_log("\nmsp.py exiting - User didn't want to continue - Log is log_msp.txt\n\n")
sys.exit()
if (Operation & OPERATION_READ) > 0:
PerformRead()
ThereWereWarnings = 0
if (Operation & OPERATION_PROGRAM) > 0 and (Operation & OPERATION_PATCH) > 0:
## Have info to do both write and patch
if Filename=="singleimage.bin":
# it's a singleimage, so do patching first
PerformPatching()
ThereWereWarnings = PerformWrite()
if (Operation & OPERATION_READ) > 0:
PerformRead()
if verbose is True:
DoubleCheckDiskSize()
else:
ThereWereWarnings = PerformWrite()
PerformPatching()
if (Operation & OPERATION_READ) > 0:
PerformRead()
if verbose is True:
DoubleCheckDiskSize()
elif (Operation & OPERATION_PROGRAM) > 0:
ThereWereWarnings = PerformWrite()
if (Operation & OPERATION_READ) > 0:
PerformRead()
device_log("\n"+"-"*78)
device_log("If you wrote any partition table information (MBR0.bin, gpt_main0.bin, etc)")
device_log(" ")
device_log(" _ _ _ __ _ ")
device_log(" | | ( ) | / _| | | ")
device_log(" __| | ___ _ __ |/| |_ | |_ ___ _ __ __ _ ___| |_ ")
device_log(" / _` |/ _ \\| '_ \\ | __| | _/ _ \\| '__/ _` |/ _ \\ __|")
device_log(" | (_| | (_) | | | | | |_ | || (_) | | | (_| | __/ |_ ")
device_log(" \\__,_|\\___/|_| |_| \\__| |_| \\___/|_| \\__, |\\___|\\__|")
device_log(" __/ | ")
device_log(" |___/ ")
device_log(" _ _ _ ")
device_log(" | | | | | | ")
device_log(" | |_ ___ _ __ __ _| |_ ___| |__ ")
device_log(" | __|/ _ \\ | '_ \\ / _` | __|/ __| '_ \\ ")
device_log(" | |_| (_) | | |_) | (_| | |_| (__| | | |")
device_log(" \\__|\\___/ | .__/ \\__,_|\\__|\\___|_| |_|")
device_log(" | | ")
device_log(" |_| ")
device_log("\n")
sudo=""
if sys.platform.startswith("linux"):
sudo="sudo "
device_log("\tEx: %spython msp.py -p patch0.xml -d %s " % (sudo,Filename))
device_log("\t\tOr, do it all in one step")
device_log("\tEx: %spython msp.py -r rawprogram0.xml -d %s -p patch0.xml" % (sudo,Filename))
device_log("-"*78)
if verbose is True:
DoubleCheckDiskSize()
elif (Operation & OPERATION_PATCH) > 0:
PerformPatching()
if verbose is True:
DoubleCheckDiskSize()
if (Operation & OPERATION_PROGRAM) > 0:
if os.path.basename(Filename)=="singleimage.bin":
device_log("\nNOTE: This program does *not* pad the last partition, therefore")
device_log(" singleimage.bin might be smaller than %d sectors (%.2f MB)" % (int(DiskSizeInBytes/SECTOR_SIZE),DiskSizeInBytes/(1048576.0)))
device_log("\n\nSUCCESS - %s created" % Filename)
device_log("SUCCESS - %s created" % Filename)
device_log("SUCCESS - %s created\n" % Filename)
if FileNotFoundShowWarning==1:
device_log("\nWARNING: 1 or more files were *not* found, your singleimage.bin is *NOT* complete")
device_log("\nWARNING: 1 or more files were *not* found, your singleimage.bin is *NOT* complete")
device_log("\nWARNING: 1 or more files were *not* found, your singleimage.bin is *NOT* complete\n\n")
device_log("\nmsp.py exiting SUCCESSFULLY- Log is log_msp.txt\n\n")
if ThereWereWarnings == 1:
PrintBigWarning("There were warnings, please see log. \n\n--------> Your image *might* not work <----------\n")
sleep(2)