2 #============================================================================
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
24 from binascii
import crc32
25 from optparse
import OptionParser
29 def UpdateMBR(options
, GPTBlobBuffer
):
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
45 GPTBlobBuffer
[510:512] = [0x55, 0xAA]
49 def UpdatePartitionEntry(options
, GPTBlobBuffer
):
51 i
= 2 * options
.sector_size
53 GPTBlobBuffer
[i
:i
+ 16] = [0x2c, 0xba, 0xa0, 0xde, 0xdd, 0xcb, 0x05, 0x48,
54 0xb4, 0xf9, 0xf4, 0x28, 0x25, 0x1c, 0x3e, 0x98]
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]
62 # LBA of BootBlock Start Content
63 GPTBlobBuffer
[i
:i
+ 8] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
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
78 GPTBlobBuffer
[i
:i
+ 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
82 GPTBlobBuffer
[i
:i
+ 17] = [0x62, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00,
83 0x62, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x6b]
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
92 GPTBlobBuffer
[i
:i
+ 16] = [0x45, 0x46, 0x49, 0x20, 0x50, 0x41, 0x52, 0x54,
93 0x00, 0x00, 0x01, 0x00, 0x5C, 0x00, 0x00, 0x00]
96 # CRC is zeroed out till calculated later
97 GPTBlobBuffer
[i
:i
+ 4] = [0x00, 0x00, 0x00, 0x00]
101 GPTBlobBuffer
[i
:i
+ 4] = [0x00, 0x00, 0x00, 0x00]
105 GPTBlobBuffer
[i
:i
+ 8] = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
108 # Backup LBA, No Backup Gpt Used
109 GPTBlobBuffer
[i
:i
+ 8] = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
112 # First Usuable LBA (qc_sec + bootblock location)
113 GPTBlobBuffer
[i
:i
+ 8] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
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
128 GPTBlobBuffer
[i
:i
+ 16] = [0x32,0x1B,0x10,0x98,0xE2,0xBB,0xF2,0x4B,
129 0xA0,0x6E,0x2B,0xB3,0x3D,0x00,0x0C,0x20]
132 # Partition Table Entry LBA
133 GPTBlobBuffer
[i
:i
+ 8] = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
136 # Number of Partition Entries
137 GPTBlobBuffer
[i
:i
+ 4] = [0x01, 0x00, 0x00, 0x00]
140 # Size of One Partition Entry
141 GPTBlobBuffer
[i
:i
+ 4] = [0x80, 0x00, 0x00, 0x00]
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
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
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)]',
176 (options
, args
) = parser
.parse_args()
178 print("Invalid arguments! Exiting...\n")
182 if options
.sector_size
!= 4096 and options
.sector_size
!= 512:
183 print("Invalid Sector Size")
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) //
195 # Add 3 sectors for MBR, GPT header and GPT partition entry
197 # Subtract one because this is last usable LBA, not amount of LBAs
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
)