From c1f25d3215920a10b56813e68e124f2d835b7dd2 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Mon, 7 Oct 2024 22:07:59 -0300 Subject: [PATCH 1/6] qcom-gen-partitions-tool: add recipe based on qclinux 1.2 Recipe based on kirkstone rev 3ac146c (qclinux 1.2), needed by qcom-partition-confs, which is the recipe responsible for generating the machine partition configuration. Signed-off-by: Ricardo Salveti --- .../qcom-gen-partitions-tool/gen_partition.py | 259 ++++++++++++++++++ .../qcom-gen-partitions-tool_1.0.bb | 23 ++ 2 files changed, 282 insertions(+) create mode 100644 recipes-devtools/partition-utils/qcom-gen-partitions-tool/gen_partition.py create mode 100644 recipes-devtools/partition-utils/qcom-gen-partitions-tool_1.0.bb diff --git a/recipes-devtools/partition-utils/qcom-gen-partitions-tool/gen_partition.py b/recipes-devtools/partition-utils/qcom-gen-partitions-tool/gen_partition.py new file mode 100644 index 00000000..88a9cf77 --- /dev/null +++ b/recipes-devtools/partition-utils/qcom-gen-partitions-tool/gen_partition.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2019, The Linux Foundation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of The Linux Foundation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys +import re +import getopt +import xml.etree.ElementTree as ET +from xml.dom import minidom +from collections import OrderedDict + +def usage(): + print("\n\tUsage: %s -i -o -m [partition_name1=image_filename1,partition_name2=image_filename2,...]\n\tVersion 1.0\n" %(sys.argv[0])) + sys.exit(1) + +################################################################## +# defaults to be used +disk_params = OrderedDict({ + "type": "", + "size": "", + "SECTOR_SIZE_IN_BYTES": "512", + "WRITE_PROTECT_BOUNDARY_IN_KB": "65536", + "GROW_LAST_PARTITION_TO_FILL_DISK": "true", + "ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY": "true", + "PERFORMANCE_BOUNDARY_IN_KB": "4" +}) + +partition_entry_defaults = { + "label": "", + "size_in_kb": "", + "type": "00000000-0000-0000-0000-000000000000", + "bootable": "false", + "readonly": "true", + "filename": "", + "sparse" : "false" +} + +################################################################## +# store entries read from input file +disk_entry = None +partition_entries_dict = {} +input_file = None +output_xml = None + +def disk_options(argv): + for (opt, arg) in argv: + if opt in ['--type']: + disk_params["type"] = arg + elif opt in ['--size']: + disk_params["size"] = arg + elif opt in ['--sector-size-in-bytes']: + disk_params["SECTOR_SIZE_IN_BYTES"] = arg + elif opt in ['--write-protect-boundary']: + disk_params["WRITE_PROTECT_BOUNDARY_IN_KB"] = arg + elif opt in ['--grow-last-partition']: + disk_params["GROW_LAST_PARTITION_TO_FILL_DISK"] = "true" + elif opt in ['--align-partitions']: + disk_params["ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY"] = "true" + disk_params["PERFORMANCE_BOUNDARY_IN_KB"] = (int(arg)/1024) + +def partition_size_in_kb(size): + if not re.search('[a-zA-Z]+', size): + return int(size)/1024 + if re.search('([0-9])*(?=([Kk]([Bb])*))', size): + return int(re.search('([0-9])*(?=([Kk]([Bb])*))', size).group(0)) + if re.search('([0-9])*(?=([Mm]([Bb])*))', size): + return (int(re.search('([0-9])*(?=([Mm]([Bb])*))', size).group(0)) * 1024) + if re.search('([0-9])*(?=([Gg]([Bb])*))', size): + return (int(re.search('([0-9])*(?=([Gg]([Bb])*))', size).group(0)) * 1024 * 1024) + +def partition_options(argv): + partition_entry = partition_entry_defaults.copy() + for (opt, arg) in argv: + if opt in ['--lun']: + partition_entry["physical_partition"] = arg + elif opt in ['--name']: + partition_entry["label"] = arg + elif opt in ['--size']: + kbytes = partition_size_in_kb(arg) + partition_entry["size_in_kb"] = str(kbytes) + elif opt in ['--type-guid']: + partition_entry["type"] = arg + elif opt in ['--attributes']: + attribute_bits = int(arg,16) + if attribute_bits & (1<<2): + partition_entry["bootable"] = "true" + else: + partition_entry["bootable"] = "false" + if attribute_bits & (1<<60): + partition_entry["readonly"] = "true" + else: + partition_entry["readonly"] = "false" + elif opt in ['--filename']: + partition_entry["filename"] = arg + elif opt in ['--sparse']: + partition_entry["sparse"] = arg + return partition_entry + +def parse_partition_entry(partition_entry): + opts_list = list(partition_entry.split(' ')) + if opts_list[0] == "--partition": + try: + options, remainders = getopt.gnu_getopt(opts_list[1:], '', + ['lun=', 'name=', 'size=','type-guid=', + 'filename=', 'attributes=', 'sparse=']) + return partition_options(options) + except Exception as e: + print (str(e)) + usage() + + return None + +def parse_disk_entry(disk_entry): + opts_list = list(disk_entry.split(' ')) + if opts_list[0] == "--disk": + try: + options, remainders = getopt.gnu_getopt(opts_list[1:], '', + ['type=', 'size=','sector-size-in-bytes=', 'write-protect-boundary=', + 'grow-last-partition', 'align-partitions=']) + disk_options(options) + except Exception as e: + print (str(e)) + usage() + +def generate_ptool_xml (disk_params, partition_entries_dict, output_xml): + print("Generating ptool XML %s" %(output_xml)) + root = ET.Element("configuration") + parser_instruction_text = "" + + for key, value in disk_params.items(): + if not key == 'size' and not key == 'type': + parser_instruction_text += '\n\t' + str(key) + '=' + str(value) + '\n\t' + + parser_inst = ET.SubElement(root,"parser_instructions").text = ( + parser_instruction_text + ) + + phy_part = ET.SubElement(root, "physical_partition") + + for partition_index, entry in partition_entries_dict.items(): + part_entry = parse_partition_entry(entry) + part = ET.SubElement(phy_part, "partition", attrib=part_entry) + + xmlstr = minidom.parseString(ET.tostring(root)).toprettyxml() + with open(output_xml, "w") as f: + f.write(xmlstr) + +def generate_ufs_xml (disk_params, partition_entries_dict, output_xml): + print("Generating UFS XML %s" %(output_xml)) + root = ET.Element("configuration") + parser_instruction_text = "" + + for key, value in disk_params.items(): + if not key == 'size' and not key == 'type': + parser_instruction_text += '\n\t' + str(key) + '=' + str(value) + '\n\t' + + parser_inst = ET.SubElement(root,"parser_instructions").text = ( + parser_instruction_text + ) + lun_index=0 + while lun_index < 6: + phy_part = ET.SubElement(root, "physical_partition") + + for partition_index, entry in partition_entries_dict.items(): + part_entry = parse_partition_entry(entry) + if part_entry["physical_partition"] == str(lun_index): + del part_entry["physical_partition"] + part = ET.SubElement(phy_part, "partition", attrib=part_entry) + lun_index +=1 + + xmlstr = minidom.parseString(ET.tostring(root)).toprettyxml() + with open(output_xml, "w") as f: + f.write(xmlstr) + + +def generate_nand_mbn_gen_xml (disk_params, partition_entry): + print("Generating nand_mbn_gen XML") + +def generate_partition_xml (disk_entry, partition_entries_dict, output_xml): + parse_disk_entry(disk_entry) + if disk_params["type"] == "emmc": + generate_ptool_xml(disk_params, partition_entries_dict, output_xml) + elif disk_params["type"] == "nand": + generate_nand_mbn_gen_xml(disk_params, partition_entries_dict, output_xml) + elif disk_params["type"] == "ufs": + generate_ufs_xml(disk_params, partition_entries_dict, output_xml) + +############################################################################### +# main +disk_entry_err_msg = "contains more than one --disk entries" + +if len(sys.argv) < 3: + usage() + +try: + if sys.argv[1] == "-h" or sys.argv[1] == "--help": + usage() + try: + opts, rem = getopt.getopt(sys.argv[1:], "i:o:m:") + for (opt, arg) in opts: + if opt in ["-i"]: + input_file=arg + elif opt in ["-o"]: + output_xml=arg + except Exception as argerr: + print (str(argerr)) + usage() + f = open(input_file) + line = f.readline() + partition_index = 0 + while line: + if not re.search("^\s*#", line) and not re.search("^\s*$", line): + line = line.strip() + if re.search("^--disk", line): + if disk_entry == None: + disk_entry = line + else: + print("%s %s" %(sys.argv[1], disk_entry_err_msg)) + print("%s\n%s" %(disk_entry, line)) + sys.exit(1) + elif re.search("^--partition", line): + partition_entries_dict[partition_index] = line + partition_index += 1 + else: + print("Ignoring %s" %(line)) + line = f.readline() + f.close() +except Exception as e: + print("Error: ", e) + sys.exit(1) + +generate_partition_xml(disk_entry, partition_entries_dict, output_xml) + +sys.exit(0) diff --git a/recipes-devtools/partition-utils/qcom-gen-partitions-tool_1.0.bb b/recipes-devtools/partition-utils/qcom-gen-partitions-tool_1.0.bb new file mode 100644 index 00000000..807e82a5 --- /dev/null +++ b/recipes-devtools/partition-utils/qcom-gen-partitions-tool_1.0.bb @@ -0,0 +1,23 @@ +SUMMARY = "ptool compliant partition generation utility" +DESCRIPTION = "Generates partition.xml in ptool suitable format" +SECTION = "devel" +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/${LICENSE};md5=550794465ba0ec5312d6919e203a55f9" + +RDEPENDS:${PN} += "python3-xml" + +SRC_URI = "file://gen_partition.py" + +S = "${WORKDIR}/sources" +UNPACKDIR = "${S}" + +INHIBIT_DEFAULT_DEPS = "1" + +do_configure[noexec] = "1" +do_compile[noexec] = "1" + +do_install() { + install -m 755 -D ${S}/gen_partition.py ${D}${bindir}/gen_partition.py +} + +BBCLASSEXTEND = "native nativesdk" From 9930740425aab664efd7464e89387fe725c7bf91 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Tue, 12 Nov 2024 20:55:07 -0300 Subject: [PATCH 2/6] qcom-ptool: add recipe based on qclinux 1.2 Recipe based on kirkstone rev 3ac146c (qclinux 1.2), used to generate the machine specific partition binary files out of partition.xml. Patches also from qclinux 1.2, which should ideally just be proposed upstream instead, but discussion pending if the target repository should indeed be used as upstream. Signed-off-by: Ricardo Salveti --- ...e-zero-files-in-output-folder-when-s.patch | 31 + .../0002-ptool.py-Python-3-support.patch | 2286 +++++++++++++++++ .../partition-utils/qcom-ptool_git.bb | 32 + 3 files changed, 2349 insertions(+) create mode 100644 recipes-devtools/partition-utils/qcom-ptool/0001-ptool.py-Generate-zero-files-in-output-folder-when-s.patch create mode 100644 recipes-devtools/partition-utils/qcom-ptool/0002-ptool.py-Python-3-support.patch create mode 100644 recipes-devtools/partition-utils/qcom-ptool_git.bb diff --git a/recipes-devtools/partition-utils/qcom-ptool/0001-ptool.py-Generate-zero-files-in-output-folder-when-s.patch b/recipes-devtools/partition-utils/qcom-ptool/0001-ptool.py-Generate-zero-files-in-output-folder-when-s.patch new file mode 100644 index 00000000..014dfb18 --- /dev/null +++ b/recipes-devtools/partition-utils/qcom-ptool/0001-ptool.py-Generate-zero-files-in-output-folder-when-s.patch @@ -0,0 +1,31 @@ +From cf7d7ce38b8884ee4e2567ab047f90a96f2fb54b Mon Sep 17 00:00:00 2001 +From: Divya Theja +Date: Mon, 11 Nov 2019 19:37:36 +0530 +Subject: [PATCH] ptool.py: Generate zero files in output folder when + specified. + +The patch allows ptool to generate zerosector files in output directory +when such directory path is specified as argument to -t option. + +Upstream-Status: Pending +--- + ptool.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ptool.py b/ptool.py +index 031ad74..66c95c5 100644 +--- a/ptool.py ++++ b/ptool.py +@@ -362,7 +362,8 @@ def ShowBackupGPT(sector): + print " " + + def CreateFileOfZeros(filename,num_sectors): +- ++ if OutputFolder: ++ filename = os.path.join(OutputFolder, filename) + try: + opfile = open(filename, "w+b") + except Exception, x: +-- +1.9.1 + diff --git a/recipes-devtools/partition-utils/qcom-ptool/0002-ptool.py-Python-3-support.patch b/recipes-devtools/partition-utils/qcom-ptool/0002-ptool.py-Python-3-support.patch new file mode 100644 index 00000000..ec75cd6f --- /dev/null +++ b/recipes-devtools/partition-utils/qcom-ptool/0002-ptool.py-Python-3-support.patch @@ -0,0 +1,2286 @@ +From 8cb694be1972d19ed591ebe37495d4edbf9dbe11 Mon Sep 17 00:00:00 2001 +From: Viswanath Kraleti +Date: Fri, 28 Aug 2020 11:52:21 +0530 +Subject: [PATCH] ptool.py: Python 3 support + +Upstream-Status: Pending + +Signed-off-by: Viswanath Kraleti +Signed-off-by: Ricardo Salveti +--- + ptool.py | 1050 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 525 insertions(+), 525 deletions(-) + +diff --git a/ptool.py b/ptool.py +index 66c95c5..ba62caa 100644 +--- a/ptool.py ++++ b/ptool.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/python ++#!/usr/bin/env python3 + #=========================================================================== + #Copyright (c) 2019, The Linux Foundation. All rights reserved. + +@@ -35,9 +35,9 @@ import struct + from types import * + from time import sleep + +-if sys.version_info < (2,5): ++if sys.version_info < (2,5): + sys.stdout.write("\n\nERROR: This script needs Python version 2.5 or greater, detected as ") +- print sys.version_info ++ print(sys.version_info) + sys.exit() # error + + from xml.etree import ElementTree as ET +@@ -94,20 +94,21 @@ EBR = [0]*SECTOR_SIZE_IN_BYTES + + hash_w = [{'start_sector':0,'num_sectors':(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES), + 'end_sector':(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)-1,'physical_partition_number':0,'boundary_num':0,'num_boundaries_covered':1}] ++gen_patch = True + NumWPregions = 0 + + def ShowPartitionExample(): +- print "Your \"partition.xml\" file needs to look like something like this below" +- print "\t(i.e. notice the *multiple* physical_partition tags)\n" +- print "" +- print "" +- print " " +- print "" +- print " " +- print "" +- print "" +- print " " +- print "" ++ print("Your \"partition.xml\" file needs to look like something like this below") ++ print("\t(i.e. notice the *multiple* physical_partition tags)\n") ++ print("") ++ print("") ++ print(" ") ++ print("") ++ print(" ") ++ print("") ++ print("") ++ print(" ") ++ print("") + + def ConvertKBtoSectors(x): + ## 1KB / SECTOR_SIZE_IN_BYTES normally means return 2 (i.e. with SECTOR_SIZE_IN_BYTES=512) +@@ -116,12 +117,11 @@ def ConvertKBtoSectors(x): + + def UpdatePatch(StartSector,ByteOffset,PHYPartition,size_in_bytes,szvalue,szfilename,szwhat): + global PatchesXML +- + SubElement(PatchesXML, 'patch', {'start_sector':StartSector, 'byte_offset':ByteOffset, + 'physical_partition_number':str(PHYPartition), 'size_in_bytes':str(size_in_bytes), + 'value':szvalue, 'filename':szfilename, 'SECTOR_SIZE_IN_BYTES':str(SECTOR_SIZE_IN_BYTES), 'what':szwhat }) + +- ++ + def UpdateRawProgram(RawProgramXML, StartSector, size_in_KB, PHYPartition, file_sector_offset, num_partition_sectors, filename, sparse, label,readbackverify='false', partofsingleimage='false'): + if StartSector<0: + szStartSector = "NUM_DISK_SECTORS%d." % StartSector ## as in NUM_DISK_SECTORS-33 since %d=-33 +@@ -131,8 +131,8 @@ def UpdateRawProgram(RawProgramXML, StartSector, size_in_KB, PHYPartition, file_ + #print "UpdateRawProgram StartSector=",StartSector + #print "StartSector=",type(StartSector) + #print "-----------------------------------------" +- +- szStartByte = str(hex(StartSector*SECTOR_SIZE_IN_BYTES)) ++ ++ szStartByte = str(hex(int(StartSector)*SECTOR_SIZE_IN_BYTES)) + szStartSector = str(StartSector) + + #import pdb; pdb.set_trace() +@@ -146,14 +146,14 @@ def UpdateRawProgram(RawProgramXML, StartSector, size_in_KB, PHYPartition, file_ + + if erasefirst: + if label!="cdt": +- SubElement(RawProgramXML, 'erase', {'start_sector':szStartSector, 'physical_partition_number':str(PHYPartition), +- 'num_partition_sectors':str(num_partition_sectors), 'filename':filename, ++ SubElement(RawProgramXML, 'erase', {'start_sector':szStartSector, 'physical_partition_number':str(PHYPartition), ++ 'num_partition_sectors':str(num_partition_sectors), 'filename':filename, + 'SECTOR_SIZE_IN_BYTES':str(SECTOR_SIZE_IN_BYTES) }) + + + SubElement(RawProgramXML, 'program', {'start_sector':szStartSector, 'size_in_KB':str(size_in_KB), 'physical_partition_number':str(PHYPartition), 'partofsingleimage':partofsingleimage, + 'file_sector_offset':str(file_sector_offset), 'num_partition_sectors':str(num_partition_sectors), 'readbackverify':readbackverify, +- 'filename':filename, 'sparse':sparse, 'start_byte_hex':szStartByte, 'SECTOR_SIZE_IN_BYTES':str(SECTOR_SIZE_IN_BYTES), 'label':label }) ++ 'filename':filename, 'sparse':sparse, 'start_byte_hex':szStartByte, 'SECTOR_SIZE_IN_BYTES':str(SECTOR_SIZE_IN_BYTES), 'label':label }) + + + #iter = RawProgramXML.getiterator() +@@ -168,37 +168,37 @@ def UpdateRawProgram(RawProgramXML, StartSector, size_in_KB, PHYPartition, file_ + + #import pdb; pdb.set_trace() + +- +- ++ ++ + def PrintBigWarning(sz): +- print "\t _ " +- print "\t (_) " +- print "\t__ ____ _ _ __ _ __ _ _ __ __ _ " +- print "\t\\ \\ /\\ / / _` | '__| '_ \\| | '_ \\ / _` |" +- print "\t \\ V V / (_| | | | | | | | | | | (_| |" +- print "\t \\_/\\_/ \\__,_|_| |_| |_|_|_| |_|\\__, |" +- print "\t __/ |" +- print "\t |___/ \n" ++ print("\t _ ") ++ print("\t (_) ") ++ print("\t__ ____ _ _ __ _ __ _ _ __ __ _ ") ++ print("\t\\ \\ /\\ / / _` | '__| '_ \\| | '_ \\ / _` |") ++ print("\t \\ V V / (_| | | | | | | | | | | (_| |") ++ print("\t \\_/\\_/ \\__,_|_| |_| |_|_|_| |_|\\__, |") ++ print("\t __/ |") ++ print("\t |___/ \n") + + if len(sz)>0: +- print sz ++ print(sz) + + def ValidGUIDForm(GUID): + + if type(GUID) is not str: + GUID = str(GUID) + +- print "Testing if GUID=",GUID ++ print("Testing if GUID=",GUID) + + m = re.search("0x([a-fA-F\d]{32})$", GUID) #0xC79926B7B668C0874433B9E5EBD0A0A2 +- if type(m) is not NoneType: ++ if m is not None: + return True + +- m = re.search("([a-fA-F\d]{8})-([a-fA-F\d]{4})-([a-fA-F\d]{4})-([a-fA-F\d]{2})([a-fA-F\d]{2})-([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})", GUID) +- if type(m) is not NoneType: ++ m = re.search("([a-fA-F\d]{8})-([a-fA-F\d]{4})-([a-fA-F\d]{4})-([a-fA-F\d]{2})([a-fA-F\d]{2})-([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})", GUID) ++ if m is not None: + return True + +- print "GUID does not match regular expression" ++ print("GUID does not match regular expression") + + return False + +@@ -213,8 +213,8 @@ def ValidateTYPE(Type): + Type = str(Type) + + m = re.search("^(0x)?([a-fA-F\d][a-fA-F\d]?)$", Type) +- if type(m) is NoneType: +- print "\tWARNING: Type \"%s\" is not in the form 0x4C" % Type ++ if m is None: ++ print("\tWARNING: Type \"%s\" is not in the form 0x4C" % Type) + sys.exit(1) + else: + #print m.group(2) +@@ -227,43 +227,43 @@ def ValidateGUID(GUID): + if type(GUID) is not str: + GUID = str(GUID) + +- print "Looking to validate GUID=",GUID ++ print("Looking to validate GUID=",GUID) + + m = re.search("0x([a-fA-F\d]{32})$", GUID) #0xC79926B7B668C0874433B9E5EBD0A0A2 +- if type(m) is not NoneType: ++ if m is not None: + tempGUID = int(m.group(1),16) +- print "\tGUID \"%s\"" % GUID ++ print("\tGUID \"%s\"" % GUID) + + if tempGUID == PARTITION_SYSTEM_GUID: +- print "\tPARTITION_SYSTEM_GUID detected\n" ++ print("\tPARTITION_SYSTEM_GUID detected\n") + elif tempGUID == PARTITION_MSFT_RESERVED_GUID: +- print "\tPARTITION_MSFT_RESERVED_GUID detected\n" ++ print("\tPARTITION_MSFT_RESERVED_GUID detected\n") + elif tempGUID == PARTITION_BASIC_DATA_GUID: +- print "\tPARTITION_BASIC_DATA_GUID detected\n" ++ print("\tPARTITION_BASIC_DATA_GUID detected\n") + else: +- print "\tUNKNOWN PARTITION_GUID detected\n" ++ print("\tUNKNOWN PARTITION_GUID detected\n") + + return tempGUID +- ++ + else: + #ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 --> #0x C7 99 26 B7 B6 68 C087 4433 B9E5 EBD0A0A2 +- m = re.search("([a-fA-F\d]{8})-([a-fA-F\d]{4})-([a-fA-F\d]{4})-([a-fA-F\d]{2})([a-fA-F\d]{2})-([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})", GUID) +- if type(m) is not NoneType: +- print "Found more advanced type" ++ m = re.search("([a-fA-F\d]{8})-([a-fA-F\d]{4})-([a-fA-F\d]{4})-([a-fA-F\d]{2})([a-fA-F\d]{2})-([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})", GUID) ++ if m is not None: ++ print("Found more advanced type") + tempGUID = (int(m.group(4),16)<<64) | (int(m.group(3),16)<<48) | (int(m.group(2),16)<<32) | int(m.group(1),16) + tempGUID|= (int(m.group(8),16)<<96) | (int(m.group(7),16)<<88) | (int(m.group(6),16)<<80) | (int(m.group(5),16)<<72) + tempGUID|= (int(m.group(11),16)<<120)| (int(m.group(10),16)<<112)| (int(m.group(9),16)<<104) +- print "** CONVERTED GUID \"%s\" is FOUND --> 0x%X" % (GUID,tempGUID) ++ print("** CONVERTED GUID \"%s\" is FOUND --> 0x%X" % (GUID,tempGUID)) + return tempGUID + else: +- print "\nWARNING: "+"-"*78 +- print "*"*78 +- print "WARNING: GUID \"%s\" is not in the form ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" % GUID +- print "*"*78 +- print "WARNING"+"-"*78+"\n" +- print "Converted to PARTITION_BASIC_DATA_GUID (0xC79926B7B668C0874433B9E5EBD0A0A2)\n" +- return PARTITION_BASIC_DATA_GUID +- ++ print("\nWARNING: "+"-"*78) ++ print("*"*78) ++ print("WARNING: GUID \"%s\" is not in the form ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" % GUID) ++ print("*"*78) ++ print("WARNING"+"-"*78+"\n") ++ print("Converted to PARTITION_BASIC_DATA_GUID (0xC79926B7B668C0874433B9E5EBD0A0A2)\n") ++ return PARTITION_BASIC_DATA_GUID ++ + def EnsureDirectoryExists(filename): + dir = os.path.dirname(filename) + +@@ -278,20 +278,20 @@ def WriteGPT(GPTMAIN, GPTBACKUP, GPTEMPTY): + # opfile.write(struct.pack("B", b)) + #for b in BackupGPT: + # opfile.write(struct.pack("B", b)) +- ++ + ofile = open(GPTMAIN, "wb") + for b in PrimaryGPT: + ofile.write(struct.pack("B", b)) + ofile.close() + +- print "\nCreated \"%s\"\t\t\t<-- Primary GPT partition tables + protective MBR" % GPTMAIN ++ print("\nCreated \"%s\"\t\t\t<-- Primary GPT partition tables + protective MBR" % GPTMAIN) + + ofile = open(GPTBACKUP, "wb") + for b in BackupGPT: + ofile.write(struct.pack("B", b)) + ofile.close() + +- print "Created \"%s\"\t\t<-- Backup GPT partition tables" % GPTBACKUP ++ print("Created \"%s\"\t\t<-- Backup GPT partition tables" % GPTBACKUP) + + ofile = open(GPTBOTH, "wb") + for b in PrimaryGPT: +@@ -300,7 +300,7 @@ def WriteGPT(GPTMAIN, GPTBACKUP, GPTEMPTY): + ofile.write(struct.pack("B", b)) + ofile.close() + +- print "Created \"%s\" \t\t<-- you can run 'perl parseGPT.pl %s'" % (GPTBOTH,GPTBOTH) ++ print("Created \"%s\" \t\t<-- you can run 'perl parseGPT.pl %s'" % (GPTBOTH,GPTBOTH)) + + ## EmptyGPT is just all 0's, let's fill in the correct data + FillInEmptyGPT() +@@ -310,7 +310,7 @@ def WriteGPT(GPTMAIN, GPTBACKUP, GPTEMPTY): + ofile.write(struct.pack("B", b)) + ofile.close() + +- print "Created \"%s\"\t\t<-- Empty GPT partition table, use to force EDL mode (very useful)" % GPTEMPTY ++ print("Created \"%s\"\t\t<-- Empty GPT partition table, use to force EDL mode (very useful)" % GPTEMPTY) + + def FillInEmptyGPT(): + global EmptyGPT +@@ -338,57 +338,58 @@ def FillInEmptyGPT(): + i+=16 + EmptyGPT[i:i+9] = [0x65, 0x00, 0x6D, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79] # unicode "empty" partition name + +- ++ + + def UpdatePrimaryGPT(value,length,i): + global PrimaryGPT + for b in range(length): +- PrimaryGPT[i] = ((value>>(b*8)) & 0xFF) ; i+=1 ++ PrimaryGPT[i] = ((int(value)>>(b*8)) & 0xFF) ; i+=1 + return i + + def UpdateBackupGPT(value,length,i): + global BackupGPT + for b in range(length): +- BackupGPT[i] = ((value>>(b*8)) & 0xFF) ; i+=1 ++ BackupGPT[i] = ((int(value)>>(b*8)) & 0xFF) ; i+=1 + return i + + def ShowBackupGPT(sector): + global BackupGPT +- print "Sector: %d" % sector ++ print("Sector: %d" % sector) + for j in range(32): + for i in range(16): + sys.stdout.write("%.2X " % BackupGPT[i+j*16+sector*SECTOR_SIZE_IN_BYTES]) +- print " " +- print " " ++ print(" ") ++ print(" ") + +-def CreateFileOfZeros(filename,num_sectors): ++def CreateFileOfZeros(filename,num_total_sectors): + if OutputFolder: + filename = os.path.join(OutputFolder, filename) + try: + opfile = open(filename, "w+b") +- except Exception, x: +- print "ERROR: Could not create '%s', cwd=%s" % (filename,os.getcwd() ) +- print "REASON: %s" % (x) ++ except Exception as x: ++ print("ERROR: Could not create '%s', cwd=%s" % (filename,os.getcwd() )) ++ print("REASON: %s" % (x)) + sys.exit(1) +- ++ ++ num_sectors = int(num_total_sectors) + temp = [0]*(SECTOR_SIZE_IN_BYTES*num_sectors) + zeros = struct.pack("%iB"%(SECTOR_SIZE_IN_BYTES*num_sectors),*temp) + try: + opfile.write(zeros) +- except Exception, x: +- print "ERROR: Could not write zeros to '%s'\nREASON: %s" % (filename,x) ++ except Exception as x: ++ print("ERROR: Could not write zeros to '%s'\nREASON: %s" % (filename,x)) + sys.exit(1) +- ++ + try: + opfile.close() +- except Exception, x: +- print "\tWARNING: Could not close %s" % filename +- print "REASON: %s" % (x) ++ except Exception as x: ++ print("\tWARNING: Could not close %s" % filename) ++ print("REASON: %s" % (x)) + +- print "Created \"%s\"\t\t<-- full of binary zeros - used by \"wipe\" rawprogram files" % filename +- +-def CreateErasingRawProgramFiles(): ++ print("Created \"%s\"\t\t<-- full of binary zeros - used by \"wipe\" rawprogram files" % filename) + ++def CreateErasingRawProgramFiles(): ++ global gen_patch + CreateFileOfZeros("zeros_1sector.bin",1) + CreateFileOfZeros("zeros_%dsectors.bin" % BackupGPTNumLBAs,BackupGPTNumLBAs) + +@@ -402,23 +403,27 @@ def CreateErasingRawProgramFiles(): + + UpdateRawProgram(temp,0, 0.5, i, 0, 1, "zeros_33sectors.bin", "false", "Overwrite MBR sector") + UpdateRawProgram(temp,1, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, i, 0, BackupGPTNumLBAs, "zeros_%dsectors.bin" % BackupGPTNumLBAs, "false", "Overwrite Primary GPT Sectors") +- UpdateRawProgram(temp,-BackupGPTNumLBAs, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, i, 0, BackupGPTNumLBAs, "zeros_%dsectors.bin" % BackupGPTNumLBAs, "false", "Overwrite Backup GPT Sectors") ++ ++ backup_gpt_lba = -BackupGPTNumLBAs ++ if gen_patch == True: ++ UpdateRawProgram(temp,backup_gpt_lba, BackupGPTNumLBAs*SECTOR_SIZE_IN_BYTES/1024.0, i, 0, BackupGPTNumLBAs, "zeros_%dsectors.bin" % BackupGPTNumLBAs, "false", "Overwrite Backup GPT Sectors") + + RAW_PROGRAM = '%swipe_rawprogram_PHY%d.xml' % (OutputFolder,i) + + opfile = open(RAW_PROGRAM, "w") + opfile.write( prettify(temp) ) + opfile.close() +- print "Created \"%s\"\t<-- Used to *wipe/erase* partition information" % RAW_PROGRAM ++ print("Created \"%s\"\t<-- Used to *wipe/erase* partition information" % RAW_PROGRAM) ++ + +- + NumPartitions = 0 + SizeOfPartitionArray= 0 + + def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + global opfile,PhyPartition,PrimaryGPT,BackupGPT,EmptyGPT,RawProgramXML, GPTMAIN, GPTBACKUP, GPTBOTH, RAW_PROGRAM, PATCHES, PrimaryGPTNumLBAs, BackupGPTNumLBAs ++ global gen_patch + +- print "\n\nMaking GUID Partitioning Table (GPT)" ++ print("\n\nMaking GUID Partitioning Table (GPT)") + + #PrintBanner("instructions") + +@@ -460,8 +465,8 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + ## Step 2. Move through xml definition and figure out partitions sizes + ## --------------------------------------------------------------------------------- + +- PrimaryGPTNumLBAs=len(PrimaryGPT)/SECTOR_SIZE_IN_BYTES +- BackupGPTNumLBAs =len(BackupGPT)/SECTOR_SIZE_IN_BYTES ++ PrimaryGPTNumLBAs=int(len(PrimaryGPT)/SECTOR_SIZE_IN_BYTES) ++ BackupGPTNumLBAs =int(len(BackupGPT)/SECTOR_SIZE_IN_BYTES) + i = 2*SECTOR_SIZE_IN_BYTES ## partition arrays begin here + FirstLBA = PrimaryGPTNumLBAs + LastLBA = FirstLBA ## Make these equal at first +@@ -470,34 +475,30 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + UpdateWPhash(FirstLBA, 0) # make sure 1st write protect boundary is setup correctly + + #print "len(PhyPartition)=%d and k=%d" % (len(PhyPartition),k) +- ++ + if(k>=len(PhyPartition)): + if UserProvided==True: +- print "\nERROR: PHY Partition %i of %i not found" % (k,len(PhyPartition)) +- print "\nERROR: PHY Partition %i of %i not found\n\n" % (k,len(PhyPartition)) ++ print("\nERROR: PHY Partition %i of %i not found" % (k,len(PhyPartition))) ++ print("\nERROR: PHY Partition %i of %i not found\n\n" % (k,len(PhyPartition))) + ShowPartitionExample() + sys.exit() + else: +- print "\nERROR: PHY Partition %i of %i not found\n\n" % (k,len(PhyPartition)) ++ print("\nERROR: PHY Partition %i of %i not found\n\n" % (k,len(PhyPartition))) + return ## Automatically trying to do 0 to 7, and some don't exist, which is to be expected + + SectorsTillNextBoundary = 0 + + +- print "\n\nOn PHY Partition %d that has %d partitions" % (k,len(PhyPartition[k])) ++ print("\n\nOn PHY Partition %d that has %d partitions" % (k,len(PhyPartition[k]))) + for j in range(len(PhyPartition[k])): + #print "\nPartition name='%s' (readonly=%s)" % (PhyPartition[k][j]['label'], PhyPartition[k][j]['readonly']) + #print "\tat sector location %d (%d KB or %.2f MB) and LastLBA=%d" % (FirstLBA,FirstLBA/2,FirstLBA/2048,LastLBA) + #print "%d of %d with label %s" %(j,len(PhyPartition[k]),PhyPartition[k][j]['label']) + +- print "\n"+"="*78 +- print " _ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-._ (\"-." +- print " ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )" +- print " (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\" (_,-\"" +- print "="*78 +- ++ print("\n"+"="*78) ++ + PhyPartition[k][j]['size_in_kb'] = int(PhyPartition[k][j]['size_in_kb']) +- print "\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%dMB) (%i sectors with %i bytes/sector)" %(j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'],PhyPartition[k][j]['readonly'],PhyPartition[k][j]['size_in_kb'],PhyPartition[k][j]['size_in_kb']/1024,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),SECTOR_SIZE_IN_BYTES) ++ print("\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%dMB) (%i sectors with %i bytes/sector)" %(j+1, len(PhyPartition[k]), PhyPartition[k][j]['label'], PhyPartition[k][j]['readonly'], PhyPartition[k][j]['size_in_kb'], PhyPartition[k][j]['size_in_kb']/1024, ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']), SECTOR_SIZE_IN_BYTES)) + + if (PhyPartition[k][j]['size_in_kb']*1024)%SECTOR_SIZE_IN_BYTES>0: + ## Have a remainder, need to round up to next full sector +@@ -506,108 +507,109 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + PhyPartition[k][j]['size_in_kb'] = (TempResult * SECTOR_SIZE_IN_BYTES)/1024 + + ##import pdb; pdb.set_trace() ## verifying sizes +- +- if HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']>0 and HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is False: +- PrintBigWarning("WARNING: HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] is %i KB\n\tbut HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is FALSE!!\n\n" % HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']) +- PrintBigWarning("WARNING: This means partitions will *NOT* be aligned to a HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] of %i KB !!\n\n" % HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']) +- print "To correct this, partition.xml should look like this\n" +- print "\t" +- print "\t\tPERFORMANCE_BOUNDARY_IN_KB = %i" % Partition['PERFORMANCE_BOUNDARY_IN_KB'] +- print "\t\tALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY=true" +- print "\t\n\n" +- +- if HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is True: +- ## to be here means this partition *must* be on an ALIGN boundary +- print "\tAlignment is to %iKB" % PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'] +- SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']) ## hi +- if SectorsTillNextBoundary>0: +- print "\tSectorsTillNextBoundary=%d, FirstLBA=%d it needs to be moved to be aligned to %d" % (SectorsTillNextBoundary,FirstLBA,FirstLBA + SectorsTillNextBoundary) +- ##print "\tPhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']=",PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'] +- FirstLBA += SectorsTillNextBoundary +- else: +- if PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']>0: +- print "\tThis partition is *NOT* aligned to a performance boundary\n" +- ++ ++ if HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']>0 and HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is False: ++ PrintBigWarning("WARNING: HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] is %i KB\n\tbut HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is FALSE!!\n\n" % HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']) ++ PrintBigWarning("WARNING: This means partitions will *NOT* be aligned to a HashInstructions['PERFORMANCE_BOUNDARY_IN_KB'] of %i KB !!\n\n" % HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']) ++ print("To correct this, partition.xml should look like this\n") ++ print("\t") ++ print("\t\tPERFORMANCE_BOUNDARY_IN_KB = %i" % Partition['PERFORMANCE_BOUNDARY_IN_KB']) ++ print("\t\tALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY=true") ++ print("\t\n\n") ++ ++ if HashInstructions['ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY'] is True: ++ ## to be here means this partition *must* be on an ALIGN boundary ++ print("\tAlignment is to %iKB" % PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']) ++ SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']) ## hi ++ if SectorsTillNextBoundary>0: ++ print("\tSectorsTillNextBoundary=%d, FirstLBA=%d it needs to be moved to be aligned to %d" % (SectorsTillNextBoundary,FirstLBA,FirstLBA + SectorsTillNextBoundary)) ++ ##print "\tPhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']=",PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'] ++ FirstLBA += SectorsTillNextBoundary ++ else: ++ if PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']>0: ++ print("\tThis partition is *NOT* aligned to a performance boundary\n") ++ + if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0: + SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']) + + if PhyPartition[k][j]['readonly']=="true": + ## to be here means this partition is read-only, so see if we need to move the start + if FirstLBA <= hash_w[NumWPregions]["end_sector"]: +- print "\tWe *don't* need to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"]) ++ print("\tWe *don't* need to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])) + pass + else: +- print "\tFirstLBA (%d) is *not* covered by the end of the WP region (%d),\n\tit needs to be moved to be aligned to %d" % (FirstLBA,hash_w[NumWPregions]["end_sector"],FirstLBA + SectorsTillNextBoundary) ++ print("\tFirstLBA (%d) is *not* covered by the end of the WP region (%d),\n\tit needs to be moved to be aligned to %d" % (FirstLBA,hash_w[NumWPregions]["end_sector"],FirstLBA + SectorsTillNextBoundary)) + FirstLBA += SectorsTillNextBoundary + + else: +- print "\n\tThis partition is *NOT* readonly" ++ print("\n\tThis partition is *NOT* readonly") + ## to be here means this partition is writeable, so see if we need to move the start + if FirstLBA <= hash_w[NumWPregions]["end_sector"]: +- print "\tWe *need* to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"]) +- print "\nhash_w[NumWPregions]['end_sector']=%i" % hash_w[NumWPregions]["end_sector"]; +- print "FirstLBA=%i\n" %FirstLBA; ++ print("\tWe *need* to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])) ++ print("\nhash_w[NumWPregions]['end_sector']=%i" % hash_w[NumWPregions]["end_sector"]); ++ print("FirstLBA=%i\n" %FirstLBA); + FirstLBA += SectorsTillNextBoundary + +- print "\tFirstLBA is now %d" % (FirstLBA) ++ print("\tFirstLBA is now %d" % (FirstLBA)) + else: + #print "Great, We *don't* need to move FirstLBA (%d) since it's *not* covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"]) + pass + + if (j+1) == len(PhyPartition[k]): +- print "\nTHIS IS THE *LAST* PARTITION" ++ print("\nTHIS IS THE *LAST* PARTITION") + +- if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True: ++ if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] == True and gen_patch == True: ++ ++ print("\nMeans patching instructions go here") + +- print "\nMeans patching instructions go here" +- + PhyPartition[k][j]['size_in_kb'] = 0 # infinite huge +- print "PhyPartition[k][j]['size_in_kb'] set to 0" ++ print("PhyPartition[k][j]['size_in_kb'] set to 0") + SectorsRemaining = BackupGPTNumLBAs + +- print "LastLBA=",LastLBA +- print "FirstLBA=",FirstLBA ++ print("LastLBA=",LastLBA) ++ print("FirstLBA=",FirstLBA) + + # gpt patch - size of last partition ################################################ + #StartSector = 2*512+40+j*128 ## i.e. skip sector 0 and 1, then it's offset + #ByteOffset = str(StartSector%512) + #StartSector = str(int(StartSector / 512)) +- ++ + StartSector = 40+j*128 ## i.e. skip sector 0 and 1, then it's offset + ByteOffset = str(StartSector%SECTOR_SIZE_IN_BYTES) + StartSector = str(2+int(StartSector / SECTOR_SIZE_IN_BYTES)) +- ++ + BackupStartSector = 40+j*128 + ByteOffset = str(BackupStartSector%SECTOR_SIZE_IN_BYTES) + BackupStartSector = int(BackupStartSector / SECTOR_SIZE_IN_BYTES) +- ++ + ## gpt patch - main gpt partition array + UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTMAIN),"Update last partition %d '%s' with actual size in Primary Header." % ((j+1),PhyPartition[k][j]['label'])) + UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update last partition %d '%s' with actual size in Primary Header." % ((j+1),PhyPartition[k][j]['label'])) + +- + ## gpt patch - backup gpt partition array + UpdatePatch(str(BackupStartSector), ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTBACKUP),"Update last partition %d '%s' with actual size in Backup Header." % ((j+1),PhyPartition[k][j]['label'])) + UpdatePatch("NUM_DISK_SECTORS-%d." % (BackupGPTNumLBAs-BackupStartSector),ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update last partition %d '%s' with actual size in Backup Header." % ((j+1),PhyPartition[k][j]['label'])) +- ++ elif HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] == True and gen_patch == False: ++ print("Ignoring GROW_LAST_PARTITION_TO_FILL_DISK because patching was disabled") ++ + LastLBA = FirstLBA + ConvertKBtoSectors( PhyPartition[k][j]['size_in_kb'] ) ## increase by num sectors, LastLBA inclusive, so add 1 for size + LastLBA -= 1 # inclusive, meaning 0 to 3 is 4 sectors + + #import pdb; pdb.set_trace() + +- print "\n\tAt sector location %d with size %.2f MB (%d sectors) and LastLBA=%d (0x%X)" % (FirstLBA,PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),LastLBA,LastLBA) +- ++ print("\n\tAt sector location %d with size %.2f MB (%d sectors) and LastLBA=%d (0x%X)" % (FirstLBA,PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),LastLBA,int(LastLBA))) ++ + if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0: + AlignedRemainder = FirstLBA % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']; + if AlignedRemainder==0: +- print "\tWPB: This partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']))) ++ print("\tWPB: This partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])))) + + if PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']>0: + AlignedRemainder = FirstLBA % PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']; + if AlignedRemainder==0: +- print "\t"+"-"*78 +- print "\tPERF: This partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB']))) +- print "\t"+"-"*78 ++ print("\t"+"-"*78) ++ print("\tPERF: This partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(PhyPartition[k][j]['PERFORMANCE_BOUNDARY_IN_KB'])))) ++ print("\t"+"-"*78) + + if PhyPartition[k][j]['readonly']=="true": + UpdateWPhash(FirstLBA, ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb'])) +@@ -617,22 +619,22 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + #print "\tsize %i kB (%.2f MB)" % (PhyPartition[k][j]['size_in_kb'], PhyPartition[k][j]['size_in_kb']/1024) + + PartitionTypeGUID = PhyPartition[k][j]['type'] +- print "\nPartitionTypeGUID\t0x%X" % PartitionTypeGUID ++ print("\nPartitionTypeGUID\t0x%X" % PartitionTypeGUID) + + # If the partition is a multiple of 4, it must start on an LBA boundary of size SECTOR_SIZE_IN_BYTES + # if j%4==0 : +-# # To be here means the partition number is a multiple of 4, so it must start on ++# # To be here means the partition number is a multiple of 4, so it must start on + # # an LBA boundary, i.e. LBA2, LBA3 etc. + # if i%SECTOR_SIZE_IN_BYTES > 0: + # print "\tWARNING: Location is %i, need to add %i to offset" % (i, SECTOR_SIZE_IN_BYTES-(i%SECTOR_SIZE_IN_BYTES)) + # i += (SECTOR_SIZE_IN_BYTES-(i%SECTOR_SIZE_IN_BYTES)) +-# ++# + # print "\n===============================================================================" +-# print "This partition array entry (%i) is a multiple of 4 and must begin on a boundary of size %i bytes" % (j,SECTOR_SIZE_IN_BYTES) ++# print "This partition array entry (%i) is a multiple of 4 and must begin on a boundary of size %i bytes" % (j,SECTOR_SIZE_IN_BYTES) + # print "This partition array entry is at LBA%i, absolute byte address %i (0x%X)" % (i/SECTOR_SIZE_IN_BYTES,i,i) +-# print "NOTE: LBA0 is protective MBR, LBA1 is Primary GPT Header, LBA2 beginning of Partition Array" ++# print "NOTE: LBA0 is protective MBR, LBA1 is Primary GPT Header, LBA2 beginning of Partition Array" + # print "===============================================================================\n" +- ++ + for b in range(16): + PrimaryGPT[i] = ((PartitionTypeGUID>>(b*8)) & 0xFF) ; i+=1 + +@@ -640,17 +642,17 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + if sequentialguid == 1: + UniquePartitionGUID = j+1 + else: +- if PhyPartition[k][j]['uguid'] != "false": +- UniquePartitionGUID = PhyPartition[k][j]['uguid'] +- else: +- UniquePartitionGUID = random.randint(0,2**(128)) +- +- print "UniquePartitionGUID\t0x%X" % UniquePartitionGUID +- +- ++ if PhyPartition[k][j]['uguid'] != "false": ++ UniquePartitionGUID = PhyPartition[k][j]['uguid'] ++ else: ++ UniquePartitionGUID = random.randint(0,2**(128)) ++ ++ print("UniquePartitionGUID\t0x%X" % UniquePartitionGUID) ++ ++ + # This HACK section is for verifying with GPARTED, allowing me to put in + # whatever uniqueGUID that program came up with +- ++ + #if j==0: + # UniquePartitionGUID = 0x373C17CF53BC7FB149B85A927ED24483 + #elif j==1: +@@ -659,19 +661,19 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + # UniquePartitionGUID = 0x04A9B2AAEF96DAAE465F429D0EF5C6E2 + #else: + # UniquePartitionGUID = 0x4D82D027725FD3AE46AF1C5A28944977 +- ++ + for b in range(16): + PrimaryGPT[i] = ((UniquePartitionGUID>>(b*8)) & 0xFF) ; i+=1 + + # First LBA + for b in range(8): +- PrimaryGPT[i] = ((FirstLBA>>(b*8)) & 0xFF) ; i+=1 ++ PrimaryGPT[i] = ((int(FirstLBA)>>(b*8)) & 0xFF) ; i+=1 + + # Last LBA + for b in range(8): +- PrimaryGPT[i] = ((LastLBA>>(b*8)) & 0xFF) ; i+=1 +- +- print "**** FirstLBA=%d and LastLBA=%d and size is %i sectors" % (FirstLBA,LastLBA,LastLBA-FirstLBA+1) ++ PrimaryGPT[i] = ((int(LastLBA)>>(b*8)) & 0xFF) ; i+=1 ++ ++ print("**** FirstLBA=%d and LastLBA=%d and size is %i sectors" % (FirstLBA,LastLBA,LastLBA-FirstLBA+1)) + + # Attributes + Attributes = 0x0 +@@ -690,17 +692,17 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + if PhyPartition[k][j]['priority']>0: + Attributes |= PhyPartition[k][j]['priority']<<48 + +- print "Attributes\t\t0x%X" % Attributes ++ print("Attributes\t\t0x%X" % Attributes) + + ##import pdb; pdb.set_trace() +- ++ + for b in range(8): + PrimaryGPT[i] = ((Attributes>>(b*8)) & 0xFF) ; i+=1 + + if len(PhyPartition[k][j]['label'])>36: +- print "Label %s is more than 36 characters, therefore it's truncated" % PhyPartition[k][j]['label'] ++ print("Label %s is more than 36 characters, therefore it's truncated" % PhyPartition[k][j]['label']) + PhyPartition[k][j]['label'] = PhyPartition[k][j]['label'][0:36] +- ++ + #print "LABEL %s and i=%i" % (PhyPartition[k][j]['label'],i) + # Partition Name + for b in PhyPartition[k][j]['label']: +@@ -710,7 +712,7 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + for b in range(36-len(PhyPartition[k][j]['label'])): + PrimaryGPT[i] = 0x00 ; i+=1 + PrimaryGPT[i] = 0x00 ; i+=1 +- ++ + #for b in range(2): + # PrimaryGPT[i] = 0x00 ; i+=1 + #for b in range(70): +@@ -719,7 +721,7 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + ##FileToProgram = "" + ##FileOffset = 0 + PartitionLabel = "" +- ++ + ## Default for each partition is no file + FileToProgram = [""] + FileOffset = [0] +@@ -731,14 +733,14 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + ##print "filename exists" + #print PhyPartition[k][j]['filename'] + #print FileToProgram[0] +- +- # These are all the default values that should be there, including an empty string possibly for filename ++ ++ # These are all the default values that should be there, including an empty string possibly for filename + FileToProgram[0] = PhyPartition[k][j]['filename'][0] + FileOffset[0] = PhyPartition[k][j]['fileoffset'][0] + FilePartitionOffset[0] = PhyPartition[k][j]['filepartitionoffset'][0] + FileAppsbin[0] = PhyPartition[k][j]['appsbin'][0] + FileSparse[0] = PhyPartition[k][j]['sparse'][0] +- ++ + for z in range(1,len(PhyPartition[k][j]['filename'])): + FileToProgram.append( PhyPartition[k][j]['filename'][z] ) + FileOffset.append( PhyPartition[k][j]['fileoffset'][z] ) +@@ -747,19 +749,19 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + FileSparse.append( PhyPartition[k][j]['sparse'][z] ) + + #print PhyPartition[k][j]['fileoffset'] +- ++ + + #for z in range(len(FileToProgram)): + # print "FileToProgram[",z,"]=",FileToProgram[z] + # print "FileOffset[",z,"]=",FileOffset[z] + # print " " +- ++ + + if 'label' in PhyPartition[k][j]: + PartitionLabel = PhyPartition[k][j]['label'] + + for z in range(len(FileToProgram)): +- #print "===============================%i of %i===========================================" % (z,len(FileToProgram)) ++ #print "===============================%i of %i===========================================" % (z,len(FileToProgram)) + #print "File: ",FileToProgram[z] + #print "Label: ",FileToProgram[z] + #print "FilePartitionOffset[z]=",FilePartitionOffset[z] +@@ -806,7 +808,7 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + + if j==0: + UpdateRawProgram(RawProgramXML_Blank,0, 33*SECTOR_SIZE_IN_BYTES/1024.0, PhysicalPartitionNumber, FileOffset[z], 33, "gpt_empty%d.bin" % k, "false", "PrimaryGPT", "false", "false") +- ++ + + LastLBA += 1 ## move to the next free sector, also, 0 to 9 inclusive means it's 10 + ## so below (LastLBA-FirstLBA) must = 10 +@@ -842,13 +844,20 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + ## Signature and Revision and HeaderSize i.e. "EFI PART" and 00 00 01 00 and 5C 00 00 00 + PrimaryGPT[i:i+16] = [0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54, 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00] ; i+=16 + ++ header_crc_offset = i + PrimaryGPT[i:i+4] = [0x00, 0x00, 0x00, 0x00] ; i+=4 ## CRC is zeroed out till calculated later + PrimaryGPT[i:i+4] = [0x00, 0x00, 0x00, 0x00] ; i+=4 ## Reserved, set to 0 + +- CurrentLBA= 1 ; i = UpdatePrimaryGPT(CurrentLBA,8,i) +- BackupLBA = 0 ; i = UpdatePrimaryGPT(BackupLBA,8,i) +- FirstLBA = len(PrimaryGPT)/SECTOR_SIZE_IN_BYTES ; i = UpdatePrimaryGPT(FirstLBA,8,i) +- LastLBA = 0 ; i = UpdatePrimaryGPT(LastLBA,8,i) ++ # Update the field that says the LBA of the header, for Primary it is always 1. ++ i = UpdatePrimaryGPT(1,8,i) ++ LastUseableLBA = LastLBA - 1; ++ BackupLBA = LastUseableLBA + BackupGPTNumLBAs ++ print("BackupLBA {0} = LastUseableLBA {1} + BackupGPTNumLBAs {2}".format( BackupLBA, LastUseableLBA , BackupGPTNumLBAs)) ++ #Update GPT Backup LBA, this field may be updated by patching. ++ i = UpdatePrimaryGPT(BackupLBA,8,i) ++ FirstLBA = PrimaryGPTNumLBAs ++ i = UpdatePrimaryGPT(FirstLBA,8,i) ++ i = UpdatePrimaryGPT(LastUseableLBA,8,i) + + ##print "\n\nBackup GPT is at sector %i" % BackupLBA + ##print "Last Usable LBA is at sector %i" % (LastLBA) +@@ -856,146 +865,144 @@ def CreateGPTPartitionTable(PhysicalPartitionNumber,UserProvided=False): + DiskGUID = random.randint(0,2**(128)) + i = UpdatePrimaryGPT(DiskGUID,16,i) + +- PartitionsLBA = 2 ; i = UpdatePrimaryGPT(PartitionsLBA,8,i) ++ PartitionsLBA = 2 ++ i = UpdatePrimaryGPT(PartitionsLBA,8,i) ++ + NumPartitions = (SECTOR_SIZE_IN_BYTES/128)*int(len(PhyPartition[k])/(SECTOR_SIZE_IN_BYTES/128)) # Want a multiple of (SECTOR_SIZE_IN_BYTES) to fill the sector (avoids gdisk warning) + if (len(PhyPartition[k])%(SECTOR_SIZE_IN_BYTES/128))>0: + NumPartitions+=(SECTOR_SIZE_IN_BYTES/128) + + if force128partitions == 1: +- print "\n\nGPT table will list 128 partitions instead of ",NumPartitions +- print "This makes the output compatible with some older test utilities" ++ print("\n\nGPT table will list 128 partitions instead of ",NumPartitions) ++ print("This makes the output compatible with some older test utilities") + NumPartitions = 128 + + i = UpdatePrimaryGPT(NumPartitions,4,i) ## (offset 80) Number of partition entries + ##NumPartitions = 8 ; i = UpdatePrimaryGPT(NumPartitions,4,i) ## (offset 80) Number of partition entries +- SizeOfPartitionArray = 128 ; i = UpdatePrimaryGPT(SizeOfPartitionArray,4,i) ## (offset 84) Size of partition entries ++ SizeOfPartitionArray = 128 ++ i = UpdatePrimaryGPT(SizeOfPartitionArray,4,i) ## (offset 84) Size of partition entries + + ## Now I can calculate the partitions CRC +- print "\n\nCalculating CRC with NumPartitions=%i, SizeOfPartitionArray=%i (bytes each) TOTAL LENGTH %d" % (NumPartitions,SizeOfPartitionArray,NumPartitions*SizeOfPartitionArray); ++ print("\n\nCalculating CRC with NumPartitions=%i, SizeOfPartitionArray=%i (bytes each) TOTAL LENGTH %d" % (NumPartitions,SizeOfPartitionArray,NumPartitions*SizeOfPartitionArray)); + ##PartitionsCRC = CalcCRC32(PrimaryGPT[1024:],NumPartitions*SizeOfPartitionArray) ## Each partition entry is 128 bytes + + + PartitionsPerSector = SECTOR_SIZE_IN_BYTES/128 ## 128 bytes per partition + + if NumPartitions>PartitionsPerSector: +- SectorsToCalculateCRCOver = NumPartitions/PartitionsPerSector ++ SectorsToCalculateCRCOver = NumPartitions/PartitionsPerSector + if NumPartitions%PartitionsPerSector: + SectorsToCalculateCRCOver+=1 + else: + SectorsToCalculateCRCOver = 1 + + PartitionsCRC = CalcCRC32(PrimaryGPT[(2*SECTOR_SIZE_IN_BYTES):],SectorsToCalculateCRCOver * SECTOR_SIZE_IN_BYTES) ## NAND HACK +- +- + i = UpdatePrimaryGPT(PartitionsCRC,4,i) +- print "\n\nCalculated PARTITION CRC is 0x%.8X" % PartitionsCRC +- +- ## gpt patch - main gpt header - last useable lba +- ByteOffset = str(48) +- StartSector = str(1) +- BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) +- UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTMAIN), "Update Primary Header with LastUseableLBA.") +- UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update Primary Header with LastUseableLBA.") +- +- UpdatePatch(BackupStartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTBACKUP), "Update Backup Header with LastUseableLBA.") +- UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update Backup Header with LastUseableLBA.") +- +- # gpt patch - location of backup gpt header ########################################## +- ByteOffset = str(32) +- StartSector = str(1) +- ## gpt patch - main gpt header +- UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.",os.path.basename(GPTMAIN), "Update Primary Header with BackupGPT Header Location.") +- UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.","DISK", "Update Primary Header with BackupGPT Header Location.") +- +- # gpt patch - currentLBA backup header ########################################## +- ByteOffset = str(24) +- BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) +- ## gpt patch - main gpt header +- UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.",os.path.basename(GPTBACKUP), "Update Backup Header with CurrentLBA.") +- UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.","DISK", "Update Backup Header with CurrentLBA.") +- +- # gpt patch - location of backup gpt header ########################################## +- ByteOffset = str(72) +- BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) +- +- ## gpt patch - main gpt header +- UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % BackupGPTNumLBAs,os.path.basename(GPTBACKUP), "Update Backup Header with Partition Array Location.") +- UpdatePatch("NUM_DISK_SECTORS-1",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % BackupGPTNumLBAs,"DISK", "Update Backup Header with Partition Array Location.") ++ print("\n\nCalculated PARTITION CRC is 0x%.8X" % PartitionsCRC) + +- # gpt patch - Partition Array CRC ################################################ +- ByteOffset = str(88) +- StartSector = str(1) +- BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) +- +- ## gpt patch - main gpt header +- UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(2,%d)" % (NumPartitions*SizeOfPartitionArray),os.path.basename(GPTMAIN), "Update Primary Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) +- UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(2,%d)" % (NumPartitions*SizeOfPartitionArray),"DISK", "Update Primary Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) +- +- ## gpt patch - backup gpt header +- UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,4,"CRC32(0,%d)" % (NumPartitions*SizeOfPartitionArray),os.path.basename(GPTBACKUP), "Update Backup Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) +- UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,4,"CRC32(NUM_DISK_SECTORS-%d.,%d)" % (BackupGPTNumLBAs,NumPartitions*SizeOfPartitionArray),"DISK", "Update Backup Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) +- +- #print "\nNeed to patch PARTITION ARRAY, @ sector 1, byte offset 88, size=4 bytes, CRC32(2,33)" +- #print "\nNeed to patch PARTITION ARRAY, @ sector -1, byte offset 88, size=4 bytes, CRC32(2,33)" +- +- ## Now I can calculate the Header CRC +- ##print "\nCalculating CRC for Primary Header" ++ #Compute the CRC over the header. + CalcHeaderCRC = CalcCRC32(PrimaryGPT[SECTOR_SIZE_IN_BYTES:],92) + UpdatePrimaryGPT(CalcHeaderCRC,4,SECTOR_SIZE_IN_BYTES+16) +- #print "\n\nCalculated HEADER CRC is 0x%.8X" % CalcHeaderCRC + +- #print "\nNeed to patch GPT HEADERS in 2 places" +- #print "\nNeed to patch CRC HEADER, @ sector 1, byte offset 16, size=4 bytes, CRC32(1,1)" +- #print "\nNeed to patch CRC HEADER, @ sector -1, byte offset 16, size=4 bytes, CRC32(1,1)" ++ ++ if gen_patch == True: ++ ## gpt patch - main gpt header - last useable lba ++ ByteOffset = str(48) ++ StartSector = str(1) ++ BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) ++ UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTMAIN), "Update Primary Header with LastUseableLBA.") ++ UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update Primary Header with LastUseableLBA.") ++ UpdatePatch(BackupStartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,os.path.basename(GPTBACKUP), "Update Backup Header with LastUseableLBA.") ++ UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % PrimaryGPTNumLBAs,"DISK", "Update Backup Header with LastUseableLBA.") ++ ++ # gpt patch - location of backup gpt header ########################################## ++ ByteOffset = str(32) ++ StartSector = str(1) ++ ## gpt patch - main gpt header ++ UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.",os.path.basename(GPTMAIN), "Update Primary Header with BackupGPT Header Location.") ++ UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.","DISK", "Update Primary Header with BackupGPT Header Location.") ++ ++ # gpt patch - currentLBA backup header ########################################## ++ ByteOffset = str(24) ++ BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) ++ ## gpt patch - main gpt header ++ UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.",os.path.basename(GPTBACKUP), "Update Backup Header with CurrentLBA.") ++ UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-1.","DISK", "Update Backup Header with CurrentLBA.") ++ ++ # gpt patch - location of backup gpt header ########################################## ++ ByteOffset = str(72) ++ BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) ++ ++ ## gpt patch - main gpt header ++ UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % BackupGPTNumLBAs,os.path.basename(GPTBACKUP), "Update Backup Header with Partition Array Location.") ++ UpdatePatch("NUM_DISK_SECTORS-1",ByteOffset,PhysicalPartitionNumber,8,"NUM_DISK_SECTORS-%d." % BackupGPTNumLBAs,"DISK", "Update Backup Header with Partition Array Location.") ++ ++ # gpt patch - Partition Array CRC ################################################ ++ ByteOffset = str(88) ++ StartSector = str(1) ++ BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) ++ ++ ## gpt patch - main gpt header ++ # Add some patch tag that does nothing to keep XML parsers happy. ++ UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(2,%d)" % (NumPartitions*SizeOfPartitionArray),os.path.basename(GPTMAIN), "Update Primary Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) ++ UpdatePatch(StartSector,ByteOffset,PhysicalPartitionNumber,4,"CRC32(2,%d)" % (NumPartitions*SizeOfPartitionArray),"DISK", "Update Primary Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) ++ ++ ## gpt patch - backup gpt header ++ UpdatePatch(BackupStartSector, ByteOffset,PhysicalPartitionNumber,4,"CRC32(0,%d)" % (NumPartitions*SizeOfPartitionArray),os.path.basename(GPTBACKUP), "Update Backup Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) ++ UpdatePatch("NUM_DISK_SECTORS-1.",ByteOffset,PhysicalPartitionNumber,4,"CRC32(NUM_DISK_SECTORS-%d.,%d)" % (BackupGPTNumLBAs,NumPartitions*SizeOfPartitionArray),"DISK", "Update Backup Header with CRC of Partition Array.") # CRC32(start_sector:num_bytes) ++ + + # gpt patch - Header CRC ################################################ + ByteOffset = str(16) + StartSector = str(1) + BackupStartSector = str(BackupGPTNumLBAs-1) ## Want last sector ##str(32) +- ++ # Add some PATCH entries that have no effect in programming to keep XML parser happy, since they expect to see a =2: +- print "\n\n" +- print "*"*78 +- print "ERROR: Empty tags detected\n" +- print "Please replace with" +- print "" +- print "" +- print "\n" ++ print("\n\n") ++ print("*"*78) ++ print("ERROR: Empty tags detected\n") ++ print("Please replace with") ++ print("") ++ print("") ++ print("\n") + sys.exit() + +- print "\nFound a physical_partition, NumPhyPartitions=%d" % NumPhyPartitions +- print "\nlen(PhyPartition)=%d" % len(PhyPartition) ++ print("\nFound a physical_partition, NumPhyPartitions=%d" % NumPhyPartitions) ++ print("\nlen(PhyPartition)=%d" % len(PhyPartition)) + + + elif element.tag=="partition" or element.tag=="primary" or element.tag=="extended": + + CurrentPartition+=1 + +- if element.keys(): ++ if list(element.keys()): + #print "\tAttributes:" + + # Reset all variables to defaults +@@ -1272,10 +1271,10 @@ def ParseXML(XMLFile): + + Partition['size_in_kb'] = 0 + Partition['original_size_in_kb']= 0 +- Partition["readonly"] = "false" ++ Partition['readonly'] = "false" + Partition['label'] = "false" + Partition['type'] = "false" +- Partition['uguid'] = "false" ## unique guid ++ Partition['uguid'] = "false" ## unique guid + Partition['align'] = "false" + Partition['hidden'] = "false" + Partition['system'] = "false" +@@ -1286,7 +1285,7 @@ def ParseXML(XMLFile): + Partition['priority'] = 0 + + ##import pdb; pdb.set_trace() +- ++ + if 'PERFORMANCE_BOUNDARY_IN_KB' in HashInstructions: + Partition['PERFORMANCE_BOUNDARY_IN_KB'] = int(HashInstructions['PERFORMANCE_BOUNDARY_IN_KB']) + else: +@@ -1294,20 +1293,20 @@ def ParseXML(XMLFile): + + FileFound = 0 + +- print " " ++ print(" ") + +- for name, value in element.items(): ++ for name, value in list(element.items()): + #print "\t\tName: '%s'=>'%s' " % (name,value) + + if name=='name' or name=='filename' : + Partition['filename'][-1] = value + FileFound = 1 +- print "Found a file tag '%s'" % value ++ print("Found a file tag '%s'" % value) + elif name=='fileoffset': + Partition['fileoffset'][-1] = value + elif name=='label': + Partition['label'] = value +- print "LABEL:",value ++ print("LABEL:",value) + elif name=='offset' or name=='filepartitionoffset': + Partition['filepartitionoffset'][-1] = int(value) + elif name=='appsbin': +@@ -1320,21 +1319,20 @@ def ParseXML(XMLFile): + if ValidGUIDForm(value) is True: + if OutputToCreate is None: + OutputToCreate = "gpt" +- elif OutputToCreate is "mbr": ++ elif OutputToCreate == "mbr": + PrintBigError("ERROR: Your partition.xml is possibly corrupt, please check the GUID TYPE field") + Partition['type'] = ValidateGUID(value) +- + else: + if OutputToCreate is None: + OutputToCreate = "mbr" +- elif OutputToCreate is "gpt": ++ elif OutputToCreate == "gpt": + PrintBigError("ERROR: Your partition.xml is possibly corrupt, please check the TYPE field") + Partition['type'] = ValidateTYPE(value) + elif name=='uniqueguid': + if ValidGUIDForm(value) is True: + Partition['uguid'] = ValidateGUID(value) + else: +- PrintBigError("ERROR: Your partition.xml is possibly corrupt, please check the TYPE field") ++ PrintBigError("ERROR: Your partition.xml is possibly corrupt, please check the TYPE field") + elif name=="triesremaining": + Partition['tries_remaining'] = int(value); + elif name=="priority": +@@ -1358,7 +1356,7 @@ def ParseXML(XMLFile): + + if value=='0': + if CheckPartitionCount[NumPhyPartitions-1] == CurrentPartition: +- ## To be here means they have size_in_kb='0' BUT this is ok since it is the LAST partition ++ ## To be here means they have size_in_kb='0' BUT this is ok since it is the LAST partition + pass + else: + PrintBigError("\nERROR: Invalid size_in_kb='0' detected on partition %d of %d. This is usually a mistake. Did you mean this to be the *last* partition"%(CurrentPartition,CheckPartitionCount[NumPhyPartitions-1])) +@@ -1373,21 +1371,21 @@ def ParseXML(XMLFile): + Partition["original_size_in_kb"]=TempSizeInBytes/1024 + + else: +- print "Just assigned %s to %s" % (name,value) ++ print("Just assigned %s to %s" % (name,value)) + Partition[name]=value +- +- # No longer appending blank filename data for Trace32. Programming based on Label now ++ ++ # No longer appending blank filename data for Trace32. Programming based on Label now + #if FileFound == 1: + # Partition['filename'].append("") + # Partition['fileoffset'].append(0) + # Partition['filepartitionoffset'].append(0) + # Partition['appsbin'].append("false") + # Partition['sparse'].append("false") +- ++ + + + ## done with all the elements, now ensure that size matches with size_in_kb +- Partition["size"] = ConvertKBtoSectors(Partition["size_in_kb"]) # Still 512 bytes/sector here since "size" is a legacy field ++ Partition["size"] = ConvertKBtoSectors(Partition["size_in_kb"]) # Still 512 bytes/sector here since "size" is a legacy field + + ## Now add this "Partition" object to the PartitionCollection + ## unless it's the label EXT, which is a left over legacy tag +@@ -1396,15 +1394,15 @@ def ParseXML(XMLFile): + #print "\nJust added %s" % Partition['label'] + PartitionCollection.append( Partition ) + +- print "="*40 +- print "storing at %d" % (NumPhyPartitions-1) ++ print("="*40) ++ print("storing at %d" % (NumPhyPartitions-1)) + ##import pdb; pdb.set_trace() + +- print "Adding PartitionCollection to \"PhyPartition\" of size %i" % (NumPhyPartitions-1) ++ print("Adding PartitionCollection to \"PhyPartition\" of size %i" % (NumPhyPartitions-1)) + PhyPartition[(NumPhyPartitions-1)] = PartitionCollection + + #print "\nPartition stored (%i partitions total)" % len(PartitionCollection) +- ++ + else: + PrintBigError("ERROR: element.tag was partition, primary or extended, but it had no keys!") + +@@ -1413,8 +1411,8 @@ def ParseXML(XMLFile): + #print PhyPartition[(NumPhyPartitions-1)] + #print "Current partition is \"%s\"\n" % Partition['label'] + +- if element.keys(): +- for name, value in element.items(): ++ if list(element.keys()): ++ for name, value in list(element.items()): + if name=='name' or name=='filename' : + Partition['filename'][-1] = value + if name=='fileoffset': +@@ -1427,14 +1425,14 @@ def ParseXML(XMLFile): + Partition['sparse'][-1] = value + + #Partition[name]=value +- ++ + #print Partition['filename'] + Partition['filename'].append("") + Partition['fileoffset'].append(0) + Partition['filepartitionoffset'].append(0) + Partition['appsbin'].append("false") + Partition['sparse'].append("false") +- ++ + #try: + # if len(Partition['filename'])>1: + # print "="*78 +@@ -1452,7 +1450,7 @@ def ParseXML(XMLFile): + #print "Showing the changes to PartitionCollection" + #print PartitionCollection[-1] + +- ++ + # Must update this if the user has updated WRITE_PROTECT_BOUNDARY_IN_KB in partition.xml + hash_w[NumWPregions]['num_sectors'] = (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES) + hash_w[NumWPregions]['end_sector'] = (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)-1 +@@ -1462,15 +1460,15 @@ def ParseXML(XMLFile): + hash_w[NumWPregions]['end_sector'] = 0 + hash_w[NumWPregions]['num_boundaries_covered'] = 0 + +- if OutputToCreate is "gpt" and HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] is False: ++ if OutputToCreate == "gpt" and HashInstructions['WRITE_PROTECT_GPT_PARTITION_TABLE'] is False: + hash_w[NumWPregions]['num_sectors'] = 0 + hash_w[NumWPregions]['end_sector'] = 0 + hash_w[NumWPregions]['num_boundaries_covered'] = 0 + +- print "HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] =%d" % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] +- print "HashInstructions['ALIGN_BOUNDARY_IN_KB'] =%d" % HashInstructions['ALIGN_BOUNDARY_IN_KB'] +- print "HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']=%s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] +- print "HashInstructions['DISK_SIGNATURE']=0x%X" % HashInstructions['DISK_SIGNATURE'] ++ print("HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'] =%d" % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']) ++ print("HashInstructions['ALIGN_BOUNDARY_IN_KB'] =%d" % HashInstructions['ALIGN_BOUNDARY_IN_KB']) ++ print("HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']=%s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']) ++ print("HashInstructions['DISK_SIGNATURE']=0x%X" % HashInstructions['DISK_SIGNATURE']) + + #for j in range(len(PhyPartition)): + #for j in range(1): +@@ -1478,7 +1476,7 @@ def ParseXML(XMLFile): + # PrintPartitionCollection( PhyPartition[j] ) + + +- print "len(PhyPartition)=",len(PhyPartition) ++ print("len(PhyPartition)=",len(PhyPartition)) + + if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==False: + ## to be here means we're *not* growing final partition, thereore, obey the sizes they've specified +@@ -1490,22 +1488,22 @@ def ParseXML(XMLFile): + MinSectorsNeeded = 1 # need MBR only + + for Partition in PhyPartition[j]: +- print "LABEL: '%s' with %d sectors " % (Partition['label'],ConvertKBtoSectors(Partition["size_in_kb"])) ++ print("LABEL: '%s' with %d sectors " % (Partition['label'],ConvertKBtoSectors(Partition["size_in_kb"]))) + + MinSectorsNeeded += ConvertKBtoSectors(Partition["size_in_kb"]) + + #print "LABEL '%s' with size %d sectors" % (Partition['label'],Partition['size_in_kb']/2) + +- +- print "MinSectorsNeeded=%d" % MinSectorsNeeded +- #sys.exit() # +- +- +- if OutputToCreate is 'gpt': ++ ++ print("MinSectorsNeeded=%d" % MinSectorsNeeded) ++ #sys.exit() # ++ ++ ++ if OutputToCreate == 'gpt': + PrintBanner("GPT GUID discovered in XML file, Output will be GPT") +- if OutputToCreate is 'mbr': ++ if OutputToCreate == 'mbr': + PrintBanner("MBR type discovered in XML file, Output will be MBR") +- ++ + + # PrintPartitionCollection( PhyPartition[0] ) + def PrintPartitionCollection(PartitionCollection): +@@ -1513,44 +1511,44 @@ def PrintPartitionCollection(PartitionCollection): + #print PartitionCollection + + for Partition in PartitionCollection: +- print Partition +- print " " ++ print(Partition) ++ print(" ") + for key in Partition: +- print key,"\t=>\t",Partition[key] ++ print(key,"\t=>\t",Partition[key]) + + #for j in range(NumMBRPartitions): + + def ParseCommandLine(): + global XMLFile,OutputToCreate,PhysicalPartitionNumber + +- print "\nArgs" ++ print("\nArgs") + for i in range(len(sys.argv)): +- print "sys.argv[%d]=%s" % (i,sys.argv[i]) ++ print("sys.argv[%d]=%s" % (i,sys.argv[i])) + +- print " " ++ print(" ") + + XMLFile = sys.argv[1]; + + if len(sys.argv) >= 3: + m = re.search("mbr|gpt", sys.argv[2] ) + +- if type(m) is not NoneType: ++ if m is not None: + OutputToCreate = sys.argv[2] + else: +- print "Unrecognized option '%s', only 'mbr' or 'gpt' expected" % sys.argv[2] ++ print("Unrecognized option '%s', only 'mbr' or 'gpt' expected" % sys.argv[2]) + else: +- print "\nUser *did* not explicitly specify partition table format (i.e. mbr|gpt)" +- print "\nWill AUTO-DETECT from file" ++ print("\nUser *did* not explicitly specify partition table format (i.e. mbr|gpt)") ++ print("\nWill AUTO-DETECT from file") + + if len(sys.argv) >= 4: # Should mean PHY partition was specified + m = re.search("^\d+$", sys.argv[3] ) +- if type(m) is not NoneType: ++ if m is not None: + PhysicalPartitionNumber = int(sys.argv[3]) +- print "PhysicalPartitionNumber specified as %d" % PhysicalPartitionNumber ++ print("PhysicalPartitionNumber specified as %d" % PhysicalPartitionNumber) + else: + PrintBigError("ERROR: PhysicalPartitionNumber of disk must only contain numbers, '%s' is not valid" % sys.argv[3]) + +- print " " ++ print(" ") + + # Updates the WriteProtect hash that is used in creating emmc_lock_regions.xml + def UpdateWPhash(Start,Size): +@@ -1566,9 +1564,9 @@ def UpdateWPhash(Start,Size): + + if Start-1 <= hash_w[NumWPregions]["end_sector"]: + #print "\n\tCurrent Write Protect region already covers the start of this partition (start=%i)" % hash_w[NumWPregions]["start_sector"] +- ++ + if (Start + Size - 1) > hash_w[NumWPregions]["end_sector"]: +- print "\n\tCurrent Write Protect region is not big enough at %i sectors, needs to be at least %i sectors" % (hash_w[NumWPregions]["end_sector"]-hash_w[NumWPregions]["start_sector"]+1,Start + Size - 1,) ++ print("\n\tCurrent Write Protect region is not big enough at %i sectors, needs to be at least %i sectors" % (hash_w[NumWPregions]["end_sector"]-hash_w[NumWPregions]["start_sector"]+1,Start + Size - 1,)) + while (Start + Size - 1) > hash_w[NumWPregions]["end_sector"]: + hash_w[NumWPregions]["num_sectors"] += (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES); + hash_w[NumWPregions]["end_sector"] += (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES); +@@ -1576,22 +1574,22 @@ def UpdateWPhash(Start,Size): + hash_w[NumWPregions]["num_boundaries_covered"] = hash_w[NumWPregions]["num_sectors"] / (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES) + else: + hash_w[NumWPregions]["num_boundaries_covered"] = 0 +- +- print "\t\tend_sector increased to %i sectors" % hash_w[NumWPregions]["end_sector"] +- print "\t\tnum_sectors increased to %i sectors" % hash_w[NumWPregions]["num_sectors"] +- ++ ++ print("\t\tend_sector increased to %i sectors" % hash_w[NumWPregions]["end_sector"]) ++ print("\t\tnum_sectors increased to %i sectors" % hash_w[NumWPregions]["num_sectors"]) ++ + #print "\n\tCurrent Write Protect region covers this partition (num_sectors=%i)\n" % hash_w[NumWPregions]["num_sectors"] +- ++ + else: +- print "\n\tNew write protect region needed" ++ print("\n\tNew write protect region needed") + #print "\tStart-1\t\t\t\t=%i" % (Start-1) + #print "\tLAST hash_w[NumWPregions][end_sector]=%i\n" % hash_w[NumWPregions]["end_sector"] +- ++ + + NumWPregions+=1; +- ++ + hash_w.append( {'start_sector':Start,'num_sectors':(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES),'end_sector':Start+(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES)-1,'physical_partition_number':0,'boundary_num':0,'num_boundaries_covered':1} ) +- ++ + hash_w[NumWPregions]["boundary_num"] = Start / (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES) + + while (Start + Size - 1) > hash_w[NumWPregions]["end_sector"]: +@@ -1600,12 +1598,12 @@ def UpdateWPhash(Start,Size): + hash_w[NumWPregions]["end_sector"] += (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES); + #print "\t\tend_sector increased to %i sectors" % hash_w[NumWPregions]["end_sector"] + #print "\t\tnum_sectors increased to %i sectors" % hash_w[NumWPregions]["num_sectors"] +- ++ + hash_w[NumWPregions]["num_boundaries_covered"] = hash_w[NumWPregions]["num_sectors"] / (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']*1024/SECTOR_SIZE_IN_BYTES) + +- print "\t\tstart_sector = %i sectors" % hash_w[NumWPregions]["start_sector"] +- print "\t\tend_sector = %i sectors" % hash_w[NumWPregions]["end_sector"] +- print "\t\tnum_sectors = %i sectors\n" % hash_w[NumWPregions]["num_sectors"] ++ print("\t\tstart_sector = %i sectors" % hash_w[NumWPregions]["start_sector"]) ++ print("\t\tend_sector = %i sectors" % hash_w[NumWPregions]["end_sector"]) ++ print("\t\tnum_sectors = %i sectors\n" % hash_w[NumWPregions]["num_sectors"]) + + # A8h reflected is 15h, i.e. 10101000 <--> 00010101 + def reflect(data,nBits): +@@ -1624,38 +1622,38 @@ def reflect(data,nBits): + def CalcCRC32(array,Len): + k = 8; # length of unit (i.e. byte) + MSB = 0; +- gx = 0x04C11DB7; # IEEE 32bit polynomial ++ gx = 0x04C11DB7; # IEEE 32bit polynomial + regs = 0xFFFFFFFF; # init to all ones + regsMask = 0xFFFFFFFF; # ensure only 32 bit answer + +- print "Calculating CRC over byte length of %i" % Len +- print "%s" % HexPrettyPrint(array,Len) ++ print("Calculating CRC over byte length of %i" % Len) ++ print("%s" % HexPrettyPrint(array,Len)) + +- for i in range(Len): ++ for i in range(int(Len)): + 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; + + #print "CRC is 0x%.8X\n" % ReflectedRegs +- ++ + return ReflectedRegs + + +@@ -1681,7 +1679,7 @@ def HexPrettyPrint(data,Length): + + TempAddress = 0 + szHexDump = "\n\tShowing %d bytes\n\t" % (Length) +- for i in range(Length): ++ for i in range(int(Length)): + v = data[i] + + if v == 0x7 and i==0 and Length>5: +@@ -1695,8 +1693,8 @@ def HexPrettyPrint(data,Length): + szNum = "" + szAsc = "" + +- ##print "v=",v," type",type(v) +- ##import pdb; pdb.set_trace() ++ ##print "v=",v," type",type(v) ++ ##import pdb; pdb.set_trace() + #if type(v) is not int: ## HACK + # v = ord(v) ## convert to unsigned char (integers in python) + szNum += "%.2X " % v +@@ -1719,22 +1717,23 @@ def ReturnHigh32bits(var): + return (var>>32) & 0xFFFFFFFF + + def PrintBanner(sz): +- print "\n"+"="*78 +- print sz +- print "="*78+"\n" ++ print("\n"+"="*78) ++ print(sz) ++ print("="*78+"\n") + + def ShowUsage(): + PrintBanner("Basic Usage") +- print "python ptool.py -x partition.xml" ++ print("python ptool.py -x partition.xml") + PrintBanner("Advanced Usage") +- print "%-44s\t\tpython ptool.py -x partition.xml" % ("Basic Usage") +- print "%-44s\t\tpython ptool.py -x partition.xml -s c:\windows" % ("Search path to find partition.xml") +- print "%-44s\tpython ptool.py -x partition.xml -p 0" % ("Specify PHY Partition 0, (creates rawprogram0.xml)") +- print "%-44s\tpython ptool.py -x partition.xml -p 1" % ("Specify PHY Partition 1, (creates rawprogram1.xml)") +- print "%-44s\tpython ptool.py -x partition.xml -p 2" % ("Specify PHY Partition 2, (creates rawprogram2.xml)") +- print "%-44s\t\tpython ptool.py -x partition.xml -v" % ("Verbose output") +- print "%-44s\t\tpython ptool.py -x partition.xml -t c:\\temp" % ("Specify place to put output") +- ++ print("%-44s\t\tpython ptool.py -x partition.xml" % ("Basic Usage")) ++ print("%-44s\t\tpython ptool.py -x partition.xml -s c:\windows" % ("Search path to find partition.xml")) ++ print("%-44s\tpython ptool.py -x partition.xml -p 0" % ("Specify PHY Partition 0, (creates rawprogram0.xml)")) ++ print("%-44s\tpython ptool.py -x partition.xml -p 1" % ("Specify PHY Partition 1, (creates rawprogram1.xml)")) ++ print("%-44s\tpython ptool.py -x partition.xml -p 2" % ("Specify PHY Partition 2, (creates rawprogram2.xml)")) ++ print("%-44s\t\tpython ptool.py -x partition.xml -v" % ("Verbose output")) ++ print("%-44s\t\tpython ptool.py -x partition.xml -t c:\\temp" % ("Specify place to put output")) ++ print("%-44s\t\tpython ptool.py -x partition.xml -n" % ("Don't require the use of patch file")) ++ + def CreateFinalPartitionBin(): + global OutputFolder + +@@ -1809,25 +1808,25 @@ def CreateMBRPartitionTable(PhysicalPartitionNumber): + k = PhysicalPartitionNumber + + if(k>=len(PhyPartition)): +- print "PHY Partition %i of %i not found" % (k,len(PhyPartition)) ++ print("PHY Partition %i of %i not found" % (k,len(PhyPartition))) + sys.exit() +- ++ + NumPartitions = len(PhyPartition[k]) + +- print "\n\nOn PHY Partition %d that has %d partitions" % (k,NumPartitions) ++ print("\n\nOn PHY Partition %d that has %d partitions" % (k,NumPartitions)) + +- print "\n------------\n" ++ print("\n------------\n") + +- print "\nFor PHY Partition %i" % k ++ print("\nFor PHY Partition %i" % k) + if(NumPartitions<=4): +- print "\tWe can get away with only an MBR"; ++ print("\tWe can get away with only an MBR"); + CreateMasterBootRecord(k, NumPartitions ) + else: +- print "\tWe will need an MBR and %d EBRs" % (NumPartitions-3) ++ print("\tWe will need an MBR and %d EBRs" % (NumPartitions-3)) + CreateMasterBootRecord(k, 3 ) + + ## Now the EXTENDED PARTITION +- print "\nAbout to make EBR, FirstLBA=%i, LastLBA=%i" % (FirstLBA,LastLBA) ++ print("\nAbout to make EBR, FirstLBA=%i, LastLBA=%i" % (FirstLBA,LastLBA)) + CreateExtendedBootRecords(k,NumPartitions-3) + + +@@ -1843,33 +1842,33 @@ def CreateMBRPartitionTable(PhysicalPartitionNumber): + ## There was more than 4 partitions, so EXT partition had to be used + UpdateRawProgram(RawProgramXML,ExtendedPartitionBegins, (NumPartitions-3)*SECTOR_SIZE_IN_BYTES/1024.0, k, 0, NumPartitions-3, EBRBIN, 'false', 'EXT') # note file offset is 0 + +- print "\nptool.py is running from CWD: ", os.getcwd(), "\n" ++ print("\nptool.py is running from CWD: ", os.getcwd(), "\n") + + opfile = open(PARTITIONBIN, "wb") + WriteMBR() + WriteEBR() + opfile.close() +- print "Created \"%s\"" % PARTITIONBIN ++ print("Created \"%s\"" % PARTITIONBIN) + + opfile = open(MBRBIN, "wb") + WriteMBR() + opfile.close() +- print "Created \"%s\"" % MBRBIN ++ print("Created \"%s\"" % MBRBIN) + + opfile = open(EBRBIN, "wb") + WriteEBR() + opfile.close() +- print "Created \"%s\"" % EBRBIN ++ print("Created \"%s\"" % EBRBIN) + + opfile = open(RAW_PROGRAM, "w") + opfile.write( prettify(RawProgramXML) ) + opfile.close() +- print "Created \"%s\"" % RAW_PROGRAM ++ print("Created \"%s\"" % RAW_PROGRAM) + + opfile = open(PATCHES, "w") + opfile.write( prettify(PatchesXML) ) + opfile.close() +- print "Created \"%s\"" % PATCHES ++ print("Created \"%s\"" % PATCHES) + + for mydict in hash_w: + #print mydict +@@ -1886,23 +1885,23 @@ def CreateMBRPartitionTable(PhysicalPartitionNumber): + + opfile.write( prettify(EmmcLockRegionsXML) ) + opfile.close() +- print "Created \"%semmc_lock_regions.xml\"" % OutputFolder ++ print("Created \"%semmc_lock_regions.xml\"" % OutputFolder) + +- print "\nUse msp tool to write this information to SD/eMMC card" +- print "\ti.e." ++ print("\nUse msp tool to write this information to SD/eMMC card") ++ print("\ti.e.") + + if sys.platform.startswith("linux"): +- print "\tsudo python msp.py rawprogram0.xml /dev/sdb <---- where /dev/sdb is assumed to be your SD/eMMC card" +- print "\tsudo python msp.py patch0.xml /dev/sdb <---- where /dev/sdb is assumed to be your SD/eMMC card\n\n" ++ print("\tsudo python msp.py rawprogram0.xml /dev/sdb <---- where /dev/sdb is assumed to be your SD/eMMC card") ++ print("\tsudo python msp.py patch0.xml /dev/sdb <---- where /dev/sdb is assumed to be your SD/eMMC card\n\n") + else: +- print "\tpython msp.py rawprogram0.xml \\\\.\\PHYSICALDRIVE2 <---- where \\\\.\\PHYSICALDRIVE2 is" +- print "\tpython msp.py patch0.xml \\\\.\\PHYSICALDRIVE2 <---- assumed to be your SD/eMMC card\n\n" ++ print("\tpython msp.py rawprogram0.xml \\\\.\\PHYSICALDRIVE2 <---- where \\\\.\\PHYSICALDRIVE2 is") ++ print("\tpython msp.py patch0.xml \\\\.\\PHYSICALDRIVE2 <---- assumed to be your SD/eMMC card\n\n") + + + # CreateMasterBootRecord(k,len(PhyPartition[k]) ) + def CreateMasterBootRecord(k,NumMBRPartitions): + global PhyPartition,HashInstructions,MBR,FirstLBA,LastLBA +- print "\nInside CreateMasterBootRecord(%d) -------------------------------------" % NumMBRPartitions ++ print("\nInside CreateMasterBootRecord(%d) -------------------------------------" % NumMBRPartitions) + + MBR = [0]*SECTOR_SIZE_IN_BYTES + MBR[440] = (HashInstructions['DISK_SIGNATURE']>>24)&0xFF +@@ -1926,23 +1925,23 @@ def CreateMasterBootRecord(k,NumMBRPartitions): + + PartitionSectorSize = ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']) # in sector form, i.e. 1KB = 2 sectors + +- print "\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%.2fMB or %i sectors)" % (j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'], ++ print("\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%.2fMB or %i sectors)" % (j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'], + PhyPartition[k][j]['readonly'],PhyPartition[k][j]['size_in_kb'], +- PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb'])) ++ PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']))) + + + # Is this sector aligned? + if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0: + AlignedRemainder = FirstLBA % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']; +- ++ + if AlignedRemainder==0: +- print "\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']))) ++ print("\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])))) + + + # are we on the very last partition, i.e. did user only specify 3 or less partitions? + if (j+1) == len(PhyPartition[k]): +- print "\nTHIS IS THE LAST PARTITION" +- print "HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = %s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] ++ print("\nTHIS IS THE LAST PARTITION") ++ print("HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = %s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']) + if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True: + SectorOffsetPatchBefore = 0 + SectorOffsetPatchAfter = 0 +@@ -1950,13 +1949,13 @@ def CreateMasterBootRecord(k,NumMBRPartitions): + UpdatePatch(str(SectorOffsetPatchBefore),str(ByteOffset),k,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA),"partition%d.bin" % k, "Update last partition with actual size.") + UpdatePatch(str(SectorOffsetPatchBefore),str(ByteOffset),k,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA),"MBR%d.bin" % k, "Update last partition with actual size.") + UpdatePatch(str(SectorOffsetPatchAfter), str(ByteOffset),k,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA),"DISK", "Update 'Update last partition with actual size.") +- +- # Update the Write-Protect hash ++ ++ # Update the Write-Protect hash + if PhyPartition[k][j]['readonly']=="true": + UpdateWPhash(FirstLBA, PartitionSectorSize) + + LastLBA += PartitionSectorSize ## increase by num sectors, LastLBA inclusive, so add 1 for size +- ++ + ## Default for each partition is no file + FileToProgram = [""] + FileOffset = [0] +@@ -1968,7 +1967,7 @@ def CreateMasterBootRecord(k,NumMBRPartitions): + ##print "filename exists" + #print PhyPartition[k][j]['filename'] + #print FileToProgram[0] +- ++ + + FileToProgram[0] = PhyPartition[k][j]['filename'][0] + FileOffset[0] = PhyPartition[k][j]['fileoffset'][0] +@@ -1984,13 +1983,13 @@ def CreateMasterBootRecord(k,NumMBRPartitions): + FileSparse.append( PhyPartition[k][j]['sparse'][z] ) + + #print PhyPartition[k][j]['fileoffset'] +- ++ + + #for z in range(len(FileToProgram)): + # print "FileToProgram[",z,"]=",FileToProgram[z] + # print "FileOffset[",z,"]=",FileOffset[z] + # print " " +- ++ + PartitionLabel = "" + Type = "" + Bootable = "false" +@@ -2019,22 +2018,22 @@ def CreateMasterBootRecord(k,NumMBRPartitions): + # CreateExtendedBootRecords(k,len(PhyPartition[k])-3) + def CreateExtendedBootRecords(k,NumEBRPartitions): + global PhyPartition,HashInstructions,MBR,EBR,FirstLBA,LastLBA,ExtendedPartitionBegins +- print "\nInside CreateExtendedBootRecords(%d) -----------------------------------------" % NumEBRPartitions ++ print("\nInside CreateExtendedBootRecords(%d) -----------------------------------------" % NumEBRPartitions) + + ## Step 1 is to update the MBR with the size of the EXT partition + ## in which logical partitions will be created + + EBROffset = 0 + +- print "EBROffset=",EBROffset ++ print("EBROffset=",EBROffset) + + ExtendedPartitionBegins = FirstLBA + + if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True: +- print "Extended Partition begins at FirstLBA=%i\n" % (ExtendedPartitionBegins) ++ print("Extended Partition begins at FirstLBA=%i\n" % (ExtendedPartitionBegins)) + MBR=UpdatePartitionTable("false","05",FirstLBA,0x0,0x1EE,MBR) ## offset at 0x1EE is the last entry in MBR + else: +- print "Extended Partition begins at FirstLBA=%i, size is %i\n" % (ExtendedPartitionBegins,MinSectorsNeeded-FirstLBA) ++ print("Extended Partition begins at FirstLBA=%i, size is %i\n" % (ExtendedPartitionBegins,MinSectorsNeeded-FirstLBA)) + MBR=UpdatePartitionTable("false","05",FirstLBA,MinSectorsNeeded-FirstLBA,0x1EE,MBR) ## offset at 0x1EE is the last entry in MBR + + ## Still patch no matter what, since this can still go on any size card +@@ -2048,14 +2047,14 @@ def CreateExtendedBootRecords(k,NumEBRPartitions): + FirstLBA += NumEBRPartitions + LastLBA += NumEBRPartitions + +- print "FirstLBA now equals %d since NumEBRPartitions=%d" % (FirstLBA,NumEBRPartitions) ++ print("FirstLBA now equals %d since NumEBRPartitions=%d" % (FirstLBA,NumEBRPartitions)) + + offset = 0 # offset to EBR array which gets EBR.extend( [0]*SECTOR_SIZE_IN_BYTES ) for each EBR + SectorsTillNextBoundary = 0 # reset + + + # EBROffset is the num sectors from the location of the EBR to the actual logical partition +- # and because we group all the EBRs together, ++ # and because we group all the EBRs together, + # EBR0 is NumEBRPartitions away from EXT0 + # EBR1 is NumEBRPartitions-1+SizeOfEXT0 away from EXT1 and so on + # EBR2 is NumEBRPartitions-2+SizeOfEXT0+SizeOfEXT1 away from EXT2 and so on +@@ -2079,93 +2078,93 @@ def CreateExtendedBootRecords(k,NumEBRPartitions): + PartitionSectorSize = ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']) + + ##print "\nPartition name='%s' (readonly=%s)" % (PhyPartition[k][j]['label'], PhyPartition[k][j]['readonly']) +- print "\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%.2fMB or %i sectors)" %(j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'],PhyPartition[k][j]['readonly'],PhyPartition[k][j]['size_in_kb'],PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb'])) +- print "\tFirstLBA=%d (with size %d sectors) and LastLBA=%d" % (FirstLBA,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),LastLBA) ++ print("\n\n%d of %d \"%s\" (readonly=%s) and size=%dKB (%.2fMB or %i sectors)" %(j+1,len(PhyPartition[k]),PhyPartition[k][j]['label'],PhyPartition[k][j]['readonly'],PhyPartition[k][j]['size_in_kb'],PhyPartition[k][j]['size_in_kb']/1024.0,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']))) ++ print("\tFirstLBA=%d (with size %d sectors) and LastLBA=%d" % (FirstLBA,ConvertKBtoSectors(PhyPartition[k][j]['size_in_kb']),LastLBA)) + + if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0: + SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']) + + # Only the last partition can be re-sized. Are we on the very last partition? + if (j+1) == len(PhyPartition[k]): +- print "\n\tTHIS IS THE LAST PARTITION" ++ print("\n\tTHIS IS THE LAST PARTITION") + + if PhyPartition[k][j]['readonly']=="true": + PhyPartition[k][j]['readonly']="false" +- print "\tIt cannot be marked as read-only, it is now set to writeable" ++ print("\tIt cannot be marked as read-only, it is now set to writeable") + + if HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']==True: + ## Here I'd want a patch for this +- print "\tHashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = %s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] ++ print("\tHashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK'] = %s" % HashInstructions['GROW_LAST_PARTITION_TO_FILL_DISK']) + +- print "\njust set LAST PartitionSectorSize = 0 (it was %d)" % PartitionSectorSize ++ print("\njust set LAST PartitionSectorSize = 0 (it was %d)" % PartitionSectorSize) + PartitionSectorSize = 0 +- print "This means the partition table will have a zero in it" ++ print("This means the partition table will have a zero in it") + LastPartitionBeginsAt = FirstLBA + + NumEBRs = (len(PhyPartition[k])-3) + SectorOffsetPatchBefore = NumEBRs + SectorOffsetPatchAfter = ExtendedPartitionBegins+NumEBRs-1 + ByteOffset = 0x1CA +- ++ + ## Patch no matter what + UpdatePatch(str(SectorOffsetPatchBefore),str(ByteOffset),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA+1),"partition%d.bin" % k, "Update last partition with actual size.") + UpdatePatch(str(SectorOffsetPatchBefore-1),str(ByteOffset),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA+1),"EBR%d.bin" % k, "Update last partition with actual size.") + UpdatePatch(str(SectorOffsetPatchAfter), str(ByteOffset),PhysicalPartitionNumber,4,"NUM_DISK_SECTORS-%s." % str(FirstLBA+1),"DISK", "Update last partition with actual size.") + + +- print "\tPhyPartition[k][j]['align']=",PhyPartition[k][j]['align'] +- print "\tSectorsTillNextBoundary=",SectorsTillNextBoundary ++ print("\tPhyPartition[k][j]['align']=",PhyPartition[k][j]['align']) ++ print("\tSectorsTillNextBoundary=",SectorsTillNextBoundary) + + if PhyPartition[k][j]['readonly']=="true": + ## to be here means this partition is read-only, so see if we need to move the start + if FirstLBA <= hash_w[NumWPregions]["end_sector"]: +- print "Great, We *don't* need to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"]) ++ print("Great, We *don't* need to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])) + pass + else: +- print "\tFirstLBA (%d) is *not* covered by the end of the WP region (%d),\n\tit needs to be moved to be aligned to %d" % (FirstLBA,hash_w[NumWPregions]["end_sector"],FirstLBA + SectorsTillNextBoundary) ++ print("\tFirstLBA (%d) is *not* covered by the end of the WP region (%d),\n\tit needs to be moved to be aligned to %d" % (FirstLBA,hash_w[NumWPregions]["end_sector"],FirstLBA + SectorsTillNextBoundary)) + FirstLBA += SectorsTillNextBoundary + elif PhyPartition[k][j]['align']=="true": +- ## to be here means this partition *must* be on an ALIGN boundary ++ ## to be here means this partition *must* be on an ALIGN boundary + SectorsTillNextBoundary = ReturnNumSectorsTillBoundary(FirstLBA,HashInstructions['ALIGN_BOUNDARY_IN_KB']) + if SectorsTillNextBoundary>0: +- print "\tSectorsTillNextBoundary=%d, FirstLBA=%d it needs to be moved to be aligned to %d" % (SectorsTillNextBoundary,FirstLBA,FirstLBA + SectorsTillNextBoundary) +- print "\tHashInstructions['ALIGN_BOUNDARY_IN_KB']=",HashInstructions['ALIGN_BOUNDARY_IN_KB'] ++ print("\tSectorsTillNextBoundary=%d, FirstLBA=%d it needs to be moved to be aligned to %d" % (SectorsTillNextBoundary,FirstLBA,FirstLBA + SectorsTillNextBoundary)) ++ print("\tHashInstructions['ALIGN_BOUNDARY_IN_KB']=",HashInstructions['ALIGN_BOUNDARY_IN_KB']) + FirstLBA += SectorsTillNextBoundary +- ++ + AlignedRemainder = FirstLBA % HashInstructions['ALIGN_BOUNDARY_IN_KB']; +- ++ + if AlignedRemainder==0: +- print "\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['ALIGN_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['ALIGN_BOUNDARY_IN_KB']))) ++ print("\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['ALIGN_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['ALIGN_BOUNDARY_IN_KB'])))) + + else: +- print "\n\tThis partition is *NOT* readonly (or does not have align='true')" ++ print("\n\tThis partition is *NOT* readonly (or does not have align='true')") + ## to be here means this partition is writeable, so see if we need to move the start + if FirstLBA <= hash_w[NumWPregions]["end_sector"]: +- print "\tWe *need* to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"]) +- print "\nhash_w[NumWPregions]['end_sector']=%i" % hash_w[NumWPregions]["end_sector"]; +- print "FirstLBA=%i\n" %FirstLBA; ++ print("\tWe *need* to move FirstLBA (%d) since it's covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"])) ++ print("\nhash_w[NumWPregions]['end_sector']=%i" % hash_w[NumWPregions]["end_sector"]); ++ print("FirstLBA=%i\n" %FirstLBA); + FirstLBA += SectorsTillNextBoundary + +- print "\tFirstLBA is now %d" % (FirstLBA) ++ print("\tFirstLBA is now %d" % (FirstLBA)) + else: + #print "Great, We *don't* need to move FirstLBA (%d) since it's *not* covered by the end of the current WP region (%d)" % (FirstLBA,hash_w[NumWPregions]["end_sector"]) + pass + + if HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']>0: + AlignedRemainder = FirstLBA % HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']; +- ++ + if AlignedRemainder==0: +- print "\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB']))) ++ print("\tThis partition is ** ALIGNED ** to a %i KB boundary at sector %i (boundary %i)" % (HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'],FirstLBA,FirstLBA/(ConvertKBtoSectors(HashInstructions['WRITE_PROTECT_BOUNDARY_IN_KB'])))) + + if PhyPartition[k][j]['readonly']=="true": + UpdateWPhash(FirstLBA, PartitionSectorSize) + + LastLBA = FirstLBA + PartitionSectorSize + +- print "\n\tFirstLBA=%u, LastLBA=%u, PartitionSectorSize=%u" % (FirstLBA,LastLBA,PartitionSectorSize) ++ print("\n\tFirstLBA=%u, LastLBA=%u, PartitionSectorSize=%u" % (FirstLBA,LastLBA,PartitionSectorSize)) + +- print "\tLastLBA is currently %i sectors" % LastLBA +- print "\tCard size of at least %.1fMB needed (%u sectors)" % (LastLBA/2048.0,LastLBA) ++ print("\tLastLBA is currently %i sectors" % LastLBA) ++ print("\tCard size of at least %.1fMB needed (%u sectors)" % (LastLBA/2048.0,LastLBA)) + PhyPartition[k][j]['size_in_kb'] = PartitionSectorSize/2 + + ## Default for each partition is no file +@@ -2179,13 +2178,13 @@ def CreateExtendedBootRecords(k,NumEBRPartitions): + ##print "filename exists" + #print PhyPartition[k][j]['filename'] + #print FileToProgram[0] +- ++ + FileToProgram[0] = PhyPartition[k][j]['filename'][0] + FileOffset[0] = PhyPartition[k][j]['fileoffset'][0] + FilePartitionOffset[0] = PhyPartition[k][j]['filepartitionoffset'][0] + FileAppsbin[0] = PhyPartition[k][j]['appsbin'][0] + FileSparse[0] = PhyPartition[k][j]['sparse'][0] +- ++ + for z in range(1,len(PhyPartition[k][j]['filename'])): + FileToProgram.append( PhyPartition[k][j]['filename'][z] ) + FileOffset.append( PhyPartition[k][j]['fileoffset'][z] ) +@@ -2194,7 +2193,7 @@ def CreateExtendedBootRecords(k,NumEBRPartitions): + FileSparse.append( PhyPartition[k][j]['sparse'][z] ) + + #print PhyPartition[k][j]['fileoffset'] +- ++ + + #for z in range(len(FileToProgram)): + # print "FileToProgram[",z,"]=",FileToProgram[z] +@@ -2247,31 +2246,31 @@ def CreateExtendedBootRecords(k,NumEBRPartitions): + FirstLBA = LastLBA # getting ready for next partition, FirstLBA is now where we left off + + +- print "\n------------------------------------------------------------------------------" +- print " LastLBA is currently %i sectors" % (LastLBA) +- print " Card size of at least %.1fMB needed (%u sectors)" % (LastLBA/2048.0,LastLBA) +- print "------------------------------------------------------------------------------" ++ print("\n------------------------------------------------------------------------------") ++ print(" LastLBA is currently %i sectors" % (LastLBA)) ++ print(" Card size of at least %.1fMB needed (%u sectors)" % (LastLBA/2048.0,LastLBA)) ++ print("------------------------------------------------------------------------------") + + def ReturnNumSectorsTillBoundary(CurrentLBA, BoundaryInKB): + #Say BoundaryInKB is 65536 (64MB) + # if SECTOR_SIZE_IN_BYTES=512, BoundaryLBA=131072 + # if SECTOR_SIZE_IN_BYTES=4096, BoundaryLBA=16384 +- ++ + #Say were at the 63MB boundary, then + # if SECTOR_SIZE_IN_BYTES=512, CurrentLBA=129024 + # if SECTOR_SIZE_IN_BYTES=4096, CurrentLBA=16128 +- ++ + # Distance is then 1MB + # if SECTOR_SIZE_IN_BYTES=512, DistanceLBA=2048 (2048*512=1MB) +- # if SECTOR_SIZE_IN_BYTES=4096, DistanceLBA=256 (256*4096=1MB) ++ # if SECTOR_SIZE_IN_BYTES=4096, DistanceLBA=256 (256*4096=1MB) + + ##import pdb; pdb.set_trace() +- ++ + x = 0 + if BoundaryInKB>0: + if (CurrentLBA%ConvertKBtoSectors(BoundaryInKB)) > 0: + x = ConvertKBtoSectors(BoundaryInKB) - (CurrentLBA%ConvertKBtoSectors(BoundaryInKB)) +- ++ + ##print "\tFYI: Increase by %dKB (%d sectors) if you want to align to %i KB boundary at sector %d" % (x/2,x,BoundaryInKB,CurrentLBA+x) + return x + +@@ -2287,35 +2286,35 @@ def WriteEBR(): + opfile.write(struct.pack("B", b)) + + def PrintBigError(sz): +- print "\t _________________ ___________ " +- print "\t| ___| ___ \\ ___ \\ _ | ___ \\" +- print "\t| |__ | |_/ / |_/ / | | | |_/ /" +- print "\t| __|| /| /| | | | / " +- print "\t| |___| |\\ \\| |\\ \\\\ \\_/ / |\\ \\ " +- print "\t\\____/\\_| \\_\\_| \\_|\\___/\\_| \\_|\n" ++ print("\t _________________ ___________ ") ++ print("\t| ___| ___ \\ ___ \\ _ | ___ \\") ++ print("\t| |__ | |_/ / |_/ / | | | |_/ /") ++ print("\t| __|| /| /| | | | / ") ++ print("\t| |___| |\\ \\| |\\ \\\\ \\_/ / |\\ \\ ") ++ print("\t\\____/\\_| \\_\\_| \\_|\\___/\\_| \\_|\n") + + if len(sz)>0: +- print sz ++ print(sz) + sys.exit(1) +- ++ + + def find_file(filename, search_paths): +- print "\n\n\tLooking for ",filename +- print "\t"+"-"*40 ++ print("\n\n\tLooking for ",filename) ++ print("\t"+"-"*40) + for x in search_paths: +- print "\tSearching ",x ++ print("\tSearching ",x) + temp = os.path.join(x, filename) + if os.path.exists(temp): +- print "\n\t**Found %s (%i bytes)" % (temp,os.path.getsize(temp)) ++ print("\n\t**Found %s (%i bytes)" % (temp,os.path.getsize(temp))) + return temp + + ## search cwd last +- print "\tSearching ",os.getcwd() ++ print("\tSearching ",os.getcwd()) + if os.path.exists(filename): +- print "\n\t**Found %s (%i bytes)" % (filename,os.path.getsize(filename)) ++ print("\n\t**Found %s (%i bytes)" % (filename,os.path.getsize(filename))) + return filename + +- print "\tCound't find file\n" ++ print("\tCound't find file\n") + return None + + ## ============================================================================================== +@@ -2331,17 +2330,17 @@ if len(sys.argv) < 2: + ShowUsage() + sys.exit(); # error + +-print "\nCWD: ", os.getcwd(), "\n" ++print("\nCWD: ", os.getcwd(), "\n") + + try: +- opts, args = getopt.getopt(sys.argv[1:], "x:f:p:s:t:g:k:v:e", ["xml=", "format=", "partition=", "search_path=", "location=", "sequentialguid=", "use128partitions=", "verbose=","erasefirst"]) +-except getopt.GetoptError, err: ++ opts, args = getopt.getopt(sys.argv[1:], "x:f:p:s:t:g:k:v:en", ["xml=", "format=", "partition=", "search_path=", "location=", "sequentialguid=", "use128partitions=", "verbose=","erasefirst","nopatch"]) ++except getopt.GetoptError as err: + # print help information and exit: +- print str(err) # will print something like "option -a not recognized" ++ print(str(err)) # will print something like "option -a not recognized" + ShowUsage() + sys.exit(1) + +-XMLFile= "aaron" ++XMLFile= "adalovelace" + OutputToCreate = None ## sys.argv[2] + PhysicalPartitionNumber = 0 ## sys.argv[3] + search_paths = [] +@@ -2369,14 +2368,14 @@ for o, a in opts: + else: + OutputFolder = re.sub(r"/","\\\\",OutputFolder) # correct slashes + +- print "OutputFolder=",OutputFolder ++ print("OutputFolder=",OutputFolder) + EnsureDirectoryExists(OutputFolder) # only need to call once + + elif o in ("-f", "--format"): + UsingGetOpts = True + OutputToCreate = a + m = re.search("^(mbr|gpt)$", a) #mbr|gpt +- if type(m) is NoneType: ++ if m is None: + PrintBigError("ERROR: Only MBR or GPT is supported") + else: + OutputToCreate = m.group(1) +@@ -2389,7 +2388,7 @@ for o, a in opts: + elif o in ("-k", "--use128partitions"): + ## Force there to be 128 partitions in the partition table + m = re.search("\d", a) #mbr|gpt +- if type(m) is NoneType: ++ if m is None: + force128partitions = 0 + else: + force128partitions = 1 +@@ -2397,10 +2396,13 @@ for o, a in opts: + elif o in ("-e", "--erasefirst"): + erasefirst = 1; + ++ elif o in ("-n", "--nopatch"): ++ gen_patch = False; ++ + elif o in ("-g", "--sequentialguid"): + ## also allow seperating commas + m = re.search("\d", a) #mbr|gpt +- if type(m) is NoneType: ++ if m is None: + sequentialguid = 0 + else: + sequentialguid = 1 +@@ -2409,7 +2411,7 @@ for o, a in opts: + UsingGetOpts = True + PhysicalPartitionNumber = a + m = re.search("^(\d)$", a) #0|1|2 +- if type(m) is NoneType: ++ if m is None: + PrintBigError("ERROR: PhysicalPartitionNumber (-p) must be a number, you supplied *",a,"*") + else: + PhysicalPartitionNumber = int(m.group(1)) +@@ -2417,7 +2419,7 @@ for o, a in opts: + UsingGetOpts = True + verbose = True + else: +- print "o=",o ++ print("o=",o) + assert False, "unhandled option" + + if UsingGetOpts is False: +@@ -2426,12 +2428,12 @@ if UsingGetOpts is False: + ShowUsage() + sys.exit(1) + +-print "XMLFile=",XMLFile ++print("XMLFile=",XMLFile) + if len(OutputFolder)>0: +- print "OutputFolder=",OutputFolder +-print "OutputToCreate",OutputToCreate +-print "PhysicalPartitionNumber",PhysicalPartitionNumber +-print "verbose",verbose ++ print("OutputFolder=",OutputFolder) ++print("OutputToCreate",OutputToCreate) ++print("PhysicalPartitionNumber",PhysicalPartitionNumber) ++print("verbose",verbose) + + + XMLFile = find_file(XMLFile, search_paths) +@@ -2479,7 +2481,7 @@ if OutputToCreate == "gpt": + InitializeXMLFileVars() + CreateGPTPartitionTable( PhysicalPartitionNumber ) ## wants it in LBA format, i.e. 1KB = 2 sectors of size SECTOR_SIZE_IN_BYTES + CreateErasingRawProgramFiles() +- print "\n\nNOTE: All Physical Partitions / LUNs were created since user did not use -p 0 option\n\n" ++ print("\n\nNOTE: All Physical Partitions / LUNs were created since user did not use -p 0 option\n\n") + else: + InitializeXMLFileVars() + CreateGPTPartitionTable( PhysicalPartitionNumber, True ) ## wants it in LBA format, i.e. 1KB = 2 sectors of size SECTOR_SIZE_IN_BYTES +@@ -2489,5 +2491,3 @@ else: + CreateMBRPartitionTable( PhysicalPartitionNumber ) + CreateFinalPartitionBin() + +- +- +-- +2.34.1 + diff --git a/recipes-devtools/partition-utils/qcom-ptool_git.bb b/recipes-devtools/partition-utils/qcom-ptool_git.bb new file mode 100644 index 00000000..e24f88e3 --- /dev/null +++ b/recipes-devtools/partition-utils/qcom-ptool_git.bb @@ -0,0 +1,32 @@ +SUMMARY = "Qualcomm partitioning tool" +DESCRIPTION = "Partitioning tool, generates the GPT and/or Partition MBN" +HOMEPAGE = "https://git.codelinaro.org/linaro/qcomlt/partioning_tool" +SECTION = "devel" +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://LICENSE;md5=7530c1d01d9cfee94e67d6a55e886db5" + +RDEPENDS:${PN} += "python3-xml" + +SRC_URI = "git://git.codelinaro.org/linaro/qcomlt/partioning_tool.git;branch=master;protocol=https \ + file://0001-ptool.py-Generate-zero-files-in-output-folder-when-s.patch \ + file://0002-ptool.py-Python-3-support.patch \ +" + +SRCREV = "3484fc0a88088dea00397774fc93f9acd3a23ce0" + +PV = "0.0+git${SRCPV}" +S = "${WORKDIR}/git" + +inherit python3native + +INHIBIT_DEFAULT_DEPS = "1" + +do_configure[noexec] = "1" +do_compile[noexec] = "1" + +do_install() { + install -d ${D}${bindir} + install -m 755 ${S}/ptool.py ${D}${bindir}/ptool.py +} + +BBCLASSEXTEND = "native nativesdk" From e010a4aeb24e09f359e6775c52329821a4c83c0a Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Tue, 12 Nov 2024 20:30:53 -0300 Subject: [PATCH 3/6] qcom-partition-confs: add recipe based on qclinux 1.2 Recipe based on kirkstone rev 3ac146c (qclinux 1.2), used to generate the machine specific partition.xml file which is later converted to binary with help from ptool.py. Partition confs for qcm6490 and qcs9100 modified to remove persist and overlay, and instead use a larger system/rootfs partition, since that should really be a distro decision and not a BSP one. Signed-off-by: Ricardo Salveti --- .../qcm6490-partitions.conf | 113 ++++++++++++++++ .../qcs9100-partitions.conf | 121 ++++++++++++++++++ .../partition/qcom-partition-confs_1.0.bb | 44 +++++++ 3 files changed, 278 insertions(+) create mode 100644 recipes-bsp/partition/qcom-partition-confs/qcm6490-partitions.conf create mode 100644 recipes-bsp/partition/qcom-partition-confs/qcs9100-partitions.conf create mode 100644 recipes-bsp/partition/qcom-partition-confs_1.0.bb diff --git a/recipes-bsp/partition/qcom-partition-confs/qcm6490-partitions.conf b/recipes-bsp/partition/qcom-partition-confs/qcm6490-partitions.conf new file mode 100644 index 00000000..46660391 --- /dev/null +++ b/recipes-bsp/partition/qcom-partition-confs/qcm6490-partitions.conf @@ -0,0 +1,113 @@ +# Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# select disk type emmc | nand | ufs Mandatory +# disk size in bytes Mandatory +# options if not explicitly provid +--disk --type=ufs --size=137438953472 --write-protect-boundary=0 --sector-size-in-bytes=4096 --grow-last-partition + +# per partition entry +# mandatory options: +# --lun (mandatory for UFS, emmc no need this) +# --name +# --size in bytes +# --type-guid +# optional options: (defaults used if not provided) +# --attributes 1000000000000004 +# --filename "" +# --readonly true +# --sparse false + +#This is LUN 0 - HLOS LUN +--partition --lun=0 --name=ssd --size=8KB --type-guid=2C86E742-745E-4FDD-BFD8-B6A7AC638772 +--partition --lun=0 --name=keystore --size=512KB --type-guid=DE7D4029-0F5B-41C8-AE7E-F6C023A02B33 +--partition --lun=0 --name=efi --size=524288KB --type-guid=C12A7328-F81F-11D2-BA4B-00A0C93EC93B --filename=efi.bin +--partition --lun=0 --name=system --size=23099392KB --type-guid=B921B045-1DF0-41C3-AF44-4C6F280D3FAE --filename=system.img + +#This is LUN 1 - Boot LUN A +--partition --lun=1 --name=xbl_a --size=3604KB --type-guid=DEA0BA2C-CBDD-4805-B4F9-F428251C3E98 --filename=xbl.elf +--partition --lun=1 --name=xbl_config_a --size=512KB --type-guid=5A325AE4-4276-B66D-0ADD-3494DF27706A --filename=xbl_config.elf +--partition --lun=1 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +#This is LUN 2 - Boot LUN B +--partition --lun=2 --name=xbl_b --size=3604KB --type-guid=DEA0BA2C-CBDD-4805-B4F9-F428251C3E98 +--partition --lun=2 --name=xbl_config_b --size=512KB --type-guid=5A325AE4-4276-B66D-0ADD-3494DF27706A +--partition --lun=2 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +#This is LUN 3 - OTP LUN +#QCOM development requirement: Ensure all partitions in LUN3 is a multiple of 128k +#Linux Android customers can ignore this requirement +--partition --lun=3 --name=ALIGN_TO_128K_1 --size=104KB --type-guid=FDE1604B-D68B-4BD4-973D-962AE7A1ED88 +--partition --lun=3 --name=cdt --size=128KB --type-guid=A19F205F-CCD8-4B6D-8F1E-2D9BC24CFFB1 +--partition --lun=3 --name=ddr --size=1024KB --type-guid=20A0C19C-286A-42FA-9CE7-F64C3226A794 +--partition --lun=3 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +#This is LUN 4 - Protected Read-only LUN +# Partition's that are expected to be OTA upgradable require a A and B version. +# If the partition you are adding is not expected to be OTA upgradable please add it after the 'B' partition list. +# These are the 'A' partition's needed for the A/B boot/ota update feature. +# If you add something to this section remember to add it to B as well +--partition --lun=4 --name=aop_a --size=512KB --type-guid=D69E90A5-4CAB-0071-F6DF-AB977F141A7F --filename=aop.mbn +--partition --lun=4 --name=SYSFW_VERSION --size=4KB --type-guid=3C44F88B-1878-4C29-B122-EE78766442A7 +--partition --lun=4 --name=dtb_a --size=65536KB --type-guid=2a1a52fc-aa0b-401c-a808-5ea0f91068f8 --filename=dtb.bin +--partition --lun=4 --name=dtb_b --size=65536KB --type-guid=a166f11a-2b39-4faa-b7e7-f8aa080d0587 +--partition --lun=4 --name=xbl_ramdump_a --size=2048KB --type-guid=0382F197-E41F-4E84-B18B-0B564AEAD875 --filename=XblRamdump.elf +--partition --lun=4 --name=xbl_ramdump_b --size=2048KB --type-guid=C3E58B09-ABCB-42EA-9F0C-3FA453FA892E +--partition --lun=4 --name=uefi_a --size=5120KB --type-guid=400FFDCD-22E0-47E7-9A23-F16ED9382388 --filename=uefi.elf +--partition --lun=4 --name=uefi_b --size=5120KB --type-guid=9F234B5B-0EFB-4313-8E4C-0AF1F605536B +--partition --lun=4 --name=tz_a --size=4096KB --type-guid=A053AA7F-40B8-4B1C-BA08-2F68AC71A4F4 --filename=tz.mbn +--partition --lun=4 --name=hyp_a --size=8192KB --type-guid=E1A6A689-0C8D-4CC6-B4E8-55A4320FBD8A --filename=hypvm.mbn +--partition --lun=4 --name=mdtpsecapp_a --size=4096KB --type-guid=EA02D680-8712-4552-A3BE-E6087829C1E6 +--partition --lun=4 --name=mdtp_a --size=32768KB --type-guid=3878408A-E263-4B67-B878-6340B35B11E3 +--partition --lun=4 --name=devcfg_a --size=128KB --type-guid=F65D4B16-343D-4E25-AAFC-BE99B6556A6D --filename=devcfg.mbn +--partition --lun=4 --name=qupfw_a --size=80KB --type-guid=21d1219f-2ed1-4ab4-930a-41a16ae75f7f --filename=qupv3fw.elf +--partition --lun=4 --name=uefisecapp_a --size=2048KB --type-guid=BE8A7E08-1B7A-4CAE-993A-D5B7FB55B3C2 --filename=uefi_sec.mbn +--partition --lun=4 --name=imagefv_a --size=2048KB --type-guid=17911177-C9E6-4372-933C-804B678E666F --filename=imagefv.elf +--partition --lun=4 --name=shrm_a --size=128KB --type-guid=CB74CA22-2F0D-4B82-A1D6-C4213F348D73 --filename=shrm.elf +--partition --lun=4 --name=multiimgoem_a --size=32KB --type-guid=E126A436-757E-42D0-8D19-0F362F7A62B8 --filename=multi_image.mbn +--partition --lun=4 --name=cpucp_a --size=1024KB --type-guid=1E8615BD-6D8C-41AD-B3EA-50E8BF40E43F --filename=cpucp.elf +--partition --lun=4 --name=qmcs --size=30720KB --type-guid=358740B1-34BD-4E4C-9656-3454F0A8FDD9 +--partition --lun=4 --name=qweslicstore_a --size=256KB --type-guid=7BAB3C93-5F73-4D02-B8CB-5B9F899D29A8 + +#These are the 'B' partition's needed for the A/B boot/ota update feature. A and B partitions must have differrent GUID's. +#For convinience sake we keep all the B partitions with the same GUID +--partition --lun=4 --name=aop_b --size=512KB --type-guid=B8B27C4C-4B5B-8AB2-502F-A792B590A896 +--partition --lun=4 --name=tz_b --size=4096KB --type-guid=C832EA16-8B0D-4398-A67B-EBB30EF98E7E +--partition --lun=4 --name=hyp_b --size=8192KB --type-guid=3D3E3AD2-8FF3-4975-A7E7-0E8A10B69F0D +--partition --lun=4 --name=mdtpsecapp_b --size=4096KB --type-guid=77036CD4-03D5-42BB-8ED1-37E5A88BAA34 +--partition --lun=4 --name=mdtp_b --size=32768KB --type-guid=77036CD4-03D5-42BB-8ED1-37E5A88BAA34 +--partition --lun=4 --name=devcfg_b --size=128KB --type-guid=4E820A31-17E3-447D-B32D-FB339F7EA1A2 +--partition --lun=4 --name=qupfw_b --size=80KB --type-guid=04BA8D53-5091-4958-9CA1-0FE0941D2CBC +--partition --lun=4 --name=uefisecapp_b --size=2048KB --type-guid=538CBDBA-D4A4-4438-A466-D7B356FAC165 +--partition --lun=4 --name=imagefv_b --size=2048KB --type-guid=920CFC3D-7285-4A47-9C1C-4A87590E0687 +--partition --lun=4 --name=shrm_b --size=128KB --type-guid=39FD6C00-49EB-6BD1-6899-2FB849DD4F75 +--partition --lun=4 --name=multiimgoem_b --size=32KB --type-guid=3E3E3ECD-C512-4F95-9144-6063826A8970 +--partition --lun=4 --name=cpucp_b --size=1024KB --type-guid=6C1111FB-5354-41DE-AC17-5B6E542BE836 +--partition --lun=4 --name=qweslicstore_b --size=256KB --type-guid=77036CD4-03D5-42BB-8ED1-37E5A88BAA34 + +#These are non A/B partitions. In a A/B build these would not be updated via a OTA update +--partition --lun=4 --name=devinfo --size=4KB --type-guid=65ADDCF4-0C5C-4D9A-AC2D-D90B5CBFCD03 +--partition --lun=4 --name=dip --size=1024KB --type-guid=4114B077-005D-4E12-AC8C-B493BDA684FB +--partition --lun=4 --name=apdp --size=256KB --type-guid=E6E98DA2-E22A-4D12-AB33-169E7DEAA507 +--partition --lun=4 --name=splash --size=33424KB --type-guid=AD99F201-DC71-4E30-9630-E19EEF553D1B +--partition --lun=4 --name=limits --size=4KB --type-guid=10A0C19C-516A-5444-5CE3-664C3226A794 +--partition --lun=4 --name=limits-cdsp --size=4KB --type-guid=545D3707-8329-40E8-8B5E-3E554CBDC786 +--partition --lun=4 --name=toolsfv --size=1024KB --type-guid=97745ABA-135A-44C3-9ADC-05616173C24C --filename=tools.fv +--partition --lun=4 --name=logfs --size=8192KB --type-guid=BC0330EB-3410-4951-A617-03898DBE3372 +--partition --lun=4 --name=quantumsdk --size=40960KB --type-guid=AA9A5C4C-4F1F-7D3A-014A-22BD33BF7191 +--partition --lun=4 --name=logdump --size=524288KB --type-guid=5AF80809-AABB-4943-9168-CDFC38742598 +--partition --lun=4 --name=uefivarstore --size=512KB --type-guid=165BD6BC-9250-4AC8-95A7-A93F4A440066 +--partition --lun=4 --name=secdata --size=25KB --type-guid=76cfc7ef-039d-4e2c-b81e-4dd8c2cb2a93 +--partition --lun=4 --name=quantumfv --size=512KB --type-guid=80c23c26-c3f9-4a19-bb38-1e457daceb09 +--partition --lun=4 --name=catecontentfv --size=1024KB --type-guid=e12d830b-7f62-4f0b-b48a-8178c5bf3ac1 +--partition --lun=4 --name=vm-data --size=33424KB --type-guid=21ADB864-C9E7-4C76-BE68-568E20C58439 +--partition --lun=4 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +#This is LUN 5 - Protected Read-write LUN +#QCOM development requirement: Ensure all partitions in LUN5 is a multiple of 128k. +--partition --lun=5 --name=ALIGN_TO_128K_2 --size=104KB --type-guid=6891a3b7-0ccc-4705-bb53-2673cac193bd +--partition --lun=5 --name=modemst1 --size=3072KB --type-guid=EBBEADAF-22C9-E33B-8F5D-0E81686A68CB +--partition --lun=5 --name=modemst2 --size=3072KB --type-guid=0A288B1F-22C9-E33B-8F5D-0E81686A68CB +--partition --lun=5 --name=fsg --size=3072KB --type-guid=638FF8E2-22C9-E33B-8F5D-0E81686A68CB +--partition --lun=5 --name=fsc --size=128KB --type-guid=57B90A16-22C9-E33B-8F5D-0E81686A68CB +--partition --lun=5 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 diff --git a/recipes-bsp/partition/qcom-partition-confs/qcs9100-partitions.conf b/recipes-bsp/partition/qcom-partition-confs/qcs9100-partitions.conf new file mode 100644 index 00000000..2f72a1e3 --- /dev/null +++ b/recipes-bsp/partition/qcom-partition-confs/qcs9100-partitions.conf @@ -0,0 +1,121 @@ +# Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# select disk type emmc | nand | ufs Mandatory +# disk size in bytes Mandatory +# options if not explicitly provide + +--disk --type=ufs --size=76841669632 --write-protect-boundary=0 --sector-size-in-bytes=4096 --grow-last-partition + +# per partition entry +# mandatory options: +# --lun (mandatory for UFS, emmc no need this) +# --name +# --size in bytes +# --type-guid +# optional options: (defaults used if not provided) +# --attributes 1000000000000004 +# --filename "" +# --readonly true +# --sparse false + +# This is LUN 0 - Guest VM(s) LUN" +--partition --lun=0 --name=ALIGN_TO_128K_2 --size=104KB --type-guid=6891a3b7-0ccc-4705-bb53-2673cac193bd +--partition --lun=0 --name=reserved1_a --size=65536KB --type-guid=4ef7c492-d028-41c6-b47a-bbd33850cb31 +--partition --lun=0 --name=reserved2_a --size=65536KB --type-guid=4e351956-aa2a-479e-b5f7-163da39f14f6 +--partition --lun=0 --name=efi --size=524288KB --type-guid=c12a7328-f81f-11d2-ba4b-00a0c93ec93b --filename=efi.bin +--partition --lun=0 --name=system --size=29390848KB --type-guid=b921b045-1df0-41c3-af44-4c6f280d3fae --filename=system.img + +# This is LUN 1 - Boot LUN A +--partition --lun=1 --name=xbl_a --size=5120KB --type-guid=DEA0BA2C-CBDD-4805-B4F9-F428251C3E98 --filename=xbl.elf +--partition --lun=1 --name=xbl_bkup_a --size=5120KB --type-guid=7A3DF1A3-A31A-454D-BD78-DF259ED486BE +--partition --lun=1 --name=xbl_config_a --size=516KB --type-guid=5A325AE4-4276-B66D-0ADD-3494DF27706A --filename=xbl_config.elf +--partition --lun=1 --name=shrm_a --size=80KB --type-guid=CB74CA22-2F0D-4B82-A1D6-C4213F348D73 --filename=shrm.elf +--partition --lun=1 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +# This is LUN 2 - Boot LUN B +--partition --lun=2 --name=xbl_b --size=5120KB --type-guid=DEA0BA2C-CBDD-4805-B4F9-F428251C3E98 --filename=xbl.elf +--partition --lun=2 --name=xbl_bkup_b --size=5120KB --type-guid=7A3DF1A3-A31A-454D-BD78-DF259ED486BE +--partition --lun=2 --name=xbl_config_b --size=516KB --type-guid=A4CDBB5A-5A73-436E-B129-689EC01DBFE3 --filename=xbl_config.elf +--partition --lun=2 --name=shrm_b --size=80KB --type-guid=39FD6C00-49EB-6BD1-6899-2FB849DD4F75 --filename=shrm.elf +--partition --lun=2 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +# This is LUN 3 - OTP LUN +# QCOM development requirement: Ensure all partitions in LUN3 is a multiple of 128k +# Linux Android customers can ignore this requirement +--partition --lun=3 --name=ALIGN_TO_128K_1 --size=104KB --type-guid=50d0abe4-f594-4641-981b-df602e400f34 +--partition --lun=3 --name=cdt --size=4KB --type-guid=A19F205F-CCD8-4B6D-8F1E-2D9BC24CFFB1 +--partition --lun=3 --name=ddr --size=1600KB --type-guid=20A0C19C-286A-42FA-9CE7-F64C3226A794 +--partition --lun=3 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +# This is LUN 4 - Primary VM Read-write LUN +# QCOM development requirement: Ensure all partitions in LUN5 is a multiple of 128k. +# ****Linux Android customers can ignore this requirement **** +--partition --lun=4 --name=aop_a --size=256KB --type-guid=D69E90A5-4CAB-0071-F6DF-AB977F141A7F --filename=aop.mbn +--partition --lun=4 --name=uefi_a --size=5120KB --type-guid=400FFDCD-22E0-47E7-9A23-F16ED9382388 --filename=uefi.elf +--partition --lun=4 --name=uefi_b --size=5120KB --type-guid=9F234B5B-0EFB-4313-8E4C-0AF1F605536B +--partition --lun=4 --name=uefisecapp_a --size=2048KB --type-guid=BE8A7E08-1B7A-4CAE-993A-D5B7FB55B3C2 --filename=uefi_sec.mbn +--partition --lun=4 --name=uefisecapp_b --size=2048KB --type-guid=538CBDBA-D4A4-4438-A466-D7B356FAC165 --filename=uefi_sec.mbn +--partition --lun=4 --name=xbl_ramdump_a --size=2048KB --type-guid=0382F197-E41F-4E84-B18B-0B564AEAD875 --filename=XblRamdump.elf +--partition --lun=4 --name=xbl_ramdump_b --size=2048KB --type-guid=C3E58B09-ABCB-42EA-9F0C-3FA453FA892E +--partition --lun=4 --name=dtb_a --size=65536KB --type-guid=2a1a52fc-aa0b-401c-a808-5ea0f91068f8 --filename=dtb.bin +--partition --lun=4 --name=dtb_b --size=65536KB --type-guid=a166f11a-2b39-4faa-b7e7-f8aa080d0587 --filename=dtb.bin +--partition --lun=4 --name=tz_a --size=4000KB --type-guid=A053AA7F-40B8-4B1C-BA08-2F68AC71A4F4 --filename=tz.mbn +--partition --lun=4 --name=hyp_a --size=65536KB --type-guid=E1A6A689-0C8D-4CC6-B4E8-55A4320FBD8A --filename=hypvm.mbn +--partition --lun=4 --name=TZAPPS --size=320KB --type-guid=14D11C40-2A3D-4F97-882D-103A1EC09333 +--partition --lun=4 --name=mdtpsecapp_a --size=4096KB --type-guid=EA02D680-8712-4552-A3BE-E6087829C1E6 +--partition --lun=4 --name=mdtp_a --size=32768KB --type-guid=3878408A-E263-4B67-B878-6340B35B11E3 +--partition --lun=4 --name=keymaster_a --size=512KB --type=A11D2A7C-D82A-4C2F-8A01-1805240E6626 +--partition --lun=4 --name=devcfg_a --size=128KB --type-guid=F65D4B16-343D-4E25-AAFC-BE99B6556A6D --filename=devcfg_iot.mbn +--partition --lun=4 --name=qupfw_a --size=128KB --type-guid=21d1219f-2ed1-4ab4-930a-41a16ae75f7f +--partition --lun=4 --name=qupfw_b --size=128KB --type-guid=04BA8D53-5091-4958-9CA1-0FE0941D2CBC +--partition --lun=4 --name=cpucp_a --size=1024KB --type-guid=1E8615BD-6D8C-41AD-B3EA-50E8BF40E43F --filename=cpucp.elf +--partition --lun=4 --name=apdp_a --size=64KB --type-guid=E6E98DA2-E22A-4D12-AB33-169E7DEAA507 +--partition --lun=4 --name=multiimgoem_a --size=32KB --type-guid=E126A436-757E-42D0-8D19-0F362F7A62B8 --filename=multi_image.mbn +--partition --lun=4 --name=multiimgqti_a --size=32KB --type-guid=846C6F05-EB46-4C0A-A1A3-3648EF3F9D0E --filename=multi_image_qti.mbn +--partition --lun=4 --name=imagefv_a --size=1024KB --type-guid=920CFC3D-7285-4A47-9C1C-4A87590E0687 --filename=imagefv.elf +--partition --lun=4 --name=usb4fw_a --size=61KB --type-guid=3FA03C7A-9FDC-498B-A2A8-DE11EE339790 +--partition --lun=4 --name=devinfo --size=4KB --type-guid=65ADDCF4-0C5C-4D9A-AC2D-D90B5CBFCD03 +--partition --lun=4 --name=dip --size=1024KB --type-guid=4114B077-005D-4E12-AC8C-B493BDA684FB +--partition --lun=4 --name=spunvm --size=8192KB --type-guid=e42e2b4c-33b0-429b-b1ef-d341c547022c +--partition --lun=4 --name=splash --size=33424KB --type-guid=AD99F201-DC71-4E30-9630-E19EEF553D1B +--partition --lun=4 --name=limits --size=4KB --type-guid=10A0C19C-516A-5444-5CE3-664C3226A794 +--partition --lun=4 --name=logfs --size=8192KB --type-guid=BC0330EB-3410-4951-A617-03898DBE3372 +--partition --lun=4 --name=emac --size=512KB --type-guid=e7e5eff9-d224-4eb3-8f0b-1d2a4be18665 +--partition --lun=4 --name=uefivarstore --size=512KB --type-guid=165BD6BC-9250-4AC8-95A7-A93F4A440066 +--partition --lun=4 --name=secdata --size=128KB --type-guid=76cfc7ef-039d-4e2c-b81e-4dd8c2cb2a93 +--partition --lun=4 --name=toolsfv --size=1024KB --type-guid=97745ABA-135A-44C3-9ADC-05616173C24C --filename=tools.fv +--partition --lun=4 --name=softsku --size=8KB --type-guid=69cfd37f-3d6b-48ed-9739-23015606be65 +# - Below are PVM images +--partition --lun=4 --name=gearvm_a --size=16000KB --type-guid=06ef844e-08fc-494e-89eb-396d4d6c5b27 +--partition --lun=4 --name=diag_log --size=65536KB --type-guid=3989af30-5c02-4154-ad00-1d34c816cac1 +--partition --lun=4 --name=pvm_log --size=65536KB --type-guid=2889c942-ff80-4da8-a5b8-3f32f285c0d8 +--partition --lun=4 --name=gvm_log --size=65536KB --type-guid=78ebfd49-e8b1-4e75-abc0-3f2dbc7428dd +--partition --lun=4 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +# This is LUN 5 - Primary VM Read-write LUN +--partition --lun=5 --name=ALIGN_TO_128K_2 --size=104KB --type-guid=6891a3b7-0ccc-4705-bb53-2673cac193bd +# These are the 'B' partition's needed for the A/B boot/ota update feature. A and B partitions must have differrent GUID's. +# For convinience sake we keep all the B partitions with the same GUID +--partition --lun=5 --name=aop_b --size=256KB --type-guid=B8B27C4C-4B5B-8AB2-502F-A792B590A896 --filename=aop.mbn +--partition --lun=5 --name=tz_b --size=4000KB --type-guid=C832EA16-8B0D-4398-A67B-EBB30EF98E7E --filename=tz.mbn +--partition --lun=5 --name=hyp_b --size=65536KB --type-guid=3D3E3AD2-8FF3-4975-A7E7-0E8A10B69F0D --filename=hypvm.mbn +--partition --lun=5 --name=keymaster_b --size=512KB --type-guid=77036CD4-03D5-42BB-8ED1-37E5A88BAA34 --filename=keymint.mbn +--partition --lun=5 --name=devcfg_b --size=128KB --type-guid=4E820A31-17E3-447D-B32D-FB339F7EA1A2 --filename=devcfg_iot.mbn +--partition --lun=5 --name=cpucp_b --size=1024KB --type-guid=6C1111FB-5354-41DE-AC17-5B6E542BE836 --filename=cpucp.elf +--partition --lun=5 --name=apdp_b --size=64KB --type-guid=110F198D-8174-4193-9AF1-5DA94CDC59C9 +--partition --lun=5 --name=multiimgoem_b --size=32KB --type-guid=3E3E3ECD-C512-4F95-9144-6063826A8970 --filename=multi_image.mbn +--partition --lun=5 --name=multiimgqti_b --size=32KB --type-guid=749e5def-7b57-4bc6-ab51-aaee077c2d56 --filename=multi_image_qti.mbn +--partition --lun=5 --name=imagefv_b --size=1024KB --type-guid=77036CD4-03D5-42BB-8ED1-37E5A88BAA34 --filename=imagefv.elf +--partition --lun=5 --name=gearvm_b --size=16000KB --type-guid=06ef844e-08fc-494e-89eb-396d4d6c5b27 +--partition --lun=5 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +# This is LUN 6 - Protected Read-write LUN +--partition --lun=6 --name=ALIGN_TO_128K_2 --size=104KB --type-guid=6891a3b7-0ccc-4705-bb53-2673cac193bd +--partition --lun=6 --name=last_parti --size=0KB --type-guid=00000000-0000-0000-0000-000000000000 + +# This is LUN 7 - Protected Read-write LUN +--partition --lun=7 --name=logdump --size=524288KB --type-guid=5AF80809-AABB-4943-9168-CDFC38742598 +--partition --lun=7 --name=ALIGN_TO_128K_4 --size=104KB --type-guid=6891a3b7-0ccc-4705-bb53-2673cac193bd +--partition --lun=7 --name=recoveryinfo --size=4KB --type-guid=7374B391-291C-49FA-ABC2-0463AB5F713F +--partition --lun=7 --name=xbl_logs --size=1024KB --type-guid=F7EECB66-781A-439A-8955-70E12ED4A7A0 diff --git a/recipes-bsp/partition/qcom-partition-confs_1.0.bb b/recipes-bsp/partition/qcom-partition-confs_1.0.bb new file mode 100644 index 00000000..92a4464e --- /dev/null +++ b/recipes-bsp/partition/qcom-partition-confs_1.0.bb @@ -0,0 +1,44 @@ +SUMMARY = "Qualcomm machine specific partition configuration" +DESCRIPTION = "Machine partition configuration used by qcom-gen-partitions-tool \ +for generating the machine specific partition.xml file." +LICENSE = "BSD-3-Clause-Clear" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/BSD-3-Clause-Clear;md5=7a434440b651f4a472ca93716d01033a" + +DEPENDS += "qcom-gen-partitions-tool-native" + +SRC_URI = " \ + file://qcm6490-partitions.conf \ + file://qcs9100-partitions.conf \ +" + +PROVIDES += "virtual/partconf" + +S = "${WORKDIR}/sources" +UNPACKDIR = "${S}" +B = "${WORKDIR}/build" + +inherit python3native deploy + +INHIBIT_DEFAULT_DEPS = "1" + +do_configure[noexec] = "1" + +PARTCONF ?= "" +PARTCONF:qcm6490 ?= "qcm6490-partitions.conf" +PARTCONF:qcs9100 ?= "qcs9100-partitions.conf" + +do_compile() { + gen_partition.py -i ${S}/${PARTCONF} -o ${B}/${MACHINE}-partition.xml +} + +do_install() { + install -D -m0644 ${B}/${MACHINE}-partition.xml ${D}${datadir}/qcom-partition-confs/${MACHINE}-partition.xml +} + +do_deploy() { + install -m 0644 ${B}/${MACHINE}-partition.xml -D ${DEPLOYDIR}/partition.xml +} +addtask deploy after do_install + +COMPATIBLE_MACHINE = "(qcm6490|qcs9100)" +PACKAGE_ARCH = "${MACHINE_ARCH}" From 519847d00ce0de1fd3bf93ce298e145b902ea2ee Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Tue, 12 Nov 2024 21:46:31 -0300 Subject: [PATCH 4/6] qcom-gen-partition-bins: add recipe based on qclinux 1.2 Recipe based on kirkstone rev 3ac146c (qclinux 1.2), used to generate the machine specific partition binaries, required for flashing with qdl. Signed-off-by: Ricardo Salveti --- .../qcom-gen-partition-bins_1.0.bb | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 recipes-devtools/partition-utils/qcom-gen-partition-bins_1.0.bb diff --git a/recipes-devtools/partition-utils/qcom-gen-partition-bins_1.0.bb b/recipes-devtools/partition-utils/qcom-gen-partition-bins_1.0.bb new file mode 100644 index 00000000..ef51b3b8 --- /dev/null +++ b/recipes-devtools/partition-utils/qcom-gen-partition-bins_1.0.bb @@ -0,0 +1,32 @@ +SUMMARY = "Generate and deploy the machine specific partition binaries" +LICENSE = "BSD-3-Clause-Clear" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/${LICENSE};md5=7a434440b651f4a472ca93716d01033a" + +DEPENDS += "qcom-ptool-native" + +inherit deploy python3native + +INHIBIT_DEFAULT_DEPS = "1" + +do_configure[noexec] = "1" +do_install[noexec] = "1" +do_compile[depends] += "virtual/partconf:do_deploy" + +do_compile() { + ptool.py -x ${DEPLOY_DIR_IMAGE}/partition.xml +} + +do_deploy() { + install -m 0644 ${B}/gpt_backup*.bin -D ${DEPLOYDIR} + install -m 0644 ${B}/gpt_both*.bin -D ${DEPLOYDIR} + install -m 0644 ${B}/gpt_empty*.bin -D ${DEPLOYDIR} + install -m 0644 ${B}/gpt_main*.bin -D ${DEPLOYDIR} + install -m 0644 ${B}/patch*.xml -D ${DEPLOYDIR} + install -m 0644 ${B}/rawprogram*.xml -D ${DEPLOYDIR} + install -m 0644 ${B}/zeros_*.bin -D ${DEPLOYDIR} + install -m 0644 ${B}/wipe_rawprogram_PHY*.xml -D ${DEPLOYDIR} +} +addtask deploy before do_build after do_compile + +COMPATIBLE_MACHINE = "(qcm6490|qcs9100)" +PACKAGE_ARCH = "${MACHINE_ARCH}" From 3e9e54a585751c2d9d106fdc9441bf40f8b180e2 Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Tue, 12 Nov 2024 21:49:36 -0300 Subject: [PATCH 5/6] qcom-qcs6490: add qcom-gen-partition-bins to EXTRA_IMAGEDEPENDS Add qcom-gen-partition-bins to EXTRA_IMAGEDEPENDS in order to build and deploy all the machine specific partition binaries which are required for flashing the device. Signed-off-by: Ricardo Salveti --- conf/machine/include/qcom-qcs6490.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/machine/include/qcom-qcs6490.inc b/conf/machine/include/qcom-qcs6490.inc index 07dbb872..de38708b 100644 --- a/conf/machine/include/qcom-qcs6490.inc +++ b/conf/machine/include/qcom-qcs6490.inc @@ -9,4 +9,4 @@ require conf/machine/include/arm/arch-armv8-2a.inc KERNEL_CMDLINE_EXTRA ?= "pcie_pme=nomsi earlycon" -EXTRA_IMAGEDEPENDS += "firmware-qcom-boot-qcs6490" +EXTRA_IMAGEDEPENDS += "firmware-qcom-boot-qcs6490 qcom-gen-partition-bins" From 38072acc8e4affb32fb091ed937d15a86fffb42c Mon Sep 17 00:00:00 2001 From: Ricardo Salveti Date: Tue, 12 Nov 2024 21:51:29 -0300 Subject: [PATCH 6/6] qcom-qcs9100: add qcom-gen-partition-bins to EXTRA_IMAGEDEPENDS Add qcom-gen-partition-bins to EXTRA_IMAGEDEPENDS in order to build and deploy all the machine specific partition binaries which are required for flashing the device. Signed-off-by: Ricardo Salveti --- conf/machine/include/qcom-qcs9100.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conf/machine/include/qcom-qcs9100.inc b/conf/machine/include/qcom-qcs9100.inc index 6abd6f16..0fa6abe4 100644 --- a/conf/machine/include/qcom-qcs9100.inc +++ b/conf/machine/include/qcom-qcs9100.inc @@ -8,3 +8,5 @@ DEFAULTTUNE = "armv8-2a-crypto" require conf/machine/include/arm/arch-armv8-2a.inc KERNEL_CMDLINE_EXTRA ?= "pci=noaer pcie_pme=nomsi earlycon" + +EXTRA_IMAGEDEPENDS += "qcom-gen-partition-bins"