multiple fixes

This commit is contained in:
Cr4sh 2018-02-15 06:04:34 +03:00
parent 9d623c91e6
commit df95f0755c
8 changed files with 101 additions and 65 deletions

View file

@ -1,6 +1,6 @@
/* uefiextract_main.cpp /* uefiextract_main.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved. Copyright (c) 2018, LongSoft. All rights reserved.
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush"); a.setOrganizationName("LongSoft");
a.setOrganizationDomain("coderush.me"); a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIExtract"); a.setApplicationName("UEFIExtract");
UEFIExtract w; UEFIExtract w;
@ -52,7 +52,7 @@ int main(int argc, char *argv[])
} }
else { else {
std::cout << "UEFIExtract 0.4.4" << std::endl << std::endl << std::cout << "UEFIExtract 0.4.5" << std::endl << std::endl <<
"Usage: uefiextract imagefile [FileGUID_1 FileGUID_2 ... FileGUID_31]" << std::endl << "Usage: uefiextract imagefile [FileGUID_1 FileGUID_2 ... FileGUID_31]" << std::endl <<
"Returned value is a bit mask where 0 on position N meant File with GUID_N was found and unpacked, 1 otherwise" << std::endl; "Returned value is a bit mask where 0 on position N meant File with GUID_N was found and unpacked, 1 otherwise" << std::endl;
return 1; return 1;

View file

@ -34,6 +34,7 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F
# PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge # PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:75080FBAE80F89442430:EB080FBAE80F89442430 8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:75080FBAE80F89442430:EB080FBAE80F89442430
# PowerManagement | New SB-E/IB-E # PowerManagement | New SB-E/IB-E
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:0FBA6C24380F:0FBA7424380F 8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:0FBA6C24380F:0FBA7424380F
@ -48,5 +49,12 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:75080D00800000:EB080D00800000 299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:75080D00800000:EB080D00800000
# SiInit | Kaby Lake # SiInit | Kaby Lake
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:81E10080000033C1:9090909090909090 299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:81E10080000033C1:9090909090909090
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:81E10080000033C1:9090909090909090 299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:81E10080000033C1:9090909090909090
# SiInit | Skylake-X
D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 10 P:81E10080000033C1:9090909090909090
D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 12 P:81E10080000033C1:9090909090909090
# PpmInitialize | Skylake-X, Kaby Lake-X
3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBAE80F:0FBAE00F

View file

@ -1,6 +1,6 @@
/* uefipatch_main.cpp /* uefipatch_main.cpp
Copyright (c) 2017, LongSoft. All rights reserved. Copyright (c) 2018, LongSoft. All rights reserved.
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -31,7 +31,7 @@ int main(int argc, char *argv[])
result = w.patchFromFile(a.arguments().at(1)); result = w.patchFromFile(a.arguments().at(1));
} }
else { else {
std::cout << "UEFIPatch 0.3.11 - UEFI image file patching utility" << std::endl << std::endl << std::cout << "UEFIPatch 0.3.12 - UEFI image file patching utility" << std::endl << std::endl <<
"Usage: UEFIPatch image_file" << std::endl << std::endl << "Usage: UEFIPatch image_file" << std::endl << std::endl <<
"Patches will be read from patches.txt file\n"; "Patches will be read from patches.txt file\n";
return ERR_SUCCESS; return ERR_SUCCESS;

View file

@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication a(argc, argv); QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush"); a.setOrganizationName("LongSoft");
a.setOrganizationDomain("coderush.me"); a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIReplace"); a.setApplicationName("UEFIReplace");
UEFIReplace r; UEFIReplace r;
@ -28,7 +28,7 @@ int main(int argc, char *argv[])
QStringList args = a.arguments(); QStringList args = a.arguments();
if (args.length() < 5) { if (args.length() < 5) {
std::cout << "UEFIReplace 0.3.9 - UEFI image file replacement utility" << std::endl << std::endl << std::cout << "UEFIReplace 0.1.1 - UEFI image file replacement utility" << std::endl << std::endl <<
"Usage: UEFIReplace image_file guid section_type contents_file" << std::endl; "Usage: UEFIReplace image_file guid section_type contents_file" << std::endl;
return ERR_SUCCESS; return ERR_SUCCESS;
} }

View file

@ -871,7 +871,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
if (msgUnknownRevision) if (msgUnknownRevision)
msg(tr("parseBios: unknown volume revision %1").arg(volumeHeader->Revision), index); msg(tr("parseBios: unknown volume revision %1").arg(volumeHeader->Revision), index);
if (msgSizeMismach) if (msgSizeMismach)
msg(tr("parseBios: volume size stored in header %1h differs from calculated using block map %3h") msg(tr("parseBios: volume size stored in header %1h differs from calculated using block map %2h")
.hexarg(volumeSize).arg(bmVolumeSize), .hexarg(volumeSize).arg(bmVolumeSize),
index); index);
@ -1825,7 +1825,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
// Get TE info // Get TE info
bool msgInvalidSignature = false; bool msgInvalidSignature = false;
const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)body.constData(); const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)body.constData();
UINT32 teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
// Most EFI images today include teFixup in ImageBase value,
// which doesn't follow the UEFI spec, but is so popular that
// only a few images out of thousands are different
UINT32 teFixup = 0; //teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
if (teHeader->Signature != EFI_IMAGE_TE_SIGNATURE) { if (teHeader->Signature != EFI_IMAGE_TE_SIGNATURE) {
info += tr("\nSignature: %1h, invalid").hexarg2(teHeader->Signature, 4); info += tr("\nSignature: %1h, invalid").hexarg2(teHeader->Signature, 4);
msgInvalidSignature = true; msgInvalidSignature = true;
@ -3543,18 +3547,21 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon
volumeSize = newSize; volumeSize = newSize;
} }
} }
// Check new volume size
if ((UINT32)(header.size() + reconstructed.size()) > volumeSize)
{
msg(tr("reconstructVolume: volume grow failed"), index);
return ERR_INVALID_VOLUME;
}
} }
// Use current volume body // Use current volume body
else else {
reconstructed = model->body(index); reconstructed = model->body(index);
// BUGBUG: volume size may change during this operation for volumes withour files in them
// but such volumes are fairly rare
}
// Check new volume size
if ((UINT32)(header.size() + reconstructed.size()) != volumeSize) {
msg(tr("reconstructVolume: volume size can't be changed"), index);
return ERR_INVALID_VOLUME;
}
// Reconstruction successful // Reconstruction successful
reconstructed = header.append(reconstructed); reconstructed = header.append(reconstructed);
@ -3574,6 +3581,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon
volumeHeader->Checksum = calculateChecksum16((const UINT16*)volumeHeader, volumeHeader->HeaderLength); volumeHeader->Checksum = calculateChecksum16((const UINT16*)volumeHeader, volumeHeader->HeaderLength);
} }
} }
// Store new free space offset, if needed // Store new free space offset, if needed
if (model->text(index).contains("AppleFSO ")) { if (model->text(index).contains("AppleFSO ")) {
// Get current CRC32 value from volume header // Get current CRC32 value from volume header
@ -3716,30 +3724,31 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision,
offset += section.size(); offset += section.size();
} }
} }
// Correct file size
UINT8 tailSize = (revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) ? sizeof(UINT16) : 0;
if (revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
uint32ToUint24(EFI_SECTION2_IS_USED, fileHeader->Size);
EFI_FFS_FILE_HEADER2* fileHeader2 = (EFI_FFS_FILE_HEADER2*) fileHeader;
fileHeader2->ExtendedSize = sizeof(EFI_FFS_FILE_HEADER2) + reconstructed.size() + tailSize;
} else {
if (sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize > 0xFFFFFF) {
msg(tr("reconstructFile: resulting file size is too big"), index);
return ERR_INVALID_FILE;
}
uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize, fileHeader->Size);
}
// Recalculate header checksum
fileHeader->IntegrityCheck.Checksum.Header = 0;
fileHeader->IntegrityCheck.Checksum.File = 0;
fileHeader->IntegrityCheck.Checksum.Header = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->State);
} }
// Use current file body // Use current file body
else else
reconstructed = model->body(index); reconstructed = model->body(index);
// Correct file size
UINT8 tailSize = (revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) ? sizeof(UINT16) : 0;
if (revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) {
uint32ToUint24(EFI_SECTION2_IS_USED, fileHeader->Size);
EFI_FFS_FILE_HEADER2* fileHeader2 = (EFI_FFS_FILE_HEADER2*)fileHeader;
fileHeader2->ExtendedSize = sizeof(EFI_FFS_FILE_HEADER2) + reconstructed.size() + tailSize;
}
else {
if (sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize > 0xFFFFFF) {
msg(tr("reconstructFile: resulting file size is too big"), index);
return ERR_INVALID_FILE;
}
uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize, fileHeader->Size);
}
// Recalculate header checksum
fileHeader->IntegrityCheck.Checksum.Header = 0;
fileHeader->IntegrityCheck.Checksum.File = 0;
fileHeader->IntegrityCheck.Checksum.Header = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->State);
// Recalculate data checksum, if needed // Recalculate data checksum, if needed
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((const UINT8*)reconstructed.constData(), reconstructed.size()); fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((const UINT8*)reconstructed.constData(), reconstructed.size());
@ -3755,6 +3764,7 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision,
UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File; UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File;
reconstructed.append(ht).append(ft); reconstructed.append(ht).append(ft);
} }
// Set file state // Set file state
state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION; state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
if (erasePolarity == ERASE_POLARITY_TRUE) if (erasePolarity == ERASE_POLARITY_TRUE)
@ -3792,8 +3802,8 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
model->action(index) == Actions::Rebase) { model->action(index) == Actions::Rebase) {
QByteArray header = model->header(index); QByteArray header = model->header(index);
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)header.data(); EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)header.data();
bool extended = false; bool extended = false;
if(uint24ToUint32(commonHeader->Size) == 0xFFFFFF) { if (uint24ToUint32(commonHeader->Size) == 0xFFFFFF) {
extended = true; extended = true;
} }
@ -3894,34 +3904,44 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
.arg(model->subtype(index)), index); .arg(model->subtype(index)), index);
return ERR_INVALID_SECTION; return ERR_INVALID_SECTION;
} }
// Correct section size
if (extended) {
EFI_COMMON_SECTION_HEADER2 * extHeader = (EFI_COMMON_SECTION_HEADER2*) commonHeader;
extHeader->ExtendedSize = header.size() + reconstructed.size();
uint32ToUint24(0xFFFFFF, commonHeader->Size);
} else {
uint32ToUint24(header.size() + reconstructed.size(), commonHeader->Size);
}
} }
// Leaf section // Leaf section
else else {
reconstructed = model->body(index); reconstructed = model->body(index);
}
// Correct section size
if (extended) {
EFI_COMMON_SECTION_HEADER2 * extHeader = (EFI_COMMON_SECTION_HEADER2*)commonHeader;
extHeader->ExtendedSize = header.size() + reconstructed.size();
uint32ToUint24(0xFFFFFF, commonHeader->Size);
}
else {
uint32ToUint24(header.size() + reconstructed.size(), commonHeader->Size);
}
// Rebase PE32 or TE image, if needed // Rebase PE32 or TE image, if needed
if ((model->subtype(index) == EFI_SECTION_PE32 || model->subtype(index) == EFI_SECTION_TE) && if ((model->subtype(index) == EFI_SECTION_PE32 || model->subtype(index) == EFI_SECTION_TE) &&
(model->subtype(index.parent()) == EFI_FV_FILETYPE_PEI_CORE || (model->subtype(index.parent()) == EFI_FV_FILETYPE_PEI_CORE ||
model->subtype(index.parent()) == EFI_FV_FILETYPE_PEIM || model->subtype(index.parent()) == EFI_FV_FILETYPE_PEIM ||
model->subtype(index.parent()) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { model->subtype(index.parent()) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) {
UINT16 teFixup = 0; UINT16 teFixup = 0;
//TODO: add proper handling
/*if (model->subtype(index) == EFI_SECTION_TE) { // Most EFI images today include teFixup in ImageBase value,
const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)model->body(index).constData(); // which doesn't follow the UEFI spec, but is so popular that
teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER); // only a few images out of thousands are different
}*/
// There are some heuristics possible here to detect if an entry point is calculated correctly
// or needs a proper fixup, but new_engine already have them and it's better to work on proper
// builder for it than trying to fix this mess
//if (model->subtype(index) == EFI_SECTION_TE) {
// const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)model->body(index).constData();
// teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER);
//
if (base) { if (base) {
result = rebase(reconstructed, base - teFixup + header.size()); result = rebase(reconstructed, base - teFixup + header.size(), index);
if (result) { if (result) {
msg(tr("reconstructSection: executable section rebase failed"), index); msg(tr("reconstructSection: executable section rebase failed"), index);
return result; return result;
@ -4217,7 +4237,7 @@ UINT8 FfsEngine::findTextPattern(const QModelIndex & index, const QString & patt
return ERR_SUCCESS; return ERR_SUCCESS;
} }
UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base) UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base, const QModelIndex & index)
{ {
UINT32 delta; // Difference between old and new base addresses UINT32 delta; // Difference between old and new base addresses
UINT32 relocOffset; // Offset of relocation region UINT32 relocOffset; // Offset of relocation region
@ -4290,6 +4310,9 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base)
relocSize = teHeader->DataDirectory[EFI_IMAGE_TE_DIRECTORY_ENTRY_BASERELOC].Size; relocSize = teHeader->DataDirectory[EFI_IMAGE_TE_DIRECTORY_ENTRY_BASERELOC].Size;
// Set new base // Set new base
teHeader->ImageBase = base; teHeader->ImageBase = base;
// Warn the user about possible outcome of incorrect rebase of TE image
msg(tr("rebase: can't determine if TE image base is adjusted or not, rebased TE image may stop working"), index);
} }
else else
return ERR_UNKNOWN_IMAGE_TYPE; return ERR_UNKNOWN_IMAGE_TYPE;
@ -4319,6 +4342,12 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base)
// Run this relocation record // Run this relocation record
while (Reloc < RelocEnd) { while (Reloc < RelocEnd) {
if (*Reloc == 0x0000) {
// Skip last emtpy reloc entry
Reloc += 1;
continue;
}
UINT32 RelocLocation = RelocBase->VirtualAddress - teFixup + (*Reloc & 0x0FFF); UINT32 RelocLocation = RelocBase->VirtualAddress - teFixup + (*Reloc & 0x0FFF);
if ((UINT32)file.size() < RelocLocation) if ((UINT32)file.size() < RelocLocation)
return ERR_BAD_RELOCATION_ENTRY; return ERR_BAD_RELOCATION_ENTRY;

View file

@ -84,7 +84,6 @@ public:
UINT8 reconstructIntelImage(const QModelIndex& index, QByteArray & reconstructed); UINT8 reconstructIntelImage(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed, bool includeHeader = true); UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed, bool includeHeader = true);
UINT8 reconstructPadding(const QModelIndex& index, QByteArray & reconstructed); UINT8 reconstructPadding(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructBios(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructVolume(const QModelIndex& index, QByteArray & reconstructed); UINT8 reconstructVolume(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructFile(const QModelIndex& index, const UINT8 revision, const UINT8 erasePolarity, const UINT32 base, QByteArray& reconstructed); UINT8 reconstructFile(const QModelIndex& index, const UINT8 revision, const UINT8 erasePolarity, const UINT32 base, QByteArray& reconstructed);
UINT8 reconstructSection(const QModelIndex& index, const UINT32 base, QByteArray & reconstructed); UINT8 reconstructSection(const QModelIndex& index, const UINT32 base, QByteArray & reconstructed);
@ -126,7 +125,7 @@ private:
// Rebase routines // Rebase routines
UINT8 getBase(const QByteArray& file, UINT32& base); UINT8 getBase(const QByteArray& file, UINT32& base);
UINT8 getEntryPoint(const QByteArray& file, UINT32 &entryPoint); UINT8 getEntryPoint(const QByteArray& file, UINT32 &entryPoint);
UINT8 rebase(QByteArray & executable, const UINT32 base); UINT8 rebase(QByteArray & executable, const UINT32 base, const QModelIndex & index);
void rebasePeiFiles(const QModelIndex & index); void rebasePeiFiles(const QModelIndex & index);
// Patch routines // Patch routines

View file

@ -69,7 +69,7 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
case Types::Image: case Types::Image:
if (subtype == Subtypes::IntelImage) if (subtype == Subtypes::IntelImage)
return QObject::tr("Intel"); return QObject::tr("Intel");
else if (Subtypes::UefiImage) else if (subtype == Subtypes::UefiImage)
return QObject::tr("UEFI"); return QObject::tr("UEFI");
else else
return QObject::tr("Unknown subtype"); return QObject::tr("Unknown subtype");
@ -153,4 +153,4 @@ QString actionTypeToQString(const UINT8 action)
default: default:
return QObject::tr("Unknown"); return QObject::tr("Unknown");
} }
} }

View file

@ -17,7 +17,7 @@
UEFITool::UEFITool(QWidget *parent) : UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::UEFITool), ui(new Ui::UEFITool),
version(tr("0.22.2")) version(tr("0.22.3"))
{ {
clipboard = QApplication::clipboard(); clipboard = QApplication::clipboard();