2016-10-10 14:05:04 +08:00
/* nvramparser.cpp
2022-08-28 18:47:01 +08:00
Copyright ( c ) 2016 , Nikolaj Schlej . All rights reserved .
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution . The full text of the license may be found at
http : //opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN " AS IS " BASIS ,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND , EITHER EXPRESS OR IMPLIED .
*/
2016-10-10 14:05:04 +08:00
2023-02-20 04:24:20 +08:00
# ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
2016-11-03 03:40:38 +08:00
# include <map>
2016-10-10 14:05:04 +08:00
# include "nvramparser.h"
# include "parsingdata.h"
2023-02-20 04:24:20 +08:00
# include "ustring.h"
2016-10-10 14:05:04 +08:00
# include "utility.h"
# include "nvram.h"
# include "ffs.h"
2022-08-29 14:23:38 +08:00
# include "intel_microcode.h"
2016-10-10 14:05:04 +08:00
2023-02-20 04:24:20 +08:00
# include "umemstream.h"
# include "kaitai/kaitaistream.h"
# include "generated/ami_nvar.h"
2016-10-10 14:05:04 +08:00
USTATUS NvramParser : : parseNvarStore ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2023-02-20 04:24:20 +08:00
UByteArray nvar = model - > body ( index ) ;
// Nothing to parse in an empty store
if ( nvar . isEmpty ( ) )
return U_SUCCESS ;
try {
const UINT32 localOffset = ( UINT32 ) model - > header ( index ) . size ( ) ;
umemstream is ( nvar . constData ( ) , nvar . size ( ) ) ;
kaitai : : kstream ks ( & is ) ;
ami_nvar_t parsed ( & ks ) ;
UINT16 guidsInStore = 0 ;
UINT32 currentEntryIndex = 0 ;
for ( const auto & entry : * parsed . entries ( ) ) {
UINT8 subtype = Subtypes : : FullNvarEntry ;
UString name ;
UString text ;
UString info ;
UString guid ;
UByteArray header ;
UByteArray body ;
UByteArray tail ;
// This is a terminating entry, needs special processing
if ( entry - > _is_null_signature_rest ( ) ) {
UINT32 guidAreaSize = guidsInStore * sizeof ( EFI_GUID ) ;
UINT32 unparsedSize = ( UINT32 ) nvar . size ( ) - entry - > offset ( ) - guidAreaSize ;
// Check if the data left is a free space or a padding
UByteArray padding = nvar . mid ( entry - > offset ( ) , unparsedSize ) ;
// Get info
UString info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) padding . size ( ) , ( UINT32 ) padding . size ( ) ) ;
if ( ( UINT32 ) padding . count ( 0xFF ) = = unparsedSize ) { // Free space
// Add tree item
model - > addItem ( localOffset + entry - > offset ( ) , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
else {
// Nothing is parsed yet, but the file is not empty
if ( entry - > offset ( ) = = 0 ) {
msg ( usprintf ( " %s: file can't be parsed as NVAR variable store " , __FUNCTION__ ) , index ) ;
return U_SUCCESS ;
}
// Add tree item
model - > addItem ( localOffset + entry - > offset ( ) , Types : : Padding , getPaddingType ( padding ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
}
// Add GUID store area
UByteArray guidArea = nvar . right ( guidAreaSize ) ;
// Get info
name = UString ( " GUID store " ) ;
info = usprintf ( " Full size: %Xh (%u) \n GUIDs in store: %u " ,
( UINT32 ) guidArea . size ( ) , ( UINT32 ) guidArea . size ( ) ,
guidsInStore ) ;
2016-10-28 00:31:15 +08:00
// Add tree item
2023-02-20 04:24:20 +08:00
model - > addItem ( ( UINT32 ) ( localOffset + entry - > offset ( ) + padding . size ( ) ) , Types : : NvarGuidStore , 0 , name , UString ( ) , info , UByteArray ( ) , guidArea , UByteArray ( ) , Fixed , index ) ;
return U_SUCCESS ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
// This is a normal entry
const auto entry_body = entry - > body ( ) ;
// Set default next to predefined last value
NVAR_ENTRY_PARSING_DATA pdata = { } ;
pdata . emptyByte = 0xFF ;
pdata . next = 0xFFFFFF ;
pdata . isValid = TRUE ;
// Check for invalid entry
if ( ! entry - > attributes ( ) - > valid ( ) ) {
subtype = Subtypes : : InvalidNvarEntry ;
name = UString ( " Invalid " ) ;
pdata . isValid = FALSE ;
goto processing_done ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
// Check for link entry
if ( entry - > next ( ) ! = 0xFFFFFF ) {
subtype = Subtypes : : LinkNvarEntry ;
pdata . next = ( UINT32 ) entry - > next ( ) ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
// Check for data-only entry (nameless and GUIDless entry or link)
if ( entry - > attributes ( ) - > data_only ( ) ) {
// Search backwards for a previous entry with a link to this variable
UModelIndex prevEntryIndex ;
if ( currentEntryIndex > 0 ) {
for ( UINT32 i = currentEntryIndex - 1 ; i > 0 ; i - - ) {
2023-02-27 05:23:25 +08:00
const auto & previousEntry = parsed . entries ( ) - > at ( i ) ;
2023-02-20 04:24:20 +08:00
if ( previousEntry = = entry )
break ;
2023-02-20 04:38:35 +08:00
if ( ( UINT32 ) previousEntry - > next ( ) + ( UINT32 ) previousEntry - > offset ( ) = = ( UINT32 ) entry - > offset ( ) ) { // Previous link is present and valid
2023-02-20 04:24:20 +08:00
prevEntryIndex = index . model ( ) - > index ( i , 0 , index ) ;
// Make sure that we are linking to a valid entry
NVAR_ENTRY_PARSING_DATA pd = readUnaligned ( ( NVAR_ENTRY_PARSING_DATA * ) model - > parsingData ( prevEntryIndex ) . constData ( ) ) ;
if ( ! pd . isValid ) {
prevEntryIndex = UModelIndex ( ) ;
}
break ;
}
2016-10-10 14:05:04 +08:00
}
}
2023-02-20 04:24:20 +08:00
// Check if the link is valid
if ( prevEntryIndex . isValid ( ) ) {
// Use the name and text of the previous entry
name = model - > name ( prevEntryIndex ) ;
text = model - > text ( prevEntryIndex ) ;
if ( entry - > next ( ) = = 0xFFFFFF )
subtype = Subtypes : : DataNvarEntry ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
else {
subtype = Subtypes : : InvalidLinkNvarEntry ;
name = UString ( " InvalidLink " ) ;
pdata . isValid = FALSE ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
goto processing_done ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
// Obtain text
if ( ! entry_body - > _is_null_ascii_name ( ) ) {
text = entry_body - > ascii_name ( ) . c_str ( ) ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
else if ( ! entry_body - > _is_null_ucs2_name ( ) ) {
UByteArray temp ;
for ( const auto & ch : * entry_body - > ucs2_name ( ) - > ucs2_chars ( ) ) {
temp + = UByteArray ( ( const char * ) & ch , sizeof ( ch ) ) ;
}
text = uFromUcs2 ( temp . constData ( ) ) ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
// Obtain GUID
if ( ! entry_body - > _is_null_guid ( ) ) { // GUID is stored in the entry itself
2023-03-12 23:49:19 +08:00
const EFI_GUID g = readUnaligned ( ( EFI_GUID * ) entry_body - > guid ( ) . c_str ( ) ) ;
name = guidToUString ( g ) ;
guid = guidToUString ( g , false ) ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
else { // GUID is stored in GUID store at the end of the NVAR store
// Grow the GUID store if needed
if ( guidsInStore < entry_body - > guid_index ( ) + 1 )
guidsInStore = entry_body - > guid_index ( ) + 1 ;
2016-10-10 14:05:04 +08:00
// The list begins at the end of the store and goes backwards
2023-03-12 23:49:19 +08:00
const EFI_GUID g = readUnaligned ( ( EFI_GUID * ) ( nvar . constData ( ) + nvar . size ( ) ) - ( entry_body - > guid_index ( ) + 1 ) ) ;
2023-02-20 04:24:20 +08:00
name = guidToUString ( g ) ;
guid = guidToUString ( g , false ) ;
2016-10-10 14:05:04 +08:00
}
2023-02-20 04:24:20 +08:00
processing_done :
// This feels hacky, but I haven't found a way to ask Kaitai for raw bytes
header = nvar . mid ( entry - > offset ( ) , sizeof ( NVAR_ENTRY_HEADER ) + entry_body - > data_start_offset ( ) ) ;
body = nvar . mid ( entry - > offset ( ) + sizeof ( NVAR_ENTRY_HEADER ) + entry_body - > data_start_offset ( ) , entry_body - > data_size ( ) ) ;
tail = nvar . mid ( entry - > end_offset ( ) - entry_body - > extended_header_size ( ) , entry_body - > extended_header_size ( ) ) ;
// Add GUID info for valid entries
if ( ! guid . isEmpty ( ) )
info + = UString ( " Variable GUID: " ) + guid + " \n " ;
// Add GUID index information
if ( ! entry_body - > _is_null_guid_index ( ) )
info + = usprintf ( " GUID index: %u \n " , entry_body - > guid_index ( ) ) ;
// Add header, body and extended data info
info + = usprintf ( " Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Tail size: %Xh (%u) " ,
entry - > size ( ) , entry - > size ( ) ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
( UINT32 ) tail . size ( ) , ( UINT32 ) tail . size ( ) ) ;
// Add attributes info
const NVAR_ENTRY_HEADER entryHeader = readUnaligned ( ( NVAR_ENTRY_HEADER * ) header . constData ( ) ) ;
info + = usprintf ( " \n Attributes: %02Xh " , entryHeader . Attributes ) ;
// Translate attributes to text
if ( entryHeader . Attributes ! = 0x00 & & entryHeader . Attributes ! = 0xFF )
info + = UString ( " ( " ) + nvarAttributesToUString ( entryHeader . Attributes ) + UString ( " ) " ) ;
// Add next node info
if ( entry - > next ( ) ! = 0xFFFFFF )
info + = usprintf ( " \n Next node at offset: %Xh " , localOffset + entry - > offset ( ) + ( UINT32 ) entry - > next ( ) ) ;
// Add extended header info
if ( entry_body - > extended_header_size ( ) > 0 ) {
info + = usprintf ( " \n Extended header size: %Xh (%u) " ,
entry_body - > extended_header_size ( ) , entry_body - > extended_header_size ( ) ) ;
const UINT8 extendedAttributes = * tail . constData ( ) ;
info + = usprintf ( " \n Extended attributes: %02Xh ( " , extendedAttributes ) + nvarExtendedAttributesToUString ( extendedAttributes ) + UString ( " ) " ) ;
// Add checksum
if ( ! entry_body - > _is_null_extended_header_checksum ( ) ) {
UINT8 calculatedChecksum = 0 ;
UByteArray wholeBody = body + tail ;
// Include entry body
UINT8 * start = ( UINT8 * ) wholeBody . constData ( ) ;
for ( UINT8 * p = start ; p < start + wholeBody . size ( ) ; p + + ) {
calculatedChecksum + = * p ;
}
// Include entry size and flags
start = ( UINT8 * ) & entryHeader . Size ;
for ( UINT8 * p = start ; p < start + sizeof ( UINT16 ) ; p + + ) {
calculatedChecksum + = * p ;
}
// Include entry attributes
calculatedChecksum + = entryHeader . Attributes ;
info + = usprintf ( " \n Checksum: %02Xh, " , entry_body - > extended_header_checksum ( ) )
+ ( calculatedChecksum ? usprintf ( " , invalid, should be %02Xh " , 0x100 - calculatedChecksum ) : UString ( " , valid " ) ) ;
}
// Add timestamp
if ( ! entry_body - > _is_null_extended_header_timestamp ( ) )
info + = usprintf ( " \n Timestamp: % " PRIX64 " h " , entry_body - > extended_header_timestamp ( ) ) ;
// Add hash
if ( ! entry_body - > _is_null_extended_header_hash ( ) ) {
UByteArray hash = UByteArray ( entry_body - > extended_header_hash ( ) . c_str ( ) , entry_body - > extended_header_hash ( ) . size ( ) ) ;
info + = UString ( " \n Hash: " ) + UString ( hash . toHex ( ) . constData ( ) ) ;
}
}
// Add tree item
UModelIndex varIndex = model - > addItem ( localOffset + entry - > offset ( ) , Types : : NvarEntry , subtype , name , text , info , header , body , tail , Fixed , index ) ;
currentEntryIndex + + ;
// Set parsing data
model - > setParsingData ( varIndex , UByteArray ( ( const char * ) & pdata , sizeof ( pdata ) ) ) ;
// Try parsing the entry data as NVAR storage if it begins with NVAR signature
if ( ( subtype = = Subtypes : : DataNvarEntry | | subtype = = Subtypes : : FullNvarEntry )
& & body . size ( ) > = 4 & & readUnaligned ( ( const UINT32 * ) body . constData ( ) ) = = NVRAM_NVAR_ENTRY_SIGNATURE )
( void ) parseNvarStore ( varIndex ) ;
2016-10-10 14:05:04 +08:00
}
}
2023-02-20 04:24:20 +08:00
catch ( . . . ) {
msg ( usprintf ( " %s: unable to parse AMI NVAR storage " , __FUNCTION__ ) , index ) ;
return U_INVALID_STORE ;
}
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
USTATUS NvramParser : : parseNvramVolumeBody ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Obtain required fields from parsing data
UINT8 emptyByte = 0xFF ;
if ( model - > hasEmptyParsingData ( index ) = = false ) {
UByteArray data = model - > parsingData ( index ) ;
const VOLUME_PARSING_DATA * pdata = ( const VOLUME_PARSING_DATA * ) data . constData ( ) ;
emptyByte = pdata - > emptyByte ;
}
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Get local offset
2021-04-04 17:09:23 +08:00
UINT32 localOffset = ( UINT32 ) model - > header ( index ) . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get item data
UByteArray data = model - > body ( index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Search for first store
USTATUS result ;
UINT32 prevStoreOffset ;
2016-10-28 00:31:15 +08:00
result = findNextStore ( index , data , localOffset , 0 , prevStoreOffset ) ;
2016-10-10 14:05:04 +08:00
if ( result )
return result ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// First store is not at the beginning of volume body
UString name ;
UString info ;
if ( prevStoreOffset > 0 ) {
// Get info
UByteArray padding = data . left ( prevStoreOffset ) ;
name = UString ( " Padding " ) ;
2022-08-28 18:47:01 +08:00
info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) padding . size ( ) , ( UINT32 ) padding . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
model - > addItem ( localOffset , Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Search for and parse all stores
UINT32 storeOffset = prevStoreOffset ;
UINT32 prevStoreSize = 0 ;
2022-08-28 18:47:01 +08:00
2016-12-04 06:36:01 +08:00
while ( ! result ) {
2016-10-10 14:05:04 +08:00
// Padding between stores
if ( storeOffset > prevStoreOffset + prevStoreSize ) {
UINT32 paddingOffset = prevStoreOffset + prevStoreSize ;
UINT32 paddingSize = storeOffset - paddingOffset ;
UByteArray padding = data . mid ( paddingOffset , paddingSize ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get info
name = UString ( " Padding " ) ;
2022-08-28 18:47:01 +08:00
info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) padding . size ( ) , ( UINT32 ) padding . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
model - > addItem ( localOffset + paddingOffset , Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get store size
UINT32 storeSize = 0 ;
result = getStoreSize ( data , storeOffset , storeSize ) ;
if ( result ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: getStoreSize failed with error " , __FUNCTION__ ) + errorCodeToUString ( result ) , index ) ;
2016-10-10 14:05:04 +08:00
return result ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check that current store is fully present in input
if ( storeSize > ( UINT32 ) data . size ( ) | | storeOffset + storeSize > ( UINT32 ) data . size ( ) ) {
// Mark the rest as padding and finish parsing
UByteArray padding = data . mid ( storeOffset ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get info
name = UString ( " Padding " ) ;
2022-08-28 18:47:01 +08:00
info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) padding . size ( ) , ( UINT32 ) padding . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
UModelIndex paddingIndex = model - > addItem ( localOffset + storeOffset , Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: one of stores inside overlaps the end of data " , __FUNCTION__ ) , paddingIndex ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Update variables
prevStoreOffset = storeOffset ;
2021-04-04 17:09:23 +08:00
prevStoreSize = ( UINT32 ) padding . size ( ) ;
2016-10-10 14:05:04 +08:00
break ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Parse current store header
UModelIndex storeIndex ;
2016-10-28 00:31:15 +08:00
UByteArray store = data . mid ( storeOffset , storeSize ) ;
result = parseStoreHeader ( store , localOffset + storeOffset , index , storeIndex ) ;
2016-10-10 14:05:04 +08:00
if ( result )
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: store header parsing failed with error " , __FUNCTION__ ) + errorCodeToUString ( result ) , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Go to next store
prevStoreOffset = storeOffset ;
prevStoreSize = storeSize ;
2016-10-28 00:31:15 +08:00
result = findNextStore ( index , data , localOffset , storeOffset + prevStoreSize , storeOffset ) ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Padding/free space at the end
storeOffset = prevStoreOffset + prevStoreSize ;
if ( ( UINT32 ) data . size ( ) > storeOffset ) {
UByteArray padding = data . mid ( storeOffset ) ;
2016-10-28 00:31:15 +08:00
// Add info
2022-08-28 18:47:01 +08:00
info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) padding . size ( ) , ( UINT32 ) padding . size ( ) ) ;
2016-10-28 00:31:15 +08:00
if ( padding . count ( emptyByte ) = = padding . size ( ) ) { // Free space
// Add tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + storeOffset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
else {
2021-10-07 23:51:39 +08:00
// Nothing is parsed yet, but the file is not empty
2016-10-10 14:05:04 +08:00
if ( ! storeOffset ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: can't be parsed as NVRAM volume " , __FUNCTION__ ) , index ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Add tree item
model - > addItem ( localOffset + storeOffset , Types : : Padding , getPaddingType ( padding ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Parse bodies
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2021-04-04 17:09:23 +08:00
UModelIndex current = index . model ( ) - > index ( i , 0 , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
switch ( model - > type ( current ) ) {
2022-08-28 18:47:01 +08:00
case Types : : FdcStore :
parseFdcStoreBody ( current ) ;
break ;
case Types : : VssStore :
parseVssStoreBody ( current , 0 ) ;
break ;
case Types : : Vss2Store :
parseVssStoreBody ( current , 4 ) ;
break ;
case Types : : FsysStore :
parseFsysStoreBody ( current ) ;
break ;
case Types : : EvsaStore :
parseEvsaStoreBody ( current ) ;
break ;
case Types : : FlashMapStore :
parseFlashMapBody ( current ) ;
break ;
default :
// Ignore unknown!
break ;
2016-10-10 14:05:04 +08:00
}
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : findNextStore ( const UModelIndex & index , const UByteArray & volume , const UINT32 localOffset , const UINT32 storeOffset , UINT32 & nextStoreOffset )
2016-10-10 14:05:04 +08:00
{
2021-04-04 17:09:23 +08:00
UINT32 dataSize = ( UINT32 ) volume . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
if ( dataSize < sizeof ( UINT32 ) )
return U_STORES_NOT_FOUND ;
2022-08-28 18:47:01 +08:00
2021-10-07 23:51:39 +08:00
// TODO: add checks for restSize
2022-08-29 14:23:38 +08:00
// TODO: remove misaligned access by doing the signature checks differently, the current way is UB is C++
// TODO: rewrite this all as Kaitai-based parser
2016-10-10 14:05:04 +08:00
UINT32 offset = storeOffset ;
for ( ; offset < dataSize - sizeof ( UINT32 ) ; offset + + ) {
const UINT32 * currentPos = ( const UINT32 * ) ( volume . constData ( ) + offset ) ;
2023-02-01 12:15:12 +08:00
if ( readUnaligned ( currentPos ) = = NVRAM_VSS_STORE_SIGNATURE
| | readUnaligned ( currentPos ) = = NVRAM_APPLE_SVS_STORE_SIGNATURE
| | readUnaligned ( currentPos ) = = NVRAM_APPLE_NSS_STORE_SIGNATURE ) { // $VSS, $SVS or $NSS signatures found, perform checks
2016-10-10 14:05:04 +08:00
const VSS_VARIABLE_STORE_HEADER * vssHeader = ( const VSS_VARIABLE_STORE_HEADER * ) currentPos ;
if ( vssHeader - > Format ! = NVRAM_VSS_VARIABLE_STORE_FORMATTED ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: VSS store candidate at offset %Xh skipped, has invalid format %02Xh " , __FUNCTION__ , localOffset + offset , vssHeader - > Format ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
if ( vssHeader - > Size = = 0 | | vssHeader - > Size = = 0xFFFFFFFF ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: VSS store candidate at offset %Xh skipped, has invalid size %Xh " , __FUNCTION__ , localOffset + offset , vssHeader - > Size ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1
| | readUnaligned ( currentPos ) = = NVRAM_VSS2_STORE_GUID_PART1 ) { // VSS2 store signatures found, perform checks
2017-07-31 14:06:11 +08:00
UByteArray guid = UByteArray ( volume . constData ( ) + offset , sizeof ( EFI_GUID ) ) ;
2017-12-11 09:56:00 +08:00
if ( guid ! = NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID & & guid ! = NVRAM_VSS2_STORE_GUID ) // Check the whole signature
2017-07-31 14:06:11 +08:00
continue ;
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
const VSS2_VARIABLE_STORE_HEADER * vssHeader = ( const VSS2_VARIABLE_STORE_HEADER * ) currentPos ;
2017-07-31 14:06:11 +08:00
if ( vssHeader - > Format ! = NVRAM_VSS_VARIABLE_STORE_FORMATTED ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: VSS2 store candidate at offset %Xh skipped, has invalid format %02Xh " , __FUNCTION__ , localOffset + offset , vssHeader - > Format ) , index ) ;
2017-07-31 14:06:11 +08:00
continue ;
}
if ( vssHeader - > Size = = 0 | | vssHeader - > Size = = 0xFFFFFFFF ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: VSS2 store candidate at offset %Xh skipped, has invalid size %Xh " , __FUNCTION__ , localOffset + offset , vssHeader - > Size ) , index ) ;
2017-07-31 14:06:11 +08:00
continue ;
}
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = NVRAM_FDC_VOLUME_SIGNATURE ) { // FDC signature found
2016-10-10 14:05:04 +08:00
const FDC_VOLUME_HEADER * fdcHeader = ( const FDC_VOLUME_HEADER * ) currentPos ;
if ( fdcHeader - > Size = = 0 | | fdcHeader - > Size = = 0xFFFFFFFF ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: FDC store candidate at offset %Xh skipped, has invalid size %Xh " , __FUNCTION__ , localOffset + offset , fdcHeader - > Size ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = NVRAM_APPLE_FSYS_STORE_SIGNATURE
| | readUnaligned ( currentPos ) = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) { // Fsys or Gaid signature found
2016-10-10 14:05:04 +08:00
const APPLE_FSYS_STORE_HEADER * fsysHeader = ( const APPLE_FSYS_STORE_HEADER * ) currentPos ;
if ( fsysHeader - > Size = = 0 | | fsysHeader - > Size = = 0xFFFF ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: Fsys store candidate at offset %Xh skipped, has invalid size %Xh " , __FUNCTION__ , localOffset + offset , fsysHeader - > Size ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = NVRAM_EVSA_STORE_SIGNATURE ) { //EVSA signature found
2016-10-10 14:05:04 +08:00
if ( offset < sizeof ( UINT32 ) )
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
const EVSA_STORE_ENTRY * evsaHeader = ( const EVSA_STORE_ENTRY * ) ( currentPos - 1 ) ;
if ( evsaHeader - > Header . Type ! = NVRAM_EVSA_ENTRY_TYPE_STORE ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: EVSA store candidate at offset %Xh skipped, has invalid type %02Xh " , __FUNCTION__ , localOffset + offset - 4 , evsaHeader - > Header . Type ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
if ( evsaHeader - > StoreSize = = 0 | | evsaHeader - > StoreSize = = 0xFFFFFFFF ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: EVSA store candidate at offset %Xh skipped, has invalid size %Xh " , __FUNCTION__ , localOffset + offset , evsaHeader - > StoreSize ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
// All checks passed, store found
offset - = sizeof ( UINT32 ) ;
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = NVRAM_MAIN_STORE_VOLUME_GUID_DATA1
| | readUnaligned ( currentPos ) = = EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 ) { // Possible FTW block signature found
2016-10-10 14:05:04 +08:00
UByteArray guid = UByteArray ( volume . constData ( ) + offset , sizeof ( EFI_GUID ) ) ;
2017-12-11 09:56:00 +08:00
if ( guid ! = NVRAM_MAIN_STORE_VOLUME_GUID & & guid ! = EDKII_WORKING_BLOCK_SIGNATURE_GUID & & guid ! = VSS2_WORKING_BLOCK_SIGNATURE_GUID ) // Check the whole signature
2016-10-10 14:05:04 +08:00
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Detect header variant based on WriteQueueSize
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ftwHeader = ( const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ) currentPos ;
if ( ftwHeader - > WriteQueueSize % 0x10 = = 0x04 ) { // Header with 32 bit WriteQueueSize
if ( ftwHeader - > WriteQueueSize = = 0 | | ftwHeader - > WriteQueueSize = = 0xFFFFFFFF ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: FTW block candidate at offset %Xh skipped, has invalid body size %Xh " , __FUNCTION__ , localOffset + offset , ftwHeader - > WriteQueueSize ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
}
else if ( ftwHeader - > WriteQueueSize % 0x10 = = 0x00 ) { // Header with 64 bit WriteQueueSize
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 * ftw64Header = ( const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 * ) currentPos ;
if ( ftw64Header - > WriteQueueSize = = 0 | | ftw64Header - > WriteQueueSize > = 0xFFFFFFFF ) {
2022-08-29 13:08:45 +08:00
msg ( usprintf ( " %s: FTW block candidate at offset %Xh skipped, has invalid body size % " PRIX64 " h " , __FUNCTION__ , localOffset + offset , ftw64Header - > WriteQueueSize ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
}
else // Unknown header
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 ) { // Phoenix SCT flash map
2016-10-10 14:05:04 +08:00
UByteArray signature = UByteArray ( volume . constData ( ) + offset , NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH ) ;
if ( signature ! = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE ) // Check the whole signature
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE ) { // Phoenix SCT CMDB store
2016-10-10 14:05:04 +08:00
const PHOENIX_CMDB_HEADER * cmdbHeader = ( const PHOENIX_CMDB_HEADER * ) currentPos ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check size
if ( cmdbHeader - > HeaderSize ! = sizeof ( PHOENIX_CMDB_HEADER ) )
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = INTEL_MICROCODE_HEADER_VERSION_1 ) { // Intel microcode
2016-10-10 14:05:04 +08:00
const INTEL_MICROCODE_HEADER * ucodeHeader = ( const INTEL_MICROCODE_HEADER * ) currentPos ;
2019-07-25 01:30:59 +08:00
// TotalSize is greater then DataSize and is multiple of 1024
2019-09-05 08:07:18 +08:00
if ( FALSE = = ffsParser - > microcodeHeaderValid ( ucodeHeader ) ) {
2019-07-25 01:30:59 +08:00
continue ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// All checks passed, store found
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = OEM_ACTIVATION_PUBKEY_MAGIC ) { // SLIC pubkey
2016-10-10 14:05:04 +08:00
if ( offset < 4 * sizeof ( UINT32 ) )
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
const OEM_ACTIVATION_PUBKEY * pubkeyHeader = ( const OEM_ACTIVATION_PUBKEY * ) ( currentPos - 4 ) ;
// Check type
if ( pubkeyHeader - > Type ! = OEM_ACTIVATION_PUBKEY_TYPE )
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// All checks passed, store found
offset - = 4 * sizeof ( UINT32 ) ;
break ;
}
2023-02-01 12:15:12 +08:00
else if ( readUnaligned ( currentPos ) = = OEM_ACTIVATION_MARKER_WINDOWS_FLAG_PART1 ) { // SLIC marker
2022-08-25 12:49:10 +08:00
if ( offset < 26
| | offset > = dataSize - sizeof ( UINT64 )
| | * ( const UINT64 * ) currentPos ! = OEM_ACTIVATION_MARKER_WINDOWS_FLAG ) // Check full windows flag and structure size
2016-10-10 14:05:04 +08:00
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
const OEM_ACTIVATION_MARKER * markerHeader = ( const OEM_ACTIVATION_MARKER * ) ( volume . constData ( ) + offset - 26 ) ;
// Check reserved bytes
bool reservedBytesValid = true ;
for ( UINT32 i = 0 ; i < sizeof ( markerHeader - > Reserved ) ; i + + )
if ( markerHeader - > Reserved [ i ] ! = OEM_ACTIVATION_MARKER_RESERVED_BYTE ) {
reservedBytesValid = false ;
break ;
}
if ( ! reservedBytesValid )
continue ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// All checks passed, store found
offset - = 26 ;
break ;
}
}
// No more stores found
if ( offset > = dataSize - sizeof ( UINT32 ) )
return U_STORES_NOT_FOUND ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
nextStoreOffset = offset ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
USTATUS NvramParser : : getStoreSize ( const UByteArray & data , const UINT32 storeOffset , UINT32 & storeSize )
{
const UINT32 * signature = ( const UINT32 * ) ( data . constData ( ) + storeOffset ) ;
2019-07-25 01:30:59 +08:00
if ( * signature = = NVRAM_VSS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_NSS_STORE_SIGNATURE ) {
2016-10-10 14:05:04 +08:00
const VSS_VARIABLE_STORE_HEADER * vssHeader = ( const VSS_VARIABLE_STORE_HEADER * ) signature ;
storeSize = vssHeader - > Size ;
}
2017-12-11 09:56:00 +08:00
else if ( * signature = = NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 | | * signature = = NVRAM_VSS2_STORE_GUID_PART1 ) {
const VSS2_VARIABLE_STORE_HEADER * vssHeader = ( const VSS2_VARIABLE_STORE_HEADER * ) signature ;
2017-07-31 14:06:11 +08:00
storeSize = vssHeader - > Size ;
}
2016-10-10 14:05:04 +08:00
else if ( * signature = = NVRAM_FDC_VOLUME_SIGNATURE ) {
const FDC_VOLUME_HEADER * fdcHeader = ( const FDC_VOLUME_HEADER * ) signature ;
storeSize = fdcHeader - > Size ;
}
else if ( * signature = = NVRAM_APPLE_FSYS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) {
const APPLE_FSYS_STORE_HEADER * fsysHeader = ( const APPLE_FSYS_STORE_HEADER * ) signature ;
storeSize = fsysHeader - > Size ;
}
else if ( * ( signature + 1 ) = = NVRAM_EVSA_STORE_SIGNATURE ) {
const EVSA_STORE_ENTRY * evsaHeader = ( const EVSA_STORE_ENTRY * ) signature ;
storeSize = evsaHeader - > StoreSize ;
}
else if ( * signature = = NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 | | * signature = = EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 ) {
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ftwHeader = ( const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ) signature ;
if ( ftwHeader - > WriteQueueSize % 0x10 = = 0x04 ) { // Header with 32 bit WriteQueueSize
storeSize = sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 ) + ftwHeader - > WriteQueueSize ;
}
else { // Header with 64 bit WriteQueueSize
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 * ftw64Header = ( const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 * ) signature ;
storeSize = sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) + ( UINT32 ) ftw64Header - > WriteQueueSize ;
}
}
else if ( * signature = = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 ) { // Phoenix SCT flash map
const PHOENIX_FLASH_MAP_HEADER * flashMapHeader = ( const PHOENIX_FLASH_MAP_HEADER * ) signature ;
storeSize = sizeof ( PHOENIX_FLASH_MAP_HEADER ) + sizeof ( PHOENIX_FLASH_MAP_ENTRY ) * flashMapHeader - > NumEntries ;
}
else if ( * signature = = NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE ) { // Phoenix SCT CMDB store
storeSize = NVRAM_PHOENIX_CMDB_SIZE ; // It's a predefined max size, no need to calculate
}
else if ( * ( signature + 4 ) = = OEM_ACTIVATION_PUBKEY_MAGIC ) { // SLIC pubkey
const OEM_ACTIVATION_PUBKEY * pubkeyHeader = ( const OEM_ACTIVATION_PUBKEY * ) signature ;
storeSize = pubkeyHeader - > Size ;
}
else if ( * ( const UINT64 * ) ( data . constData ( ) + storeOffset + 26 ) = = OEM_ACTIVATION_MARKER_WINDOWS_FLAG ) { // SLIC marker
const OEM_ACTIVATION_MARKER * markerHeader = ( const OEM_ACTIVATION_MARKER * ) signature ;
storeSize = markerHeader - > Size ;
}
2019-07-25 01:30:59 +08:00
else if ( * signature = = INTEL_MICROCODE_HEADER_VERSION_1 ) { // Intel microcode, must be checked after SLIC marker because of the same *signature values
2016-10-10 14:05:04 +08:00
const INTEL_MICROCODE_HEADER * ucodeHeader = ( const INTEL_MICROCODE_HEADER * ) signature ;
storeSize = ucodeHeader - > TotalSize ;
2019-02-02 00:45:39 +08:00
} else {
return U_INVALID_PARAMETER ; // Unreachable
2016-10-10 14:05:04 +08:00
}
return U_SUCCESS ;
}
2017-12-11 09:56:00 +08:00
USTATUS NvramParser : : parseVssStoreHeader ( const UByteArray & store , const UINT32 localOffset , const bool sizeOverride , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < sizeof ( VSS_VARIABLE_STORE_HEADER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for VSS store header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get VSS store header
const VSS_VARIABLE_STORE_HEADER * vssStoreHeader = ( const VSS_VARIABLE_STORE_HEADER * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
// Check for size override
UINT32 storeSize = vssStoreHeader - > Size ;
if ( sizeOverride ) {
storeSize = dataSize ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
2017-12-11 09:56:00 +08:00
if ( dataSize < storeSize ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: VSS store size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
storeSize , storeSize ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = store . left ( sizeof ( VSS_VARIABLE_STORE_HEADER ) ) ;
2017-12-11 09:56:00 +08:00
UByteArray body = store . mid ( sizeof ( VSS_VARIABLE_STORE_HEADER ) , storeSize - sizeof ( VSS_VARIABLE_STORE_HEADER ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
2019-07-25 01:30:59 +08:00
UString name ;
if ( vssStoreHeader - > Signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE ) {
name = UString ( " SVS store " ) ;
}
else if ( vssStoreHeader - > Signature = = NVRAM_APPLE_NSS_STORE_SIGNATURE ) {
name = UString ( " NSS store " ) ;
}
else {
name = UString ( " VSS store " ) ;
}
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Signature: %Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Format: %02Xh \n State: %02Xh \n Unknown: %04Xh " ,
2022-08-28 18:47:01 +08:00
vssStoreHeader - > Signature ,
storeSize , storeSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
vssStoreHeader - > Format ,
vssStoreHeader - > State ,
vssStoreHeader - > Unknown ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : VssStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2017-12-11 09:56:00 +08:00
USTATUS NvramParser : : parseVss2StoreHeader ( const UByteArray & store , const UINT32 localOffset , const bool sizeOverride , const UModelIndex & parent , UModelIndex & index )
2017-07-31 14:06:11 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2017-07-31 14:06:11 +08:00
// Check store size
2017-12-11 09:56:00 +08:00
if ( dataSize < sizeof ( VSS2_VARIABLE_STORE_HEADER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for VSS2 store header " , __FUNCTION__ ) , parent ) ;
2017-07-31 14:06:11 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
// Get VSS2 store header
const VSS2_VARIABLE_STORE_HEADER * vssStoreHeader = ( const VSS2_VARIABLE_STORE_HEADER * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
// Check for size override
UINT32 storeSize = vssStoreHeader - > Size ;
if ( sizeOverride ) {
storeSize = dataSize ;
}
2022-08-28 18:47:01 +08:00
2017-07-31 14:06:11 +08:00
// Check store size
2017-12-11 09:56:00 +08:00
if ( dataSize < storeSize ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: VSS2 store size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
storeSize , storeSize ,
dataSize , dataSize ) , parent ) ;
2017-07-31 14:06:11 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2017-07-31 14:06:11 +08:00
// Construct header and body
2017-12-11 09:56:00 +08:00
UByteArray header = store . left ( sizeof ( VSS2_VARIABLE_STORE_HEADER ) ) ;
UByteArray body = store . mid ( sizeof ( VSS2_VARIABLE_STORE_HEADER ) , storeSize - sizeof ( VSS2_VARIABLE_STORE_HEADER ) ) ;
2022-08-28 18:47:01 +08:00
2017-07-31 14:06:11 +08:00
// Add info
2017-12-11 09:56:00 +08:00
UString name = UString ( " VSS2 store " ) ;
2023-03-12 23:49:19 +08:00
UString info = UString ( " Signature: " ) + guidToUString ( vssStoreHeader - > Signature , false ) +
2022-08-28 18:47:01 +08:00
usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Format: %02Xh \n State: %02Xh \n Unknown: %04Xh " ,
storeSize , storeSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
vssStoreHeader - > Format ,
vssStoreHeader - > State ,
vssStoreHeader - > Unknown ) ;
2017-07-31 14:06:11 +08:00
// Add tree item
2017-12-11 09:56:00 +08:00
index = model - > addItem ( localOffset , Types : : Vss2Store , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2017-07-31 14:06:11 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseFtwStoreHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for FTW store header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Obtain required information from parent volume
UINT8 emptyByte = 0xFF ;
2018-01-23 16:00:03 +08:00
UModelIndex parentVolumeIndex = model - > findParentOfType ( parent , Types : : Volume ) ;
2016-10-28 00:31:15 +08:00
if ( parentVolumeIndex . isValid ( ) & & model - > hasEmptyParsingData ( parentVolumeIndex ) = = false ) {
UByteArray data = model - > parsingData ( parentVolumeIndex ) ;
const VOLUME_PARSING_DATA * pdata = ( const VOLUME_PARSING_DATA * ) data . constData ( ) ;
2016-12-04 06:36:01 +08:00
emptyByte = pdata - > emptyByte ;
2016-10-28 00:31:15 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get FTW block headers
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ftw32BlockHeader = ( const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ) store . constData ( ) ;
const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 * ftw64BlockHeader = ( const EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
UINT32 ftwBlockSize ;
bool has32bitHeader ;
if ( ftw32BlockHeader - > WriteQueueSize % 0x10 = = 0x04 ) { // Header with 32 bit WriteQueueSize
ftwBlockSize = sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 ) + ftw32BlockHeader - > WriteQueueSize ;
has32bitHeader = true ;
}
else { // Header with 64 bit WriteQueueSize
ftwBlockSize = sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) + ( UINT32 ) ftw64BlockHeader - > WriteQueueSize ;
has32bitHeader = false ;
}
if ( dataSize < ftwBlockSize ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: FTW store size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
ftwBlockSize , ftwBlockSize ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UINT32 headerSize = has32bitHeader ? sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 ) : sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) ;
UByteArray header = store . left ( headerSize ) ;
UByteArray body = store . mid ( headerSize , ftwBlockSize - headerSize ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check block header checksum
UByteArray crcHeader = header ;
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * crcFtwBlockHeader = ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ) header . data ( ) ;
2016-10-28 00:31:15 +08:00
crcFtwBlockHeader - > Crc = emptyByte ? 0xFFFFFFFF : 0 ;
crcFtwBlockHeader - > State = emptyByte ? 0xFF : 0 ;
2019-07-25 01:30:59 +08:00
UINT32 calculatedCrc = ( UINT32 ) crc32 ( 0 , ( const UINT8 * ) crcFtwBlockHeader , headerSize ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " FTW store " ) ;
2023-03-12 23:49:19 +08:00
UString info = UString ( " Signature: " ) + guidToUString ( ftw32BlockHeader - > Signature , false ) +
2022-08-28 18:47:01 +08:00
usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n State: %02Xh \n Header CRC32: %08Xh " ,
ftwBlockSize , ftwBlockSize ,
headerSize , headerSize ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
ftw32BlockHeader - > State ,
ftw32BlockHeader - > Crc ) +
( ftw32BlockHeader - > Crc ! = calculatedCrc ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc ) : UString ( " , valid " ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : FtwStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseFdcStoreHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < sizeof ( FDC_VOLUME_HEADER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for FDC store header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get Fdc store header
const FDC_VOLUME_HEADER * fdcStoreHeader = ( const FDC_VOLUME_HEADER * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < fdcStoreHeader - > Size ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: FDC store size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
fdcStoreHeader - > Size , fdcStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
2018-05-08 23:42:16 +08:00
UByteArray header = store . left ( sizeof ( FDC_VOLUME_HEADER ) ) ;
UByteArray body = store . mid ( sizeof ( FDC_VOLUME_HEADER ) , fdcStoreHeader - > Size - sizeof ( FDC_VOLUME_HEADER ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " FDC store " ) ;
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Signature: _FDC \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) " ,
2022-08-28 18:47:01 +08:00
fdcStoreHeader - > Size , fdcStoreHeader - > Size ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : FdcStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseFsysStoreHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < sizeof ( APPLE_FSYS_STORE_HEADER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for Fsys store header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get Fsys store header
const APPLE_FSYS_STORE_HEADER * fsysStoreHeader = ( const APPLE_FSYS_STORE_HEADER * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < fsysStoreHeader - > Size ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: Fsys store size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
fsysStoreHeader - > Size , fsysStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = store . left ( sizeof ( APPLE_FSYS_STORE_HEADER ) ) ;
UByteArray body = store . mid ( sizeof ( APPLE_FSYS_STORE_HEADER ) , fsysStoreHeader - > Size - sizeof ( APPLE_FSYS_STORE_HEADER ) - sizeof ( UINT32 ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store checksum
UINT32 storedCrc = * ( UINT32 * ) store . right ( sizeof ( UINT32 ) ) . constData ( ) ;
2021-10-07 23:56:25 +08:00
UINT32 calculatedCrc = ( UINT32 ) crc32 ( 0 , ( const UINT8 * ) store . constData ( ) , ( UINT32 ) store . size ( ) - sizeof ( UINT32 ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
bool isGaidStore = ( fsysStoreHeader - > Signature = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) ;
UString name = isGaidStore ? UString ( " Gaid store " ) : UString ( " Fsys store " ) ;
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Signature: %s \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Unknown0: %02Xh \n Unknown1: %08Xh \n CRC32: %08Xh " ,
2022-08-28 18:47:01 +08:00
isGaidStore ? " Gaid " : " Fsys " ,
fsysStoreHeader - > Size , fsysStoreHeader - > Size ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
fsysStoreHeader - > Unknown0 ,
fsysStoreHeader - > Unknown1 ,
storedCrc )
+ ( storedCrc ! = calculatedCrc ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc ) : UString ( " , valid " ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : FsysStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseEvsaStoreHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check dataSize
if ( dataSize < sizeof ( EVSA_STORE_ENTRY ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for EVSA store header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get EVSA store header
const EVSA_STORE_ENTRY * evsaStoreHeader = ( const EVSA_STORE_ENTRY * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < evsaStoreHeader - > StoreSize ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: EVSA store size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
evsaStoreHeader - > StoreSize , evsaStoreHeader - > StoreSize ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = store . left ( evsaStoreHeader - > Header . Size ) ;
UByteArray body = store . mid ( evsaStoreHeader - > Header . Size , evsaStoreHeader - > StoreSize - evsaStoreHeader - > Header . Size ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Recalculate checksum
UINT8 calculated = calculateChecksum8 ( ( ( const UINT8 * ) evsaStoreHeader ) + 2 , evsaStoreHeader - > Header . Size - 2 ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " EVSA store " ) ;
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Signature: EVSA \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Type: %02Xh \n Attributes: %08Xh \n Checksum: %02Xh " ,
2022-08-28 18:47:01 +08:00
evsaStoreHeader - > StoreSize , evsaStoreHeader - > StoreSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
evsaStoreHeader - > Header . Type ,
evsaStoreHeader - > Attributes ,
evsaStoreHeader - > Header . Checksum ) +
( evsaStoreHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : EvsaStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseFlashMapStoreHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check data size
if ( dataSize < sizeof ( PHOENIX_FLASH_MAP_HEADER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for FlashMap block header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get FlashMap block header
const PHOENIX_FLASH_MAP_HEADER * flashMapHeader = ( const PHOENIX_FLASH_MAP_HEADER * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
UINT32 flashMapSize = sizeof ( PHOENIX_FLASH_MAP_HEADER ) + flashMapHeader - > NumEntries * sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ;
if ( dataSize < flashMapSize ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: FlashMap block size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
flashMapSize , flashMapSize ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = store . left ( sizeof ( PHOENIX_FLASH_MAP_HEADER ) ) ;
UByteArray body = store . mid ( sizeof ( PHOENIX_FLASH_MAP_HEADER ) , flashMapSize - sizeof ( PHOENIX_FLASH_MAP_HEADER ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " Phoenix SCT flash map " ) ;
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Signature: _FLASH_MAP \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Number of entries: %u " ,
2022-08-28 18:47:01 +08:00
flashMapSize , flashMapSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
flashMapHeader - > NumEntries ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : FlashMapStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseCmdbStoreHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < sizeof ( PHOENIX_CMDB_HEADER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for CMDB store header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
UINT32 cmdbSize = NVRAM_PHOENIX_CMDB_SIZE ;
if ( dataSize < cmdbSize ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: CMDB store size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
cmdbSize , cmdbSize ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get store header
const PHOENIX_CMDB_HEADER * cmdbHeader = ( const PHOENIX_CMDB_HEADER * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = store . left ( cmdbHeader - > TotalSize ) ;
UByteArray body = store . mid ( cmdbHeader - > TotalSize , cmdbSize - cmdbHeader - > TotalSize ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " CMDB store " ) ;
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Signature: CMDB \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) " ,
2022-08-28 18:47:01 +08:00
cmdbSize , cmdbSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : CmdbStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseSlicPubkeyHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check data size
if ( dataSize < sizeof ( OEM_ACTIVATION_PUBKEY ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for SLIC pubkey header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get SLIC pubkey header
const OEM_ACTIVATION_PUBKEY * pubkeyHeader = ( const OEM_ACTIVATION_PUBKEY * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < pubkeyHeader - > Size ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: SLIC pubkey size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
pubkeyHeader - > Size , pubkeyHeader - > Size ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = store . left ( sizeof ( OEM_ACTIVATION_PUBKEY ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " SLIC pubkey " ) ;
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Type: 0h \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: 0h (0) \n "
2022-08-28 18:47:01 +08:00
" Key type: %02Xh \n Version: %02Xh \n Algorithm: %08Xh \n Magic: RSA1 \n Bit length: %08Xh \n Exponent: %08Xh " ,
pubkeyHeader - > Size , pubkeyHeader - > Size ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
pubkeyHeader - > KeyType ,
pubkeyHeader - > Version ,
pubkeyHeader - > Algorithm ,
pubkeyHeader - > BitLength ,
pubkeyHeader - > Exponent ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : SlicData , Subtypes : : PubkeySlicData , name , UString ( ) , info , header , UByteArray ( ) , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseSlicMarkerHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check data size
if ( dataSize < sizeof ( OEM_ACTIVATION_MARKER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for SLIC marker header " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get SLIC marker header
const OEM_ACTIVATION_MARKER * markerHeader = ( const OEM_ACTIVATION_MARKER * ) store . constData ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check store size
if ( dataSize < markerHeader - > Size ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: SLIC marker size %Xh (%u) is greater than volume body size %Xh (%u) " , __FUNCTION__ ,
2022-08-28 18:47:01 +08:00
markerHeader - > Size , markerHeader - > Size ,
dataSize , dataSize ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = store . left ( sizeof ( OEM_ACTIVATION_MARKER ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " SLIC marker " ) ;
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Type: 1h \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: 0h (0) \n "
2022-08-28 18:47:01 +08:00
" Version: %08Xh \n OEM ID: %s \n OEM table ID: %s \n Windows flag: WINDOWS \n SLIC version: %08Xh " ,
markerHeader - > Size , markerHeader - > Size ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
markerHeader - > Version ,
( const char * ) UString ( ( const char * ) & ( markerHeader - > OemId ) ) . left ( 6 ) . toLocal8Bit ( ) ,
( const char * ) UString ( ( const char * ) & ( markerHeader - > OemTableId ) ) . left ( 8 ) . toLocal8Bit ( ) ,
markerHeader - > SlicVersion ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
index = model - > addItem ( localOffset , Types : : SlicData , Subtypes : : MarkerSlicData , name , UString ( ) , info , header , UByteArray ( ) , UByteArray ( ) , Fixed , parent ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2016-10-28 00:31:15 +08:00
USTATUS NvramParser : : parseStoreHeader ( const UByteArray & store , const UINT32 localOffset , const UModelIndex & parent , UModelIndex & index )
2016-10-10 14:05:04 +08:00
{
2021-10-07 23:56:25 +08:00
const UINT32 dataSize = ( UINT32 ) store . size ( ) ;
2016-10-10 14:05:04 +08:00
const UINT32 * signature = ( const UINT32 * ) store . constData ( ) ;
// Check store size
if ( dataSize < sizeof ( UINT32 ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: volume body is too small even for a store signature " , __FUNCTION__ ) , parent ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check signature and run parser function needed
2019-07-25 01:30:59 +08:00
// VSS/SVS/NSS store
if ( * signature = = NVRAM_VSS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_NSS_STORE_SIGNATURE )
2017-12-11 09:56:00 +08:00
return parseVssStoreHeader ( store , localOffset , false , parent , index ) ;
// VSS2 store
if ( * signature = = NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 | | * signature = = NVRAM_VSS2_STORE_GUID_PART1 )
return parseVss2StoreHeader ( store , localOffset , false , parent , index ) ;
2016-10-10 14:05:04 +08:00
// FTW store
2017-12-11 09:56:00 +08:00
else if ( * signature = = NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 | | * signature = = EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 )
2016-10-28 00:31:15 +08:00
return parseFtwStoreHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// FDC store
2017-12-11 09:56:00 +08:00
else if ( * signature = = NVRAM_FDC_VOLUME_SIGNATURE )
2016-10-28 00:31:15 +08:00
return parseFdcStoreHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// Apple Fsys/Gaid store
2017-12-11 09:56:00 +08:00
else if ( * signature = = NVRAM_APPLE_FSYS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_GAID_STORE_SIGNATURE )
2016-10-28 00:31:15 +08:00
return parseFsysStoreHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// EVSA store
2018-04-30 13:33:19 +08:00
else if ( dataSize > = 2 * sizeof ( UINT32 ) & & * ( signature + 1 ) = = NVRAM_EVSA_STORE_SIGNATURE )
2016-10-28 00:31:15 +08:00
return parseEvsaStoreHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// Phoenix SCT flash map
2017-12-11 09:56:00 +08:00
else if ( * signature = = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 )
2016-10-28 00:31:15 +08:00
return parseFlashMapStoreHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// Phoenix CMDB store
2017-12-11 09:56:00 +08:00
else if ( * signature = = NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE )
2016-10-28 00:31:15 +08:00
return parseCmdbStoreHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// SLIC pubkey
2018-04-30 13:33:19 +08:00
else if ( dataSize > = 5 * sizeof ( UINT32 ) & & * ( signature + 4 ) = = OEM_ACTIVATION_PUBKEY_MAGIC )
2016-10-28 00:31:15 +08:00
return parseSlicPubkeyHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// SLIC marker
2018-04-30 13:33:19 +08:00
else if ( dataSize > = 34 & & * ( const UINT64 * ) ( store . constData ( ) + 26 ) = = OEM_ACTIVATION_MARKER_WINDOWS_FLAG )
2016-10-28 00:31:15 +08:00
return parseSlicMarkerHeader ( store , localOffset , parent , index ) ;
2016-10-10 14:05:04 +08:00
// Intel microcode
// Must be checked after SLIC marker because of the same *signature values
2019-07-25 01:30:59 +08:00
else if ( * signature = = INTEL_MICROCODE_HEADER_VERSION_1 )
2018-10-08 17:58:12 +08:00
return ffsParser - > parseIntelMicrocodeHeader ( store , localOffset , parent , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
msg ( usprintf ( " parseStoreHeader: don't know how to parse a header with signature %08Xh " , * signature ) , parent ) ;
return U_SUCCESS ;
}
2017-12-11 09:56:00 +08:00
USTATUS NvramParser : : parseFdcStoreBody ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
// Get item data
const UByteArray data = model - > body ( index ) ;
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
// Get local offset
2021-04-04 17:09:23 +08:00
UINT32 localOffset = ( UINT32 ) model - > header ( index ) . size ( ) ;
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
// The body is a firmware volume with either a VSS or VSS2 store
UModelIndex volumeIndex ;
USTATUS status = ffsParser - > parseVolumeHeader ( data , localOffset , index , volumeIndex ) ;
if ( status | | ! volumeIndex . isValid ( ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: store can't be parsed as FDC store " , __FUNCTION__ ) , index ) ;
2017-12-11 09:56:00 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
// Determine if it's a VSS or VSS2 store inside
UByteArray store = model - > body ( volumeIndex ) ;
2018-04-30 13:33:19 +08:00
if ( ( UINT32 ) store . size ( ) > = sizeof ( UINT32 ) & & * ( const UINT32 * ) store . constData ( ) = = NVRAM_VSS_STORE_SIGNATURE ) {
2017-12-11 09:56:00 +08:00
UModelIndex vssIndex ;
2021-04-04 17:09:23 +08:00
status = parseVssStoreHeader ( store , ( UINT32 ) ( localOffset + model - > header ( volumeIndex ) . size ( ) ) , true , volumeIndex , vssIndex ) ;
2017-12-11 09:56:00 +08:00
if ( status )
return status ;
return parseVssStoreBody ( vssIndex , 0 ) ;
}
2018-04-30 13:33:19 +08:00
else if ( ( UINT32 ) store . size ( ) > = sizeof ( EFI_GUID ) & & store . left ( sizeof ( EFI_GUID ) ) = = NVRAM_FDC_STORE_GUID ) {
2017-12-11 09:56:00 +08:00
UModelIndex vss2Index ;
2021-04-04 17:09:23 +08:00
status = parseVss2StoreHeader ( store , ( UINT32 ) ( localOffset + model - > header ( volumeIndex ) . size ( ) ) , true , volumeIndex , vss2Index ) ;
2017-12-11 09:56:00 +08:00
if ( status )
return status ;
return parseVssStoreBody ( vss2Index , 0 ) ;
}
else {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: internal volume can't be parsed as VSS/VSS2 store " , __FUNCTION__ ) , index ) ;
2017-12-11 09:56:00 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2017-12-11 09:56:00 +08:00
}
2017-07-31 14:06:11 +08:00
USTATUS NvramParser : : parseVssStoreBody ( const UModelIndex & index , UINT8 alignment )
2016-10-10 14:05:04 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Obtain required information from parent volume
UINT8 emptyByte = 0xFF ;
UModelIndex parentVolumeIndex = model - > findParentOfType ( index , Types : : Volume ) ;
if ( parentVolumeIndex . isValid ( ) & & model - > hasEmptyParsingData ( parentVolumeIndex ) = = false ) {
UByteArray data = model - > parsingData ( parentVolumeIndex ) ;
const VOLUME_PARSING_DATA * pdata = ( const VOLUME_PARSING_DATA * ) data . constData ( ) ;
2016-12-04 06:36:01 +08:00
emptyByte = pdata - > emptyByte ;
2016-10-28 00:31:15 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Get local offset
2021-04-04 17:09:23 +08:00
UINT32 localOffset = ( UINT32 ) model - > header ( index ) . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Get item data
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check that the is enough space for variable header
const UINT32 dataSize = ( UINT32 ) data . size ( ) ;
if ( dataSize < sizeof ( VSS_VARIABLE_HEADER ) ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: store body is too small even for VSS variable header " , __FUNCTION__ ) , index ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
UINT32 offset = 0 ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Parse all variables
while ( 1 ) {
2018-05-08 23:42:16 +08:00
bool isInvalid = true ;
2016-10-10 14:05:04 +08:00
bool isAuthenticated = false ;
bool isAppleCrc32 = false ;
2017-10-12 13:59:23 +08:00
bool isIntelSpecial = false ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
UINT32 storedCrc32 = 0 ;
UINT32 calculatedCrc32 = 0 ;
UINT64 monotonicCounter = 0 ;
2018-05-09 00:02:25 +08:00
EFI_TIME timestamp = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2016-10-10 14:05:04 +08:00
UINT32 pubKeyIndex = 0 ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
UINT8 subtype = 0 ;
UString name ;
UString text ;
2018-05-08 01:50:56 +08:00
EFI_GUID * variableGuid = NULL ;
2016-10-10 14:05:04 +08:00
CHAR16 * variableName = ( CHAR16 * ) L " " ;
UByteArray header ;
UByteArray body ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
UINT32 unparsedSize = dataSize - offset ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get variable header
const VSS_VARIABLE_HEADER * variableHeader = ( const VSS_VARIABLE_HEADER * ) ( data . constData ( ) + offset ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check variable header to fit in still unparsed data
UINT32 variableSize = 0 ;
2017-10-12 13:59:23 +08:00
if ( unparsedSize > = sizeof ( VSS_VARIABLE_HEADER )
2016-10-10 14:05:04 +08:00
& & variableHeader - > StartId = = NVRAM_VSS_VARIABLE_START_ID ) {
2021-10-07 23:51:39 +08:00
// Apple VSS variable with CRC32 of the data
2016-10-10 14:05:04 +08:00
if ( variableHeader - > Attributes & NVRAM_VSS_VARIABLE_APPLE_DATA_CHECKSUM ) {
isAppleCrc32 = true ;
if ( unparsedSize < sizeof ( VSS_APPLE_VARIABLE_HEADER ) ) {
variableSize = 0 ;
}
else {
const VSS_APPLE_VARIABLE_HEADER * appleVariableHeader = ( const VSS_APPLE_VARIABLE_HEADER * ) variableHeader ;
variableSize = sizeof ( VSS_APPLE_VARIABLE_HEADER ) + appleVariableHeader - > NameSize + appleVariableHeader - > DataSize ;
variableGuid = ( EFI_GUID * ) & appleVariableHeader - > VendorGuid ;
variableName = ( CHAR16 * ) ( appleVariableHeader + 1 ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
header = data . mid ( offset , sizeof ( VSS_APPLE_VARIABLE_HEADER ) + appleVariableHeader - > NameSize ) ;
body = data . mid ( offset + header . size ( ) , appleVariableHeader - > DataSize ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Calculate CRC32 of the variable data
storedCrc32 = appleVariableHeader - > DataCrc32 ;
2021-04-04 17:09:23 +08:00
calculatedCrc32 = ( UINT32 ) crc32 ( 0 , ( const UINT8 * ) body . constData ( ) , ( uInt ) body . size ( ) ) ;
2016-10-10 14:05:04 +08:00
}
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Authenticated variable
else if ( ( variableHeader - > Attributes & NVRAM_VSS_VARIABLE_AUTHENTICATED_WRITE_ACCESS )
2022-08-28 18:47:01 +08:00
| | ( variableHeader - > Attributes & NVRAM_VSS_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS )
| | ( variableHeader - > Attributes & NVRAM_VSS_VARIABLE_APPEND_WRITE )
| | ( variableHeader - > NameSize = = 0 & & variableHeader - > DataSize = = 0 ) ) { // If both NameSize and DataSize are zeros, it's auth variable with zero montonic counter
2016-10-10 14:05:04 +08:00
isAuthenticated = true ;
if ( unparsedSize < sizeof ( VSS_AUTH_VARIABLE_HEADER ) ) {
variableSize = 0 ;
}
else {
const VSS_AUTH_VARIABLE_HEADER * authVariableHeader = ( const VSS_AUTH_VARIABLE_HEADER * ) variableHeader ;
variableSize = sizeof ( VSS_AUTH_VARIABLE_HEADER ) + authVariableHeader - > NameSize + authVariableHeader - > DataSize ;
variableGuid = ( EFI_GUID * ) & authVariableHeader - > VendorGuid ;
variableName = ( CHAR16 * ) ( authVariableHeader + 1 ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
header = data . mid ( offset , sizeof ( VSS_AUTH_VARIABLE_HEADER ) + authVariableHeader - > NameSize ) ;
body = data . mid ( offset + header . size ( ) , authVariableHeader - > DataSize ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
monotonicCounter = authVariableHeader - > MonotonicCounter ;
timestamp = authVariableHeader - > Timestamp ;
pubKeyIndex = authVariableHeader - > PubKeyIndex ;
}
}
2022-08-28 18:47:01 +08:00
2017-10-12 13:59:23 +08:00
// Intel special variable
2018-05-08 23:42:16 +08:00
else if ( variableHeader - > State = = NVRAM_VSS_INTEL_VARIABLE_VALID
2022-08-28 18:47:01 +08:00
| | variableHeader - > State = = NVRAM_VSS_INTEL_VARIABLE_INVALID ) {
2017-10-12 13:59:23 +08:00
isIntelSpecial = true ;
const VSS_INTEL_VARIABLE_HEADER * intelVariableHeader = ( const VSS_INTEL_VARIABLE_HEADER * ) variableHeader ;
variableSize = intelVariableHeader - > TotalSize ;
variableGuid = ( EFI_GUID * ) & intelVariableHeader - > VendorGuid ;
variableName = ( CHAR16 * ) ( intelVariableHeader + 1 ) ;
2022-08-28 18:47:01 +08:00
2017-10-12 13:59:23 +08:00
UINT32 i = 0 ;
while ( variableName [ i ] ! = 0 ) + + i ;
2022-08-28 18:47:01 +08:00
2017-10-12 13:59:23 +08:00
i = sizeof ( VSS_INTEL_VARIABLE_HEADER ) + 2 * ( i + 1 ) ;
i = i < variableSize ? i : variableSize ;
2022-08-28 18:47:01 +08:00
2017-10-12 13:59:23 +08:00
header = data . mid ( offset , i ) ;
body = data . mid ( offset + header . size ( ) , variableSize - i ) ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Normal VSS variable
2018-05-08 23:42:16 +08:00
else {
2016-10-10 14:05:04 +08:00
variableSize = sizeof ( VSS_VARIABLE_HEADER ) + variableHeader - > NameSize + variableHeader - > DataSize ;
variableGuid = ( EFI_GUID * ) & variableHeader - > VendorGuid ;
variableName = ( CHAR16 * ) ( variableHeader + 1 ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
header = data . mid ( offset , sizeof ( VSS_VARIABLE_HEADER ) + variableHeader - > NameSize ) ;
body = data . mid ( offset + header . size ( ) , variableHeader - > DataSize ) ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check variable state
2018-05-08 23:42:16 +08:00
if ( variableHeader - > State = = NVRAM_VSS_INTEL_VARIABLE_VALID
| | variableHeader - > State = = NVRAM_VSS_VARIABLE_ADDED
| | variableHeader - > State = = NVRAM_VSS_VARIABLE_HEADER_VALID ) {
isInvalid = false ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check variable size
if ( variableSize > unparsedSize ) {
2017-07-23 02:43:20 +08:00
variableSize = 0 ;
2016-10-10 14:05:04 +08:00
}
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Can't parse further, add the last element and break the loop
if ( ! variableSize ) {
// Check if the data left is a free space or a padding
UByteArray padding = data . mid ( offset , unparsedSize ) ;
2016-10-28 00:31:15 +08:00
// Get info
2022-08-28 18:47:01 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) padding . size ( ) , ( UINT32 ) padding . size ( ) ) ;
2016-10-28 00:31:15 +08:00
if ( padding . count ( emptyByte ) = = padding . size ( ) ) { // Free space
// Add tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
2016-10-28 00:31:15 +08:00
else { // Padding
2021-10-07 23:51:39 +08:00
// Nothing is parsed yet, but the store is not empty
2016-10-10 14:05:04 +08:00
if ( ! offset ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: store can't be parsed as VSS store " , __FUNCTION__ ) , index ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Add tree item
model - > addItem ( localOffset + offset , Types : : Padding , getPaddingType ( padding ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
UString info ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Rename invalid variables
2018-05-08 01:50:56 +08:00
if ( isInvalid | | ! variableGuid ) {
2018-05-09 00:33:00 +08:00
isInvalid = true ;
2016-10-10 14:05:04 +08:00
name = UString ( " Invalid " ) ;
}
else { // Add GUID and text for valid variables
2023-03-12 23:49:19 +08:00
name = guidToUString ( readUnaligned ( variableGuid ) ) ;
info + = UString ( " Variable GUID: " ) + guidToUString ( readUnaligned ( variableGuid ) , false ) + " \n " ;
2023-02-01 12:15:12 +08:00
text = uFromUcs2 ( ( const char * ) variableName ) ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
2022-08-28 18:01:43 +08:00
info + = usprintf ( " Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n State: %02Xh \n Reserved: %02Xh \n Attributes: %08Xh ( " ,
2022-08-28 18:47:01 +08:00
variableSize , variableSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
variableHeader - > State ,
variableHeader - > Reserved ,
variableHeader - > Attributes ) + vssAttributesToUString ( variableHeader - > Attributes ) + UString ( " ) " ) ;
2016-10-10 14:05:04 +08:00
// Set subtype and add related info
if ( isInvalid )
subtype = Subtypes : : InvalidVssEntry ;
else if ( isAuthenticated ) {
subtype = Subtypes : : AuthVssEntry ;
info + = usprintf ( " \n Monotonic counter: % " PRIX64 " h \n Timestamp: " , monotonicCounter ) + efiTimeToUString ( timestamp )
2022-08-28 18:47:01 +08:00
+ usprintf ( " \n PubKey index: %u " , pubKeyIndex ) ;
2016-10-10 14:05:04 +08:00
}
else if ( isAppleCrc32 ) {
subtype = Subtypes : : AppleVssEntry ;
info + = usprintf ( " \n Data checksum: %08Xh " , storedCrc32 ) +
2022-08-28 18:47:01 +08:00
( storedCrc32 ! = calculatedCrc32 ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc32 ) : UString ( " , valid " ) ) ;
2016-10-10 14:05:04 +08:00
}
2017-10-12 13:59:23 +08:00
else if ( isIntelSpecial ) {
subtype = Subtypes : : IntelVssEntry ;
}
2018-05-08 23:42:16 +08:00
else {
2016-10-10 14:05:04 +08:00
subtype = Subtypes : : StandardVssEntry ;
2018-05-08 23:42:16 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : VssEntry , subtype , name , text , info , header , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2017-07-31 14:06:11 +08:00
// Apply alignment, if needed
if ( alignment ) {
variableSize = ( ( variableSize + alignment - 1 ) & ( ~ ( alignment - 1 ) ) ) ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Move to next variable
offset + = variableSize ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
USTATUS NvramParser : : parseFsysStoreBody ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Get local offset
2021-04-04 17:09:23 +08:00
UINT32 localOffset = ( UINT32 ) model - > header ( index ) . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Get item data
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check that the is enough space for variable header
2018-05-08 23:42:16 +08:00
const UINT32 storeDataSize = ( UINT32 ) data . size ( ) ;
2016-10-10 14:05:04 +08:00
UINT32 offset = 0 ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Parse all variables
while ( 1 ) {
2018-05-08 23:42:16 +08:00
UINT32 unparsedSize = storeDataSize - offset ;
2016-10-10 14:05:04 +08:00
UINT32 variableSize = 0 ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get nameSize and name of the variable
2016-12-23 06:34:24 +08:00
UINT8 nameSize = * ( UINT8 * ) ( data . constData ( ) + offset ) ;
bool valid = ! ( nameSize & 0x80 ) ; // Last bit is a validity bit, 0 means valid
nameSize & = 0x7F ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check sanity
if ( unparsedSize > = nameSize + sizeof ( UINT8 ) ) {
variableSize = nameSize + sizeof ( UINT8 ) ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
UByteArray name ;
if ( variableSize ) {
name = data . mid ( offset + sizeof ( UINT8 ) , nameSize ) ;
// Check for EOF variable
if ( nameSize = = 3 & & name [ 0 ] = = ' E ' & & name [ 1 ] = = ' O ' & & name [ 2 ] = = ' F ' ) {
// There is no data afterward, add EOF variable and free space and return
UByteArray header = data . mid ( offset , sizeof ( UINT8 ) + nameSize ) ;
2022-08-28 18:47:01 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add EOF tree item
2016-12-23 06:34:24 +08:00
model - > addItem ( localOffset + offset , Types : : FsysEntry , Subtypes : : NormalFsysEntry , UString ( " EOF " ) , UString ( ) , info , header , UByteArray ( ) , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add free space
2022-08-28 18:47:01 +08:00
offset + = ( UINT32 ) header . size ( ) ;
2016-10-10 14:05:04 +08:00
UByteArray body = data . mid ( offset ) ;
2022-08-28 18:47:01 +08:00
info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add free space tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get dataSize and data of the variable
const UINT16 dataSize = * ( UINT16 * ) ( data . constData ( ) + offset + sizeof ( UINT8 ) + nameSize ) ;
if ( unparsedSize > = sizeof ( UINT8 ) + nameSize + sizeof ( UINT16 ) + dataSize ) {
variableSize = sizeof ( UINT8 ) + nameSize + sizeof ( UINT16 ) + dataSize ;
}
else {
// Last variable is bad, add the rest as padding and return
UByteArray body = data . mid ( offset ) ;
2022-08-28 18:47:01 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-28 00:31:15 +08:00
// Add padding tree item
model - > addItem ( localOffset + offset , Types : : Padding , getPaddingType ( body ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Show message
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: next variable appears too big, added as padding " , __FUNCTION__ ) , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header and body
UByteArray header = data . mid ( offset , sizeof ( UINT8 ) + nameSize + sizeof ( UINT16 ) ) ;
UByteArray body = data . mid ( offset + sizeof ( UINT8 ) + nameSize + sizeof ( UINT16 ) , dataSize ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
2022-08-28 18:01:43 +08:00
UString info = usprintf ( " Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) " ,
2022-08-28 18:47:01 +08:00
variableSize , variableSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-10 14:05:04 +08:00
// Add tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : FsysEntry , valid ? Subtypes : : NormalFsysEntry : Subtypes : : InvalidFsysEntry , UString ( name . constData ( ) ) , UString ( ) , info , header , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Move to next variable
offset + = variableSize ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
USTATUS NvramParser : : parseEvsaStoreBody ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Obtain required information from parent volume
UINT8 emptyByte = 0xFF ;
UModelIndex parentVolumeIndex = model - > findParentOfType ( index , Types : : Volume ) ;
if ( parentVolumeIndex . isValid ( ) & & model - > hasEmptyParsingData ( parentVolumeIndex ) = = false ) {
UByteArray data = model - > parsingData ( parentVolumeIndex ) ;
const VOLUME_PARSING_DATA * pdata = ( const VOLUME_PARSING_DATA * ) data . constData ( ) ;
2016-12-04 06:36:01 +08:00
emptyByte = pdata - > emptyByte ;
2016-10-28 00:31:15 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Get local offset
2021-04-04 17:09:23 +08:00
UINT32 localOffset = ( UINT32 ) model - > header ( index ) . size ( ) ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Get item data
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check that the is enough space for entry header
2018-05-08 23:42:16 +08:00
const UINT32 storeDataSize = ( UINT32 ) data . size ( ) ;
2016-10-10 14:05:04 +08:00
UINT32 offset = 0 ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
std : : map < UINT16 , EFI_GUID > guidMap ;
std : : map < UINT16 , UString > nameMap ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Parse all entries
2018-05-08 23:42:16 +08:00
UINT32 unparsedSize = storeDataSize ;
2016-10-10 14:05:04 +08:00
while ( unparsedSize ) {
UINT32 variableSize = 0 ;
UString name ;
UString info ;
UByteArray header ;
UByteArray body ;
UINT8 subtype ;
UINT8 calculated ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
const EVSA_ENTRY_HEADER * entryHeader = ( const EVSA_ENTRY_HEADER * ) ( data . constData ( ) + offset ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check entry size
variableSize = sizeof ( EVSA_ENTRY_HEADER ) ;
2022-11-15 22:47:42 +08:00
if ( unparsedSize < variableSize | | unparsedSize < entryHeader - > Size | | entryHeader - > Size < 2 ) {
2018-05-08 23:42:16 +08:00
body = data . mid ( offset ) ;
2022-08-28 18:47:01 +08:00
info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-28 00:31:15 +08:00
if ( body . count ( emptyByte ) = = body . size ( ) ) { // Free space
// Add free space tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
2016-10-28 00:31:15 +08:00
else {
// Add padding tree item
UModelIndex itemIndex = model - > addItem ( localOffset + offset , Types : : Padding , getPaddingType ( body ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Show message
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: variable parsing failed, the rest of unparsed store added as padding " , __FUNCTION__ ) , itemIndex ) ;
2016-10-28 00:31:15 +08:00
}
2016-10-10 14:05:04 +08:00
break ;
}
variableSize = entryHeader - > Size ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Recalculate entry checksum
calculated = calculateChecksum8 ( ( ( const UINT8 * ) entryHeader ) + 2 , entryHeader - > Size - 2 ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// GUID entry
2017-12-11 09:56:00 +08:00
if ( entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_GUID1 | |
2016-10-10 14:05:04 +08:00
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_GUID2 ) {
const EVSA_GUID_ENTRY * guidHeader = ( const EVSA_GUID_ENTRY * ) entryHeader ;
header = data . mid ( offset , sizeof ( EVSA_GUID_ENTRY ) ) ;
body = data . mid ( offset + sizeof ( EVSA_GUID_ENTRY ) , guidHeader - > Header . Size - sizeof ( EVSA_GUID_ENTRY ) ) ;
2023-03-12 23:49:19 +08:00
EFI_GUID guid = * ( EFI_GUID * ) body . constData ( ) ;
name = guidToUString ( guid ) ;
info = UString ( " GUID: " ) + guidToUString ( guid , false )
2022-08-28 18:47:01 +08:00
+ usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Type: %02Xh \n Checksum: %02Xh " ,
variableSize , variableSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
guidHeader - > Header . Type ,
guidHeader - > Header . Checksum )
+ ( guidHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) )
+ usprintf ( " \n GuidId: %04Xh " , guidHeader - > GuidId ) ;
2016-10-10 14:05:04 +08:00
subtype = Subtypes : : GuidEvsaEntry ;
guidMap . insert ( std : : pair < UINT16 , EFI_GUID > ( guidHeader - > GuidId , guid ) ) ;
}
// Name entry
else if ( entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_NAME1 | |
2022-08-28 18:47:01 +08:00
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_NAME2 ) {
2016-10-10 14:05:04 +08:00
const EVSA_NAME_ENTRY * nameHeader = ( const EVSA_NAME_ENTRY * ) entryHeader ;
header = data . mid ( offset , sizeof ( EVSA_NAME_ENTRY ) ) ;
body = data . mid ( offset + sizeof ( EVSA_NAME_ENTRY ) , nameHeader - > Header . Size - sizeof ( EVSA_NAME_ENTRY ) ) ;
2023-02-01 12:15:12 +08:00
name = uFromUcs2 ( body . constData ( ) ) ;
2022-08-28 18:47:01 +08:00
info = UString ( " Name: " ) + name
+ usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Type: %02Xh \n Checksum: %02Xh " ,
variableSize , variableSize ,
( UINT32 ) header . size ( ) , ( UINT32 ) header . size ( ) ,
( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ,
nameHeader - > Header . Type ,
nameHeader - > Header . Checksum )
+ ( nameHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) )
+ usprintf ( " \n VarId: %04Xh " , nameHeader - > VarId ) ;
2016-10-10 14:05:04 +08:00
subtype = Subtypes : : NameEvsaEntry ;
nameMap . insert ( std : : pair < UINT16 , UString > ( nameHeader - > VarId , name ) ) ;
}
// Data entry
else if ( entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA1 | |
2022-08-28 18:47:01 +08:00
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA2 | |
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID ) {
2016-10-10 14:05:04 +08:00
const EVSA_DATA_ENTRY * dataHeader = ( const EVSA_DATA_ENTRY * ) entryHeader ;
// Check for extended header
UINT32 headerSize = sizeof ( EVSA_DATA_ENTRY ) ;
UINT32 dataSize = dataHeader - > Header . Size - sizeof ( EVSA_DATA_ENTRY ) ;
if ( dataHeader - > Attributes & NVRAM_EVSA_DATA_EXTENDED_HEADER ) {
const EVSA_DATA_ENTRY_EXTENDED * dataHeaderExtended = ( const EVSA_DATA_ENTRY_EXTENDED * ) entryHeader ;
headerSize = sizeof ( EVSA_DATA_ENTRY_EXTENDED ) ;
dataSize = dataHeaderExtended - > DataSize ;
variableSize = headerSize + dataSize ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
header = data . mid ( offset , headerSize ) ;
body = data . mid ( offset + headerSize , dataSize ) ;
name = UString ( " Data " ) ;
2021-10-07 23:51:39 +08:00
info = usprintf ( " Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Type: %02Xh \n Checksum: %02Xh " ,
2022-08-28 18:47:01 +08:00
variableSize , variableSize ,
headerSize , headerSize ,
dataSize , dataSize ,
dataHeader - > Header . Type ,
dataHeader - > Header . Checksum )
+ ( dataHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) )
+ usprintf ( " \n VarId: %04Xh \n GuidId: %04Xh \n Attributes: %08Xh ( " ,
dataHeader - > VarId ,
dataHeader - > GuidId ,
dataHeader - > Attributes )
+ evsaAttributesToUString ( dataHeader - > Attributes ) + UString ( " ) " ) ;
2016-10-10 14:05:04 +08:00
subtype = Subtypes : : DataEvsaEntry ;
}
// Unknown entry or free space
else {
2018-05-08 23:42:16 +08:00
body = data . mid ( offset ) ;
2022-08-28 18:47:01 +08:00
info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-28 00:31:15 +08:00
if ( body . count ( emptyByte ) = = body . size ( ) ) { // Free space
// Add free space tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
}
2016-10-28 00:31:15 +08:00
else {
// Add padding tree item
UModelIndex itemIndex = model - > addItem ( localOffset + offset , Types : : Padding , getPaddingType ( body ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-28 00:31:15 +08:00
// Show message
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: unknown variable of type %02Xh found at offset %Xh, the rest of unparsed store added as padding " , __FUNCTION__ , entryHeader - > Type , offset ) , itemIndex ) ;
2017-12-11 09:56:00 +08:00
}
2016-10-10 14:05:04 +08:00
break ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : EvsaEntry , subtype , name , UString ( ) , info , header , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Move to next variable
offset + = variableSize ;
2018-05-08 23:42:16 +08:00
unparsedSize = storeDataSize - offset ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Reparse all data variables to detect invalid ones and assign name and test to valid ones
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2021-04-04 17:09:23 +08:00
UModelIndex current = index . model ( ) - > index ( i , 0 , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
if ( model - > subtype ( current ) = = Subtypes : : DataEvsaEntry ) {
UByteArray header = model - > header ( current ) ;
const EVSA_DATA_ENTRY * dataHeader = ( const EVSA_DATA_ENTRY * ) header . constData ( ) ;
UString guid ;
2017-12-11 09:56:00 +08:00
if ( guidMap . count ( dataHeader - > GuidId ) )
2023-03-12 23:49:19 +08:00
guid = guidToUString ( guidMap [ dataHeader - > GuidId ] , false ) ;
2016-10-10 14:05:04 +08:00
UString name ;
if ( nameMap . count ( dataHeader - > VarId ) )
name = nameMap [ dataHeader - > VarId ] ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check for variable validity
if ( guid . isEmpty ( ) & & name . isEmpty ( ) ) { // Both name and guid aren't found
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
model - > setName ( current , UString ( " Invalid " ) ) ;
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: data variable with invalid GuidId and invalid VarId " , __FUNCTION__ ) , current ) ;
2016-10-10 14:05:04 +08:00
}
else if ( guid . isEmpty ( ) ) { // Guid not found
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
model - > setName ( current , UString ( " Invalid " ) ) ;
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: data variable with invalid GuidId " , __FUNCTION__ ) , current ) ;
2016-10-10 14:05:04 +08:00
}
else if ( name . isEmpty ( ) ) { // Name not found
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
model - > setName ( current , UString ( " Invalid " ) ) ;
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: data variable with invalid VarId " , __FUNCTION__ ) , current ) ;
2016-10-10 14:05:04 +08:00
}
else { // Variable is OK, rename it
if ( dataHeader - > Header . Type = = NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID ) {
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
model - > setName ( current , UString ( " Invalid " ) ) ;
}
else {
model - > setName ( current , guid ) ;
}
model - > setText ( current , name ) ;
2022-08-29 14:23:38 +08:00
model - > addInfo ( current , UString ( " GUID: " ) + guid + UString ( " \n Name: " ) + name + " \n " , false ) ;
2016-10-10 14:05:04 +08:00
}
}
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
USTATUS NvramParser : : parseFlashMapBody ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Get parsing data for the current item
2021-04-04 17:09:23 +08:00
UINT32 localOffset = ( UINT32 ) model - > header ( index ) . size ( ) ;
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
const UINT32 dataSize = ( UINT32 ) data . size ( ) ;
UINT32 offset = 0 ;
UINT32 unparsedSize = dataSize ;
// Parse all entries
while ( unparsedSize ) {
const PHOENIX_FLASH_MAP_ENTRY * entryHeader = ( const PHOENIX_FLASH_MAP_ENTRY * ) ( data . constData ( ) + offset ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Check entry size
if ( unparsedSize < sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ) {
// Last variable is bad, add the rest as padding and return
UByteArray body = data . mid ( offset ) ;
2022-08-28 18:47:01 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , ( UINT32 ) body . size ( ) , ( UINT32 ) body . size ( ) ) ;
2016-10-28 00:31:15 +08:00
// Add padding tree item
model - > addItem ( localOffset + offset , Types : : Padding , getPaddingType ( body ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Show message
if ( unparsedSize < entryHeader - > Size )
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: next entry appears too big, added as padding " , __FUNCTION__ ) , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
break ;
}
2022-08-28 18:47:01 +08:00
2023-03-12 23:49:19 +08:00
UString name = guidToUString ( entryHeader - > Guid ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Construct header
UByteArray header = data . mid ( offset , sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add info
2023-03-12 23:49:19 +08:00
UString info = UString ( " Entry GUID: " ) + guidToUString ( entryHeader - > Guid , false ) +
2022-08-28 18:47:01 +08:00
usprintf ( " \n Full size: 24h (36) \n Header size: 24h (36) \n Body size: 0h (0) \n "
2022-08-29 14:23:38 +08:00
" Entry type: %04Xh \n Data type: %04Xh \n Memory address: %08Xh \n Size: %08Xh \n Offset: %08Xh " ,
2022-08-28 18:47:01 +08:00
entryHeader - > EntryType ,
entryHeader - > DataType ,
2022-08-29 14:23:38 +08:00
( UINT32 ) entryHeader - > PhysicalAddress ,
2022-08-28 18:47:01 +08:00
entryHeader - > Size ,
entryHeader - > Offset ) ;
2016-10-10 14:05:04 +08:00
// Determine subtype
UINT8 subtype = 0 ;
switch ( entryHeader - > DataType ) {
2022-08-28 18:47:01 +08:00
case NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_VOLUME :
subtype = Subtypes : : VolumeFlashMapEntry ;
break ;
case NVRAM_PHOENIX_FLASH_MAP_ENTRY_TYPE_DATA_BLOCK :
subtype = Subtypes : : DataFlashMapEntry ;
break ;
2016-10-10 14:05:04 +08:00
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Add tree item
2019-01-07 21:05:57 +08:00
model - > addItem ( localOffset + offset , Types : : FlashMapEntry , subtype , name , flashMapGuidToUString ( entryHeader - > Guid ) , info , header , UByteArray ( ) , UByteArray ( ) , Fixed , index ) ;
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
// Move to next variable
offset + = sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ;
unparsedSize = dataSize - offset ;
}
2022-08-28 18:47:01 +08:00
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
# endif // U_ENABLE_NVRAM_PARSING_SUPPORT