Skip to content

Commit

Permalink
multiple fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr4sh committed Feb 15, 2018
1 parent 9d623c9 commit df95f07
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 65 deletions.
8 changes: 4 additions & 4 deletions UEFIExtract/uefiextract_main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* uefiextract_main.cpp
Copyright (c) 2015, Nikolaj Schlej. All rights reserved.
Copyright (c) 2018, LongSoft. 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
Expand All @@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setOrganizationName("LongSoft");
a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIExtract");

UEFIExtract w;
Expand Down Expand Up @@ -52,7 +52,7 @@ int main(int argc, char *argv[])

}
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 <<
"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;
Expand Down
10 changes: 9 additions & 1 deletion UEFIPatch/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F

# PowerManagement | Sandy Bridge with ME 8.xx, Ivy Bridge
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:75080FBAE80F89442430:EB080FBAE80F89442430

# PowerManagement | New SB-E/IB-E
8C783970-F02A-4A4D-AF09-8797A51EEC8D 10 P:0FBA6C24380F:0FBA7424380F

Expand All @@ -48,5 +49,12 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F
299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:75080D00800000:EB080D00800000

# 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

# 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
4 changes: 2 additions & 2 deletions UEFIPatch/uefipatch_main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* uefipatch_main.cpp
Copyright (c) 2017, LongSoft. All rights reserved.
Copyright (c) 2018, LongSoft. 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
Expand Down Expand Up @@ -31,7 +31,7 @@ int main(int argc, char *argv[])
result = w.patchFromFile(a.arguments().at(1));
}
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 <<
"Patches will be read from patches.txt file\n";
return ERR_SUCCESS;
Expand Down
6 changes: 3 additions & 3 deletions UEFIReplace/uefireplace_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
a.setOrganizationName("CodeRush");
a.setOrganizationDomain("coderush.me");
a.setOrganizationName("LongSoft");
a.setOrganizationDomain("longsoft.me");
a.setApplicationName("UEFIReplace");

UEFIReplace r;
UINT8 result = ERR_SUCCESS;
QStringList args = a.arguments();

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;
return ERR_SUCCESS;
}
Expand Down
129 changes: 79 additions & 50 deletions ffsengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
if (msgUnknownRevision)
msg(tr("parseBios: unknown volume revision %1").arg(volumeHeader->Revision), index);
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),
index);

Expand Down Expand Up @@ -1825,7 +1825,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c
// Get TE info
bool msgInvalidSignature = false;
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) {
info += tr("\nSignature: %1h, invalid").hexarg2(teHeader->Signature, 4);
msgInvalidSignature = true;
Expand Down Expand Up @@ -3543,18 +3547,21 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon
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
else
else {
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
reconstructed = header.append(reconstructed);

Expand All @@ -3574,6 +3581,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon
volumeHeader->Checksum = calculateChecksum16((const UINT16*)volumeHeader, volumeHeader->HeaderLength);
}
}

// Store new free space offset, if needed
if (model->text(index).contains("AppleFSO ")) {
// Get current CRC32 value from volume header
Expand Down Expand Up @@ -3716,30 +3724,31 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision,
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
else
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
if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((const UINT8*)reconstructed.constData(), reconstructed.size());
Expand All @@ -3755,6 +3764,7 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision,
UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File;
reconstructed.append(ht).append(ft);
}

// Set file state
state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION;
if (erasePolarity == ERASE_POLARITY_TRUE)
Expand Down Expand Up @@ -3792,8 +3802,8 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
model->action(index) == Actions::Rebase) {
QByteArray header = model->header(index);
EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)header.data();
bool extended = false;
if(uint24ToUint32(commonHeader->Size) == 0xFFFFFF) {
bool extended = false;
if (uint24ToUint32(commonHeader->Size) == 0xFFFFFF) {
extended = true;
}

Expand Down Expand Up @@ -3894,34 +3904,44 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base,
.arg(model->subtype(index)), index);
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
else
else {
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
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_PEIM ||
model->subtype(index.parent()) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) {
model->subtype(index.parent()) == EFI_FV_FILETYPE_PEIM ||
model->subtype(index.parent()) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) {
UINT16 teFixup = 0;
//TODO: add proper handling
/*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);
}*/

// 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

// 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) {
result = rebase(reconstructed, base - teFixup + header.size());
result = rebase(reconstructed, base - teFixup + header.size(), index);
if (result) {
msg(tr("reconstructSection: executable section rebase failed"), index);
return result;
Expand Down Expand Up @@ -4217,7 +4237,7 @@ UINT8 FfsEngine::findTextPattern(const QModelIndex & index, const QString & patt
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 relocOffset; // Offset of relocation region
Expand Down Expand Up @@ -4290,6 +4310,9 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base)
relocSize = teHeader->DataDirectory[EFI_IMAGE_TE_DIRECTORY_ENTRY_BASERELOC].Size;
// Set new 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
return ERR_UNKNOWN_IMAGE_TYPE;
Expand Down Expand Up @@ -4319,6 +4342,12 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base)

// Run this relocation record
while (Reloc < RelocEnd) {
if (*Reloc == 0x0000) {
// Skip last emtpy reloc entry
Reloc += 1;
continue;
}

UINT32 RelocLocation = RelocBase->VirtualAddress - teFixup + (*Reloc & 0x0FFF);
if ((UINT32)file.size() < RelocLocation)
return ERR_BAD_RELOCATION_ENTRY;
Expand Down
3 changes: 1 addition & 2 deletions ffsengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ class FfsEngine : public QObject
UINT8 reconstructIntelImage(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed, bool includeHeader = true);
UINT8 reconstructPadding(const QModelIndex& index, QByteArray & reconstructed);
UINT8 reconstructBios(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 reconstructSection(const QModelIndex& index, const UINT32 base, QByteArray & reconstructed);
Expand Down Expand Up @@ -126,7 +125,7 @@ class FfsEngine : public QObject
// Rebase routines
UINT8 getBase(const QByteArray& file, UINT32& base);
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);

// Patch routines
Expand Down
4 changes: 2 additions & 2 deletions types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype)
case Types::Image:
if (subtype == Subtypes::IntelImage)
return QObject::tr("Intel");
else if (Subtypes::UefiImage)
else if (subtype == Subtypes::UefiImage)
return QObject::tr("UEFI");
else
return QObject::tr("Unknown subtype");
Expand Down Expand Up @@ -153,4 +153,4 @@ QString actionTypeToQString(const UINT8 action)
default:
return QObject::tr("Unknown");
}
}
}
2 changes: 1 addition & 1 deletion uefitool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
UEFITool::UEFITool(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::UEFITool),
version(tr("0.22.2"))
version(tr("0.22.3"))
{
clipboard = QApplication::clipboard();

Expand Down

0 comments on commit df95f07

Please sign in to comment.