2013-10-08 15:07:03 +08:00
|
|
|
/* ffs.cpp
|
|
|
|
|
2015-01-31 22:00:00 +08:00
|
|
|
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
|
2013-10-08 15:07:03 +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.
|
|
|
|
*/
|
|
|
|
|
2013-10-15 23:19:15 +08:00
|
|
|
#include <QObject>
|
2013-10-08 15:07:03 +08:00
|
|
|
#include "ffs.h"
|
|
|
|
|
2015-01-31 22:46:17 +08:00
|
|
|
const QVector<QByteArray> FFSv2Volumes =
|
|
|
|
QVector<QByteArray>()
|
|
|
|
<< EFI_FIRMWARE_FILE_SYSTEM_GUID
|
|
|
|
<< EFI_FIRMWARE_FILE_SYSTEM2_GUID
|
|
|
|
<< EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM_GUID
|
|
|
|
<< EFI_APPLE_BOOT_VOLUME_FILE_SYSTEM2_GUID
|
|
|
|
<< EFI_INTEL_FILE_SYSTEM_GUID
|
|
|
|
<< EFI_INTEL_FILE_SYSTEM2_GUID
|
|
|
|
<< EFI_SONY_FILE_SYSTEM_GUID;
|
|
|
|
|
2014-07-25 07:59:51 +08:00
|
|
|
const UINT8 ffsAlignmentTable[] =
|
|
|
|
{ 0, 4, 7, 9, 10, 12, 15, 16 };
|
2013-10-08 15:07:03 +08:00
|
|
|
|
2015-01-31 22:00:00 +08:00
|
|
|
UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize)
|
2013-10-08 15:07:03 +08:00
|
|
|
{
|
2014-07-25 07:59:51 +08:00
|
|
|
if (!buffer)
|
2013-12-05 04:27:12 +08:00
|
|
|
return 0;
|
2014-07-25 07:59:51 +08:00
|
|
|
|
2013-12-05 04:27:12 +08:00
|
|
|
UINT8 counter = 0;
|
2013-11-19 03:11:22 +08:00
|
|
|
|
2014-07-25 07:59:51 +08:00
|
|
|
while (bufferSize--)
|
2013-10-08 15:07:03 +08:00
|
|
|
counter += buffer[bufferSize];
|
2013-11-19 03:11:22 +08:00
|
|
|
|
2014-07-25 07:59:51 +08:00
|
|
|
return (UINT8)0x100 - counter;
|
2013-10-08 15:07:03 +08:00
|
|
|
}
|
|
|
|
|
2015-01-31 22:00:00 +08:00
|
|
|
UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize)
|
2013-10-08 15:07:03 +08:00
|
|
|
{
|
2014-07-25 07:59:51 +08:00
|
|
|
if (!buffer)
|
2013-12-05 04:27:12 +08:00
|
|
|
return 0;
|
2013-11-19 03:11:22 +08:00
|
|
|
|
2013-12-05 04:27:12 +08:00
|
|
|
UINT16 counter = 0;
|
|
|
|
UINT32 index = 0;
|
2013-11-19 03:11:22 +08:00
|
|
|
|
2013-12-05 04:27:12 +08:00
|
|
|
bufferSize /= sizeof(UINT16);
|
2013-11-19 03:11:22 +08:00
|
|
|
|
2013-12-05 04:27:12 +08:00
|
|
|
for (; index < bufferSize; index++) {
|
2014-07-25 07:59:51 +08:00
|
|
|
counter = (UINT16)(counter + buffer[index]);
|
2013-12-05 04:27:12 +08:00
|
|
|
}
|
2013-11-19 03:11:22 +08:00
|
|
|
|
2014-07-25 07:59:51 +08:00
|
|
|
return (UINT16)0x10000 - counter;
|
2013-10-08 15:07:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID uint32ToUint24(UINT32 size, UINT8* ffsSize)
|
|
|
|
{
|
2014-07-25 07:59:51 +08:00
|
|
|
ffsSize[2] = (UINT8)((size) >> 16);
|
|
|
|
ffsSize[1] = (UINT8)((size) >> 8);
|
|
|
|
ffsSize[0] = (UINT8)((size));
|
2013-10-08 15:07:03 +08:00
|
|
|
}
|
|
|
|
|
2015-01-31 22:00:00 +08:00
|
|
|
UINT32 uint24ToUint32(const UINT8* ffsSize)
|
2013-10-08 15:07:03 +08:00
|
|
|
{
|
2014-01-12 07:02:54 +08:00
|
|
|
return (ffsSize[2] << 16) +
|
2014-07-25 07:59:51 +08:00
|
|
|
(ffsSize[1] << 8) +
|
|
|
|
ffsSize[0];
|
2013-10-08 15:07:03 +08:00
|
|
|
}
|
|
|
|
|
2014-01-24 20:29:21 +08:00
|
|
|
QString guidToQString(const EFI_GUID& guid)
|
2013-10-08 15:07:03 +08:00
|
|
|
{
|
2014-07-25 07:59:51 +08:00
|
|
|
QByteArray baGuid = QByteArray::fromRawData((const char*)guid.Data, sizeof(EFI_GUID));
|
2015-01-31 22:00:00 +08:00
|
|
|
const UINT32 i32 = *(const UINT32*)baGuid.left(4).constData();
|
|
|
|
const UINT16 i16_0 = *(const UINT16*)baGuid.mid(4, 2).constData();
|
|
|
|
const UINT16 i16_1 = *(const UINT16*)baGuid.mid(6, 2).constData();
|
|
|
|
const UINT8 i8_0 = *(const UINT8*)baGuid.mid(8, 1).constData();
|
|
|
|
const UINT8 i8_1 = *(const UINT8*)baGuid.mid(9, 1).constData();
|
|
|
|
const UINT8 i8_2 = *(const UINT8*)baGuid.mid(10, 1).constData();
|
|
|
|
const UINT8 i8_3 = *(const UINT8*)baGuid.mid(11, 1).constData();
|
|
|
|
const UINT8 i8_4 = *(const UINT8*)baGuid.mid(12, 1).constData();
|
|
|
|
const UINT8 i8_5 = *(const UINT8*)baGuid.mid(13, 1).constData();
|
|
|
|
const UINT8 i8_6 = *(const UINT8*)baGuid.mid(14, 1).constData();
|
|
|
|
const UINT8 i8_7 = *(const UINT8*)baGuid.mid(15, 1).constData();
|
2014-07-25 07:59:51 +08:00
|
|
|
|
2013-10-08 15:07:03 +08:00
|
|
|
return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11")
|
2014-07-25 07:59:51 +08:00
|
|
|
.arg(i32, 8, 16, QChar('0'))
|
|
|
|
.arg(i16_0, 4, 16, QChar('0'))
|
|
|
|
.arg(i16_1, 4, 16, QChar('0'))
|
|
|
|
.arg(i8_0, 2, 16, QChar('0'))
|
|
|
|
.arg(i8_1, 2, 16, QChar('0'))
|
|
|
|
.arg(i8_2, 2, 16, QChar('0'))
|
|
|
|
.arg(i8_3, 2, 16, QChar('0'))
|
|
|
|
.arg(i8_4, 2, 16, QChar('0'))
|
|
|
|
.arg(i8_5, 2, 16, QChar('0'))
|
|
|
|
.arg(i8_6, 2, 16, QChar('0'))
|
|
|
|
.arg(i8_7, 2, 16, QChar('0')).toUpper();
|
2013-10-08 15:07:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
QString fileTypeToQString(const UINT8 type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
2015-01-31 22:00:00 +08:00
|
|
|
case EFI_FV_FILETYPE_RAW: return QObject::tr("Raw");
|
|
|
|
case EFI_FV_FILETYPE_FREEFORM: return QObject::tr("Freeform");
|
|
|
|
case EFI_FV_FILETYPE_SECURITY_CORE: return QObject::tr("SEC core");
|
|
|
|
case EFI_FV_FILETYPE_PEI_CORE: return QObject::tr("PEI core");
|
|
|
|
case EFI_FV_FILETYPE_DXE_CORE: return QObject::tr("DXE core");
|
|
|
|
case EFI_FV_FILETYPE_PEIM: return QObject::tr("PEI module");
|
|
|
|
case EFI_FV_FILETYPE_DRIVER: return QObject::tr("DXE driver");
|
|
|
|
case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: return QObject::tr("Combined PEI/DXE");
|
|
|
|
case EFI_FV_FILETYPE_APPLICATION: return QObject::tr("Application");
|
|
|
|
case EFI_FV_FILETYPE_SMM: return QObject::tr("SMM module");
|
|
|
|
case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: return QObject::tr("Volume image");
|
|
|
|
case EFI_FV_FILETYPE_COMBINED_SMM_DXE: return QObject::tr("Combined SMM/DXE");
|
|
|
|
case EFI_FV_FILETYPE_SMM_CORE: return QObject::tr("SMM core");
|
|
|
|
case EFI_FV_FILETYPE_PAD: return QObject::tr("Pad");
|
|
|
|
default: return QObject::tr("Unknown");
|
2013-10-08 15:07:03 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
QString sectionTypeToQString(const UINT8 type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
2015-01-31 22:00:00 +08:00
|
|
|
case EFI_SECTION_COMPRESSION: return QObject::tr("Compressed");
|
|
|
|
case EFI_SECTION_GUID_DEFINED: return QObject::tr("GUID defined");
|
|
|
|
case EFI_SECTION_DISPOSABLE: return QObject::tr("Disposable");
|
|
|
|
case EFI_SECTION_PE32: return QObject::tr("PE32(+) image");
|
|
|
|
case EFI_SECTION_PIC: return QObject::tr("PIC image");
|
|
|
|
case EFI_SECTION_TE: return QObject::tr("TE image");
|
|
|
|
case EFI_SECTION_DXE_DEPEX: return QObject::tr("DXE dependency");
|
|
|
|
case EFI_SECTION_VERSION: return QObject::tr("Version");
|
|
|
|
case EFI_SECTION_USER_INTERFACE: return QObject::tr("User interface");
|
|
|
|
case EFI_SECTION_COMPATIBILITY16: return QObject::tr("16-bit image");
|
|
|
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return QObject::tr("Volume image");
|
|
|
|
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return QObject::tr("Freeform subtype GUID");
|
|
|
|
case EFI_SECTION_RAW: return QObject::tr("Raw");
|
|
|
|
case EFI_SECTION_PEI_DEPEX: return QObject::tr("PEI dependency");
|
|
|
|
case EFI_SECTION_SMM_DEPEX: return QObject::tr("SMM dependency");
|
|
|
|
case HP_SECTION_POSTCODE: return QObject::tr("HP postcode");
|
|
|
|
case SCT_SECTION_POSTCODE: return QObject::tr("SCT postcode");
|
|
|
|
default: return QObject::tr("Unknown");
|
2013-10-08 15:07:03 +08:00
|
|
|
}
|
2013-10-09 16:30:58 +08:00
|
|
|
}
|
|
|
|
|
2015-01-31 22:00:00 +08:00
|
|
|
UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header)
|
2013-10-09 16:30:58 +08:00
|
|
|
{
|
2014-06-19 11:45:20 +08:00
|
|
|
if (!header)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (header->Type)
|
2013-10-09 16:30:58 +08:00
|
|
|
{
|
2014-06-19 11:45:20 +08:00
|
|
|
case EFI_SECTION_GUID_DEFINED: {
|
2015-01-31 22:00:00 +08:00
|
|
|
const EFI_GUID_DEFINED_SECTION* gdsHeader = (const EFI_GUID_DEFINED_SECTION*)header;
|
2014-12-11 02:18:05 +08:00
|
|
|
return gdsHeader->DataOffset; }
|
2015-01-31 22:00:00 +08:00
|
|
|
case EFI_SECTION_COMPRESSION: return sizeof(EFI_COMPRESSION_SECTION);
|
|
|
|
case EFI_SECTION_DISPOSABLE: return sizeof(EFI_DISPOSABLE_SECTION);
|
|
|
|
case EFI_SECTION_PE32: return sizeof(EFI_PE32_SECTION);
|
|
|
|
case EFI_SECTION_PIC: return sizeof(EFI_PIC_SECTION);
|
|
|
|
case EFI_SECTION_TE: return sizeof(EFI_TE_SECTION);
|
|
|
|
case EFI_SECTION_DXE_DEPEX: return sizeof(EFI_DXE_DEPEX_SECTION);
|
|
|
|
case EFI_SECTION_VERSION: return sizeof(EFI_VERSION_SECTION);
|
|
|
|
case EFI_SECTION_USER_INTERFACE: return sizeof(EFI_USER_INTERFACE_SECTION);
|
|
|
|
case EFI_SECTION_COMPATIBILITY16: return sizeof(EFI_COMPATIBILITY16_SECTION);
|
|
|
|
case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: return sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION);
|
|
|
|
case EFI_SECTION_FREEFORM_SUBTYPE_GUID: return sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION);
|
|
|
|
case EFI_SECTION_RAW: return sizeof(EFI_RAW_SECTION);
|
|
|
|
case EFI_SECTION_PEI_DEPEX: return sizeof(EFI_PEI_DEPEX_SECTION);
|
|
|
|
case EFI_SECTION_SMM_DEPEX: return sizeof(EFI_SMM_DEPEX_SECTION);
|
|
|
|
case HP_SECTION_POSTCODE: return sizeof(POSTCODE_SECTION);
|
|
|
|
case SCT_SECTION_POSTCODE: return sizeof(POSTCODE_SECTION);
|
|
|
|
default: return sizeof(EFI_COMMON_SECTION_HEADER);
|
2013-10-09 16:30:58 +08:00
|
|
|
}
|
2015-01-31 22:46:17 +08:00
|
|
|
}
|