2016-07-09 16:08:32 +08:00
/* ffsparser.cpp
2015-03-13 14:48:53 +08:00
2016-02-02 09:08:08 +08:00
Copyright ( c ) 2016 , Nikolaj Schlej . All rights reserved .
2015-03-13 14:48:53 +08:00
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 ,
WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND , EITHER EXPRESS OR IMPLIED .
*/
2016-02-02 09:08:08 +08:00
# include "ffsparser.h"
2016-07-06 00:19:04 +08:00
# include <map>
2016-03-01 15:20:44 +08:00
# include <cmath>
# include <algorithm>
2016-06-26 16:05:45 +08:00
# include <inttypes.h>
2015-03-13 14:48:53 +08:00
2016-02-02 09:08:08 +08:00
// Region info structure definition
struct REGION_INFO {
UINT32 offset ;
UINT32 length ;
UINT8 type ;
2016-06-26 11:54:21 +08:00
UByteArray data ;
2016-02-02 09:08:08 +08:00
friend bool operator < ( const REGION_INFO & lhs , const REGION_INFO & rhs ) { return lhs . offset < rhs . offset ; }
} ;
2015-03-13 14:48:53 +08:00
2016-02-02 09:08:08 +08:00
// Firmware image parsing functions
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parse ( const UByteArray & buffer )
2015-03-13 14:48:53 +08:00
{
2016-06-26 11:54:21 +08:00
UModelIndex root ;
USTATUS result = performFirstPass ( buffer , root ) ;
2016-02-02 09:08:08 +08:00
addOffsetsRecursive ( root ) ;
if ( result )
return result ;
2016-04-17 07:25:44 +08:00
if ( lastVtf . isValid ( ) )
2016-02-02 09:08:08 +08:00
result = performSecondPass ( root ) ;
2016-04-17 07:25:44 +08:00
else
2016-06-26 11:54:21 +08:00
msg ( ( " parse: not a single Volume Top File is found, the image may be corrupted " ) ) ;
2016-02-02 09:08:08 +08:00
return result ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : performFirstPass ( const UByteArray & buffer , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
2016-02-02 09:08:08 +08:00
// Reset capsule offset fixup value
2015-09-13 23:32:22 +08:00
capsuleOffsetFixup = 0 ;
2015-12-12 17:59:38 +08:00
// Check buffer size to be more than or equal to size of EFI_CAPSULE_HEADER
2015-03-13 14:48:53 +08:00
if ( ( UINT32 ) buffer . size ( ) < = sizeof ( EFI_CAPSULE_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " performFirstPass: image file is smaller than minimum size of 1Ch (28) bytes " ) ) ;
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
}
2015-12-12 17:59:38 +08:00
UINT32 capsuleHeaderSize = 0 ;
// Check buffer for being normal EFI capsule header
2015-09-01 03:34:42 +08:00
if ( buffer . startsWith ( EFI_CAPSULE_GUID )
2016-02-02 09:08:08 +08:00
| | buffer . startsWith ( INTEL_CAPSULE_GUID )
| | buffer . startsWith ( LENOVO_CAPSULE_GUID )
| | buffer . startsWith ( LENOVO2_CAPSULE_GUID ) ) {
2015-03-13 14:48:53 +08:00
// Get info
const EFI_CAPSULE_HEADER * capsuleHeader = ( const EFI_CAPSULE_HEADER * ) buffer . constData ( ) ;
2015-12-12 17:59:38 +08:00
// Check sanity of HeaderSize and CapsuleImageSize values
if ( capsuleHeader - > HeaderSize = = 0 | | capsuleHeader - > HeaderSize > ( UINT32 ) buffer . size ( ) | | capsuleHeader - > HeaderSize > capsuleHeader - > CapsuleImageSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " performFirstPass: UEFI capsule header size of %Xh (%u) bytes is invalid " ,
capsuleHeader - > HeaderSize ,
capsuleHeader - > HeaderSize ) ) ;
return U_INVALID_CAPSULE ;
2015-12-12 17:59:38 +08:00
}
if ( capsuleHeader - > CapsuleImageSize = = 0 | | capsuleHeader - > CapsuleImageSize > ( UINT32 ) buffer . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " performFirstPass: UEFI capsule image size of %Xh (%u) bytes is invalid " ,
capsuleHeader - > CapsuleImageSize ,
capsuleHeader - > CapsuleImageSize ) ) ;
return U_INVALID_CAPSULE ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
capsuleHeaderSize = capsuleHeader - > HeaderSize ;
2016-06-26 11:54:21 +08:00
UByteArray header = buffer . left ( capsuleHeaderSize ) ;
UByteArray body = buffer . mid ( capsuleHeaderSize ) ;
UString name ( " UEFI capsule " ) ;
UString info = UString ( " Capsule GUID: " ) + guidToUString ( capsuleHeader - > CapsuleGuid ) +
usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Image size: %Xh (%u) \n Flags: %08Xh " ,
buffer . size ( ) , buffer . size ( ) ,
capsuleHeaderSize , capsuleHeaderSize ,
capsuleHeader - > CapsuleImageSize - capsuleHeaderSize , capsuleHeader - > CapsuleImageSize - capsuleHeaderSize ,
capsuleHeader - > Flags ) ;
2015-03-13 14:48:53 +08:00
2015-09-13 23:32:22 +08:00
// Set capsule offset fixup for correct volume allignment warnings
2015-12-12 17:59:38 +08:00
capsuleOffsetFixup = capsuleHeaderSize ;
2015-09-13 23:32:22 +08:00
2015-03-13 14:48:53 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Capsule , Subtypes : : UefiCapsule , name , UString ( ) , info , header , body , UByteArray ( ) , true ) ;
2015-03-13 14:48:53 +08:00
}
2015-09-01 03:34:42 +08:00
// Check buffer for being Toshiba capsule header
else if ( buffer . startsWith ( TOSHIBA_CAPSULE_GUID ) ) {
// Get info
const TOSHIBA_CAPSULE_HEADER * capsuleHeader = ( const TOSHIBA_CAPSULE_HEADER * ) buffer . constData ( ) ;
2015-12-12 17:59:38 +08:00
// Check sanity of HeaderSize and FullSize values
if ( capsuleHeader - > HeaderSize = = 0 | | capsuleHeader - > HeaderSize > ( UINT32 ) buffer . size ( ) | | capsuleHeader - > HeaderSize > capsuleHeader - > FullSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " performFirstPass: Toshiba capsule header size of %Xh (%u) bytes is invalid " ,
capsuleHeader - > HeaderSize , capsuleHeader - > HeaderSize ) ) ;
return U_INVALID_CAPSULE ;
2015-12-12 17:59:38 +08:00
}
if ( capsuleHeader - > FullSize = = 0 | | capsuleHeader - > FullSize > ( UINT32 ) buffer . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " performFirstPass: Toshiba capsule full size of %Xh (%u) bytes is invalid " ,
capsuleHeader - > FullSize , capsuleHeader - > FullSize ) ) ;
return U_INVALID_CAPSULE ;
2015-12-12 17:59:38 +08:00
}
2015-09-01 03:34:42 +08:00
capsuleHeaderSize = capsuleHeader - > HeaderSize ;
2016-06-26 11:54:21 +08:00
UByteArray header = buffer . left ( capsuleHeaderSize ) ;
2016-07-05 23:22:03 +08:00
UByteArray body = buffer . mid ( capsuleHeaderSize ) ;
2016-06-26 11:54:21 +08:00
UString name ( " Toshiba capsule " ) ;
UString info = UString ( " Capsule GUID: " ) + guidToUString ( capsuleHeader - > CapsuleGuid ) +
usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Image size: %Xh (%u) \n Flags: %08Xh " ,
buffer . size ( ) , buffer . size ( ) ,
capsuleHeaderSize , capsuleHeaderSize ,
capsuleHeader - > FullSize - capsuleHeaderSize , capsuleHeader - > FullSize - capsuleHeaderSize ,
capsuleHeader - > Flags ) ;
2015-09-01 03:34:42 +08:00
2015-09-13 23:32:22 +08:00
// Set capsule offset fixup for correct volume allignment warnings
2015-12-12 17:59:38 +08:00
capsuleOffsetFixup = capsuleHeaderSize ;
2015-09-13 23:32:22 +08:00
2015-09-01 03:34:42 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Capsule , Subtypes : : ToshibaCapsule , name , UString ( ) , info , header , body , UByteArray ( ) , true ) ;
2015-09-01 03:34:42 +08:00
}
2016-02-02 09:08:08 +08:00
// Check buffer for being extended Aptio capsule header
2015-03-13 14:48:53 +08:00
else if ( buffer . startsWith ( APTIO_SIGNED_CAPSULE_GUID ) | | buffer . startsWith ( APTIO_UNSIGNED_CAPSULE_GUID ) ) {
bool signedCapsule = buffer . startsWith ( APTIO_SIGNED_CAPSULE_GUID ) ;
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) buffer . size ( ) < = sizeof ( APTIO_CAPSULE_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " performFirstPass: AMI capsule image file is smaller than minimum size of 20h (32) bytes " ) ) ;
return U_INVALID_PARAMETER ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
// Get info
const APTIO_CAPSULE_HEADER * capsuleHeader = ( const APTIO_CAPSULE_HEADER * ) buffer . constData ( ) ;
2015-12-12 17:59:38 +08:00
// Check sanity of RomImageOffset and CapsuleImageSize values
if ( capsuleHeader - > RomImageOffset = = 0 | | capsuleHeader - > RomImageOffset > ( UINT32 ) buffer . size ( ) | | capsuleHeader - > RomImageOffset > capsuleHeader - > CapsuleHeader . CapsuleImageSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " performFirstPass: AMI capsule image offset of %Xh (%u) bytes is invalid " ,
capsuleHeader - > RomImageOffset , capsuleHeader - > RomImageOffset ) ) ;
return U_INVALID_CAPSULE ;
2015-12-12 17:59:38 +08:00
}
if ( capsuleHeader - > CapsuleHeader . CapsuleImageSize = = 0 | | capsuleHeader - > CapsuleHeader . CapsuleImageSize > ( UINT32 ) buffer . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " performFirstPass: AMI capsule image size of %Xh (%u) bytes is invalid " ,
capsuleHeader - > CapsuleHeader . CapsuleImageSize ,
capsuleHeader - > CapsuleHeader . CapsuleImageSize ) ) ;
return U_INVALID_CAPSULE ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
capsuleHeaderSize = capsuleHeader - > RomImageOffset ;
2016-06-26 11:54:21 +08:00
UByteArray header = buffer . left ( capsuleHeaderSize ) ;
UByteArray body = buffer . mid ( capsuleHeaderSize ) ;
UString name ( " AMI Aptio capsule " ) ;
UString info = UString ( " Capsule GUID: " ) + guidToUString ( capsuleHeader - > CapsuleHeader . CapsuleGuid ) +
usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Image size: %Xh (%u) \n Flags: %08Xh " ,
buffer . size ( ) , buffer . size ( ) ,
capsuleHeaderSize , capsuleHeaderSize ,
capsuleHeader - > CapsuleHeader . CapsuleImageSize - capsuleHeaderSize , capsuleHeader - > CapsuleHeader . CapsuleImageSize - capsuleHeaderSize ,
capsuleHeader - > CapsuleHeader . Flags ) ;
2015-03-13 14:48:53 +08:00
2015-09-13 23:32:22 +08:00
// Set capsule offset fixup for correct volume allignment warnings
capsuleOffsetFixup = capsuleHeaderSize ;
2015-03-13 14:48:53 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Capsule , signedCapsule ? Subtypes : : AptioSignedCapsule : Subtypes : : AptioUnsignedCapsule , name , UString ( ) , info , header , body , UByteArray ( ) , true ) ;
2015-03-13 14:48:53 +08:00
// Show message about possible Aptio signature break
if ( signedCapsule ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " performFirstPass: Aptio capsule signature may become invalid after image modifications " ) , index ) ;
2015-03-13 14:48:53 +08:00
}
}
// Skip capsule header to have flash chip image
2016-06-26 11:54:21 +08:00
UByteArray flashImage = buffer . mid ( capsuleHeaderSize ) ;
2015-03-13 14:48:53 +08:00
// Check for Intel flash descriptor presence
const FLASH_DESCRIPTOR_HEADER * descriptorHeader = ( const FLASH_DESCRIPTOR_HEADER * ) flashImage . constData ( ) ;
// Check descriptor signature
2016-06-26 11:54:21 +08:00
USTATUS result ;
2015-03-13 14:48:53 +08:00
if ( descriptorHeader - > Signature = = FLASH_DESCRIPTOR_SIGNATURE ) {
// Parse as Intel image
2016-06-26 11:54:21 +08:00
UModelIndex imageIndex ;
2015-07-09 05:05:48 +08:00
result = parseIntelImage ( flashImage , capsuleHeaderSize , index , imageIndex ) ;
2016-06-26 11:54:21 +08:00
if ( result ! = U_INVALID_FLASH_DESCRIPTOR ) {
2016-02-02 09:08:08 +08:00
if ( ! index . isValid ( ) )
index = imageIndex ;
2015-03-13 14:48:53 +08:00
return result ;
2016-02-02 09:08:08 +08:00
}
2015-03-13 14:48:53 +08:00
}
// Get info
2016-06-26 11:54:21 +08:00
UString name ( " UEFI image " ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , flashImage . size ( ) , flashImage . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-03-13 14:48:53 +08:00
pdata . offset = capsuleHeaderSize ;
// Add tree item
2016-06-26 11:54:21 +08:00
UModelIndex biosIndex = model - > addItem ( Types : : Image , Subtypes : : UefiImage , name , UString ( ) , info , UByteArray ( ) , flashImage , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2015-04-02 16:04:37 +08:00
// Parse the image
2016-04-17 07:25:44 +08:00
result = parseRawArea ( biosIndex ) ;
2016-02-02 09:08:08 +08:00
if ( ! index . isValid ( ) )
index = biosIndex ;
return result ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseIntelImage ( const UByteArray & intelImage , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( intelImage . isEmpty ( ) )
return EFI_INVALID_PARAMETER ;
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Store the beginning of descriptor as descriptor base address
const UINT8 * descriptor = ( const UINT8 * ) intelImage . constData ( ) ;
// Check for buffer size to be greater or equal to descriptor region size
if ( intelImage . size ( ) < FLASH_DESCRIPTOR_SIZE ) {
2016-06-26 16:05:45 +08:00
msg ( usprintf ( " parseIntelImage: input file is smaller than minimum descriptor size of %Xh (%u) bytes " , FLASH_DESCRIPTOR_SIZE , FLASH_DESCRIPTOR_SIZE ) ) ;
2016-06-26 11:54:21 +08:00
return U_INVALID_FLASH_DESCRIPTOR ;
2015-03-13 14:48:53 +08:00
}
// Parse descriptor map
const FLASH_DESCRIPTOR_MAP * descriptorMap = ( const FLASH_DESCRIPTOR_MAP * ) ( descriptor + sizeof ( FLASH_DESCRIPTOR_HEADER ) ) ;
2016-02-02 09:08:08 +08:00
const FLASH_DESCRIPTOR_UPPER_MAP * upperMap = ( const FLASH_DESCRIPTOR_UPPER_MAP * ) ( descriptor + FLASH_DESCRIPTOR_UPPER_MAP_BASE ) ;
2015-12-12 17:59:38 +08:00
// Check sanity of base values
if ( descriptorMap - > MasterBase > FLASH_DESCRIPTOR_MAX_BASE
| | descriptorMap - > MasterBase = = descriptorMap - > RegionBase
| | descriptorMap - > MasterBase = = descriptorMap - > ComponentBase ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseIntelImage: invalid descriptor master base %02Xh " , descriptorMap - > MasterBase ) ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2015-12-12 17:59:38 +08:00
}
if ( descriptorMap - > RegionBase > FLASH_DESCRIPTOR_MAX_BASE
| | descriptorMap - > RegionBase = = descriptorMap - > ComponentBase ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseIntelImage: invalid descriptor region base %02Xh " , descriptorMap - > RegionBase ) ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2015-12-12 17:59:38 +08:00
}
if ( descriptorMap - > ComponentBase > FLASH_DESCRIPTOR_MAX_BASE ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseIntelImage: invalid descriptor component base %02Xh " , descriptorMap - > ComponentBase ) ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
const FLASH_DESCRIPTOR_REGION_SECTION * regionSection = ( const FLASH_DESCRIPTOR_REGION_SECTION * ) calculateAddress8 ( descriptor , descriptorMap - > RegionBase ) ;
2015-09-13 04:53:07 +08:00
const FLASH_DESCRIPTOR_COMPONENT_SECTION * componentSection = ( const FLASH_DESCRIPTOR_COMPONENT_SECTION * ) calculateAddress8 ( descriptor , descriptorMap - > ComponentBase ) ;
// Check descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency
UINT8 descriptorVersion = 0 ;
if ( componentSection - > FlashParameters . ReadClockFrequency = = FLASH_FREQUENCY_20MHZ ) // Old descriptor
descriptorVersion = 1 ;
else if ( componentSection - > FlashParameters . ReadClockFrequency = = FLASH_FREQUENCY_17MHZ ) // Skylake+ descriptor
descriptorVersion = 2 ;
else {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseIntelImage: unknown descriptor version with ReadClockFrequency %02Xh " , componentSection - > FlashParameters . ReadClockFrequency ) ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2015-03-13 14:48:53 +08:00
}
2015-09-13 04:53:07 +08:00
2016-02-02 09:08:08 +08:00
// Regions
2016-03-01 15:20:44 +08:00
std : : vector < REGION_INFO > regions ;
2016-02-02 09:08:08 +08:00
2015-03-13 14:48:53 +08:00
// ME region
2016-02-02 09:08:08 +08:00
REGION_INFO me ;
me . type = Subtypes : : MeRegion ;
me . offset = 0 ;
me . length = 0 ;
2015-03-13 14:48:53 +08:00
if ( regionSection - > MeLimit ) {
2016-02-02 09:08:08 +08:00
me . offset = calculateRegionOffset ( regionSection - > MeBase ) ;
me . length = calculateRegionSize ( regionSection - > MeBase , regionSection - > MeLimit ) ;
me . data = intelImage . mid ( me . offset , me . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( me ) ;
2015-03-13 14:48:53 +08:00
}
2015-09-13 04:53:07 +08:00
2015-03-13 14:48:53 +08:00
// BIOS region
2016-02-02 09:08:08 +08:00
REGION_INFO bios ;
bios . type = Subtypes : : BiosRegion ;
bios . offset = 0 ;
bios . length = 0 ;
2015-03-13 14:48:53 +08:00
if ( regionSection - > BiosLimit ) {
2016-02-02 09:08:08 +08:00
bios . offset = calculateRegionOffset ( regionSection - > BiosBase ) ;
bios . length = calculateRegionSize ( regionSection - > BiosBase , regionSection - > BiosLimit ) ;
2015-03-13 14:48:53 +08:00
// Check for Gigabyte specific descriptor map
2016-02-02 09:08:08 +08:00
if ( bios . length = = ( UINT32 ) intelImage . size ( ) ) {
if ( ! me . offset ) {
2016-06-26 11:54:21 +08:00
msg ( ( " parseIntelImage: can't determine BIOS region start from Gigabyte-specific descriptor " ) ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2015-03-13 14:48:53 +08:00
}
2016-02-02 09:08:08 +08:00
// Use ME region end as BIOS region offset
bios . offset = me . offset + me . length ;
bios . length = ( UINT32 ) intelImage . size ( ) - bios . offset ;
bios . data = intelImage . mid ( bios . offset , bios . length ) ;
2015-10-05 16:21:33 +08:00
}
// Normal descriptor map
else {
2016-02-02 09:08:08 +08:00
bios . data = intelImage . mid ( bios . offset , bios . length ) ;
2015-03-13 14:48:53 +08:00
}
2016-02-02 09:08:08 +08:00
2016-03-01 15:20:44 +08:00
regions . push_back ( bios ) ;
2015-03-13 14:48:53 +08:00
}
else {
2016-06-26 11:54:21 +08:00
msg ( ( " parseIntelImage: descriptor parsing failed, BIOS region not found in descriptor " ) ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2015-03-13 14:48:53 +08:00
}
2015-09-13 04:53:07 +08:00
// GbE region
2016-02-02 09:08:08 +08:00
REGION_INFO gbe ;
gbe . type = Subtypes : : GbeRegion ;
gbe . offset = 0 ;
gbe . length = 0 ;
2015-09-13 04:53:07 +08:00
if ( regionSection - > GbeLimit ) {
2016-02-02 09:08:08 +08:00
gbe . offset = calculateRegionOffset ( regionSection - > GbeBase ) ;
gbe . length = calculateRegionSize ( regionSection - > GbeBase , regionSection - > GbeLimit ) ;
gbe . data = intelImage . mid ( gbe . offset , gbe . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( gbe ) ;
2015-09-13 04:53:07 +08:00
}
// PDR region
2016-02-02 09:08:08 +08:00
REGION_INFO pdr ;
pdr . type = Subtypes : : PdrRegion ;
pdr . offset = 0 ;
pdr . length = 0 ;
2015-09-13 04:53:07 +08:00
if ( regionSection - > PdrLimit ) {
2016-02-02 09:08:08 +08:00
pdr . offset = calculateRegionOffset ( regionSection - > PdrBase ) ;
pdr . length = calculateRegionSize ( regionSection - > PdrBase , regionSection - > PdrLimit ) ;
pdr . data = intelImage . mid ( pdr . offset , pdr . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( pdr ) ;
2016-02-02 09:08:08 +08:00
}
// Reserved1 region
REGION_INFO reserved1 ;
reserved1 . type = Subtypes : : Reserved1Region ;
reserved1 . offset = 0 ;
reserved1 . length = 0 ;
if ( regionSection - > Reserved1Limit & & regionSection - > Reserved1Base ! = 0xFFFF & & regionSection - > Reserved1Limit ! = 0xFFFF ) {
reserved1 . offset = calculateRegionOffset ( regionSection - > Reserved1Base ) ;
reserved1 . length = calculateRegionSize ( regionSection - > Reserved1Base , regionSection - > Reserved1Limit ) ;
reserved1 . data = intelImage . mid ( reserved1 . offset , reserved1 . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( reserved1 ) ;
2016-02-02 09:08:08 +08:00
}
// Reserved2 region
REGION_INFO reserved2 ;
reserved2 . type = Subtypes : : Reserved2Region ;
reserved2 . offset = 0 ;
reserved2 . length = 0 ;
if ( regionSection - > Reserved2Limit & & regionSection - > Reserved2Base ! = 0xFFFF & & regionSection - > Reserved2Limit ! = 0xFFFF ) {
reserved2 . offset = calculateRegionOffset ( regionSection - > Reserved2Base ) ;
reserved2 . length = calculateRegionSize ( regionSection - > Reserved2Base , regionSection - > Reserved2Limit ) ;
reserved2 . data = intelImage . mid ( reserved2 . offset , reserved2 . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( reserved2 ) ;
2016-02-02 09:08:08 +08:00
}
// Reserved3 region
REGION_INFO reserved3 ;
reserved3 . type = Subtypes : : Reserved3Region ;
reserved3 . offset = 0 ;
reserved3 . length = 0 ;
2015-09-13 04:53:07 +08:00
// EC region
2016-02-02 09:08:08 +08:00
REGION_INFO ec ;
ec . type = Subtypes : : EcRegion ;
ec . offset = 0 ;
ec . length = 0 ;
// Reserved4 region
REGION_INFO reserved4 ;
reserved3 . type = Subtypes : : Reserved4Region ;
reserved4 . offset = 0 ;
reserved4 . length = 0 ;
// Check for EC and reserved region 4 only for v2 descriptor
2015-09-13 04:53:07 +08:00
if ( descriptorVersion = = 2 ) {
2016-02-02 09:08:08 +08:00
if ( regionSection - > Reserved3Limit ) {
reserved3 . offset = calculateRegionOffset ( regionSection - > Reserved3Base ) ;
reserved3 . length = calculateRegionSize ( regionSection - > Reserved3Base , regionSection - > Reserved3Limit ) ;
reserved3 . data = intelImage . mid ( reserved3 . offset , reserved3 . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( reserved3 ) ;
2016-02-02 09:08:08 +08:00
}
2015-09-13 04:53:07 +08:00
if ( regionSection - > EcLimit ) {
2016-02-02 09:08:08 +08:00
ec . offset = calculateRegionOffset ( regionSection - > EcBase ) ;
ec . length = calculateRegionSize ( regionSection - > EcBase , regionSection - > EcLimit ) ;
ec . data = intelImage . mid ( ec . offset , ec . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( ec ) ;
2016-02-02 09:08:08 +08:00
}
if ( regionSection - > Reserved4Limit ) {
reserved4 . offset = calculateRegionOffset ( regionSection - > Reserved4Base ) ;
reserved4 . length = calculateRegionSize ( regionSection - > Reserved4Base , regionSection - > Reserved4Limit ) ;
reserved4 . data = intelImage . mid ( reserved4 . offset , reserved4 . length ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( reserved4 ) ;
2015-09-13 04:53:07 +08:00
}
}
2016-02-02 09:08:08 +08:00
// Sort regions in ascending order
2016-03-21 06:59:03 +08:00
std : : sort ( regions . begin ( ) , regions . end ( ) ) ;
2016-02-02 09:08:08 +08:00
// Check for intersections and paddings between regions
REGION_INFO region ;
// Check intersection with the descriptor
2016-03-01 15:20:44 +08:00
if ( regions . front ( ) . offset < FLASH_DESCRIPTOR_SIZE ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseIntelImage: " ) + itemSubtypeToUString ( Types : : Region , regions . front ( ) . type )
+ UString ( " region has intersection with flash descriptor " ) ,
index ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2015-03-13 14:48:53 +08:00
}
2016-02-02 09:08:08 +08:00
// Check for padding between descriptor and the first region
2016-03-01 15:20:44 +08:00
else if ( regions . front ( ) . offset > FLASH_DESCRIPTOR_SIZE ) {
2016-02-02 09:08:08 +08:00
region . offset = FLASH_DESCRIPTOR_SIZE ;
2016-03-01 15:20:44 +08:00
region . length = regions . front ( ) . offset - FLASH_DESCRIPTOR_SIZE ;
2016-02-02 09:08:08 +08:00
region . data = intelImage . mid ( region . offset , region . length ) ;
region . type = getPaddingType ( region . data ) ;
2016-03-01 16:52:25 +08:00
regions . insert ( regions . begin ( ) , region ) ;
2016-02-02 09:08:08 +08:00
}
// Check for intersections/paddings between regions
2016-03-01 15:20:44 +08:00
for ( size_t i = 1 ; i < regions . size ( ) ; i + + ) {
2016-02-02 09:08:08 +08:00
UINT32 previousRegionEnd = regions [ i - 1 ] . offset + regions [ i - 1 ] . length ;
// Check that current region is fully present in the image
if ( regions [ i ] . offset + regions [ i ] . length > ( UINT32 ) intelImage . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseIntelImage: " ) + itemSubtypeToUString ( Types : : Region , regions [ i ] . type )
+ UString ( " region is located outside of opened image, if your system uses dual-chip storage, please append another part to the opened image " ) ,
index ) ;
return U_TRUNCATED_IMAGE ;
2016-02-02 09:08:08 +08:00
}
// Check for intersection with previous region
if ( regions [ i ] . offset < previousRegionEnd ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseIntelImage: " ) + itemSubtypeToUString ( Types : : Region , regions [ i ] . type )
+ UString ( " region has intersection with " ) + itemSubtypeToUString ( Types : : Region , regions [ i - 1 ] . type ) + UString ( " region " ) ,
index ) ;
return U_INVALID_FLASH_DESCRIPTOR ;
2016-02-02 09:08:08 +08:00
}
// Check for padding between current and previous regions
else if ( regions [ i ] . offset > previousRegionEnd ) {
region . offset = previousRegionEnd ;
region . length = regions [ i ] . offset - previousRegionEnd ;
region . data = intelImage . mid ( region . offset , region . length ) ;
region . type = getPaddingType ( region . data ) ;
2016-03-01 16:52:25 +08:00
std : : vector < REGION_INFO > : : iterator iter = regions . begin ( ) ;
std : : advance ( iter , i - 1 ) ;
regions . insert ( iter , region ) ;
2016-02-02 09:08:08 +08:00
}
2015-09-13 04:53:07 +08:00
}
2016-02-02 09:08:08 +08:00
// Check for padding after the last region
2016-03-01 15:20:44 +08:00
if ( regions . back ( ) . offset + regions . back ( ) . length < ( UINT32 ) intelImage . size ( ) ) {
region . offset = regions . back ( ) . offset + regions . back ( ) . length ;
2016-02-02 09:08:08 +08:00
region . length = intelImage . size ( ) - region . offset ;
region . data = intelImage . mid ( region . offset , region . length ) ;
region . type = getPaddingType ( region . data ) ;
2016-03-01 15:20:44 +08:00
regions . push_back ( region ) ;
2015-09-13 04:53:07 +08:00
}
2016-02-02 09:08:08 +08:00
2015-03-13 14:48:53 +08:00
// Region map is consistent
// Intel image
2016-06-26 11:54:21 +08:00
UString name ( " Intel image " ) ;
UString info = usprintf ( " Full size: %Xh (%u) \n Flash chips: %u \n Regions: %u \n Masters: %u \n PCH straps: %u \n PROC straps: %u " ,
intelImage . size ( ) , intelImage . size ( ) ,
descriptorMap - > NumberOfFlashChips + 1 , //
descriptorMap - > NumberOfRegions + 1 , // Zero-based numbers in storage
descriptorMap - > NumberOfMasters + 1 , //
descriptorMap - > NumberOfPchStraps ,
descriptorMap - > NumberOfProcStraps ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
2015-07-09 05:05:48 +08:00
pdata . offset = parentOffset ;
2015-03-13 14:48:53 +08:00
// Add Intel image tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Image , Subtypes : : IntelImage , name , UString ( ) , info , UByteArray ( ) , intelImage , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-03-13 14:48:53 +08:00
// Descriptor
// Get descriptor info
2016-06-26 11:54:21 +08:00
UByteArray body = intelImage . left ( FLASH_DESCRIPTOR_SIZE ) ;
name = UString ( " Descriptor region " ) ;
info = usprintf ( " Full size: %Xh (%u) " , FLASH_DESCRIPTOR_SIZE , FLASH_DESCRIPTOR_SIZE ) ;
2016-02-02 09:08:08 +08:00
// Add offsets of actual regions
2016-03-01 15:20:44 +08:00
for ( size_t i = 0 ; i < regions . size ( ) ; i + + ) {
2016-02-02 09:08:08 +08:00
if ( regions [ i ] . type ! = Subtypes : : ZeroPadding & & regions [ i ] . type ! = Subtypes : : OnePadding & & regions [ i ] . type ! = Subtypes : : DataPadding )
2016-06-26 16:05:45 +08:00
info + = UString ( " \n " ) + itemSubtypeToUString ( Types : : Region , regions [ i ] . type )
+ usprintf ( " region offset: %Xh " , regions [ i ] . offset + parentOffset ) ;
2015-03-13 14:48:53 +08:00
}
// Region access settings
2015-09-13 04:53:07 +08:00
if ( descriptorVersion = = 1 ) {
const FLASH_DESCRIPTOR_MASTER_SECTION * masterSection = ( const FLASH_DESCRIPTOR_MASTER_SECTION * ) calculateAddress8 ( descriptor , descriptorMap - > MasterBase ) ;
2016-06-26 11:54:21 +08:00
info + = UString ( " \n Region access settings: " ) ;
info + = usprintf ( " \n BIOS: %02Xh %02Xh ME: %02Xh %02Xh \n GbE: %02Xh %02Xh " ,
masterSection - > BiosRead ,
masterSection - > BiosWrite ,
masterSection - > MeRead ,
masterSection - > MeWrite ,
masterSection - > GbeRead ,
masterSection - > GbeWrite ) ;
2015-09-13 04:53:07 +08:00
// BIOS access table
2016-06-26 11:54:21 +08:00
info + = UString ( " \n BIOS access table: " )
+ UString ( " \n Read Write " )
+ usprintf ( " \n Desc %s %s " , masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? " Yes " : " No " ) ;
info + = UString ( " \n BIOS Yes Yes " )
+ usprintf ( " \n ME %s %s " , masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? " Yes " : " No " ) ;
info + = usprintf ( " \n GbE %s %s " , masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? " Yes " : " No " ) ;
info + = usprintf ( " \n PDR %s %s " , masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? " Yes " : " No " ) ;
2015-09-13 04:53:07 +08:00
}
else if ( descriptorVersion = = 2 ) {
const FLASH_DESCRIPTOR_MASTER_SECTION_V2 * masterSection = ( const FLASH_DESCRIPTOR_MASTER_SECTION_V2 * ) calculateAddress8 ( descriptor , descriptorMap - > MasterBase ) ;
2016-06-26 16:05:45 +08:00
info + = UString ( " \n Region access settings: " ) ;
info + = usprintf ( " \n BIOS: %03Xh %03Xh ME: %03Xh %03Xh \n GbE: %03Xh %03Xh EC: %03Xh %03Xh " ,
2016-06-26 11:54:21 +08:00
masterSection - > BiosRead ,
masterSection - > BiosWrite ,
masterSection - > MeRead ,
masterSection - > MeWrite ,
masterSection - > GbeRead ,
masterSection - > GbeWrite ,
masterSection - > EcRead ,
masterSection - > EcWrite ) ;
2015-09-13 04:53:07 +08:00
// BIOS access table
2016-06-26 11:54:21 +08:00
info + = UString ( " \n BIOS access table: " )
+ UString ( " \n Read Write " )
+ usprintf ( " \n Desc %s %s " ,
masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? " Yes " : " No " ) ;
info + = UString ( " \n BIOS Yes Yes " )
+ usprintf ( " \n ME %s %s " ,
masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? " Yes " : " No " ) ;
info + = usprintf ( " \n GbE %s %s " ,
masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? " Yes " : " No " ) ;
info + = usprintf ( " \n PDR %s %s " ,
masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? " Yes " : " No " ) ;
info + = usprintf ( " \n EC %s %s " ,
masterSection - > BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_EC ? " Yes " : " No " ,
masterSection - > BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_EC ? " Yes " : " No " ) ;
2015-09-13 04:53:07 +08:00
}
2015-03-13 14:48:53 +08:00
// VSCC table
const VSCC_TABLE_ENTRY * vsccTableEntry = ( const VSCC_TABLE_ENTRY * ) ( descriptor + ( ( UINT16 ) upperMap - > VsccTableBase < < 4 ) ) ;
2016-06-26 11:54:21 +08:00
info + = UString ( " \n Flash chips in VSCC table: " ) ;
2015-03-13 14:48:53 +08:00
UINT8 vsscTableSize = upperMap - > VsccTableSize * sizeof ( UINT32 ) / sizeof ( VSCC_TABLE_ENTRY ) ;
for ( int i = 0 ; i < vsscTableSize ; i + + ) {
2016-06-26 16:05:45 +08:00
info + = usprintf ( " \n %02X%02X%02Xh " ,
2016-06-26 11:54:21 +08:00
vsccTableEntry - > VendorId , vsccTableEntry - > DeviceId0 , vsccTableEntry - > DeviceId1 ) ;
2015-03-13 14:48:53 +08:00
vsccTableEntry + + ;
}
// Add descriptor tree item
2016-06-26 11:54:21 +08:00
UModelIndex regionIndex = model - > addItem ( Types : : Region , Subtypes : : DescriptorRegion , name , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2016-02-02 09:08:08 +08:00
2015-03-13 14:48:53 +08:00
// Parse regions
2016-06-26 11:54:21 +08:00
UINT8 result = U_SUCCESS ;
UINT8 parseResult = U_SUCCESS ;
2016-03-01 15:20:44 +08:00
for ( size_t i = 0 ; i < regions . size ( ) ; i + + ) {
region = regions [ i ] ;
2016-02-02 09:08:08 +08:00
switch ( region . type ) {
case Subtypes : : BiosRegion :
result = parseBiosRegion ( region . data , region . offset , index , regionIndex ) ;
break ;
case Subtypes : : MeRegion :
result = parseMeRegion ( region . data , region . offset , index , regionIndex ) ;
break ;
case Subtypes : : GbeRegion :
result = parseGbeRegion ( region . data , region . offset , index , regionIndex ) ;
break ;
case Subtypes : : PdrRegion :
result = parsePdrRegion ( region . data , region . offset , index , regionIndex ) ;
break ;
case Subtypes : : Reserved1Region :
case Subtypes : : Reserved2Region :
case Subtypes : : Reserved3Region :
case Subtypes : : EcRegion :
case Subtypes : : Reserved4Region :
result = parseGeneralRegion ( region . type , region . data , region . offset , index , regionIndex ) ;
break ;
case Subtypes : : ZeroPadding :
case Subtypes : : OnePadding :
case Subtypes : : DataPadding : {
// Add padding between regions
2016-06-26 11:54:21 +08:00
UByteArray padding = intelImage . mid ( region . offset , region . length ) ;
2015-09-01 03:34:42 +08:00
2016-02-02 09:08:08 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-09-01 03:34:42 +08:00
2016-02-02 09:08:08 +08:00
// Get info
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
2016-06-26 16:05:45 +08:00
info = usprintf ( " Full size: %Xh (%u) " ,
2016-06-26 11:54:21 +08:00
padding . size ( ) , padding . size ( ) ) ;
2015-09-01 03:34:42 +08:00
2016-02-02 09:08:08 +08:00
// Construct parsing data
pdata . offset = parentOffset + region . offset ;
2016-01-28 07:21:51 +08:00
2016-02-02 09:08:08 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
regionIndex = model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
result = U_SUCCESS ;
2016-02-02 09:08:08 +08:00
} break ;
default :
2016-06-26 11:54:21 +08:00
msg ( ( " parseIntelImage: region of unknown type found " ) , index ) ;
result = U_INVALID_FLASH_DESCRIPTOR ;
2016-02-02 09:08:08 +08:00
}
// Store the first failed result as a final result
if ( ! parseResult & & result )
parseResult = result ;
2015-06-20 02:26:45 +08:00
}
2016-02-02 09:08:08 +08:00
return parseResult ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseGbeRegion ( const UByteArray & gbe , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Check sanity
if ( gbe . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
return U_EMPTY_REGION ;
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) gbe . size ( ) < GBE_VERSION_OFFSET + sizeof ( GBE_VERSION ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_REGION ;
2015-03-13 14:48:53 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name ( " GbE region " ) ;
2015-03-13 14:48:53 +08:00
const GBE_MAC_ADDRESS * mac = ( const GBE_MAC_ADDRESS * ) gbe . constData ( ) ;
const GBE_VERSION * version = ( const GBE_VERSION * ) ( gbe . constData ( ) + GBE_VERSION_OFFSET ) ;
2016-06-26 11:54:21 +08:00
UString info = usprintf ( " Full size: %Xh (%u) \n MAC: %02X:%02X:%02X:%02X:%02X:%02X \n Version: %u.%u " ,
gbe . size ( ) , gbe . size ( ) ,
mac - > vendor [ 0 ] , mac - > vendor [ 1 ] , mac - > vendor [ 2 ] ,
mac - > device [ 0 ] , mac - > device [ 1 ] , mac - > device [ 2 ] ,
version - > major ,
version - > minor ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Region , Subtypes : : GbeRegion , name , UString ( ) , info , UByteArray ( ) , gbe , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseMeRegion ( const UByteArray & me , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Check sanity
if ( me . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
return U_EMPTY_REGION ;
2015-03-13 14:48:53 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name ( " ME region " ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , me . size ( ) , me . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Parse region
bool versionFound = true ;
bool emptyRegion = false ;
// Check for empty region
2016-07-05 23:22:03 +08:00
if ( me . size ( ) = = me . count ( ' \xFF ' ) | | me . size ( ) = = me . count ( ' \x00 ' ) ) {
2015-03-13 14:48:53 +08:00
// Further parsing not needed
emptyRegion = true ;
2016-06-26 11:54:21 +08:00
info + = ( " \n State: empty " ) ;
2015-03-13 14:48:53 +08:00
}
else {
// Search for new signature
INT32 versionOffset = me . indexOf ( ME_VERSION_SIGNATURE2 ) ;
if ( versionOffset < 0 ) { // New signature not found
// Search for old signature
versionOffset = me . indexOf ( ME_VERSION_SIGNATURE ) ;
if ( versionOffset < 0 ) {
2016-06-26 11:54:21 +08:00
info + = ( " \n Version: unknown " ) ;
2015-03-13 14:48:53 +08:00
versionFound = false ;
}
}
2015-12-12 17:59:38 +08:00
// Check sanity
if ( ( UINT32 ) me . size ( ) < ( UINT32 ) versionOffset + sizeof ( ME_VERSION ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_REGION ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Add version information
if ( versionFound ) {
const ME_VERSION * version = ( const ME_VERSION * ) ( me . constData ( ) + versionOffset ) ;
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Version: %u.%u.%u.%u " ,
version - > major ,
version - > minor ,
version - > bugfix ,
version - > build ) ;
2015-03-13 14:48:53 +08:00
}
}
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Region , Subtypes : : MeRegion , name , UString ( ) , info , UByteArray ( ) , me , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-03-13 14:48:53 +08:00
// Show messages
if ( emptyRegion ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseMeRegion: ME region is empty " ) , index ) ;
2015-03-13 14:48:53 +08:00
}
else if ( ! versionFound ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseMeRegion: ME version is unknown, it can be damaged " ) , index ) ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parsePdrRegion ( const UByteArray & pdr , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Check sanity
if ( pdr . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
return U_EMPTY_REGION ;
2015-03-13 14:48:53 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name ( " PDR region " ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , pdr . size ( ) , pdr . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Region , Subtypes : : PdrRegion , name , UString ( ) , info , UByteArray ( ) , pdr , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-03-13 14:48:53 +08:00
// Parse PDR region as BIOS space
2016-04-17 07:25:44 +08:00
UINT8 result = parseRawArea ( index ) ;
2016-06-26 11:54:21 +08:00
if ( result & & result ! = U_VOLUMES_NOT_FOUND & & result ! = U_INVALID_VOLUME )
2015-03-13 14:48:53 +08:00
return result ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseGeneralRegion ( const UINT8 subtype , const UByteArray & region , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-09-13 04:53:07 +08:00
{
// Check sanity
2016-02-02 09:08:08 +08:00
if ( region . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
return U_EMPTY_REGION ;
2015-09-13 04:53:07 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-09-13 04:53:07 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name = itemSubtypeToUString ( Types : : Region , subtype ) + UString ( " region " ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , region . size ( ) , region . size ( ) ) ;
2015-09-13 04:53:07 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Region , subtype , name , UString ( ) , info , UByteArray ( ) , region , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-09-13 04:53:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-09-13 04:53:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseBiosRegion ( const UByteArray & bios , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( bios . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
return U_EMPTY_REGION ;
2015-03-13 14:48:53 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name ( " BIOS region " ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , bios . size ( ) , bios . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Region , Subtypes : : BiosRegion , name , UString ( ) , info , UByteArray ( ) , bios , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-03-13 14:48:53 +08:00
2016-04-17 07:25:44 +08:00
return parseRawArea ( index ) ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
UINT8 FfsParser : : getPaddingType ( const UByteArray & padding )
2015-03-13 14:48:53 +08:00
{
2016-07-05 23:22:03 +08:00
if ( padding . count ( ' \x00 ' ) = = padding . size ( ) )
2015-03-13 14:48:53 +08:00
return Subtypes : : ZeroPadding ;
2016-07-05 23:22:03 +08:00
if ( padding . count ( ' \xFF ' ) = = padding . size ( ) )
2015-03-13 14:48:53 +08:00
return Subtypes : : OnePadding ;
return Subtypes : : DataPadding ;
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseRawArea ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-03-13 14:48:53 +08:00
UINT32 headerSize = model - > header ( index ) . size ( ) ;
2016-01-28 07:21:51 +08:00
UINT32 offset = pdata . offset + headerSize ;
2015-03-13 14:48:53 +08:00
2016-04-17 07:25:44 +08:00
// Get item data
2016-06-26 11:54:21 +08:00
UByteArray data = model - > body ( index ) ;
2016-04-17 07:25:44 +08:00
2015-03-13 14:48:53 +08:00
// Search for first volume
2016-06-26 11:54:21 +08:00
USTATUS result ;
2015-03-13 14:48:53 +08:00
UINT32 prevVolumeOffset ;
2016-01-28 07:21:51 +08:00
result = findNextVolume ( index , data , offset , 0 , prevVolumeOffset ) ;
2015-03-13 14:48:53 +08:00
if ( result )
return result ;
2016-03-28 21:03:32 +08:00
// First volume is not at the beginning of RAW area
2016-06-26 11:54:21 +08:00
UString name ;
UString info ;
2015-03-13 14:48:53 +08:00
if ( prevVolumeOffset > 0 ) {
// Get info
2016-06-26 11:54:21 +08:00
UByteArray padding = data . left ( prevVolumeOffset ) ;
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
2016-01-28 07:21:51 +08:00
pdata . offset = offset ;
2015-03-13 14:48:53 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
}
// Search for and parse all volumes
UINT32 volumeOffset = prevVolumeOffset ;
UINT32 prevVolumeSize = 0 ;
while ( ! result )
{
// Padding between volumes
if ( volumeOffset > prevVolumeOffset + prevVolumeSize ) {
UINT32 paddingOffset = prevVolumeOffset + prevVolumeSize ;
UINT32 paddingSize = volumeOffset - paddingOffset ;
2016-06-26 11:54:21 +08:00
UByteArray padding = data . mid ( paddingOffset , paddingSize ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
2016-01-28 07:21:51 +08:00
pdata . offset = offset + paddingOffset ;
2015-03-13 14:48:53 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
}
// Get volume size
UINT32 volumeSize = 0 ;
UINT32 bmVolumeSize = 0 ;
2015-04-02 16:04:37 +08:00
result = getVolumeSize ( data , volumeOffset , volumeSize , bmVolumeSize ) ;
2015-12-12 17:59:38 +08:00
if ( result ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseRawArea: getVolumeSize failed with error " ) + errorCodeToUString ( result ) , index ) ;
2015-03-13 14:48:53 +08:00
return result ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
// Check that volume is fully present in input
2015-12-12 17:59:38 +08:00
if ( volumeSize > ( UINT32 ) data . size ( ) | | volumeOffset + volumeSize > ( UINT32 ) data . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseRawArea: one of volumes inside overlaps the end of data " ) , index ) ;
return U_INVALID_VOLUME ;
2015-12-12 17:59:38 +08:00
}
2016-06-26 11:54:21 +08:00
UByteArray volume = data . mid ( volumeOffset , volumeSize ) ;
2015-03-13 14:48:53 +08:00
if ( volumeSize > ( UINT32 ) volume . size ( ) ) {
// Mark the rest as padding and finish the parsing
2016-06-26 11:54:21 +08:00
UByteArray padding = data . right ( volume . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
2016-01-28 07:21:51 +08:00
pdata . offset = offset + volumeOffset ;
2015-03-13 14:48:53 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
UModelIndex paddingIndex = model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
msg ( UString ( " parseRawArea: one of volumes inside overlaps the end of data " ) , paddingIndex ) ;
2015-03-13 14:48:53 +08:00
// Update variables
prevVolumeOffset = volumeOffset ;
prevVolumeSize = padding . size ( ) ;
break ;
}
// Parse current volume's header
2016-06-26 11:54:21 +08:00
UModelIndex volumeIndex ;
2016-03-28 21:03:32 +08:00
result = parseVolumeHeader ( volume , headerSize + volumeOffset , index , volumeIndex ) ;
2015-03-13 14:48:53 +08:00
if ( result )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseRawArea: volume header parsing failed with error " ) + errorCodeToUString ( result ) , index ) ;
2015-03-13 14:48:53 +08:00
else {
// Show messages
if ( volumeSize ! = bmVolumeSize )
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseRawArea: volume size stored in header %Xh (%u) differs from calculated using block map %Xh (%u) " ,
volumeSize , volumeSize ,
bmVolumeSize , bmVolumeSize ) ,
2015-03-13 14:48:53 +08:00
volumeIndex ) ;
}
// Go to next volume
prevVolumeOffset = volumeOffset ;
prevVolumeSize = volumeSize ;
2016-01-28 07:21:51 +08:00
result = findNextVolume ( index , data , offset , volumeOffset + prevVolumeSize , volumeOffset ) ;
2015-03-13 14:48:53 +08:00
}
2016-03-28 21:03:32 +08:00
// Padding at the end of RAW area
2015-03-13 14:48:53 +08:00
volumeOffset = prevVolumeOffset + prevVolumeSize ;
2015-04-02 16:04:37 +08:00
if ( ( UINT32 ) data . size ( ) > volumeOffset ) {
2016-06-26 11:54:21 +08:00
UByteArray padding = data . mid ( volumeOffset ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset = offset + headerSize + volumeOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
}
2015-09-13 22:36:43 +08:00
// Parse bodies
2015-03-13 14:48:53 +08:00
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2016-06-26 11:54:21 +08:00
UModelIndex current = index . child ( i , 0 ) ;
2015-03-13 14:48:53 +08:00
switch ( model - > type ( current ) ) {
case Types : : Volume :
parseVolumeBody ( current ) ;
break ;
case Types : : Padding :
// No parsing required
break ;
default :
2016-06-26 11:54:21 +08:00
return U_UNKNOWN_ITEM_TYPE ;
2015-03-13 14:48:53 +08:00
}
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseVolumeHeader ( const UByteArray & volume , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( volume . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
2015-12-12 17:59:38 +08:00
// Check that there is space for the volume header
if ( ( UINT32 ) volume . size ( ) < sizeof ( EFI_FIRMWARE_VOLUME_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseVolumeHeader: input volume size %Xh (%u) is smaller than volume header size 40h (64) " , volume . size ( ) , volume . size ( ) ) ) ;
return U_INVALID_VOLUME ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
// Populate volume header
const EFI_FIRMWARE_VOLUME_HEADER * volumeHeader = ( const EFI_FIRMWARE_VOLUME_HEADER * ) ( volume . constData ( ) ) ;
2015-12-12 17:59:38 +08:00
// Check sanity of HeaderLength value
if ( ( UINT32 ) ALIGN8 ( volumeHeader - > HeaderLength ) > ( UINT32 ) volume . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeHeader: volume header overlaps the end of data " ) ) ;
return U_INVALID_VOLUME ;
2015-12-12 17:59:38 +08:00
}
// Check sanity of ExtHeaderOffset value
if ( volumeHeader - > Revision > 1 & & volumeHeader - > ExtHeaderOffset
& & ( UINT32 ) ALIGN8 ( volumeHeader - > ExtHeaderOffset + sizeof ( EFI_FIRMWARE_VOLUME_EXT_HEADER ) ) > ( UINT32 ) volume . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeHeader: extended volume header overlaps the end of data " ) ) ;
return U_INVALID_VOLUME ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
// Calculate volume header size
UINT32 headerSize ;
2015-06-20 02:26:45 +08:00
EFI_GUID extendedHeaderGuid = { { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } } ;
2015-03-13 14:48:53 +08:00
bool hasExtendedHeader = false ;
if ( volumeHeader - > Revision > 1 & & volumeHeader - > ExtHeaderOffset ) {
hasExtendedHeader = true ;
const EFI_FIRMWARE_VOLUME_EXT_HEADER * extendedHeader = ( const EFI_FIRMWARE_VOLUME_EXT_HEADER * ) ( volume . constData ( ) + volumeHeader - > ExtHeaderOffset ) ;
headerSize = volumeHeader - > ExtHeaderOffset + extendedHeader - > ExtHeaderSize ;
extendedHeaderGuid = extendedHeader - > FvName ;
}
else
headerSize = volumeHeader - > HeaderLength ;
// Extended header end can be unaligned
headerSize = ALIGN8 ( headerSize ) ;
// Check for volume structure to be known
bool isUnknown = true ;
2016-04-07 14:23:37 +08:00
bool isNvramVolume = false ;
2015-03-13 14:48:53 +08:00
UINT8 ffsVersion = 0 ;
// Check for FFS v2 volume
2016-06-26 11:54:21 +08:00
UByteArray guid = UByteArray ( ( const char * ) volumeHeader - > FileSystemGuid . Data , sizeof ( EFI_GUID ) ) ;
2016-03-01 15:20:44 +08:00
if ( std : : find ( FFSv2Volumes . begin ( ) , FFSv2Volumes . end ( ) , guid ) ! = FFSv2Volumes . end ( ) ) {
2015-03-13 14:48:53 +08:00
isUnknown = false ;
ffsVersion = 2 ;
}
// Check for FFS v3 volume
2016-03-01 15:20:44 +08:00
if ( std : : find ( FFSv3Volumes . begin ( ) , FFSv3Volumes . end ( ) , guid ) ! = FFSv3Volumes . end ( ) ) {
2015-03-13 14:48:53 +08:00
isUnknown = false ;
ffsVersion = 3 ;
}
2016-03-28 21:03:32 +08:00
// Check for VSS NVRAM volume
2016-04-08 19:22:18 +08:00
if ( guid = = NVRAM_MAIN_STORE_VOLUME_GUID | | guid = = NVRAM_ADDITIONAL_STORE_VOLUME_GUID ) {
2016-03-28 21:03:32 +08:00
isUnknown = false ;
2016-04-07 14:23:37 +08:00
isNvramVolume = true ;
2016-03-28 21:03:32 +08:00
}
2015-03-13 14:48:53 +08:00
// Check volume revision and alignment
bool msgAlignmentBitsSet = false ;
bool msgUnaligned = false ;
bool msgUnknownRevision = false ;
UINT32 alignment = 65536 ; // Default volume alignment is 64K
if ( volumeHeader - > Revision = = 1 ) {
// Acquire alignment capability bit
2016-07-09 16:42:49 +08:00
bool alignmentCap = ( volumeHeader - > Attributes & EFI_FVB_ALIGNMENT_CAP ) ! = 0 ;
2015-03-13 14:48:53 +08:00
if ( ! alignmentCap ) {
2016-07-09 16:42:49 +08:00
if ( volumeHeader - > Attributes & 0xFFFF0000 )
2015-03-13 14:48:53 +08:00
msgAlignmentBitsSet = true ;
}
// Do not check for volume alignment on revision 1 volumes
2016-07-16 13:02:33 +08:00
// No one gives a single damn about setting it correctly
2015-03-13 14:48:53 +08:00
}
else if ( volumeHeader - > Revision = = 2 ) {
// Acquire alignment
alignment = ( UINT32 ) pow ( 2.0 , ( int ) ( volumeHeader - > Attributes & EFI_FVB2_ALIGNMENT ) > > 16 ) ;
// Check alignment
2015-12-30 06:39:43 +08:00
if ( ! isUnknown & & ! model - > compressed ( parent ) & & ( ( pdata . offset + parentOffset - capsuleOffsetFixup ) % alignment ) )
2015-03-13 14:48:53 +08:00
msgUnaligned = true ;
}
else
msgUnknownRevision = true ;
// Check attributes
// Determine value of empty byte
UINT8 emptyByte = volumeHeader - > Attributes & EFI_FVB_ERASE_POLARITY ? ' \xFF ' : ' \x00 ' ;
2015-09-01 03:34:42 +08:00
// Check for AppleCRC32 and AppleFreeSpaceOffset in ZeroVector
2015-07-07 21:57:41 +08:00
bool hasAppleCrc32 = false ;
2015-09-01 03:34:42 +08:00
bool hasAppleFSO = false ;
2015-03-13 14:48:53 +08:00
UINT32 volumeSize = volume . size ( ) ;
2015-07-07 21:57:41 +08:00
UINT32 appleCrc32 = * ( UINT32 * ) ( volume . constData ( ) + 8 ) ;
2015-09-01 03:34:42 +08:00
UINT32 appleFSO = * ( UINT32 * ) ( volume . constData ( ) + 12 ) ;
2015-07-07 21:57:41 +08:00
if ( appleCrc32 ! = 0 ) {
2015-03-13 14:48:53 +08:00
// Calculate CRC32 of the volume body
UINT32 crc = crc32 ( 0 , ( const UINT8 * ) ( volume . constData ( ) + volumeHeader - > HeaderLength ) , volumeSize - volumeHeader - > HeaderLength ) ;
2015-07-07 21:57:41 +08:00
if ( crc = = appleCrc32 ) {
hasAppleCrc32 = true ;
2015-03-13 14:48:53 +08:00
}
2015-09-01 03:34:42 +08:00
// Check if FreeSpaceOffset is non-zero
if ( appleFSO ! = 0 ) {
hasAppleFSO = true ;
}
2015-03-13 14:48:53 +08:00
}
// Check header checksum by recalculating it
bool msgInvalidChecksum = false ;
2016-06-26 11:54:21 +08:00
UByteArray tempHeader ( ( const char * ) volumeHeader , volumeHeader - > HeaderLength ) ;
2015-12-13 03:09:37 +08:00
( ( EFI_FIRMWARE_VOLUME_HEADER * ) tempHeader . data ( ) ) - > Checksum = 0 ;
UINT16 calculated = calculateChecksum16 ( ( const UINT16 * ) tempHeader . constData ( ) , volumeHeader - > HeaderLength ) ;
if ( volumeHeader - > Checksum ! = calculated )
2015-03-13 14:48:53 +08:00
msgInvalidChecksum = true ;
// Get info
2016-06-26 11:54:21 +08:00
UByteArray header = volume . left ( headerSize ) ;
UByteArray body = volume . mid ( headerSize ) ;
UString name = guidToUString ( volumeHeader - > FileSystemGuid ) ;
UString info = usprintf ( " Signature: _FVH \n ZeroVector: \n %02X %02X %02X %02X %02X %02X %02X %02X \n "
" %02X %02X %02X %02X %02X %02X %02X %02X \n FileSystem GUID: " ,
volumeHeader - > ZeroVector [ 0 ] , volumeHeader - > ZeroVector [ 1 ] , volumeHeader - > ZeroVector [ 2 ] , volumeHeader - > ZeroVector [ 3 ] ,
volumeHeader - > ZeroVector [ 4 ] , volumeHeader - > ZeroVector [ 5 ] , volumeHeader - > ZeroVector [ 6 ] , volumeHeader - > ZeroVector [ 7 ] ,
volumeHeader - > ZeroVector [ 8 ] , volumeHeader - > ZeroVector [ 9 ] , volumeHeader - > ZeroVector [ 10 ] , volumeHeader - > ZeroVector [ 11 ] ,
volumeHeader - > ZeroVector [ 12 ] , volumeHeader - > ZeroVector [ 13 ] , volumeHeader - > ZeroVector [ 14 ] , volumeHeader - > ZeroVector [ 15 ] )
+ guidToUString ( volumeHeader - > FileSystemGuid ) \
2016-06-26 16:05:45 +08:00
+ usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Revision: %u \n Attributes: %08Xh \n Erase polarity: %u \n Checksum: %04Xh " ,
2016-06-26 11:54:21 +08:00
volumeSize , volumeSize ,
headerSize , headerSize ,
volumeSize - headerSize , volumeSize - headerSize ,
volumeHeader - > Revision ,
2016-06-26 16:05:45 +08:00
volumeHeader - > Attributes ,
( emptyByte ? 1 : 0 ) ,
2016-06-26 11:54:21 +08:00
volumeHeader - > Checksum ) +
2016-06-26 16:05:45 +08:00
( msgInvalidChecksum ? usprintf ( " , invalid, should be %04Xh " , calculated ) : UString ( " , valid " ) ) ;
2015-03-13 14:48:53 +08:00
// Extended header present
if ( volumeHeader - > Revision > 1 & & volumeHeader - > ExtHeaderOffset ) {
const EFI_FIRMWARE_VOLUME_EXT_HEADER * extendedHeader = ( const EFI_FIRMWARE_VOLUME_EXT_HEADER * ) ( volume . constData ( ) + volumeHeader - > ExtHeaderOffset ) ;
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Extended header size: %Xh (%u) \n Volume GUID: " ,
extendedHeader - > ExtHeaderSize , extendedHeader - > ExtHeaderSize ) + guidToUString ( extendedHeader - > FvName ) ;
2015-03-13 14:48:53 +08:00
}
// Construct parsing data
pdata . offset + = parentOffset ;
pdata . emptyByte = emptyByte ;
pdata . ffsVersion = ffsVersion ;
pdata . volume . hasExtendedHeader = hasExtendedHeader ? TRUE : FALSE ;
pdata . volume . extendedHeaderGuid = extendedHeaderGuid ;
pdata . volume . alignment = alignment ;
pdata . volume . revision = volumeHeader - > Revision ;
2015-07-07 21:57:41 +08:00
pdata . volume . hasAppleCrc32 = hasAppleCrc32 ;
2015-09-01 03:34:42 +08:00
pdata . volume . hasAppleFSO = hasAppleFSO ;
2015-03-13 14:48:53 +08:00
pdata . volume . isWeakAligned = ( volumeHeader - > Revision > 1 & & ( volumeHeader - > Attributes & EFI_FVB2_WEAK_ALIGNMENT ) ) ;
// Add text
2016-06-26 11:54:21 +08:00
UString text ;
2015-07-07 21:57:41 +08:00
if ( hasAppleCrc32 )
2016-06-26 11:54:21 +08:00
text + = UString ( " AppleCRC32 " ) ;
2015-09-01 03:34:42 +08:00
if ( hasAppleFSO )
2016-06-26 11:54:21 +08:00
text + = UString ( " AppleFSO " ) ;
2015-03-13 14:48:53 +08:00
// Add tree item
UINT8 subtype = Subtypes : : UnknownVolume ;
if ( ! isUnknown ) {
if ( ffsVersion = = 2 )
subtype = Subtypes : : Ffs2Volume ;
else if ( ffsVersion = = 3 )
subtype = Subtypes : : Ffs3Volume ;
2016-04-07 14:23:37 +08:00
else if ( isNvramVolume )
subtype = Subtypes : : NvramVolume ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Volume , subtype , name , text , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-03-13 14:48:53 +08:00
// Show messages
if ( isUnknown )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeHeader: unknown file system " ) + guidToUString ( volumeHeader - > FileSystemGuid ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgInvalidChecksum )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeHeader: volume header checksum is invalid " ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgAlignmentBitsSet )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeHeader: alignment bits set on volume without alignment capability " ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgUnaligned )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeHeader: unaligned volume " ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgUnknownRevision )
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseVolumeHeader: unknown volume revision %u " , volumeHeader - > Revision ) , index ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : findNextVolume ( const UModelIndex & index , const UByteArray & bios , const UINT32 parentOffset , const UINT32 volumeOffset , UINT32 & nextVolumeOffset )
2015-03-13 14:48:53 +08:00
{
int nextIndex = bios . indexOf ( EFI_FV_SIGNATURE , volumeOffset ) ;
if ( nextIndex < EFI_FV_SIGNATURE_OFFSET )
2016-06-26 11:54:21 +08:00
return U_VOLUMES_NOT_FOUND ;
2015-03-13 14:48:53 +08:00
2015-09-13 23:32:22 +08:00
// Check volume header to be sane
2016-01-28 07:21:51 +08:00
for ( ; nextIndex > 0 ; nextIndex = bios . indexOf ( EFI_FV_SIGNATURE , nextIndex + 1 ) ) {
2015-09-13 23:32:22 +08:00
const EFI_FIRMWARE_VOLUME_HEADER * volumeHeader = ( const EFI_FIRMWARE_VOLUME_HEADER * ) ( bios . constData ( ) + nextIndex - EFI_FV_SIGNATURE_OFFSET ) ;
2015-12-12 17:59:38 +08:00
if ( volumeHeader - > FvLength < sizeof ( EFI_FIRMWARE_VOLUME_HEADER ) + 2 * sizeof ( EFI_FV_BLOCK_MAP_ENTRY ) | | volumeHeader - > FvLength > = 0xFFFFFFFFUL ) {
2016-07-09 16:08:32 +08:00
msg ( usprintf ( " findNextVolume: volume candidate at offset %Xh skipped, has invalid FvLength % " PRIX64 " h " ,
2016-06-26 11:54:21 +08:00
parentOffset + ( nextIndex - EFI_FV_SIGNATURE_OFFSET ) ,
volumeHeader - > FvLength ) , index ) ;
2015-09-13 23:32:22 +08:00
continue ;
}
if ( volumeHeader - > Reserved ! = 0xFF & & volumeHeader - > Reserved ! = 0x00 ) {
2016-06-26 16:05:45 +08:00
msg ( usprintf ( " findNextVolume: volume candidate at offset %Xh skipped, has invalid Reserved byte value %02Xh " ,
2016-06-26 11:54:21 +08:00
parentOffset + ( nextIndex - EFI_FV_SIGNATURE_OFFSET ) ,
volumeHeader - > Reserved ) , index ) ;
2015-09-13 23:32:22 +08:00
continue ;
}
if ( volumeHeader - > Revision ! = 1 & & volumeHeader - > Revision ! = 2 ) {
2016-06-26 16:05:45 +08:00
msg ( usprintf ( " findNextVolume: volume candidate at offset %Xh skipped, has invalid Revision byte value %02Xh " ,
2016-06-26 11:54:21 +08:00
parentOffset + ( nextIndex - EFI_FV_SIGNATURE_OFFSET )
, volumeHeader - > Revision ) , index ) ;
2015-09-13 23:32:22 +08:00
continue ;
}
// All checks passed, volume found
break ;
}
2016-03-28 21:03:32 +08:00
// No more volumes found
2015-09-13 23:32:22 +08:00
if ( nextIndex < EFI_FV_SIGNATURE_OFFSET )
2016-06-26 11:54:21 +08:00
return U_VOLUMES_NOT_FOUND ;
2015-09-13 23:32:22 +08:00
2015-03-13 14:48:53 +08:00
nextVolumeOffset = nextIndex - EFI_FV_SIGNATURE_OFFSET ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : getVolumeSize ( const UByteArray & bios , UINT32 volumeOffset , UINT32 & volumeSize , UINT32 & bmVolumeSize )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check that there is space for the volume header and at least two block map entries.
if ( ( UINT32 ) bios . size ( ) < volumeOffset + sizeof ( EFI_FIRMWARE_VOLUME_HEADER ) + 2 * sizeof ( EFI_FV_BLOCK_MAP_ENTRY ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_VOLUME ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Populate volume header
const EFI_FIRMWARE_VOLUME_HEADER * volumeHeader = ( const EFI_FIRMWARE_VOLUME_HEADER * ) ( bios . constData ( ) + volumeOffset ) ;
// Check volume signature
2016-06-26 11:54:21 +08:00
if ( UByteArray ( ( const char * ) & volumeHeader - > Signature , sizeof ( volumeHeader - > Signature ) ) ! = EFI_FV_SIGNATURE )
return U_INVALID_VOLUME ;
2015-03-13 14:48:53 +08:00
// Calculate volume size using BlockMap
const EFI_FV_BLOCK_MAP_ENTRY * entry = ( const EFI_FV_BLOCK_MAP_ENTRY * ) ( bios . constData ( ) + volumeOffset + sizeof ( EFI_FIRMWARE_VOLUME_HEADER ) ) ;
UINT32 calcVolumeSize = 0 ;
while ( entry - > NumBlocks ! = 0 & & entry - > Length ! = 0 ) {
if ( ( void * ) entry > bios . constData ( ) + bios . size ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_VOLUME ;
2015-03-13 14:48:53 +08:00
calcVolumeSize + = entry - > NumBlocks * entry - > Length ;
entry + = 1 ;
}
2016-07-06 00:19:04 +08:00
volumeSize = ( UINT32 ) volumeHeader - > FvLength ;
2015-03-13 14:48:53 +08:00
bmVolumeSize = calcVolumeSize ;
2015-12-12 17:59:38 +08:00
if ( volumeSize = = 0 )
2016-06-26 11:54:21 +08:00
return U_INVALID_VOLUME ;
2015-12-12 17:59:38 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseVolumeNonUefiData ( const UByteArray & data , const UINT32 parentOffset , const UModelIndex & index )
2015-09-19 16:08:26 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-09-19 16:08:26 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-09-19 16:08:26 +08:00
2016-07-16 13:02:33 +08:00
// Add parent offset
2015-09-19 16:08:26 +08:00
pdata . offset + = parentOffset ;
// Get info
2016-07-16 13:02:33 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , data . size ( ) , data . size ( ) ) ;
2015-09-19 16:08:26 +08:00
// Add padding tree item
2016-07-16 13:02:33 +08:00
UModelIndex paddingIndex = model - > addItem ( Types : : Padding , Subtypes : : DataPadding , UString ( " Non-UEFI data " ) , UString ( ) , info , UByteArray ( ) , data , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeNonUefiData: non-UEFI data found in volume's free space " ) , paddingIndex ) ;
2015-09-19 16:08:26 +08:00
2016-07-16 13:02:33 +08:00
// Parse contents as RAW area
return parseRawArea ( paddingIndex ) ;
2015-09-19 16:08:26 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseVolumeBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Get volume header size and body
2016-06-26 11:54:21 +08:00
UByteArray volumeBody = model - > body ( index ) ;
2015-03-13 14:48:53 +08:00
UINT32 volumeHeaderSize = model - > header ( index ) . size ( ) ;
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-03-13 14:48:53 +08:00
UINT32 offset = pdata . offset ;
2016-03-28 21:03:32 +08:00
// Parse VSS NVRAM volumes with a dedicated function
2016-04-07 14:23:37 +08:00
if ( model - > subtype ( index ) = = Subtypes : : NvramVolume )
2016-04-17 07:25:44 +08:00
return parseNvramVolumeBody ( index ) ;
2016-03-28 21:03:32 +08:00
2015-03-13 14:48:53 +08:00
if ( pdata . ffsVersion ! = 2 & & pdata . ffsVersion ! = 3 ) // Don't parse unknown volumes
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
// Search for and parse all files
UINT32 volumeBodySize = volumeBody . size ( ) ;
UINT32 fileOffset = 0 ;
while ( fileOffset < volumeBodySize ) {
UINT32 fileSize = getFileSize ( volumeBody , fileOffset , pdata . ffsVersion ) ;
// Check file size
if ( fileSize < sizeof ( EFI_FFS_FILE_HEADER ) | | fileSize > volumeBodySize - fileOffset ) {
// Check that we are at the empty space
2016-06-26 11:54:21 +08:00
UByteArray header = volumeBody . mid ( fileOffset , sizeof ( EFI_FFS_FILE_HEADER ) ) ;
2015-03-13 14:48:53 +08:00
if ( header . count ( pdata . emptyByte ) = = header . size ( ) ) { //Empty space
// Check free space to be actually free
2016-06-26 11:54:21 +08:00
UByteArray freeSpace = volumeBody . mid ( fileOffset ) ;
2016-07-05 23:22:03 +08:00
if ( freeSpace . count ( pdata . emptyByte ) ! = freeSpace . size ( ) ) {
2015-03-13 14:48:53 +08:00
// Search for the first non-empty byte
UINT32 i ;
UINT32 size = freeSpace . size ( ) ;
const UINT8 * current = ( UINT8 * ) freeSpace . constData ( ) ;
for ( i = 0 ; i < size ; i + + ) {
if ( * current + + ! = pdata . emptyByte )
break ;
}
// Align found index to file alignment
// It must be possible because minimum 16 bytes of empty were found before
if ( i ! = ALIGN8 ( i ) )
i = ALIGN8 ( i ) - 8 ;
// Construct parsing data
pdata . offset = offset + volumeHeaderSize + fileOffset ;
2015-09-19 16:08:26 +08:00
// Add all bytes before as free space
2015-03-13 14:48:53 +08:00
if ( i > 0 ) {
2016-06-26 11:54:21 +08:00
UByteArray free = freeSpace . left ( i ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , free . size ( ) , free . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Add free space item
2016-07-16 13:02:33 +08:00
model - > addItem ( Types : : FreeSpace , 0 , UString ( " Volume free space " ) , UString ( ) , info , UByteArray ( ) , free , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
}
2015-09-19 16:08:26 +08:00
// Parse non-UEFI data
parseVolumeNonUefiData ( freeSpace . mid ( i ) , volumeHeaderSize + fileOffset + i , index ) ;
2015-03-13 14:48:53 +08:00
}
else {
// Construct parsing data
pdata . offset = offset + volumeHeaderSize + fileOffset ;
// Get info
2016-06-26 11:54:21 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , freeSpace . size ( ) , freeSpace . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Add free space item
2016-07-16 13:02:33 +08:00
model - > addItem ( Types : : FreeSpace , 0 , UString ( " Volume free space " ) , UString ( ) , info , UByteArray ( ) , freeSpace , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
}
break ; // Exit from parsing loop
}
else { //File space
2015-09-19 16:08:26 +08:00
// Parse non-UEFI data
parseVolumeNonUefiData ( volumeBody . mid ( fileOffset ) , volumeHeaderSize + fileOffset , index ) ;
2015-03-13 14:48:53 +08:00
break ; // Exit from parsing loop
}
}
// Get file header
2016-06-26 11:54:21 +08:00
UByteArray file = volumeBody . mid ( fileOffset , fileSize ) ;
UByteArray header = file . left ( sizeof ( EFI_FFS_FILE_HEADER ) ) ;
2015-03-13 14:48:53 +08:00
const EFI_FFS_FILE_HEADER * fileHeader = ( const EFI_FFS_FILE_HEADER * ) header . constData ( ) ;
if ( pdata . ffsVersion = = 3 & & ( fileHeader - > Attributes & FFS_ATTRIB_LARGE_FILE ) ) {
header = file . left ( sizeof ( EFI_FFS_FILE_HEADER2 ) ) ;
}
//Parse current file's header
2016-06-26 11:54:21 +08:00
UModelIndex fileIndex ;
USTATUS result = parseFileHeader ( file , volumeHeaderSize + fileOffset , index , fileIndex ) ;
2015-03-13 14:48:53 +08:00
if ( result )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeBody: file header parsing failed with error " ) + errorCodeToUString ( result ) , index ) ;
2015-03-13 14:48:53 +08:00
// Move to next file
fileOffset + = fileSize ;
fileOffset = ALIGN8 ( fileOffset ) ;
}
// Check for duplicate GUIDs
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2016-06-26 11:54:21 +08:00
UModelIndex current = index . child ( i , 0 ) ;
2015-03-13 14:48:53 +08:00
// Skip non-file entries and pad files
if ( model - > type ( current ) ! = Types : : File | | model - > subtype ( current ) = = EFI_FV_FILETYPE_PAD )
continue ;
2016-04-21 04:41:18 +08:00
// Get current file parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA currentPdata = parsingDataFromUModelIndex ( current ) ;
UByteArray currentGuid ( ( const char * ) & currentPdata . file . guid , sizeof ( EFI_GUID ) ) ;
2016-04-21 04:41:18 +08:00
2015-12-12 17:59:38 +08:00
// Check files after current for having an equal GUID
2015-03-13 14:48:53 +08:00
for ( int j = i + 1 ; j < model - > rowCount ( index ) ; j + + ) {
2016-06-26 11:54:21 +08:00
UModelIndex another = index . child ( j , 0 ) ;
2016-04-21 04:41:18 +08:00
2015-03-13 14:48:53 +08:00
// Skip non-file entries
if ( model - > type ( another ) ! = Types : : File )
continue ;
2016-04-21 04:41:18 +08:00
// Get another file parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA anotherPdata = parsingDataFromUModelIndex ( another ) ;
UByteArray anotherGuid ( ( const char * ) & anotherPdata . file . guid , sizeof ( EFI_GUID ) ) ;
2016-04-21 04:41:18 +08:00
2015-12-12 17:59:38 +08:00
// Check GUIDs for being equal
2015-03-13 14:48:53 +08:00
if ( currentGuid = = anotherGuid ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVolumeBody: file with duplicate GUID " ) + guidToUString ( anotherPdata . file . guid ) , another ) ;
2015-03-13 14:48:53 +08:00
}
}
}
//Parse bodies
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2016-06-26 11:54:21 +08:00
UModelIndex current = index . child ( i , 0 ) ;
2015-03-13 14:48:53 +08:00
switch ( model - > type ( current ) ) {
case Types : : File :
parseFileBody ( current ) ;
break ;
case Types : : Padding :
case Types : : FreeSpace :
// No parsing required
break ;
default :
2016-06-26 11:54:21 +08:00
return U_UNKNOWN_ITEM_TYPE ;
2015-03-13 14:48:53 +08:00
}
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
UINT32 FfsParser : : getFileSize ( const UByteArray & volume , const UINT32 fileOffset , const UINT8 ffsVersion )
2015-03-13 14:48:53 +08:00
{
if ( ffsVersion = = 2 ) {
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) volume . size ( ) < fileOffset + sizeof ( EFI_FFS_FILE_HEADER ) )
return 0 ;
2015-03-13 14:48:53 +08:00
const EFI_FFS_FILE_HEADER * fileHeader = ( const EFI_FFS_FILE_HEADER * ) ( volume . constData ( ) + fileOffset ) ;
return uint24ToUint32 ( fileHeader - > Size ) ;
}
else if ( ffsVersion = = 3 ) {
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) volume . size ( ) < fileOffset + sizeof ( EFI_FFS_FILE_HEADER2 ) )
return 0 ;
2015-03-13 14:48:53 +08:00
const EFI_FFS_FILE_HEADER2 * fileHeader = ( const EFI_FFS_FILE_HEADER2 * ) ( volume . constData ( ) + fileOffset ) ;
if ( fileHeader - > Attributes & FFS_ATTRIB_LARGE_FILE )
return fileHeader - > ExtendedSize ;
else
return uint24ToUint32 ( fileHeader - > Size ) ;
}
else
return 0 ;
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFileHeader ( const UByteArray & file , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( file . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) file . size ( ) < sizeof ( EFI_FFS_FILE_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_FILE ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Get parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Get file header
2016-06-26 11:54:21 +08:00
UByteArray header = file . left ( sizeof ( EFI_FFS_FILE_HEADER ) ) ;
2015-03-13 14:48:53 +08:00
const EFI_FFS_FILE_HEADER * fileHeader = ( const EFI_FFS_FILE_HEADER * ) header . constData ( ) ;
if ( pdata . ffsVersion = = 3 & & ( fileHeader - > Attributes & FFS_ATTRIB_LARGE_FILE ) ) {
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) file . size ( ) < sizeof ( EFI_FFS_FILE_HEADER2 ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_FILE ;
2015-03-13 14:48:53 +08:00
header = file . left ( sizeof ( EFI_FFS_FILE_HEADER2 ) ) ;
}
// Check file alignment
bool msgUnalignedFile = false ;
UINT8 alignmentPower = ffsAlignmentTable [ ( fileHeader - > Attributes & FFS_ATTRIB_DATA_ALIGNMENT ) > > 3 ] ;
UINT32 alignment = ( UINT32 ) pow ( 2.0 , alignmentPower ) ;
if ( ( parentOffset + header . size ( ) ) % alignment )
msgUnalignedFile = true ;
// Check file alignment agains volume alignment
2015-12-12 17:59:38 +08:00
bool msgFileAlignmentIsGreaterThanVolumes = false ;
2015-03-13 14:48:53 +08:00
if ( ! pdata . volume . isWeakAligned & & pdata . volume . alignment < alignment )
2015-12-12 17:59:38 +08:00
msgFileAlignmentIsGreaterThanVolumes = true ;
2015-03-13 14:48:53 +08:00
// Check header checksum
2016-06-26 11:54:21 +08:00
UByteArray tempHeader = header ;
2015-03-13 14:48:53 +08:00
EFI_FFS_FILE_HEADER * tempFileHeader = ( EFI_FFS_FILE_HEADER * ) ( tempHeader . data ( ) ) ;
tempFileHeader - > IntegrityCheck . Checksum . Header = 0 ;
tempFileHeader - > IntegrityCheck . Checksum . File = 0 ;
2015-12-13 03:09:37 +08:00
UINT8 calculatedHeader = calculateChecksum8 ( ( const UINT8 * ) tempFileHeader , header . size ( ) - 1 ) ;
2015-03-13 14:48:53 +08:00
bool msgInvalidHeaderChecksum = false ;
2015-12-13 03:09:37 +08:00
if ( fileHeader - > IntegrityCheck . Checksum . Header ! = calculatedHeader )
2015-03-13 14:48:53 +08:00
msgInvalidHeaderChecksum = true ;
// Check data checksum
// Data checksum must be calculated
bool msgInvalidDataChecksum = false ;
2015-12-13 03:09:37 +08:00
UINT8 calculatedData = 0 ;
2015-03-13 14:48:53 +08:00
if ( fileHeader - > Attributes & FFS_ATTRIB_CHECKSUM ) {
UINT32 bufferSize = file . size ( ) - header . size ( ) ;
// Exclude file tail from data checksum calculation
if ( pdata . volume . revision = = 1 & & ( fileHeader - > Attributes & FFS_ATTRIB_TAIL_PRESENT ) )
bufferSize - = sizeof ( UINT16 ) ;
2015-12-13 03:09:37 +08:00
calculatedData = calculateChecksum8 ( ( const UINT8 * ) ( file . constData ( ) + header . size ( ) ) , bufferSize ) ;
if ( fileHeader - > IntegrityCheck . Checksum . File ! = calculatedData )
2015-03-13 14:48:53 +08:00
msgInvalidDataChecksum = true ;
}
// Data checksum must be one of predefined values
2015-12-13 03:09:37 +08:00
else if ( pdata . volume . revision = = 1 & & fileHeader - > IntegrityCheck . Checksum . File ! = FFS_FIXED_CHECKSUM ) {
calculatedData = FFS_FIXED_CHECKSUM ;
2015-03-13 14:48:53 +08:00
msgInvalidDataChecksum = true ;
2015-12-13 03:09:37 +08:00
}
else if ( pdata . volume . revision = = 2 & & fileHeader - > IntegrityCheck . Checksum . File ! = FFS_FIXED_CHECKSUM2 ) {
calculatedData = FFS_FIXED_CHECKSUM2 ;
2015-03-13 14:48:53 +08:00
msgInvalidDataChecksum = true ;
2015-12-13 03:09:37 +08:00
}
2015-03-13 14:48:53 +08:00
// Check file type
bool msgUnknownType = false ;
if ( fileHeader - > Type > EFI_FV_FILETYPE_SMM_CORE & & fileHeader - > Type ! = EFI_FV_FILETYPE_PAD ) {
msgUnknownType = true ;
} ;
// Get file body
2016-06-26 11:54:21 +08:00
UByteArray body = file . mid ( header . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Check for file tail presence
2016-06-26 11:54:21 +08:00
UByteArray tail ;
2015-03-13 14:48:53 +08:00
bool msgInvalidTailValue = false ;
if ( pdata . volume . revision = = 1 & & ( fileHeader - > Attributes & FFS_ATTRIB_TAIL_PRESENT ) )
{
//Check file tail;
2016-04-21 04:41:18 +08:00
UINT16 tailValue = * ( UINT16 * ) body . right ( sizeof ( UINT16 ) ) . constData ( ) ;
if ( fileHeader - > IntegrityCheck . TailReference ! = ( UINT16 ) ~ tailValue )
2015-03-13 14:48:53 +08:00
msgInvalidTailValue = true ;
2016-04-21 04:41:18 +08:00
// Get tail and remove it from file body
tail = body . right ( sizeof ( UINT16 ) ) ;
2015-03-13 14:48:53 +08:00
body = body . left ( body . size ( ) - sizeof ( UINT16 ) ) ;
}
// Get info
2016-06-26 11:54:21 +08:00
UString name ;
UString info ;
2015-03-13 14:48:53 +08:00
if ( fileHeader - > Type ! = EFI_FV_FILETYPE_PAD )
2016-06-26 11:54:21 +08:00
name = guidToUString ( fileHeader - > Name ) ;
2015-03-13 14:48:53 +08:00
else
2016-06-26 11:54:21 +08:00
name = UString ( " Pad-file " ) ;
2016-06-26 16:05:45 +08:00
info = UString ( " File GUID: " ) + guidToUString ( fileHeader - > Name ) +
usprintf ( " \n Type: %02Xh \n Attributes: %02Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Tail size: %Xh (%u) \n State: %02Xh " ,
2016-06-26 11:54:21 +08:00
fileHeader - > Type ,
fileHeader - > Attributes ,
header . size ( ) + body . size ( ) + tail . size ( ) , header . size ( ) + body . size ( ) + tail . size ( ) ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
tail . size ( ) , tail . size ( ) ,
2016-06-26 16:05:45 +08:00
fileHeader - > State ) +
usprintf ( " \n Header checksum: %02Xh " , fileHeader - > IntegrityCheck . Checksum . Header ) + ( msgInvalidHeaderChecksum ? usprintf ( " , invalid, should be %02Xh " , calculatedHeader ) : UString ( " , valid " ) ) +
usprintf ( " \n Data checksum: %02Xh " , fileHeader - > IntegrityCheck . Checksum . File ) + ( msgInvalidDataChecksum ? usprintf ( " , invalid, should be %02Xh " , calculatedData ) : UString ( " , valid " ) ) ;
2015-03-13 14:48:53 +08:00
2016-04-21 04:41:18 +08:00
// Add file GUID to parsing data
pdata . file . guid = fileHeader - > Name ;
2016-03-21 06:59:03 +08:00
2016-06-26 11:54:21 +08:00
UString text ;
2015-06-20 02:26:45 +08:00
bool isVtf = false ;
2016-03-21 06:59:03 +08:00
// Check if the file is a Volume Top File
2016-06-26 11:54:21 +08:00
if ( UByteArray ( ( const char * ) & fileHeader - > Name , sizeof ( EFI_GUID ) ) = = EFI_FFS_VOLUME_TOP_FILE_GUID ) {
2015-06-20 02:26:45 +08:00
// Mark it as the last VTF
// This information will later be used to determine memory addresses of uncompressed image elements
// Because the last byte of the last VFT is mapped to 0xFFFFFFFF physical memory address
isVtf = true ;
2016-06-26 11:54:21 +08:00
text = UString ( " Volume Top File " ) ;
2015-06-20 02:26:45 +08:00
}
2015-03-13 14:48:53 +08:00
// Construct parsing data
2016-07-07 13:57:45 +08:00
bool fixed = ( fileHeader - > Attributes & FFS_ATTRIB_FIXED ) ! = 0 ;
2015-03-13 14:48:53 +08:00
pdata . offset + = parentOffset ;
2016-04-21 04:41:18 +08:00
2015-03-13 14:48:53 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : File , fileHeader - > Type , name , text , info , header , body , tail , fixed , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-06-20 02:26:45 +08:00
// Overwrite lastVtf, if needed
if ( isVtf ) {
lastVtf = index ;
}
2015-03-13 14:48:53 +08:00
// Show messages
if ( msgUnalignedFile )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFileHeader: unaligned file " ) , index ) ;
2015-12-12 17:59:38 +08:00
if ( msgFileAlignmentIsGreaterThanVolumes )
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseFileHeader: file alignment %Xh is greater than parent volume alignment %Xh " , alignment , pdata . volume . alignment ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgInvalidHeaderChecksum )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFileHeader: invalid header checksum " ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgInvalidDataChecksum )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFileHeader: invalid data checksum " ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgInvalidTailValue )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFileHeader: invalid tail value " ) , index ) ;
2015-03-13 14:48:53 +08:00
if ( msgUnknownType )
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseFileHeader: unknown file type %02Xh " , fileHeader - > Type ) , index ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
UINT32 FfsParser : : getSectionSize ( const UByteArray & file , const UINT32 sectionOffset , const UINT8 ffsVersion )
2015-03-13 14:48:53 +08:00
{
if ( ffsVersion = = 2 ) {
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) file . size ( ) < sectionOffset + sizeof ( EFI_COMMON_SECTION_HEADER ) )
return 0 ;
2015-03-13 14:48:53 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( file . constData ( ) + sectionOffset ) ;
return uint24ToUint32 ( sectionHeader - > Size ) ;
}
else if ( ffsVersion = = 3 ) {
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) file . size ( ) < sectionOffset + sizeof ( EFI_COMMON_SECTION_HEADER2 ) )
return 0 ;
2015-03-13 14:48:53 +08:00
const EFI_COMMON_SECTION_HEADER2 * sectionHeader = ( const EFI_COMMON_SECTION_HEADER2 * ) ( file . constData ( ) + sectionOffset ) ;
UINT32 size = uint24ToUint32 ( sectionHeader - > Size ) ;
if ( size = = EFI_SECTION2_IS_USED )
return sectionHeader - > ExtendedSize ;
else
return size ;
}
else
return 0 ;
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFileBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Do not parse non-file bodies
if ( model - > type ( index ) ! = Types : : File )
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
// Parse pad-file body
if ( model - > subtype ( index ) = = EFI_FV_FILETYPE_PAD )
return parsePadFileBody ( index ) ;
// Parse raw files as raw areas
2016-03-21 06:59:03 +08:00
if ( model - > subtype ( index ) = = EFI_FV_FILETYPE_RAW | | model - > subtype ( index ) = = EFI_FV_FILETYPE_ALL ) {
// Get data from parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-03-21 06:59:03 +08:00
2016-04-07 14:23:37 +08:00
// Parse NVAR store
2016-06-26 11:54:21 +08:00
if ( UByteArray ( ( const char * ) & pdata . file . guid , sizeof ( EFI_GUID ) ) = = NVRAM_NVAR_STORE_FILE_GUID )
2016-04-21 04:41:18 +08:00
return parseNvarStore ( index ) ;
2016-03-21 06:59:03 +08:00
2016-04-17 07:25:44 +08:00
return parseRawArea ( index ) ;
2016-03-21 06:59:03 +08:00
}
2015-03-13 14:48:53 +08:00
// Parse sections
2016-07-16 13:02:33 +08:00
return parseSections ( model - > body ( index ) , index , true ) ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parsePadFileBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Get data from parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-03-13 14:48:53 +08:00
// Check if all bytes of the file are empty
2016-06-26 11:54:21 +08:00
UByteArray body = model - > body ( index ) ;
2015-03-13 14:48:53 +08:00
if ( body . size ( ) = = body . count ( pdata . emptyByte ) )
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
// Search for the first non-empty byte
UINT32 i ;
UINT32 size = body . size ( ) ;
const UINT8 * current = ( const UINT8 * ) body . constData ( ) ;
for ( i = 0 ; i < size ; i + + ) {
if ( * current + + ! = pdata . emptyByte )
break ;
}
// Add all bytes before as free space...
if ( i > = 8 ) {
// Align free space to 8 bytes boundary
if ( i ! = ALIGN8 ( i ) )
i = ALIGN8 ( i ) - 8 ;
2016-06-26 11:54:21 +08:00
UByteArray free = body . left ( i ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , free . size ( ) , free . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Constuct parsing data
pdata . offset + = model - > header ( index ) . size ( ) ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , free , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
}
else
i = 0 ;
// ... and all bytes after as a padding
2016-06-26 11:54:21 +08:00
UByteArray padding = body . mid ( i ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Constuct parsing data
pdata . offset + = i ;
// Add tree item
2016-07-16 13:02:33 +08:00
UModelIndex dataIndex = model - > addItem ( Types : : Padding , Subtypes : : DataPadding , UString ( " Non-UEFI data " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
// Show message
2016-06-26 11:54:21 +08:00
msg ( UString ( " parsePadFileBody: non-UEFI data found in pad-file " ) , dataIndex ) ;
2015-03-13 14:48:53 +08:00
// Rename the file
2016-06-26 11:54:21 +08:00
model - > setName ( index , UString ( " Non-empty pad-file " ) ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parseSections ( const UByteArray & sections , const UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Get data from parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-03-13 14:48:53 +08:00
// Search for and parse all sections
UINT32 bodySize = sections . size ( ) ;
UINT32 headerSize = model - > header ( index ) . size ( ) ;
UINT32 sectionOffset = 0 ;
2016-06-26 11:54:21 +08:00
USTATUS result = U_SUCCESS ;
2015-03-13 14:48:53 +08:00
while ( sectionOffset < bodySize ) {
// Get section size
UINT32 sectionSize = getSectionSize ( sections , sectionOffset , pdata . ffsVersion ) ;
// Check section size
if ( sectionSize < sizeof ( EFI_COMMON_SECTION_HEADER ) | | sectionSize > ( bodySize - sectionOffset ) ) {
2016-02-02 09:08:08 +08:00
// Final parsing
2016-07-16 13:02:33 +08:00
if ( insertIntoTree ) {
// Add padding to fill the rest of sections
UByteArray padding = sections . mid ( sectionOffset ) ;
// Get info
UString info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
// Constuct parsing data
pdata . offset + = headerSize + sectionOffset ;
2016-02-02 09:08:08 +08:00
// Add tree item
2016-07-16 13:02:33 +08:00
UModelIndex dataIndex = model - > addItem ( Types : : Padding , Subtypes : : DataPadding , UString ( " Non-UEFI data " ) , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2015-03-13 14:48:53 +08:00
2016-02-02 09:08:08 +08:00
// Show message
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseSections: non-UEFI data found in sections area " ) , dataIndex ) ;
2016-07-16 13:02:33 +08:00
// Exit from parsing loop
break ;
2016-02-02 09:08:08 +08:00
}
// Preparsing
2016-07-16 13:02:33 +08:00
else
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-03-13 14:48:53 +08:00
}
// Parse section header
2016-06-26 11:54:21 +08:00
UModelIndex sectionIndex ;
2016-07-16 13:02:33 +08:00
result = parseSectionHeader ( sections . mid ( sectionOffset , sectionSize ) , headerSize + sectionOffset , index , sectionIndex , insertIntoTree ) ;
2016-02-02 09:08:08 +08:00
if ( result ) {
2016-07-16 13:02:33 +08:00
if ( insertIntoTree )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseSections: section header parsing failed with error " ) + errorCodeToUString ( result ) , index ) ;
2016-02-02 09:08:08 +08:00
else
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-02-02 09:08:08 +08:00
}
2015-03-13 14:48:53 +08:00
// Move to next section
sectionOffset + = sectionSize ;
sectionOffset = ALIGN4 ( sectionOffset ) ;
}
2016-07-16 13:02:33 +08:00
// Parse bodies, will be skipped if insertIntoTree is not required
2015-03-13 14:48:53 +08:00
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2016-06-26 11:54:21 +08:00
UModelIndex current = index . child ( i , 0 ) ;
2015-03-13 14:48:53 +08:00
switch ( model - > type ( current ) ) {
case Types : : Section :
parseSectionBody ( current ) ;
break ;
case Types : : Padding :
// No parsing required
break ;
default :
2016-06-26 11:54:21 +08:00
return U_UNKNOWN_ITEM_TYPE ;
2015-03-13 14:48:53 +08:00
}
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parseSectionHeader ( const UByteArray & section , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-03-13 14:48:53 +08:00
2015-12-12 17:59:38 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( section . constData ( ) ) ;
2015-03-13 14:48:53 +08:00
switch ( sectionHeader - > Type ) {
// Special
2016-07-16 13:02:33 +08:00
case EFI_SECTION_COMPRESSION : return parseCompressedSectionHeader ( section , parentOffset , parent , index , insertIntoTree ) ;
case EFI_SECTION_GUID_DEFINED : return parseGuidedSectionHeader ( section , parentOffset , parent , index , insertIntoTree ) ;
case EFI_SECTION_FREEFORM_SUBTYPE_GUID : return parseFreeformGuidedSectionHeader ( section , parentOffset , parent , index , insertIntoTree ) ;
case EFI_SECTION_VERSION : return parseVersionSectionHeader ( section , parentOffset , parent , index , insertIntoTree ) ;
2016-03-21 06:59:03 +08:00
case PHOENIX_SECTION_POSTCODE :
2016-07-16 13:02:33 +08:00
case INSYDE_SECTION_POSTCODE : return parsePostcodeSectionHeader ( section , parentOffset , parent , index , insertIntoTree ) ;
2015-03-13 14:48:53 +08:00
// Common
case EFI_SECTION_DISPOSABLE :
case EFI_SECTION_DXE_DEPEX :
case EFI_SECTION_PEI_DEPEX :
case EFI_SECTION_SMM_DEPEX :
case EFI_SECTION_PE32 :
case EFI_SECTION_PIC :
2015-06-20 02:26:45 +08:00
case EFI_SECTION_TE :
2015-03-13 14:48:53 +08:00
case EFI_SECTION_COMPATIBILITY16 :
case EFI_SECTION_USER_INTERFACE :
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE :
2016-07-16 13:02:33 +08:00
case EFI_SECTION_RAW : return parseCommonSectionHeader ( section , parentOffset , parent , index , insertIntoTree ) ;
2015-12-12 17:59:38 +08:00
// Unknown
2015-03-13 14:48:53 +08:00
default :
2016-07-16 13:02:33 +08:00
USTATUS result = parseCommonSectionHeader ( section , parentOffset , parent , index , insertIntoTree ) ;
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseSectionHeader: section with unknown type %02Xh " , sectionHeader - > Type ) , index ) ;
2015-03-13 14:48:53 +08:00
return result ;
}
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parseCommonSectionHeader ( const UByteArray & section , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
2015-03-13 14:48:53 +08:00
// Get data from parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Obtain header fields
2016-05-05 01:41:03 +08:00
UINT32 headerSize ;
UINT8 type ;
const EFI_COMMON_SECTION_HEADER_APPLE * appleHeader = ( const EFI_COMMON_SECTION_HEADER_APPLE * ) ( section . constData ( ) ) ;
if ( ( UINT32 ) section . size ( ) > = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) & & appleHeader - > Reserved = = EFI_SECTION_APPLE_USED ) {
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) ;
type = appleHeader - > Type ;
}
else {
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( section . constData ( ) ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER ) ;
if ( pdata . ffsVersion = = 3 & & uint24ToUint32 ( sectionHeader - > Size ) = = EFI_SECTION2_IS_USED )
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER2 ) ;
type = sectionHeader - > Type ;
}
2015-03-13 14:48:53 +08:00
2016-05-05 01:41:03 +08:00
// Check sanity again
if ( ( UINT32 ) section . size ( ) < headerSize )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
2016-06-26 11:54:21 +08:00
UByteArray header = section . left ( headerSize ) ;
UByteArray body = section . mid ( headerSize ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name = sectionTypeToUString ( type ) + UString ( " section " ) ;
UString info = usprintf ( " Type: %02Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) " ,
type ,
section . size ( ) , section . size ( ) ,
headerSize , headerSize ,
body . size ( ) , body . size ( ) ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-07-16 13:02:33 +08:00
if ( insertIntoTree ) {
2016-07-11 15:35:01 +08:00
index = model - > addItem ( Types : : Section , type , name , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-02-09 19:00:14 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parseCompressedSectionHeader ( const UByteArray & section , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
2016-05-05 01:41:03 +08:00
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Get data from parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Obtain header fields
2016-05-05 01:41:03 +08:00
UINT32 headerSize ;
UINT8 compressionType ;
UINT32 uncompressedLength ;
2015-03-13 14:48:53 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( section . constData ( ) ) ;
2016-05-05 01:41:03 +08:00
const EFI_COMMON_SECTION_HEADER2 * section2Header = ( const EFI_COMMON_SECTION_HEADER2 * ) ( section . constData ( ) ) ;
const EFI_COMMON_SECTION_HEADER_APPLE * appleHeader = ( const EFI_COMMON_SECTION_HEADER_APPLE * ) ( section . constData ( ) ) ;
if ( ( UINT32 ) section . size ( ) > = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) & & appleHeader - > Reserved = = EFI_SECTION_APPLE_USED ) { // Check for apple section
const EFI_COMPRESSION_SECTION_APPLE * appleSectionHeader = ( const EFI_COMPRESSION_SECTION_APPLE * ) ( appleHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) + sizeof ( EFI_COMPRESSION_SECTION_APPLE ) ;
compressionType = ( UINT8 ) appleSectionHeader - > CompressionType ;
uncompressedLength = appleSectionHeader - > UncompressedLength ;
}
else if ( pdata . ffsVersion = = 3 & & uint24ToUint32 ( sectionHeader - > Size ) = = EFI_SECTION2_IS_USED ) { // Check for extended header section
const EFI_COMPRESSION_SECTION * compressedSectionHeader = ( const EFI_COMPRESSION_SECTION * ) ( section2Header + 1 ) ;
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( EFI_COMPRESSION_SECTION ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( EFI_COMPRESSION_SECTION ) ;
compressionType = compressedSectionHeader - > CompressionType ;
uncompressedLength = compressedSectionHeader - > UncompressedLength ;
}
else { // Normal section
const EFI_COMPRESSION_SECTION * compressedSectionHeader = ( const EFI_COMPRESSION_SECTION * ) ( sectionHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER ) + sizeof ( EFI_COMPRESSION_SECTION ) ;
compressionType = compressedSectionHeader - > CompressionType ;
2015-03-13 14:48:53 +08:00
uncompressedLength = compressedSectionHeader - > UncompressedLength ;
}
2016-05-05 01:41:03 +08:00
// Check sanity again
if ( ( UINT32 ) section . size ( ) < headerSize )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
2016-06-26 11:54:21 +08:00
UByteArray header = section . left ( headerSize ) ;
UByteArray body = section . mid ( headerSize ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name = sectionTypeToUString ( sectionHeader - > Type ) + UString ( " section " ) ;
UString info = usprintf ( " Type: %02Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Compression type: %02Xh \n Decompressed size: %Xh (%u) " ,
sectionHeader - > Type ,
section . size ( ) , section . size ( ) ,
headerSize , headerSize ,
body . size ( ) , body . size ( ) ,
compressionType ,
uncompressedLength , uncompressedLength ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
pdata . section . compressed . compressionType = compressionType ;
pdata . section . compressed . uncompressedSize = uncompressedLength ;
// Add tree item
2016-07-16 13:02:33 +08:00
if ( insertIntoTree ) {
2016-07-11 15:35:01 +08:00
index = model - > addItem ( Types : : Section , sectionHeader - > Type , name , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-02-09 19:00:14 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parseGuidedSectionHeader ( const UByteArray & section , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
2016-05-05 01:41:03 +08:00
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Get data from parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Obtain header fields
2016-05-05 01:41:03 +08:00
UINT32 headerSize ;
EFI_GUID guid ;
UINT16 dataOffset ;
UINT16 attributes ;
2015-03-13 14:48:53 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( section . constData ( ) ) ;
2016-05-05 01:41:03 +08:00
const EFI_COMMON_SECTION_HEADER2 * section2Header = ( const EFI_COMMON_SECTION_HEADER2 * ) ( section . constData ( ) ) ;
const EFI_COMMON_SECTION_HEADER_APPLE * appleHeader = ( const EFI_COMMON_SECTION_HEADER_APPLE * ) ( section . constData ( ) ) ;
if ( ( UINT32 ) section . size ( ) > = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) & & appleHeader - > Reserved = = EFI_SECTION_APPLE_USED ) { // Check for apple section
const EFI_GUID_DEFINED_SECTION_APPLE * appleSectionHeader = ( const EFI_GUID_DEFINED_SECTION_APPLE * ) ( appleHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) + sizeof ( EFI_GUID_DEFINED_SECTION_APPLE ) ;
if ( ( UINT32 ) section . size ( ) < headerSize )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
guid = appleSectionHeader - > SectionDefinitionGuid ;
dataOffset = appleSectionHeader - > DataOffset ;
attributes = appleSectionHeader - > Attributes ;
2015-03-13 14:48:53 +08:00
}
2016-05-05 01:41:03 +08:00
else if ( pdata . ffsVersion = = 3 & & uint24ToUint32 ( sectionHeader - > Size ) = = EFI_SECTION2_IS_USED ) { // Check for extended header section
const EFI_GUID_DEFINED_SECTION * guidDefinedSectionHeader = ( const EFI_GUID_DEFINED_SECTION * ) ( section2Header + 1 ) ;
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( EFI_GUID_DEFINED_SECTION ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( EFI_GUID_DEFINED_SECTION ) ;
guid = guidDefinedSectionHeader - > SectionDefinitionGuid ;
dataOffset = guidDefinedSectionHeader - > DataOffset ;
attributes = guidDefinedSectionHeader - > Attributes ;
}
else { // Normal section
const EFI_GUID_DEFINED_SECTION * guidDefinedSectionHeader = ( const EFI_GUID_DEFINED_SECTION * ) ( sectionHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER ) + sizeof ( EFI_GUID_DEFINED_SECTION ) ;
guid = guidDefinedSectionHeader - > SectionDefinitionGuid ;
dataOffset = guidDefinedSectionHeader - > DataOffset ;
attributes = guidDefinedSectionHeader - > Attributes ;
}
// Check sanity again
if ( ( UINT32 ) section . size ( ) < headerSize )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-02-09 19:00:14 +08:00
2015-12-12 17:59:38 +08:00
// Check for special GUIDed sections
2016-06-26 16:05:45 +08:00
UString additionalInfo ;
2016-06-26 11:54:21 +08:00
UByteArray baGuid ( ( const char * ) & guid , sizeof ( EFI_GUID ) ) ;
2016-02-09 19:00:14 +08:00
bool msgSignedSectionFound = false ;
2015-12-12 17:59:38 +08:00
bool msgNoAuthStatusAttribute = false ;
bool msgNoProcessingRequiredAttributeCompressed = false ;
bool msgNoProcessingRequiredAttributeSigned = false ;
bool msgInvalidCrc = false ;
bool msgUnknownCertType = false ;
bool msgUnknownCertSubtype = false ;
if ( baGuid = = EFI_GUIDED_SECTION_CRC32 ) {
if ( ( attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID ) = = 0 ) { // Check that AuthStatusValid attribute is set on compressed GUIDed sections
msgNoAuthStatusAttribute = true ;
}
2016-05-05 01:41:03 +08:00
if ( ( UINT32 ) section . size ( ) < headerSize + sizeof ( UINT32 ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
2016-05-05 01:41:03 +08:00
UINT32 crc = * ( UINT32 * ) ( section . constData ( ) + headerSize ) ;
2016-06-26 11:54:21 +08:00
additionalInfo + = UString ( " \n Checksum type: CRC32 " ) ;
2015-12-12 17:59:38 +08:00
// Calculate CRC32 of section data
UINT32 calculated = crc32 ( 0 , ( const UINT8 * ) section . constData ( ) + dataOffset , section . size ( ) - dataOffset ) ;
if ( crc = = calculated ) {
2016-06-26 11:54:21 +08:00
additionalInfo + = usprintf ( " \n Checksum: %08Xh, valid " , crc ) ;
2015-12-12 17:59:38 +08:00
}
else {
2016-06-26 16:05:45 +08:00
additionalInfo + = usprintf ( " \n Checksum: %08Xh, invalid, should be %08Xh " , crc , calculated ) ;
2015-12-12 17:59:38 +08:00
msgInvalidCrc = true ;
}
// No need to change dataOffset here
}
else if ( baGuid = = EFI_GUIDED_SECTION_LZMA | | baGuid = = EFI_GUIDED_SECTION_TIANO ) {
if ( ( attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED ) = = 0 ) { // Check that ProcessingRequired attribute is set on compressed GUIDed sections
msgNoProcessingRequiredAttributeCompressed = true ;
}
// No need to change dataOffset here
}
else if ( baGuid = = EFI_FIRMWARE_CONTENTS_SIGNED_GUID ) {
if ( ( attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED ) = = 0 ) { // Check that ProcessingRequired attribute is set on signed GUIDed sections
msgNoProcessingRequiredAttributeSigned = true ;
}
// Get certificate type and length
2016-05-05 01:41:03 +08:00
if ( ( UINT32 ) section . size ( ) < headerSize + sizeof ( WIN_CERTIFICATE ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
2016-05-05 01:41:03 +08:00
const WIN_CERTIFICATE * winCertificate = ( const WIN_CERTIFICATE * ) ( section . constData ( ) + headerSize ) ;
2015-12-12 17:59:38 +08:00
UINT32 certLength = winCertificate - > Length ;
UINT16 certType = winCertificate - > CertificateType ;
// Adjust dataOffset
dataOffset + = certLength ;
// Check section size once again
if ( ( UINT32 ) section . size ( ) < dataOffset )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
// Check certificate type
if ( certType = = WIN_CERT_TYPE_EFI_GUID ) {
2016-06-26 11:54:21 +08:00
additionalInfo + = UString ( " \n Certificate type: UEFI " ) ;
2015-12-12 17:59:38 +08:00
// Get certificate GUID
2016-05-05 01:41:03 +08:00
const WIN_CERTIFICATE_UEFI_GUID * winCertificateUefiGuid = ( const WIN_CERTIFICATE_UEFI_GUID * ) ( section . constData ( ) + headerSize ) ;
2016-06-26 11:54:21 +08:00
UByteArray certTypeGuid ( ( const char * ) & winCertificateUefiGuid - > CertType , sizeof ( EFI_GUID ) ) ;
2015-12-12 17:59:38 +08:00
if ( certTypeGuid = = EFI_CERT_TYPE_RSA2048_SHA256_GUID ) {
2016-06-26 11:54:21 +08:00
additionalInfo + = UString ( " \n Certificate subtype: RSA2048/SHA256 " ) ;
2015-12-12 17:59:38 +08:00
}
else {
2016-06-26 11:54:21 +08:00
additionalInfo + = UString ( " \n Certificate subtype: unknown, GUID " ) + guidToUString ( winCertificateUefiGuid - > CertType ) ;
2015-12-12 17:59:38 +08:00
msgUnknownCertSubtype = true ;
}
}
else {
2016-06-26 11:54:21 +08:00
additionalInfo + = usprintf ( " \n Certificate type: unknown (%04Xh) " , certType ) ;
2015-12-12 17:59:38 +08:00
msgUnknownCertType = true ;
}
2016-02-09 19:00:14 +08:00
msgSignedSectionFound = true ;
2015-12-12 17:59:38 +08:00
}
2016-06-26 11:54:21 +08:00
UByteArray header = section . left ( dataOffset ) ;
UByteArray body = section . mid ( dataOffset ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name = guidToUString ( guid ) ;
UString info = UString ( " Section GUID: " ) + name +
usprintf ( " \n Type: %02Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Data offset: %Xh \n Attributes: %04Xh " ,
sectionHeader - > Type ,
section . size ( ) , section . size ( ) ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
dataOffset ,
attributes ) ;
2015-03-13 14:48:53 +08:00
2015-12-12 17:59:38 +08:00
// Append additional info
2016-06-26 16:05:45 +08:00
info + = additionalInfo ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
pdata . section . guidDefined . guid = guid ;
// Add tree item
2016-07-16 13:02:33 +08:00
if ( insertIntoTree ) {
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Section , sectionHeader - > Type , name , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-02-09 19:00:14 +08:00
// Show messages
if ( msgSignedSectionFound )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionHeader: section signature may become invalid after any modification " ) , index ) ;
2016-02-09 19:00:14 +08:00
if ( msgNoAuthStatusAttribute )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionHeader: CRC32 GUIDed section without AuthStatusValid attribute " ) , index ) ;
2016-02-09 19:00:14 +08:00
if ( msgNoProcessingRequiredAttributeCompressed )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionHeader: compressed GUIDed section without ProcessingRequired attribute " ) , index ) ;
2016-02-09 19:00:14 +08:00
if ( msgNoProcessingRequiredAttributeSigned )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionHeader: signed GUIDed section without ProcessingRequired attribute " ) , index ) ;
2016-02-09 19:00:14 +08:00
if ( msgInvalidCrc )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionHeader: GUID defined section with invalid CRC32 " ) , index ) ;
2016-02-09 19:00:14 +08:00
if ( msgUnknownCertType )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionHeader: signed GUIDed section with unknown type " ) , index ) ;
2016-02-09 19:00:14 +08:00
if ( msgUnknownCertSubtype )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionHeader: signed GUIDed section with unknown subtype " ) , index ) ;
2016-02-09 19:00:14 +08:00
}
2015-12-12 17:59:38 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parseFreeformGuidedSectionHeader ( const UByteArray & section , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
2016-05-05 01:41:03 +08:00
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Get data from parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Obtain header fields
2016-05-05 01:41:03 +08:00
UINT32 headerSize ;
EFI_GUID guid ;
UINT8 type ;
2015-03-13 14:48:53 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( section . constData ( ) ) ;
2016-05-05 01:41:03 +08:00
const EFI_COMMON_SECTION_HEADER2 * section2Header = ( const EFI_COMMON_SECTION_HEADER2 * ) ( section . constData ( ) ) ;
const EFI_COMMON_SECTION_HEADER_APPLE * appleHeader = ( const EFI_COMMON_SECTION_HEADER_APPLE * ) ( section . constData ( ) ) ;
if ( ( UINT32 ) section . size ( ) > = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) & & appleHeader - > Reserved = = EFI_SECTION_APPLE_USED ) { // Check for apple section
const EFI_FREEFORM_SUBTYPE_GUID_SECTION * appleSectionHeader = ( const EFI_FREEFORM_SUBTYPE_GUID_SECTION * ) ( appleHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) + sizeof ( EFI_FREEFORM_SUBTYPE_GUID_SECTION ) ;
guid = appleSectionHeader - > SubTypeGuid ;
type = appleHeader - > Type ;
}
else if ( pdata . ffsVersion = = 3 & & uint24ToUint32 ( sectionHeader - > Size ) = = EFI_SECTION2_IS_USED ) { // Check for extended header section
const EFI_FREEFORM_SUBTYPE_GUID_SECTION * fsgSectionHeader = ( const EFI_FREEFORM_SUBTYPE_GUID_SECTION * ) ( section2Header + 1 ) ;
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( EFI_FREEFORM_SUBTYPE_GUID_SECTION ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( EFI_FREEFORM_SUBTYPE_GUID_SECTION ) ;
guid = fsgSectionHeader - > SubTypeGuid ;
type = section2Header - > Type ;
}
else { // Normal section
const EFI_FREEFORM_SUBTYPE_GUID_SECTION * fsgSectionHeader = ( const EFI_FREEFORM_SUBTYPE_GUID_SECTION * ) ( sectionHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER ) + sizeof ( EFI_FREEFORM_SUBTYPE_GUID_SECTION ) ;
guid = fsgSectionHeader - > SubTypeGuid ;
type = sectionHeader - > Type ;
2015-03-13 14:48:53 +08:00
}
2016-05-05 01:41:03 +08:00
// Check sanity again
if ( ( UINT32 ) section . size ( ) < headerSize )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-05-05 01:41:03 +08:00
2016-06-26 11:54:21 +08:00
UByteArray header = section . left ( headerSize ) ;
UByteArray body = section . mid ( headerSize ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name = sectionTypeToUString ( type ) + ( " section " ) ;
UString info = usprintf ( " Type: %02Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Subtype GUID: " ,
type ,
section . size ( ) , section . size ( ) ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) )
+ guidToUString ( guid ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
pdata . section . freeformSubtypeGuid . guid = guid ;
// Add tree item
2016-07-16 13:02:33 +08:00
if ( insertIntoTree ) {
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Section , type , name , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , parent ) ;
2015-03-13 14:48:53 +08:00
2016-02-09 19:00:14 +08:00
// Rename section
2016-06-26 11:54:21 +08:00
model - > setName ( index , guidToUString ( guid ) ) ;
2016-02-09 19:00:14 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parseVersionSectionHeader ( const UByteArray & section , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
2016-05-05 01:41:03 +08:00
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Get data from parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Obtain header fields
2016-05-05 01:41:03 +08:00
UINT32 headerSize ;
UINT16 buildNumber ;
UINT8 type ;
2015-03-13 14:48:53 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( section . constData ( ) ) ;
2016-05-05 01:41:03 +08:00
const EFI_COMMON_SECTION_HEADER2 * section2Header = ( const EFI_COMMON_SECTION_HEADER2 * ) ( section . constData ( ) ) ;
const EFI_COMMON_SECTION_HEADER_APPLE * appleHeader = ( const EFI_COMMON_SECTION_HEADER_APPLE * ) ( section . constData ( ) ) ;
if ( ( UINT32 ) section . size ( ) > = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) & & appleHeader - > Reserved = = EFI_SECTION_APPLE_USED ) { // Check for apple section
const EFI_VERSION_SECTION * versionHeader = ( const EFI_VERSION_SECTION * ) ( appleHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) + sizeof ( EFI_VERSION_SECTION ) ;
buildNumber = versionHeader - > BuildNumber ;
type = appleHeader - > Type ;
}
else if ( pdata . ffsVersion = = 3 & & uint24ToUint32 ( sectionHeader - > Size ) = = EFI_SECTION2_IS_USED ) { // Check for extended header section
const EFI_VERSION_SECTION * versionHeader = ( const EFI_VERSION_SECTION * ) ( section2Header + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( EFI_VERSION_SECTION ) ;
buildNumber = versionHeader - > BuildNumber ;
type = section2Header - > Type ;
}
else { // Normal section
const EFI_VERSION_SECTION * versionHeader = ( const EFI_VERSION_SECTION * ) ( sectionHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER ) + sizeof ( EFI_VERSION_SECTION ) ;
buildNumber = versionHeader - > BuildNumber ;
type = sectionHeader - > Type ;
}
// Check sanity again
if ( ( UINT32 ) section . size ( ) < headerSize )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
UByteArray header = section . left ( headerSize ) ;
UByteArray body = section . mid ( headerSize ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name = sectionTypeToUString ( type ) + ( " section " ) ;
2016-06-26 16:05:45 +08:00
UString info = usprintf ( " Type: %02Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Build number: %u " ,
2016-06-26 11:54:21 +08:00
type ,
section . size ( ) , section . size ( ) ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
buildNumber ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-07-16 13:02:33 +08:00
if ( insertIntoTree ) {
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Section , type , name , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-02-09 19:00:14 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
USTATUS FfsParser : : parsePostcodeSectionHeader ( const UByteArray & section , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index , const bool insertIntoTree )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
2016-05-05 01:41:03 +08:00
if ( ( UINT32 ) section . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-12-12 17:59:38 +08:00
2015-03-13 14:48:53 +08:00
// Get data from parent's parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2015-03-13 14:48:53 +08:00
// Obtain header fields
2016-05-05 01:41:03 +08:00
UINT32 headerSize ;
UINT32 postCode ;
UINT8 type ;
2015-03-13 14:48:53 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( section . constData ( ) ) ;
2016-05-05 01:41:03 +08:00
const EFI_COMMON_SECTION_HEADER2 * section2Header = ( const EFI_COMMON_SECTION_HEADER2 * ) ( section . constData ( ) ) ;
const EFI_COMMON_SECTION_HEADER_APPLE * appleHeader = ( const EFI_COMMON_SECTION_HEADER_APPLE * ) ( section . constData ( ) ) ;
if ( ( UINT32 ) section . size ( ) > = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) & & appleHeader - > Reserved = = EFI_SECTION_APPLE_USED ) { // Check for apple section
const POSTCODE_SECTION * postcodeHeader = ( const POSTCODE_SECTION * ) ( appleHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER_APPLE ) + sizeof ( POSTCODE_SECTION ) ;
postCode = postcodeHeader - > Postcode ;
type = appleHeader - > Type ;
}
else if ( pdata . ffsVersion = = 3 & & uint24ToUint32 ( sectionHeader - > Size ) = = EFI_SECTION2_IS_USED ) { // Check for extended header section
const POSTCODE_SECTION * postcodeHeader = ( const POSTCODE_SECTION * ) ( section2Header + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER2 ) + sizeof ( POSTCODE_SECTION ) ;
postCode = postcodeHeader - > Postcode ;
type = section2Header - > Type ;
}
else { // Normal section
const POSTCODE_SECTION * postcodeHeader = ( const POSTCODE_SECTION * ) ( sectionHeader + 1 ) ;
headerSize = sizeof ( EFI_COMMON_SECTION_HEADER ) + sizeof ( POSTCODE_SECTION ) ;
postCode = postcodeHeader - > Postcode ;
type = sectionHeader - > Type ;
}
// Check sanity again
if ( ( UINT32 ) section . size ( ) < headerSize )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
UByteArray header = section . left ( headerSize ) ;
UByteArray body = section . mid ( headerSize ) ;
2015-03-13 14:48:53 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UString name = sectionTypeToUString ( type ) + ( " section " ) ;
2016-06-26 16:05:45 +08:00
UString info = usprintf ( " Type: %02Xh \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n Postcode: %Xh " ,
type ,
2016-06-26 11:54:21 +08:00
section . size ( ) , section . size ( ) ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
postCode ) ;
2015-03-13 14:48:53 +08:00
// Construct parsing data
pdata . offset + = parentOffset ;
// Add tree item
2016-07-16 13:02:33 +08:00
if ( insertIntoTree ) {
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Section , sectionHeader - > Type , name , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-02-09 19:00:14 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
UByteArray header = model - > header ( index ) ;
2016-03-21 18:00:10 +08:00
if ( ( UINT32 ) header . size ( ) < sizeof ( EFI_COMMON_SECTION_HEADER ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_SECTION ;
2016-03-21 06:59:03 +08:00
const EFI_COMMON_SECTION_HEADER * sectionHeader = ( const EFI_COMMON_SECTION_HEADER * ) ( header . constData ( ) ) ;
2015-03-13 14:48:53 +08:00
switch ( sectionHeader - > Type ) {
// Encapsulation
case EFI_SECTION_COMPRESSION : return parseCompressedSectionBody ( index ) ;
case EFI_SECTION_GUID_DEFINED : return parseGuidedSectionBody ( index ) ;
2016-07-16 13:02:33 +08:00
case EFI_SECTION_DISPOSABLE : return parseSections ( model - > body ( index ) , index , true ) ;
2015-03-13 14:48:53 +08:00
// Leaf
2016-04-17 07:25:44 +08:00
case EFI_SECTION_FREEFORM_SUBTYPE_GUID : return parseRawArea ( index ) ;
2015-03-13 14:48:53 +08:00
case EFI_SECTION_VERSION : return parseVersionSectionBody ( index ) ;
case EFI_SECTION_DXE_DEPEX :
case EFI_SECTION_PEI_DEPEX :
case EFI_SECTION_SMM_DEPEX : return parseDepexSectionBody ( index ) ;
2015-06-20 02:26:45 +08:00
case EFI_SECTION_TE : return parseTeImageSectionBody ( index ) ;
2015-03-13 14:48:53 +08:00
case EFI_SECTION_PE32 :
2015-06-20 02:26:45 +08:00
case EFI_SECTION_PIC : return parsePeImageSectionBody ( index ) ;
2015-03-13 14:48:53 +08:00
case EFI_SECTION_USER_INTERFACE : return parseUiSectionBody ( index ) ;
2016-04-17 07:25:44 +08:00
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE : return parseRawArea ( index ) ;
2015-03-13 14:48:53 +08:00
case EFI_SECTION_RAW : return parseRawSectionBody ( index ) ;
// No parsing needed
case EFI_SECTION_COMPATIBILITY16 :
2016-03-21 06:59:03 +08:00
case PHOENIX_SECTION_POSTCODE :
2015-03-13 14:48:53 +08:00
case INSYDE_SECTION_POSTCODE :
default :
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseCompressedSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Get data from parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-03-13 14:48:53 +08:00
UINT8 algorithm = pdata . section . compressed . compressionType ;
// Decompress section
2016-06-26 11:54:21 +08:00
UByteArray decompressed ;
UByteArray efiDecompressed ;
USTATUS result = decompress ( model - > body ( index ) , algorithm , decompressed , efiDecompressed ) ;
2015-03-13 14:48:53 +08:00
if ( result ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseCompressedSectionBody: decompression failed with error " ) + errorCodeToUString ( result ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
// Check reported uncompressed size
2015-04-04 21:22:52 +08:00
if ( pdata . section . compressed . uncompressedSize ! = ( UINT32 ) decompressed . size ( ) ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseCompressedSectionBody: decompressed size stored in header %Xh (%u) differs from actual %Xh (%u) " ,
pdata . section . compressed . uncompressedSize ,
pdata . section . compressed . uncompressedSize ,
decompressed . size ( ) ,
decompressed . size ( ) ) , index ) ;
model - > addInfo ( index , usprintf ( " \n Actual decompressed size: %Xh (%u) " , decompressed . size ( ) , decompressed . size ( ) ) ) ;
2015-03-13 14:48:53 +08:00
}
2016-02-02 09:08:08 +08:00
// Check for undecided compression algorithm, this is a special case
if ( algorithm = = COMPRESSION_ALGORITHM_UNDECIDED ) {
// Try preparse of sections decompressed with Tiano algorithm
2016-07-16 13:02:33 +08:00
if ( U_SUCCESS = = parseSections ( decompressed , index , false ) ) {
2016-02-02 09:08:08 +08:00
algorithm = COMPRESSION_ALGORITHM_TIANO ;
}
// Try preparse of sections decompressed with EFI 1.1 algorithm
2016-07-16 13:02:33 +08:00
else if ( U_SUCCESS = = parseSections ( efiDecompressed , index , false ) ) {
2016-02-02 09:08:08 +08:00
algorithm = COMPRESSION_ALGORITHM_EFI11 ;
decompressed = efiDecompressed ;
}
else {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseCompressedSectionBody: can't guess the correct decompression algorithm, both preparse steps are failed " ) , index ) ;
2016-02-02 09:08:08 +08:00
}
}
2015-03-13 14:48:53 +08:00
// Add info
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , UString ( " \n Compression algorithm: " ) + compressionTypeToUString ( algorithm ) ) ;
2015-03-13 14:48:53 +08:00
2015-12-30 06:39:43 +08:00
// Update data
2015-03-13 14:48:53 +08:00
pdata . section . compressed . algorithm = algorithm ;
2015-12-30 06:39:43 +08:00
if ( algorithm ! = COMPRESSION_ALGORITHM_NONE )
model - > setCompressed ( index , true ) ;
2016-06-26 11:54:21 +08:00
model - > setParsingData ( index , parsingDataToUByteArray ( pdata ) ) ;
2015-12-30 06:39:43 +08:00
2015-03-13 14:48:53 +08:00
// Parse decompressed data
2016-07-16 13:02:33 +08:00
return parseSections ( decompressed , index , true ) ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseGuidedSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Get data from parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-03-13 14:48:53 +08:00
EFI_GUID guid = pdata . section . guidDefined . guid ;
// Check if section requires processing
2016-06-26 11:54:21 +08:00
UByteArray processed = model - > body ( index ) ;
UByteArray efiDecompressed ;
UString info ;
2015-03-13 14:48:53 +08:00
bool parseCurrentSection = true ;
UINT8 algorithm = COMPRESSION_ALGORITHM_NONE ;
2015-12-12 17:59:38 +08:00
// Tiano compressed section
2016-06-26 11:54:21 +08:00
if ( UByteArray ( ( const char * ) & guid , sizeof ( EFI_GUID ) ) = = EFI_GUIDED_SECTION_TIANO ) {
2015-12-12 17:59:38 +08:00
algorithm = EFI_STANDARD_COMPRESSION ;
2016-06-26 11:54:21 +08:00
USTATUS result = decompress ( model - > body ( index ) , algorithm , processed , efiDecompressed ) ;
2015-12-12 17:59:38 +08:00
if ( result ) {
parseCurrentSection = false ;
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionBody: decompression failed with error " ) + errorCodeToUString ( result ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-02-02 09:08:08 +08:00
// Check for undecided compression algorithm, this is a special case
if ( algorithm = = COMPRESSION_ALGORITHM_UNDECIDED ) {
// Try preparse of sections decompressed with Tiano algorithm
2016-07-16 13:02:33 +08:00
if ( U_SUCCESS = = parseSections ( processed , index , false ) ) {
2016-02-02 09:08:08 +08:00
algorithm = COMPRESSION_ALGORITHM_TIANO ;
}
// Try preparse of sections decompressed with EFI 1.1 algorithm
2016-07-16 13:02:33 +08:00
else if ( U_SUCCESS = = parseSections ( efiDecompressed , index , false ) ) {
2016-02-02 09:08:08 +08:00
algorithm = COMPRESSION_ALGORITHM_EFI11 ;
processed = efiDecompressed ;
}
else {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionBody: can't guess the correct decompression algorithm, both preparse steps are failed " ) , index ) ;
2016-04-18 22:44:49 +08:00
parseCurrentSection = false ;
2016-02-02 09:08:08 +08:00
}
2015-07-12 14:15:03 +08:00
}
2016-02-02 09:08:08 +08:00
2016-06-26 11:54:21 +08:00
info + = UString ( " \n Compression algorithm: " ) + compressionTypeToUString ( algorithm ) ;
2016-07-05 23:22:03 +08:00
info + = usprintf ( " \n Decompressed size: %Xh (%u) " , processed . size ( ) , processed . size ( ) ) ;
2015-12-12 17:59:38 +08:00
}
// LZMA compressed section
2016-06-26 11:54:21 +08:00
else if ( UByteArray ( ( const char * ) & guid , sizeof ( EFI_GUID ) ) = = EFI_GUIDED_SECTION_LZMA ) {
2015-12-12 17:59:38 +08:00
algorithm = EFI_CUSTOMIZED_COMPRESSION ;
2016-06-26 11:54:21 +08:00
USTATUS result = decompress ( model - > body ( index ) , algorithm , processed , efiDecompressed ) ;
2015-12-12 17:59:38 +08:00
if ( result ) {
2015-03-13 14:48:53 +08:00
parseCurrentSection = false ;
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionBody: decompression failed with error " ) + errorCodeToUString ( result ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2015-12-12 17:59:38 +08:00
if ( algorithm = = COMPRESSION_ALGORITHM_LZMA ) {
2016-06-26 11:54:21 +08:00
info + = UString ( " \n Compression algorithm: LZMA " ) ;
2016-07-05 23:22:03 +08:00
info + = usprintf ( " \n Decompressed size: %Xh (%u) " , processed . size ( ) , processed . size ( ) ) ;
2015-03-13 14:48:53 +08:00
}
2016-04-18 22:44:49 +08:00
else {
2016-06-26 11:54:21 +08:00
info + = UString ( " \n Compression algorithm: unknown " ) ;
2016-04-18 22:44:49 +08:00
parseCurrentSection = false ;
}
2015-03-13 14:48:53 +08:00
}
// Add info
model - > addInfo ( index , info ) ;
2015-12-30 06:39:43 +08:00
// Update data
if ( algorithm ! = COMPRESSION_ALGORITHM_NONE )
model - > setCompressed ( index , true ) ;
2016-06-26 11:54:21 +08:00
model - > setParsingData ( index , parsingDataToUByteArray ( pdata ) ) ;
2015-03-13 14:48:53 +08:00
if ( ! parseCurrentSection ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseGuidedSectionBody: GUID defined section can not be processed " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-07-16 13:02:33 +08:00
return parseSections ( processed , index , true ) ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseVersionSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Add info
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , UString ( " \n Version string: " ) + UString : : fromUtf16 ( ( const CHAR16 * ) model - > body ( index ) . constData ( ) ) ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseDepexSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
UByteArray body = model - > body ( index ) ;
UString parsed ;
2015-03-13 14:48:53 +08:00
// Check data to be present
2015-12-12 17:59:38 +08:00
if ( body . size ( ) < 2 ) { // 2 is a minimal sane value, i.e TRUE + END
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: DEPEX section too short " ) , index ) ;
return U_DEPEX_PARSE_FAILED ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
const EFI_GUID * guid ;
const UINT8 * current = ( const UINT8 * ) body . constData ( ) ;
// Special cases of first opcode
switch ( * current ) {
case EFI_DEP_BEFORE :
if ( body . size ( ) ! = 2 * EFI_DEP_OPCODE_SIZE + sizeof ( EFI_GUID ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: DEPEX section too long for a section starting with BEFORE opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
guid = ( const EFI_GUID * ) ( current + EFI_DEP_OPCODE_SIZE ) ;
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n BEFORE " ) + guidToUString ( * guid ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE + sizeof ( EFI_GUID ) ;
if ( * current ! = EFI_DEP_END ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: DEPEX section ends with non-END opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
case EFI_DEP_AFTER :
if ( body . size ( ) ! = 2 * EFI_DEP_OPCODE_SIZE + sizeof ( EFI_GUID ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: DEPEX section too long for a section starting with AFTER opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
guid = ( const EFI_GUID * ) ( current + EFI_DEP_OPCODE_SIZE ) ;
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n AFTER " ) + guidToUString ( * guid ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE + sizeof ( EFI_GUID ) ;
if ( * current ! = EFI_DEP_END ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: DEPEX section ends with non-END opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
case EFI_DEP_SOR :
if ( body . size ( ) < = 2 * EFI_DEP_OPCODE_SIZE ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: DEPEX section too short for a section starting with SOR opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n SOR " ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE ;
break ;
}
// Parse the rest of depex
while ( current - ( const UINT8 * ) body . constData ( ) < body . size ( ) ) {
switch ( * current ) {
case EFI_DEP_BEFORE : {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: misplaced BEFORE opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
case EFI_DEP_AFTER : {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: misplaced AFTER opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
case EFI_DEP_SOR : {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: misplaced SOR opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
case EFI_DEP_PUSH :
// Check that the rest of depex has correct size
if ( ( UINT32 ) body . size ( ) - ( UINT32 ) ( current - ( const UINT8 * ) body . constData ( ) ) < = EFI_DEP_OPCODE_SIZE + sizeof ( EFI_GUID ) ) {
parsed . clear ( ) ;
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: remains of DEPEX section too short for PUSH opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
guid = ( const EFI_GUID * ) ( current + EFI_DEP_OPCODE_SIZE ) ;
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n PUSH " ) + guidToUString ( * guid ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE + sizeof ( EFI_GUID ) ;
break ;
case EFI_DEP_AND :
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n AND " ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE ;
break ;
case EFI_DEP_OR :
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n OR " ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE ;
break ;
case EFI_DEP_NOT :
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n NOT " ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE ;
break ;
case EFI_DEP_TRUE :
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n TRUE " ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE ;
break ;
case EFI_DEP_FALSE :
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n FALSE " ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE ;
break ;
case EFI_DEP_END :
2016-06-26 11:54:21 +08:00
parsed + = UString ( " \n END " ) ;
2015-03-13 14:48:53 +08:00
current + = EFI_DEP_OPCODE_SIZE ;
// Check that END is the last opcode
if ( current - ( const UINT8 * ) body . constData ( ) < body . size ( ) ) {
parsed . clear ( ) ;
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: DEPEX section ends with non-END opcode " ) , index ) ;
2015-03-13 14:48:53 +08:00
}
break ;
default :
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseDepexSectionBody: unknown opcode " ) , index ) ;
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
break ;
}
}
// Add info
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , UString ( " \n Parsed expression: " ) + parsed ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseUiSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
UString text = UString : : fromUtf16 ( ( const CHAR16 * ) model - > body ( index ) . constData ( ) ) ;
2015-03-13 14:48:53 +08:00
// Add info
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , UString ( " \n Text: " ) + text ) ;
2015-03-13 14:48:53 +08:00
// Rename parent file
model - > setText ( model - > findParentOfType ( index , Types : : File ) , text ) ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseAprioriRawSection ( const UByteArray & body , UString & parsed )
2015-04-02 16:04:37 +08:00
{
2015-12-12 17:59:38 +08:00
// Sanity check
if ( body . size ( ) % sizeof ( EFI_GUID ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseAprioriRawSection: apriori file has size is not a multiple of 16 " ) ) ;
2015-12-12 17:59:38 +08:00
}
2015-04-02 16:04:37 +08:00
parsed . clear ( ) ;
UINT32 count = body . size ( ) / sizeof ( EFI_GUID ) ;
if ( count > 0 ) {
for ( UINT32 i = 0 ; i < count ; i + + ) {
const EFI_GUID * guid = ( const EFI_GUID * ) body . constData ( ) + i ;
2016-06-26 16:05:45 +08:00
parsed + = UString ( " \n " ) + guidToUString ( * guid ) ;
2015-04-02 16:04:37 +08:00
}
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-04-02 16:04:37 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseRawSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
// Check for apriori file
2016-06-26 11:54:21 +08:00
UModelIndex parentFile = model - > findParentOfType ( index , Types : : File ) ;
2016-04-21 04:41:18 +08:00
// Get parent file parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parentFile ) ;
UByteArray parentFileGuid ( ( const char * ) & pdata . file . guid , sizeof ( EFI_GUID ) ) ;
2016-04-21 04:41:18 +08:00
2015-03-13 14:48:53 +08:00
if ( parentFileGuid = = EFI_PEI_APRIORI_FILE_GUID ) { // PEI apriori file
// Parse apriori file list
2016-06-26 11:54:21 +08:00
UString str ;
USTATUS result = parseAprioriRawSection ( model - > body ( index ) , str ) ;
2015-03-13 14:48:53 +08:00
if ( ! result & & ! str . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , UString ( " \n File list: " ) + str ) ;
2015-03-13 14:48:53 +08:00
// Set parent file text
2016-06-26 11:54:21 +08:00
model - > setText ( parentFile , UString ( " PEI apriori file " ) ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
else if ( parentFileGuid = = EFI_DXE_APRIORI_FILE_GUID ) { // DXE apriori file
// Parse apriori file list
2016-06-26 11:54:21 +08:00
UString str ;
USTATUS result = parseAprioriRawSection ( model - > body ( index ) , str ) ;
2015-03-13 14:48:53 +08:00
if ( ! result & & ! str . isEmpty ( ) )
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , UString ( " \n File list: " ) + str ) ;
2015-03-13 14:48:53 +08:00
// Set parent file text
2016-06-26 11:54:21 +08:00
model - > setText ( parentFile , UString ( " DXE apriori file " ) ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-04-21 04:41:18 +08:00
else if ( parentFileGuid = = NVRAM_NVAR_EXTERNAL_DEFAULTS_FILE_GUID ) {
// Parse NVAR area
parseNvarStore ( index ) ;
// Set parent file text
2016-06-26 11:54:21 +08:00
model - > setText ( parentFile , UString ( " NVRAM external defaults " ) ) ;
2016-04-21 04:41:18 +08:00
}
2015-03-13 14:48:53 +08:00
// Parse as raw area
2016-04-17 07:25:44 +08:00
return parseRawArea ( index ) ;
2015-03-13 14:48:53 +08:00
}
2015-06-20 02:26:45 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parsePeImageSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
2015-06-20 02:26:45 +08:00
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
2015-06-20 02:26:45 +08:00
// Get section body
2016-06-26 11:54:21 +08:00
UByteArray body = model - > body ( index ) ;
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) body . size ( ) < sizeof ( EFI_IMAGE_DOS_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parsePeImageSectionBody: section body size is smaller than DOS header size " ) , index ) ;
return U_SUCCESS ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
2016-06-26 16:05:45 +08:00
UString info ;
2015-03-13 14:48:53 +08:00
const EFI_IMAGE_DOS_HEADER * dosHeader = ( const EFI_IMAGE_DOS_HEADER * ) body . constData ( ) ;
if ( dosHeader - > e_magic ! = EFI_IMAGE_DOS_SIGNATURE ) {
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n DOS signature: %04Xh, invalid " , dosHeader - > e_magic ) ;
msg ( UString ( " parsePeImageSectionBody: PE32 image with invalid DOS signature " ) , index ) ;
2015-12-12 17:59:38 +08:00
model - > addInfo ( index , info ) ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-12-12 17:59:38 +08:00
}
const EFI_IMAGE_PE_HEADER * peHeader = ( EFI_IMAGE_PE_HEADER * ) ( body . constData ( ) + dosHeader - > e_lfanew ) ;
if ( body . size ( ) < ( UINT8 * ) peHeader - ( UINT8 * ) dosHeader ) {
2016-06-26 11:54:21 +08:00
info + = UString ( " \n DOS header: invalid " ) ;
msg ( UString ( " parsePeImageSectionBody: PE32 image with invalid DOS header " ) , index ) ;
2015-12-12 17:59:38 +08:00
model - > addInfo ( index , info ) ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-12-12 17:59:38 +08:00
}
if ( peHeader - > Signature ! = EFI_IMAGE_PE_SIGNATURE ) {
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n PE signature: %08Xh, invalid " , peHeader - > Signature ) ;
msg ( UString ( " parsePeImageSectionBody: PE32 image with invalid PE signature " ) , index ) ;
2015-12-12 17:59:38 +08:00
model - > addInfo ( index , info ) ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-12-12 17:59:38 +08:00
}
const EFI_IMAGE_FILE_HEADER * imageFileHeader = ( const EFI_IMAGE_FILE_HEADER * ) ( peHeader + 1 ) ;
if ( body . size ( ) < ( UINT8 * ) imageFileHeader - ( UINT8 * ) dosHeader ) {
2016-06-26 11:54:21 +08:00
info + = UString ( " \n PE header: invalid " ) ;
msg ( UString ( " parsePeImageSectionBody: PE32 image with invalid PE header " ) , index ) ;
2015-12-12 17:59:38 +08:00
model - > addInfo ( index , info ) ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-12-12 17:59:38 +08:00
}
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n DOS signature: %04Xh \n PE signature: %08Xh " ,
dosHeader - > e_magic ,
peHeader - > Signature ) +
2016-06-26 16:05:45 +08:00
UString ( " \n Machine type: " ) + machineTypeToUString ( imageFileHeader - > Machine ) +
2016-06-26 11:54:21 +08:00
usprintf ( " \n Number of sections: %u \n Characteristics: %04Xh " ,
imageFileHeader - > NumberOfSections ,
imageFileHeader - > Characteristics ) ;
2015-12-12 17:59:38 +08:00
EFI_IMAGE_OPTIONAL_HEADER_POINTERS_UNION optionalHeader ;
optionalHeader . H32 = ( const EFI_IMAGE_OPTIONAL_HEADER32 * ) ( imageFileHeader + 1 ) ;
if ( body . size ( ) < ( UINT8 * ) optionalHeader . H32 - ( UINT8 * ) dosHeader ) {
2016-06-26 11:54:21 +08:00
info + = UString ( " \n PE optional header: invalid " ) ;
msg ( UString ( " parsePeImageSectionBody: PE32 image with invalid PE optional header " ) , index ) ;
2015-12-12 17:59:38 +08:00
model - > addInfo ( index , info ) ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-12-12 17:59:38 +08:00
}
if ( optionalHeader . H32 - > Magic = = EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC ) {
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Optional header signature: %04Xh \n Subsystem: %04Xh \n Address of entry point: %Xh \n Base of code: %Xh \n Image base: %Xh " ,
optionalHeader . H32 - > Magic ,
optionalHeader . H32 - > Subsystem ,
optionalHeader . H32 - > AddressOfEntryPoint ,
optionalHeader . H32 - > BaseOfCode ,
optionalHeader . H32 - > ImageBase ) ;
2015-12-12 17:59:38 +08:00
}
else if ( optionalHeader . H32 - > Magic = = EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC ) {
2016-07-09 16:08:32 +08:00
info + = usprintf ( " \n Optional header signature: %04Xh \n Subsystem: %04Xh \n Address of entry point: %Xh \n Base of code: %Xh \n Image base: % " PRIX64 " h " ,
2016-06-26 11:54:21 +08:00
optionalHeader . H64 - > Magic ,
optionalHeader . H64 - > Subsystem ,
optionalHeader . H64 - > AddressOfEntryPoint ,
optionalHeader . H64 - > BaseOfCode ,
optionalHeader . H64 - > ImageBase ) ;
2015-03-13 14:48:53 +08:00
}
else {
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Optional header signature: %04Xh, unknown " , optionalHeader . H32 - > Magic ) ;
msg ( UString ( " parsePeImageSectionBody: PE32 image with invalid optional PE header signature " ) , index ) ;
2015-03-13 14:48:53 +08:00
}
2015-06-20 02:26:45 +08:00
model - > addInfo ( index , info ) ;
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2015-06-20 02:26:45 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseTeImageSectionBody ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
2015-12-12 17:59:38 +08:00
// Check sanity
2015-06-20 02:26:45 +08:00
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
2015-06-20 02:26:45 +08:00
// Get section body
2016-06-26 11:54:21 +08:00
UByteArray body = model - > body ( index ) ;
2015-12-12 17:59:38 +08:00
if ( ( UINT32 ) body . size ( ) < sizeof ( EFI_IMAGE_TE_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( ( " parsePeImageSectionBody: section body size is smaller than TE header size " ) , index ) ;
return U_SUCCESS ;
2015-12-12 17:59:38 +08:00
}
2015-03-13 14:48:53 +08:00
2016-06-26 16:05:45 +08:00
UString info ;
2015-03-13 14:48:53 +08:00
const EFI_IMAGE_TE_HEADER * teHeader = ( const EFI_IMAGE_TE_HEADER * ) body . constData ( ) ;
if ( teHeader - > Signature ! = EFI_IMAGE_TE_SIGNATURE ) {
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Signature: %04Xh, invalid " , teHeader - > Signature ) ;
msg ( UString ( " parseTeImageSectionBody: TE image with invalid TE signature " ) , index ) ;
2015-03-13 14:48:53 +08:00
}
else {
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Signature: %04Xh " , teHeader - > Signature ) +
2016-06-26 16:05:45 +08:00
UString ( " \n Machine type: " ) + machineTypeToUString ( teHeader - > Machine ) +
2016-06-26 11:54:21 +08:00
usprintf ( " \n Number of sections: %u \n Subsystem: %02Xh \n Stripped size: %Xh (%u) \n "
2016-07-09 16:08:32 +08:00
" Base of code: %Xh \n Address of entry point: %Xh \n Image base: % " PRIX64 " h \n Adjusted image base: % " PRIX64 " h " ,
2016-06-26 11:54:21 +08:00
teHeader - > NumberOfSections ,
2016-07-15 03:22:51 +08:00
teHeader - > Subsystem ,
2016-06-26 11:54:21 +08:00
teHeader - > StrippedSize , teHeader - > StrippedSize ,
teHeader - > BaseOfCode ,
teHeader - > AddressOfEntryPoint ,
teHeader - > ImageBase ,
teHeader - > ImageBase + teHeader - > StrippedSize - sizeof ( EFI_IMAGE_TE_HEADER ) ) ;
2015-03-13 14:48:53 +08:00
}
2015-06-20 02:26:45 +08:00
// Get data from parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-07-06 00:19:04 +08:00
pdata . section . teImage . imageBase = ( UINT32 ) teHeader - > ImageBase ;
pdata . section . teImage . adjustedImageBase = ( UINT32 ) ( teHeader - > ImageBase + teHeader - > StrippedSize - sizeof ( EFI_IMAGE_TE_HEADER ) ) ;
2015-06-20 02:26:45 +08:00
// Update parsing data
2016-06-26 11:54:21 +08:00
model - > setParsingData ( index , parsingDataToUByteArray ( pdata ) ) ;
2015-06-20 02:26:45 +08:00
// Add TE info
model - > addInfo ( index , info ) ;
2015-03-13 14:48:53 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2015-06-20 02:26:45 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : performSecondPass ( const UModelIndex & index )
2015-03-13 14:48:53 +08:00
{
2015-06-20 02:26:45 +08:00
// Sanity check
if ( ! index . isValid ( ) | | ! lastVtf . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2015-03-13 14:48:53 +08:00
2015-12-30 06:39:43 +08:00
// Check for compressed lastVtf
if ( model - > compressed ( lastVtf ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " performSecondPass: the last VTF appears inside compressed item, the image may be damaged " ) , lastVtf ) ;
return U_SUCCESS ;
2015-06-20 02:26:45 +08:00
}
2016-07-15 03:22:51 +08:00
2015-12-30 06:39:43 +08:00
// Get parsing data for the last VTF
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( lastVtf ) ;
2015-12-30 06:39:43 +08:00
2015-06-20 02:26:45 +08:00
// Calculate address difference
2016-04-21 04:41:18 +08:00
const UINT32 vtfSize = model - > header ( lastVtf ) . size ( ) + model - > body ( lastVtf ) . size ( ) + model - > tail ( lastVtf ) . size ( ) ;
2015-07-07 21:57:41 +08:00
const UINT32 diff = 0xFFFFFFFFUL - pdata . offset - vtfSize + 1 ;
2015-03-13 14:48:53 +08:00
2016-07-15 03:22:51 +08:00
// Find and parse FIT
parseFit ( index , diff ) ;
2015-06-20 02:26:45 +08:00
// Apply address information to index and all it's child items
2015-07-05 12:20:03 +08:00
addMemoryAddressesRecursive ( index , diff ) ;
2016-07-15 03:22:51 +08:00
// Add fixed and compressed
addFixedAndCompressedRecursive ( index ) ;
return U_SUCCESS ;
}
USTATUS FfsParser : : addFixedAndCompressedRecursive ( const UModelIndex & index ) {
// Sanity check
if ( ! index . isValid ( ) )
return U_INVALID_PARAMETER ;
// Add fixed and compressed info
model - > addInfo ( index , usprintf ( " \n Compressed: %s " , model - > compressed ( index ) ? " Yes " : " No " ) ) ;
model - > addInfo ( index , usprintf ( " \n Fixed: %s " , model - > fixed ( index ) ? " Yes " : " No " ) ) ;
// Process child items
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
addFixedAndCompressedRecursive ( index . child ( i , 0 ) ) ;
}
return U_SUCCESS ;
}
USTATUS FfsParser : : parseFit ( const UModelIndex & index , const UINT32 diff )
{
// Check sanity
if ( ! index . isValid ( ) )
return EFI_INVALID_PARAMETER ;
// Search for FIT
UModelIndex fitIndex ;
UINT32 fitOffset ;
USTATUS result = findFitRecursive ( index , diff , fitIndex , fitOffset ) ;
if ( result )
return result ;
// FIT not found
if ( ! fitIndex . isValid ( ) )
return U_SUCCESS ;
// Explicitly set the item as fixed
model - > setFixed ( fitIndex , true ) ;
// Special case of FIT header
UByteArray fitBody = model - > body ( fitIndex ) ;
const FIT_ENTRY * fitHeader = ( const FIT_ENTRY * ) ( fitBody . constData ( ) + fitOffset ) ;
// Check FIT checksum, if present
UINT32 fitSize = ( fitHeader - > Size & 0xFFFFFF ) < < 4 ;
if ( fitHeader - > Type & 0x80 ) {
// Calculate FIT entry checksum
UByteArray tempFIT = model - > body ( fitIndex ) . mid ( fitOffset , fitSize ) ;
FIT_ENTRY * tempFitHeader = ( FIT_ENTRY * ) tempFIT . data ( ) ;
tempFitHeader - > Checksum = 0 ;
UINT8 calculated = calculateChecksum8 ( ( const UINT8 * ) tempFitHeader , fitSize ) ;
2016-07-16 13:02:33 +08:00
calculated | = 0x80 ; // Set checksum flag on calculated checksum
2016-07-15 03:22:51 +08:00
if ( calculated ! = fitHeader - > Checksum ) {
2016-07-16 13:02:33 +08:00
msg ( usprintf ( " parseFit: invalid FIT table checksum %02Xh, should be %02Xh " , fitHeader - > Checksum , calculated ) , fitIndex ) ;
2016-07-15 03:22:51 +08:00
}
}
// Check fit header type
if ( ( fitHeader - > Type & 0x7F ) ! = FIT_TYPE_HEADER ) {
msg ( ( " Invalid FIT header type " ) , fitIndex ) ;
}
// Add FIT header to fitTable
std : : vector < UString > currentStrings ;
currentStrings . push_back ( UString ( " _FIT_ " ) ) ;
currentStrings . push_back ( usprintf ( " %08Xh " , fitSize ) ) ;
currentStrings . push_back ( usprintf ( " %04Xh " , fitHeader - > Version ) ) ;
currentStrings . push_back ( usprintf ( " %02Xh " , fitHeader - > Checksum ) ) ;
currentStrings . push_back ( fitEntryTypeToUString ( fitHeader - > Type ) ) ;
fitTable . push_back ( currentStrings ) ;
// Process all other entries
bool msgModifiedImageMayNotWork = false ;
for ( UINT32 i = 1 ; i < fitHeader - > Size ; i + + ) {
currentStrings . clear ( ) ;
const FIT_ENTRY * currentEntry = fitHeader + i ;
// Check entry type
switch ( currentEntry - > Type & 0x7F ) {
case FIT_TYPE_HEADER :
2016-07-16 13:02:33 +08:00
msg ( UString ( " parseFit: second FIT header found, the table is damaged " ) , fitIndex ) ;
2016-07-15 03:22:51 +08:00
break ;
case FIT_TYPE_EMPTY :
case FIT_TYPE_MICROCODE :
break ;
case FIT_TYPE_BIOS_AC_MODULE :
case FIT_TYPE_BIOS_INIT_MODULE :
case FIT_TYPE_TPM_POLICY :
case FIT_TYPE_BIOS_POLICY_DATA :
case FIT_TYPE_TXT_CONF_POLICY :
case FIT_TYPE_AC_KEY_MANIFEST :
case FIT_TYPE_AC_BOOT_POLICY :
default :
msgModifiedImageMayNotWork = true ;
break ;
}
// Add entry to fitTable
currentStrings . push_back ( usprintf ( " %016 " PRIX64 , currentEntry - > Address ) ) ;
currentStrings . push_back ( usprintf ( " %08Xh " , currentEntry - > Size , currentEntry - > Size ) ) ;
currentStrings . push_back ( usprintf ( " %04Xh " , currentEntry - > Version ) ) ;
currentStrings . push_back ( usprintf ( " %02Xh " , currentEntry - > Checksum ) ) ;
currentStrings . push_back ( fitEntryTypeToUString ( currentEntry - > Type ) ) ;
fitTable . push_back ( currentStrings ) ;
}
if ( msgModifiedImageMayNotWork )
2016-07-16 13:02:33 +08:00
msg ( UString ( " parseFit: opened image may not work after any modification " ) , fitIndex ) ;
2016-07-15 03:22:51 +08:00
return U_SUCCESS ;
}
USTATUS FfsParser : : findFitRecursive ( const UModelIndex & index , const UINT32 diff , UModelIndex & found , UINT32 & fitOffset )
{
// Sanity check
if ( ! index . isValid ( ) )
return U_SUCCESS ;
// Process child items
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
findFitRecursive ( index . child ( i , 0 ) , diff , found , fitOffset ) ;
if ( found . isValid ( ) )
return U_SUCCESS ;
}
// Get parsing data for the current item
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
// Check for all FIT signatures in item's body
UByteArray lastVtfBody = model - > body ( lastVtf ) ;
UINT32 storedFitAddress = * ( const UINT32 * ) ( lastVtfBody . constData ( ) + lastVtfBody . size ( ) - FIT_POINTER_OFFSET ) ;
for ( INT32 offset = model - > body ( index ) . indexOf ( FIT_SIGNATURE ) ;
offset > = 0 ;
offset = model - > body ( index ) . indexOf ( FIT_SIGNATURE , offset + 1 ) ) {
// FIT candidate found, calculate it's physical address
UINT32 fitAddress = pdata . offset + diff + model - > header ( index ) . size ( ) + ( UINT32 ) offset ;
// Check FIT address to be stored in the last VTF
if ( fitAddress = = storedFitAddress ) {
found = index ;
fitOffset = offset ;
2016-07-16 13:02:33 +08:00
msg ( usprintf ( " findFitRecursive: real FIT table found at physical address %08Xh " , fitAddress ) , found ) ;
2016-07-15 03:22:51 +08:00
return U_SUCCESS ;
}
else if ( model - > rowCount ( index ) = = 0 ) // Show messages only to leaf items
2016-07-16 13:02:33 +08:00
msg ( UString ( " findFitRecursive: FIT table candidate found, but not referenced from the last VTF " ) , index ) ;
2016-07-15 03:22:51 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-03-13 14:48:53 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : addMemoryAddressesRecursive ( const UModelIndex & index , const UINT32 diff )
2015-06-20 02:26:45 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-12-30 06:39:43 +08:00
// Set address value for non-compressed data
if ( ! model - > compressed ( index ) ) {
// Get parsing data for the current item
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2015-06-20 02:26:45 +08:00
// Check address sanity
2015-07-07 21:57:41 +08:00
if ( ( const UINT64 ) diff + pdata . offset < = 0xFFFFFFFFUL ) {
2015-06-20 02:26:45 +08:00
// Update info
pdata . address = diff + pdata . offset ;
UINT32 headerSize = model - > header ( index ) . size ( ) ;
if ( headerSize ) {
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , usprintf ( " \n Header memory address: %08Xh " , pdata . address ) ) ;
model - > addInfo ( index , usprintf ( " \n Data memory address: %08Xh " , pdata . address + headerSize ) ) ;
2015-06-20 02:26:45 +08:00
}
else {
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , usprintf ( " \n Memory address: %08Xh " , pdata . address ) ) ;
2015-06-20 02:26:45 +08:00
}
// Special case of uncompressed TE image sections
2015-12-30 06:39:43 +08:00
if ( model - > type ( index ) = = Types : : Section & & model - > subtype ( index ) = = EFI_SECTION_TE ) {
2015-06-20 02:26:45 +08:00
// Check data memory address to be equal to either ImageBase or AdjustedImageBase
2016-07-16 13:02:33 +08:00
UINT32 base = pdata . address + headerSize ;
pdata . section . teImage . imageBaseType = EFI_IMAGE_TE_BASE_OTHER ;
if ( pdata . section . teImage . imageBase = = base ) {
pdata . section . teImage . imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL ;
2015-06-20 02:26:45 +08:00
}
2016-07-16 13:02:33 +08:00
else if ( pdata . section . teImage . adjustedImageBase = = base ) {
pdata . section . teImage . imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED ;
2015-06-20 02:26:45 +08:00
}
2016-07-16 13:02:33 +08:00
else {
// Check for one-bit difference
UINT32 xored = base ^ pdata . section . teImage . imageBase ; // XOR result can't be zero
if ( ( xored & ( xored - 1 ) ) = = 0 ) { // Check that XOR result is a power of 2, i.e. has exactly one bit set
pdata . section . teImage . imageBaseType = EFI_IMAGE_TE_BASE_ORIGINAL ;
}
else { // The same check for adjustedImageBase
xored = base ^ pdata . section . teImage . adjustedImageBase ;
if ( ( xored & ( xored - 1 ) ) = = 0 ) {
pdata . section . teImage . imageBaseType = EFI_IMAGE_TE_BASE_ADJUSTED ;
}
}
2015-06-20 02:26:45 +08:00
}
2016-07-16 13:02:33 +08:00
// Show message if imageBaseType is still unknown
if ( pdata . section . teImage . imageBase ! = 0 & & pdata . section . teImage . imageBaseType = = EFI_IMAGE_TE_BASE_OTHER )
msg ( UString ( " addMemoryAddressesRecursive: TE image base is neither zero, nor original, nor adjusted, nor top-swapped " ) , index ) ;
2015-06-20 02:26:45 +08:00
}
// Set modified parsing data
2016-06-26 11:54:21 +08:00
model - > setParsingData ( index , parsingDataToUByteArray ( pdata ) ) ;
2015-06-20 02:26:45 +08:00
}
}
2016-01-28 07:21:51 +08:00
// Process child items
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
addMemoryAddressesRecursive ( index . child ( i , 0 ) , diff ) ;
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-01-28 07:21:51 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : addOffsetsRecursive ( const UModelIndex & index )
2016-01-28 07:21:51 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2016-01-28 07:21:51 +08:00
// Get parsing data for the current item
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-01-28 07:21:51 +08:00
// Add current offset if the element is not compressed
2016-03-21 06:59:03 +08:00
// or it's compressed, but it's parent isn't
if ( ( ! model - > compressed ( index ) ) | | ( index . parent ( ) . isValid ( ) & & ! model - > compressed ( index . parent ( ) ) ) ) {
2016-06-26 11:54:21 +08:00
model - > addInfo ( index , usprintf ( " Offset: %Xh \n " , pdata . offset ) , false ) ;
2016-01-28 07:21:51 +08:00
}
2015-06-20 02:26:45 +08:00
// Process child items
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2016-01-28 07:21:51 +08:00
addOffsetsRecursive ( index . child ( i , 0 ) ) ;
2015-06-20 02:26:45 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2015-07-05 12:20:03 +08:00
}
2016-03-21 06:59:03 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseNvarStore ( const UModelIndex & index )
2016-03-21 06:59:03 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2016-03-21 06:59:03 +08:00
// Get parsing data for the current item
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-03-21 06:59:03 +08:00
UINT32 parentOffset = pdata . offset + model - > header ( index ) . size ( ) ;
2016-04-21 04:41:18 +08:00
// Get item data
2016-06-26 11:54:21 +08:00
const UByteArray data = model - > body ( index ) ;
2016-04-21 04:41:18 +08:00
2016-03-21 06:59:03 +08:00
// Rename parent file
2016-06-26 11:54:21 +08:00
model - > setText ( model - > findParentOfType ( index , Types : : File ) , UString ( " NVAR store " ) ) ;
2016-03-21 06:59:03 +08:00
UINT32 offset = 0 ;
2016-04-07 14:23:37 +08:00
UINT32 guidsInStore = 0 ;
2016-04-18 21:10:07 +08:00
const UINT8 emptyByte = pdata . emptyByte ;
2016-04-17 07:25:44 +08:00
// Parse all entries
2016-03-21 06:59:03 +08:00
while ( 1 ) {
bool msgUnknownExtDataFormat = false ;
bool msgExtHeaderTooLong = false ;
bool msgExtDataTooShort = false ;
bool isInvalid = false ;
2016-04-18 21:10:07 +08:00
bool isInvalidLink = false ;
2016-03-21 06:59:03 +08:00
bool isDataOnly = false ;
bool hasExtendedHeader = false ;
bool hasChecksum = false ;
2016-07-15 01:28:02 +08:00
bool hasTimestamp = false ;
bool hasHash = false ;
2016-03-21 17:19:02 +08:00
bool hasGuidIndex = false ;
2016-03-21 06:59:03 +08:00
2016-03-21 17:19:02 +08:00
UINT32 guidIndex = 0 ;
2016-03-21 06:59:03 +08:00
UINT8 storedChecksum = 0 ;
UINT8 calculatedChecksum = 0 ;
2016-04-21 04:41:18 +08:00
UINT32 extendedHeaderSize = 0 ;
2016-03-21 06:59:03 +08:00
UINT8 extendedAttributes = 0 ;
UINT64 timestamp = 0 ;
2016-06-26 11:54:21 +08:00
UByteArray hash ;
2016-03-21 06:59:03 +08:00
2016-04-17 07:25:44 +08:00
UINT8 subtype = Subtypes : : FullNvarEntry ;
2016-06-26 11:54:21 +08:00
UString name ;
UString text ;
UByteArray header ;
UByteArray body ;
UByteArray tail ;
2016-03-28 21:03:32 +08:00
2016-04-07 14:23:37 +08:00
UINT32 guidAreaSize = guidsInStore * sizeof ( EFI_GUID ) ;
2016-03-21 06:59:03 +08:00
UINT32 unparsedSize = ( UINT32 ) data . size ( ) - offset - guidAreaSize ;
2016-04-17 07:25:44 +08:00
// Get entry header
const NVAR_ENTRY_HEADER * entryHeader = ( const NVAR_ENTRY_HEADER * ) ( data . constData ( ) + offset ) ;
2016-03-21 06:59:03 +08:00
2016-04-18 21:10:07 +08:00
// Check header size and signature
2016-04-17 07:25:44 +08:00
if ( unparsedSize < sizeof ( NVAR_ENTRY_HEADER ) | |
2016-04-18 21:10:07 +08:00
entryHeader - > Signature ! = NVRAM_NVAR_ENTRY_SIGNATURE | |
2016-04-17 07:25:44 +08:00
unparsedSize < entryHeader - > Size ) {
2016-03-21 16:54:20 +08:00
2016-03-21 06:59:03 +08:00
// Check if the data left is a free space or a padding
2016-06-26 11:54:21 +08:00
UByteArray padding = data . mid ( offset , unparsedSize ) ;
2016-03-21 06:59:03 +08:00
UINT8 type ;
2016-04-18 23:05:56 +08:00
if ( ( UINT32 ) padding . count ( emptyByte ) = = unparsedSize ) {
2016-03-21 06:59:03 +08:00
// It's a free space
2016-06-26 11:54:21 +08:00
name = ( " Free space " ) ;
2016-03-21 06:59:03 +08:00
type = Types : : FreeSpace ;
subtype = 0 ;
}
else {
2016-03-21 16:54:20 +08:00
// Nothing is parsed yet, but the file is not empty
if ( ! offset ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseNvarStore: file can't be parsed as NVAR variables store " ) , index ) ;
return U_SUCCESS ;
2016-03-21 16:54:20 +08:00
}
2016-03-21 06:59:03 +08:00
// It's a padding
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
2016-03-21 06:59:03 +08:00
type = Types : : Padding ;
subtype = getPaddingType ( padding ) ;
}
// Get info
2016-06-26 11:54:21 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2016-03-21 06:59:03 +08:00
// Construct parsing data
pdata . offset = parentOffset + offset ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( type , subtype , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-21 06:59:03 +08:00
2016-04-07 14:23:37 +08:00
// Add GUID store area
2016-06-26 11:54:21 +08:00
UByteArray guidArea = data . right ( guidAreaSize ) ;
2016-03-21 06:59:03 +08:00
// Get info
2016-06-26 11:54:21 +08:00
name = UString ( " GUID store area " ) ;
info = usprintf ( " Full size: %Xh (%u) \n GUIDs in store: %u " ,
guidArea . size ( ) , guidArea . size ( ) ,
guidsInStore ) ;
2016-03-21 06:59:03 +08:00
// Construct parsing data
pdata . offset = parentOffset + offset + padding . size ( ) ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( guidArea ) , name , UString ( ) , info , UByteArray ( ) , guidArea , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-21 06:59:03 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-03-21 06:59:03 +08:00
}
// Contruct generic header and body
2016-04-17 07:25:44 +08:00
header = data . mid ( offset , sizeof ( NVAR_ENTRY_HEADER ) ) ;
body = data . mid ( offset + sizeof ( NVAR_ENTRY_HEADER ) , entryHeader - > Size - sizeof ( NVAR_ENTRY_HEADER ) ) ;
2016-03-21 06:59:03 +08:00
2016-03-21 16:54:20 +08:00
UINT32 lastVariableFlag = pdata . emptyByte ? 0xFFFFFF : 0 ;
2016-03-21 06:59:03 +08:00
// Set default next to predefined last value
2016-04-18 21:10:07 +08:00
pdata . nvar . next = lastVariableFlag ;
2016-03-21 06:59:03 +08:00
2016-04-17 07:25:44 +08:00
// Entry is marked as invalid
2016-04-18 21:10:07 +08:00
if ( ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_VALID ) = = 0 ) { // Valid attribute is not set
2016-03-21 06:59:03 +08:00
isInvalid = true ;
// Do not parse further
goto parsing_done ;
}
// Add next node information to parsing data
2016-04-17 07:25:44 +08:00
if ( entryHeader - > Next ! = lastVariableFlag ) {
subtype = Subtypes : : LinkNvarEntry ;
2016-04-18 21:10:07 +08:00
pdata . nvar . next = entryHeader - > Next ;
2016-03-21 06:59:03 +08:00
}
2016-04-18 21:10:07 +08:00
// Entry with extended header
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_EXT_HEADER ) {
2016-03-21 06:59:03 +08:00
hasExtendedHeader = true ;
msgUnknownExtDataFormat = true ;
extendedHeaderSize = * ( UINT16 * ) ( body . constData ( ) + body . size ( ) - sizeof ( UINT16 ) ) ;
2016-04-21 04:41:18 +08:00
if ( extendedHeaderSize > ( UINT32 ) body . size ( ) ) {
2016-03-21 06:59:03 +08:00
msgExtHeaderTooLong = true ;
isInvalid = true ;
// Do not parse further
goto parsing_done ;
}
extendedAttributes = * ( UINT8 * ) ( body . constData ( ) + body . size ( ) - extendedHeaderSize ) ;
// Variable with checksum
2016-04-18 21:10:07 +08:00
if ( extendedAttributes & NVRAM_NVAR_ENTRY_EXT_CHECKSUM ) {
2016-03-21 06:59:03 +08:00
// Get stored checksum
storedChecksum = * ( UINT8 * ) ( body . constData ( ) + body . size ( ) - sizeof ( UINT16 ) - sizeof ( UINT8 ) ) ;
// Recalculate checksum for the variable
calculatedChecksum = 0 ;
2016-04-17 07:25:44 +08:00
// Include entry data
UINT8 * start = ( UINT8 * ) ( entryHeader + 1 ) ;
for ( UINT8 * p = start ; p < start + entryHeader - > Size - sizeof ( NVAR_ENTRY_HEADER ) ; p + + ) {
2016-03-21 06:59:03 +08:00
calculatedChecksum + = * p ;
}
2016-04-17 07:25:44 +08:00
// Include entry size and flags
start = ( UINT8 * ) & entryHeader - > Size ;
2016-03-21 06:59:03 +08:00
for ( UINT8 * p = start ; p < start + sizeof ( UINT16 ) ; p + + ) {
calculatedChecksum + = * p ;
}
2016-04-17 07:25:44 +08:00
// Include entry attributes
calculatedChecksum + = entryHeader - > Attributes ;
2016-03-21 06:59:03 +08:00
hasChecksum = true ;
msgUnknownExtDataFormat = false ;
}
2016-04-21 04:41:18 +08:00
tail = body . mid ( body . size ( ) - extendedHeaderSize ) ;
2016-03-21 06:59:03 +08:00
body = body . left ( body . size ( ) - extendedHeaderSize ) ;
2016-04-17 07:25:44 +08:00
// Entry with authenticated write (for SecureBoot)
2016-04-18 21:10:07 +08:00
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_AUTH_WRITE ) {
2016-07-15 01:28:02 +08:00
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 ;
}
timestamp = * ( UINT64 * ) ( tail . constData ( ) + sizeof ( UINT8 ) ) ;
hasTimestamp = true ;
msgUnknownExtDataFormat = false ;
2016-03-21 06:59:03 +08:00
}
2016-07-15 01:28:02 +08:00
else { // Full or link variable have hash
if ( ( UINT32 ) tail . size ( ) < sizeof ( UINT64 ) + SHA256_HASH_SIZE ) {
msgExtDataTooShort = true ;
isInvalid = true ;
// Do not parse further
goto parsing_done ;
}
2016-03-21 06:59:03 +08:00
2016-07-15 01:28:02 +08:00
timestamp = * ( UINT64 * ) ( tail . constData ( ) + sizeof ( UINT8 ) ) ;
hash = tail . mid ( sizeof ( UINT64 ) + sizeof ( UINT8 ) , SHA256_HASH_SIZE ) ;
hasTimestamp = true ;
hasHash = true ;
msgUnknownExtDataFormat = false ;
}
2016-03-21 06:59:03 +08:00
}
}
2016-04-17 07:25:44 +08:00
// Entry is data-only (nameless and GUIDless entry or link)
2016-04-18 21:10:07 +08:00
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_DATA_ONLY ) { // Data-only attribute is set
isInvalidLink = true ;
2016-06-26 11:54:21 +08:00
UModelIndex nvarIndex ;
2016-07-15 01:28:02 +08:00
// Search prevously added entries for a link to this variable
2016-03-21 06:59:03 +08:00
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
nvarIndex = index . child ( i , 0 ) ;
2016-06-26 11:54:21 +08:00
PARSING_DATA nvarPdata = parsingDataFromUModelIndex ( nvarIndex ) ;
2016-04-18 21:10:07 +08:00
if ( nvarPdata . nvar . isValid & & nvarPdata . nvar . next + nvarPdata . offset - parentOffset = = offset ) { // Previous link is present and valid
isInvalidLink = false ;
2016-03-21 06:59:03 +08:00
break ;
}
}
// Check if the link is valid
2016-04-18 21:10:07 +08:00
if ( ! isInvalidLink ) {
2016-03-21 06:59:03 +08:00
// Use the name and text of the previous link
name = model - > name ( nvarIndex ) ;
text = model - > text ( nvarIndex ) ;
2016-04-17 07:25:44 +08:00
if ( entryHeader - > Next = = lastVariableFlag )
subtype = Subtypes : : DataNvarEntry ;
2016-03-21 06:59:03 +08:00
}
isDataOnly = true ;
// Do not parse further
goto parsing_done ;
}
2016-04-17 07:25:44 +08:00
// Get entry name
2016-03-21 18:00:10 +08:00
{
2016-04-21 04:41:18 +08:00
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
2016-04-17 07:25:44 +08:00
CHAR8 * namePtr = ( CHAR8 * ) ( entryHeader + 1 ) + nameOffset ;
2016-03-21 18:00:10 +08:00
UINT32 nameSize = 0 ;
2016-04-18 21:10:07 +08:00
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_ASCII_NAME ) { // Name is stored as ASCII string of CHAR8s
2016-06-26 11:54:21 +08:00
text = UString ( namePtr ) ;
2016-03-21 18:00:10 +08:00
nameSize = text . length ( ) + 1 ;
}
else { // Name is stored as UCS2 string of CHAR16s
2016-06-26 11:54:21 +08:00
text = UString : : fromUtf16 ( ( CHAR16 * ) namePtr ) ;
2016-03-21 18:00:10 +08:00
nameSize = ( text . length ( ) + 1 ) * 2 ;
}
2016-03-21 06:59:03 +08:00
2016-04-17 07:25:44 +08:00
// Get entry GUID
2016-04-18 21:10:07 +08:00
if ( entryHeader - > Attributes & NVRAM_NVAR_ENTRY_GUID ) { // GUID is strored in the variable itself
2016-06-26 11:54:21 +08:00
name = guidToUString ( * ( EFI_GUID * ) ( entryHeader + 1 ) ) ;
2016-03-21 18:00:10 +08:00
}
2016-04-07 14:23:37 +08:00
// GUID is stored in GUID list at the end of the store
2016-03-21 18:00:10 +08:00
else {
2016-04-17 07:25:44 +08:00
guidIndex = * ( UINT8 * ) ( entryHeader + 1 ) ;
2016-04-07 14:23:37 +08:00
if ( guidsInStore < guidIndex + 1 )
guidsInStore = guidIndex + 1 ;
2016-03-21 18:00:10 +08:00
2016-04-07 14:23:37 +08:00
// The list begins at the end of the store and goes backwards
2016-03-21 18:00:10 +08:00
const EFI_GUID * guidPtr = ( const EFI_GUID * ) ( data . constData ( ) + data . size ( ) ) - 1 - guidIndex ;
2016-06-26 11:54:21 +08:00
name = guidToUString ( * guidPtr ) ;
2016-03-21 18:00:10 +08:00
hasGuidIndex = true ;
}
2016-03-21 06:59:03 +08:00
2016-04-17 07:25:44 +08:00
// Include name and GUID into the header and remove them from body
header = data . mid ( offset , sizeof ( NVAR_ENTRY_HEADER ) + nameOffset + nameSize ) ;
2016-03-21 18:00:10 +08:00
body = body . mid ( nameOffset + nameSize ) ;
2016-03-21 06:59:03 +08:00
}
parsing_done :
2016-06-26 11:54:21 +08:00
UString info ;
2016-04-18 21:10:07 +08:00
2016-04-17 07:25:44 +08:00
// Rename invalid entries according to their types
2016-04-18 21:10:07 +08:00
pdata . nvar . isValid = TRUE ;
2016-03-21 06:59:03 +08:00
if ( isInvalid ) {
2016-06-26 11:54:21 +08:00
name = UString ( " Invalid " ) ;
2016-04-18 21:10:07 +08:00
subtype = Subtypes : : InvalidNvarEntry ;
pdata . nvar . isValid = FALSE ;
}
else if ( isInvalidLink ) {
2016-06-26 11:54:21 +08:00
name = UString ( " Invalid link " ) ;
2016-04-18 21:10:07 +08:00
subtype = Subtypes : : InvalidLinkNvarEntry ;
pdata . nvar . isValid = FALSE ;
2016-03-21 06:59:03 +08:00
}
2016-04-17 07:25:44 +08:00
else // Add GUID info for valid entries
2016-06-26 11:54:21 +08:00
info + = UString ( " Variable GUID: " ) + name + UString ( " \n " ) ;
2016-03-21 06:59:03 +08:00
2016-03-21 17:19:02 +08:00
// Add GUID index information
if ( hasGuidIndex )
2016-06-26 11:54:21 +08:00
info + = usprintf ( " GUID index: %u \n " , guidIndex ) ;
2016-03-21 17:19:02 +08:00
2016-03-21 06:59:03 +08:00
// Add header, body and extended data info
2016-06-26 11:54:21 +08:00
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 ( ) ) ;
2016-03-21 06:59:03 +08:00
// Add attributes info
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Attributes: %02Xh " , entryHeader - > Attributes ) ;
2016-03-21 06:59:03 +08:00
// Translate attributes to text
2016-04-18 21:10:07 +08:00
if ( entryHeader - > Attributes & & entryHeader - > Attributes ! = 0xFF )
2016-06-26 16:05:45 +08:00
info + = UString ( " ( " ) + nvarAttributesToUString ( entryHeader - > Attributes ) + UString ( " ) " ) ;
2016-03-21 06:59:03 +08:00
// Add next node info
2016-04-17 07:25:44 +08:00
if ( ! isInvalid & & entryHeader - > Next ! = lastVariableFlag )
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Next node at offset: %Xh " , parentOffset + offset + entryHeader - > Next ) ;
2016-03-21 06:59:03 +08:00
// Add extended header info
if ( hasExtendedHeader ) {
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Extended header size: %Xh (%u) \n Extended attributes: %Xh ( " ,
extendedHeaderSize , extendedHeaderSize ,
2016-06-26 16:05:45 +08:00
extendedAttributes ) + nvarExtendedAttributesToUString ( extendedAttributes ) + UString ( " ) " ) ;
2016-04-18 21:10:07 +08:00
2016-07-15 01:28:02 +08:00
// Add checksum
2016-03-21 06:59:03 +08:00
if ( hasChecksum )
2016-06-26 11:54:21 +08:00
info + = usprintf ( " \n Checksum: %02Xh " , storedChecksum ) +
( calculatedChecksum ? usprintf ( " , invalid, should be %02Xh " , 0x100 - calculatedChecksum ) : UString ( " , valid " ) ) ;
2016-07-15 01:28:02 +08:00
// Add timestamp
if ( hasTimestamp )
info + = usprintf ( " \n Timestamp: % " PRIX64 " h " , timestamp ) ;
// Add hash
if ( hasHash )
info + = UString ( " \n Hash: " ) + UString ( hash . toHex ( ) . constData ( ) ) ;
2016-03-21 06:59:03 +08:00
}
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add tree item
2016-06-26 11:54:21 +08:00
UModelIndex varIndex = model - > addItem ( Types : : NvarEntry , subtype , name , text , info , header , body , tail , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-21 06:59:03 +08:00
// Show messages
2016-06-26 11:54:21 +08:00
if ( msgUnknownExtDataFormat ) msg ( UString ( " parseNvarStore: unknown extended data format " ) , varIndex ) ;
if ( msgExtHeaderTooLong ) msg ( usprintf ( " parseNvarStore: extended header size (%Xh) is greater than body size (%Xh) " ,
extendedHeaderSize , body . size ( ) ) , varIndex ) ;
if ( msgExtDataTooShort ) msg ( usprintf ( " parseNvarStore: extended header size (%Xh) is too small for timestamp and hash " ,
tail . size ( ) ) , varIndex ) ;
2016-04-17 07:25:44 +08:00
// Try parsing the entry data as NVAR storage if it begins with NVAR signature
if ( ( subtype = = Subtypes : : DataNvarEntry | | subtype = = Subtypes : : FullNvarEntry )
& & * ( const UINT32 * ) body . constData ( ) = = NVRAM_NVAR_ENTRY_SIGNATURE )
2016-04-21 04:41:18 +08:00
parseNvarStore ( varIndex ) ;
2016-04-08 19:22:18 +08:00
2016-04-17 07:25:44 +08:00
// Move to next exntry
offset + = entryHeader - > Size ;
2016-03-21 06:59:03 +08:00
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-03-21 18:00:10 +08:00
}
2016-03-28 21:03:32 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseNvramVolumeBody ( const UModelIndex & index )
2016-03-28 21:03:32 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2016-03-28 21:03:32 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-03-28 21:03:32 +08:00
UINT32 parentOffset = pdata . offset + model - > header ( index ) . size ( ) ;
2016-04-17 07:25:44 +08:00
// Get item data
2016-06-26 11:54:21 +08:00
UByteArray data = model - > body ( index ) ;
2016-04-17 07:25:44 +08:00
2016-04-18 21:10:07 +08:00
// Search for first store
2016-06-26 11:54:21 +08:00
USTATUS result ;
2016-04-07 14:23:37 +08:00
UINT32 prevStoreOffset ;
result = findNextStore ( index , data , parentOffset , 0 , prevStoreOffset ) ;
2016-03-28 21:03:32 +08:00
if ( result )
return result ;
2016-04-07 14:23:37 +08:00
// First store is not at the beginning of volume body
2016-06-26 11:54:21 +08:00
UString name ;
UString info ;
2016-04-07 14:23:37 +08:00
if ( prevStoreOffset > 0 ) {
2016-03-28 21:03:32 +08:00
// Get info
2016-06-26 11:54:21 +08:00
UByteArray padding = data . left ( prevStoreOffset ) ;
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2016-03-28 21:03:32 +08:00
// Construct parsing data
pdata . offset = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-28 21:03:32 +08:00
}
2016-04-07 14:23:37 +08:00
// Search for and parse all stores
UINT32 storeOffset = prevStoreOffset ;
UINT32 prevStoreSize = 0 ;
2016-03-28 21:03:32 +08:00
while ( ! result )
{
2016-04-07 14:23:37 +08:00
// Padding between stores
if ( storeOffset > prevStoreOffset + prevStoreSize ) {
UINT32 paddingOffset = prevStoreOffset + prevStoreSize ;
UINT32 paddingSize = storeOffset - paddingOffset ;
2016-06-26 11:54:21 +08:00
UByteArray padding = data . mid ( paddingOffset , paddingSize ) ;
2016-03-28 21:03:32 +08:00
// Get info
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2016-03-28 21:03:32 +08:00
// Construct parsing data
pdata . offset = parentOffset + paddingOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-28 21:03:32 +08:00
}
2016-04-07 14:23:37 +08:00
// Get store size
UINT32 storeSize = 0 ;
result = getStoreSize ( data , storeOffset , storeSize ) ;
2016-03-28 21:03:32 +08:00
if ( result ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseNvramVolumeBody: getStoreSize failed with error " ) + errorCodeToUString ( result ) , index ) ;
2016-03-28 21:03:32 +08:00
return result ;
}
2016-04-08 19:22:18 +08:00
// Check that current store is fully present in input
2016-04-07 14:23:37 +08:00
if ( storeSize > ( UINT32 ) data . size ( ) | | storeOffset + storeSize > ( UINT32 ) data . size ( ) ) {
2016-04-18 21:10:07 +08:00
// Mark the rest as padding and finish parsing
2016-06-26 11:54:21 +08:00
UByteArray padding = data . mid ( storeOffset ) ;
2016-03-28 21:03:32 +08:00
// Get info
2016-06-26 16:05:45 +08:00
name = UString ( " Padding " ) ;
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2016-03-28 21:03:32 +08:00
// Construct parsing data
2016-04-07 14:23:37 +08:00
pdata . offset = parentOffset + storeOffset ;
2016-03-28 21:03:32 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
UModelIndex paddingIndex = model - > addItem ( Types : : Padding , getPaddingType ( padding ) , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
msg ( UString ( " parseNvramVolumeBody: one of stores inside overlaps the end of data " ) , paddingIndex ) ;
2016-03-28 21:03:32 +08:00
// Update variables
2016-04-07 14:23:37 +08:00
prevStoreOffset = storeOffset ;
prevStoreSize = padding . size ( ) ;
2016-03-28 21:03:32 +08:00
break ;
}
2016-06-26 11:54:21 +08:00
UByteArray store = data . mid ( storeOffset , storeSize ) ;
2016-04-18 21:10:07 +08:00
// Parse current store header
2016-06-26 11:54:21 +08:00
UModelIndex storeIndex ;
2016-04-07 14:23:37 +08:00
result = parseStoreHeader ( store , parentOffset + storeOffset , index , storeIndex ) ;
2016-04-18 21:10:07 +08:00
if ( result )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseNvramVolumeBody: store header parsing failed with error " ) + errorCodeToUString ( result ) , index ) ;
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Go to next store
2016-04-07 14:23:37 +08:00
prevStoreOffset = storeOffset ;
prevStoreSize = storeSize ;
result = findNextStore ( index , data , parentOffset , storeOffset + prevStoreSize , storeOffset ) ;
2016-03-28 21:03:32 +08:00
}
2016-04-18 21:10:07 +08:00
// Padding/free space at the end
2016-04-07 14:23:37 +08:00
storeOffset = prevStoreOffset + prevStoreSize ;
if ( ( UINT32 ) data . size ( ) > storeOffset ) {
2016-06-26 11:54:21 +08:00
UByteArray padding = data . mid ( storeOffset ) ;
2016-03-28 21:03:32 +08:00
UINT8 type ;
UINT8 subtype ;
if ( padding . count ( pdata . emptyByte ) = = padding . size ( ) ) {
// It's a free space
2016-06-26 11:54:21 +08:00
name = UString ( " Free space " ) ;
2016-03-28 21:03:32 +08:00
type = Types : : FreeSpace ;
subtype = 0 ;
}
else {
// Nothing is parsed yet, but the file is not empty
2016-04-07 14:23:37 +08:00
if ( ! storeOffset ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseNvramVolumeBody: can't be parsed as NVRAM volume " ) , index ) ;
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
// It's a padding
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
2016-03-28 21:03:32 +08:00
type = Types : : Padding ;
subtype = getPaddingType ( padding ) ;
}
// Add info
2016-06-26 11:54:21 +08:00
info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2016-03-28 21:03:32 +08:00
// Construct parsing data
2016-04-07 14:23:37 +08:00
pdata . offset = parentOffset + storeOffset ;
2016-03-28 21:03:32 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( type , subtype , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-28 21:03:32 +08:00
}
// Parse bodies
2016-03-29 22:15:23 +08:00
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2016-06-26 11:54:21 +08:00
UModelIndex current = index . child ( i , 0 ) ;
2016-03-28 21:03:32 +08:00
switch ( model - > type ( current ) ) {
2016-04-17 07:25:44 +08:00
case Types : : VssStore :
case Types : : FdcStore : parseVssStoreBody ( current ) ; break ;
case Types : : FsysStore : parseFsysStoreBody ( current ) ; break ;
case Types : : EvsaStore : parseEvsaStoreBody ( current ) ; break ;
case Types : : FlashMapStore : parseFlashMapBody ( current ) ; break ;
2016-03-28 21:03:32 +08:00
}
}
2016-03-29 22:15:23 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : findNextStore ( const UModelIndex & index , const UByteArray & volume , const UINT32 parentOffset , const UINT32 storeOffset , UINT32 & nextStoreOffset )
2016-03-28 21:03:32 +08:00
{
2016-04-17 07:25:44 +08:00
UINT32 dataSize = volume . size ( ) ;
2016-03-28 21:03:32 +08:00
if ( dataSize < sizeof ( UINT32 ) )
2016-06-26 11:54:21 +08:00
return U_STORES_NOT_FOUND ;
2016-03-28 21:03:32 +08:00
2016-04-07 14:23:37 +08:00
UINT32 offset = storeOffset ;
2016-03-28 21:03:32 +08:00
for ( ; offset < dataSize - sizeof ( UINT32 ) ; offset + + ) {
2016-04-17 07:25:44 +08:00
const UINT32 * currentPos = ( const UINT32 * ) ( volume . constData ( ) + offset ) ;
2016-03-28 21:03:32 +08:00
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 ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: VSS store candidate at offset %Xh skipped, has invalid format %02Xh " , parentOffset + offset , vssHeader - > Format ) , index ) ;
2016-03-28 21:03:32 +08:00
continue ;
}
if ( vssHeader - > Size = = 0 | | vssHeader - > Size = = 0xFFFFFFFF ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: VSS store candidate at offset %Xh skipped, has invalid size %Xh " , parentOffset + offset , vssHeader - > Size ) , index ) ;
2016-03-28 21:03:32 +08:00
continue ;
}
2016-04-07 14:23:37 +08:00
// All checks passed, store found
2016-03-28 21:03:32 +08:00
break ;
}
2016-04-05 06:47:34 +08:00
else if ( * currentPos = = NVRAM_FDC_VOLUME_SIGNATURE ) { //FDC signature found
2016-04-08 19:22:18 +08:00
const FDC_VOLUME_HEADER * fdcHeader = ( const FDC_VOLUME_HEADER * ) currentPos ;
if ( fdcHeader - > Size = = 0 | | fdcHeader - > Size = = 0xFFFFFFFF ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: FDC store candidate at offset %Xh skipped, has invalid size %Xh " , parentOffset + offset , fdcHeader - > Size ) , index ) ;
2016-04-08 19:22:18 +08:00
continue ;
}
// All checks passed, store found
2016-04-07 14:23:37 +08:00
break ;
2016-04-05 06:47:34 +08:00
}
2016-04-13 07:35:18 +08:00
else if ( * currentPos = = NVRAM_APPLE_FSYS_STORE_SIGNATURE | | * currentPos = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) { //Fsys or Gaid signature found
2016-04-08 19:22:18 +08:00
const APPLE_FSYS_STORE_HEADER * fsysHeader = ( const APPLE_FSYS_STORE_HEADER * ) currentPos ;
if ( fsysHeader - > Size = = 0 | | fsysHeader - > Size = = 0xFFFF ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: Fsys store candidate at offset %Xh skipped, has invalid size %Xh " , parentOffset + offset , fsysHeader - > Size ) , index ) ;
2016-04-08 19:22:18 +08:00
continue ;
}
// All checks passed, store found
2016-04-07 14:23:37 +08:00
break ;
}
else if ( * currentPos = = NVRAM_EVSA_STORE_SIGNATURE ) { //EVSA signature found
2016-04-15 02:36:59 +08:00
if ( offset < sizeof ( UINT32 ) )
2016-04-07 14:23:37 +08:00
continue ;
2016-04-15 02:36:59 +08:00
2016-04-07 14:23:37 +08:00
const EVSA_STORE_ENTRY * evsaHeader = ( const EVSA_STORE_ENTRY * ) ( currentPos - 1 ) ;
if ( evsaHeader - > Header . Type ! = NVRAM_EVSA_ENTRY_TYPE_STORE ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: EVSA store candidate at offset %Xh skipped, has invalid type %02Xh " , parentOffset + offset - 4 , evsaHeader - > Header . Type ) , index ) ;
2016-04-07 14:23:37 +08:00
continue ;
}
2016-04-08 19:22:18 +08:00
if ( evsaHeader - > StoreSize = = 0 | | evsaHeader - > StoreSize = = 0xFFFFFFFF ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: EVSA store candidate at offset %Xh skipped, has invalid size %Xh " , parentOffset + offset , evsaHeader - > StoreSize ) , index ) ;
2016-04-08 19:22:18 +08:00
continue ;
}
2016-04-07 14:23:37 +08:00
// All checks passed, store found
2016-04-15 02:36:59 +08:00
offset - = sizeof ( UINT32 ) ;
2016-04-07 14:23:37 +08:00
break ;
2016-04-05 06:47:34 +08:00
}
2016-04-13 07:35:18 +08:00
else if ( * currentPos = = NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 | | * currentPos = = EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 ) { //Possible FTW block signature found
2016-06-26 11:54:21 +08:00
UByteArray guid = UByteArray ( volume . constData ( ) + offset , sizeof ( EFI_GUID ) ) ;
2016-04-13 07:35:18 +08:00
if ( guid ! = NVRAM_MAIN_STORE_VOLUME_GUID & & guid ! = EDKII_WORKING_BLOCK_SIGNATURE_GUID ) // Check the whole signature
2016-04-08 19:22:18 +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 ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: FTW block candidate at offset %Xh skipped, has invalid body size %Xh " , parentOffset + offset , ftwHeader - > WriteQueueSize ) , index ) ;
2016-04-08 19:22:18 +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 ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " findNextStore: FTW block candidate at offset %Xh skipped, has invalid body size %Xh " , parentOffset + offset , ftw64Header - > WriteQueueSize ) , index ) ;
2016-04-08 19:22:18 +08:00
continue ;
}
}
else // Unknown header
continue ;
2016-04-15 02:36:59 +08:00
2016-04-08 19:22:18 +08:00
// All checks passed, store found
break ;
}
2016-04-13 07:35:18 +08:00
else if ( * currentPos = = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 ) { // Phoenix SCT flash map
2016-06-26 11:54:21 +08:00
UByteArray signature = UByteArray ( volume . constData ( ) + offset , NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_LENGTH ) ;
2016-04-13 07:35:18 +08:00
if ( signature ! = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE ) // Check the whole signature
continue ;
// All checks passed, store found
break ;
}
2016-04-15 02:36:59 +08:00
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 ;
2016-04-15 03:02:17 +08:00
for ( UINT32 i = 0 ; i < sizeof ( ucodeHeader - > Reserved ) ; i + + )
2016-04-15 02:36:59 +08:00
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
if ( offset > = dataSize - sizeof ( UINT64 ) | |
* ( const UINT64 * ) currentPos ! = OEM_ACTIVATION_MARKER_WINDOWS_FLAG | |
offset < 26 ) // Check full windows flag and structure size
continue ;
2016-04-17 07:25:44 +08:00
const OEM_ACTIVATION_MARKER * markerHeader = ( const OEM_ACTIVATION_MARKER * ) ( volume . constData ( ) + offset - 26 ) ;
2016-04-15 02:36:59 +08:00
// Check reserved bytes
bool reservedBytesValid = true ;
2016-04-15 03:02:17 +08:00
for ( UINT32 i = 0 ; i < sizeof ( markerHeader - > Reserved ) ; i + + )
2016-04-15 02:36:59 +08:00
if ( markerHeader - > Reserved [ i ] ! = OEM_ACTIVATION_MARKER_RESERVED_BYTE ) {
reservedBytesValid = false ;
break ;
}
if ( ! reservedBytesValid )
continue ;
// All checks passed, store found
offset - = 26 ;
break ;
}
2016-03-28 21:03:32 +08:00
}
2016-04-08 19:22:18 +08:00
// No more stores found
2016-04-05 06:47:34 +08:00
if ( offset > = dataSize - sizeof ( UINT32 ) )
2016-06-26 11:54:21 +08:00
return U_STORES_NOT_FOUND ;
2016-03-28 21:03:32 +08:00
2016-04-07 14:23:37 +08:00
nextStoreOffset = offset ;
2016-03-28 21:03:32 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : getStoreSize ( const UByteArray & data , const UINT32 storeOffset , UINT32 & storeSize )
2016-03-28 21:03:32 +08:00
{
2016-04-07 14:23:37 +08:00
const UINT32 * signature = ( const UINT32 * ) ( data . constData ( ) + storeOffset ) ;
2016-04-05 06:47:34 +08:00
if ( * signature = = NVRAM_VSS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE ) {
const VSS_VARIABLE_STORE_HEADER * vssHeader = ( const VSS_VARIABLE_STORE_HEADER * ) signature ;
2016-04-07 14:23:37 +08:00
storeSize = vssHeader - > Size ;
2016-04-05 06:47:34 +08:00
}
else if ( * signature = = NVRAM_FDC_VOLUME_SIGNATURE ) {
const FDC_VOLUME_HEADER * fdcHeader = ( const FDC_VOLUME_HEADER * ) signature ;
2016-04-07 14:23:37 +08:00
storeSize = fdcHeader - > Size ;
2016-04-05 06:47:34 +08:00
}
2016-04-13 07:35:18 +08:00
else if ( * signature = = NVRAM_APPLE_FSYS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) {
2016-04-05 06:47:34 +08:00
const APPLE_FSYS_STORE_HEADER * fsysHeader = ( const APPLE_FSYS_STORE_HEADER * ) signature ;
2016-04-07 14:23:37 +08:00
storeSize = fsysHeader - > Size ;
}
else if ( * ( signature + 1 ) = = NVRAM_EVSA_STORE_SIGNATURE ) {
const EVSA_STORE_ENTRY * evsaHeader = ( const EVSA_STORE_ENTRY * ) signature ;
storeSize = evsaHeader - > StoreSize ;
2016-04-05 06:47:34 +08:00
}
2016-04-13 07:35:18 +08:00
else if ( * signature = = NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 | | * signature = = EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 ) {
2016-04-08 19:22:18 +08:00
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 ;
2016-07-06 00:19:04 +08:00
storeSize = sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) + ( UINT32 ) ftw64Header - > WriteQueueSize ;
2016-04-08 19:22:18 +08:00
}
}
2016-04-13 07:35:18 +08:00
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 ;
}
2016-04-15 02:36:59 +08:00
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 ;
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseVssStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-03-28 21:03:32 +08:00
{
2016-04-18 21:10:07 +08:00
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check store size
if ( dataSize < sizeof ( VSS_VARIABLE_STORE_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVssStoreHeader: volume body is too small even for VSS store header " ) , parent ) ;
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-04-18 21:10:07 +08:00
// Get VSS store header
const VSS_VARIABLE_STORE_HEADER * vssStoreHeader = ( const VSS_VARIABLE_STORE_HEADER * ) store . constData ( ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
if ( dataSize < vssStoreHeader - > Size ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseVssStoreHeader: VSS store size %Xh (%u) is greater than volume body size %Xh (%u) " ,
vssStoreHeader - > Size , vssStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( sizeof ( VSS_VARIABLE_STORE_HEADER ) ) ;
UByteArray body = store . mid ( sizeof ( VSS_VARIABLE_STORE_HEADER ) , vssStoreHeader - > Size - sizeof ( VSS_VARIABLE_STORE_HEADER ) ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Add info
bool isSvsStore = ( vssStoreHeader - > Signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE ) ;
2016-06-26 11:54:21 +08:00
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 " ,
vssStoreHeader - > Size , vssStoreHeader - > Size ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
vssStoreHeader - > Format ,
vssStoreHeader - > State ,
vssStoreHeader - > Unknown ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : VssStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-05 06:47:34 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFtwStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check store size
if ( dataSize < sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFtwStoreHeader: volume body is too small even for FTW store header " ) , parent ) ;
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-04-18 21:10:07 +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 ( ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +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
2016-07-06 00:19:04 +08:00
ftwBlockSize = sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) + ( UINT32 ) ftw64BlockHeader - > WriteQueueSize ;
2016-04-18 21:10:07 +08:00
has32bitHeader = false ;
}
if ( dataSize < ftwBlockSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseFtwStoreHeader: FTW store size %Xh (%u) is greater than volume body size %Xh (%u) " ,
ftwBlockSize , ftwBlockSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
UINT32 headerSize = has32bitHeader ? sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 ) : sizeof ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER64 ) ;
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( headerSize ) ;
UByteArray body = store . mid ( headerSize , ftwBlockSize - headerSize ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Check block header checksum
2016-06-26 11:54:21 +08:00
UByteArray crcHeader = header ;
2016-04-18 21:10:07 +08:00
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * crcFtwBlockHeader = ( EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER32 * ) header . data ( ) ;
crcFtwBlockHeader - > Crc = pdata . emptyByte ? 0xFFFFFFFF : 0 ;
crcFtwBlockHeader - > State = pdata . emptyByte ? 0xFF : 0 ;
UINT32 calculatedCrc = crc32 ( 0 , ( const UINT8 * ) crcFtwBlockHeader , headerSize ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Add info
2016-06-26 11:54:21 +08:00
UString name ( " FTW store " ) ;
2016-06-26 16:05:45 +08:00
UString info = UString ( " Signature: " ) + guidToUString ( ftw32BlockHeader - > Signature ) +
usprintf ( " \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n State: %02Xh \n Header CRC32: %08Xh " ,
2016-06-26 11:54:21 +08:00
ftwBlockSize , ftwBlockSize ,
headerSize , headerSize ,
body . size ( ) , body . size ( ) ,
2016-06-26 16:05:45 +08:00
ftw32BlockHeader - > State ,
ftw32BlockHeader - > Crc ) +
( ftw32BlockHeader - > Crc ! = calculatedCrc ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc ) : UString ( " , valid " ) ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : FtwStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-05 06:47:34 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-05 06:47:34 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFdcStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
if ( dataSize < sizeof ( FDC_VOLUME_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFdcStoreHeader: volume body is too small even for FDC store header " ) , parent ) ;
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-04-18 21:10:07 +08:00
// Get Fdc store header
const FDC_VOLUME_HEADER * fdcStoreHeader = ( const FDC_VOLUME_HEADER * ) store . constData ( ) ;
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
if ( dataSize < fdcStoreHeader - > Size ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseFdcStoreHeader: FDC store size %Xh (%u) is greater than volume body size %Xh (%u) " ,
fdcStoreHeader - > Size , fdcStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Determine internal volume header size
const EFI_FIRMWARE_VOLUME_HEADER * volumeHeader = ( const EFI_FIRMWARE_VOLUME_HEADER * ) ( fdcStoreHeader + 1 ) ;
UINT32 headerSize ;
if ( volumeHeader - > Revision > 1 & & volumeHeader - > ExtHeaderOffset ) {
const EFI_FIRMWARE_VOLUME_EXT_HEADER * extendedHeader = ( const EFI_FIRMWARE_VOLUME_EXT_HEADER * ) ( ( const UINT8 * ) volumeHeader + volumeHeader - > ExtHeaderOffset ) ;
headerSize = volumeHeader - > ExtHeaderOffset + extendedHeader - > ExtHeaderSize ;
}
else
headerSize = volumeHeader - > HeaderLength ;
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Extended header end can be unaligned
headerSize = ALIGN8 ( headerSize ) ;
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Add VSS store header
headerSize + = sizeof ( VSS_VARIABLE_STORE_HEADER ) ;
2016-04-05 06:47:34 +08:00
2016-04-18 21:10:07 +08:00
// Add FDC header
headerSize + = sizeof ( FDC_VOLUME_HEADER ) ;
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Check sanity of combined header size
if ( dataSize < headerSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseFdcStoreHeader: FDC store header size %Xh (%u) is greater than volume body size %Xh (%u) " ,
fdcStoreHeader - > Size , fdcStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-07 14:23:37 +08:00
}
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-07 14:23:37 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( headerSize ) ;
UByteArray body = store . mid ( headerSize , fdcStoreHeader - > Size - headerSize ) ;
2016-04-07 14:23:37 +08:00
2016-04-18 21:10:07 +08:00
// Add info
2016-06-26 11:54:21 +08:00
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 ( ) ) ;
2016-04-07 14:23:37 +08:00
2016-04-18 21:10:07 +08:00
// TODO: add internal headers info
2016-04-07 14:23:37 +08:00
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
2016-04-07 14:23:37 +08:00
2016-04-18 21:10:07 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : FdcStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-07 14:23:37 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFsysStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check store size
if ( dataSize < sizeof ( APPLE_FSYS_STORE_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFsysStoreHeader: volume body is too small even for Fsys store header " ) , parent ) ;
return U_SUCCESS ;
2016-04-05 06:47:34 +08:00
}
2016-04-08 19:22:18 +08:00
2016-04-18 21:10:07 +08:00
// Get Fsys store header
const APPLE_FSYS_STORE_HEADER * fsysStoreHeader = ( const APPLE_FSYS_STORE_HEADER * ) store . constData ( ) ;
2016-04-08 19:22:18 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
if ( dataSize < fsysStoreHeader - > Size ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseFsysStoreHeader: Fsys store size %Xh (%u) is greater than volume body size %Xh (%u) " ,
fsysStoreHeader - > Size , fsysStoreHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-08 19:22:18 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-08 19:22:18 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
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 ) ) ;
2016-04-08 19:22:18 +08:00
2016-04-18 21:10:07 +08:00
// Check store checksum
2016-07-05 23:22:03 +08:00
UINT32 storedCrc = * ( UINT32 * ) store . right ( sizeof ( UINT32 ) ) . constData ( ) ;
2016-04-18 22:21:15 +08:00
UINT32 calculatedCrc = crc32 ( 0 , ( const UINT8 * ) store . constData ( ) , ( const UINT32 ) store . size ( ) - sizeof ( UINT32 ) ) ;
2016-04-18 21:10:07 +08:00
// Add info
bool isGaidStore = ( fsysStoreHeader - > Signature = = NVRAM_APPLE_GAID_STORE_SIGNATURE ) ;
2016-06-26 11:54:21 +08:00
UString name = isGaidStore ? UString ( " Gaid store " ) : UString ( " Fsys store " ) ;
2016-06-26 16:05:45 +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 " ,
2016-06-26 11:54:21 +08:00
isGaidStore ? " Gaid " : " Fsys " ,
fsysStoreHeader - > Size , fsysStoreHeader - > Size ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
fsysStoreHeader - > Unknown0 ,
fsysStoreHeader - > Unknown1 )
2016-06-26 16:05:45 +08:00
+ ( storedCrc ! = calculatedCrc ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc ) : UString ( " , valid " ) ) ;
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : FsysStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-18 21:10:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseEvsaStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check dataSize
if ( dataSize < sizeof ( EVSA_STORE_ENTRY ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseEvsaStoreHeader: volume body is too small even for EVSA store header " ) , parent ) ;
return U_SUCCESS ;
2016-04-13 07:35:18 +08:00
}
2016-04-18 21:10:07 +08:00
// Get EVSA store header
const EVSA_STORE_ENTRY * evsaStoreHeader = ( const EVSA_STORE_ENTRY * ) store . constData ( ) ;
2016-04-13 07:35:18 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
if ( dataSize < evsaStoreHeader - > StoreSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseEvsaStoreHeader: EVSA store size %Xh (%u) is greater than volume body size %Xh (%u) " ,
evsaStoreHeader - > StoreSize , evsaStoreHeader - > StoreSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-13 07:35:18 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-13 07:35:18 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( evsaStoreHeader - > Header . Size ) ;
UByteArray body = store . mid ( evsaStoreHeader - > Header . Size , evsaStoreHeader - > StoreSize - evsaStoreHeader - > Header . Size ) ;
2016-04-13 07:35:18 +08:00
2016-04-18 21:10:07 +08:00
// Recalculate checksum
UINT8 calculated = calculateChecksum8 ( ( ( const UINT8 * ) evsaStoreHeader ) + 2 , evsaStoreHeader - > Header . Size - 2 ) ;
2016-04-13 07:35:18 +08:00
2016-04-18 21:10:07 +08:00
// Add info
2016-06-26 11:54:21 +08:00
UString name ( " EVSA store " ) ;
2016-06-26 16:05:45 +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 " ,
2016-06-26 11:54:21 +08:00
evsaStoreHeader - > StoreSize , evsaStoreHeader - > StoreSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
evsaStoreHeader - > Header . Type ,
2016-06-26 16:05:45 +08:00
evsaStoreHeader - > Attributes ,
evsaStoreHeader - > Header . Checksum ) +
( evsaStoreHeader - > Header . Checksum ! = calculated ? usprintf ( " %, invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) ) ;
2016-04-13 07:35:18 +08:00
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : EvsaStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-18 21:10:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFlashMapStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check data size
if ( dataSize < sizeof ( PHOENIX_FLASH_MAP_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFlashMapStoreHeader: volume body is too small even for FlashMap block header " ) , parent ) ;
return U_SUCCESS ;
2016-04-08 19:22:18 +08:00
}
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Get FlashMap block header
const PHOENIX_FLASH_MAP_HEADER * flashMapHeader = ( const PHOENIX_FLASH_MAP_HEADER * ) store . constData ( ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
UINT32 flashMapSize = sizeof ( PHOENIX_FLASH_MAP_HEADER ) + flashMapHeader - > NumEntries * sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ;
if ( dataSize < flashMapSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseFlashMapStoreHeader: FlashMap block size %Xh (%u) is greater than volume body size %Xh (%u) " ,
flashMapSize , flashMapSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( sizeof ( PHOENIX_FLASH_MAP_HEADER ) ) ;
UByteArray body = store . mid ( sizeof ( PHOENIX_FLASH_MAP_HEADER ) , flashMapSize - sizeof ( PHOENIX_FLASH_MAP_HEADER ) ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add info
2016-06-26 11:54:21 +08:00
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 ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : FlashMapStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-18 21:10:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseCmdbStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check store size
if ( dataSize < sizeof ( PHOENIX_CMDB_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseCmdbStoreHeader: volume body is too small even for CMDB store header " ) , parent ) ;
return U_SUCCESS ;
2016-04-15 02:36:59 +08:00
}
2016-04-18 21:10:07 +08:00
UINT32 cmdbSize = NVRAM_PHOENIX_CMDB_SIZE ;
if ( dataSize < cmdbSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseCmdbStoreHeader: CMDB store size %Xh (%u) is greater than volume body size %Xh (%u) " ,
cmdbSize , cmdbSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Get store header
const PHOENIX_CMDB_HEADER * cmdbHeader = ( const PHOENIX_CMDB_HEADER * ) store . constData ( ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( cmdbHeader - > TotalSize ) ;
UByteArray body = store . mid ( cmdbHeader - > TotalSize , cmdbSize - cmdbHeader - > TotalSize ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add info
2016-06-26 11:54:21 +08:00
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 ( ) ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : CmdbStore , 0 , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-18 21:10:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseSlicPubkeyHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check data size
if ( dataSize < sizeof ( OEM_ACTIVATION_PUBKEY ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseSlicPubkeyHeader: volume body is too small even for SLIC pubkey header " ) , parent ) ;
return U_SUCCESS ;
2016-04-15 02:36:59 +08:00
}
2016-04-18 21:10:07 +08:00
// Get SLIC pubkey header
const OEM_ACTIVATION_PUBKEY * pubkeyHeader = ( const OEM_ACTIVATION_PUBKEY * ) store . constData ( ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
if ( dataSize < pubkeyHeader - > Size ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseSlicPubkeyHeader: SLIC pubkey size %Xh (%u) is greater than volume body size %Xh (%u) " ,
pubkeyHeader - > Size , pubkeyHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( sizeof ( OEM_ACTIVATION_PUBKEY ) ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add info
2016-06-26 11:54:21 +08:00
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 "
2016-07-09 16:01:41 +08:00
" Key type: %02Xh \n Version: %02Xh \n Algorithm: %08Xh \n Magic: RSA1 \n Bit length: %08Xh \n Exponent: %08Xh " ,
2016-06-26 11:54:21 +08:00
pubkeyHeader - > Size , pubkeyHeader - > Size ,
header . size ( ) , header . size ( ) ,
pubkeyHeader - > KeyType ,
pubkeyHeader - > Version ,
pubkeyHeader - > Algorithm ,
pubkeyHeader - > BitLength ,
pubkeyHeader - > Exponent ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : SlicData , Subtypes : : PubkeySlicData , name , UString ( ) , info , header , UByteArray ( ) , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-18 21:10:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseSlicMarkerHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check data size
if ( dataSize < sizeof ( OEM_ACTIVATION_MARKER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseSlicMarkerHeader: volume body is too small even for SLIC marker header " ) , parent ) ;
return U_SUCCESS ;
2016-04-15 02:36:59 +08:00
}
2016-04-18 21:10:07 +08:00
// Get SLIC marker header
const OEM_ACTIVATION_MARKER * markerHeader = ( const OEM_ACTIVATION_MARKER * ) store . constData ( ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Check store size
if ( dataSize < markerHeader - > Size ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseSlicMarkerHeader: SLIC marker size %Xh (%u) is greater than volume body size %Xh (%u) " ,
markerHeader - > Size , markerHeader - > Size ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( sizeof ( OEM_ACTIVATION_MARKER ) ) ;
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Add info
2016-06-26 11:54:21 +08:00
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 "
2016-07-09 16:01:41 +08:00
" Version: %08Xh \n OEM ID: %s \n OEM table ID: %s \n Windows flag: WINDOWS \n SLIC version: %08Xh " ,
2016-06-26 11:54:21 +08:00
markerHeader - > Size , markerHeader - > Size ,
header . size ( ) , header . size ( ) ,
markerHeader - > Version ,
2016-07-05 22:18:55 +08:00
( const char * ) UString ( ( const char * ) & ( markerHeader - > OemId ) ) . left ( 6 ) . toLocal8Bit ( ) ,
( const char * ) UString ( ( const char * ) & ( markerHeader - > OemTableId ) ) . left ( 8 ) . toLocal8Bit ( ) ,
2016-06-26 11:54:21 +08:00
markerHeader - > SlicVersion ) ;
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : SlicData , Subtypes : : MarkerSlicData , name , UString ( ) , info , header , UByteArray ( ) , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-18 21:10:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseIntelMicrocodeHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
// Check data size
if ( dataSize < sizeof ( INTEL_MICROCODE_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseIntelMicrocodeHeader: volume body is too small even for Intel microcode header " ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
// Get Intel microcode header
const INTEL_MICROCODE_HEADER * ucodeHeader = ( const INTEL_MICROCODE_HEADER * ) store . constData ( ) ;
// Check store size
if ( dataSize < ucodeHeader - > TotalSize ) {
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseIntelMicrocodeHeader: Intel microcode size %Xh (%u) is greater than volume body size %Xh (%u) " ,
ucodeHeader - > TotalSize , ucodeHeader - > TotalSize ,
dataSize , dataSize ) , parent ) ;
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-04-15 02:36:59 +08:00
2016-04-18 21:10:07 +08:00
// Get parsing data
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( parent ) ;
2016-04-18 21:10:07 +08:00
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = store . left ( sizeof ( INTEL_MICROCODE_HEADER ) ) ;
UByteArray body = store . mid ( sizeof ( INTEL_MICROCODE_HEADER ) , ucodeHeader - > DataSize ) ;
2016-04-18 21:10:07 +08:00
//TODO: recalculate checksum
// Add info
2016-06-26 11:54:21 +08:00
UString name ( " Intel microcode " ) ;
UString info = usprintf ( " Revision: 1h \n Full size: %Xh (%u) \n Header size: %Xh (%u) \n Body size: %Xh (%u) \n "
" Date: %08Xh \n CPU signature: %08Xh \n Checksum: %08Xh \n Loader revision: %08Xh \n CPU flags: %08Xh " ,
ucodeHeader - > TotalSize , ucodeHeader - > TotalSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
ucodeHeader - > Date ,
ucodeHeader - > CpuSignature ,
ucodeHeader - > Checksum ,
ucodeHeader - > LoaderRevision ,
ucodeHeader - > CpuFlags ) ;
2016-04-18 21:10:07 +08:00
// Add correct offset
pdata . offset = parentOffset ;
// Add tree item
2016-06-26 11:54:21 +08:00
index = model - > addItem ( Types : : Microcode , Subtypes : : IntelMicrocode , name , UString ( ) , info , header , body , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , parent ) ;
2016-04-18 21:10:07 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-18 21:10:07 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseStoreHeader ( const UByteArray & store , const UINT32 parentOffset , const UModelIndex & parent , UModelIndex & index )
2016-04-18 21:10:07 +08:00
{
const UINT32 dataSize = ( const UINT32 ) store . size ( ) ;
const UINT32 * signature = ( const UINT32 * ) store . constData ( ) ;
// Check store size
if ( dataSize < sizeof ( UINT32 ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseStoreHeader: volume body is too small even for store signature " ) , parent ) ;
return U_SUCCESS ;
2016-04-15 02:36:59 +08:00
}
2016-03-28 21:03:32 +08:00
2016-04-18 21:10:07 +08:00
// Check signature and run parser function needed
// VSS/SVS store
if ( * signature = = NVRAM_VSS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_SVS_STORE_SIGNATURE )
return parseVssStoreHeader ( store , parentOffset , parent , index ) ;
// FTW store
else if ( * signature = = NVRAM_MAIN_STORE_VOLUME_GUID_DATA1 | | * signature = = EDKII_WORKING_BLOCK_SIGNATURE_GUID_DATA1 )
return parseFtwStoreHeader ( store , parentOffset , parent , index ) ;
// FDC store
else if ( * signature = = NVRAM_FDC_VOLUME_SIGNATURE )
return parseFdcStoreHeader ( store , parentOffset , parent , index ) ;
// Apple Fsys/Gaid store
else if ( * signature = = NVRAM_APPLE_FSYS_STORE_SIGNATURE | | * signature = = NVRAM_APPLE_GAID_STORE_SIGNATURE )
return parseFsysStoreHeader ( store , parentOffset , parent , index ) ;
// EVSA store
else if ( * ( signature + 1 ) = = NVRAM_EVSA_STORE_SIGNATURE )
return parseEvsaStoreHeader ( store , parentOffset , parent , index ) ;
// Phoenix SCT flash map
else if ( * signature = = NVRAM_PHOENIX_FLASH_MAP_SIGNATURE_PART1 )
return parseFlashMapStoreHeader ( store , parentOffset , parent , index ) ;
// Phoenix CMDB store
else if ( * signature = = NVRAM_PHOENIX_CMDB_HEADER_SIGNATURE )
return parseCmdbStoreHeader ( store , parentOffset , parent , index ) ;
// SLIC pubkey
else if ( * ( signature + 4 ) = = OEM_ACTIVATION_PUBKEY_MAGIC )
return parseSlicPubkeyHeader ( store , parentOffset , parent , index ) ;
// SLIC marker
else if ( * ( const UINT64 * ) ( store . constData ( ) + 26 ) = = OEM_ACTIVATION_MARKER_WINDOWS_FLAG )
return parseSlicMarkerHeader ( store , parentOffset , parent , index ) ;
// Intel microcode
// Must be checked after SLIC marker because of the same *signature values
else if ( * signature = = INTEL_MICROCODE_HEADER_VERSION )
return parseIntelMicrocodeHeader ( store , parentOffset , parent , index ) ;
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseStoreHeader: don't know how to parse a header with signature %08Xh " , * signature ) , parent ) ;
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseVssStoreBody ( const UModelIndex & index )
2016-03-28 21:03:32 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2016-03-28 21:03:32 +08:00
// Get parsing data for the current item
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-03-28 21:03:32 +08:00
UINT32 parentOffset = pdata . offset + model - > header ( index ) . size ( ) ;
2016-06-26 11:54:21 +08:00
const UByteArray data = model - > body ( index ) ;
2016-03-28 21:03:32 +08:00
// Check that the is enough space for variable header
const UINT32 dataSize = ( UINT32 ) data . size ( ) ;
if ( dataSize < sizeof ( VSS_VARIABLE_HEADER ) ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVssStoreBody: store body is too small even for VSS variable header " ) , index ) ;
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
UINT32 offset = 0 ;
// Parse all variables
while ( 1 ) {
bool isInvalid = false ;
bool isAuthenticated = false ;
bool isAppleCrc32 = false ;
UINT32 storedCrc32 = 0 ;
UINT32 calculatedCrc32 = 0 ;
UINT64 monotonicCounter = 0 ;
2016-03-30 00:10:30 +08:00
EFI_TIME timestamp = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2016-03-28 21:03:32 +08:00
UINT32 pubKeyIndex = 0 ;
UINT8 subtype = 0 ;
2016-06-26 11:54:21 +08:00
UString name ;
UString text ;
2016-03-28 21:03:32 +08:00
EFI_GUID * variableGuid ;
CHAR16 * variableName ;
2016-06-26 11:54:21 +08:00
UByteArray header ;
UByteArray body ;
2016-03-28 21:03:32 +08:00
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 ;
if ( unparsedSize > = sizeof ( VSS_VARIABLE_HEADER )
& & 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 ;
}
}
// Normal VSS variable
if ( ! isAuthenticated & & ! isAppleCrc32 ) {
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 ) ;
}
// There is also a case of authenticated Apple variables, but I haven't seen one yet
// Check variable state
if ( variableHeader - > State ! = NVRAM_VSS_VARIABLE_ADDED & & variableHeader - > State ! = NVRAM_VSS_VARIABLE_HEADER_VALID ) {
isInvalid = true ;
}
}
// 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
2016-06-26 11:54:21 +08:00
UByteArray padding = data . mid ( offset , unparsedSize ) ;
2016-03-28 21:03:32 +08:00
UINT8 type ;
if ( padding . count ( pdata . emptyByte ) = = padding . size ( ) ) {
// It's a free space
2016-06-26 11:54:21 +08:00
name = UString ( " Free space " ) ;
2016-03-28 21:03:32 +08:00
type = Types : : FreeSpace ;
subtype = 0 ;
}
else {
2016-04-07 14:23:37 +08:00
// Nothing is parsed yet, but the store is not empty
2016-03-28 21:03:32 +08:00
if ( ! offset ) {
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseVssStoreBody: store can't be parsed as VSS store " ) , index ) ;
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
// It's a padding
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
2016-03-28 21:03:32 +08:00
type = Types : : Padding ;
subtype = getPaddingType ( padding ) ;
}
// Get info
2016-06-26 11:54:21 +08:00
UString info = usprintf ( " Full size: %Xh (%u) " , padding . size ( ) , padding . size ( ) ) ;
2016-03-28 21:03:32 +08:00
// Construct parsing data
pdata . offset = parentOffset + offset ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( type , subtype , name , UString ( ) , info , UByteArray ( ) , padding , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-28 21:03:32 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-03-28 21:03:32 +08:00
}
2016-06-26 11:54:21 +08:00
UString info ;
2016-03-28 21:03:32 +08:00
2016-04-09 19:18:10 +08:00
// Rename invalid variables
2016-03-28 21:03:32 +08:00
if ( isInvalid ) {
2016-06-26 11:54:21 +08:00
name = UString ( " Invalid " ) ;
2016-03-28 21:03:32 +08:00
}
else { // Add GUID and text for valid variables
2016-06-26 11:54:21 +08:00
name = guidToUString ( * variableGuid ) ;
info + = UString ( " Variable GUID: " ) + name + UString ( " \n " ) ;
text = UString : : fromUtf16 ( variableName ) ;
2016-03-28 21:03:32 +08:00
}
2016-06-26 11:54:21 +08:00
// Add info
info + = usprintf ( " Full size: %Xh (%u) \n Header size %Xh (%u) \n Body size: %Xh (%u) \n State: %02Xh \n Attributes: %08Xh ( " ,
variableSize , variableSize ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
variableHeader - > State ,
2016-06-26 16:05:45 +08:00
variableHeader - > Attributes ) + vssAttributesToUString ( variableHeader - > Attributes ) + UString ( " ) " ) ;
2016-03-28 21:03:32 +08:00
// Set subtype and add related info
if ( isInvalid )
2016-04-17 07:25:44 +08:00
subtype = Subtypes : : InvalidVssEntry ;
2016-03-28 21:03:32 +08:00
else if ( isAuthenticated ) {
2016-04-17 07:25:44 +08:00
subtype = Subtypes : : AuthVssEntry ;
2016-07-09 16:08:32 +08:00
info + = usprintf ( " \n Monotonic counter: % " PRIX64 " h \n Timestamp: " , monotonicCounter ) + efiTimeToUString ( timestamp )
2016-06-26 11:54:21 +08:00
+ usprintf ( " \n PubKey index: %u " , pubKeyIndex ) ;
2016-03-28 21:03:32 +08:00
}
else if ( isAppleCrc32 ) {
2016-04-17 07:25:44 +08:00
subtype = Subtypes : : AppleVssEntry ;
2016-06-26 16:05:45 +08:00
info + = usprintf ( " \n Data checksum: %08Xh " , storedCrc32 ) +
( storedCrc32 ! = calculatedCrc32 ? usprintf ( " , invalid, should be %08Xh " , calculatedCrc32 ) : UString ( " , valid " ) ) ;
2016-03-28 21:03:32 +08:00
}
else
2016-04-17 07:25:44 +08:00
subtype = Subtypes : : StandardVssEntry ;
2016-03-28 21:03:32 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : VssEntry , subtype , name , text , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-03-28 21:03:32 +08:00
// Move to next variable
offset + = variableSize ;
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-03-30 00:10:30 +08:00
}
2016-04-05 06:47:34 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFsysStoreBody ( const UModelIndex & index )
2016-04-05 06:47:34 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2016-04-05 06:47:34 +08:00
// Get parsing data for the current item
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-04-05 06:47:34 +08:00
UINT32 parentOffset = pdata . offset + model - > header ( index ) . size ( ) ;
2016-06-26 11:54:21 +08:00
const UByteArray data = model - > body ( index ) ;
2016-04-05 06:47:34 +08:00
// Check that the is enough space for variable header
const UINT32 dataSize = ( UINT32 ) data . size ( ) ;
UINT32 offset = 0 ;
// Parse all variables
while ( 1 ) {
UINT32 unparsedSize = dataSize - offset ;
UINT32 variableSize = 0 ;
// Get nameSize and name of the variable
const UINT8 nameSize = * ( UINT8 * ) ( data . constData ( ) + offset ) ;
// Check sanity
if ( unparsedSize > = nameSize + sizeof ( UINT8 ) ) {
variableSize = nameSize + sizeof ( UINT8 ) ;
}
2016-06-26 11:54:21 +08:00
UByteArray name ;
2016-04-05 06:47:34 +08:00
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
2016-06-26 11:54:21 +08:00
UByteArray header = data . mid ( offset , sizeof ( UINT8 ) + nameSize ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , header . size ( ) , header . size ( ) ) ;
2016-04-05 06:47:34 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add EOF tree item
2016-07-05 23:22:03 +08:00
model - > addItem ( Types : : FsysEntry , 0 , UString ( " EOF " ) , UString ( ) , info , header , UByteArray ( ) , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-05 06:47:34 +08:00
// Add free space
offset + = header . size ( ) ;
unparsedSize = dataSize - offset ;
2016-06-26 11:54:21 +08:00
UByteArray body = data . mid ( offset ) ;
info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
2016-04-05 06:47:34 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add free space tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : FreeSpace , 0 , UString ( " Free space " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-05 06:47:34 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-05 06:47:34 +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
2016-06-26 11:54:21 +08:00
UByteArray body = data . mid ( offset ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
2016-04-05 06:47:34 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add free space tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( body ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-05 06:47:34 +08:00
// Show message
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFsysStoreBody: next variable appears too big, added as padding " ) , index ) ;
2016-04-05 06:47:34 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-05 06:47:34 +08:00
}
// Construct header and body
2016-06-26 11:54:21 +08:00
UByteArray header = data . mid ( offset , sizeof ( UINT8 ) + nameSize + sizeof ( UINT16 ) ) ;
UByteArray body = data . mid ( offset + sizeof ( UINT8 ) + nameSize + sizeof ( UINT16 ) , dataSize ) ;
2016-04-05 06:47:34 +08:00
// Add info
2016-06-26 11:54:21 +08:00
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 ( ) ) ;
2016-04-05 06:47:34 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add tree item
2016-07-07 13:57:45 +08:00
model - > addItem ( Types : : FsysEntry , 0 , UString ( name . constData ( ) ) , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-05 06:47:34 +08:00
// Move to next variable
offset + = variableSize ;
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-05 06:47:34 +08:00
}
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseEvsaStoreBody ( const UModelIndex & index )
2016-04-07 14:23:37 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2016-04-07 14:23:37 +08:00
// Get parsing data for the current item
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-04-07 14:23:37 +08:00
UINT32 parentOffset = pdata . offset + model - > header ( index ) . size ( ) ;
2016-06-26 11:54:21 +08:00
const UByteArray data = model - > body ( index ) ;
2016-04-07 14:23:37 +08:00
2016-04-18 21:10:07 +08:00
// Check that the is enough space for entry header
2016-04-07 14:23:37 +08:00
const UINT32 dataSize = ( UINT32 ) data . size ( ) ;
UINT32 offset = 0 ;
2016-04-08 19:22:18 +08:00
std : : map < UINT16 , EFI_GUID > guidMap ;
2016-06-26 11:54:21 +08:00
std : : map < UINT16 , UString > nameMap ;
2016-04-08 19:22:18 +08:00
2016-04-18 21:10:07 +08:00
// Parse all entries
2016-04-08 19:22:18 +08:00
UINT32 unparsedSize = dataSize ;
while ( unparsedSize ) {
2016-04-07 14:23:37 +08:00
UINT32 variableSize = 0 ;
2016-06-26 11:54:21 +08:00
UString name ;
UString info ;
UByteArray header ;
UByteArray body ;
2016-04-07 14:23:37 +08:00
UINT8 subtype ;
UINT8 calculated ;
const EVSA_ENTRY_HEADER * entryHeader = ( const EVSA_ENTRY_HEADER * ) ( data . constData ( ) + offset ) ;
2016-04-18 21:10:07 +08:00
// Check entry size
2016-04-07 14:23:37 +08:00
variableSize = sizeof ( EVSA_ENTRY_HEADER ) ;
if ( unparsedSize < variableSize | | unparsedSize < entryHeader - > Size ) {
2016-06-26 11:54:21 +08:00
UByteArray body = data . mid ( offset ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
2016-04-08 19:22:18 +08:00
2016-04-18 21:10:07 +08:00
// Checke type
2016-06-26 11:54:21 +08:00
UString name ( " Free space " ) ;
2016-04-15 02:36:59 +08:00
UINT8 type = Types : : FreeSpace ;
UINT8 subtype = 0 ;
if ( getPaddingType ( body ) = = Subtypes : : DataPadding ) {
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
2016-04-15 02:36:59 +08:00
type = Types : : Padding ;
subtype = Subtypes : : DataPadding ;
}
2016-04-08 19:22:18 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add free space tree item
2016-06-26 11:54:21 +08:00
UModelIndex itemIndex = model - > addItem ( type , subtype , name , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-15 02:36:59 +08:00
2016-04-08 19:22:18 +08:00
// Show message
2016-04-15 02:36:59 +08:00
if ( type = = Types : : Padding )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseEvsaStoreBody: variable parsing failed, rest of unparsed store added as padding " ) , itemIndex ) ;
2016-04-08 19:22:18 +08:00
break ;
2016-04-07 14:23:37 +08:00
}
variableSize = entryHeader - > Size ;
// Recalculate entry checksum
calculated = calculateChecksum8 ( ( ( const UINT8 * ) entryHeader ) + 2 , entryHeader - > Size - 2 ) ;
// GUID entry
if ( entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_GUID1 | |
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 ) ) ;
2016-04-13 07:35:18 +08:00
body = data . mid ( offset + sizeof ( EVSA_GUID_ENTRY ) , guidHeader - > Header . Size - sizeof ( EVSA_GUID_ENTRY ) ) ;
EFI_GUID guid = * ( EFI_GUID * ) body . constData ( ) ;
2016-06-26 11:54:21 +08:00
name = guidToUString ( guid ) ;
info = UString ( " GUID: " ) + 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 ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
guidHeader - > Header . Type ,
guidHeader - > Header . Checksum )
2016-06-26 16:05:45 +08:00
+ ( guidHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) )
2016-06-26 11:54:21 +08:00
+ usprintf ( " \n GuidId: %04Xh " , guidHeader - > GuidId ) ;
2016-04-07 14:23:37 +08:00
subtype = Subtypes : : GuidEvsaEntry ;
2016-04-13 07:35:18 +08:00
guidMap . insert ( std : : pair < UINT16 , EFI_GUID > ( guidHeader - > GuidId , guid ) ) ;
2016-04-07 14:23:37 +08:00
}
// 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 ) ) ;
2016-06-26 11:54:21 +08:00
name = UString : : fromUtf16 ( ( const CHAR16 * ) body . constData ( ) ) ;
info = UString ( " GUID: " ) + 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 ,
header . size ( ) , header . size ( ) ,
body . size ( ) , body . size ( ) ,
nameHeader - > Header . Type ,
nameHeader - > Header . Checksum )
2016-06-26 16:05:45 +08:00
+ ( nameHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) )
2016-06-26 11:54:21 +08:00
+ usprintf ( " \n VarId: %04Xh " , nameHeader - > VarId ) ;
2016-04-07 14:23:37 +08:00
subtype = Subtypes : : NameEvsaEntry ;
2016-06-26 11:54:21 +08:00
nameMap . insert ( std : : pair < UINT16 , UString > ( nameHeader - > VarId , name ) ) ;
2016-04-07 14:23:37 +08:00
}
// Data entry
else if ( entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA1 | |
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA2 | |
2016-04-15 02:36:59 +08:00
entryHeader - > Type = = NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID ) {
2016-04-07 14:23:37 +08:00
const EVSA_DATA_ENTRY * dataHeader = ( const EVSA_DATA_ENTRY * ) entryHeader ;
2016-04-15 02:36:59 +08:00
// Check for extended header
UINT32 headerSize = sizeof ( EVSA_DATA_ENTRY ) ;
UINT32 dataSize = dataHeader - > Header . Size - sizeof ( EVSA_DATA_ENTRY ) ;
2016-04-18 21:10:07 +08:00
if ( dataHeader - > Attributes & NVRAM_EVSA_DATA_EXTENDED_HEADER ) {
2016-04-15 02:36:59 +08:00
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 ) ;
2016-06-26 11:54:21 +08:00
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 )
2016-06-26 16:05:45 +08:00
+ ( dataHeader - > Header . Checksum ! = calculated ? usprintf ( " , invalid, should be %02Xh " , calculated ) : UString ( " , valid " ) )
2016-06-26 11:54:21 +08:00
+ usprintf ( " \n VarId: %04Xh \n GuidId: %04Xh \n Attributes: %08Xh ( " ,
dataHeader - > VarId ,
dataHeader - > GuidId ,
dataHeader - > Attributes )
2016-06-26 16:05:45 +08:00
+ evsaAttributesToUString ( dataHeader - > Attributes ) + UString ( " ) " ) ;
2016-04-07 14:23:37 +08:00
subtype = Subtypes : : DataEvsaEntry ;
}
2016-04-15 02:36:59 +08:00
// Unknown entry or free space
2016-04-07 14:23:37 +08:00
else {
2016-06-26 11:54:21 +08:00
UByteArray body = data . mid ( offset ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
2016-04-15 02:36:59 +08:00
// Check type
2016-06-26 11:54:21 +08:00
UString name ( " Free space " ) ;
2016-04-15 02:36:59 +08:00
UINT8 type = Types : : FreeSpace ;
UINT8 subtype = 0 ;
if ( getPaddingType ( body ) = = Subtypes : : DataPadding ) {
2016-06-26 11:54:21 +08:00
name = UString ( " Padding " ) ;
2016-04-15 02:36:59 +08:00
type = Types : : Padding ;
subtype = Subtypes : : DataPadding ;
}
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add free space tree item
2016-06-26 11:54:21 +08:00
UModelIndex itemIndex = model - > addItem ( type , subtype , name , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-15 02:36:59 +08:00
// Show message
if ( type = = Types : : Padding )
2016-06-26 11:54:21 +08:00
msg ( usprintf ( " parseEvsaStoreBody: unknown variable of type %02Xh found at offset %Xh, the rest of unparsed store added as padding " , entryHeader - > Type , offset ) , itemIndex ) ;
2016-04-15 02:36:59 +08:00
break ;
2016-04-07 14:23:37 +08:00
}
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : EvsaEntry , subtype , name , UString ( ) , info , header , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-07 14:23:37 +08:00
// Move to next variable
offset + = variableSize ;
2016-04-08 19:22:18 +08:00
unparsedSize = dataSize - offset ;
2016-04-07 14:23:37 +08:00
}
2016-04-08 19:22:18 +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 + + ) {
2016-06-26 11:54:21 +08:00
UModelIndex current = index . child ( i , 0 ) ;
2016-04-08 19:22:18 +08:00
if ( model - > subtype ( current ) = = Subtypes : : DataEvsaEntry ) {
2016-06-26 11:54:21 +08:00
UByteArray header = model - > header ( current ) ;
2016-04-08 19:22:18 +08:00
const EVSA_DATA_ENTRY * dataHeader = ( const EVSA_DATA_ENTRY * ) header . constData ( ) ;
2016-06-26 11:54:21 +08:00
UString guid ;
2016-04-08 19:22:18 +08:00
if ( guidMap . count ( dataHeader - > GuidId ) )
2016-06-26 11:54:21 +08:00
guid = guidToUString ( guidMap [ dataHeader - > GuidId ] ) ;
UString name ;
2016-04-08 19:22:18 +08:00
if ( nameMap . count ( dataHeader - > VarId ) )
name = nameMap [ dataHeader - > VarId ] ;
// Check for variable validity
if ( guid . isEmpty ( ) & & name . isEmpty ( ) ) { // Both name and guid aren't found
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
2016-06-26 11:54:21 +08:00
model - > setName ( current , UString ( " Invalid " ) ) ;
msg ( UString ( " parseEvsaStoreBody: data variable with invalid GuidId and invalid VarId " ) , current ) ;
2016-04-08 19:22:18 +08:00
}
else if ( guid . isEmpty ( ) ) { // Guid not found
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
2016-06-26 11:54:21 +08:00
model - > setName ( current , UString ( " Invalid " ) ) ;
msg ( UString ( " parseEvsaStoreBody: data variable with invalid GuidId " ) , current ) ;
2016-04-08 19:22:18 +08:00
}
else if ( name . isEmpty ( ) ) { // Name not found
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
2016-06-26 11:54:21 +08:00
model - > setName ( current , UString ( " Invalid " ) ) ;
msg ( UString ( " parseEvsaStoreBody: data variable with invalid VarId " ) , current ) ;
2016-04-08 19:22:18 +08:00
}
else { // Variable is OK, rename it
2016-04-15 02:36:59 +08:00
if ( dataHeader - > Header . Type = = NVRAM_EVSA_ENTRY_TYPE_DATA_INVALID ) {
model - > setSubtype ( current , Subtypes : : InvalidEvsaEntry ) ;
2016-06-26 11:54:21 +08:00
model - > setName ( current , UString ( " Invalid " ) ) ;
2016-04-15 02:36:59 +08:00
}
else {
model - > setName ( current , guid ) ;
}
2016-04-08 19:22:18 +08:00
model - > setText ( current , name ) ;
2016-06-26 16:05:45 +08:00
model - > addInfo ( current , UString ( " GUID: " ) + guid + UString ( " \n Name: " ) + name + UString ( " \n " ) , false ) ;
2016-04-08 19:22:18 +08:00
}
}
}
2016-04-07 14:23:37 +08:00
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-07 14:23:37 +08:00
}
2016-04-05 06:47:34 +08:00
2016-06-26 11:54:21 +08:00
USTATUS FfsParser : : parseFlashMapBody ( const UModelIndex & index )
2016-04-13 07:35:18 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
2016-06-26 11:54:21 +08:00
return U_INVALID_PARAMETER ;
2016-04-13 07:35:18 +08:00
// Get parsing data for the current item
2016-06-26 11:54:21 +08:00
PARSING_DATA pdata = parsingDataFromUModelIndex ( index ) ;
2016-04-13 07:35:18 +08:00
UINT32 parentOffset = pdata . offset + model - > header ( index ) . size ( ) ;
2016-06-26 11:54:21 +08:00
const UByteArray data = model - > body ( index ) ;
2016-04-13 07:35:18 +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
2016-06-26 11:54:21 +08:00
UByteArray body = data . mid ( offset ) ;
UString info = usprintf ( " Full size: %Xh (%u) " , body . size ( ) , body . size ( ) ) ;
2016-04-13 07:35:18 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
// Add free space tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : Padding , getPaddingType ( body ) , UString ( " Padding " ) , UString ( ) , info , UByteArray ( ) , body , UByteArray ( ) , false , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-13 07:35:18 +08:00
// Show message
if ( unparsedSize < entryHeader - > Size )
2016-06-26 11:54:21 +08:00
msg ( UString ( " parseFlashMapBody: next entry appears too big, added as padding " ) , index ) ;
2016-04-13 07:35:18 +08:00
break ;
}
2016-06-26 11:54:21 +08:00
UString name = guidToUString ( entryHeader - > Guid ) ;
2016-04-13 07:35:18 +08:00
// Construct header
2016-06-26 11:54:21 +08:00
UByteArray header = data . mid ( offset , sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ) ;
2016-04-13 07:35:18 +08:00
// Add info
2016-06-26 11:54:21 +08:00
UString info = UString ( " Entry GUID: " ) + name + 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-04-13 07:35:18 +08:00
// Add correct offset to parsing data
pdata . offset = parentOffset + offset ;
2016-04-15 02:36:59 +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 :
2016-04-17 07:25:44 +08:00
subtype = Subtypes : : DataFlashMapEntry ;
2016-04-15 02:36:59 +08:00
break ;
}
2016-04-13 07:35:18 +08:00
// Add tree item
2016-06-26 11:54:21 +08:00
model - > addItem ( Types : : FlashMapEntry , subtype , name , flashMapGuidToUString ( entryHeader - > Guid ) , info , header , UByteArray ( ) , UByteArray ( ) , true , parsingDataToUByteArray ( pdata ) , index ) ;
2016-04-13 07:35:18 +08:00
// Move to next variable
offset + = sizeof ( PHOENIX_FLASH_MAP_ENTRY ) ;
unparsedSize = dataSize - offset ;
}
2016-06-26 11:54:21 +08:00
return U_SUCCESS ;
2016-04-13 07:35:18 +08:00
}