6
6
Copyright (C) 2014-2018 Plato Mavropoulos
7
7
"""
8
8
9
- title = 'ME Analyzer v1.46.1 '
9
+ title = 'ME Analyzer v1.48.0 '
10
10
11
11
import os
12
12
import re
@@ -3059,8 +3059,8 @@ def cse_unpack(fpt_part_all, bpdt_part_all, fw_type, file_end, fpt_start, fpt_ch
3059
3059
3060
3060
print (col_y + '\n --> Stored $FPT %s Partition "%s" [0x%0.6X - 0x%0.6X]' % (part_type , part_name , part_start , part_end ) + col_e )
3061
3061
3062
- if part [0 ] in [b'UTOK' ,b'STKN' , b'OEMP' ] :
3063
- ext_print ,x1 = key_anl (mod_fname , [], part_name , [variant , major , minor , hotfix , build ]) # Retrieve & Store UTOK/STKN/OEMP Extension Info
3062
+ if part [0 ] in [b'UTOK' ,b'STKN' ] :
3063
+ ext_print ,x1 = key_anl (mod_fname , [], part_name , [variant , major , minor , hotfix , build ]) # Retrieve & Store UTOK/STKN Extension Info
3064
3064
3065
3065
# Print Manifest/Metadata/Key Extension Info
3066
3066
for index in range (0 , len (ext_print ), 2 ) : # Only Name (index), skip Info (index + 1)
@@ -3120,8 +3120,8 @@ def cse_unpack(fpt_part_all, bpdt_part_all, fw_type, file_end, fpt_start, fpt_ch
3120
3120
3121
3121
print (col_y + '\n --> Stored BPDT %s Partition "%s" [0x%0.6X - 0x%0.6X]' % (part_order , part_name , part_start , part_end ) + col_e )
3122
3122
3123
- if part [0 ] in ['UTOK' , 'OEMP' ] :
3124
- ext_print ,x1 = key_anl (mod_fname , [], part_name , [variant , major , minor , hotfix , build ]) # Retrieve & Store UTOK/OEMP Extension Info
3123
+ if part [0 ] in ['UTOK' ] :
3124
+ ext_print ,x1 = key_anl (mod_fname , [], part_name , [variant , major , minor , hotfix , build ]) # Retrieve & Store UTOK Extension Info
3125
3125
3126
3126
# Print Manifest/Metadata/Key Extension Info
3127
3127
for index in range (0 , len (ext_print ), 2 ) : # Only Name (index), skip Info (index + 1)
@@ -3305,7 +3305,7 @@ def ext_anl(input_type, input_offset, file_end, var_ver) :
3305
3305
hdr_rev_tag = '' # CSE Extension Header Revision Tag
3306
3306
mod_rev_tag = '' # CSE Extension Module Revision Tag
3307
3307
3308
- if ((variant ,major ) == ('CSME' ,12 ) and ( minor ,hotfix , build ) not in [ (0 ,0 , 7070 ),( 0 , 0 , 7075 )] ) or dnx_version == 2 :
3308
+ if ((variant ,major ) == ('CSME' ,12 ) and not (( minor ,hotfix ) == (0 ,0 ) and build >= 7000 ) ) or dnx_version == 2 :
3309
3309
if ext_tag in ext_tag_rev_hdr : hdr_rev_tag = '_R2'
3310
3310
if ext_tag in ext_tag_rev_mod : mod_rev_tag = '_R2'
3311
3311
else :
@@ -4225,7 +4225,7 @@ def key_anl(mod_fname, ext_print, mod_name, var_ver) :
4225
4225
hdr_rev_tag = '' # CSE Extension Header Revision Tag
4226
4226
mod_rev_tag = '' # CSE Extension Module Revision Tag
4227
4227
4228
- if (variant ,major ) == ('CSME' ,12 ) and ( minor ,hotfix , build ) not in [ (0 ,0 , 7070 ),( 0 , 0 , 7075 )] :
4228
+ if (variant ,major ) == ('CSME' ,12 ) and not (( minor ,hotfix ) == (0 ,0 ) and build >= 7000 ) :
4229
4229
if ext_tag in ext_tag_rev_hdr : hdr_rev_tag = '_R2'
4230
4230
if ext_tag in ext_tag_rev_mod : mod_rev_tag = '_R2'
4231
4231
else :
@@ -4610,6 +4610,7 @@ def uefi_find(file_in, uf_path) :
4610
4610
header count 0C111D82A3D0F74CAEF3E28088491704 {0}\n \
4611
4611
header count 6E1F582C87B1AA4696E72081098D6413 {0}\n \
4612
4612
header count 8226C7591C5C22479F25B26F4275BFEF {0}\n \
4613
+ header count 9D3EF263DA5F5E419C2A64C4E2A6ECE8 {0}\n \
4613
4614
" .format (file_in ).replace (' ' , '' )
4614
4615
4615
4616
try :
@@ -4693,15 +4694,16 @@ def fovd_clean(fovdtype) :
4693
4694
def fw_types (fw_type ) :
4694
4695
type_db = 'NaN'
4695
4696
4696
- if variant in ['SPS' ,'CSSPS' ] and (fw_type == "Region" or fw_type == "Region, Stock" or fw_type == "Region, Extracted" ) : # SPS --> Region (EXTR at DB)
4697
- fw_type = "Region"
4698
- type_db = "EXTR"
4699
- elif fw_type == "Region, Extracted" : type_db = "EXTR"
4700
- elif fw_type == "Region, Stock" or fw_type == "Region" : type_db = "RGN"
4701
- elif fw_type == "Update" : type_db = "UPD"
4702
- elif fw_type == "Operational" : type_db = "OPR"
4703
- elif fw_type == "Recovery" : type_db = "REC"
4704
- elif fw_type == "Unknown" : type_db = "UNK"
4697
+ if variant in ['SPS' ,'CSSPS' ] and fw_type in ['Region' ,'Region, Stock' ,'Region, Extracted' ] : # SPS --> Region (EXTR at DB)
4698
+ fw_type = 'Region'
4699
+ type_db = 'EXTR'
4700
+ elif fw_type == 'Region, Extracted' : type_db = 'EXTR'
4701
+ elif fw_type == 'Region, FWUpdate' : type_db = 'FWU'
4702
+ elif fw_type == 'Region, Stock' or fw_type == 'Region' : type_db = 'RGN'
4703
+ elif fw_type == 'Update' : type_db = 'UPD'
4704
+ elif fw_type == 'Operational' : type_db = 'OPR'
4705
+ elif fw_type == 'Recovery' : type_db = 'REC'
4706
+ elif fw_type == 'Unknown' : type_db = 'UNK'
4705
4707
4706
4708
return fw_type , type_db
4707
4709
@@ -5103,6 +5105,7 @@ def mass_scan(f_path) :
5103
5105
me11_sku_anl = False
5104
5106
me11_ker_msg = False
5105
5107
can_search_db = True
5108
+ fpt_chk_null = False
5106
5109
fpt_chk_fail = False
5107
5110
fpt_num_fail = False
5108
5111
cse_lt_exist = False
@@ -5473,7 +5476,7 @@ def mass_scan(f_path) :
5473
5476
else :
5474
5477
p_empty = 'No'
5475
5478
5476
- if p_empty == 'No' :
5479
+ if p_empty == 'No' and p_offset_spi < file_end :
5477
5480
# Get CSE Partition Instance ID
5478
5481
cse_in_id ,x1 ,x2 = cse_part_inid (reading , p_offset_spi , ext_dict )
5479
5482
cse_in_id_str = '%0.4X' % cse_in_id
@@ -5517,11 +5520,11 @@ def mass_scan(f_path) :
5517
5520
fpt_romb_found = True
5518
5521
if p_offset_spi != 0 and p_size != 0 : fpt_romb_used = True
5519
5522
5520
- # CSME12+ FWUpdate tool requires PMC firmware (PMCP, EXTR not RGN )
5523
+ # CSME12+ FWUpdate tool requires PMC firmware (PMCP)
5521
5524
if p_name == 'PMCP' and p_empty == 'No' : fwu_pmcp_found = True
5522
5525
5523
- # Detect if CSE firmware has OEM/ODM Unlock Token (UTOK/STKN/OEMP )
5524
- if p_name in ('UTOK' ,'STKN' , 'OEMP' ) and reading [p_offset_spi :p_offset_spi + 0x10 ] != b'\xFF ' * 0x10 : utok_found = True
5526
+ # Detect if CSE firmware has OEM/ODM Unlock Token (UTOK/STKN)
5527
+ if p_name in ('UTOK' ,'STKN' ) and p_offset_spi < file_end and reading [p_offset_spi :p_offset_spi + 0x10 ] != b'\xFF ' * 0x10 : utok_found = True
5525
5528
5526
5529
if 0 < p_offset_spi < p_max_size and 0 < p_size < p_max_size : eng_fw_end = p_offset_spi + p_size
5527
5530
else : eng_fw_end = p_max_size
@@ -5609,7 +5612,7 @@ def mass_scan(f_path) :
5609
5612
if p_type in bpdt_dict : p_name = bpdt_dict [p_type ]
5610
5613
else : p_name = 'Unknown'
5611
5614
5612
- if p_empty == 'No' :
5615
+ if p_empty == 'No' and p_offset_spi < file_end :
5613
5616
# Get CSE Partition Instance ID
5614
5617
cse_in_id ,x1 ,x2 = cse_part_inid (reading , p_offset_spi , ext_dict )
5615
5618
@@ -5626,7 +5629,7 @@ def mass_scan(f_path) :
5626
5629
5627
5630
pt_dbpdt .add_row ([p_name ,'%0.2d' % p_type ,'Primary' ,p_offset_print ,p_size_print ,p_end_print ,'%0.4X' % cse_in_id ,p_empty ])
5628
5631
5629
- if p_type == 5 and p_empty == 'No' : # Secondary BPDT (S-BPDT)
5632
+ if p_type == 5 and p_empty == 'No' and p_offset_spi < file_end : # Secondary BPDT (S-BPDT)
5630
5633
init_s_bpdt_ver = int .from_bytes (reading [start_fw_start_match + 0x6 :start_fw_start_match + 0x8 ], 'little' ) # BPDT Version
5631
5634
if init_s_bpdt_ver == 2 : s_bpdt_hdr = get_struct (reading , p_offset_spi , BPDT_Header_2 )
5632
5635
else : s_bpdt_hdr = get_struct (reading , p_offset_spi , BPDT_Header )
@@ -5683,7 +5686,7 @@ def mass_scan(f_path) :
5683
5686
bpdt_part_all .append ([p_name , p_offset_spi , p_offset_spi + p_size , p_type , p_empty , 'Primary' , cse_in_id ])
5684
5687
5685
5688
# Adjust Manifest Header to Recovery section based on BPDT
5686
- if p_type == 2 and p_empty == 'No' : # CSE_BUP
5689
+ if p_type == 2 and p_empty == 'No' and p_offset_spi < file_end : # CSE_BUP
5687
5690
# Only if partition exists at file (counter-example: sole IFWI etc)
5688
5691
# noinspection PyTypeChecker
5689
5692
if p_offset_spi + p_size <= file_end :
@@ -5699,9 +5702,9 @@ def mass_scan(f_path) :
5699
5702
# Show BPDT Partition info on demand (-dfpt)
5700
5703
if param .fpt_disp : print ('%s\n ' % pt_dbpdt )
5701
5704
5702
- # Detect if CSE firmware has OEM/ODM Unlock Token (UTOK/STKN/OEMP )
5705
+ # Detect if CSE firmware has OEM/ODM Unlock Token (UTOK/STKN)
5703
5706
for part in bpdt_part_all :
5704
- if part [0 ] in ('UTOK' ,'STKN' , 'OEMP' ) and reading [part [1 ]:part [1 ] + 0x10 ] != b'\xFF ' * 0x10 : utok_found = True
5707
+ if part [0 ] in ('UTOK' ,'STKN' ) and reading [part [1 ]:part [1 ] + 0x10 ] != b'\xFF ' * 0x10 : utok_found = True
5705
5708
5706
5709
# Detect BPDT partition overlaps
5707
5710
for part in bpdt_part_all :
@@ -5757,8 +5760,10 @@ def mass_scan(f_path) :
5757
5760
fpt_chk_calc = '0x%0.2X' % ((0x100 - chk_sum & 0xFF ) & 0xFF )
5758
5761
if fpt_chk_calc != fpt_chk_file : fpt_chk_fail = True
5759
5762
5760
- # CSME12+, CSTXE3+, CSSPS5+ EXTR checksum from FIT is a placeholder (0x00), ignore
5761
- if fpt_chk_fail and fpt_chk_file == '0x00' and variant in ['CSME' ,'CSTXE' ,'CSSPS' ] : fpt_chk_fail = False
5763
+ # CSME12+ & CSTXE EXTR checksum from FIT is a placeholder (0x00), ignore
5764
+ if ((variant == 'CSME' and major >= 12 ) or variant == 'CSTXE' ) and fpt_chk_file == '0x00' :
5765
+ fpt_chk_null = True
5766
+ fpt_chk_fail = False
5762
5767
5763
5768
# Check SPS3 $FPT Checksum validity (from Lordkag's UEFIStrip)
5764
5769
if variant == 'SPS' and major == 3 :
@@ -6013,7 +6018,7 @@ def mass_scan(f_path) :
6013
6018
elif rgn_exist : # SPS 1-3 have their own firmware Types
6014
6019
if variant == 'SPS' : fw_type = 'Region' # SPS is built manually so EXTR
6015
6020
elif variant == 'ME' and (2 <= major <= 7 ) :
6016
- # Check 1, FOVD section
6021
+ # Check 1, FOVD partition
6017
6022
if (major > 2 and not fovd_clean ('new' )) or (major == 2 and not fovd_clean ('old' )) : fw_type = 'Region, Extracted'
6018
6023
else :
6019
6024
# Check 2, EFFS/NVKR strings
@@ -6023,12 +6028,16 @@ def mass_scan(f_path) :
6023
6028
else : fw_type = 'Region, Extracted'
6024
6029
elif major in [2 ,3 ] : fw_type_fix = True # ME2-Only Fix 1, ME3-Only Fix 1
6025
6030
else : fw_type = 'Region, Stock'
6026
- elif (variant in [ 'ME' , 'CSME' ] and 8 <= major <= 12 ) or variant == 'TXE' or ( variant == ' CSSPS' and major == 4 ) :
6031
+ elif (variant == 'ME' and major >= 8 ) or variant in [ 'CSME' , 'CSTXE' , ' CSSPS', 'TXE' ] :
6027
6032
# Check 1, FITC Version
6028
- if fpt_hdr .FitBuild == 0 or fpt_hdr . FitBuild == 65535 : # 0000/FFFF --> clean ME/ TXE
6033
+ if fpt_hdr .FitBuild in [ 0 , 65535 ] : # 0000/FFFF --> clean CS(ME)/CS( TXE)
6029
6034
fw_type = 'Region, Stock'
6030
- # Check 2, FOVD section
6035
+
6036
+ # Check 2, FOVD partition
6031
6037
if not fovd_clean ('new' ) : fw_type = 'Region, Extracted'
6038
+
6039
+ # Check 3, CSTXE FIT temporarily/placeholder $FPT Header and Checksum
6040
+ if reading [fpt_start :fpt_start + 0x10 ] + reading [fpt_start + 0x1C :fpt_start + 0x30 ] == b'\xFF ' * 0x24 : fw_type = 'Region, Extracted'
6032
6041
else :
6033
6042
# Get FIT/FITC version used to build the image
6034
6043
fitc_ver_found = True
@@ -6037,11 +6046,9 @@ def mass_scan(f_path) :
6037
6046
fitc_minor = fpt_hdr .FitMinor
6038
6047
fitc_hotfix = fpt_hdr .FitHotfix
6039
6048
fitc_build = fpt_hdr .FitBuild
6040
- elif variant == 'CSME' or variant == 'CSTXE' or variant == 'CSSPS' :
6041
- # Extracted are created by FIT temporarily, placeholder $FPT header and checksum
6042
- if reading [fpt_start :fpt_start + 0x10 ] + reading [fpt_start + 0x1C :fpt_start + 0x30 ] + \
6043
- reading [fpt_start + 0x1B :fpt_start + 0x1C ] == b'\xFF ' * 0x24 + b'\x00 ' : fw_type = 'Region, Extracted'
6044
- else : fw_type = 'Region, Stock'
6049
+
6050
+ # Check 4, CSME12+ FIT FWUpdate image
6051
+ if reading [fpt_start :fpt_start + 0x10 ] == b'\xFF ' * 0x10 and fwu_pmcp_found and not fpt_chk_null : fw_type = 'Region, FWUpdate'
6045
6052
else :
6046
6053
fw_type = 'Update' # No Region detected, Update
6047
6054
@@ -6058,7 +6065,6 @@ def mass_scan(f_path) :
6058
6065
# Detect Firmware Release (Production, Pre-Production, ROM-Bypass, Other)
6059
6066
mn2_flags_pvbit ,mn2_flags_reserved ,mn2_flags_pre ,mn2_flags_debug = mn2_ftpr_hdr .get_flags ()
6060
6067
rel_signed = ['Production' , 'Debug' ][mn2_flags_debug ]
6061
- #rel_flag = ['PRD', 'PRE'][mn2_flags_pre] # Set only at ME9-10
6062
6068
6063
6069
# Check for ROM-Bypass entry at $FPT
6064
6070
if rgn_exist and fpt_romb_found :
@@ -6857,6 +6863,7 @@ def mass_scan(f_path) :
6857
6863
name_db = "%s.%s.%s.%s_%s_%s_%s" % (major , minor , hotfix , build , sku_db , rel_db , type_db ) # The re-created filename without extension
6858
6864
name_db_rgn = "%s.%s.%s.%s_%s_%s_RGN_%s" % (major , minor , hotfix , build , sku_db , rel_db , rsa_sig_hash ) # The equivalent RGN filename
6859
6865
name_db_extr = "%s.%s.%s.%s_%s_%s_EXTR_%s" % (major , minor , hotfix , build , sku_db , rel_db , rsa_sig_hash ) # The equivalent EXTR filename
6866
+ name_db_fwu = "%s.%s.%s.%s_%s_%s_FWU_%s" % (major , minor , hotfix , build , sku_db , rel_db , rsa_sig_hash ) # The equivalent FWU filename
6860
6867
elif variant in ['CSSPS' ,'SPS' ] and sku != 'NaN' :
6861
6868
name_db = "%s.%s.%s.%s_%s_%s_%s" % ("{0:02d}" .format (major ), "{0:02d}" .format (minor ), "{0:02d}" .format (hotfix ), "{0:03d}" .format (build ), sku_db , rel_db , type_db )
6862
6869
name_db_rgn = "%s.%s.%s.%s_%s_%s_RGN_%s" % ("{0:02d}" .format (major ), "{0:02d}" .format (minor ), "{0:02d}" .format (hotfix ), "{0:03d}" .format (build ), sku_db , rel_db , rsa_sig_hash )
@@ -6881,9 +6888,10 @@ def mass_scan(f_path) :
6881
6888
if len (line ) < 2 or line [:3 ] == '***' :
6882
6889
continue # Skip empty lines or comments
6883
6890
else : # Search the re-created file name without extension at the database
6884
- if name_db_hash in line : fw_in_db_found = "Yes" # Known firmware, nothing new
6885
- if type_db == 'EXTR' and name_db_rgn in line :
6886
- rgn_over_extr_found = True # Same firmware found at database but RGN instead of imported EXTR, so nothing new
6891
+ if name_db_hash in line : fw_in_db_found = 'Yes' # Known firmware, nothing new
6892
+ if (type_db == 'EXTR' and (name_db_rgn in line or (variant == 'CSME' and major >= 12 and name_db_fwu in line ))) or \
6893
+ (type_db == 'FWU' and name_db_rgn in line ) :
6894
+ rgn_over_extr_found = True # Same firmware found but of preferred type (RGN > FWU > EXTR), nothing new
6887
6895
fw_in_db_found = 'Yes'
6888
6896
# Only for ME8+ or ME7 non-PRD or ME6.0 IGN
6889
6897
if type_db == 'UPD' and ((variant in ['ME' ,'CSME' ] and (major > 7 or (major == 7 and release != 'Production' ) or
0 commit comments