Advertisement
manfromnn

msp

Feb 27th, 2015
835
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 64.98 KB | None | 0 0
  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: //source/qcom/qct/core/storage/tools/emmc/src/jsdcc/partition_load_pt/msp.py#18 $
  10. #  $DateTime: 2011/08/09 20:02:16 $
  11. #  $Author: ahughes $
  12.  
  13. # when          who     what, where, why
  14. # --------      ---     -------------------------------------------------------
  15. # 2011-08-09    ah      -t option specifies output directory for files
  16. # 2011-08-01    ah      Bug fix whhen patching DISK
  17. # 2011-07-26    ah      Much better error messages
  18. # 2011-07-21    ah      Major changes, now using getopt(), patching/writing can be all one step
  19. # 2011-07-13    ah      Better error messages for user experience
  20. # 2011-06-01    ah      Improved singleimage support for GPT
  21. # 2011-05-26    ah      Handles sparse files and "zeroout" tag
  22. # 2011-05-17    ah      Removed auto-patching MBR - must manually patch just like in GPT
  23. # 2011-05-02    ah      No longer querying for /proc/partitions by default (user must ask now)
  24. # 2011-03-22    ah      Enforcing that msp can't patch/write to partitions other than USER
  25. # 2011-03-22    ah      Fixed memory bug with large file writing, fixed bug with SINGLEIMAGE creation (i.e. append)
  26. # 2011-03-16    ah      Fixed memory bug with large file patching and read/write permissions for
  27. #                       SCons and singleimage.bin, Now need user input when patching DISK, "sync" command for linux
  28. # 2011-03-09    ah      Replaces msp.exe - compatible with Linux and Windows
  29. #                       does not need cygwin, cleaner code, more error checking
  30. # 2011-02-14    ah      Changed 'dd' to 'cat' to avoid error happening on Win7
  31. # 2010-10-26    ah      Now "patches" partition table on the fly, adds warnings before nuking drive
  32. # 2010-10-22    ah      Used to replace msp.exe - can program cards and singleimages.bin
  33.  
  34. # Copyright (c) 2007-2010
  35. # Qualcomm Incorporated.
  36. # All Rights Reserved.
  37. # Qualcomm Confidential and Proprietary
  38. # ===========================================================================*/
  39.  
  40. import struct, os, sys, getopt
  41. import math
  42. import re
  43. import codecs
  44. from types import *
  45. import time
  46. import subprocess as sub
  47.  
  48. from xml.etree import ElementTree as ET
  49. #from elementtree.ElementTree import ElementTree
  50. from xml.etree.ElementTree import Element, SubElement, Comment, tostring
  51. from xml.dom import minidom
  52.  
  53. DiskSectors         =      0
  54. SingleImageSize     =      0
  55.  
  56. BLOCK_SIZE          =      0x200
  57. TABLE_ENTRY_0       =      0x1BE
  58. TABLE_ENTRY_1       =      0x1CE
  59. TABLE_ENTRY_2       =      0x1DE
  60. TABLE_ENTRY_3       =      0x1EE
  61.  
  62. EMMCBLD_MIN_DISK_SIZE   = (4*1024*1024) # 4MB
  63.  
  64. MAX_FILE_SIZE_BEFORE_SPLIT = (10*1024*1024)
  65. #MAX_FILE_SIZE_BEFORE_SPLIT = (2048) # testing purposes
  66.  
  67. ExtendedPartitionBegins = 0
  68. bytes_read              = 0
  69. FileNotFoundShowWarning = 0
  70.  
  71. print "\nmsp.py is running from CWD: ", os.getcwd(), "\n"
  72.  
  73.  
  74. SECTOR_SIZE = 512
  75. disk_size = None
  76.  
  77. def ReadSectors(opfile,NumSectors):
  78.     try:
  79.         return opfile.read(NumSectors*512)
  80.     except:
  81.         print "ERROR: Could not complete the read"
  82.         sys.exit()
  83.  
  84. def EnsureDirectoryExists(filename):
  85.     dir = os.path.dirname(filename)
  86.  
  87.     try:
  88.         os.stat(dir)
  89.     except:
  90.         os.makedirs(dir)
  91.  
  92. def PrintBigError(sz):
  93.     print "\t _________________ ___________ "
  94.     print "\t|  ___| ___ \\ ___ \\  _  | ___ \\"
  95.     print "\t| |__ | |_/ / |_/ / | | | |_/ /"
  96.     print "\t|  __||    /|    /| | | |    / "
  97.     print "\t| |___| |\\ \\| |\\ \\\\ \\_/ / |\\ \\ "
  98.     print "\t\\____/\\_| \\_\\_| \\_|\\___/\\_| \\_|\n"
  99.  
  100.     if len(sz)>0:
  101.         print sz
  102.         sys.exit(1)
  103.        
  104. def PrettyPrintArray(bytes_read):
  105.     Bytes = struct.unpack("%dB" % len(bytes_read),bytes_read)
  106.  
  107.     for k in range(len(Bytes)/512):
  108.         print "-"*78
  109.         for j in range(32):
  110.             for i in range(16):
  111.                 sys.stdout.write("%.2X " % Bytes[i+j*16])
  112.    
  113.             sys.stdout.write("\t")
  114.    
  115.             for i in range(16):
  116.                 sys.stdout.write("%c" % Bytes[i+j*16])
  117.             print " "
  118.     print " "
  119.  
  120. def Zerout(disk_name,start_sector,num_sectors):
  121.     global verbose
  122.    
  123.  
  124.     verbose = True
  125.  
  126.     if verbose:
  127.         print "\nIn Zeroout"
  128.         print "Attempting to open %s" % disk_name
  129.     try:
  130.         opfile = open(disk_name, "r+b")
  131.     except:
  132.         print "ERROR: (Zerout) Could not open %s, cwd=%s" % (disk_name,os.getcwd() )
  133.  
  134.         if sys.platform.startswith("linux"):
  135.             print "Did you remember to use SUDO?\n"
  136.         else:
  137.             print "\t  ___      _           _       _     _             _                ___  "
  138.             print "\t / _ \\    | |         (_)     (_)   | |           | |              |__ \\ "
  139.             print "\t/ /_\\ \\ __| |_ __ ___  _ _ __  _ ___| |_ _ __ __ _| |_  ___  _ __     ) |"
  140.             print "\t|  _  |/ _` | '_ ` _ \\| | '_ \\| / __| __| '__/ _` | __|/ _ \\| '__|   / / "
  141.             print "\t| | | | (_| | | | | | | | | | | \\__ \\ |_| | | (_| | |_| (_) | |     |_|  "
  142.             print "\t\\_| |_/\\__,_|_| |_| |_|_|_| |_|_|___/\\__|_|  \\__,_|\\__|\\___/|_|     (_)  \n\n"
  143.                                                                          
  144.             print "Did you remember to be in Administrator Mode for Win7?\n"
  145.         sys.exit()
  146.  
  147.  
  148.     if start_sector<0:
  149.         # Means do this NUM_DISK_SECTORS - start_sector
  150.         start_sector = (AvailablePartitions[disk_name]/512) + start_sector # remember start_sector is negative, so add it
  151.  
  152.     if verbose:
  153.         print "Moving to sector %i" % start_sector
  154.     try:
  155.         opfile.seek(int(start_sector*512))
  156.     except:
  157.         print "ERROR: Could not move to sector %d in %s" % (start_sector,disk_name)
  158.         sys.exit()
  159.  
  160.     temp = [0]*(512*num_sectors)
  161.     bytes_read = struct.pack("%iB"%(512*num_sectors),*temp)
  162.     if verbose:
  163.         print "Writing %i zeros" % len(temp)
  164.     try:
  165.         opfile.write(bytes_read)
  166.     except:
  167.         print "ERROR: Could not write at sector %d in %s" % (Zeroout['start_sector'],disk_name)
  168.         sys.exit()
  169.  
  170.     try:
  171.         opfile.close()
  172.     except:
  173.         print "\tWARNING: Could not close %s" % disk_name
  174.         pass
  175.  
  176.  
  177. def external_call(command, capture_output=True):
  178.     errors = None
  179.     output = None
  180.     try:
  181.         if capture_output:
  182.             p = sub.Popen(command, stdout=sub.PIPE, stderr=sub.PIPE)
  183.             output, errors = p.communicate()
  184.         else:
  185.             os.system(command)
  186.     except Exception, e:
  187.         print "Error executing command %s. %s" % (str(command), e)
  188.         #clean_up()
  189.         sys.exit(1)
  190.     finally:
  191.         #if not output is None:
  192.         #    print "Result: %s" % output
  193.         if (not errors is None) and (not errors == ""):
  194.             print "Process stderr: %s" % errors
  195.     return output
  196.  
  197. def ParseXML(xml_filename):
  198.     global PartitionArray, PatchArray, ZeroOutArray,MinDiskSize
  199.  
  200.     root = ET.parse( xml_filename )
  201.     #Create an iterator
  202.     iter = root.getiterator()
  203.     for element in iter:
  204.         #print "\nElement:" , element.tag
  205.         # Parse out include files
  206.         if element.tag=="program":
  207.             #print "\nFound a partition to program"
  208.  
  209.             if element.keys():
  210.                 ##print "\tAttributes:"
  211.                 Partition = {}
  212.                 for name, value in element.items():
  213.                     #print "\t\tName: '%s'=>'%s' " % (name,value)
  214.                     Partition[name]=value
  215.  
  216.             ##print "Partition['start_sector']=",Partition['start_sector']
  217.  
  218.             m = re.search("NUM_DISK_SECTORS-(\d+)", Partition['start_sector'])
  219.             if type(m) is not NoneType:
  220.                 if DiskSize > 0 :
  221.                     Partition['start_sector']           = int((DiskSize/512)-int(m.group(1)))
  222.                 else:
  223.                     Partition['start_sector']           = int((EMMCBLD_MIN_DISK_SIZE/512)-int(m.group(1)))
  224.             else:
  225.                 Partition['start_sector']           = int(Partition['start_sector'])
  226.  
  227.             if 'num_sectors' in Partition:
  228.                 Partition['num_sectors']            = int(Partition['num_sectors'])
  229.             else:
  230.                 Partition['num_sectors']            = int(Partition['num_partition_sectors'])
  231.  
  232.             if 'offset' in Partition:
  233.                 Partition['offset']                 = int(Partition['offset'])
  234.             else:
  235.                 Partition['offset']                 = int(Partition['file_sector_offset'])
  236.  
  237.             Partition['physical_partition_number']  = int(Partition['physical_partition_number'])
  238.  
  239.             PartitionArray.append( Partition )
  240.  
  241.         elif element.tag=="patch":
  242.             #print "\nFound a PATCH to program"
  243.  
  244.             if element.keys():
  245.                 #print "\n\tAttributes:"
  246.                 Patch = {}
  247.                 for name, value in element.items():
  248.                     #print "\t\tName: '%s'=>'%s' " % (name,value)
  249.                     Patch[name]=value
  250.  
  251.                 Patch['function']           = "none"
  252.                 Patch['arg0']               = 0
  253.                 Patch['arg1']               = 0
  254.  
  255.  
  256.                 m = re.search("NUM_DISK_SECTORS-(\d+)", Patch['start_sector'])
  257.                 if type(m) is not NoneType:
  258.                     Patch['start_sector'] = Patch['start_sector'].replace("NUM_DISK_SECTORS-%s"%m.group(1),str(int((DiskSize/512)-int(m.group(1)))))
  259.  
  260.                 m = re.search("NUM_DISK_SECTORS-(\d+)", Patch['value'])
  261.                 if type(m) is not NoneType:
  262.                     # if we are patching, then at this point NUM_DISK_SECTORS could have been zero
  263.                     # In that case, set to EMMCBLD_MIN_DISK_SIZE
  264.                     if DiskSize>0:
  265.                         Patch['value'] = Patch['value'].replace("NUM_DISK_SECTORS-%s"%m.group(1),str(int((DiskSize/512)-int(m.group(1)))))
  266.                     else:
  267.                         Patch['value'] = Patch['value'].replace("NUM_DISK_SECTORS-%s"%m.group(1),str(int(EMMCBLD_MIN_DISK_SIZE/512)-int(m.group(1))))
  268.  
  269.                 Patch['start_sector']   = int(float(Patch['start_sector']))
  270.  
  271.                 m = re.search("CRC32\((\d+).?,(\d+).?\)", Patch['value'])
  272.                 if type(m) is not NoneType:
  273.                     Patch['value']          = 0
  274.                     Patch['function']       = "CRC32"
  275.                     Patch['arg0']           = int(float(m.group(1)))   # start_sector
  276.                     Patch['arg1']           = int(float(m.group(2)))   # len_in_bytes
  277.  
  278.                 ##print Patch['value']
  279.  
  280.                 Patch['value']              = int(float(Patch['value']))
  281.                 Patch['byte_offset']        = int(float(Patch['byte_offset']))
  282.                 Patch['size_in_bytes']      = int(float(Patch['size_in_bytes']))
  283.                 Patch['byte_offset']        = int(float(Patch['byte_offset']))
  284.  
  285.                 Patch['physical_partition_number']  = int(float(Patch['physical_partition_number']))
  286.  
  287.                 if Patching=="DISK":
  288.                     if Patch['filename']=="DISK":
  289.                         PatchArray.append( Patch )
  290.                 if Patching=="FILES":
  291.                     if Patch['filename']!="DISK":
  292.                         PatchArray.append( Patch )
  293.  
  294.         elif element.tag=="zeroout":
  295.             #print "\nFound a zeroout to program"
  296.  
  297.             if element.keys():
  298.                 #print "\n\tAttributes:"
  299.                 Zeroout = {}
  300.                 for name, value in element.items():
  301.                     #print "\t\tName: '%s'=>'%s' " % (name,value)
  302.                     Zeroout[name]=value
  303.  
  304.                     # <zeroout label="Wipe_GPT_Backup" num_partition_sectors="1" physical_partition_number="0" start_sector="NUM_DISK_SECTORS-1."/>
  305.  
  306.                 m = re.search("NUM_DISK_SECTORS-(\d+)", Zeroout['start_sector'])
  307.                 if type(m) is not NoneType:
  308.                     Zeroout['start_sector'] = Zeroout['start_sector'].replace("NUM_DISK_SECTORS-%s"%m.group(1),str(int((DiskSize/512)-int(m.group(1)))))
  309.  
  310.                 Zeroout['start_sector']   = int(float(Zeroout['start_sector']))
  311.                 Zeroout['physical_partition_number']  = int(float(Zeroout['physical_partition_number']))
  312.  
  313.                 ZeroOutArray.append( Zeroout )
  314.                 #print Zeroout
  315.                 #print "\n"
  316.  
  317.  
  318. def ReturnArrayFromCommaSeparatedList(sz):
  319.     temp = re.sub("\s+|\n"," ",sz)
  320.     temp = re.sub("^\s+","",temp)
  321.     temp = re.sub("\s+$","",temp)
  322.     return temp.split(',')
  323.  
  324. def find_file(filename, search_paths):
  325.     print "\n\n\tLooking for",filename
  326.     print "\t"+"-"*40
  327.     for x in search_paths:
  328.         print "\tSearching ",x
  329.         temp = os.path.join(x, filename)
  330.         if os.path.exists(temp):
  331.             print "\n\t**Found %s (%i bytes)" % (temp,os.path.getsize(temp))
  332.             return temp
  333.  
  334.     ## search cwd last
  335.     print "\tSearching ",os.getcwd()
  336.     if os.path.exists(filename):
  337.         print "\n\t**Found %s (%i bytes)" % (filename,os.path.getsize(filename))
  338.         return filename
  339.  
  340.     print "\tCound't find file\n"
  341.     return None
  342.  
  343.  
  344. def DoubleCheckDiskSize():
  345.  
  346.     if os.path.basename(Filename)=="singleimage.bin":
  347.         return
  348.  
  349.     if sys.platform.startswith("win"):
  350.         print "\n\nTesting of OS detected disk size correctly...\n"
  351.    
  352.         Size = AvailablePartitions[Filename]
  353.    
  354.         TrueSize = Size
  355.    
  356.         count = 0
  357.         # Windows workaround to get the correct number of sectors
  358.         fp = open(Filename, 'rb')
  359.         fp.seek(int(Size))
  360.         try:
  361.             while True:
  362.                 fp.read(SECTOR_SIZE)
  363.  
  364.                 if count % 128 == 0:
  365.                     sys.stdout.write(".")
  366.  
  367.                 count += 1
  368.  
  369.         except:
  370.             TrueSize = fp.tell()
  371.         fp.close()
  372.    
  373.         if TrueSize != Size and Size<=(64*1024*1024*1024):
  374.             print "\n\t                          _             "
  375.             print "\t                         (_)            "
  376.             print "\t__      ____ _ _ __ _ __  _ _ __   __ _ "
  377.             print "\t\\ \\ /\\ / / _` | '__| '_ \\| | '_ \\ / _` |"
  378.             print "\t \\ V  V / (_| | |  | | | | | | | | (_| |"
  379.             print "\t  \\_/\\_/ \\__,_|_|  |_| |_|_|_| |_|\\__, |"
  380.             print "\t                                   __/ |"
  381.             print "\t                                  |___/ \n\n"
  382.             print "NOTE: This OS has *not* detected the correct size of the disk"
  383.             print "\nSECTORS: Size=%i, TrueSize=%i, Difference=%i sectors (%s)" % (Size/512,TrueSize/512,(TrueSize-Size)/512,ReturnSizeString(TrueSize-Size))
  384.             print "This means the backup GPT header will *not* be located at the true last sector"
  385.             print "This is only an issue if you care :) It will be off by %s" % ReturnSizeString(TrueSize-Size)
  386.             print "\nNOTE: This program *can't* write to the end of the disk, OS limitation"
  387.         else:
  388.             print "\n\nAll is well\n"
  389.    
  390.  
  391.  
  392. def PerformWrite():
  393.     global PartitionSorted, LoadSubsetOfFiles, search_paths, interactive, SingleImageSize, Filename
  394.  
  395.     print "\t                                                     _            "
  396.     print "\t                                                    (_)            "
  397.     print "\t _ __  _ __ ___   __ _ _ __ __ _ _ __ ___  _ __ ___  _ _ __   __ _ "
  398.     print "\t| '_ \\| '__/ _ \\ / _` | '__/ _` | '_ ` _ \\| '_ ` _ \\| | '_ \\ / _` |"
  399.     print "\t| |_) | | | (_) | (_| | | | (_| | | | | | | | | | | | | | | | (_| |"
  400.     print "\t| .__/|_|  \\___/ \\__, |_|  \\__,_|_| |_| |_|_| |_| |_|_|_| |_|\\__, |"
  401.     print "\t| |               __/ |                                       __/ |"
  402.     print "\t|_|              |___/                                       |___/ "
  403.  
  404.     for Partition in PartitionSorted:   # Here Partition is a *sorted* entry from rawprogram.xml
  405.         if Partition['physical_partition_number']!=0:   ## msp tool can only write to PHY partition 0
  406.             print "Skipping '%s' for physical_partition_number=%d (only 0 is accessible)" % (Partition['filename'],Partition['physical_partition_number'])
  407.         else:
  408.  
  409.             if len(Partition['filename'])==0:
  410.                 continue
  411.  
  412.             if LoadSubsetOfFiles is True:
  413.                 # To be here means user only wants some of the files loaded from rawprogram0.xml
  414.                 if Partition['filename'] in file_list:
  415.                     #print "LOAD: '%s' was specified to be programmed" % Partition['filename']
  416.                     pass
  417.                 else:
  418.                     #print "SKIPPING: '%s', it was not specified to be programmed" % Partition['filename']
  419.                     continue
  420.  
  421.  
  422.             print "\n"+"="*78
  423.             print "="*78
  424.             FileWithPath = find_file(Partition['filename'], search_paths)
  425.  
  426.             size=0
  427.             if FileWithPath is not None:
  428.                 size = os.path.getsize(FileWithPath)
  429.  
  430.  
  431.             # to be here the rawprogram.xml file had to have a "filename" entry
  432.             print "\n'%s' (%s) to partition '%s' at sector %d (at %s)\n" % (Partition['filename'],ReturnSizeString(size),Partition['label'],Partition['start_sector'],ReturnSizeString(Partition['start_sector']*512))
  433.  
  434.             if interactive is True:
  435.                 loadfile = raw_input("Do you want to load this file? (Y|n|q)")
  436.                 if loadfile=='Y' or loadfile=='y' or loadfile=='':
  437.                     pass
  438.                 elif loadfile=='q' or loadfile=='Q':
  439.                     sys.exit()
  440.                 else:
  441.                     continue
  442.  
  443.             while FileWithPath is None:
  444.                 FileNotFoundShowWarning = 1
  445.  
  446.                 print "\t______      _   _        ___  "
  447.                 print "\t| ___ \\    | | | |      |__ \\ "
  448.                 print "\t| |_/ /__ _| |_| |__       ) |"
  449.                 print "\t|  __// _` | __| '_ \\     / / "
  450.                 print "\t| |  | (_| | |_| | | |   |_|  "
  451.                 print "\t\\_|   \\__,_|\\__|_| |_|   (_)  \n\n"
  452.  
  453.                 print "ERROR: '%s' listed in '%s' not found\n" % (Partition['filename'],rawprogram_filename)
  454.  
  455.                 print "Please provide a path for this file"
  456.                 print "Ex. \\\\somepath\\folder OR c:\\somepath\\folder\n"
  457.                 temppath = raw_input("Enter PATH or Q to quit? ")
  458.                 if temppath=='Q' or temppath=='q' or temppath=='':
  459.                     sys.exit()
  460.  
  461.                 print "\n"
  462.  
  463.                 FileWithPath = find_file(Partition['filename'], [temppath])
  464.  
  465.                 size=0
  466.                 if FileWithPath is not None:
  467.                     size = os.path.getsize(FileWithPath)
  468.  
  469.                     temp = raw_input("\nShould this path be used to find other files? (Y|n|q)")
  470.                     if temp=='Q' or temp=='q':
  471.                         sys.exit()
  472.                     elif temp=='Y' or temp=='y' or temp=='':
  473.                         search_paths.append(temppath)
  474.                     print "\n"
  475.  
  476.             if size==0:
  477.                 loadfile = raw_input("WARNING: This file is 0 bytes, do you want to load this file? (y|N|q)")
  478.                 if loadfile=='N' or loadfile=='n' or loadfile=='':
  479.                     continue
  480.                 elif loadfile=='q' or loadfile=='Q':
  481.                     sys.exit()
  482.                 else:
  483.                     pass
  484.  
  485.  
  486.             if Partition['num_sectors']==0:
  487.                 Partition['num_sectors'] = int(size/512)
  488.                 if size%512 != 0:
  489.                     Partition['num_sectors']+=1 # not an even multiple of 512, so ++
  490.  
  491.             ##print "At start_sector %i (%.2fKB) write %i sectors" % (Partition['start_sector'],Partition['start_sector']/2.0,Partition['num_sectors'])
  492.             ##print "\tsize of \"%s\" is %i bytes" % (Partition['filename'],size)
  493.             ##print "\tsize of partition listed in in \"%s\" is %i bytes" % (rawprogram_filename,Partition['num_sectors']*512)
  494.  
  495.             ## This below happens on files like partition0.bin, where they hold the entire partition table,
  496.             ## but, only MBR is meant to be written, thus partition0.bin is 9 sectors but MBR is only 1 sector
  497.  
  498.             if size > (Partition['num_sectors']*512):
  499.                 size = Partition['num_sectors']*512
  500.  
  501.             ##print "\tAttempting to read %i bytes from \n\t\"%s\" at offset %i" % (size,Partition['filename'],Partition['offset'])
  502.             #os.getcwd()+"\\"+
  503.  
  504.             try:
  505.                 ipfile = open(FileWithPath, "rb")
  506.             except:
  507.                 print "ERROR: Could not open FileWithPath=%s, cwd=%s" % (Partition['filename'], os.getcwd() )
  508.                 sys.exit()
  509.  
  510.  
  511.             print "\tAttempting to move to sector %i (file offset) in %s" % (Partition['offset'],Partition['filename'])
  512.             try:
  513.                 ipfile.seek(int(Partition['offset']*512))
  514.             except:
  515.                 print "ERROR: Could not move to sector %d in %s" % (Partition['offset'],Partition['filename'])
  516.                 sys.exit()
  517.  
  518.             print "\tAttempting to read %i bytes" % (size)
  519.             try:
  520.                 if size<MAX_FILE_SIZE_BEFORE_SPLIT:
  521.                     bytes_read = ipfile.read(size)
  522.                 else:
  523.                     print "File is too large to read all at once, must be broken up"
  524.             except:
  525.                 print "ERROR: Could not read %d bytes in %s" % (size,Partition['filename'])
  526.                 sys.exit()
  527.  
  528.             if size<MAX_FILE_SIZE_BEFORE_SPLIT:
  529.                 ipfile.close()
  530.  
  531.             if size<MAX_FILE_SIZE_BEFORE_SPLIT:
  532.                 print "\tSuccessfully read %d bytes of %d bytes and closed %s" % (len(bytes_read),size,Partition['filename'])
  533.  
  534.                 Remainder = len(bytes_read)%512
  535.  
  536.                 if Remainder != 0:
  537.                     print "\tbytes_read is not a multiple of 512, appending zeros"
  538.  
  539.                     Bytes = struct.unpack("%dB" % len(bytes_read),bytes_read)    ## unpack returns list, so get index 0
  540.  
  541.                     Temp         = list(Bytes) + [0x00]*(512-Remainder)   # concat
  542.                     TotalSize = len(Temp)
  543.  
  544.                     bytes_read = struct.pack("%dB" % TotalSize, *Temp)
  545.                     print "\tNow len(bytes_read)=%d" % len(bytes_read)
  546.  
  547.                 # At this point bytes_read is a multiple of 512
  548.  
  549.             #print "\t\tNeed to move to location %i (%i bytes) in %s" % (Partition['start_sector'],(Partition['start_sector']*512),Filename)
  550.             #print "\t\tPartition['start_sector']*512 = %i" % (Partition['start_sector']*512)
  551.  
  552.             if (2*DiskSize)<Partition['start_sector'] and os.path.basename(Filename)!="singleimage.bin":
  553.                 print "2*DiskSize=%d" % (2*DiskSize)
  554.                 print "Partition['start_sector']=",Partition['start_sector']
  555.                 print "\n\nERROR: Attempting to move to sector %i (%.2f MB) and only %i sectors (%.2f MB) exist (%i difference (%.2f MB) )" % (Partition['start_sector'],Partition['start_sector']/2048.0,2*DiskSize,DiskSize/1024.0,Partition['start_sector']-(2*DiskSize),(Partition['start_sector']-(2*DiskSize))/2048.0)
  556.                 sys.exit()
  557.  
  558.             try:
  559.                 if os.path.basename(Filename)=="singleimage.bin":
  560.                     Filename = OutputFolder+os.path.basename(Filename)
  561.  
  562.                 opfile = open(Filename, "r+b")  ## Filename = '\\.\PHYSICALDRIVE1'
  563.                 #print "Opened '%s', cwd=%s" % (Filename, os.getcwd() )
  564.             except:
  565.                 print "ERROR: Could not open Filename=%s, cwd=%s" % (Filename, os.getcwd() )
  566.  
  567.                 if sys.platform.startswith("linux"):
  568.                     print "\tDon't forget you need SUDO with this program"
  569.                     print "\tsudo python msp.py partition.xml /dev/sdx (where x is the device node)"
  570.                 else:
  571.                     print "\t  ___      _           _       _     _             _                ___  "
  572.                     print "\t / _ \\    | |         (_)     (_)   | |           | |              |__ \\ "
  573.                     print "\t/ /_\\ \\ __| |_ __ ___  _ _ __  _ ___| |_ _ __ __ _| |_  ___  _ __     ) |"
  574.                     print "\t|  _  |/ _` | '_ ` _ \\| | '_ \\| / __| __| '__/ _` | __|/ _ \\| '__|   / / "
  575.                     print "\t| | | | (_| | | | | | | | | | | \\__ \\ |_| | | (_| | |_| (_) | |     |_|  "
  576.                     print "\t\\_| |_/\\__,_|_| |_| |_|_|_| |_|_|___/\\__|_|  \\__,_|\\__|\\___/|_|     (_)  \n\n"
  577.  
  578.                     print "\n"+"-"*78
  579.                     print "\tThis program needs to be run as Administrator!!"
  580.                     print "-"*78+"\n"
  581.                     print "-"*78
  582.                     print "\tTo fix, you must open a CMD prompt with \"Run as administrator\""
  583.                     print "-"*78+"\n"
  584.  
  585.                 sys.exit()
  586.  
  587.             print "\n\tOpened %s" % Filename
  588.  
  589.  
  590.             if Partition['start_sector'] < 0:
  591.                 print "start sector is less than 0 - skipping this instruction, most likely for GPT HACK"
  592.                 continue
  593.  
  594.             if Partition['start_sector'] > int(DiskSize/512):
  595.                 print "\nERROR: Start sector is BIGGER than the disk"
  596.                 print "\nERROR: Your device is TOO SMALL to handle this partition info"
  597.                 sys.exit(1)
  598.  
  599.             try:
  600.                 opfile.seek(int(Partition['start_sector']*512))
  601.             except:
  602.                 print "ERROR: Could not move to sector %d on %s" % (Partition['start_sector'],Filename)
  603.                 sys.exit()
  604.  
  605.             print "\tMoved to sector %d on %s" % (Partition['start_sector'],Filename)
  606.  
  607.             ##print "size=",size
  608.             ##print "MAX_FILE_SIZE_BEFORE_SPLIT=",MAX_FILE_SIZE_BEFORE_SPLIT
  609.  
  610.             if size<MAX_FILE_SIZE_BEFORE_SPLIT:
  611.                 print "\tFile can be written completely."
  612.                 try:
  613.                     opfile.write(bytes_read)
  614.                 except:
  615.                     print "ERROR: Could not write to %s" % (Filename)
  616.                     print "\nPlease try removing the medium and re-inserting it"
  617.                     print "Strangly this helps sometimes after writing *new* partition tables\n\n"
  618.                     sys.exit()
  619.  
  620.             else:
  621.                 ## To be here means I need to break up the file
  622.                 ##print "I need to break up this file"
  623.  
  624.                 TempSize = size
  625.                 NumLoop = int(TempSize/MAX_FILE_SIZE_BEFORE_SPLIT)
  626.                 Remainder = size%MAX_FILE_SIZE_BEFORE_SPLIT
  627.                 if Remainder>0:
  628.                     Remainder=1
  629.  
  630.                 print "\nNeed to break up this file, will loop %d times writing %i bytes each time" % (NumLoop+Remainder,MAX_FILE_SIZE_BEFORE_SPLIT)
  631.                 TempSize=0
  632.                 for a in range(NumLoop):
  633.                     #print "read %i bytes" % MAX_FILE_SIZE_BEFORE_SPLIT
  634.                     try:
  635.                         bytes_read = ipfile.read(MAX_FILE_SIZE_BEFORE_SPLIT)
  636.                     except:
  637.                         print "ERROR: Could not read from %s" % (FileWithPath)
  638.                         sys.exit()
  639.  
  640.                     ##print "\n\t%i) Packing %i Bytes [%i:%i]" % (a+1,MAX_FILE_SIZE_BEFORE_SPLIT,TempSize,TempSize+MAX_FILE_SIZE_BEFORE_SPLIT)
  641.                     ##bytes_read = struct.pack("%dB" % MAX_FILE_SIZE_BEFORE_SPLIT, *Bytes[TempSize:(TempSize+MAX_FILE_SIZE_BEFORE_SPLIT)])
  642.                     print "\t%.2i) Writing %i Bytes [%i:%i]" % (a+1,MAX_FILE_SIZE_BEFORE_SPLIT,TempSize,TempSize+MAX_FILE_SIZE_BEFORE_SPLIT)
  643.                     try:
  644.                         opfile.write(bytes_read)
  645.                     except:
  646.                         print "ERROR: Could not write to %s" % (Filename)
  647.                         sys.exit()
  648.  
  649.                     TempSize += MAX_FILE_SIZE_BEFORE_SPLIT
  650.                 ##print "Out of loop"
  651.                 a+=1    
  652.  
  653.                 if Remainder == 1:
  654.                     # Need to PAD the file to be a multiple of 512 bytes too
  655.    
  656.                     #print "\n\t%i) Packing %i Bytes [%i:%i]" % (a,(len(Bytes)-TempSize),TempSize,len(Bytes))
  657.                     #bytes_read = struct.pack("%dB" % (len(Bytes)-TempSize), *Bytes[TempSize:len(Bytes)])
  658.    
  659.                     print "\t%.2i) Writing %i Bytes [%i:%i]" % (a+1,(size-TempSize),TempSize,size)
  660.                     try:
  661.                         bytes_read = ipfile.read(size-TempSize)
  662.                     except:
  663.                         print "ERROR: Could not read from %s" % (FileWithPath)
  664.                         sys.exit()
  665.    
  666.                     ##print "len(bytes_read)=",len(bytes_read)
  667.    
  668.                     Remainder = len(bytes_read)%512
  669.    
  670.                     if Remainder != 0:
  671.                         print "\tbytes_read is not a multiple of 512, appending zeros"
  672.    
  673.                         Bytes = struct.unpack("%dB" % len(bytes_read),bytes_read)    ## unpack returns list, so get index 0
  674.    
  675.                         Temp         = list(Bytes) + [0x00]*(512-Remainder)   # concat
  676.                         TotalSize = len(Temp)
  677.    
  678.                         bytes_read = struct.pack("%dB" % TotalSize, *Temp)
  679.                         print "\tNow len(bytes_read)=%d" % len(bytes_read)
  680.    
  681.                     # At this point bytes_read is a multiple of 512
  682.    
  683.                     #print "This is the final write"
  684.                     try:
  685.                         opfile.write(bytes_read)
  686.                     except:
  687.                         print "ERROR: Could not write to %s" % (Filename)
  688.                         sys.exit()
  689.  
  690.                 ipfile.close()
  691.  
  692.             if os.path.basename(Filename)=="singleimage.bin":
  693.                 print "\tSingleImageSize before = ", SingleImageSize
  694.                 SingleImageSize+=int(len(bytes_read)/512)
  695.                 print "\tSingleImageSize after = ", SingleImageSize
  696.  
  697.             #print "\tWrote %d bytes at sector %d on %s" % (len(bytes_read),Partition['start_sector'],Filename)
  698.  
  699.             try:
  700.                 ##print opfile
  701.                 opfile.close()
  702.             except:
  703.                 print "\tWARNING: Can't close the file?"
  704.                 #sys.exit()
  705.                 pass
  706.  
  707.  
  708.             print "\n\tWritten with"
  709.             print "\tpython dd.py --if=%s --bs=512 --count=%i --seek=%i --of=%s" % (FileWithPath,int((size-1)/SECTOR_SIZE)+1,Partition['start_sector'],Filename)
  710.             print "\n\tVerify with"
  711.             print "\tpython dd.py --if=%s --bs=512 --count=%i --skip=%i --of=dump.bin" % (Filename,int((size-1)/SECTOR_SIZE)+1,Partition['start_sector'])
  712.  
  713.             print "\n\tSuccessfully wrote \"%s\" (%s payload) to %s" % (Partition['filename'],ReturnSizeString(size),Filename)
  714.  
  715.             #raw_input("Enter something: ")
  716.  
  717.             #if Partition['filename']=="sbl3.mbn":
  718.             #    sys.exit()
  719.     print "\nDone Writing Files\n"
  720.  
  721. def GetPartitions():
  722.     global Devices,AvailablePartitions
  723.     if sys.platform.startswith("linux"):
  724.         print "This is a linux system since sys.platform='%s'" % sys.platform
  725.  
  726.         print "-"*78    
  727.         print "\tRemember - DON'T FORGET SUDO"
  728.         print "\tRemember - DON'T FORGET SUDO"
  729.         print "\tRemember - DON'T FORGET SUDO"
  730.         print "-"*78+"\n"
  731.  
  732.         os.system("cat /proc/partitions > temp_partitions.txt")
  733.         IN = open("temp_partitions.txt")
  734.         output = IN.readlines()
  735.         for line in output:
  736.             #print line
  737.  
  738.             m = re.search("(\d+) (sd[a-z])$", line)
  739.             if type(m) is not NoneType:
  740.                 Size    = int(m.group(1))
  741.                 Device  = "/dev/"+m.group(2)
  742.                 #print "%s\tSize=%d,%.1fMB (%.2fGB) (%iKB)" % (Device,Size,int(Size)/1024.0,int(Size)/(1024.0*1024.0),int(Size))
  743.                 AvailablePartitions[Device] = Size*1024.0    # linux reports in terms of 1024,
  744.  
  745.  
  746.     else:
  747.         ##print "This is a windows system since sys.platform='%s'" % sys.platform
  748.  
  749.         print "\t  ___      _           _       _     _             _                ___  "
  750.         print "\t / _ \\    | |         (_)     (_)   | |           | |              |__ \\ "
  751.         print "\t/ /_\\ \\ __| |_ __ ___  _ _ __  _ ___| |_ _ __ __ _| |_  ___  _ __     ) |"
  752.         print "\t|  _  |/ _` | '_ ` _ \\| | '_ \\| / __| __| '__/ _` | __|/ _ \\| '__|   / / "
  753.         print "\t| | | | (_| | | | | | | | | | | \\__ \\ |_| | | (_| | |_| (_) | |     |_|  "
  754.         print "\t\\_| |_/\\__,_|_| |_| |_|_|_| |_|_|___/\\__|_|  \\__,_|\\__|\\___/|_|     (_)  \n\n"
  755.  
  756.         print "-"*78    
  757.         print "\tRemember - Under Win7 you must run this as Administrator"
  758.         print "\tRemember - Under Win7 you must run this as Administrator"
  759.         print "\tRemember - Under Win7 you must run this as Administrator"
  760.         print "-"*78
  761.  
  762.         response = external_call('wmic DISKDRIVE get DeviceID, MediaType, Model, Size')
  763.         m = re.search("Access is denied", response)
  764.         if type(m) is not NoneType:
  765.             print "\nERROR: This computer does not have correct privileges, you need administrator group privilege\n"
  766.             sys.exit(1)
  767.  
  768.         response = response.replace('\r', '').strip("\n").split("\n")[1:]
  769.         for line in response:
  770.             m = re.search("(PHYSICALDRIVE\d+).+ (\d+) ", line)
  771.             if type(m) is not NoneType:
  772.                 Size    = int(m.group(2))       # size in sectors
  773.                 Device  = "\\\\.\\"+m.group(1)  # \\.\PHYSICALDRIVE1
  774.  
  775.                 AvailablePartitions[Device] = Size
  776.  
  777.  
  778.     Devices = AvailablePartitions.keys()
  779.     Devices.sort()
  780.  
  781.     print "\n\n"+"-"*78
  782.     print "--------------------------------Partitions Detected--------------------------------------"
  783.     print "-"*78+"\n"
  784.     for device in Devices:
  785.         value = AvailablePartitions[device]
  786.  
  787.         if value/(1024.0*1024.0*1024.0) > 31.0:
  788.             print "%s   %s\tsectors:%i <--- Not likely an SD card, careful!" % (device,ReturnSizeString(value),value/512)
  789.         else:
  790.             print "%s   %s\tsectors:%i" % (device,ReturnSizeString(value),value/512)
  791.  
  792.     print "\n"+"-"*78+"\n"
  793.  
  794. def PerformPatching():
  795.     global PatchArray,Patching
  796.  
  797.     print "\t             _        _     _             "
  798.     print "\t            | |      | |   (_)            "
  799.     print "\t _ __   __ _| |_  ___| |__  _ _ __   __ _ "
  800.     print "\t| '_ \\ / _` | __|/ __| '_ \\| | '_ \\ / _` |"
  801.     print "\t| |_) | (_| | |_| (__| | | | | | | | (_| |"
  802.     print "\t| .__/ \\__,_|\\__|\\___|_| |_|_|_| |_|\\__, |"
  803.     print "\t| |                                  __/ |"
  804.     print "\t|_|                                 |___/ "
  805.    
  806.     var = 'Y'
  807.     if Patching == "DISK":
  808.         var = 'N'           ## user must authorize this
  809.  
  810.     ## PATCHING HAPPENS HERE - PATCHING HAPPENS HERE - PATCHING HAPPENS HERE
  811.  
  812.     for Patch in PatchArray:
  813.  
  814.         if Patch['physical_partition_number']!=0:   ## msp tool can only write to PHY partition 0
  815.             print "Skipping '%s' for physical_partition_number=%d (only 0 is accessible)" % (Patch['filename'],Patch['physical_partition_number'])
  816.         else:
  817.  
  818.             print "\n" + "-"*78
  819.             print "PATCH: (%s) %s" % (Patch['filename'],Patch['what'])
  820.  
  821.             FileToOpen =  Patch['filename']
  822.  
  823.             if nopromt is True:
  824.                 # means don't bug them, i.e. automation
  825.                 pass
  826.             else:
  827.                 if var=='N' or var=='n':
  828.                     var = raw_input("\nWARNING: Are you sure you want to PATCH to '%s' of size %s (y|N) " % (Filename,ReturnSizeString(DiskSize)))
  829.                     if var=='Y' or var=='y':
  830.                         pass
  831.                     else:
  832.                         sys.exit(1)
  833.  
  834.             if Patching=="DISK":
  835.                 FileWithPath = Filename
  836.             else:
  837.                 FileWithPath = find_file(FileToOpen, search_paths)
  838.  
  839.             while FileWithPath is None:
  840.                 FileNotFoundShowWarning = 1
  841.  
  842.                 print "\t______      _   _        ___  "
  843.                 print "\t| ___ \\    | | | |      |__ \\ "
  844.                 print "\t| |_/ /__ _| |_| |__       ) |"
  845.                 print "\t|  __// _` | __| '_ \\     / / "
  846.                 print "\t| |  | (_| | |_| | | |   |_|  "
  847.                 print "\t\\_|   \\__,_|\\__|_| |_|   (_)  \n\n"
  848.  
  849.                 if rawprogram_filename is None:
  850.                     print "ERROR: '%s' listed in '%s' not found\n" % (FileToOpen,patch_filename)
  851.                 else:
  852.                     print "ERROR: '%s' listed in '%s' not found\n" % (FileToOpen,rawprogram_filename)
  853.  
  854.                 print "Please provide a path for this file"
  855.                 print "Ex. \\\\somepath\\folder OR c:\\somepath\\folder\n"
  856.                 temppath = raw_input("Enter PATH or Q to quit? ")
  857.                 if temppath=='Q' or temppath=='q' or temppath=='':
  858.                     sys.exit()
  859.  
  860.                 print "\n"
  861.  
  862.                 FileWithPath = find_file(Partition['filename'], [temppath])
  863.  
  864.                 size=0
  865.                 if FileWithPath is not None:
  866.                     size = os.path.getsize(FileWithPath)
  867.  
  868.                     temp = raw_input("\nShould this path be used to find other files? (Y|n|q)")
  869.                     if temp=='Q' or temp=='q':
  870.                         sys.exit()
  871.                     elif temp=='Y' or temp=='y' or temp=='':
  872.                         search_paths.append(temppath)
  873.                     print "\n"            
  874.                
  875.             try:
  876.                 opfile = open(FileWithPath, "r+b")
  877.                 print "Opened %s, cwd=%s" % (FileWithPath,os.getcwd() )
  878.             except:
  879.                 print "ERROR: Could not open %s, cwd=%s" % (FileWithPath,os.getcwd() )
  880.                 sys.exit()
  881.  
  882.             if Patch['function']=="CRC32":
  883.                 print "\t%s(%u,%u) requested " % (Patch['function'],Patch['arg0'],Patch['arg1'])
  884.  
  885.                 PStartSector = int(Patch['arg0'])
  886.                 PNumSectors  = int(Patch['arg1']/512)
  887.                 if PNumSectors==0:
  888.                     PNumSectors+=1
  889.  
  890.                 try:
  891.                     if Patch['arg0']>64:
  892.                         print "\tPatch['arg0']=%d" % Patch['arg0']
  893.                         print "\tPatch['arg1']=%d" % Patch['arg1']
  894.  
  895.                         print "\tmoving to sector %d-%d (%d)" % (PStartSector,(64-PNumSectors),PStartSector-(64-PNumSectors))
  896.                         opfile.seek( int( (PStartSector-(64-PNumSectors) )*512 ))
  897.                     else:
  898.                         print "moving to sector %d (byte location %d)" % (Patch['arg0'],Patch['arg0']*512)
  899.                         opfile.seek( int(Patch['arg0']*512))
  900.  
  901.                 except:
  902.                     print "ERROR: Could not complete move in %s" % (FileWithPath)
  903.                     sys.exit()
  904.  
  905.                 print "\tMove Successful "
  906.  
  907.                 try:
  908.                     if Patch['arg0']>64:
  909.                         print "\tTrying to read %d bytes in %s" % (64*512,FileWithPath)
  910.                         bytes_read = opfile.read(64*512)
  911.                     else:
  912.                         print "\tTrying to read %d bytes in %s" % (Patch['arg1'],FileWithPath)
  913.                         bytes_read = opfile.read(Patch['arg1'])
  914.                 except:
  915.                     print "ERROR: Could not read in %s" % (FileWithPath)
  916.                     sys.exit()
  917.  
  918.                 print "\tlen(bytes_read)=",len(bytes_read)
  919.  
  920.                 if Patch['arg0']>64:
  921.                     Bytes = struct.unpack("%dB" % (64*512),bytes_read)    ## unpack returns list, so get index 0
  922.                 else:
  923.                     Bytes = struct.unpack("%dB" % Patch['arg1'],bytes_read)    ## unpack returns list, so get index 0
  924.  
  925.  
  926.  
  927.                 if Patch['arg0']>64:
  928.                     #PStartSector
  929.                     #PNumSectors
  930.                     StartByte = (64-PNumSectors)*512
  931.                     print "\tStartByte=",StartByte
  932.  
  933.                     Patch['value'] = CalcCRC32(Bytes[StartByte:],Patch['arg1'])
  934.                 else:
  935.                     Patch['value'] = CalcCRC32(Bytes,Patch['arg1'])
  936.  
  937.                 print "\tCRC32=0x%.8X" % Patch['value']
  938.  
  939.             # ELSE - patch is not a CRC
  940.             try:
  941.                 if Patch['start_sector']>64:
  942.                     #print "moving to %d-63=%d" % (Patch['start_sector'],Patch['start_sector']-63)
  943.                     opfile.seek( int((Patch['start_sector']-63)*512))
  944.                 else:
  945.                     #print "moving to sector %d (byte location %d)" % (Patch['start_sector'],Patch['start_sector']*512)
  946.                     opfile.seek(int(Patch['start_sector']*512))
  947.             except:
  948.                 print "ERROR: Could not move to sector %d in %s" % (Patch['start_sector'],FileWithPath)
  949.                 sys.exit()
  950.  
  951.             try:
  952.                 if Patch['start_sector']>64:
  953.                     bytes_read = opfile.read(64*512)
  954.                     if len(bytes_read) != (64*512):
  955.                         PrintBigError("Didn't get the read size 64*512");
  956.                 else:
  957.                     bytes_read = opfile.read(512)
  958.                     if len(bytes_read) != (512):
  959.                         PrintBigError("Didn't get the read size 512");
  960.             except:
  961.                 print "ERROR: Could not read sector %d in %s" % (Patch['start_sector'],FileWithPath)
  962.                 sys.exit()
  963.  
  964.  
  965.             print "success was able to read len(bytes_read)=%d" % (len(bytes_read))
  966.  
  967.             # Move back to do the write
  968.             try:
  969.                 if Patch['start_sector']>64:
  970.                     #print "moving to %d-63=%d" % (Patch['start_sector'],Patch['start_sector']-63)
  971.                     opfile.seek(int((Patch['start_sector']-63)*512))
  972.                 else:
  973.                     #print "moving to sector %d (byte location %d)" % (Patch['start_sector'],Patch['start_sector']*512)
  974.                     opfile.seek(int(Patch['start_sector']*512))
  975.             except:
  976.                 print "ERROR: Could not move to sector %d in %s" % (Patch['start_sector'],FileWithPath)
  977.                 sys.exit()
  978.  
  979.  
  980.             if Patch['value'] < 0:
  981.                 print "ERROR: Patch value was negative. This means your DISK size is too small"
  982.                 sys.exit()
  983.  
  984.             print "At sector %d (0x%X) offset %d (0x%X) in %s with %d (0x%X)" % (Patch['start_sector'],Patch['start_sector']*512,Patch['byte_offset'],Patch['byte_offset'],FileWithPath,Patch['value'],Patch['value'])
  985.  
  986.             #Patch['byte_offset']
  987.             if Patch['start_sector']>64:
  988.                 ValueList = list(struct.unpack("32768B",bytes_read))
  989.             else:
  990.                 ValueList = list(struct.unpack("512B",bytes_read))
  991.  
  992.             #print "\nBefore"
  993.             #j=0
  994.             #sys.stdout.write("%.4X\t "%j)
  995.             #for b in ValueList[-512:]:
  996.             #    sys.stdout.write("%.2X "%b)
  997.             #    j+=1
  998.             #    #if j>64:
  999.             #    #    break
  1000.             #    if j%16==0:
  1001.             #        print " "
  1002.             #        sys.stdout.write("%.4X\t "%j)
  1003.  
  1004.  
  1005.             print "Patch value:",Patch['value'],"\t"
  1006.  
  1007.             for j in range(Patch['size_in_bytes']):
  1008.                 if Patch['start_sector']>64:
  1009.                     #print "Applying patch at %d+%d=%d value=0x%.2X" % (63*512,Patch['byte_offset']+j,63*512+j+Patch['byte_offset'],(Patch['value']>>(j*8))&0xFF)
  1010.                     ValueList[63*512+Patch['byte_offset']+j ] = (Patch['value']>>(j*8))&0xFF
  1011.                     sys.stdout.write("%.2X " % (int(Patch['value']>>(j*8)) & 0xFF))
  1012.                 else:
  1013.                     ValueList[Patch['byte_offset']+j ] = (Patch['value']>>(j*8))&0xFF
  1014.                     #import pdb; pdb.set_trace()
  1015.                     sys.stdout.write("%.2X " % (int(Patch['value']>>(j*8)) & 0xFF))
  1016.  
  1017.            
  1018.             #for b in ValueList:
  1019.             #    sys.stdout.write("%.2X "%b)
  1020.  
  1021.  
  1022.             #print "\nAfter"
  1023.             #j=0
  1024.             #sys.stdout.write("%.4X\t "%j)
  1025.             #for b in ValueList[-512:]:
  1026.             #    sys.stdout.write("%.2X "%b)
  1027.             #    j+=1
  1028.             #    #if j>64:
  1029.             #    #    break
  1030.             #    if j%16==0:
  1031.             #        print " "
  1032.             #        sys.stdout.write("%.4X\t "%j)
  1033.  
  1034.             #print " "
  1035.  
  1036.             if Patch['start_sector']>64:
  1037.                 bytes_read = struct.pack("32768B",*ValueList)
  1038.             else:
  1039.                 bytes_read = struct.pack("512B",*ValueList)
  1040.  
  1041.             print "(little endian)"
  1042.             print "committing patch"
  1043.             try:
  1044.                 opfile.write(bytes_read)
  1045.             except:
  1046.                 print "ERROR: Could not write %d bytes to %s" % (len(bytes_read),FileWithPath)
  1047.                 sys.exit()
  1048.  
  1049.                 #WriteValue(fd, RawProgramInfo.start_sector, RawProgramInfo.byte_offset, RawProgramInfo.value, RawProgramInfo.size_in_bytes);
  1050.  
  1051.             try:
  1052.                 opfile.close()
  1053.             except:
  1054.                 #print "\tWARNING: Could not close %s" % FileWithPath
  1055.                 pass
  1056.  
  1057.  
  1058.             if sys.platform.startswith("linux"):
  1059.                 os.system("sync")
  1060.  
  1061.             print "PATCH:" , Patch['what']
  1062.             print "DONE\n"
  1063.  
  1064.             #if Patch['what']== "Update Backup Header with Partition Array Location.":
  1065.             #    sys.exit(0)
  1066.  
  1067.     print "Done patching"
  1068.  
  1069. def Usage():
  1070.     print "\nUsage: Mass Storage Programmer - destructively writes data to disks!!\n"
  1071.  
  1072.     sudo = ""
  1073.     drive= ""
  1074.     if sys.platform.startswith("linux"):
  1075.         sudo = "sudo"
  1076.         drive= "/dev/sdb"
  1077.     else:
  1078.         print "\tYou must run as Administrator under Win7"
  1079.         print "\tYou must run as Administrator under Win7"
  1080.         print "\tYou must run as Administrator under Win7\n"
  1081.         drive="\\\\.\\PHYSICALDRIVE1"
  1082.  
  1083.     print "%-40s\t python msp.py" % "Display this info"
  1084.     print "%-40s\t%s python msp.py -w -d %s" % ("Wipe partition info (-w)",sudo,drive)
  1085.     print "%-40s\t%s python msp.py -e -d %s" % ("Erase entire card (-e)",sudo,drive)
  1086.     print "\n%-40s\t%s python msp.py -r rawprogram0.xml -d %s" % ("Program a device (-r)",sudo,drive)
  1087.     print "%-40s\t%s python msp.py -r rawprogram0.xml -d 0" % ("Create a singleimage.bin (-r)",sudo)
  1088.     print "%-40s\t%s python msp.py -r rawprogram0.xml -d 0 -t c:\\temp" % ("singleimage.bin stored to c:\\temp (-r)",sudo)
  1089.     print "%-40s\t%s python msp.py -r rawprogram0.xml -d 8192" % ("Create an 4MB singleimage.bin (-r)",sudo)
  1090.     print "%-40s\t%s python msp.py -r rawprogram0.xml -d 16777216" % ("Create an 8GB singleimage.bin (-r)",sudo)
  1091.     print "\n%-40s\t%s python msp.py -n -r rawprogram.xml -d %s" % ("no prompts (-n) i.e. automation",sudo,drive)
  1092.     print "%-40s\t%s python msp.py -i -r rawprogram.xml -d %s " % ("Interactively choose files (-i)",sudo,drive)
  1093.     print "\n%-40s\t%s python msp.py -f sbl1.mbn -f sbl2.mbn -r rawprogram.xml -d %s " % ("Specify files from rawprogram.xml (-f)",sudo,drive)
  1094.     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)
  1095.     print "\n%-40s\t%s python msp.py -s c:\windows -s d:\ -r rawprogram.xml -d %s " % ("Search this path for files (-s)",sudo,drive)
  1096.     print "%-40s\t%s python msp.py -s c:\windows,d:\ -r rawprogram.xml -d %s " % ("Search this path for files (-s)",sudo,drive)
  1097.     print "\n%-40s\t%s python msp.py -p patch0.xml -d %s" % ("Patch a device (-p)",sudo,drive)
  1098.     print "%-40s\t%s python msp.py -p patch0.xml -d 0" % ("Patch files to default size (-p)",sudo)
  1099.     print "%-40s\t%s python msp.py -p patch0.xml -d 16384" % ("Patch files to 8MB disk size (-p)",sudo)
  1100.     print "\n%-40s\t%s python msp.py -r rawprogram0.xml -p patch0.xml -d %s" % ("ALL IN ONE STEP",sudo,drive)
  1101.  
  1102.  
  1103.  
  1104. def ReturnSizeString(size):
  1105.     if size>(1024*1024*1024):
  1106.         return "%.2f GB" % (size/(1024.0*1024.0*1024.0))
  1107.     elif size>(1024*1024):
  1108.         return "%.2f MB" % (size/(1024.0*1024.0))
  1109.     elif size>(1024):
  1110.         return "%.2f KB" % (size/(1024.0))
  1111.     else:
  1112.         return "%i B" % (size)
  1113.  
  1114.  
  1115. # A8h reflected is 15h, i.e. 10101000 <--> 00010101
  1116. def reflect(data,nBits):
  1117.  
  1118.     reflection = 0x00000000
  1119.     bit = 0
  1120.  
  1121.     for bit in range(nBits):
  1122.         if(data & 0x01):
  1123.             reflection |= (1 << ((nBits - 1) - bit))
  1124.         data = (data >> 1);
  1125.  
  1126.     return reflection
  1127.  
  1128.  
  1129. def CalcCRC32(array,len):
  1130.    k        = 8;            # length of unit (i.e. byte)
  1131.    MSB      = 0;
  1132.    gx       = 0x04C11DB7;   # IEEE 32bit polynomial
  1133.    regs     = 0xFFFFFFFF;   # init to all ones
  1134.    regsMask = 0xFFFFFFFF;   # ensure only 32 bit answer
  1135.  
  1136.    for i in range(len):
  1137.       DataByte = array[i]
  1138.       DataByte = reflect( DataByte, 8 );
  1139.  
  1140.       for j in range(k):
  1141.         MSB  = DataByte>>(k-1)  ## get MSB
  1142.         MSB &= 1                ## ensure just 1 bit
  1143.  
  1144.         regsMSB = (regs>>31) & 1
  1145.  
  1146.         regs = regs<<1          ## shift regs for CRC-CCITT
  1147.  
  1148.         if regsMSB ^ MSB:       ## MSB is a 1
  1149.             regs = regs ^ gx    ## XOR with generator poly
  1150.  
  1151.         regs = regs & regsMask; ## Mask off excess upper bits
  1152.  
  1153.         DataByte <<= 1          ## get to next bit
  1154.  
  1155.  
  1156.    regs          = regs & regsMask ## Mask off excess upper bits
  1157.    ReflectedRegs = reflect(regs,32) ^ 0xFFFFFFFF;
  1158.  
  1159.    return ReflectedRegs
  1160.  
  1161.  
  1162. ## ==============================================================================================
  1163. ## ==============================================================================================
  1164. ## ==============================================================================================
  1165. ## =====main()===================================================================================
  1166. ## ==============================================================================================
  1167. ## ==============================================================================================
  1168. ## ==============================================================================================
  1169.  
  1170. AvailablePartitions = {}
  1171.  
  1172. try:
  1173.     opts, args = getopt.getopt(sys.argv[1:], "r:p:d:iewns:f:t:v", ["rawprogram=", "patch=", "dest=","nopromt=", "interactive=", "erase=",  "wipe=", "search_path=","file=","location=","verbose="])
  1174. except getopt.GetoptError, err:
  1175.     # print help information and exit:
  1176.     print str(err) # will print something like "option -a not recognized"
  1177.     Usage()
  1178.     sys.exit(1)
  1179.  
  1180. check_sparse            = None
  1181. dd                      = None
  1182. xml_filename            = None
  1183. rawprogram_filename     = None
  1184. patch_filename          = None
  1185. disk_name               = None
  1186. search_paths            = []
  1187. file_list               = []
  1188. LoadSubsetOfFiles       = False
  1189. interactive             = False
  1190. erase_device            = False
  1191. wipe_device             = False
  1192. nopromt                 = False
  1193. verbose                 = False
  1194.  
  1195. Operation               = 0
  1196. OPERATION_PROGRAM       = 2
  1197. OPERATION_PATCH         = 4
  1198. OPERATION_ERASE         = 8
  1199. OPERATION_WIPE          = 16
  1200. Patching                = "FILES"
  1201. OutputFolder            = ""
  1202.  
  1203. Filename                = "singleimage.bin"
  1204. DiskSize                = 0
  1205. MinDiskSize             = 0
  1206.  
  1207. GetPartitions()
  1208. Usage()
  1209.  
  1210. for o, a in opts:
  1211.     if o in ("-r", "--rawprogram"):
  1212.         rawprogram_filename = a
  1213.         Operation |= OPERATION_PROGRAM
  1214.     elif o in ("-t", "--location"):
  1215.         OutputFolder = a
  1216.         OutputFolder = re.sub(r"\\$","",OutputFolder)    # remove final slash if it exists
  1217.         OutputFolder = re.sub(r"/$","",OutputFolder)     # remove final slash if it exists
  1218.  
  1219.         OutputFolder += "/"     # slashes will all be corrected below
  1220.  
  1221.         if sys.platform.startswith("linux"):
  1222.             OutputFolder = re.sub(r"\\","/",OutputFolder)   # correct slashes
  1223.         else:
  1224.             OutputFolder = re.sub(r"/","\\\\",OutputFolder) # correct slashes
  1225.  
  1226.         print "OutputFolder=",OutputFolder
  1227.         EnsureDirectoryExists(OutputFolder) # only need to call once
  1228.  
  1229.         Filename = OutputFolder + Filename
  1230.  
  1231.     elif o in ("-p", "--patch"):
  1232.         patch_filename = a
  1233.         Operation |= OPERATION_PATCH
  1234.     elif o in ("-d", "--dest"):
  1235.         disk_name = a
  1236.  
  1237.         # if a number was specified, it's size in sectoras and we're making a singleimage.bin
  1238.         # otherwise, a drive /dev/sdb or something was specified
  1239.  
  1240.         m = re.search("^(\d+)$", disk_name)
  1241.         if type(m) is not NoneType:
  1242.  
  1243.             ## they specified a number must be making a single image or patching files
  1244.             Patching = "FILES"
  1245.             Filename = OutputFolder + "singleimage.bin"
  1246.             DiskSize = int(int(m.group(1))*512) # comes in as sectors
  1247.  
  1248.         else:
  1249.  
  1250.             ## to be here means they didn't specify a number, thus a device
  1251.             Filename        = disk_name
  1252.             Patching        = "DISK"
  1253.             ValidDiskName   = False
  1254.  
  1255.             # User can also specify the singleimage.bin name, and I can treat that like it's the disk
  1256.  
  1257.             if sys.platform.startswith("linux"):
  1258.                 m = re.search("/dev/sd[a-z]", disk_name)
  1259.                 if type(m) is not NoneType:
  1260.                     ValidDiskName   = True
  1261.             else:
  1262.                 m = re.search("(PHYSICALDRIVE\d+)", disk_name)
  1263.                 if type(m) is not NoneType:
  1264.                     ValidDiskName   = True
  1265.                     Filename = "\\\\.\\"+m.group(1)
  1266.  
  1267.             if ValidDiskName:
  1268.                 if Filename not in Devices:
  1269.                     print "ERROR: %s does not exist" % Filename
  1270.                     Usage()
  1271.                     sys.exit()
  1272.                 DiskSize = AvailablePartitions[Filename]
  1273.             else:
  1274.                 # To be here means user did this possibly "-d singleimage.bin"
  1275.                 try:
  1276.                     DiskSize = os.path.getsize(disk_name)
  1277.                     if DiskSize < EMMCBLD_MIN_DISK_SIZE:
  1278.                         DiskSize = EMMCBLD_MIN_DISK_SIZE
  1279.                 except:
  1280.                     print "ERROR: Can't get size of %s" % Filename
  1281.                     Usage()
  1282.                     sys.exit()
  1283.  
  1284.     elif o in ("-i", "--interactive"):
  1285.         interactive = True
  1286.     elif o in ("-e", "--erase"):
  1287.         Operation = OPERATION_ERASE
  1288.         erase_device = True
  1289.     elif o in ("-n", "--nopromt"):
  1290.         nopromt = True
  1291.     elif o in ("-v", "--verbose"):
  1292.         verbose = True
  1293.     elif o in ("-w", "--wipe"):
  1294.         Operation = OPERATION_WIPE
  1295.         wipe_device = True
  1296.     elif o in ("-s", "--search_path"):
  1297.         ## also allow seperating commas
  1298.         for x in a.strip("\n").split(","):
  1299.             search_paths.append(x)
  1300.     elif o in ("-f", "--file_list"):
  1301.         ## also allow seperating files by commas, i.e. -f sbl1.mbn,slb2.mbn,etc
  1302.         LoadSubsetOfFiles = True
  1303.         for x in a.strip("\n").split(","):
  1304.             file_list.append(x)
  1305.     else:
  1306.         assert False, "unhandled option"
  1307.  
  1308. if Operation==0:
  1309.     sys.exit(1)
  1310.  
  1311.  
  1312.  
  1313. print "\nSearch Paths"
  1314. print search_paths
  1315. print "\nFiles"
  1316. print file_list
  1317.  
  1318. if (Operation & OPERATION_PROGRAM) > 0:
  1319.     if rawprogram_filename is None:
  1320.         print "Error: You must specify an \"rawprogram\" XML file for option -r"
  1321.         sys.exit(1)
  1322.     else:
  1323.         rawprogram_filename = find_file(rawprogram_filename, search_paths)
  1324.         if rawprogram_filename is None:
  1325.             print "Error: You must specify an \"rawprogram\" XML file for option -r"
  1326.             sys.exit(1)
  1327.  
  1328. if (Operation & OPERATION_PATCH) > 0:
  1329.     if patch_filename is None:
  1330.         print "Error: You must specify an \"patch\" XML file for option -p"
  1331.         sys.exit(1)
  1332.     else:
  1333.         patch_filename = find_file(patch_filename, search_paths)
  1334.         if patch_filename is None:
  1335.             print "Error: You must specify an \"patch\" XML file for option -p"
  1336.             sys.exit(1)
  1337.  
  1338. elif Operation==OPERATION_ERASE or Operation==OPERATION_WIPE:
  1339.     if disk_name is None:
  1340.         print "Error: You must specify a DISK, option -d"
  1341.         sys.exit(1)
  1342.    
  1343.        
  1344. if (Operation & OPERATION_WIPE) > 0:
  1345.     if nopromt is True:
  1346.         # means don't bug them, i.e. automation
  1347.         pass
  1348.     else:
  1349.         print "\n\nWARNING: Destructive Operation Requested"
  1350.         print "\n\nWARNING: Wiping out the MBR/GPT information means you must re-partition and format after!!"
  1351.         var = raw_input("\nAre you sure you want to ZERO OUT the MBR/GPT information for %s of %s (y|N) " % (disk_name,ReturnSizeString(AvailablePartitions[disk_name])))
  1352.         if var=='Y' or var=='y':
  1353.             pass
  1354.         else:
  1355.             sys.exit()
  1356.  
  1357.     print "\n\nZero out first 2 sectors on card"
  1358.     Zerout(disk_name,0 ,2)  ## Sector 0, wipe out 2 sectors
  1359.  
  1360.     print "\n\nZero out last sector on card"
  1361.     Zerout(disk_name,-1,1)  ## Last Sector, wipe out 1 sector
  1362.  
  1363.     print "\n'%s' no longer has partition information\n" % disk_name
  1364.     sys.exit(1)
  1365.  
  1366.  
  1367.  
  1368. if (Operation & OPERATION_PROGRAM) > 0:
  1369.  
  1370.     # Can we test for sparse images?
  1371.     check_sparse = find_file("checksparse.py", search_paths)
  1372.  
  1373.     if check_sparse is not None:
  1374.         sz = "python %s -i %s " % (check_sparse,rawprogram_filename)
  1375.         for path in search_paths:
  1376.             sz += "-s %s " % path
  1377.  
  1378.         print "\n"+"-"*78
  1379.         print "-"*78
  1380.  
  1381.         print "Checking for sparse files"
  1382.         print "-"*78
  1383.         print "-"*78
  1384.         print sz
  1385.         os.system(sz)
  1386.  
  1387.     if os.path.basename(Filename)=="singleimage.bin":
  1388.         ## Wipe out any old singleimage
  1389.         SingleImageSize = 0
  1390.         opfile = open(Filename, "wb")
  1391.         opfile.close()
  1392.  
  1393.         print "\nProgramming %s of size %s" % (Filename,ReturnSizeString(DiskSize))
  1394.  
  1395.         if nopromt is False:
  1396.             if (DiskSize/(1024.0*1024.0))>100:
  1397.                 var = raw_input("\nThis will be a LARGE singleimage.bin, it will take a long time, Do you want to continue? (Y|n)")
  1398.                 if var=='Y' or var=='y' or var=='':
  1399.                     pass
  1400.                 else:
  1401.                     sys.exit()
  1402.     else:
  1403.         if nopromt is True:
  1404.             # means don't bug them, i.e. automation
  1405.             pass
  1406.         else:
  1407.             var = raw_input("\nWARNING: Are you sure you want to write to '%s' of size %s (y|N) " % (Filename,ReturnSizeString(DiskSize)))
  1408.             if var=='Y' or var=='y':
  1409.                 pass
  1410.             else:
  1411.                 sys.exit()
  1412.  
  1413.  
  1414. NumPhyPartitions        = 0
  1415. PartitionArray          = []
  1416. PatchArray              = []
  1417. ZeroOutArray            = []
  1418. PhyPartition            = {}       # Main HASH that holds all the partition info
  1419.  
  1420. if rawprogram_filename is not None:
  1421.     ParseXML(rawprogram_filename)
  1422.  
  1423. if patch_filename is not None:
  1424.     ParseXML(patch_filename)
  1425.  
  1426. if DiskSize>0:
  1427.     if DiskSize<int(MinDiskSize):
  1428.         print "\nERROR: Current eMMC/SD card is too small to program these partitions"
  1429.         print "       Need at least %s" % ReturnSizeString(int(MinDiskSize))
  1430.         sys.exit(1)
  1431.  
  1432. if DiskSize==0:
  1433.     DiskSize = int(MinDiskSize)
  1434.     if DiskSize == 0:
  1435.         DiskSize = EMMCBLD_MIN_DISK_SIZE
  1436.     print "\nDiskSize was set to 0, DiskSize will be %s (%d sectors)" % (ReturnSizeString(DiskSize),int(DiskSize/512))
  1437.  
  1438. #print PartitionArray
  1439.  
  1440. ## rawprogram0.xml is random in terms of start_sector. It's important for
  1441. ## making the single image that we first write at sector 0, then 100, then 200 etc
  1442. ## i.e. writing 200, then going back to write 100 is more complicated, so SORT
  1443.  
  1444. ## Step 1. Sort all the start sectors where there's a file to program
  1445. PartitionStartSector = []
  1446.  
  1447. for Partition in PartitionArray:
  1448.  
  1449.     if Partition['filename']=="":
  1450.         #print "no filename for label ",Partition['label']
  1451.         continue
  1452.  
  1453.     if 'sparse' in Partition:
  1454.         m = re.search("true", Partition['sparse'],re.IGNORECASE)
  1455.         if type(m) is not NoneType:
  1456.             print """
  1457.            \nERROR: Found sparse image, can't continue\n
  1458.            You must first run \"python checksparse.py -i rawprogram0.xml -s C:\path1 -s C:\path2\"
  1459.            This will modify rawprogram0.xml to be able to handle the sparse image(s)\n
  1460.            Also, you *must* specify the various paths to the sparse images and they need to be
  1461.            opened and parsed. Then you can run msp.py again to program.
  1462.            """
  1463.             sys.exit(1)
  1464.  
  1465.     PartitionStartSector.append( Partition["start_sector"] )
  1466.  
  1467. PartitionStartSector.sort()
  1468.  
  1469. ## Step 2. Create a "PartitionSorted" based on PartitionStartSector
  1470. PartitionSorted = []
  1471. Count = 0
  1472. while 1 and (Operation & OPERATION_PROGRAM) > 0:
  1473.     for Partition in PartitionArray:
  1474.         ##print "---------------- with start_sector = %i and PartitionStartSector[%i]=%i" % (Partition["start_sector"],Count,PartitionStartSector[Count])
  1475.  
  1476.         if Partition['filename']=="":
  1477.             continue
  1478.  
  1479.         if Partition["start_sector"] == PartitionStartSector[Count]:
  1480.             ##print "FOUND, len(PartitionStartSector)=%d and len(PartitionSorted)=%d" % (len(PartitionStartSector),len(PartitionSorted))
  1481.             # To be here means I found the *next* start_sector in order, i.e. 0,100,200 etc
  1482.             PartitionSorted.append( Partition )
  1483.             Count += 1  # now go to next sorted entry
  1484.             if len(PartitionSorted) == len(PartitionStartSector):
  1485.                 break   # we're done, both arrays are the same size
  1486.  
  1487.     if len(PartitionSorted) == len(PartitionStartSector):
  1488.         break   # we're done, both arrays are the same size
  1489.  
  1490.  
  1491. #for Partition in PartitionSorted:
  1492. #    print "----------------------"
  1493. #    print Partition
  1494.  
  1495. # Possibilities,
  1496. # 1. programming DISK, then patching DISK
  1497. # 2. patching FILES, programming singleimage
  1498. # 3. programming DISK
  1499. # 4. programming singleimage
  1500. # 5. patching DISK
  1501. # 6. patching FILES
  1502.  
  1503. if (Operation & OPERATION_PROGRAM) > 0 and (Operation & OPERATION_PATCH) > 0:
  1504.     ## Have info to do both write and patch
  1505.  
  1506.     if Filename!="singleimage.bin":
  1507.         # This is a DISK and we need to zero out sectors already there
  1508.  
  1509.         print "\n\nZero out first 34 sectors on card"
  1510.         Zerout(Filename,0,34)           # First 34 sectors wipes MBR/GPT
  1511.  
  1512.         print "\n\nZero out last 33 sectors on card, DiskSize=",DiskSize
  1513.         Zerout(Filename,(DiskSize/512)-34,33) # Last 33 wipes backup GPT
  1514.  
  1515.         # User could have specified more zero out ranges
  1516.         for Zeroout in ZeroOutArray:
  1517.             print "\n======================================================================"
  1518.             print "ZERO-OUT: '%s'" % Zeroout['label']
  1519.             Zerout(Filename,Zeroout['start_sector'],int(Zeroout['num_partition_sectors']))
  1520.  
  1521.         PerformWrite()
  1522.         PerformPatching()
  1523.         DoubleCheckDiskSize()
  1524.     else:
  1525.         PerformPatching()
  1526.         PerformWrite()
  1527.         DoubleCheckDiskSize()
  1528.  
  1529. elif (Operation & OPERATION_PROGRAM) > 0:
  1530.     PerformWrite()  
  1531.     print "\n"+"-"*78
  1532.     print "If you wrote any partition table information (MBR0.bin, gpt_main0.bin, etc)"
  1533.     print " "
  1534.     print "         _             _ _      __                     _   "
  1535.     print "        | |           ( ) |    / _|                   | |  "
  1536.     print "      __| | ___  _ __ |/| |_  | |_ ___  _ __ __ _  ___| |_ "
  1537.     print "     / _` |/ _ \\| '_ \\  | __| |  _/ _ \\| '__/ _` |/ _ \\ __|"
  1538.     print "    | (_| | (_) | | | | | |_  | || (_) | | | (_| |  __/ |_ "
  1539.     print "     \\__,_|\\___/|_| |_|  \\__| |_| \\___/|_|  \\__, |\\___|\\__|"
  1540.     print "                                             __/ |         "
  1541.     print "                                            |___/          "
  1542.     print "             _                       _        _     "
  1543.     print "            | |                     | |      | |    "
  1544.     print "            | |_  ___    _ __   __ _| |_  ___| |__  "
  1545.     print "            | __|/ _ \\  | '_ \\ / _` | __|/ __| '_ \\ "
  1546.     print "            | |_| (_) | | |_) | (_| | |_| (__| | | |"
  1547.     print "             \\__|\\___/  | .__/ \\__,_|\\__|\\___|_| |_|"
  1548.     print "                        | |                         "
  1549.     print "                        |_|                         "
  1550.     print "\n"
  1551.  
  1552.     sudo=""
  1553.     if sys.platform.startswith("linux"):
  1554.         sudo="sudo "
  1555.  
  1556.     print "\tEx: %spython msp.py -p patch0.xml -d %s " % (sudo,Filename)
  1557.     print "\n\tOr, do it all in one step\n"
  1558.     print "\tEx: %spython msp.py -r rawprogram.xml -d %s -p patch0.xml" % (sudo,Filename)
  1559.     print "\n"+"-"*78
  1560.  
  1561.     DoubleCheckDiskSize()
  1562.  
  1563. elif (Operation & OPERATION_PATCH) > 0:
  1564.     PerformPatching()  
  1565.     DoubleCheckDiskSize()
  1566.        
  1567. if (Operation & OPERATION_PROGRAM) > 0:
  1568.    
  1569.     if os.path.basename(Filename)=="singleimage.bin":  
  1570.         print "\nNOTE: This program does *not* pad the last partition, therefore"
  1571.         print "      singleimage.bin might be smaller than %d sectors " % int(DiskSize/512)
  1572.  
  1573.         print "\n\nSUCCESS - %s created" % Filename
  1574.         print "SUCCESS - %s created" % Filename
  1575.         print "SUCCESS - %s created\n" % Filename
  1576.        
  1577.         if FileNotFoundShowWarning==1:
  1578.             print "\nWARNING: 1 or more files were *not* found, your singleimage.bin is *NOT* complete"
  1579.             print "\nWARNING: 1 or more files were *not* found, your singleimage.bin is *NOT* complete"
  1580.             print "\nWARNING: 1 or more files were *not* found, your singleimage.bin is *NOT* complete\n\n"
  1581.  
  1582.  
  1583.  
  1584. print "\n"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement