2016-10-10 14:05:04 +08:00
/* nvramparser.cpp
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 .
*/
2018-05-08 15:48:04 +08:00
// A workaround for compilers not supporting c++11 and c11
// for using PRIX64.
# define __STDC_FORMAT_MACROS
2018-05-08 08:02:07 +08:00
# include <inttypes.h>
2016-11-03 03:40:38 +08:00
# include <map>
2016-10-10 14:05:04 +08:00
# include "nvramparser.h"
# include "parsingdata.h"
# include "utility.h"
# include "nvram.h"
# include "ffs.h"
# include "fit.h"
# ifdef U_ENABLE_NVRAM_PARSING_SUPPORT
USTATUS NvramParser : : parseNvarStore ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2016-10-28 00:31:15 +08:00
// Obtain required information from parent file
UINT8 emptyByte = 0xFF ;
UModelIndex parentFileIndex = model - > findParentOfType ( index , Types : : File ) ;
if ( parentFileIndex . isValid ( ) & & model - > hasEmptyParsingData ( parentFileIndex ) = = false ) {
2017-02-12 15:28:33 +08:00
UByteArray data = model - > parsingData ( parentFileIndex ) ;
2016-10-28 00:31:15 +08:00
const FILE_PARSING_DATA * pdata = ( const FILE_PARSING_DATA * ) data . constData ( ) ;
emptyByte = pdata - > emptyByte ;
}
// Rename parent file
model - > setText ( parentFileIndex , UString ( " NVAR store " ) ) ;
// Get local offset
UINT32 localOffset = model - > offset ( index ) + model - > header ( index ) . size ( ) ;
2016-10-10 14:05:04 +08:00
// Get item data
const UByteArray data = model - > body ( index ) ;
2016-10-28 00:31:15 +08:00
// Parse all entries
2016-10-10 14:05:04 +08:00
UINT32 offset = 0 ;
UINT32 guidsInStore = 0 ;
while ( 1 ) {
bool msgUnknownExtDataFormat = false ;
bool msgExtHeaderTooLong = false ;
bool msgExtDataTooShort = false ;
bool isInvalid = false ;
bool isInvalidLink = false ;
bool hasExtendedHeader = false ;
bool hasChecksum = false ;
bool hasTimestamp = false ;
bool hasHash = false ;
bool hasGuidIndex = false ;
UINT32 guidIndex = 0 ;
UINT8 storedChecksum = 0 ;
UINT8 calculatedChecksum = 0 ;
UINT32 extendedHeaderSize = 0 ;
UINT8 extendedAttributes = 0 ;
UINT64 timestamp = 0 ;
UByteArray hash ;
UINT8 subtype = Subtypes : : FullNvarEntry ;
UString name ;
2017-02-14 14:39:16 +08:00
UString guid ;
2016-10-10 14:05:04 +08:00
UString text ;
UByteArray header ;
UByteArray body ;
UByteArray tail ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
UINT32 guidAreaSize = guidsInStore * sizeof ( EFI_GUID ) ;
UINT32 unparsedSize = ( UINT32 ) data . size ( ) - offset - guidAreaSize ;
// Get entry header
const NVAR_ENTRY_HEADER * entryHeader = ( const NVAR_ENTRY_HEADER * ) ( data . constData ( ) + offset ) ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Check header size and signature
if ( unparsedSize < sizeof ( NVAR_ENTRY_HEADER ) | |
entryHeader - > Signature ! = NVRAM_NVAR_ENTRY_SIGNATURE | |
unparsedSize < entryHeader - > Size ) {
// 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
UString info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
if ( ( UINT32 ) padding . count ( emptyByte ) = = unparsedSize ) { // Free space
// Add tree item
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Movable , index ) ;
2016-10-10 14:05:04 +08:00
}
else {
// Nothing is parsed yet, but the file is not empty
if ( ! offset ) {
2018-04-30 13:33:19 +08:00
msg ( usprintf ( " %s: file can't be parsed as NVAR variables store " , __FUNCTION__ ) , index ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
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
}
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Add GUID store area
UByteArray guidArea = data . right ( guidAreaSize ) ;
// Get info
2016-12-04 06:36:01 +08:00
name = UString ( " GUID store " ) ;
2016-10-10 14:05:04 +08:00
info = usprintf ( " Full size: %Xh (%u) \n GUIDs in store: %u " ,
guidArea . size ( ) , guidArea . size ( ) ,
guidsInStore ) ;
// Add tree item
2016-10-28 00:31:15 +08:00
model - > addItem ( localOffset + offset + padding . size ( ) , Types : : Padding , getPaddingType ( guidArea ) , name , UString ( ) , info , UByteArray ( ) , guidArea , UByteArray ( ) , Fixed , index ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Contruct generic header and body
header = data . mid ( offset , sizeof ( NVAR_ENTRY_HEADER ) ) ;
body = data . mid ( offset + sizeof ( NVAR_ENTRY_HEADER ) , entryHeader - > Size - sizeof ( NVAR_ENTRY_HEADER ) ) ;
2016-10-28 00:31:15 +08:00
UINT32 lastVariableFlag = emptyByte ? 0xFFFFFF : 0 ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Set default next to predefined last value
2016-10-28 00:31:15 +08:00
NVAR_ENTRY_PARSING_DATA pdata ;
pdata . emptyByte = emptyByte ;
pdata . next = lastVariableFlag ;
2016-10-10 14:05:04 +08:00
// Entry is marked as invalid
if ( ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_VALID ) = = 0 ) { // Valid attribute is not set
isInvalid = true ;
// Do not parse further
goto parsing_done ;
}
// Add next node information to parsing data
if ( entryHeader - > Next ! = lastVariableFlag ) {
subtype = Subtypes : : LinkNvarEntry ;
2016-10-28 00:31:15 +08:00
pdata . next = entryHeader - > Next ;
2016-10-10 14:05:04 +08:00
}
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Entry with extended header
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_EXT_HEADER ) {
hasExtendedHeader = true ;
msgUnknownExtDataFormat = true ;
2018-10-08 17:58:12 +08:00
extendedHeaderSize = readMisaligned ( ( UINT16 * ) ( body . constData ( ) + body . size ( ) - sizeof ( UINT16 ) ) ) ;
2016-10-10 14:05:04 +08:00
if ( extendedHeaderSize > ( UINT32 ) body . size ( ) ) {
msgExtHeaderTooLong = true ;
isInvalid = true ;
// Do not parse further
goto parsing_done ;
}
extendedAttributes = * ( UINT8 * ) ( body . constData ( ) + body . size ( ) - extendedHeaderSize ) ;
// Variable with checksum
if ( extendedAttributes & NVRAM_NVAR_ENTRY_EXT_CHECKSUM ) {
// Get stored checksum
storedChecksum = * ( UINT8 * ) ( body . constData ( ) + body . size ( ) - sizeof ( UINT16 ) - sizeof ( UINT8 ) ) ;
// Recalculate checksum for the variable
calculatedChecksum = 0 ;
// Include entry data
UINT8 * start = ( UINT8 * ) ( entryHeader + 1 ) ;
for ( UINT8 * p = start ; p < start + entryHeader - > Size - sizeof ( NVAR_ENTRY_HEADER ) ; 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 ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
hasChecksum = true ;
msgUnknownExtDataFormat = false ;
}
tail = body . mid ( body . size ( ) - extendedHeaderSize ) ;
body = body . left ( body . size ( ) - extendedHeaderSize ) ;
// Entry with authenticated write (for SecureBoot)
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_AUTH_WRITE ) {
if ( ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY ) ) { // Data only auth. variables has no hash
if ( ( UINT32 ) tail . size ( ) < sizeof ( UINT64 ) ) {
msgExtDataTooShort = true ;
isInvalid = true ;
// Do not parse further
goto parsing_done ;
}
2018-10-08 17:58:12 +08:00
timestamp = readMisaligned ( tail . constData ( ) + sizeof ( UINT8 ) ) ;
2016-10-10 14:05:04 +08:00
hasTimestamp = true ;
msgUnknownExtDataFormat = false ;
}
else { // Full or link variable have hash
2017-12-11 09:56:00 +08:00
if ( ( UINT32 ) tail . size ( ) < sizeof ( UINT64 ) + SHA256_HASH_SIZE ) {
2016-10-10 14:05:04 +08:00
msgExtDataTooShort = true ;
isInvalid = true ;
// Do not parse further
goto parsing_done ;
}
2018-10-08 17:58:12 +08:00
timestamp = readMisaligned ( ( UINT64 * ) ( tail . constData ( ) ) + sizeof ( UINT8 ) ) ;
2016-10-10 14:05:04 +08:00
hash = tail . mid ( sizeof ( UINT64 ) + sizeof ( UINT8 ) , SHA256_HASH_SIZE ) ;
hasTimestamp = true ;
hasHash = true ;
msgUnknownExtDataFormat = false ;
}
}
}
// Entry is data-only (nameless and GUIDless entry or link)
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY ) { // Data-only attribute is set
isInvalidLink = true ;
UModelIndex nvarIndex ;
// Search prevously added entries for a link to this variable
2018-04-30 13:33:19 +08:00
// WARNING: O(n^2), may be very slow
for ( int i = model - > rowCount ( index ) - 1 ; i > = 0 ; i - - ) {
2016-10-10 14:05:04 +08:00
nvarIndex = index . child ( i , 0 ) ;
2016-10-28 00:31:15 +08:00
if ( model - > hasEmptyParsingData ( nvarIndex ) = = false ) {
UByteArray nvarData = model - > parsingData ( nvarIndex ) ;
const NVAR_ENTRY_PARSING_DATA * nvarPdata = ( const NVAR_ENTRY_PARSING_DATA * ) nvarData . constData ( ) ;
if ( nvarPdata - > isValid & & nvarPdata - > next + model - > offset ( nvarIndex ) - localOffset = = offset ) { // Previous link is present and valid
isInvalidLink = false ;
break ;
}
2016-10-10 14:05:04 +08:00
}
}
// Check if the link is valid
if ( ! isInvalidLink ) {
// Use the name and text of the previous link
name = model - > name ( nvarIndex ) ;
text = model - > text ( nvarIndex ) ;
if ( entryHeader - > Next = = lastVariableFlag )
subtype = Subtypes : : DataNvarEntry ;
}
//isDataOnly = true;
// Do not parse further
goto parsing_done ;
}
// Get entry name
{
UINT32 nameOffset = ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_GUID ) ? sizeof ( EFI_GUID ) : sizeof ( UINT8 ) ; // GUID can be stored with the variable or in a separate store, so there will only be an index of it
CHAR8 * namePtr = ( CHAR8 * ) ( entryHeader + 1 ) + nameOffset ;
UINT32 nameSize = 0 ;
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_ASCII_NAME ) { // Name is stored as ASCII string of CHAR8s
text = UString ( namePtr ) ;
nameSize = text . length ( ) + 1 ;
}
else { // Name is stored as UCS2 string of CHAR16s
text = UString : : fromUtf16 ( ( CHAR16 * ) namePtr ) ;
nameSize = ( text . length ( ) + 1 ) * 2 ;
}
// Get entry GUID
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_GUID ) { // GUID is strored in the variable itself
2018-10-08 17:58:12 +08:00
name = guidToUString ( readMisaligned ( ( EFI_GUID * ) ( entryHeader + 1 ) ) ) ;
guid = guidToUString ( readMisaligned ( ( EFI_GUID * ) ( entryHeader + 1 ) ) , false ) ;
2016-10-10 14:05:04 +08:00
}
// GUID is stored in GUID list at the end of the store
else {
guidIndex = * ( UINT8 * ) ( entryHeader + 1 ) ;
if ( guidsInStore < guidIndex + 1 )
guidsInStore = guidIndex + 1 ;
// The list begins at the end of the store and goes backwards
const EFI_GUID * guidPtr = ( const EFI_GUID * ) ( data . constData ( ) + data . size ( ) ) - 1 - guidIndex ;
2018-10-08 17:58:12 +08:00
name = guidToUString ( readMisaligned ( guidPtr ) ) ;
guid = guidToUString ( readMisaligned ( guidPtr ) , false ) ;
2016-10-10 14:05:04 +08:00
hasGuidIndex = true ;
}
// Include name and GUID into the header and remove them from body
header = data . mid ( offset , sizeof ( NVAR_ENTRY_HEADER ) + nameOffset + nameSize ) ;
body = body . mid ( nameOffset + nameSize ) ;
}
2017-12-11 09:56:00 +08:00
parsing_done :
2016-10-10 14:05:04 +08:00
UString info ;
// Rename invalid entries according to their types
2016-10-28 00:31:15 +08:00
pdata . isValid = TRUE ;
2016-10-10 14:05:04 +08:00
if ( isInvalid ) {
name = UString ( " Invalid " ) ;
subtype = Subtypes : : InvalidNvarEntry ;
2016-10-28 00:31:15 +08:00
pdata . isValid = FALSE ;
2016-10-10 14:05:04 +08:00
}
else if ( isInvalidLink ) {
name = UString ( " Invalid link " ) ;
subtype = Subtypes : : InvalidLinkNvarEntry ;
2016-10-28 00:31:15 +08:00
pdata . isValid = FALSE ;
2016-10-10 14:05:04 +08:00
}
else // Add GUID info for valid entries
2017-02-14 14:39:16 +08:00
info + = UString ( " Variable GUID: " ) + guid + UString ( " \n " ) ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Add GUID index information
if ( hasGuidIndex )
info + = usprintf ( " GUID index: %u \n " , guidIndex ) ;
// Add header, body and extended data info
info + = usprintf ( " Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) " ,
entryHeader - > Size , entryHeader - > Size ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ) ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Add attributes info
info + = usprintf ( " \n Attributes: %02Xh " , entryHeader - > Attributes ) ;
// Translate attributes to text
if ( entryHeader - > Attributes & & entryHeader - > Attributes ! = 0xFF )
info + = UString ( " ( " ) + nvarAttributesToUString ( entryHeader - > Attributes ) + UString ( " ) " ) ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Add next node info
if ( ! isInvalid & & entryHeader - > Next ! = lastVariableFlag )
2016-10-28 00:31:15 +08:00
info + = usprintf ( " \n Next node at offset: %Xh " , localOffset + offset + entryHeader - > Next ) ;
2016-10-10 14:05:04 +08:00
// Add extended header info
if ( hasExtendedHeader ) {
info + = usprintf ( " \n Extended header size: %Xh (%u) \n Extended attributes: %Xh ( " ,
extendedHeaderSize , extendedHeaderSize ,
extendedAttributes ) + nvarExtendedAttributesToUString ( extendedAttributes ) + UString ( " ) " ) ;
// Add checksum
if ( hasChecksum )
info + = usprintf ( " \n Checksum: %02Xh " , storedChecksum ) +
2017-12-11 09:56:00 +08:00
( calculatedChecksum ? usprintf ( " , invalid, should be %02Xh " , 0x100 - calculatedChecksum ) : UString ( " , valid " ) ) ;
2016-10-10 14:05:04 +08:00
// Add timestamp
2017-12-11 09:56:00 +08:00
if ( hasTimestamp )
2016-10-10 14:05:04 +08:00
info + = usprintf ( " \n Timestamp: % " PRIX64 " h " , timestamp ) ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Add hash
2017-12-11 09:56:00 +08:00
if ( hasHash )
2016-10-10 14:05:04 +08:00
info + = UString ( " \n Hash: " ) + UString ( hash . toHex ( ) . constData ( ) ) ;
}
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
UModelIndex varIndex = model - > addItem ( localOffset + offset , Types : : NvarEntry , subtype , name , text , info , header , body , tail , Movable , index ) ;
// Set parsing data for created entry
model - > setParsingData ( varIndex , UByteArray ( ( const char * ) & pdata , sizeof ( pdata ) ) ) ;
2016-10-10 14:05:04 +08:00
// Show messages
2018-04-30 13:33:19 +08:00
if ( msgUnknownExtDataFormat ) msg ( usprintf ( " %s: unknown extended data format " , __FUNCTION__ ) , varIndex ) ;
if ( msgExtHeaderTooLong ) msg ( usprintf ( " %s: extended header size (%Xh) is greater than body size (%Xh) " , __FUNCTION__ ,
2017-12-11 09:56:00 +08:00
extendedHeaderSize , body . size ( ) ) , varIndex ) ;
2018-04-30 13:33:19 +08:00
if ( msgExtDataTooShort ) msg ( usprintf ( " %s: extended header size (%Xh) is too small for timestamp and hash " , __FUNCTION__ ,
2017-12-11 09:56:00 +08:00
tail . size ( ) ) , varIndex ) ;
2016-10-10 14:05:04 +08:00
// Try parsing the entry data as NVAR storage if it begins with NVAR signature
2017-12-11 09:56:00 +08:00
if ( ( subtype = = Subtypes : : DataNvarEntry | | subtype = = Subtypes : : FullNvarEntry )
2018-10-08 17:58:12 +08:00
& & body . size ( ) > = 4 & & * ( const UINT32 * ) body . constData ( ) = = NVRAM_NVAR_ENTRY_SIGNATURE )
2016-10-10 14:05:04 +08:00
parseNvarStore ( varIndex ) ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Move to next exntry
offset + = entryHeader - > Size ;
}
2017-12-11 09:56:00 +08:00
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 ;
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 ;
}
// Get local offset
UINT32 localOffset = model - > offset ( index ) + model - > header ( index ) . size ( ) ;
2016-10-10 14:05:04 +08:00
// Get item data
UByteArray data = model - > body ( index ) ;
// 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 ;
// 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 " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
// 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
}
// Search for and parse all stores
UINT32 storeOffset = prevStoreOffset ;
UINT32 prevStoreSize = 0 ;
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 ) ;
// Get info
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
// 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
}
// 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 ;
}
// 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 ) ;
// Get info
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
// 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 ) ;
2016-10-10 14:05:04 +08:00
// Update variables
prevStoreOffset = storeOffset ;
prevStoreSize = padding . size ( ) ;
break ;
}
// 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 ) ;
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
}
// 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
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
if ( padding . count ( emptyByte ) = = padding . size ( ) ) { // Free space
// Add tree item
model - > addItem ( localOffset + storeOffset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Movable , index ) ;
2016-10-10 14:05:04 +08:00
}
else {
// Nothing is parsed yet, but the file is not empty
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 ;
}
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
}
}
// Parse bodies
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
UModelIndex current = index . child ( i , 0 ) ;
switch ( model - > type ( current ) ) {
2018-08-02 08:41:11 +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!
2018-08-02 08:51:52 +08:00
break ;
2016-10-10 14:05:04 +08:00
}
}
2017-12-11 09:56:00 +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
{
UINT32 dataSize = volume . size ( ) ;
if ( dataSize < sizeof ( UINT32 ) )
return U_STORES_NOT_FOUND ;
UINT32 offset = storeOffset ;
for ( ; offset < dataSize - sizeof ( UINT32 ) ; offset + + ) {
const UINT32 * currentPos = ( const UINT32 * ) ( volume . constData ( ) + offset ) ;
if ( * currentPos = = NVRAM_VSS_STORE_SIGNATURE | | * currentPos = = NVRAM_APPLE_SVS_STORE_SIGNATURE ) { //$VSS or $SVS signatures found, perform checks
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 ;
}
2017-12-11 09:56:00 +08:00
else if ( * currentPos = = NVRAM_VSS2_AUTH_VAR_KEY_DATABASE_GUID_PART1 | | * 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 ;
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 ;
}
2016-10-10 14:05:04 +08:00
else if ( * currentPos = = NVRAM_FDC_VOLUME_SIGNATURE ) { //FDC signature found
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 ;
}
else if ( * currentPos = = NVRAM_APPLE_FSYS_STORE_SIGNATURE | | * currentPos = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) { //Fsys or Gaid signature found
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 ;
}
else if ( * currentPos = = NVRAM_EVSA_STORE_SIGNATURE ) { //EVSA signature found
if ( offset < sizeof ( UINT32 ) )
continue ;
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 ;
}
else if ( * currentPos = = NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 | | * currentPos = = EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 ) { //Possible FTW block signature found
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 ;
// 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 ) {
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 , ftw64Header - > WriteQueueSize ) , index ) ;
2016-10-10 14:05:04 +08:00
continue ;
}
}
else // Unknown header
continue ;
// All checks passed, store found
break ;
}
else if ( * currentPos = = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 ) { // Phoenix SCT flash map
UByteArray signature = UByteArray ( volume . constData ( ) + offset , NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH ) ;
if ( signature ! = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE ) // Check the whole signature
continue ;
// All checks passed, store found
break ;
}
else if ( * currentPos = = NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE ) { // Phoenix SCT CMDB store
const PHOENIX_CMDB_HEADER * cmdbHeader = ( const PHOENIX_CMDB_HEADER * ) currentPos ;
// Check size
if ( cmdbHeader - > HeaderSize ! = sizeof ( PHOENIX_CMDB_HEADER ) )
continue ;
// All checks passed, store found
break ;
}
else if ( * currentPos = = INTEL_MICROCODE_HEADER_VERSION ) { // Intel microcode
if ( ! INTEL_MICROCODE_HEADER_SIZES_VALID ( currentPos ) ) // Check header sizes
continue ;
// Check reserved bytes
const INTEL_MICROCODE_HEADER * ucodeHeader = ( const INTEL_MICROCODE_HEADER * ) currentPos ;
bool reservedBytesValid = true ;
for ( UINT32 i = 0 ; i < sizeof ( ucodeHeader - > Reserved ) ; i + + )
if ( ucodeHeader - > Reserved [ i ] ! = INTEL_MICROCODE_HEADER_RESERVED_BYTE ) {
reservedBytesValid = false ;
break ;
}
if ( ! reservedBytesValid )
continue ;
// All checks passed, store found
break ;
}
else if ( * currentPos = = OEM_ACTIVATION_PUBKEY_MAGIC ) { // SLIC pubkey
if ( offset < 4 * sizeof ( UINT32 ) )
continue ;
const OEM_ACTIVATION_PUBKEY * pubkeyHeader = ( const OEM_ACTIVATION_PUBKEY * ) ( currentPos - 4 ) ;
// Check type
if ( pubkeyHeader - > Type ! = OEM_ACTIVATION_PUBKEY_TYPE )
continue ;
// All checks passed, store found
offset - = 4 * sizeof ( UINT32 ) ;
break ;
}
else if ( * currentPos = = OEM_ACTIVATION_MARKER_WINDOWS_FLAG_PART1 ) { // SLIC marker
2017-12-11 09:56:00 +08:00
if ( offset > = dataSize - sizeof ( UINT64 ) | |
2016-10-10 14:05:04 +08:00
* ( const UINT64 * ) currentPos ! = OEM_ACTIVATION_MARKER_WINDOWS_FLAG | |
offset < 26 ) // Check full windows flag and structure size
continue ;
2017-12-11 09:56:00 +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 ;
// All checks passed, store found
offset - = 26 ;
break ;
}
}
// No more stores found
if ( offset > = dataSize - sizeof ( UINT32 ) )
return U_STORES_NOT_FOUND ;
nextStoreOffset = offset ;
return U_SUCCESS ;
}
USTATUS NvramParser : : getStoreSize ( const UByteArray & data , const UINT32 storeOffset , UINT32 & storeSize )
{
const UINT32 * signature = ( const UINT32 * ) ( data . constData ( ) + storeOffset ) ;
if ( * signature = = NVRAM_VSS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE ) {
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 ;
}
else if ( * signature = = INTEL_MICROCODE_HEADER_VERSION ) { // Intel microcode, must be checked after SLIC marker because of the same *signature values
const INTEL_MICROCODE_HEADER * ucodeHeader = ( const INTEL_MICROCODE_HEADER * ) signature ;
storeSize = ucodeHeader - > TotalSize ;
}
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
2017-12-11 09:56:00 +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 ;
}
// Get VSS store header
const VSS_VARIABLE_STORE_HEADER * vssStoreHeader = ( const VSS_VARIABLE_STORE_HEADER * ) store . constData ( ) ;
2017-12-11 09:56:00 +08:00
// Check for size override
UINT32 storeSize = vssStoreHeader - > Size ;
if ( sizeOverride ) {
storeSize = dataSize ;
}
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__ ,
2017-12-11 09:56:00 +08:00
storeSize , storeSize ,
2016-10-10 14:05:04 +08:00
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// 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 ) ) ;
2016-10-10 14:05:04 +08:00
// Add info
bool isSvsStore = ( vssStoreHeader - > Signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE ) ;
UString name = isSvsStore ? UString ( " SVS store " ) : UString ( " VSS store " ) ;
UString info = usprintf ( " Signature: %s \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Format: %02Xh \n State: %02Xh \n Unknown: %04Xh " ,
isSvsStore ? " $SVS " : " $VSS " ,
2017-12-11 09:56:00 +08:00
storeSize , storeSize ,
2016-10-10 14:05:04 +08:00
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
vssStoreHeader - > Format ,
2017-12-11 09:56:00 +08:00
vssStoreHeader - > State ,
2016-10-10 14:05:04 +08:00
vssStoreHeader - > Unknown ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
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 ( ) ;
// Check for size override
UINT32 storeSize = vssStoreHeader - > Size ;
if ( sizeOverride ) {
storeSize = dataSize ;
}
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__ ,
2017-12-11 09:56:00 +08:00
storeSize , storeSize ,
2017-07-31 14:06:11 +08:00
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// 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 ) ) ;
2017-07-31 14:06:11 +08:00
// Add info
2017-12-11 09:56:00 +08:00
UString name = UString ( " VSS2 store " ) ;
2017-07-31 14:06:11 +08:00
UString info = UString ( " Signature: " ) + guidToUString ( vssStoreHeader - > Signature , false ) +
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 " ,
2017-12-11 09:56:00 +08:00
storeSize , storeSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
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
}
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 ( ) ;
// 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__ ,
2016-10-10 14:05:04 +08:00
ftwBlockSize , ftwBlockSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// 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 ) ;
// 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 ;
2016-10-10 14:05:04 +08:00
UINT32 calculatedCrc = crc32 ( 0 , ( const UINT8 * ) crcFtwBlockHeader , headerSize ) ;
// Add info
UString name ( " FTW store " ) ;
2017-02-14 14:39:16 +08:00
UString info = UString ( " Signature: " ) + guidToUString ( ftw32BlockHeader - > Signature , false ) +
2016-10-10 14:05:04 +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 " ,
2017-12-11 09:56:00 +08:00
ftwBlockSize , ftwBlockSize ,
headerSize , headerSize ,
body . size ( ) , 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
// Get Fdc store header
const FDC_VOLUME_HEADER * fdcStoreHeader = ( const FDC_VOLUME_HEADER * ) store . constData ( ) ;
// 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__ ,
2016-10-10 14:05:04 +08:00
fdcStoreHeader - > Size , fdcStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// 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 ) ) ;
2016-10-10 14:05:04 +08:00
// Add info
UString name ( " FDC store " ) ;
UString info = usprintf ( " Signature: _FDC \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) " ,
fdcStoreHeader - > Size , fdcStoreHeader - > Size ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
// Get Fsys store header
const APPLE_FSYS_STORE_HEADER * fsysStoreHeader = ( const APPLE_FSYS_STORE_HEADER * ) store . constData ( ) ;
// 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__ ,
2016-10-10 14:05:04 +08:00
fsysStoreHeader - > Size , fsysStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// 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 ) ) ;
// Check store checksum
UINT32 storedCrc = * ( UINT32 * ) store . right ( sizeof ( UINT32 ) ) . constData ( ) ;
UINT32 calculatedCrc = crc32 ( 0 , ( const UINT8 * ) store . constData ( ) , ( const UINT32 ) store . size ( ) - sizeof ( UINT32 ) ) ;
// Add info
bool isGaidStore = ( fsysStoreHeader - > Signature = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) ;
UString name = isGaidStore ? UString ( " Gaid store " ) : UString ( " Fsys store " ) ;
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 " ,
isGaidStore ? " Gaid " : " Fsys " ,
fsysStoreHeader - > Size , fsysStoreHeader - > Size ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
2017-12-11 09:56:00 +08:00
fsysStoreHeader - > Unknown0 ,
2016-10-10 14:05:04 +08:00
fsysStoreHeader - > Unknown1 )
+ ( storedCrc ! = calculatedCrc ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc ) : UString ( " , valid " ) ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
// Get EVSA store header
const EVSA_STORE_ENTRY * evsaStoreHeader = ( const EVSA_STORE_ENTRY * ) store . constData ( ) ;
// 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__ ,
2016-10-10 14:05:04 +08:00
evsaStoreHeader - > StoreSize , evsaStoreHeader - > StoreSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// Construct header and body
UByteArray header = store . left ( evsaStoreHeader - > Header . Size ) ;
UByteArray body = store . mid ( evsaStoreHeader - > Header . Size , evsaStoreHeader - > StoreSize - evsaStoreHeader - > Header . Size ) ;
// Recalculate checksum
UINT8 calculated = calculateChecksum8 ( ( ( const UINT8 * ) evsaStoreHeader ) + 2 , evsaStoreHeader - > Header . Size - 2 ) ;
// Add info
UString name ( " EVSA store " ) ;
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 " ,
evsaStoreHeader - > StoreSize , evsaStoreHeader - > StoreSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
evsaStoreHeader - > Header . Type ,
evsaStoreHeader - > Attributes ,
evsaStoreHeader - > Header . Checksum ) +
( evsaStoreHeader - > Header . Checksum ! = calculated ? usprintf ( " %, invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
// Get FlashMap block header
const PHOENIX_FLASH_MAP_HEADER * flashMapHeader = ( const PHOENIX_FLASH_MAP_HEADER * ) store . constData ( ) ;
// 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__ ,
2016-10-10 14:05:04 +08:00
flashMapSize , flashMapSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// 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 ) ) ;
// Add info
UString name ( " Phoenix SCT flash map " ) ;
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 " ,
flashMapSize , flashMapSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
flashMapHeader - > NumEntries ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
2017-12-11 09:56:00 +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 ;
}
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__ ,
2016-10-10 14:05:04 +08:00
cmdbSize , cmdbSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// Get store header
const PHOENIX_CMDB_HEADER * cmdbHeader = ( const PHOENIX_CMDB_HEADER * ) store . constData ( ) ;
// Construct header and body
UByteArray header = store . left ( cmdbHeader - > TotalSize ) ;
UByteArray body = store . mid ( cmdbHeader - > TotalSize , cmdbSize - cmdbHeader - > TotalSize ) ;
// Add info
UString name ( " CMDB store " ) ;
UString info = usprintf ( " Signature: CMDB \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) " ,
cmdbSize , cmdbSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
// Get SLIC pubkey header
const OEM_ACTIVATION_PUBKEY * pubkeyHeader = ( const OEM_ACTIVATION_PUBKEY * ) store . constData ( ) ;
// 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__ ,
2016-10-10 14:05:04 +08:00
pubkeyHeader - > Size , pubkeyHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// Construct header and body
UByteArray header = store . left ( sizeof ( OEM_ACTIVATION_PUBKEY ) ) ;
// Add info
UString name ( " SLIC pubkey " ) ;
UString info = usprintf ( " Type: 0h \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: 0h (0) \n "
" Key type: %02Xh \n Version: %02Xh \n Algorithm: %08Xh \n Magic: RSA1 \n Bit length: %08Xh \n Exponent: %08Xh " ,
pubkeyHeader - > Size , pubkeyHeader - > Size ,
header . size ( ) , header . size ( ) ,
pubkeyHeader - > KeyType ,
pubkeyHeader - > Version ,
pubkeyHeader - > Algorithm ,
pubkeyHeader - > BitLength ,
pubkeyHeader - > Exponent ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// 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 ;
}
// Get SLIC marker header
const OEM_ACTIVATION_MARKER * markerHeader = ( const OEM_ACTIVATION_MARKER * ) store . constData ( ) ;
// 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__ ,
2016-10-10 14:05:04 +08:00
markerHeader - > Size , markerHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
}
// Construct header and body
UByteArray header = store . left ( sizeof ( OEM_ACTIVATION_MARKER ) ) ;
// Add info
UString name ( " SLIC marker " ) ;
UString info = usprintf ( " Type: 1h \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: 0h (0) \n "
" Version: %08Xh \n OEM ID: %s \n OEM table ID: %s \n Windows flag: WINDOWS \n SLIC version: %08Xh " ,
markerHeader - > Size , markerHeader - > Size ,
header . size ( ) , header . size ( ) ,
2017-12-11 09:56:00 +08:00
markerHeader - > Version ,
2018-08-02 08:51:52 +08:00
( const char * ) UString ( ( const char * ) & ( markerHeader - > OemId ) ) . left ( 6 ) . toLocal8Bit ( ) ,
( const char * ) UString ( ( const char * ) & ( markerHeader - > OemTableId ) ) . left ( 8 ) . toLocal8Bit ( ) ,
2016-10-10 14:05:04 +08:00
markerHeader - > SlicVersion ) ;
// 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 ) ;
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
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
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 ;
}
// Check signature and run parser function needed
// VSS/SVS store
2017-12-11 09:56:00 +08:00
if ( * signature = = NVRAM_VSS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE )
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
else if ( * signature = = INTEL_MICROCODE_HEADER_VERSION )
2018-10-08 17:58:12 +08:00
return ffsParser - > parseIntelMicrocodeHeader ( store , localOffset , parent , index ) ;
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 ;
// Get item data
const UByteArray data = model - > body ( index ) ;
// Get local offset
UINT32 localOffset = model - > offset ( index ) + model - > header ( index ) . size ( ) ;
// 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 ;
}
// 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 ;
status = parseVssStoreHeader ( store , localOffset + model - > header ( volumeIndex ) . size ( ) , true , volumeIndex , vssIndex ) ;
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 ;
status = parseVss2StoreHeader ( store , localOffset + model - > header ( volumeIndex ) . size ( ) , true , volumeIndex , vss2Index ) ;
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 ;
}
}
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 ;
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
}
// Get local offset
UINT32 localOffset = model - > offset ( index ) + model - > header ( index ) . size ( ) ;
// Get item data
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
// 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 ;
}
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
UINT32 offset = 0 ;
// 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 ;
2017-12-11 09:56:00 +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 ;
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 ;
UINT32 unparsedSize = dataSize - offset ;
// Get variable header
const VSS_VARIABLE_HEADER * variableHeader = ( const VSS_VARIABLE_HEADER * ) ( data . constData ( ) + offset ) ;
// 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 ) {
// Apple VSS variable with CRC32 of the data
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 ) ;
header = data . mid ( offset , sizeof ( VSS_APPLE_VARIABLE_HEADER ) + appleVariableHeader - > NameSize ) ;
body = data . mid ( offset + header . size ( ) , appleVariableHeader - > DataSize ) ;
// Calculate CRC32 of the variable data
storedCrc32 = appleVariableHeader - > DataCrc32 ;
calculatedCrc32 = crc32 ( 0 , ( const UINT8 * ) body . constData ( ) , body . size ( ) ) ;
}
}
// Authenticated variable
else if ( ( variableHeader - > Attributes & NVRAM_VSS_VARIABLE_AUTHENTICATED_WRITE_ACCESS )
| | ( 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
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 ) ;
header = data . mid ( offset , sizeof ( VSS_AUTH_VARIABLE_HEADER ) + authVariableHeader - > NameSize ) ;
body = data . mid ( offset + header . size ( ) , authVariableHeader - > DataSize ) ;
monotonicCounter = authVariableHeader - > MonotonicCounter ;
timestamp = authVariableHeader - > Timestamp ;
pubKeyIndex = authVariableHeader - > PubKeyIndex ;
}
}
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
| | 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 ) ;
UINT32 i = 0 ;
while ( variableName [ i ] ! = 0 ) + + i ;
i = sizeof ( VSS_INTEL_VARIABLE_HEADER ) + 2 * ( i + 1 ) ;
i = i < variableSize ? i : variableSize ;
header = data . mid ( offset , i ) ;
body = data . mid ( offset + header . size ( ) , variableSize - i ) ;
}
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 ) ;
header = data . mid ( offset , sizeof ( VSS_VARIABLE_HEADER ) + variableHeader - > NameSize ) ;
body = data . mid ( offset + header . size ( ) , variableHeader - > DataSize ) ;
}
// 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
}
// Check variable size
if ( variableSize > unparsedSize ) {
2017-07-23 02:43:20 +08:00
variableSize = 0 ;
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
UString info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2016-10-10 14:05:04 +08:00
2016-10-28 00:31:15 +08:00
if ( padding . count ( emptyByte ) = = padding . size ( ) ) { // Free space
// Add tree item
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , Movable , index ) ;
2016-10-10 14:05:04 +08:00
}
2016-10-28 00:31:15 +08:00
else { // Padding
2016-10-10 14:05:04 +08:00
// Nothing is parsed yet, but the store is not empty
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 ;
}
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
}
return U_SUCCESS ;
}
UString info ;
2017-12-11 09:56:00 +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
2018-10-08 17:58:12 +08:00
name = guidToUString ( readMisaligned ( variableGuid ) ) ;
info + = UString ( " Variable GUID: " ) + guidToUString ( readMisaligned ( variableGuid ) , false ) + UString ( " \n " ) ;
2016-10-10 14:05:04 +08:00
text = UString : : fromUtf16 ( variableName ) ;
}
// Add info
2017-10-12 13:59:23 +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 ( " ,
2016-10-10 14:05:04 +08:00
variableSize , variableSize ,
header . size ( ) , header . size ( ) ,
2017-12-11 09:56:00 +08:00
body . size ( ) , body . size ( ) ,
2016-10-10 14:05:04 +08:00
variableHeader - > State ,
2017-10-12 13:59:23 +08:00
variableHeader - > Reserved ,
2016-10-10 14:05:04 +08:00
variableHeader - > Attributes ) + vssAttributesToUString ( variableHeader - > Attributes ) + UString ( " ) " ) ;
// 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 )
+ usprintf ( " \n PubKey index: %u " , pubKeyIndex ) ;
}
else if ( isAppleCrc32 ) {
subtype = Subtypes : : AppleVssEntry ;
info + = usprintf ( " \n Data checksum: %08Xh " , storedCrc32 ) +
( storedCrc32 ! = calculatedCrc32 ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc32 ) : UString ( " , valid " ) ) ;
}
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
}
2016-10-10 14:05:04 +08:00
// Add tree item
2016-10-28 00:31:15 +08:00
model - > addItem ( localOffset + offset , Types : : VssEntry , subtype , name , text , info , header , body , UByteArray ( ) , Movable , index ) ;
2016-10-10 14:05:04 +08:00
2017-07-31 14:06:11 +08:00
// Apply alignment, if needed
if ( alignment ) {
variableSize = ( ( variableSize + alignment - 1 ) & ( ~ ( alignment - 1 ) ) ) ;
}
2016-10-10 14:05:04 +08:00
// Move to next variable
offset + = variableSize ;
}
return U_SUCCESS ;
}
USTATUS NvramParser : : parseFsysStoreBody ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
2016-10-28 00:31:15 +08:00
// Get local offset
UINT32 localOffset = model - > offset ( index ) + model - > header ( index ) . size ( ) ;
// Get item data
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
// 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 ;
// 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 ;
// 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 ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Check sanity
if ( unparsedSize > = nameSize + sizeof ( UINT8 ) ) {
variableSize = nameSize + sizeof ( UINT8 ) ;
}
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 ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , header . size ( ) , header . size ( ) ) ;
2017-12-11 09:56:00 +08:00
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 ) ;
2016-10-10 14:05:04 +08:00
// Add free space
offset + = header . size ( ) ;
UByteArray body = data . mid ( offset ) ;
info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
// Add free space tree item
2016-10-28 00:31:15 +08:00
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Movable , index ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
}
// 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 ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , 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 ) ;
2017-12-11 09:56:00 +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 ) ;
2016-10-10 14:05:04 +08:00
return U_SUCCESS ;
}
// 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 ) ;
// Add info
UString info = usprintf ( " Full size: %Xh (%u) \n Header size %Xh (%u) \n Body size: %Xh (%u) " ,
variableSize , variableSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ) ;
// Add tree item
2016-12-23 06:34:24 +08:00
model - > addItem ( localOffset + offset , Types : : FsysEntry , valid ? Subtypes : : NormalFsysEntry : Subtypes : : InvalidFsysEntry , UString ( name . constData ( ) ) , UString ( ) , info , header , body , UByteArray ( ) , Movable , index ) ;
2016-10-10 14:05:04 +08:00
// Move to next variable
offset + = variableSize ;
}
2017-12-11 09:56:00 +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 ;
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
}
// Get local offset
UINT32 localOffset = model - > offset ( index ) + model - > header ( index ) . size ( ) ;
// Get item data
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
// 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 ;
std : : map < UINT16 , EFI_GUID > guidMap ;
std : : map < UINT16 , UString > nameMap ;
// 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 ;
const EVSA_ENTRY_HEADER * entryHeader = ( const EVSA_ENTRY_HEADER * ) ( data . constData ( ) + offset ) ;
// Check entry size
variableSize = sizeof ( EVSA_ENTRY_HEADER ) ;
if ( unparsedSize < variableSize | | unparsedSize < entryHeader - > Size ) {
2018-05-08 23:42:16 +08:00
body = data . mid ( offset ) ;
info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
2016-10-10 14:05:04 +08:00
2016-10-28 00:31:15 +08:00
if ( body . count ( emptyByte ) = = body . size ( ) ) { // Free space
// Add free space tree item
2016-11-03 03:40:38 +08:00
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Movable , 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 ) ;
2016-10-10 14:05:04 +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 ;
// Recalculate entry checksum
calculated = calculateChecksum8 ( ( ( const UINT8 * ) entryHeader ) + 2 , entryHeader - > Size - 2 ) ;
// 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 ) ) ;
EFI_GUID guid = * ( EFI_GUID * ) body . constData ( ) ;
name = guidToUString ( guid ) ;
2017-02-14 14:39:16 +08:00
info = UString ( " GUID: " ) + guidToUString ( guid , false ) + usprintf ( " \n Full size: %Xh (%u) \n Header size %Xh (%u) \n Body size: %Xh (%u) \n Type: %02Xh \n Checksum: %02Xh " ,
2016-10-10 14:05:04 +08:00
variableSize , variableSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , 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 ) ;
subtype = Subtypes : : GuidEvsaEntry ;
guidMap . insert ( std : : pair < UINT16 , EFI_GUID > ( guidHeader - > GuidId , guid ) ) ;
}
// Name entry
else if ( entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_NAME1 | |
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_NAME2 ) {
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 ) ) ;
name = UString : : fromUtf16 ( ( const CHAR16 * ) body . constData ( ) ) ;
2017-02-14 14:39:16 +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 " ,
2016-10-10 14:05:04 +08:00
variableSize , variableSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
nameHeader - > Header . Type ,
2017-12-11 09:56:00 +08:00
nameHeader - > Header . Checksum )
2016-10-10 14:05:04 +08:00
+ ( nameHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) )
+ usprintf ( " \n VarId: %04Xh " , nameHeader - > VarId ) ;
subtype = Subtypes : : NameEvsaEntry ;
nameMap . insert ( std : : pair < UINT16 , UString > ( nameHeader - > VarId , name ) ) ;
}
// Data entry
else if ( entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA1 | |
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA2 | |
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID ) {
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 ;
}
header = data . mid ( offset , headerSize ) ;
body = data . mid ( offset + headerSize , dataSize ) ;
name = UString ( " Data " ) ;
info = usprintf ( " Full size: %Xh (%u) \n Header size %Xh (%u) \n Body size: %Xh (%u) \n Type: %02Xh \n Checksum: %02Xh " ,
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 ( " ,
2017-12-11 09:56:00 +08:00
dataHeader - > VarId ,
dataHeader - > GuidId ,
dataHeader - > Attributes )
2016-10-10 14:05:04 +08:00
+ evsaAttributesToUString ( dataHeader - > Attributes ) + UString ( " ) " ) ;
subtype = Subtypes : : DataEvsaEntry ;
}
// Unknown entry or free space
else {
2018-05-08 23:42:16 +08:00
body = data . mid ( offset ) ;
info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
2016-10-10 14:05:04 +08:00
2016-10-28 00:31:15 +08:00
if ( body . count ( emptyByte ) = = body . size ( ) ) { // Free space
// Add free space tree item
2016-11-03 03:40:38 +08:00
model - > addItem ( localOffset + offset , Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , Movable , 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 ) ;
2016-10-10 14:05:04 +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 ;
}
// Add tree item
2016-10-28 00:31:15 +08:00
model - > addItem ( localOffset + offset , Types : : EvsaEntry , subtype , name , UString ( ) , info , header , body , UByteArray ( ) , Movable , index ) ;
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
}
// 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 + + ) {
UModelIndex current = index . child ( i , 0 ) ;
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 ) )
2017-02-14 14:39:16 +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 ] ;
2017-12-11 09:56:00 +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 ) ;
model - > addInfo ( current , UString ( " GUID: " ) + guid + UString ( " \n Name: " ) + name + UString ( " \n " ) , false ) ;
}
}
}
return U_SUCCESS ;
}
USTATUS NvramParser : : parseFlashMapBody ( const UModelIndex & index )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
// Get parsing data for the current item
2016-10-28 00:31:15 +08:00
UINT32 localOffset = model - > offset ( index ) + model - > header ( index ) . size ( ) ;
2016-10-10 14:05:04 +08:00
const UByteArray data = model - > body ( index ) ;
2017-12-11 09:56:00 +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 ) ;
// 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 ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , 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 ) ;
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 ) ;
2016-10-10 14:05:04 +08:00
break ;
}
UString name = guidToUString ( entryHeader - > Guid ) ;
2017-12-11 09:56:00 +08:00
2016-10-10 14:05:04 +08:00
// Construct header
UByteArray header = data . mid ( offset , sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ) ;
// Add info
2017-12-11 09:56:00 +08:00
UString info = UString ( " Entry GUID: " ) + guidToUString ( entryHeader - > Guid , false ) +
usprintf ( " \n Full size: 24h (36) \n Header size: 24h (36) \n Body size: 0h (0) \n "
" Entry type: %04Xh \n Data type: %04Xh \n Memory address: %08Xh \n Size: %08Xh \n Offset: %08Xh " ,
entryHeader - > EntryType ,
entryHeader - > DataType ,
entryHeader - > PhysicalAddress ,
entryHeader - > Size ,
entryHeader - > Offset ) ;
2016-10-10 14:05:04 +08:00
// Determine subtype
UINT8 subtype = 0 ;
switch ( entryHeader - > DataType ) {
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 ;
}
// Add tree item
2016-10-28 00:31:15 +08:00
model - > addItem ( localOffset + offset , Types : : FlashMapEntry , subtype , name , flashMapGuidToUString ( entryHeader - > Guid ) , info , header , UByteArray ( ) , UByteArray ( ) , Movable , index ) ;
2016-10-10 14:05:04 +08:00
// Move to next variable
offset + = sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ;
unparsedSize = dataSize - offset ;
}
return U_SUCCESS ;
}
# endif // U_ENABLE_NVRAM_PARSING_SUPPORT