security/intel/stm/Makefile.inc: Fix typo
[coreboot.git] / util / qualcomm / qgpt.py
bloba4cdf690b482c1e5a3ec3c34d94ed1c1b5d28113
1 #!/usr/bin/env python3
2 #============================================================================
4 #/** @file qgpt.py
6 # GENERAL DESCRIPTION
7 # Generates QCom GPT header for wrapping Bootblock
9 # Copyright (c) 2018, The Linux Foundation. All rights reserved.
11 # SPDX-License-Identifier: BSD-3-Clause
13 #**/
16 import os
17 import math
18 import random
19 import re
20 import struct
21 import sys
22 import tempfile
24 from binascii import crc32
25 from optparse import OptionParser
26 from types import *
29 def UpdateMBR(options, GPTBlobBuffer):
30 i = 0x1BE
31 GPTBlobBuffer[i + 0] = 0x00 # not bootable
32 GPTBlobBuffer[i + 1] = 0x00 # head
33 GPTBlobBuffer[i + 2] = 0x01 # sector
34 GPTBlobBuffer[i + 3] = 0x00 # cylinder
35 GPTBlobBuffer[i + 4] = 0xEE # type
36 GPTBlobBuffer[i + 5] = 0xFF # head
37 GPTBlobBuffer[i + 6] = 0xFF # sector
38 GPTBlobBuffer[i + 7] = 0xFF # cylinder
39 GPTBlobBuffer[i + 8:i + 8 + 4] = [0x01, 0x00, 0x00, 0x00]
41 GPTBlobBuffer[i + 12:i + 16] = [0x00, 0x0f, 0x00, 0x00]
43 # magic byte for MBR partitioning - always at this location regardless of
44 # options.sector
45 GPTBlobBuffer[510:512] = [0x55, 0xAA]
46 return i
49 def UpdatePartitionEntry(options, GPTBlobBuffer):
51 i = 2 * options.sector_size
52 # GUID of Boot Block
53 GPTBlobBuffer[i:i + 16] = [0x2c, 0xba, 0xa0, 0xde, 0xdd, 0xcb, 0x05, 0x48,
54 0xb4, 0xf9, 0xf4, 0x28, 0x25, 0x1c, 0x3e, 0x98]
55 i += 16
57 #This is to set Unique Partition GUID. Below Hex Value is : 00ChezaBootblock00
58 GPTBlobBuffer[i:i + 16] = [0x00, 0x43, 0x68, 0x65, 0x7a, 0x61, 0x42, 0x6f,
59 0x6f, 0x74, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x00]
60 i += 16
62 # LBA of BootBlock Start Content
63 GPTBlobBuffer[i:i + 8] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
64 i += 8
66 # End LBA of BootBlock Content
67 GPTBlobBuffer[i] = options.end_lba & 0xFF
68 GPTBlobBuffer[i+1] = (options.end_lba>>8) & 0xFF
69 GPTBlobBuffer[i+2] = (options.end_lba>>16) & 0xFF
70 GPTBlobBuffer[i+3] = (options.end_lba>>24) & 0xFF
71 GPTBlobBuffer[i+4] = (options.end_lba>>32) & 0xFF
72 GPTBlobBuffer[i+5] = (options.end_lba>>40) & 0xFF
73 GPTBlobBuffer[i+6] = (options.end_lba>>48) & 0xFF
74 GPTBlobBuffer[i+7] = (options.end_lba>>56) & 0xFF
75 i += 8
77 # Attributes
78 GPTBlobBuffer[i:i + 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
79 i += 8
81 # Label
82 GPTBlobBuffer[i:i + 17] = [0x62, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00,
83 0x62, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x6b]
85 return i
87 def UpdateGPTHeader(options, GPTBlobBuffer):
89 i = options.sector_size
90 # Signature and Revision and HeaderSize i.e. "EFI PART" and 00 00 01 00
91 # and 5C 00 00 00
92 GPTBlobBuffer[i:i + 16] = [0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54,
93 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00]
94 i += 16
96 # CRC is zeroed out till calculated later
97 GPTBlobBuffer[i:i + 4] = [0x00, 0x00, 0x00, 0x00]
98 i += 4
100 # Reserved, set to 0
101 GPTBlobBuffer[i:i + 4] = [0x00, 0x00, 0x00, 0x00]
102 i += 4
104 # Current LBA
105 GPTBlobBuffer[i:i + 8] = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
106 i += 8
108 # Backup LBA, No Backup Gpt Used
109 GPTBlobBuffer[i:i + 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
110 i += 8
112 # First Usuable LBA (qc_sec + bootblock location)
113 GPTBlobBuffer[i:i + 8] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
114 i += 8
116 # Last Usuable LBA (qc_sec + bootblock end location)
117 GPTBlobBuffer[i] = options.end_lba & 0xFF
118 GPTBlobBuffer[i+1] = (options.end_lba>>8) & 0xFF
119 GPTBlobBuffer[i+2] = (options.end_lba>>16) & 0xFF
120 GPTBlobBuffer[i+3] = (options.end_lba>>24) & 0xFF
121 GPTBlobBuffer[i+4] = (options.end_lba>>32) & 0xFF
122 GPTBlobBuffer[i+5] = (options.end_lba>>40) & 0xFF
123 GPTBlobBuffer[i+6] = (options.end_lba>>48) & 0xFF
124 GPTBlobBuffer[i+7] = (options.end_lba>>56) & 0xFF
125 i += 8
127 # GUID
128 GPTBlobBuffer[i:i + 16] = [0x32,0x1B,0x10,0x98,0xE2,0xBB,0xF2,0x4B,
129 0xA0,0x6E,0x2B,0xB3,0x3D,0x00,0x0C,0x20]
130 i += 16
132 # Partition Table Entry LBA
133 GPTBlobBuffer[i:i + 8] = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
134 i += 8
136 # Number of Partition Entries
137 GPTBlobBuffer[i:i + 4] = [0x01, 0x00, 0x00, 0x00]
138 i += 4
140 # Size of One Partition Entry
141 GPTBlobBuffer[i:i + 4] = [0x80, 0x00, 0x00, 0x00]
142 i += 4
144 # CRC of Partition Entry
146 PartEntry = GPTBlobBuffer[options.sector_size*2:options.sector_size*2 + 128]
147 CalcEntryCRC = crc32(b''.join(struct.pack("B", x) for x in PartEntry))
149 GPTBlobBuffer[i] = CalcEntryCRC & 0xFF
150 GPTBlobBuffer[i+1] = (CalcEntryCRC>>8) & 0xFF
151 GPTBlobBuffer[i+2] = (CalcEntryCRC>>16) & 0xFF
152 GPTBlobBuffer[i+3] = (CalcEntryCRC>>24) & 0xFF
153 i += 4
155 # CRC of Partition Table Header
156 GPTHeader = GPTBlobBuffer[options.sector_size:options.sector_size + 92]
157 CalcEntryCRC = crc32(b''.join(struct.pack("B", x) for x in GPTHeader))
158 i = options.sector_size + 16
160 GPTBlobBuffer[i] = CalcEntryCRC & 0xFF
161 GPTBlobBuffer[i+1] = (CalcEntryCRC>>8) & 0xFF
162 GPTBlobBuffer[i+2] = (CalcEntryCRC>>16) & 0xFF
163 GPTBlobBuffer[i+3] = (CalcEntryCRC>>24) & 0xFF
165 return i
168 if __name__ == '__main__':
169 usage = 'usage: %prog [OPTIONS] INFILE OUTFILE\n\n' + \
170 'Packages IMAGE in a GPT format.'
171 parser = OptionParser(usage)
172 parser.add_option('-s', type="int", dest='sector_size', default=4096,
173 help='Sector size in bytes [Default:4096(4KB)]',
174 metavar='SIZE')
176 (options, args) = parser.parse_args()
177 if len(args) != 2:
178 print("Invalid arguments! Exiting...\n")
179 parser.print_help()
180 sys.exit(1)
182 if options.sector_size != 4096 and options.sector_size != 512:
183 print("Invalid Sector Size")
184 sys.exit(1)
186 options.inputfile = args[0]
187 options.outputfile = args[1]
189 with open(options.inputfile, 'rb+') as fin:
190 bb_buffer = fin.read()
192 # Round up to next sector if bootblock size not evenly divisible
193 options.end_lba = ((len(bb_buffer) + options.sector_size - 1) //
194 options.sector_size)
195 # Add 3 sectors for MBR, GPT header and GPT partition entry
196 options.end_lba += 3
197 # Subtract one because this is last usable LBA, not amount of LBAs
198 options.end_lba -= 1
200 GPTBlobBuffer = [0] * (options.sector_size*3) #Size of MBR+GPT+PART_ENTRY
202 UpdateMBR(options, GPTBlobBuffer)
204 UpdatePartitionEntry(options, GPTBlobBuffer)
206 UpdateGPTHeader(options, GPTBlobBuffer)
208 with open(options.outputfile, 'wb') as fout:
209 for b in GPTBlobBuffer:
210 fout.write(struct.pack("B", b))
211 fout.write(bb_buffer)