2016-03-21 18:34:45 +08:00
/* fssbuilder.cpp
2015-04-02 16:04:37 +08:00
Copyright ( c ) 2015 , Nikolaj Schlej . All rights reserved .
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution . The full text of the license may be found at
http : //opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN " AS IS " BASIS ,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND , EITHER EXPRESS OR IMPLIED .
*/
2015-05-15 01:15:19 +08:00
# include "ffsbuilder.h"
2015-06-20 02:26:45 +08:00
STATUS FfsBuilder : : erase ( const QModelIndex & index , QByteArray & erased )
2015-05-15 01:15:19 +08:00
{
2015-06-20 02:26:45 +08:00
// Sanity check
if ( ! index . isValid ( ) )
return ERR_INVALID_PARAMETER ;
2015-07-07 21:57:41 +08:00
PARSING_DATA pdata = parsingDataFromQModelIndex ( index ) ;
2015-06-20 02:26:45 +08:00
erased . fill ( pdata . emptyByte ) ;
return ERR_SUCCESS ;
2015-05-15 01:15:19 +08:00
}
2016-03-01 15:20:44 +08:00
STATUS FfsBuilder : : build ( const QModelIndex & root , QByteArray & image )
{
// Sanity check
if ( ! root . isValid ( ) )
return ERR_INVALID_PARAMETER ;
if ( model - > type ( root ) = = Types : : Capsule ) {
return buildCapsule ( root , image ) ;
}
else if ( model - > type ( root ) = = Types : : Image ) {
if ( model - > subtype ( root ) = = Subtypes : : IntelImage ) {
return buildIntelImage ( root , image ) ;
}
2016-03-21 18:34:45 +08:00
else if ( model - > subtype ( root ) = = Subtypes : : UefiImage ) {
2016-03-01 15:20:44 +08:00
return buildRawArea ( root , image ) ;
}
}
return ERR_NOT_IMPLEMENTED ;
}
2015-05-15 01:15:19 +08:00
STATUS FfsBuilder : : buildCapsule ( const QModelIndex & index , QByteArray & capsule )
{
// Sanity check
if ( ! index . isValid ( ) )
return ERR_INVALID_PARAMETER ;
// No action required
if ( model - > action ( index ) = = Actions : : NoAction ) {
2015-12-30 06:39:43 +08:00
// Use original item data
2015-05-15 01:15:19 +08:00
capsule = model - > header ( index ) . append ( model - > body ( index ) ) ;
return ERR_SUCCESS ;
}
// Rebuild or Replace
else if ( model - > action ( index ) = = Actions : : Rebuild
| | model - > action ( index ) = = Actions : : Replace ) {
if ( model - > rowCount ( index ) ) {
// Clear the supplied QByteArray
capsule . clear ( ) ;
2015-12-30 06:39:43 +08:00
// Right now there is only one capsule image element supported
if ( model - > rowCount ( index ) ! = 1 ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildCapsule: building of capsules with %1 elements are not supported, original item data is used " ) . arg ( model - > rowCount ( index ) ) , index ) ;
2015-12-30 06:39:43 +08:00
// Use original item data
capsule = model - > header ( index ) . append ( model - > body ( index ) ) ;
return ERR_SUCCESS ;
2015-05-15 01:15:19 +08:00
}
2015-12-30 06:39:43 +08:00
// Build image
QModelIndex imageIndex = index . child ( 0 , 0 ) ;
QByteArray imageData ;
// Check image type
if ( model - > type ( imageIndex ) = = Types : : Image ) {
2016-03-01 16:52:25 +08:00
STATUS result = ERR_SUCCESS ;
2016-03-01 15:20:44 +08:00
if ( model - > subtype ( imageIndex ) = = Subtypes : : IntelImage ) {
2015-12-30 06:39:43 +08:00
result = buildIntelImage ( imageIndex , imageData ) ;
2016-03-01 15:20:44 +08:00
}
else if ( model - > subtype ( imageIndex ) = = Subtypes : : UefiImage ) {
2015-12-30 06:39:43 +08:00
result = buildRawArea ( imageIndex , imageData ) ;
2016-03-01 15:20:44 +08:00
}
else {
msg ( QObject : : tr ( " buildCapsule: unexpected item of subtype %1 can't be processed, original item data is used " ) . arg ( model - > subtype ( imageIndex ) ) , imageIndex ) ;
capsule . append ( model - > header ( imageIndex ) ) . append ( model - > body ( imageIndex ) ) ;
}
2015-12-30 06:39:43 +08:00
// Check build result
if ( result ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildCapsule: building of \" %1 \" failed with error \" %2 \" , original item data is used " ) . arg ( model - > name ( imageIndex ) ) . arg ( errorCodeToQString ( result ) ) , imageIndex ) ;
2015-12-30 06:39:43 +08:00
capsule . append ( model - > header ( imageIndex ) ) . append ( model - > body ( imageIndex ) ) ;
}
else
capsule . append ( imageData ) ;
}
else {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildCapsule: unexpected item of type %1 can't be processed, original item data is used " ) . arg ( model - > type ( imageIndex ) ) , imageIndex ) ;
2015-12-30 06:39:43 +08:00
capsule . append ( model - > header ( imageIndex ) ) . append ( model - > body ( imageIndex ) ) ;
}
2015-05-15 01:15:19 +08:00
// Check size of reconstructed capsule, it must remain the same
2015-06-20 02:26:45 +08:00
UINT32 newSize = capsule . size ( ) ;
UINT32 oldSize = model - > body ( index ) . size ( ) ;
if ( newSize > oldSize ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildCapsule: new capsule body size %1h (%2) is bigger than the original %3h (%4) " )
2015-06-20 02:26:45 +08:00
. hexarg ( newSize ) . arg ( newSize ) . hexarg ( oldSize ) . arg ( oldSize ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_INVALID_PARAMETER ;
}
2015-06-20 02:26:45 +08:00
else if ( newSize < oldSize ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildCapsule: new capsule body size %1h (%2) is smaller than the original %3h (%4) " )
2015-06-20 02:26:45 +08:00
. hexarg ( newSize ) . arg ( newSize ) . hexarg ( oldSize ) . arg ( oldSize ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_INVALID_PARAMETER ;
}
}
else
capsule = model - > body ( index ) ;
// Build successful, append header
capsule = model - > header ( index ) . append ( capsule ) ;
return ERR_SUCCESS ;
}
2015-06-20 02:26:45 +08:00
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildCapsule: unexpected action \" %1 \" " ) . arg ( actionTypeToQString ( model - > action ( index ) ) ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_NOT_IMPLEMENTED ;
}
2015-06-20 02:26:45 +08:00
STATUS FfsBuilder : : buildIntelImage ( const QModelIndex & index , QByteArray & intelImage )
2015-05-15 01:15:19 +08:00
{
2016-01-28 07:21:51 +08:00
// Sanity check
2015-06-20 02:26:45 +08:00
if ( ! index . isValid ( ) )
return ERR_SUCCESS ;
2015-12-30 06:39:43 +08:00
2015-06-20 02:26:45 +08:00
// No action
if ( model - > action ( index ) = = Actions : : NoAction ) {
intelImage = model - > header ( index ) . append ( model - > body ( index ) ) ;
return ERR_SUCCESS ;
}
2016-03-01 15:20:44 +08:00
// Rebuild
2015-06-20 02:26:45 +08:00
else if ( model - > action ( index ) = = Actions : : Rebuild ) {
intelImage . clear ( ) ;
2016-03-01 15:20:44 +08:00
2015-12-30 06:39:43 +08:00
// First child will always be descriptor for this type of image, and it's read only
2016-03-01 15:20:44 +08:00
intelImage . append ( model - > header ( index . child ( 0 , 0 ) ) . append ( model - > body ( index . child ( 0 , 0 ) ) ) ) ;
2015-12-30 06:39:43 +08:00
2016-03-01 15:20:44 +08:00
// Process other regions
2015-06-20 02:26:45 +08:00
for ( int i = 1 ; i < model - > rowCount ( index ) ; i + + ) {
2015-12-30 06:39:43 +08:00
QModelIndex currentRegion = index . child ( i , 0 ) ;
2016-03-01 15:20:44 +08:00
2015-12-30 06:39:43 +08:00
// Skip regions with Remove action
if ( model - > action ( currentRegion ) = = Actions : : Remove )
continue ;
// Check item type to be either region or padding
UINT8 type = model - > type ( currentRegion ) ;
if ( type = = Types : : Padding ) {
2016-03-01 15:20:44 +08:00
// Add padding as is
intelImage . append ( model - > header ( currentRegion ) . append ( model - > body ( currentRegion ) ) ) ;
2015-12-30 06:39:43 +08:00
continue ;
}
// Check region subtype
STATUS result ;
2016-03-01 15:20:44 +08:00
QByteArray region ;
2015-12-30 06:39:43 +08:00
UINT8 regionType = model - > subtype ( currentRegion ) ;
switch ( regionType ) {
2015-06-20 02:26:45 +08:00
case Subtypes : : BiosRegion :
case Subtypes : : PdrRegion :
2016-03-01 15:20:44 +08:00
result = buildRawArea ( currentRegion , region ) ;
2015-12-30 06:39:43 +08:00
if ( result ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildIntelImage: building of %1 region failed with error \" %2 \" , original item data is used " ) . arg ( regionTypeToQString ( regionType ) ) . arg ( errorCodeToQString ( result ) ) , currentRegion ) ;
region = model - > header ( currentRegion ) . append ( model - > body ( currentRegion ) ) ;
2015-12-30 06:39:43 +08:00
}
break ;
2016-03-01 15:20:44 +08:00
case Subtypes : : GbeRegion :
case Subtypes : : MeRegion :
2015-12-30 06:39:43 +08:00
case Subtypes : : EcRegion :
2016-03-01 15:20:44 +08:00
case Subtypes : : Reserved1Region :
case Subtypes : : Reserved2Region :
case Subtypes : : Reserved3Region :
case Subtypes : : Reserved4Region :
// Add region as is
region = model - > header ( currentRegion ) . append ( model - > body ( currentRegion ) ) ;
2015-06-20 02:26:45 +08:00
break ;
default :
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildIntelImage: don't know how to build region of unknown type " ) , index ) ;
2015-12-30 06:39:43 +08:00
return ERR_UNKNOWN_ITEM_TYPE ;
2015-06-20 02:26:45 +08:00
}
2015-12-30 06:39:43 +08:00
2016-03-01 15:20:44 +08:00
// Append the resulting region
intelImage . append ( region ) ;
2015-06-20 02:26:45 +08:00
}
2016-01-28 07:21:51 +08:00
2015-06-20 02:26:45 +08:00
// Check size of new image, it must be same as old one
UINT32 newSize = intelImage . size ( ) ;
UINT32 oldSize = model - > body ( index ) . size ( ) ;
if ( newSize > oldSize ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildIntelImage: new image size %1h (%2) is bigger than the original %3h (%4) " )
2015-06-20 02:26:45 +08:00
. hexarg ( newSize ) . arg ( newSize ) . hexarg ( oldSize ) . arg ( oldSize ) , index ) ;
return ERR_INVALID_PARAMETER ;
}
else if ( newSize < oldSize ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildIntelImage: new image size %1h (%2) is smaller than the original %3h (%4) " )
2015-06-20 02:26:45 +08:00
. hexarg ( newSize ) . arg ( newSize ) . hexarg ( oldSize ) . arg ( oldSize ) , index ) ;
return ERR_INVALID_PARAMETER ;
}
// Reconstruction successful
return ERR_SUCCESS ;
}
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildIntelImage: unexpected action \" %1 \" " ) . arg ( actionTypeToQString ( model - > action ( index ) ) ) , index ) ;
2015-06-20 02:26:45 +08:00
return ERR_NOT_IMPLEMENTED ;
}
STATUS FfsBuilder : : buildRawArea ( const QModelIndex & index , QByteArray & rawArea , bool addHeader )
2015-05-15 01:15:19 +08:00
{
// Sanity check
if ( ! index . isValid ( ) )
return ERR_INVALID_PARAMETER ;
// No action required
if ( model - > action ( index ) = = Actions : : NoAction ) {
rawArea = model - > header ( index ) . append ( model - > body ( index ) ) ;
return ERR_SUCCESS ;
}
// Rebuild or Replace
else if ( model - > action ( index ) = = Actions : : Rebuild
| | model - > action ( index ) = = Actions : : Replace ) {
if ( model - > rowCount ( index ) ) {
// Clear the supplied QByteArray
rawArea . clear ( ) ;
2015-06-20 02:26:45 +08:00
// Build children
2015-05-15 01:15:19 +08:00
for ( int i = 0 ; i < model - > rowCount ( index ) ; i + + ) {
2016-03-01 15:20:44 +08:00
STATUS result = ERR_SUCCESS ;
2015-05-15 01:15:19 +08:00
QModelIndex currentChild = index . child ( i , 0 ) ;
QByteArray currentData ;
// Check child type
if ( model - > type ( currentChild ) = = Types : : Volume ) {
result = buildVolume ( currentChild , currentData ) ;
}
else if ( model - > type ( currentChild ) = = Types : : Padding ) {
result = buildPadding ( currentChild , currentData ) ;
}
else {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildRawArea: unexpected item of type %1 can't be processed, original item data is used " ) . arg ( model - > type ( currentChild ) ) , currentChild ) ;
2015-05-15 01:15:19 +08:00
currentData = model - > header ( currentChild ) . append ( model - > body ( currentChild ) ) ;
}
// Check build result
if ( result ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildRawArea: building of %1 failed with error \" %2 \" , original item data is used " ) . arg ( model - > name ( currentChild ) ) . arg ( errorCodeToQString ( result ) ) , currentChild ) ;
2015-05-15 01:15:19 +08:00
currentData = model - > header ( currentChild ) . append ( model - > body ( currentChild ) ) ;
}
// Append current data
rawArea . append ( currentData ) ;
}
2015-06-20 02:26:45 +08:00
// Check size of new raw area, it must be same as original one
UINT32 newSize = rawArea . size ( ) ;
UINT32 oldSize = model - > body ( index ) . size ( ) ;
if ( newSize > oldSize ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildRawArea: new area size %1h (%2) is bigger than the original %3h (%4) " )
2015-06-20 02:26:45 +08:00
. hexarg ( newSize ) . arg ( newSize ) . hexarg ( oldSize ) . arg ( oldSize ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_INVALID_PARAMETER ;
}
2015-06-20 02:26:45 +08:00
else if ( newSize < oldSize ) {
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildRawArea: new area size %1h (%2) is smaller than the original %3h (%4) " )
2015-06-20 02:26:45 +08:00
. hexarg ( newSize ) . arg ( newSize ) . hexarg ( oldSize ) . arg ( oldSize ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_INVALID_PARAMETER ;
}
}
else
rawArea = model - > body ( index ) ;
2015-06-20 02:26:45 +08:00
// Build successful, add header if needed
if ( addHeader )
rawArea = model - > header ( index ) . append ( rawArea ) ;
2015-05-15 01:15:19 +08:00
return ERR_SUCCESS ;
}
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildRawArea: unexpected action \" %1 \" " ) . arg ( actionTypeToQString ( model - > action ( index ) ) ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_NOT_IMPLEMENTED ;
}
STATUS FfsBuilder : : buildPadding ( const QModelIndex & index , QByteArray & padding )
{
// Sanity check
if ( ! index . isValid ( ) )
return ERR_INVALID_PARAMETER ;
// No action required
if ( model - > action ( index ) = = Actions : : NoAction ) {
padding = model - > header ( index ) . append ( model - > body ( index ) ) ;
return ERR_SUCCESS ;
}
// Erase
else if ( model - > action ( index ) = = Actions : : Erase ) {
2015-06-20 02:26:45 +08:00
padding = model - > header ( index ) . append ( model - > body ( index ) ) ;
if ( erase ( index , padding ) )
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildPadding: erase failed, original item data is used " ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_SUCCESS ;
}
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildPadding: unexpected action \" %1 \" " ) . arg ( actionTypeToQString ( model - > action ( index ) ) ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_NOT_IMPLEMENTED ;
}
STATUS FfsBuilder : : buildNonUefiData ( const QModelIndex & index , QByteArray & data )
{
// Sanity check
if ( ! index . isValid ( ) )
return ERR_INVALID_PARAMETER ;
// No action required
if ( model - > action ( index ) = = Actions : : NoAction ) {
data = model - > header ( index ) . append ( model - > body ( index ) ) ;
return ERR_SUCCESS ;
}
// Erase
else if ( model - > action ( index ) = = Actions : : Erase ) {
2015-06-20 02:26:45 +08:00
data = model - > header ( index ) . append ( model - > body ( index ) ) ;
if ( erase ( index , data ) )
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildNonUefiData: erase failed, original item data is used " ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_SUCCESS ;
}
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildNonUefiData: unexpected action \" %1 \" " ) . arg ( actionTypeToQString ( model - > action ( index ) ) ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_NOT_IMPLEMENTED ;
}
STATUS FfsBuilder : : buildFreeSpace ( const QModelIndex & index , QByteArray & freeSpace )
{
// Sanity check
if ( ! index . isValid ( ) )
return ERR_INVALID_PARAMETER ;
// No action required
if ( model - > action ( index ) = = Actions : : NoAction ) {
freeSpace = model - > header ( index ) . append ( model - > body ( index ) ) ;
return ERR_SUCCESS ;
}
2016-03-01 15:20:44 +08:00
msg ( QObject : : tr ( " buildFreeSpace: unexpected action \" %1 \" " ) . arg ( actionTypeToQString ( model - > action ( index ) ) ) , index ) ;
2015-05-15 01:15:19 +08:00
return ERR_NOT_IMPLEMENTED ;
}
2015-06-20 02:26:45 +08:00
STATUS FfsBuilder : : buildVolume ( const QModelIndex & index , QByteArray & volume )
{
return ERR_NOT_IMPLEMENTED ;
}
2015-05-15 01:15:19 +08:00
STATUS FfsBuilder : : buildPadFile ( const QModelIndex & index , QByteArray & padFile )
{
return ERR_NOT_IMPLEMENTED ;
}
STATUS FfsBuilder : : buildFile ( const QModelIndex & index , QByteArray & file )
{
return ERR_NOT_IMPLEMENTED ;
}
STATUS FfsBuilder : : buildSection ( const QModelIndex & index , QByteArray & section )
{
return ERR_NOT_IMPLEMENTED ;
}
2016-03-01 15:20:44 +08:00