From 92c9754c02f67932d05be451f7fea125f03000f0 Mon Sep 17 00:00:00 2001 From: cyrozap Date: Sat, 28 Mar 2015 22:15:06 -0400 Subject: [PATCH 01/64] Add Travis CI configuration --- .travis.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a10dcd5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: cpp + +compiler: + - clang + - gcc + +before_install: + - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa + - sudo apt-get update -qq + - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev + +script: + - qmake uefitool.pro + - make From 351285dfbfb1d3c40d1424f2f8cdba2f463fddbe Mon Sep 17 00:00:00 2001 From: cyrozap Date: Sat, 28 Mar 2015 22:20:38 -0400 Subject: [PATCH 02/64] Fixing Travis build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a10dcd5..bd25b50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,5 +10,5 @@ before_install: - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev script: - - qmake uefitool.pro + - qmake -qt=qt5 uefitool.pro - make From 3013398a9d66eeecfb89d7772df5825a103950bb Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 17 May 2015 10:38:04 +0200 Subject: [PATCH 03/64] Engine 0.20.5 - raw file header was included twice during reconstruction as region --- ffsengine.cpp | 9 +++++---- ffsengine.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 2e0a8fe..0029f04 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -2740,7 +2740,7 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec return ERR_NOT_IMPLEMENTED; } -UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconstructed) +UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconstructed, bool includeHeader) { if (!index.isValid()) return ERR_SUCCESS; @@ -2790,7 +2790,8 @@ UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconst } // Reconstruction successful - reconstructed = model->header(index).append(reconstructed); + if (includeHeader) + reconstructed = model->header(index).append(reconstructed); return ERR_SUCCESS; } @@ -3207,9 +3208,9 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision, if (model->rowCount(index)) { reconstructed.clear(); // Construct new file body - // File contains raw data, must be parsed as region + // File contains raw data, must be parsed as region without header if (model->subtype(index) == EFI_FV_FILETYPE_ALL || model->subtype(index) == EFI_FV_FILETYPE_RAW) { - result = reconstructRegion(index, reconstructed); + result = reconstructRegion(index, reconstructed, false); if (result) return result; } diff --git a/ffsengine.h b/ffsengine.h index 41d9e0a..281aa6e 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -81,7 +81,7 @@ public: UINT8 reconstructImageFile(QByteArray &reconstructed); UINT8 reconstruct(const QModelIndex &index, QByteArray & reconstructed); UINT8 reconstructIntelImage(const QModelIndex& index, QByteArray & reconstructed); - UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed); + UINT8 reconstructRegion(const QModelIndex& index, QByteArray & reconstructed, bool includeHeader = true); 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); From d78df75de6afec0de8d7f30773ce948f43edf2b8 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 17 May 2015 10:39:31 +0200 Subject: [PATCH 04/64] Update version numbers --- UEFIPatch/uefipatch_main.cpp | 2 +- uefitool.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 2ff15c9..6f37b1f 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.4 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.5 - 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; diff --git a/uefitool.cpp b/uefitool.cpp index 0f344f2..44eaeff 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.20.4")) +version(tr("0.20.5")) { clipboard = QApplication::clipboard(); From c5fec376f765dc2b33ab8856f96ace966a6df8a3 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 5 Jul 2015 13:28:53 +0200 Subject: [PATCH 05/64] Engine 0.20.6 - added support for recalculation of Apple-specific free space offset value stored in volume's ZeroVector. Thanks to osxreverser for reporting the issue #29. - ZeroVectorCRC renamed to AppleCRC32, because it's Apple-specific after all. - ParsingData handling removed from old codebase, because it's only needed for the new engine. --- ffsengine.cpp | 134 +++++++++++++++++++++++++++----------------------- treeitem.cpp | 18 +------ treeitem.h | 7 +-- treemodel.cpp | 31 +----------- treemodel.h | 2 +- types.h | 21 -------- uefitool.cpp | 2 +- 7 files changed, 78 insertions(+), 137 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 0029f04..16aea9b 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -221,7 +221,7 @@ UINT8 FfsEngine::parseImageFile(const QByteArray & buffer) .hexarg(flashImage.size()).arg(flashImage.size()); // Add tree item - index = model->addItem(Types::Image, Subtypes::UefiImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, QByteArray(), index); + index = model->addItem(Types::Image, Subtypes::UefiImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), flashImage, index); return parseBios(flashImage, index); } @@ -359,7 +359,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in .arg(descriptorMap->NumberOfIccTableEntries); // Add Intel image tree item - index = model->addItem(Types::Image, Subtypes::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), intelImage, QByteArray(), parent); + index = model->addItem(Types::Image, Subtypes::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), intelImage, parent); // Descriptor // Get descriptor info @@ -426,7 +426,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in } // Add descriptor tree item - model->addItem(Types::Region, Subtypes::DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, QByteArray(), index); + model->addItem(Types::Region, Subtypes::DescriptorRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, index); // Sort regions in ascending order qSort(offsets); @@ -483,7 +483,7 @@ UINT8 FfsEngine::parseGbeRegion(const QByteArray & gbe, QModelIndex & index, con .arg(version->minor); // Add tree item - index = model->addItem(Types::Region, Subtypes::GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, QByteArray(), parent, mode); + index = model->addItem(Types::Region, Subtypes::GbeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), gbe, parent, mode); return ERR_SUCCESS; } @@ -532,7 +532,7 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const } // Add tree item - index = model->addItem(Types::Region, Subtypes::MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, QByteArray(), parent, mode); + index = model->addItem(Types::Region, Subtypes::MeRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), me, parent, mode); // Show messages if (emptyRegion) { @@ -557,7 +557,7 @@ UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, con hexarg(pdr.size()).arg(pdr.size()); // Add tree item - index = model->addItem(Types::Region, Subtypes::PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, QByteArray(), parent, mode); + index = model->addItem(Types::Region, Subtypes::PdrRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), pdr, parent, mode); // Parse PDR region as BIOS space UINT8 result = parseBios(pdr, index); @@ -578,7 +578,7 @@ UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, c hexarg(bios.size()).arg(bios.size()); // Add tree item - index = model->addItem(Types::Region, Subtypes::BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, QByteArray(), parent, mode); + index = model->addItem(Types::Region, Subtypes::BiosRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), bios, parent, mode); return parseBios(bios, index); } @@ -613,7 +613,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent) .hexarg(padding.size()).arg(padding.size()); // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent); + model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent); } // Search for and parse all volumes @@ -638,7 +638,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent) info = tr("Full size: %1h (%2)") .hexarg(padding.size()).arg(padding.size()); // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent); + model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent); } // Get volume size @@ -712,7 +712,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent) info = tr("Full size: %1h (%2)") .hexarg(padding.size()).arg(padding.size()); // Add tree item - model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, QByteArray(), parent); + model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent); } break; } @@ -784,12 +784,6 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co /*volumeFfsVersion = 2;*/ } - // Check for FFS v3 volume - /*if (FFSv3Volumes.contains(QByteArray::fromRawData((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)))) { - volumeIsUnknown = false; - volumeFfsVersion = 3; - }*/ - // Check attributes // Determine value of empty byte char empty = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? '\xFF' : '\x00'; @@ -804,13 +798,20 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Check for Apple CRC32 in ZeroVector bool volumeHasZVCRC = false; + bool volumeHasZVFSO = false; UINT32 crc32FromZeroVector = *(UINT32*)(volume.constData() + 8); + UINT32 freeSpaceOffsetFromZeroVector = *(UINT32*)(volume.constData() + 12); if (crc32FromZeroVector != 0) { // Calculate CRC32 of the volume body UINT32 crc = crc32(0, (const UINT8*)(volume.constData() + volumeHeader->HeaderLength), volumeSize - volumeHeader->HeaderLength); if (crc == crc32FromZeroVector) { volumeHasZVCRC = true; } + + // Check for free space size in zero vector + if (freeSpaceOffsetFromZeroVector != 0) { + volumeHasZVFSO = true; + } } // Check header checksum by recalculating it @@ -833,11 +834,6 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co .arg(volumeHeader->Revision) .hexarg2(volumeHeader->Attributes, 8) .arg(empty ? "1" : "0"); - - // Apple CRC32 volume - if (volumeHasZVCRC) { - info += tr("\nCRC32 in ZeroVector: valid"); - } // Extended header present if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) { @@ -847,21 +843,17 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co .arg(guidToQString(extendedHeader->FvName)); } - // Construct parsing data structure - QByteArray parsingData(sizeof(PARSING_DATA), 0); - PARSING_DATA* pdata = (PARSING_DATA*)parsingData.data(); - pdata->Type = VolumeParsingData; - pdata->Data.Volume.HasZeroVectorCRC = volumeHasZVCRC; - // Add text QString text; if (volumeHasZVCRC) - text += tr("ZeroVectorCRC "); + text += tr("AppleCRC32 "); + if (volumeHasZVFSO) + text += tr("AppleFSO "); // Add tree item QByteArray header = volume.left(headerSize); QByteArray body = volume.mid(headerSize, volumeSize - headerSize); - index = model->addItem(Types::Volume, volumeIsUnknown ? Subtypes::UnknownVolume : Subtypes::Ffs2Volume, COMPRESSION_ALGORITHM_NONE, name, text, info, header, body, parsingData, parent, mode); + index = model->addItem(Types::Volume, volumeIsUnknown ? Subtypes::UnknownVolume : Subtypes::Ffs2Volume, COMPRESSION_ALGORITHM_NONE, name, text, info, header, body, parent, mode); // Show messages if (volumeIsUnknown) { @@ -917,16 +909,16 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Add all bytes before as free space... if (i > 0) { QByteArray free = freeSpace.left(i); - model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()), QByteArray(), free, QByteArray(), index, mode); + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()), QByteArray(), free, index, mode); } // ... and all bytes after as a padding QByteArray padding = freeSpace.mid(i); - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, QByteArray(), index, mode); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, index, mode); msg(tr("parseVolume: non-UEFI data found in volume's free space"), dataIndex); } else { // Add free space element - model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(freeSpace.size()).arg(freeSpace.size()), QByteArray(), freeSpace, QByteArray(), index, mode); + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(freeSpace.size()).arg(freeSpace.size()), QByteArray(), freeSpace, index, mode); } break; // Exit from loop } @@ -951,14 +943,6 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME) msg(tr("parseVolume: FFS file parsing failed with error \"%1\"").arg(errorMessage(result)), index); - - // Construct parsing data structure - QByteArray parsingData(sizeof(PARSING_DATA), 0); - PARSING_DATA* pdata = (PARSING_DATA*)parsingData.data(); - pdata->Type = FileParsingData; - pdata->Data.File.Offset = fileOffset; - model->setParsingData(fileIndex, parsingData); - // Show messages if (msgUnalignedFile) msg(tr("parseVolume: unaligned file %1").arg(guidToQString(fileHeader->Name)), fileIndex); @@ -1108,7 +1092,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U .hexarg2(fileHeader->State, 2); // Add tree item - index = model->addItem(Types::File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Show messages if (msgInvalidHeaderChecksum) @@ -1137,11 +1121,11 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U // Add all bytes before as free space... if (i > 0) { QByteArray free = body.left(i); - model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Free space"), "", tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()), QByteArray(), free, QByteArray(), index, mode); + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Free space"), "", tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()), QByteArray(), free, index, mode); } // ... and all bytes after as a padding QByteArray padding = body.mid(i); - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, QByteArray(), index, mode); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, index, mode); // Show message msg(tr("parseFile: non-empty pad-file contents will be destroyed after volume modifications"), dataIndex); @@ -1348,7 +1332,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg(compressedSectionHeader->UncompressedLength).arg(compressedSectionHeader->UncompressedLength); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, algorithm, name, "", info, header, body, parent, mode); // Show message if (!parseCurrentSection) @@ -1488,7 +1472,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, algorithm, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, algorithm, name, "", info, header, body, parent, mode); // Show messages if (msgUnknownGuid) @@ -1527,7 +1511,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg(body.size()).arg(body.size()); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Parse section body result = parseSections(body, index); @@ -1560,7 +1544,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c info += tr("\nParsed expression:%1").arg(str); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Show messages if (msgDepexParseFailed) @@ -1600,7 +1584,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg(teHeader->ImageBase + teHeader->AddressOfEntryPoint - teFixup); } // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Show messages if (msgInvalidSignature) { @@ -1683,7 +1667,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Show messages if (msgInvalidDosSignature) { @@ -1719,7 +1703,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg(body.size()).arg(body.size()); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); } break; case EFI_SECTION_FREEFORM_SUBTYPE_GUID: { @@ -1736,7 +1720,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .arg(guidToQString(fsgHeader->SubTypeGuid)); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Rename section model->setName(index, guidToQString(fsgHeader->SubTypeGuid)); @@ -1758,7 +1742,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .arg(QString::fromUtf16((const ushort*)body.constData())); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); } break; case EFI_SECTION_USER_INTERFACE: { @@ -1775,7 +1759,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .arg(text); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Rename parent file model->setText(model->findParentOfType(parent, Types::File), text); @@ -1793,7 +1777,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg(body.size()).arg(body.size()); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Parse section body as BIOS space result = parseBios(body, index); @@ -1846,7 +1830,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Parse section body as BIOS space if (!parsed) { @@ -1874,7 +1858,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg(postcodeHeader->Postcode); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); } break; default: @@ -1888,7 +1872,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg(body.size()).arg(body.size()); // Add tree item - index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, QByteArray(), parent, mode); + index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); msg(tr("parseSection: section with unknown type %1h").hexarg2(sectionHeader->Type, 2), index); } return ERR_SUCCESS; @@ -2829,6 +2813,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon UINT32 volumeSize = header.size() + body.size(); // Reconstruct volume body + UINT32 freeSpaceOffset = 0; if (model->rowCount(index)) { reconstructed.clear(); UINT8 polarity = volumeHeader->Attributes & EFI_FVB_ERASE_POLARITY ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE; @@ -3007,6 +2992,17 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon return ERR_INVALID_VOLUME; } + // Check for free space offset in ZeroVector + if (model->text(index).contains("AppleFSO ")) { + // Align current offset to 8 byte boundary + UINT32 alignment = offset % 8; + freeSpaceOffset = model->header(index).size() + offset; + if (alignment) { + alignment = 8 - alignment; + freeSpaceOffset += alignment; + } + } + // Insert VTF or non-UEFI data to it's correct place if (!vtf.isEmpty()) { // VTF found // Determine correct VTF offset @@ -3108,22 +3104,36 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon reconstructed = header.append(reconstructed); // Recalculate CRC32 in ZeroVector, if needed - const PARSING_DATA* pdata = (const PARSING_DATA*)model->parsingData(index).constData(); - if (pdata->Type == VolumeParsingData && pdata->Data.Volume.HasZeroVectorCRC) { + if (model->text(index).contains("AppleCRC32 ")) { // Get current CRC32 value from volume header - const UINT32 current = *(const UINT32*)(reconstructed.constData() + 8); + const UINT32 currentCrc = *(const UINT32*)(reconstructed.constData() + 8); // Calculate new value UINT32 crc = crc32(0, (const UINT8*)reconstructed.constData() + volumeHeader->HeaderLength, reconstructed.size() - volumeHeader->HeaderLength); // Update the value - if (current != crc) { + if (currentCrc != crc) { *(UINT32*)(reconstructed.data() + 8) = crc; - // Recalculate header checksum again + // Recalculate header checksum volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)reconstructed.data(); volumeHeader->Checksum = 0; 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 + const UINT32 currentFso = *(const UINT32*)(reconstructed.constData() + 12); + // Update the value + if (freeSpaceOffset != 0 && currentFso != freeSpaceOffset) { + *(UINT32*)(reconstructed.data() + 12) = freeSpaceOffset; + + // Recalculate header checksum + volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)reconstructed.data(); + volumeHeader->Checksum = 0; + volumeHeader->Checksum = calculateChecksum16((const UINT16*)volumeHeader, volumeHeader->HeaderLength); + } + } + return ERR_SUCCESS; } diff --git a/treeitem.cpp b/treeitem.cpp index 94514dd..925d95b 100644 --- a/treeitem.cpp +++ b/treeitem.cpp @@ -17,7 +17,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compression, const QString & name, const QString & text, const QString & info, - const QByteArray & header, const QByteArray & body, const QByteArray & parsingData, + const QByteArray & header, const QByteArray & body, TreeItem *parent) : itemAction(Actions::NoAction), itemType(type), @@ -28,7 +28,6 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compressio itemInfo(info), itemHeader(header), itemBody(body), - itemParsingData(parsingData), parentItem(parent) { } @@ -184,11 +183,6 @@ QByteArray TreeItem::body() const return itemBody; } -QByteArray TreeItem::parsingData() const -{ - return itemParsingData; -} - bool TreeItem::hasEmptyHeader() const { return itemHeader.isEmpty(); @@ -199,16 +193,6 @@ bool TreeItem::hasEmptyBody() const return itemBody.isEmpty(); } -bool TreeItem::hasEmptyParsingData() const -{ - return itemParsingData.isEmpty(); -} - -void TreeItem::setParsingData(const QByteArray & data) -{ - itemParsingData = data; -} - UINT8 TreeItem::action() const { return itemAction; diff --git a/treeitem.h b/treeitem.h index 8697a75..58015f4 100644 --- a/treeitem.h +++ b/treeitem.h @@ -26,7 +26,7 @@ class TreeItem public: TreeItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE, const QString &name = QString(), const QString &text = QString(), const QString &info = QString(), - const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & parsingData = QByteArray(), + const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), TreeItem *parent = 0); ~TreeItem(); @@ -63,10 +63,6 @@ public: QByteArray body() const; bool hasEmptyBody() const; - QByteArray parsingData() const; - bool hasEmptyParsingData() const; - void setParsingData(const QByteArray & data); - QString info() const; void addInfo(const QString &info); void setInfo(const QString &info); @@ -87,7 +83,6 @@ private: QString itemInfo; QByteArray itemHeader; QByteArray itemBody; - QByteArray itemParsingData; TreeItem *parentItem; }; diff --git a/treemodel.cpp b/treemodel.cpp index ef83561..a82724b 100644 --- a/treemodel.cpp +++ b/treemodel.cpp @@ -178,22 +178,6 @@ bool TreeModel::hasEmptyBody(const QModelIndex &index) const return item->hasEmptyBody(); } -QByteArray TreeModel::parsingData(const QModelIndex &index) const -{ - if (!index.isValid()) - return QByteArray(); - TreeItem *item = static_cast(index.internalPointer()); - return item->parsingData(); -} - -bool TreeModel::hasEmptyParsingData(const QModelIndex &index) const -{ - if (!index.isValid()) - return true; - TreeItem *item = static_cast(index.internalPointer()); - return item->hasEmptyParsingData(); -} - QString TreeModel::name(const QModelIndex &index) const { if (!index.isValid()) @@ -284,20 +268,9 @@ void TreeModel::setAction(const QModelIndex &index, const UINT8 action) emit dataChanged(this->index(0, 0), index); } -void TreeModel::setParsingData(const QModelIndex &index, const QByteArray &data) -{ - if (!index.isValid()) - return; - - TreeItem *item = static_cast(index.internalPointer()); - item->setParsingData(data); - emit dataChanged(this->index(0, 0), index); -} - QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression, const QString & name, const QString & text, const QString & info, - const QByteArray & header, const QByteArray & body, const QByteArray & parsingData, - const QModelIndex & parent, const UINT8 mode) + const QByteArray & header, const QByteArray & body, const QModelIndex & parent, const UINT8 mode) { TreeItem *item = 0; TreeItem *parentItem = 0; @@ -318,7 +291,7 @@ QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT } } - TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parsingData, parentItem); + TreeItem *newItem = new TreeItem(type, subtype, compression, name, text, info, header, body, parentItem); if (mode == CREATE_MODE_APPEND) { emit layoutAboutToBeChanged(); parentItem->appendChild(newItem); diff --git a/treemodel.h b/treemodel.h index 3c8c210..ae9c717 100644 --- a/treemodel.h +++ b/treemodel.h @@ -65,7 +65,7 @@ public: QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE, const QString & name = QString(), const QString & text = QString(), const QString & info = QString(), - const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QByteArray & parsingData = QByteArray(), + const QByteArray & header = QByteArray(), const QByteArray & body = QByteArray(), const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); QModelIndex findParentOfType(const QModelIndex & index, UINT8 type) const; diff --git a/types.h b/types.h index a65b73e..ec605b4 100644 --- a/types.h +++ b/types.h @@ -85,25 +85,4 @@ extern QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype); extern QString compressionTypeToQString(const UINT8 algorithm); extern QString regionTypeToQString(const UINT8 type); -enum ParsingDataTypes { - UnknownParsingData, - VolumeParsingData, - FileParsingData -}; - -typedef union _PARSING_DATA_UNION { - struct _PARSING_DATA_UNION_VOLUME { - bool HasZeroVectorCRC; - } Volume; - - struct _PARSING_DATA_UNION_FILE { - UINT32 Offset; - } File; -} PARSING_DATA_UNION; - -typedef struct _PARSING_DATA { - UINT8 Type; - PARSING_DATA_UNION Data; -} PARSING_DATA; - #endif \ No newline at end of file diff --git a/uefitool.cpp b/uefitool.cpp index 44eaeff..4ff8781 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.20.5")) +version(tr("0.20.6")) { clipboard = QApplication::clipboard(); From 1109e4437909a91032e7278222140b51e14b0304 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Tue, 11 Aug 2015 18:12:12 +0200 Subject: [PATCH 06/64] Create LICENSE.md --- LICENSE.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..3f16459 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,23 @@ +Copyright (c) 2015, Nikolaj Schlej +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 63e5a4dd1cf187fe6b62bd0da60529746f2ff7a1 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Thu, 13 Aug 2015 20:28:10 +0200 Subject: [PATCH 07/64] UT 0.20.7 - added "Open in new window..." action --- uefitool.cpp | 20 +++++++++++++++++--- uefitool.h | 4 ++++ uefitool.ui | 12 ++++++++++++ uefitool_main.cpp | 1 + 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/uefitool.cpp b/uefitool.cpp index 4ff8781..14b2e56 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.20.6")) +version(tr("0.20.7")) { clipboard = QApplication::clipboard(); @@ -31,6 +31,7 @@ version(tr("0.20.6")) // Connect signals to slots connect(ui->actionOpenImageFile, SIGNAL(triggered()), this, SLOT(openImageFile())); + connect(ui->actionOpenImageFileInNewWindow, SIGNAL(triggered()), this, SLOT(openImageFileInNewWindow())); connect(ui->actionSaveImageFile, SIGNAL(triggered()), this, SLOT(saveImageFile())); connect(ui->actionSearch, SIGNAL(triggered()), this, SLOT(search())); connect(ui->actionExtract, SIGNAL(triggered()), this, SLOT(extractAsIs())); @@ -83,6 +84,11 @@ UEFITool::~UEFITool() delete searchDialog; } +void UEFITool::setProgramPath(QString path) +{ + currentProgramPath = path; +}; + void UEFITool::init() { // Clear components @@ -358,6 +364,8 @@ void UEFITool::replace(const UINT8 mode) path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace body"), currentDir, "Volume files (*.vol *.bin);;All files (*)"); else if (model->subtype(index) == EFI_SECTION_RAW) path = QFileDialog::getOpenFileName(this, tr("Select raw file to replace body"), currentDir, "Raw files (*.raw *.bin);;All files (*)"); + else if (model->subtype(index) == EFI_SECTION_PE32 || model->subtype(index) == EFI_SECTION_TE || model->subtype(index) == EFI_SECTION_PIC) + path = QFileDialog::getOpenFileName(this, tr("Select EFI executable file to replace body"), currentDir, "EFI executable files (*.efi *.dxe *.pei *.bin);;All files (*)"); else path = QFileDialog::getOpenFileName(this, tr("Select file to replace body"), currentDir, "Binary files (*.bin);;All files (*)"); } @@ -521,7 +529,7 @@ void UEFITool::exit() void UEFITool::saveImageFile() { - QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.efi *.dec);;All files (*)"); + QString path = QFileDialog::getSaveFileName(this, tr("Save BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)"); if (path.isEmpty()) return; @@ -552,10 +560,16 @@ void UEFITool::saveImageFile() void UEFITool::openImageFile() { - QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.efi *.dec);;All files (*)"); + QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)"); openImageFile(path); } +void UEFITool::openImageFileInNewWindow() +{ + QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file in new window"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)"); + QProcess::startDetached(currentProgramPath, QStringList(path)); +} + void UEFITool::openImageFile(QString path) { if (path.trimmed().isEmpty()) diff --git a/uefitool.h b/uefitool.h index dda7fdc..edac83b 100644 --- a/uefitool.h +++ b/uefitool.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ public: ~UEFITool(); void openImageFile(QString path); + void setProgramPath(QString path); private slots: void init(); @@ -58,6 +60,7 @@ public: void scrollTreeView(QListWidgetItem* item); void openImageFile(); + void openImageFileInNewWindow(); void saveImageFile(); void search(); @@ -95,6 +98,7 @@ private: SearchDialog* searchDialog; QClipboard* clipboard; QString currentDir; + QString currentProgramPath; QQueue messageItems; const QString version; diff --git a/uefitool.ui b/uefitool.ui index 82868da..5b5953a 100644 --- a/uefitool.ui +++ b/uefitool.ui @@ -188,6 +188,7 @@ &File + @@ -522,6 +523,17 @@ Ctrl+Alt+C + + + &Open image file in new window... + + + Open image file in new window + + + Ctrl+Shift+O + + diff --git a/uefitool_main.cpp b/uefitool_main.cpp index e5764c0..a9ac03a 100644 --- a/uefitool_main.cpp +++ b/uefitool_main.cpp @@ -23,6 +23,7 @@ int main(int argc, char *argv[]) a.setApplicationName("UEFITool"); UEFITool w; + w.setProgramPath(a.arguments().at(0)); if (a.arguments().length() > 1) w.openImageFile(a.arguments().at(1)); w.show(); From 9c4ddbec6218302e86955cfc53e7dfcc8f858eca Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 30 Aug 2015 10:52:19 +0200 Subject: [PATCH 08/64] UT 0.20.8 - data after the latest region of Intel image is in tree now - added Intel, Lenovo and Toshiba-specific capsule GUIDs to the list of known GUIDs - fixed bogus "File with invalid size" message while working on almost full volumes - pressing Cancel on "Open in new window" dialog now works as expected Big thanks to Lordkag for spotting most of the issues (#31). --- basetypes.h | 1 + ffs.h | 32 ++++++++-- ffsengine.cpp | 160 ++++++++++++++++++++++++++++++++++++-------------- types.cpp | 12 ++-- types.h | 3 +- uefitool.cpp | 12 ++-- 6 files changed, 159 insertions(+), 61 deletions(-) diff --git a/basetypes.h b/basetypes.h index 083267b..e8589ad 100644 --- a/basetypes.h +++ b/basetypes.h @@ -85,6 +85,7 @@ typedef unsigned int UINTN; #define ERR_INVALID_SYMBOL 40 #define ERR_NOTHING_TO_PATCH 41 #define ERR_DEPEX_PARSE_FAILED 42 +#define ERR_TRUNCATED_IMAGE 43 #define ERR_NOT_IMPLEMENTED 0xFF // UDK porting definitions diff --git a/ffs.h b/ffs.h index 8b7da95..0bb8221 100644 --- a/ffs.h +++ b/ffs.h @@ -32,7 +32,7 @@ extern QString sectionTypeToQString(const UINT8 type); //***************************************************************************** // EFI Capsule //***************************************************************************** -// Capsule header +// Standard EFI Capsule header typedef struct _EFI_CAPSULE_HEADER { EFI_GUID CapsuleGuid; UINT32 HeaderSize; @@ -49,16 +49,36 @@ typedef struct _EFI_CAPSULE_HEADER { const QByteArray EFI_CAPSULE_GUID ("\xBD\x86\x66\x3B\x76\x0D\x30\x40\xB7\x0E\xB5\x51\x9E\x2F\xC5\xA0", 16); +// Intel capsule GUID +const QByteArray INTEL_CAPSULE_GUID +("\xB9\x82\x91\x53\xB5\xAB\x91\x43\xB6\x9A\xE3\xA9\x43\xF7\x2F\xCC", 16); + +// Lenovo capsule GUID +const QByteArray LENOVO_CAPSULE_GUID +("\x8B\xA6\x3C\x4A\x23\x77\xFB\x48\x80\x3D\x57\x8C\xC1\xFE\xC4\x4D", 16); + +// Toshiba EFI Capsule header +typedef struct _TOSHIBA_CAPSULE_HEADER { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 FullSize; + UINT32 Flags; +} TOSHIBA_CAPSULE_HEADER; + +// Toshiba capsule GUID +const QByteArray TOSHIBA_CAPSULE_GUID +("\x62\x70\xE0\x3B\x51\x1D\xD2\x45\x83\x2B\xF0\x93\x25\x7E\xD4\x61", 16); + // AMI Aptio extended capsule header typedef struct _APTIO_CAPSULE_HEADER { EFI_CAPSULE_HEADER CapsuleHeader; - UINT16 RomImageOffset; // offset in bytes from the beginning of the capsule header to the start of + UINT16 RomImageOffset; // offset in bytes from the beginning of the capsule header to the start of // the capsule volume //!TODO: Enable certificate and ROM layout reading - //UINT16 RomLayoutOffset; // offset to the table of the module descriptors in the capsule's volume + //UINT16 RomLayoutOffset; // offset to the table of the module descriptors in the capsule's volume // that are included in the signature calculation //FW_CERTIFICATE FWCert; - //ROM_AREA RomAreaMap[1]; + //ROM_AREA RomAreaMap[1]; } APTIO_CAPSULE_HEADER; // AMI Aptio signed extended capsule GUID @@ -252,8 +272,8 @@ extern UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize); // Integrity check typedef union { struct { - UINT8 Header; - UINT8 File; + UINT8 Header; + UINT8 File; } Checksum; UINT16 TailReference; // Revision 1 UINT16 Checksum16; // Revision 2 diff --git a/ffsengine.cpp b/ffsengine.cpp index 16aea9b..d516019 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -75,6 +75,7 @@ QString errorMessage(UINT8 errorCode) case ERR_INVALID_SYMBOL: return QObject::tr("Invalid symbol"); case ERR_NOTHING_TO_PATCH: return QObject::tr("Nothing to patch"); case ERR_DEPEX_PARSE_FAILED: return QObject::tr("Dependency expression parsing failed"); + case ERR_TRUNCATED_IMAGE: return QObject::tr("Image is truncated"); default: return QObject::tr("Unknown error %1").arg(errorCode); } } @@ -146,14 +147,16 @@ UINT8 FfsEngine::parseImageFile(const QByteArray & buffer) // Check buffer size to be more then or equal to size of EFI_CAPSULE_HEADER if ((UINT32)buffer.size() <= sizeof(EFI_CAPSULE_HEADER)) { - msg(tr("parseImageFile: image file is smaller then minimum size of %1h (%2) bytes").hexarg(sizeof(EFI_CAPSULE_HEADER)).arg(sizeof(EFI_CAPSULE_HEADER))); + msg(tr("parseImageFile: image file is smaller then minimum size of %1h (%2) bytes").hexarg(sizeof(EFI_CAPSULE_HEADER)).arg(sizeof(EFI_CAPSULE_HEADER))); return ERR_INVALID_PARAMETER; } // Check buffer for being normal EFI capsule header UINT32 capsuleHeaderSize = 0; QModelIndex index; - if (buffer.startsWith(EFI_CAPSULE_GUID)) { + if (buffer.startsWith(EFI_CAPSULE_GUID) + || buffer.startsWith(INTEL_CAPSULE_GUID) + || buffer.startsWith(LENOVO_CAPSULE_GUID)) { // Get info const EFI_CAPSULE_HEADER* capsuleHeader = (const EFI_CAPSULE_HEADER*)buffer.constData(); capsuleHeaderSize = capsuleHeader->HeaderSize; @@ -170,7 +173,24 @@ UINT8 FfsEngine::parseImageFile(const QByteArray & buffer) // Add tree item index = model->addItem(Types::Capsule, Subtypes::UefiCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body); } + // 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(); + capsuleHeaderSize = capsuleHeader->HeaderSize; + QByteArray header = buffer.left(capsuleHeaderSize); + QByteArray body = buffer.right(buffer.size() - capsuleHeaderSize); + QString name = tr("UEFI capsule"); + QString info = tr("Capsule GUID: %1\nFull size: %2h (%3)\nHeader size: %4h (%5)\nImage size: %6h (%7)\nFlags: %8h") + .arg(guidToQString(capsuleHeader->CapsuleGuid)) + .hexarg(buffer.size()).arg(buffer.size()) + .hexarg(capsuleHeader->HeaderSize).arg(capsuleHeader->HeaderSize) + .hexarg(capsuleHeader->FullSize - capsuleHeader->HeaderSize).arg(capsuleHeader->FullSize - capsuleHeader->HeaderSize) + .hexarg2(capsuleHeader->Flags, 8); + // Add tree item + index = model->addItem(Types::Capsule, Subtypes::ToshibaCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body); + } // Check buffer for being extended Aptio signed capsule header else if (buffer.startsWith(APTIO_SIGNED_CAPSULE_GUID) || buffer.startsWith(APTIO_UNSIGNED_CAPSULE_GUID)) { // Get info @@ -192,7 +212,7 @@ UINT8 FfsEngine::parseImageFile(const QByteArray & buffer) // Add tree item index = model->addItem(Types::Capsule, signedCapsule ? Subtypes::AptioSignedCapsule : Subtypes::AptioUnsignedCapsule, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body); - + // Show message about possible Aptio signature break if (signedCapsule) { msg(tr("parseImageFile: Aptio capsule signature may become invalid after image modifications"), index); @@ -458,6 +478,34 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in return result; } + // Add the data after the last region as padding + UINT32 IntelDataEnd = 0; + UINT32 LastRegionOffset = offsets.last(); + if (LastRegionOffset == gbeBegin) + IntelDataEnd = gbeEnd; + else if (LastRegionOffset == meBegin) + IntelDataEnd = meEnd; + else if (LastRegionOffset == biosBegin) + IntelDataEnd = biosEnd; + else if (LastRegionOffset == pdrBegin) + IntelDataEnd = pdrEnd; + + if (IntelDataEnd > (UINT32)intelImage.size()) { // Image file is truncated + msg(tr("parseIntelImage: image size %1 (%2) is smaller than the end of last region %3 (%4), may be damaged") + .hexarg(intelImage.size()).arg(intelImage.size()) + .hexarg(IntelDataEnd).arg(IntelDataEnd), index); + return ERR_TRUNCATED_IMAGE; + } + else if (IntelDataEnd < (UINT32)intelImage.size()) { // Insert padding + QByteArray padding = bios.right(intelImage.size() - IntelDataEnd); + // Get info + name = tr("Padding"); + info = tr("Full size: %1h (%2)") + .hexarg(padding.size()).arg(padding.size()); + // Add tree item + model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, index); + } + return ERR_SUCCESS; } @@ -495,7 +543,7 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const return ERR_EMPTY_REGION; // Get info - QString name = tr("ME/TXE region"); + QString name = tr("ME region"); QString info = tr("Full size: %1h (%2)"). hexarg(me.size()).arg(me.size()); @@ -536,10 +584,10 @@ UINT8 FfsEngine::parseMeRegion(const QByteArray & me, QModelIndex & index, const // Show messages if (emptyRegion) { - msg(tr("parseRegion: ME/TXE region is empty"), index); + msg(tr("parseRegion: ME region is empty"), index); } else if (!versionFound) { - msg(tr("parseRegion: ME/TXE region version is unknown, it can be damaged"), index); + msg(tr("parseRegion: ME region version is unknown, it can be damaged"), index); } return ERR_SUCCESS; @@ -611,7 +659,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent) name = tr("Padding"); info = tr("Full size: %1h (%2)") .hexarg(padding.size()).arg(padding.size()); - + // Add tree item model->addItem(Types::Padding, getPaddingType(padding), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), padding, parent); } @@ -777,7 +825,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Check for volume structure to be known bool volumeIsUnknown = true; /*UINT8 volumeFfsVersion = 0;*/ - + // Check for FFS v2 volume if (FFSv2Volumes.contains(QByteArray::fromRawData((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)))) { volumeIsUnknown = false; @@ -864,7 +912,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co if (msgInvalidChecksum) { msg(tr("parseVolume: volume header checksum is invalid"), index); } - + // Search for and parse all files UINT32 fileOffset = headerSize; UINT32 fileSize; @@ -874,6 +922,22 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co bool msgUnalignedFile = false; bool msgDuplicateGuid = false; + // Check if it's possibly the latest file in the volume + if (volumeSize - fileOffset < sizeof(EFI_FFS_FILE_HEADER)) { + // No files are possible after this point + // All the rest is either free space or non-UEFI data + QByteArray rest = volume.right(volumeSize - fileOffset); + if (rest.count(empty) == rest.size()) { // It's a free space + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index, mode); + } + else { //It's non-UEFI data + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index, mode); + msg(tr("parseVolume: non-UEFI data found in volume's free space"), dataIndex); + } + // Exit from loop + break; + } + result = getFileSize(volume, fileOffset, fileSize); if (result) return result; @@ -907,7 +971,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co i = ALIGN8(i) - 8; // Add all bytes before as free space... - if (i > 0) { + if (i > 0) { QByteArray free = freeSpace.left(i); model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()), QByteArray(), free, index, mode); } @@ -1079,7 +1143,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U QString info; if (fileHeader->Type != EFI_FV_FILETYPE_PAD) name = guidToQString(fileHeader->Name); - else + else name = parseAsNonEmptyPadFile ? tr("Non-empty pad-file") : tr("Pad-file"); info = tr("File GUID: %1\nType: %2h\nAttributes: %3h\nFull size: %4h (%5)\nHeader size: %6h (%7)\nBody size: %8h (%9)\nState: %10h") @@ -1103,7 +1167,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U msg(tr("parseFile: invalid tail value"), index); if (msgInvalidType) msg(tr("parseFile: unknown file type %1h").arg(fileHeader->Type, 2), index); - + // No parsing needed if (!parseCurrentFile) return ERR_SUCCESS; @@ -1126,10 +1190,10 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U // ... and all bytes after as a padding QByteArray padding = body.mid(i); QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, index, mode); - + // Show message msg(tr("parseFile: non-empty pad-file contents will be destroyed after volume modifications"), dataIndex); - + return ERR_SUCCESS; } @@ -1211,7 +1275,7 @@ UINT8 FfsEngine::parseDepexSection(const QByteArray & body, QString & parsed) const EFI_GUID * guid; const UINT8* current = (const UINT8*)body.constData(); - + // Special cases of first opcode switch (*current) { case EFI_DEP_BEFORE: @@ -1241,7 +1305,7 @@ UINT8 FfsEngine::parseDepexSection(const QByteArray & body, QString & parsed) break; } - // Parse the rest of depex + // Parse the rest of depex while (current - (const UINT8*)body.constData() < body.size()) { switch (*current) { case EFI_DEP_BEFORE: @@ -1287,9 +1351,9 @@ UINT8 FfsEngine::parseDepexSection(const QByteArray & body, QString & parsed) return ERR_DEPEX_PARSE_FAILED; } break; - default: - return ERR_DEPEX_PARSE_FAILED; - break; + default: + return ERR_DEPEX_PARSE_FAILED; + break; } } @@ -1379,11 +1443,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c // Tiano compressed section if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_TIANO) { algorithm = COMPRESSION_ALGORITHM_UNKNOWN; - + result = decompress(body, EFI_STANDARD_COMPRESSION, processed, &algorithm); if (result) parseCurrentSection = false; - + if (algorithm == COMPRESSION_ALGORITHM_TIANO) { info += tr("\nCompression type: Tiano"); info += tr("\nDecompressed size: %1h (%2)").hexarg(processed.length()).arg(processed.length()); @@ -1392,17 +1456,17 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c info += tr("\nCompression type: EFI 1.1"); info += tr("\nDecompressed size: %1h (%2)").hexarg(processed.length()).arg(processed.length()); } - else + else info += tr("\nCompression type: unknown"); } // LZMA compressed section else if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_LZMA) { algorithm = COMPRESSION_ALGORITHM_UNKNOWN; - + result = decompress(body, EFI_CUSTOMIZED_COMPRESSION, processed, &algorithm); if (result) parseCurrentSection = false; - + if (algorithm == COMPRESSION_ALGORITHM_LZMA) { info += tr("\nCompression type: LZMA"); info += tr("\nDecompressed size: %1h (%2)").hexarg(processed.length()).arg(processed.length()); @@ -1570,7 +1634,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c if (teHeader->Signature != EFI_IMAGE_TE_SIGNATURE) { info += tr("\nSignature: %1h, invalid").hexarg2(teHeader->Signature, 4); msgInvalidSignature = true; - } + } else { info += tr("\nSignature: %1h\nMachine type: %2\nNumber of sections: %3\nSubsystem: %4h\nStrippedSize: %5h (%6)\nBaseOfCode: %7h\nRelativeEntryPoint: %8h\nImageBase: %9h\nEntryPoint: %10h") .hexarg2(teHeader->Signature, 4) @@ -1833,7 +1897,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c index = model->addItem(Types::Section, sectionHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Parse section body as BIOS space - if (!parsed) { + if (!parsed) { result = parseBios(body, index); if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME) { msg(tr("parseSection: parsing raw section as BIOS failed with error \"%1\"").arg(errorMessage(result)), index); @@ -1922,7 +1986,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte } else if (type == Types::Volume) { QByteArray volume; - if (header.isEmpty()) // Whole volume + if (header.isEmpty()) // Whole volume volume.append(body); else { // Body only volume.append(model->header(index)).append(body); @@ -1936,7 +2000,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte result = parseVolume(volume, fileIndex, index, mode); if (result) return result; - + // Set action model->setAction(fileIndex, action); } @@ -1954,7 +2018,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte QByteArray newHeader = header; EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*)newHeader.data(); - + // Correct file size UINT8 tailSize = fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT ? sizeof(UINT16) : 0; uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + body.size() + tailSize, fileHeader->Size); @@ -2478,7 +2542,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA return ERR_STANDARD_COMPRESSION_FAILED; } compressedData = QByteArray((const char*)compressed, compressedSize); - + // Check that compressed data can be decompressed normally QByteArray decompressed; if (decompress(compressedData, EFI_STANDARD_COMPRESSION, decompressed, NULL) == ERR_SUCCESS @@ -2498,7 +2562,7 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA return ERR_STANDARD_COMPRESSION_FAILED; } compressedData = QByteArray((const char*)compressed, compressedSize); - + // New functions will be trusted here, because another check will reduce performance delete[] compressed; return ERR_SUCCESS; @@ -2657,12 +2721,20 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec char empty = '\xFF'; for (int i = 1; i < model->rowCount(index); i++) { QByteArray region; + + // Padding after the end of all Intel regions + if (model->type(index.child(i, 0)) == Types::Padding) { + region = model->body(index.child(i, 0)); + reconstructed.append(region); + offset += region.size(); + continue; + } + result = reconstructRegion(index.child(i, 0), region); if (result) return result; - UINT8 type = model->subtype(index.child(i, 0)); - switch (type) + switch (model->subtype(index.child(i, 0))) { case Subtypes::GbeRegion: gbe = region; @@ -2761,7 +2833,7 @@ UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconst if (reconstructed.size() > model->body(index).size()) { msg(tr("reconstructRegion: reconstructed region size %1h (%2) is bigger then original %3h (%4)") .hexarg(reconstructed.size()).arg(reconstructed.size()) - .hexarg(model->body(index).size()).arg(reconstructed.size()), + .hexarg(model->body(index).size()).arg(reconstructed.size()), index); return ERR_INVALID_PARAMETER; } @@ -2799,7 +2871,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon reconstructed.clear(); return ERR_SUCCESS; } - else if (model->action(index) == Actions::Replace || + else if (model->action(index) == Actions::Replace || model->action(index) == Actions::Rebuild) { QByteArray header = model->header(index); QByteArray body = model->body(index); @@ -2811,7 +2883,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon // Get volume size UINT32 volumeSize = header.size() + body.size(); - + // Reconstruct volume body UINT32 freeSpaceOffset = 0; if (model->rowCount(index)) { @@ -2926,7 +2998,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon // Pad file if (fileHeader->Type == EFI_FV_FILETYPE_PAD) { padFileGuid = file.left(sizeof(EFI_GUID)); - + // Parse non-empty pad file if (model->rowCount(index.child(i, 0))) { //TODO: handle it @@ -2981,7 +3053,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon // Get non-UEFI data and it's offset nonUefiData = model->body(index.child(i + 1, 0)); nonUefiDataOffset = body.size() - nonUefiData.size(); - break; + break; } } } @@ -3133,7 +3205,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon volumeHeader->Checksum = calculateChecksum16((const UINT16*)volumeHeader, volumeHeader->HeaderLength); } } - + return ERR_SUCCESS; } @@ -3435,7 +3507,7 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base, 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()); if (result) { @@ -3966,7 +4038,7 @@ UINT8 FfsEngine::getBase(const QByteArray& file, UINT32& base) // Populate TE header const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)file.constData(); //!TODO: add handling - base = teHeader->ImageBase; + base = teHeader->ImageBase; } return ERR_SUCCESS; @@ -4041,10 +4113,10 @@ UINT8 FfsEngine::recursiveDump(const QModelIndex & index, const QString & path, return ERR_INVALID_PARAMETER; QDir dir; - if (guid.isEmpty() || + if (guid.isEmpty() || guidToQString(*(const EFI_GUID*)model->header(index).constData()) == guid || guidToQString(*(const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData()) == guid) { - + if (dir.cd(path)) return ERR_DIR_ALREADY_EXIST; @@ -4079,7 +4151,7 @@ UINT8 FfsEngine::recursiveDump(const QModelIndex & index, const QString & path, file.write(info.toLatin1()); file.close(); dumped = true; - } + } UINT8 result; for (int i = 0; i < model->rowCount(index); i++) { diff --git a/types.cpp b/types.cpp index 5904e9e..17ca51f 100644 --- a/types.cpp +++ b/types.cpp @@ -24,7 +24,7 @@ QString regionTypeToQString(const UINT8 type) case Subtypes::GbeRegion: return QObject::tr("GbE"); case Subtypes::MeRegion: - return QObject::tr("ME/TXE"); + return QObject::tr("ME"); case Subtypes::BiosRegion: return QObject::tr("BIOS"); case Subtypes::PdrRegion: @@ -80,7 +80,7 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype) return QObject::tr("Non-empty"); else return QObject::tr("Unknown subtype"); - case Types::Volume: + case Types::Volume: if (subtype == Subtypes::UnknownVolume) return QObject::tr("Unknown"); else if (subtype == Subtypes::Ffs2Volume) @@ -89,14 +89,16 @@ QString itemSubtypeToQString(const UINT8 type, const UINT8 subtype) return QObject::tr("FFSv3"); else return QObject::tr("Unknown subtype"); - case Types::Capsule: + case Types::Capsule: if (subtype == Subtypes::AptioSignedCapsule) return QObject::tr("Aptio signed"); else if (subtype == Subtypes::AptioUnsignedCapsule) return QObject::tr("Aptio unsigned"); else if (subtype == Subtypes::UefiCapsule) - return QObject::tr("UEFI 2.0 "); - else + return QObject::tr("UEFI 2.0"); + else if (subtype == Subtypes::ToshibaCapsule) + return QObject::tr("Toshiba"); + else return QObject::tr("Unknown subtype"); case Types::Region: return regionTypeToQString(subtype); diff --git a/types.h b/types.h index ec605b4..64df300 100644 --- a/types.h +++ b/types.h @@ -54,7 +54,8 @@ namespace Subtypes { enum CapsuleSubtypes { AptioSignedCapsule = 80, AptioUnsignedCapsule, - UefiCapsule + UefiCapsule, + ToshibaCapsule }; enum VolumeSubtypes { diff --git a/uefitool.cpp b/uefitool.cpp index 14b2e56..5a4ef55 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -16,8 +16,8 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), -ui(new Ui::UEFITool), -version(tr("0.20.7")) +ui(new Ui::UEFITool), +version(tr("0.20.8")) { clipboard = QApplication::clipboard(); @@ -85,8 +85,8 @@ UEFITool::~UEFITool() } void UEFITool::setProgramPath(QString path) -{ - currentProgramPath = path; +{ + currentProgramPath = path; }; void UEFITool::init() @@ -455,7 +455,7 @@ void UEFITool::extract(const UINT8 mode) case Types::Capsule: path = QFileDialog::getSaveFileName(this, tr("Save capsule body to image file"), currentDir, "Image files (*.rom *.bin);;All files (*)"); break; - case Types::Volume: + case Types::Volume: path = QFileDialog::getSaveFileName(this, tr("Save volume body to file"), currentDir, "Volume body files (*.vbd *.bin);;All files (*)"); break; case Types::File: { @@ -567,6 +567,8 @@ void UEFITool::openImageFile() void UEFITool::openImageFileInNewWindow() { QString path = QFileDialog::getOpenFileName(this, tr("Open BIOS image file in new window"), currentDir, "BIOS image files (*.rom *.bin *.cap *.bio *.fd *.wph *.dec);;All files (*)"); + if (path.trimmed().isEmpty()) + return; QProcess::startDetached(currentProgramPath, QStringList(path)); } From aa80837bf5ce68af01f1f432011b546cd8762bef Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 6 Sep 2015 23:46:26 +0200 Subject: [PATCH 09/64] UT 0.21.0 - added support for new Intel descriptor type, based on [this](http://review.coreboot.org/gitweb?p=coreboot.git;a=commit;h=1f7fd720c81755144423f2d4062c39cc651adc0a) coreboot commit, thanks to lordkag for issue #32 - solved a bug with incorrect volume free space item placement during volume replace, now works as expected - solved an issue with incorrect Aptio capsule parsing introduced in 0.20.8 --- descriptor.h | 131 ++++++++++++++-------- ffs.h | 4 - ffsengine.cpp | 292 +++++++++++++++++++++++++++++++++++++------------- ffsengine.h | 1 + types.cpp | 2 + types.h | 3 +- uefitool.cpp | 2 +- 7 files changed, 309 insertions(+), 126 deletions(-) diff --git a/descriptor.h b/descriptor.h index 82ff6da..989761b 100644 --- a/descriptor.h +++ b/descriptor.h @@ -17,7 +17,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "basetypes.h" // Make sure we use right packing rules -#pragma pack(push,1) +#pragma pack(push, 1) // Flash descriptor header typedef struct _FLASH_DESCRIPTOR_HEADER { @@ -34,37 +34,38 @@ typedef struct _FLASH_DESCRIPTOR_HEADER { // Descriptor map // Base fields are storing bits [11:4] of actual base addresses, all other bits are 0 typedef struct _FLASH_DESCRIPTOR_MAP { - UINT8 ComponentBase; // 0x03 on most machines - UINT8 NumberOfFlashChips; // Zero-based number of flash chips installed on board - UINT8 RegionBase; // 0x04 on most machines - UINT8 NumberOfRegions; // Zero-based number of flash regions (descriptor is always included) - UINT8 MasterBase; // 0x06 on most machines - UINT8 NumberOfMasters; // Zero-based number of flash masters - UINT8 PchStrapsBase; // 0x10 on most machines - UINT8 NumberOfPchStraps; // One-based number of UINT32s to read as PCH Straps, min=0, max=255 (1 Kb) - UINT8 ProcStrapsBase; // 0x20 on most machines - UINT8 NumberOfProcStraps; // Number of PROC straps to be read, can be 0 or 1 - UINT8 IccTableBase; // 0x21 on most machines - UINT8 NumberOfIccTableEntries; // 0x00 on most machines - UINT8 DmiTableBase; // 0x25 on most machines - UINT8 NumberOfDmiTableEntries; // 0x00 on most machines - UINT16 ReservedZero; // Still unknown, zeros in all descriptors I have seen + // FLMAP0 + UINT32 ComponentBase : 8; + UINT32 NumberOfFlashChips : 2; // Zero-based number of flash chips installed on board + UINT32 : 6; + UINT32 RegionBase : 8; + UINT32 : 8; + // FLMAP 1 + UINT32 MasterBase : 8; + UINT32 NumberOfMasters : 2; + UINT32 : 6; + UINT32 PchStrapsBase : 8; + UINT32 NumberOfPchStraps : 8; // One-based number of UINT32s to read as PCH straps, min=0, max=255 (1 Kb) + // FLMAP 2 + UINT32 ProcStrapsBase : 8; + UINT32 NumberOfProcStraps : 8; // One-based number of UINT32s to read as processor straps, min=0, max=255 (1 Kb) + UINT32: 16; } FLASH_DESCRIPTOR_MAP; // Component section // Flash parameters DWORD structure typedef struct _FLASH_PARAMETERS { - UINT8 FirstChipDensity : 3; - UINT8 SecondChipDensity : 3; - UINT8 ReservedZero0 : 2; // Still unknown, zeros in all descriptors I have seen - UINT8 ReservedZero1 : 8; // Still unknown, zeros in all descriptors I have seen - UINT8 ReservedZero2 : 4; // Still unknown, zeros in all descriptors I have seen + UINT8 FirstChipDensity : 4; + UINT8 SecondChipDensity : 4; + UINT8 : 8; + UINT8 : 1; + UINT8 ReadClockFreqency : 3; // Hardcoded value of 20 Mhz (000b) in v1 descriptors and 17 Mhz (110b) in v2 ones UINT8 FastReadEnabled : 1; UINT8 FastReadFreqency : 3; UINT8 FlashReadStatusFrequency : 3; UINT8 FlashWriteFrequency : 3; UINT8 DualOutputFastReadSupported : 1; - UINT8 ReservedZero3 : 1; // Still unknown, zero in all descriptors I have seen + UINT8 : 1; } FLASH_PARAMETERS; // Flash densities @@ -74,11 +75,16 @@ typedef struct _FLASH_PARAMETERS { #define FLASH_DENSITY_4MB 0x03 #define FLASH_DENSITY_8MB 0x04 #define FLASH_DENSITY_16MB 0x05 +#define FLASH_DENSITY_32MB 0x06 +#define FLASH_DENSITY_64MB 0x07 +#define FLASH_DENSITY_UNUSED 0x0F // Flash frequencies -#define FLASH_FREQUENCY_20MHZ 0x00 -#define FLASH_FREQUENCY_33MHZ 0x01 -#define FLASH_FREQUENCY_50MHZ 0x04 +#define FLASH_FREQUENCY_20MHZ 0x00 +#define FLASH_FREQUENCY_33MHZ 0x01 +#define FLASH_FREQUENCY_48MHZ 0x02 +#define FLASH_FREQUENCY_50MHZ_30MHZ 0x04 +#define FLASH_FREQUENCY_17MHZ 0x06 // Component section structure typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION { @@ -87,24 +93,45 @@ typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION { UINT8 InvalidInstruction1; // UINT8 InvalidInstruction2; // UINT8 InvalidInstruction3; // - UINT16 PartitionBoundary; // Upper 16 bit of partition boundary address. Default is 0x0000, which makes the boundary to be 0x00001000 - UINT16 ReservedZero; // Still unknown, zero in all descriptors I have seen } FLASH_DESCRIPTOR_COMPONENT_SECTION; +// Component section structure +typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION_V2 { + FLASH_PARAMETERS FlashParameters; + UINT8 InvalidInstruction0; // Instructions for SPI chip, that must not be executed, like FLASH ERASE + UINT8 InvalidInstruction1; // + UINT8 InvalidInstruction2; // + UINT8 InvalidInstruction3; // + UINT8 InvalidInstruction4; // + UINT8 InvalidInstruction5; // + UINT8 InvalidInstruction6; // + UINT8 InvalidInstruction7; // +} FLASH_DESCRIPTOR_COMPONENT_SECTION_V2; + // Region section // All base and limit register are storing upper part of actual UINT32 base and limit // If limit is zero - region is not present typedef struct _FLASH_DESCRIPTOR_REGION_SECTION { - UINT16 ReservedZero; // Still unknown, zero in all descriptors I have seen + UINT16 :16; UINT16 FlashBlockEraseSize; // Size of block erased by single BLOCK ERASE command - UINT16 BiosBase; - UINT16 BiosLimit; - UINT16 MeBase; - UINT16 MeLimit; - UINT16 GbeBase; - UINT16 GbeLimit; - UINT16 PdrBase; - UINT16 PdrLimit; + UINT16 Region0Base; // BIOS + UINT16 Region0Limit; // + UINT16 Region1Base; // ME + UINT16 Region1Limit; // + UINT16 Region2Base; // GbE + UINT16 Region2Limit; // + UINT16 Region3Base; // PDR + UINT16 Region3Limit; // + UINT16 Region4Base; // Reserved region + UINT16 Region4Limit; // + UINT16 Region5Base; // Reserved region + UINT16 Region5Limit; // + UINT16 Region6Base; // Reserved region + UINT16 Region6Limit; // + UINT16 Region7Base; // Reserved region + UINT16 Region7Limit; // + UINT16 Region8Base; // EC + UINT16 Region8Limit; // } FLASH_DESCRIPTOR_REGION_SECTION; // Flash block erase sizes @@ -115,24 +142,40 @@ typedef struct _FLASH_DESCRIPTOR_REGION_SECTION { // Master section typedef struct _FLASH_DESCRIPTOR_MASTER_SECTION { UINT16 BiosId; - UINT8 BiosRead; - UINT8 BiosWrite; + UINT8 BiosRead; + UINT8 BiosWrite; UINT16 MeId; - UINT8 MeRead; - UINT8 MeWrite; + UINT8 MeRead; + UINT8 MeWrite; UINT16 GbeId; - UINT8 GbeRead; - UINT8 GbeWrite; + UINT8 GbeRead; + UINT8 GbeWrite; } FLASH_DESCRIPTOR_MASTER_SECTION; +// Master section v2 (Skylake+) +typedef struct _FLASH_DESCRIPTOR_MASTER_SECTION_V2 { + UINT32 : 8; + UINT32 BiosRead : 12; + UINT32 BiosWrite : 12; + UINT32 : 8; + UINT32 MeRead : 12; + UINT32 MeWrite : 12; + UINT32 : 8; + UINT32 GbeRead : 12; + UINT32 GbeWrite : 12; + UINT32 :32; + UINT32 : 8; + UINT32 EcRead : 12; + UINT32 EcWrite : 12; +} FLASH_DESCRIPTOR_MASTER_SECTION_V2; + // Region access bits in master section #define FLASH_DESCRIPTOR_REGION_ACCESS_DESC 0x01 #define FLASH_DESCRIPTOR_REGION_ACCESS_BIOS 0x02 #define FLASH_DESCRIPTOR_REGION_ACCESS_ME 0x04 #define FLASH_DESCRIPTOR_REGION_ACCESS_GBE 0x08 #define FLASH_DESCRIPTOR_REGION_ACCESS_PDR 0x10 - -//!TODO: Describe PCH and PROC straps sections, as well as ICC and DMI tables +#define FLASH_DESCRIPTOR_REGION_ACCESS_EC 0x20 // Base address of descriptor upper map #define FLASH_DESCRIPTOR_UPPER_MAP_BASE 0x0EFC diff --git a/ffs.h b/ffs.h index 0bb8221..0adc031 100644 --- a/ffs.h +++ b/ffs.h @@ -53,10 +53,6 @@ const QByteArray EFI_CAPSULE_GUID const QByteArray INTEL_CAPSULE_GUID ("\xB9\x82\x91\x53\xB5\xAB\x91\x43\xB6\x9A\xE3\xA9\x43\xF7\x2F\xCC", 16); -// Lenovo capsule GUID -const QByteArray LENOVO_CAPSULE_GUID -("\x8B\xA6\x3C\x4A\x23\x77\xFB\x48\x80\x3D\x57\x8C\xC1\xFE\xC4\x4D", 16); - // Toshiba EFI Capsule header typedef struct _TOSHIBA_CAPSULE_HEADER { EFI_GUID CapsuleGuid; diff --git a/ffsengine.cpp b/ffsengine.cpp index d516019..985ea38 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -155,8 +155,7 @@ UINT8 FfsEngine::parseImageFile(const QByteArray & buffer) UINT32 capsuleHeaderSize = 0; QModelIndex index; if (buffer.startsWith(EFI_CAPSULE_GUID) - || buffer.startsWith(INTEL_CAPSULE_GUID) - || buffer.startsWith(LENOVO_CAPSULE_GUID)) { + || buffer.startsWith(INTEL_CAPSULE_GUID)) { // Get info const EFI_CAPSULE_HEADER* capsuleHeader = (const EFI_CAPSULE_HEADER*)buffer.constData(); capsuleHeaderSize = capsuleHeader->HeaderSize; @@ -266,45 +265,36 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in const FLASH_DESCRIPTOR_MAP* descriptorMap = (const FLASH_DESCRIPTOR_MAP*)(descriptor + sizeof(FLASH_DESCRIPTOR_HEADER)); const FLASH_DESCRIPTOR_UPPER_MAP* upperMap = (const FLASH_DESCRIPTOR_UPPER_MAP*)(descriptor + FLASH_DESCRIPTOR_UPPER_MAP_BASE); const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8(descriptor, descriptorMap->RegionBase); - const FLASH_DESCRIPTOR_MASTER_SECTION* masterSection = (const FLASH_DESCRIPTOR_MASTER_SECTION*)calculateAddress8(descriptor, descriptorMap->MasterBase); + const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8(descriptor, descriptorMap->ComponentBase); - // GbE region - QByteArray gbe; - UINT32 gbeBegin = 0; - UINT32 gbeEnd = 0; - if (regionSection->GbeLimit) { - gbeBegin = calculateRegionOffset(regionSection->GbeBase); - gbeEnd = calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit); - gbe = intelImage.mid(gbeBegin, gbeEnd); - gbeEnd += gbeBegin; + // Check descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency + UINT8 descriptorVersion = 0; + if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_20MHZ) // Old descriptor + descriptorVersion = 1; + else if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_17MHZ) // Skylake+ descriptor + descriptorVersion = 2; + else { + msg(tr("parseIntelImage: unknown descriptor version with ReadClockFreqency %1h").hexarg(componentSection->FlashParameters.ReadClockFreqency)); + return ERR_INVALID_FLASH_DESCRIPTOR; } + // ME region QByteArray me; UINT32 meBegin = 0; UINT32 meEnd = 0; - if (regionSection->MeLimit) { - meBegin = calculateRegionOffset(regionSection->MeBase); - meEnd = calculateRegionSize(regionSection->MeBase, regionSection->MeLimit); + if (regionSection->Region1Limit) { + meBegin = calculateRegionOffset(regionSection->Region1Base); + meEnd = calculateRegionSize(regionSection->Region1Base, regionSection->Region1Limit); me = intelImage.mid(meBegin, meEnd); meEnd += meBegin; } - // PDR region - QByteArray pdr; - UINT32 pdrBegin = 0; - UINT32 pdrEnd = 0; - if (regionSection->PdrLimit) { - pdrBegin = calculateRegionOffset(regionSection->PdrBase); - pdrEnd = calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit); - pdr = intelImage.mid(pdrBegin, pdrEnd); - pdrEnd += pdrBegin; - } // BIOS region QByteArray bios; UINT32 biosBegin = 0; UINT32 biosEnd = 0; - if (regionSection->BiosLimit) { - biosBegin = calculateRegionOffset(regionSection->BiosBase); - biosEnd = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); + if (regionSection->Region0Limit) { + biosBegin = calculateRegionOffset(regionSection->Region0Base); + biosEnd = calculateRegionSize(regionSection->Region0Base, regionSection->Region0Limit); // Check for Gigabyte specific descriptor map if (biosEnd - biosBegin == (UINT32)intelImage.size()) { @@ -322,8 +312,41 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, BIOS region not found in descriptor")); return ERR_INVALID_FLASH_DESCRIPTOR; } + // GbE region + QByteArray gbe; + UINT32 gbeBegin = 0; + UINT32 gbeEnd = 0; + if (regionSection->Region2Limit) { + gbeBegin = calculateRegionOffset(regionSection->Region2Base); + gbeEnd = calculateRegionSize(regionSection->Region2Base, regionSection->Region2Limit); + gbe = intelImage.mid(gbeBegin, gbeEnd); + gbeEnd += gbeBegin; + } + // PDR region + QByteArray pdr; + UINT32 pdrBegin = 0; + UINT32 pdrEnd = 0; + if (regionSection->Region3Limit) { + pdrBegin = calculateRegionOffset(regionSection->Region3Base); + pdrEnd = calculateRegionSize(regionSection->Region3Base, regionSection->Region3Limit); + pdr = intelImage.mid(pdrBegin, pdrEnd); + pdrEnd += pdrBegin; + } + // EC region + QByteArray ec; + UINT32 ecBegin = 0; + UINT32 ecEnd = 0; + if (descriptorVersion == 2) { + if (regionSection->Region8Limit) { + pdrBegin = calculateRegionOffset(regionSection->Region8Base); + pdrEnd = calculateRegionSize(regionSection->Region8Base, regionSection->Region8Limit); + pdr = intelImage.mid(ecBegin, ecEnd); + ecEnd += ecBegin; + } + } // Check for intersections between regions + // Descriptor if (hasIntersection(descriptorBegin, descriptorEnd, gbeBegin, gbeEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, descriptor region has intersection with GbE region")); return ERR_INVALID_FLASH_DESCRIPTOR; @@ -340,6 +363,11 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, descriptor region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } + if (descriptorVersion == 2 && hasIntersection(descriptorBegin, descriptorEnd, ecBegin, ecEnd)) { + msg(tr("parseIntelImage: descriptor parsing failed, descriptor region has intersection with EC region")); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + // GbE if (hasIntersection(gbeBegin, gbeEnd, meBegin, meEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, GbE region has intersection with ME region")); return ERR_INVALID_FLASH_DESCRIPTOR; @@ -352,6 +380,11 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, GbE region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } + if (descriptorVersion == 2 && hasIntersection(gbeBegin, gbeEnd, ecBegin, ecEnd)) { + msg(tr("parseIntelImage: descriptor parsing failed, GbE region has intersection with EC region")); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + // ME if (hasIntersection(meBegin, meEnd, biosBegin, biosEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, ME region has intersection with BIOS region")); return ERR_INVALID_FLASH_DESCRIPTOR; @@ -360,23 +393,35 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, ME region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } + if (descriptorVersion == 2 && hasIntersection(meBegin, meEnd, ecBegin, ecEnd)) { + msg(tr("parseIntelImage: descriptor parsing failed, ME region has intersection with EC region")); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + // BIOS if (hasIntersection(biosBegin, biosEnd, pdrBegin, pdrEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, BIOS region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } + if (descriptorVersion == 2 && hasIntersection(biosBegin, biosEnd, ecBegin, ecEnd)) { + msg(tr("parseIntelImage: descriptor parsing failed, BIOS region has intersection with EC region")); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + // PDR + if (descriptorVersion == 2 && hasIntersection(pdrBegin, pdrEnd, ecBegin, ecEnd)) { + msg(tr("parseIntelImage: descriptor parsing failed, PDR region has intersection with EC region")); + return ERR_INVALID_FLASH_DESCRIPTOR; + } // Region map is consistent // Intel image QString name = tr("Intel image"); - QString info = tr("Full size: %1h (%2)\nFlash chips: %3\nRegions: %4\nMasters: %5\nPCH straps: %6\nPROC straps: %7\nICC table entries: %8") + QString info = tr("Full size: %1h (%2)\nFlash chips: %3\nMasters: %4\nPCH straps: %5\nCPU straps: %6\n") .hexarg(intelImage.size()).arg(intelImage.size()) - .arg(descriptorMap->NumberOfFlashChips + 1) // - .arg(descriptorMap->NumberOfRegions + 1) // Zero-based numbers in storage - .arg(descriptorMap->NumberOfMasters + 1) // + .arg(descriptorMap->NumberOfFlashChips + 1) + .arg(descriptorMap->NumberOfMasters + 1) .arg(descriptorMap->NumberOfPchStraps) - .arg(descriptorMap->NumberOfProcStraps) - .arg(descriptorMap->NumberOfIccTableEntries); + .arg(descriptorMap->NumberOfProcStraps); // Add Intel image tree item index = model->addItem(Types::Image, Subtypes::IntelImage, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), intelImage, parent); @@ -389,49 +434,89 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in // Check regions presence once again QVector offsets; - if (regionSection->GbeLimit) { + if (regionSection->Region2Limit) { offsets.append(gbeBegin); info += tr("\nGbE region offset: %1h").hexarg(gbeBegin); } - if (regionSection->MeLimit) { + if (regionSection->Region1Limit) { offsets.append(meBegin); info += tr("\nME region offset: %1h").hexarg(meBegin); } - if (regionSection->BiosLimit) { + if (regionSection->Region0Limit) { offsets.append(biosBegin); info += tr("\nBIOS region offset: %1h").hexarg(biosBegin); } - if (regionSection->PdrLimit) { + if (regionSection->Region3Limit) { offsets.append(pdrBegin); info += tr("\nPDR region offset: %1h").hexarg(pdrBegin); } + if (descriptorVersion == 2 && regionSection->Region8Limit) { + offsets.append(ecBegin); + info += tr("\nEC region offset: %1h").hexarg(ecBegin); + } // Region access settings - info += tr("\nRegion access settings:"); - info += tr("\nBIOS:%1%2h ME:%3%4h GbE:%5%6h") - .hexarg2(masterSection->BiosRead, 2) - .hexarg2(masterSection->BiosWrite, 2) - .hexarg2(masterSection->MeRead, 2) - .hexarg2(masterSection->MeWrite, 2) - .hexarg2(masterSection->GbeRead, 2) - .hexarg2(masterSection->GbeWrite, 2); + if (descriptorVersion == 1) { + const FLASH_DESCRIPTOR_MASTER_SECTION* masterSection = (const FLASH_DESCRIPTOR_MASTER_SECTION*)calculateAddress8(descriptor, descriptorMap->MasterBase); + info += tr("\nRegion access settings:"); + info += tr("\nBIOS:%1%2h ME:%3%4h GbE:%5%6h") + .hexarg2(masterSection->BiosRead, 2) + .hexarg2(masterSection->BiosWrite, 2) + .hexarg2(masterSection->MeRead, 2) + .hexarg2(masterSection->MeWrite, 2) + .hexarg2(masterSection->GbeRead, 2) + .hexarg2(masterSection->GbeWrite, 2); - // BIOS access table - info += tr("\nBIOS access table:"); - info += tr("\n Read Write"); - info += tr("\nDesc %1 %2") - .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? "Yes " : "No ") - .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? "Yes " : "No "); - info += tr("\nBIOS Yes Yes"); - info += tr("\nME %1 %2") - .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? "Yes " : "No ") - .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? "Yes " : "No "); - info += tr("\nGbE %1 %2") - .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? "Yes " : "No ") - .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? "Yes " : "No "); - info += tr("\nPDR %1 %2") - .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No ") - .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No "); + // BIOS access table + info += tr("\nBIOS access table:"); + info += tr("\n Read Write"); + info += tr("\nDesc %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? "Yes " : "No "); + info += tr("\nBIOS Yes Yes"); + info += tr("\nME %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? "Yes " : "No "); + info += tr("\nGbE %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? "Yes " : "No "); + info += tr("\nPDR %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No "); + } + else if (descriptorVersion == 2) { + const FLASH_DESCRIPTOR_MASTER_SECTION_V2* masterSection = (const FLASH_DESCRIPTOR_MASTER_SECTION_V2*)calculateAddress8(descriptor, descriptorMap->MasterBase); + info += tr("\nRegion access settings:"); + info += tr("\nBIOS: %1h %2h ME: %3h %4h\nGbE: %5h %6h EC: %7h %8h") + .hexarg2(masterSection->BiosRead, 3) + .hexarg2(masterSection->BiosWrite, 3) + .hexarg2(masterSection->MeRead, 3) + .hexarg2(masterSection->MeWrite, 3) + .hexarg2(masterSection->GbeRead, 3) + .hexarg2(masterSection->GbeWrite, 3) + .hexarg2(masterSection->EcRead, 3) + .hexarg2(masterSection->EcWrite, 3); + + // BIOS access table + info += tr("\nBIOS access table:"); + info += tr("\n Read Write"); + info += tr("\nDesc %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_DESC ? "Yes " : "No "); + info += tr("\nBIOS Yes Yes"); + info += tr("\nME %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_ME ? "Yes " : "No "); + info += tr("\nGbE %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_GBE ? "Yes " : "No "); + info += tr("\nPDR %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No "); + info += tr("\nEC %1 %2") + .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_EC ? "Yes " : "No ") + .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_EC ? "Yes " : "No "); + } // VSCC table const VSCC_TABLE_ENTRY* vsccTableEntry = (const VSCC_TABLE_ENTRY*)(descriptor + ((UINT16)upperMap->VsccTableBase << 4)); @@ -474,6 +559,11 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in QModelIndex pdrIndex; result = parsePdrRegion(pdr, pdrIndex, index); } + // Parse EC region + else if (descriptorVersion == 2 && offsets.at(i) == ecBegin) { + QModelIndex ecIndex; + result = parseEcRegion(ec, ecIndex, index); + } if (result) return result; } @@ -489,6 +579,8 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in IntelDataEnd = biosEnd; else if (LastRegionOffset == pdrBegin) IntelDataEnd = pdrEnd; + else if (descriptorVersion == 2 && LastRegionOffset == ecBegin) + IntelDataEnd = ecEnd; if (IntelDataEnd > (UINT32)intelImage.size()) { // Image file is truncated msg(tr("parseIntelImage: image size %1 (%2) is smaller than the end of last region %3 (%4), may be damaged") @@ -615,6 +707,23 @@ UINT8 FfsEngine::parsePdrRegion(const QByteArray & pdr, QModelIndex & index, con return ERR_SUCCESS; } +UINT8 FfsEngine::parseEcRegion(const QByteArray & ec, QModelIndex & index, const QModelIndex & parent, const UINT8 mode) +{ + // Check sanity + if (ec.isEmpty()) + return ERR_EMPTY_REGION; + + // Get info + QString name = tr("EC region"); + QString info = tr("Full size: %1h (%2)"). + hexarg(ec.size()).arg(ec.size()); + + // Add tree item + index = model->addItem(Types::Region, Subtypes::EcRegion, COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), ec, parent, mode); + + return ERR_SUCCESS; +} + UINT8 FfsEngine::parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent, const UINT8 mode) { if (bios.isEmpty()) @@ -928,10 +1037,10 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // All the rest is either free space or non-UEFI data QByteArray rest = volume.right(volumeSize - fileOffset); if (rest.count(empty) == rest.size()) { // It's a free space - model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index, mode); + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index); } else { //It's non-UEFI data - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index, mode); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index); msg(tr("parseVolume: non-UEFI data found in volume's free space"), dataIndex); } // Exit from loop @@ -973,16 +1082,16 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Add all bytes before as free space... if (i > 0) { QByteArray free = freeSpace.left(i); - model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()), QByteArray(), free, index, mode); + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(free.size()).arg(free.size()), QByteArray(), free, index); } // ... and all bytes after as a padding QByteArray padding = freeSpace.mid(i); - QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, index, mode); + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(padding.size()).arg(padding.size()), QByteArray(), padding, index); msg(tr("parseVolume: non-UEFI data found in volume's free space"), dataIndex); } else { // Add free space element - model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(freeSpace.size()).arg(freeSpace.size()), QByteArray(), freeSpace, index, mode); + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(freeSpace.size()).arg(freeSpace.size()), QByteArray(), freeSpace, index); } break; // Exit from loop } @@ -1989,7 +2098,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte if (header.isEmpty()) // Whole volume volume.append(body); else { // Body only - volume.append(model->header(index)).append(body); + volume.append(header).append(body); INT32 sizeDiff = model->body(index).size() - body.size(); if (sizeDiff > 0) { const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)model->header(index).constData(); @@ -2704,17 +2813,37 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec const FLASH_DESCRIPTOR_MAP* descriptorMap = (const FLASH_DESCRIPTOR_MAP*)(descriptor.constData() + sizeof(FLASH_DESCRIPTOR_HEADER)); const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->RegionBase); QByteArray gbe; - UINT32 gbeBegin = calculateRegionOffset(regionSection->GbeBase); - UINT32 gbeEnd = gbeBegin + calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit); + UINT32 gbeBegin = calculateRegionOffset(regionSection->Region2Base); + UINT32 gbeEnd = gbeBegin + calculateRegionSize(regionSection->Region2Base, regionSection->Region2Limit); QByteArray me; - UINT32 meBegin = calculateRegionOffset(regionSection->MeBase); - UINT32 meEnd = meBegin + calculateRegionSize(regionSection->MeBase, regionSection->MeLimit); + UINT32 meBegin = calculateRegionOffset(regionSection->Region1Base); + UINT32 meEnd = meBegin + calculateRegionSize(regionSection->Region1Base, regionSection->Region1Limit); QByteArray bios; - UINT32 biosBegin = calculateRegionOffset(regionSection->BiosBase); - UINT32 biosEnd = biosBegin + calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); + UINT32 biosBegin = calculateRegionOffset(regionSection->Region0Base); + UINT32 biosEnd = biosBegin + calculateRegionSize(regionSection->Region0Base, regionSection->Region0Limit); QByteArray pdr; - UINT32 pdrBegin = calculateRegionOffset(regionSection->PdrBase); - UINT32 pdrEnd = pdrBegin + calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit); + UINT32 pdrBegin = calculateRegionOffset(regionSection->Region3Base); + UINT32 pdrEnd = pdrBegin + calculateRegionSize(regionSection->Region3Base, regionSection->Region3Limit); + QByteArray ec; + UINT32 ecBegin = 0; + UINT32 ecEnd = 0; + + const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->ComponentBase); + // Check descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency + UINT8 descriptorVersion = 0; + if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_20MHZ) { // Old descriptor + descriptorVersion = 1; + } + else if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_17MHZ) { // Skylake+ descriptor + descriptorVersion = 2; + ecBegin = calculateRegionOffset(regionSection->Region8Base); + ecEnd = ecBegin + calculateRegionSize(regionSection->Region8Base, regionSection->Region8Limit); + } + else { + msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFreqency %1h").hexarg(componentSection->FlashParameters.ReadClockFreqency)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + UINT32 offset = descriptor.size(); // Reconstruct other regions @@ -2764,6 +2893,17 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec reconstructed.append(pdr); offset = pdrEnd; break; + case Subtypes::EcRegion: + if (descriptorVersion == 1) { + msg(tr("reconstructIntelImage: incompatible region type found"), index); + return ERR_INVALID_REGION; + } + ec = region; + if (ecBegin > offset) + reconstructed.append(QByteArray(ecBegin - offset, empty)); + reconstructed.append(ec); + offset = ecEnd; + break; default: msg(tr("reconstructIntelImage: unknown region type found"), index); return ERR_INVALID_REGION; diff --git a/ffsengine.h b/ffsengine.h index 281aa6e..c565921 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -67,6 +67,7 @@ public: UINT8 parseMeRegion(const QByteArray & me, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseBiosRegion(const QByteArray & bios, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); UINT8 parsePdrRegion(const QByteArray & pdr, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); + UINT8 parseEcRegion(const QByteArray & ec, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex()); UINT8 parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseFile(const QByteArray & file, QModelIndex & index, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); diff --git a/types.cpp b/types.cpp index 17ca51f..a9a9300 100644 --- a/types.cpp +++ b/types.cpp @@ -29,6 +29,8 @@ QString regionTypeToQString(const UINT8 type) return QObject::tr("BIOS"); case Subtypes::PdrRegion: return QObject::tr("PDR"); + case Subtypes::EcRegion: + return QObject::tr("EC"); default: return QObject::tr("Unknown"); }; diff --git a/types.h b/types.h index 64df300..7d71953 100644 --- a/types.h +++ b/types.h @@ -69,7 +69,8 @@ namespace Subtypes { GbeRegion, MeRegion, BiosRegion, - PdrRegion + PdrRegion, + EcRegion }; enum PaddingSubtypes { diff --git a/uefitool.cpp b/uefitool.cpp index 5a4ef55..39d77ce 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.20.8")) +version(tr("0.21.0")) { clipboard = QApplication::clipboard(); From c286459676c8ca41a3066c8e23f9c43932597980 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 6 Sep 2015 23:51:50 +0200 Subject: [PATCH 10/64] UP 0.3.6 - changed version number due to rebuild with engine version 0.21.0 --- UEFIPatch/uefipatch_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 6f37b1f..f1642d0 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.5 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.6 - 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; From 8a149654630a3fa1f02a5d745563ee4630d0146c Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Tue, 8 Sep 2015 08:54:42 +0200 Subject: [PATCH 11/64] Spellchecking Corrections of issue #32 --- descriptor.h | 22 +++++++++++----------- ffs.cpp | 2 +- ffsengine.cpp | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/descriptor.h b/descriptor.h index 989761b..bd4c996 100644 --- a/descriptor.h +++ b/descriptor.h @@ -36,19 +36,20 @@ typedef struct _FLASH_DESCRIPTOR_HEADER { typedef struct _FLASH_DESCRIPTOR_MAP { // FLMAP0 UINT32 ComponentBase : 8; - UINT32 NumberOfFlashChips : 2; // Zero-based number of flash chips installed on board + UINT32 NumberOfFlashChips : 2; // Zero-based number of flash chips installed on board UINT32 : 6; - UINT32 RegionBase : 8; - UINT32 : 8; + UINT32 RegionBase : 8; + UINT32 NumberOfRegions : 3; // Reserved in v2 descriptor + UINT32 : 5; // FLMAP 1 UINT32 MasterBase : 8; UINT32 NumberOfMasters : 2; UINT32 : 6; UINT32 PchStrapsBase : 8; - UINT32 NumberOfPchStraps : 8; // One-based number of UINT32s to read as PCH straps, min=0, max=255 (1 Kb) + UINT32 NumberOfPchStraps : 8; // One-based number of UINT32s to read as PCH straps, min=0, max=255 (1 Kb) // FLMAP 2 UINT32 ProcStrapsBase : 8; - UINT32 NumberOfProcStraps : 8; // One-based number of UINT32s to read as processor straps, min=0, max=255 (1 Kb) + UINT32 NumberOfProcStraps : 8; // One-based number of UINT32s to read as processor straps, min=0, max=255 (1 Kb) UINT32: 16; } FLASH_DESCRIPTOR_MAP; @@ -59,11 +60,11 @@ typedef struct _FLASH_PARAMETERS { UINT8 SecondChipDensity : 4; UINT8 : 8; UINT8 : 1; - UINT8 ReadClockFreqency : 3; // Hardcoded value of 20 Mhz (000b) in v1 descriptors and 17 Mhz (110b) in v2 ones + UINT8 ReadClockFrequency : 3; // Hardcoded value of 20 Mhz (000b) in v1 descriptors and 17 Mhz (110b) in v2 ones UINT8 FastReadEnabled : 1; - UINT8 FastReadFreqency : 3; - UINT8 FlashReadStatusFrequency : 3; + UINT8 FastReadFrequency : 3; UINT8 FlashWriteFrequency : 3; + UINT8 FlashReadStatusFrequency : 3; UINT8 DualOutputFastReadSupported : 1; UINT8 : 1; } FLASH_PARAMETERS; @@ -112,8 +113,7 @@ typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION_V2 { // All base and limit register are storing upper part of actual UINT32 base and limit // If limit is zero - region is not present typedef struct _FLASH_DESCRIPTOR_REGION_SECTION { - UINT16 :16; - UINT16 FlashBlockEraseSize; // Size of block erased by single BLOCK ERASE command + UINT32 :32; UINT16 Region0Base; // BIOS UINT16 Region0Limit; // UINT16 Region1Base; // ME @@ -198,7 +198,7 @@ typedef struct _VSCC_TABLE_ENTRY { // Base address and size of OEM section #define FLASH_DESCRIPTOR_OEM_SECTION_BASE 0x0F00 -#define FLASH_DESCRIPTOR_OEM_SECTION_SIZE 0xFF +#define FLASH_DESCRIPTOR_OEM_SECTION_SIZE 0x100 // Restore previous packing rules #pragma pack(pop) diff --git a/ffs.cpp b/ffs.cpp index fcdf03f..33410c3 100644 --- a/ffs.cpp +++ b/ffs.cpp @@ -155,7 +155,7 @@ UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header) if (!header) return 0; - bool extended = false; + const bool extended = false; /*if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) { extended = true; }*/ diff --git a/ffsengine.cpp b/ffsengine.cpp index 985ea38..42f0a7b 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -269,12 +269,12 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in // Check descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency UINT8 descriptorVersion = 0; - if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_20MHZ) // Old descriptor + if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) // Old descriptor descriptorVersion = 1; - else if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_17MHZ) // Skylake+ descriptor + else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ) // Skylake+ descriptor descriptorVersion = 2; else { - msg(tr("parseIntelImage: unknown descriptor version with ReadClockFreqency %1h").hexarg(componentSection->FlashParameters.ReadClockFreqency)); + msg(tr("parseIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -2831,16 +2831,16 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->ComponentBase); // Check descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency UINT8 descriptorVersion = 0; - if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_20MHZ) { // Old descriptor + if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) { // Old descriptor descriptorVersion = 1; } - else if (componentSection->FlashParameters.ReadClockFreqency == FLASH_FREQUENCY_17MHZ) { // Skylake+ descriptor + else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ) { // Skylake+ descriptor descriptorVersion = 2; ecBegin = calculateRegionOffset(regionSection->Region8Base); ecEnd = ecBegin + calculateRegionSize(regionSection->Region8Base, regionSection->Region8Limit); } else { - msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFreqency %1h").hexarg(componentSection->FlashParameters.ReadClockFreqency)); + msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); return ERR_INVALID_FLASH_DESCRIPTOR; } From e5cf61f89a639ce77197b9e8a8ba129b58196f5c Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sat, 12 Sep 2015 19:44:59 +0200 Subject: [PATCH 12/64] Small fixes of FLASH_DESCRIPTOR_REGION_SECTION definition --- descriptor.h | 46 ++++++++++++++++++--------------------- ffsengine.cpp | 60 +++++++++++++++++++++++++-------------------------- 2 files changed, 51 insertions(+), 55 deletions(-) diff --git a/descriptor.h b/descriptor.h index bd4c996..579e600 100644 --- a/descriptor.h +++ b/descriptor.h @@ -43,7 +43,7 @@ typedef struct _FLASH_DESCRIPTOR_MAP { UINT32 : 5; // FLMAP 1 UINT32 MasterBase : 8; - UINT32 NumberOfMasters : 2; + UINT32 NumberOfMasters : 2; // Zero-based number of flash masters UINT32 : 6; UINT32 PchStrapsBase : 8; UINT32 NumberOfPchStraps : 8; // One-based number of UINT32s to read as PCH straps, min=0, max=255 (1 Kb) @@ -113,32 +113,28 @@ typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION_V2 { // All base and limit register are storing upper part of actual UINT32 base and limit // If limit is zero - region is not present typedef struct _FLASH_DESCRIPTOR_REGION_SECTION { - UINT32 :32; - UINT16 Region0Base; // BIOS - UINT16 Region0Limit; // - UINT16 Region1Base; // ME - UINT16 Region1Limit; // - UINT16 Region2Base; // GbE - UINT16 Region2Limit; // - UINT16 Region3Base; // PDR - UINT16 Region3Limit; // - UINT16 Region4Base; // Reserved region - UINT16 Region4Limit; // - UINT16 Region5Base; // Reserved region - UINT16 Region5Limit; // - UINT16 Region6Base; // Reserved region - UINT16 Region6Limit; // - UINT16 Region7Base; // Reserved region - UINT16 Region7Limit; // - UINT16 Region8Base; // EC - UINT16 Region8Limit; // + UINT16 DescriptorBase; // Descriptor + UINT16 DescriptorLimit; // + UINT16 BiosBase; // BIOS + UINT16 BiosLimit; // + UINT16 MeBase; // ME + UINT16 MeLimit; // + UINT16 GbeBase; // GbE + UINT16 GbeLimit; // + UINT16 PdrBase; // PDR + UINT16 PdrLimit; // + UINT16 Region5Base; // Reserved region + UINT16 Region5Limit; // + UINT16 Region6Base; // Reserved region + UINT16 Region6Limit; // + UINT16 Region7Base; // Reserved region + UINT16 Region7Limit; // + UINT16 Region8Base; // Reserved region + UINT16 Region8Limit; // + UINT16 EcBase; // EC + UINT16 EcLimit; // } FLASH_DESCRIPTOR_REGION_SECTION; -// Flash block erase sizes -#define FLASH_BLOCK_ERASE_SIZE_4KB 0x0000 -#define FLASH_BLOCK_ERASE_SIZE_8KB 0x0001 -#define FLASH_BLOCK_ERASE_SIZE_64KB 0x000F - // Master section typedef struct _FLASH_DESCRIPTOR_MASTER_SECTION { UINT16 BiosId; diff --git a/ffsengine.cpp b/ffsengine.cpp index 42f0a7b..5556ae0 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -282,9 +282,9 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in QByteArray me; UINT32 meBegin = 0; UINT32 meEnd = 0; - if (regionSection->Region1Limit) { - meBegin = calculateRegionOffset(regionSection->Region1Base); - meEnd = calculateRegionSize(regionSection->Region1Base, regionSection->Region1Limit); + if (regionSection->MeLimit) { + meBegin = calculateRegionOffset(regionSection->MeBase); + meEnd = calculateRegionSize(regionSection->MeBase, regionSection->MeLimit); me = intelImage.mid(meBegin, meEnd); meEnd += meBegin; } @@ -292,9 +292,9 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in QByteArray bios; UINT32 biosBegin = 0; UINT32 biosEnd = 0; - if (regionSection->Region0Limit) { - biosBegin = calculateRegionOffset(regionSection->Region0Base); - biosEnd = calculateRegionSize(regionSection->Region0Base, regionSection->Region0Limit); + if (regionSection->BiosLimit) { + biosBegin = calculateRegionOffset(regionSection->BiosBase); + biosEnd = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); // Check for Gigabyte specific descriptor map if (biosEnd - biosBegin == (UINT32)intelImage.size()) { @@ -316,9 +316,9 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in QByteArray gbe; UINT32 gbeBegin = 0; UINT32 gbeEnd = 0; - if (regionSection->Region2Limit) { - gbeBegin = calculateRegionOffset(regionSection->Region2Base); - gbeEnd = calculateRegionSize(regionSection->Region2Base, regionSection->Region2Limit); + if (regionSection->GbeLimit) { + gbeBegin = calculateRegionOffset(regionSection->GbeBase); + gbeEnd = calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit); gbe = intelImage.mid(gbeBegin, gbeEnd); gbeEnd += gbeBegin; } @@ -326,9 +326,9 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in QByteArray pdr; UINT32 pdrBegin = 0; UINT32 pdrEnd = 0; - if (regionSection->Region3Limit) { - pdrBegin = calculateRegionOffset(regionSection->Region3Base); - pdrEnd = calculateRegionSize(regionSection->Region3Base, regionSection->Region3Limit); + if (regionSection->PdrLimit) { + pdrBegin = calculateRegionOffset(regionSection->PdrBase); + pdrEnd = calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit); pdr = intelImage.mid(pdrBegin, pdrEnd); pdrEnd += pdrBegin; } @@ -337,9 +337,9 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in UINT32 ecBegin = 0; UINT32 ecEnd = 0; if (descriptorVersion == 2) { - if (regionSection->Region8Limit) { - pdrBegin = calculateRegionOffset(regionSection->Region8Base); - pdrEnd = calculateRegionSize(regionSection->Region8Base, regionSection->Region8Limit); + if (regionSection->EcLimit) { + pdrBegin = calculateRegionOffset(regionSection->EcBase); + pdrEnd = calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); pdr = intelImage.mid(ecBegin, ecEnd); ecEnd += ecBegin; } @@ -434,23 +434,23 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in // Check regions presence once again QVector offsets; - if (regionSection->Region2Limit) { + if (regionSection->GbeLimit) { offsets.append(gbeBegin); info += tr("\nGbE region offset: %1h").hexarg(gbeBegin); } - if (regionSection->Region1Limit) { + if (regionSection->MeLimit) { offsets.append(meBegin); info += tr("\nME region offset: %1h").hexarg(meBegin); } - if (regionSection->Region0Limit) { + if (regionSection->BiosLimit) { offsets.append(biosBegin); info += tr("\nBIOS region offset: %1h").hexarg(biosBegin); } - if (regionSection->Region3Limit) { + if (regionSection->PdrLimit) { offsets.append(pdrBegin); info += tr("\nPDR region offset: %1h").hexarg(pdrBegin); } - if (descriptorVersion == 2 && regionSection->Region8Limit) { + if (descriptorVersion == 2 && regionSection->EcLimit) { offsets.append(ecBegin); info += tr("\nEC region offset: %1h").hexarg(ecBegin); } @@ -2813,17 +2813,17 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec const FLASH_DESCRIPTOR_MAP* descriptorMap = (const FLASH_DESCRIPTOR_MAP*)(descriptor.constData() + sizeof(FLASH_DESCRIPTOR_HEADER)); const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->RegionBase); QByteArray gbe; - UINT32 gbeBegin = calculateRegionOffset(regionSection->Region2Base); - UINT32 gbeEnd = gbeBegin + calculateRegionSize(regionSection->Region2Base, regionSection->Region2Limit); + UINT32 gbeBegin = calculateRegionOffset(regionSection->GbeBase); + UINT32 gbeEnd = gbeBegin + calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit); QByteArray me; - UINT32 meBegin = calculateRegionOffset(regionSection->Region1Base); - UINT32 meEnd = meBegin + calculateRegionSize(regionSection->Region1Base, regionSection->Region1Limit); + UINT32 meBegin = calculateRegionOffset(regionSection->MeBase); + UINT32 meEnd = meBegin + calculateRegionSize(regionSection->MeBase, regionSection->MeLimit); QByteArray bios; - UINT32 biosBegin = calculateRegionOffset(regionSection->Region0Base); - UINT32 biosEnd = biosBegin + calculateRegionSize(regionSection->Region0Base, regionSection->Region0Limit); + UINT32 biosBegin = calculateRegionOffset(regionSection->BiosBase); + UINT32 biosEnd = biosBegin + calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); QByteArray pdr; - UINT32 pdrBegin = calculateRegionOffset(regionSection->Region3Base); - UINT32 pdrEnd = pdrBegin + calculateRegionSize(regionSection->Region3Base, regionSection->Region3Limit); + UINT32 pdrBegin = calculateRegionOffset(regionSection->PdrBase); + UINT32 pdrEnd = pdrBegin + calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit); QByteArray ec; UINT32 ecBegin = 0; UINT32 ecEnd = 0; @@ -2836,8 +2836,8 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec } else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ) { // Skylake+ descriptor descriptorVersion = 2; - ecBegin = calculateRegionOffset(regionSection->Region8Base); - ecEnd = ecBegin + calculateRegionSize(regionSection->Region8Base, regionSection->Region8Limit); + ecBegin = calculateRegionOffset(regionSection->EcBase); + ecEnd = ecBegin + calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); } else { msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); From 9c7c94702dd3b15cd5de3c56ff819cab0ccb9b0d Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sat, 12 Sep 2015 20:46:21 +0200 Subject: [PATCH 13/64] Replace action for paddings - and a very small visual bugfix --- ffsengine.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++++---- ffsengine.h | 1 + uefitool.cpp | 9 ++++++- uefitool.ui | 2 ++ 4 files changed, 77 insertions(+), 6 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 5556ae0..6848c3c 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -2093,6 +2093,18 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte // Set action model->setAction(fileIndex, action); } + else if (type == Types::Padding) { + // Get info + QString name = tr("Padding"); + QString info = tr("Full size: %1h (%2)") + .hexarg(body.size()).arg(body.size()); + + // Add tree item + QModelIndex fileIndex = model->addItem(Types::Padding, getPaddingType(body), COMPRESSION_ALGORITHM_NONE, name, "", info, QByteArray(), body, index, mode); + + // Set action + model->setAction(fileIndex, action); + } else if (type == Types::Volume) { QByteArray volume; if (header.isEmpty()) // Whole volume @@ -2351,6 +2363,12 @@ UINT8 FfsEngine::replace(const QModelIndex & index, const QByteArray & object, c else return ERR_NOT_IMPLEMENTED; } + else if (model->type(index) == Types::Padding) { + if (mode == REPLACE_MODE_AS_IS) + result = create(index, Types::Padding, QByteArray(), object, CREATE_MODE_AFTER, Actions::Replace); + else + return ERR_NOT_IMPLEMENTED; + } else if (model->type(index) == Types::Volume) { if (mode == REPLACE_MODE_AS_IS) { result = create(index, Types::Volume, QByteArray(), object, CREATE_MODE_AFTER, Actions::Replace); @@ -2973,14 +2991,14 @@ UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconst if (reconstructed.size() > model->body(index).size()) { msg(tr("reconstructRegion: reconstructed region size %1h (%2) is bigger then original %3h (%4)") .hexarg(reconstructed.size()).arg(reconstructed.size()) - .hexarg(model->body(index).size()).arg(reconstructed.size()), + .hexarg(model->body(index).size()).arg(model->body(index).size()), index); return ERR_INVALID_PARAMETER; } else if (reconstructed.size() < model->body(index).size()) { msg(tr("reconstructRegion: reconstructed region size %1h (%2) is smaller then original %3h (%4)") .hexarg(reconstructed.size()).arg(reconstructed.size()) - .hexarg(model->body(index).size()).arg(reconstructed.size()), + .hexarg(model->body(index).size()).arg(model->body(index).size()), index); return ERR_INVALID_PARAMETER; } @@ -2995,6 +3013,49 @@ UINT8 FfsEngine::reconstructRegion(const QModelIndex& index, QByteArray& reconst return ERR_NOT_IMPLEMENTED; } +UINT8 FfsEngine::reconstructPadding(const QModelIndex& index, QByteArray& reconstructed) +{ + if (!index.isValid()) + return ERR_SUCCESS; + + // No action + if (model->action(index) == Actions::NoAction) { + reconstructed = model->body(index); + return ERR_SUCCESS; + } + else if (model->action(index) == Actions::Remove) { + reconstructed.clear(); + return ERR_SUCCESS; + } + else if (model->action(index) == Actions::Rebuild || + model->action(index) == Actions::Replace) { + // Use stored item body + reconstructed = model->body(index); + + // Check size of reconstructed region, it must be same + if (reconstructed.size() > model->body(index).size()) { + msg(tr("reconstructPadding: reconstructed padding size %1h (%2) is bigger then original %3h (%4)") + .hexarg(reconstructed.size()).arg(reconstructed.size()) + .hexarg(model->body(index).size()).arg(model->body(index).size()), + index); + return ERR_INVALID_PARAMETER; + } + else if (reconstructed.size() < model->body(index).size()) { + msg(tr("reconstructPadding: reconstructed padding size %1h (%2) is smaller then original %3h (%4)") + .hexarg(reconstructed.size()).arg(reconstructed.size()) + .hexarg(model->body(index).size()).arg(model->body(index).size()), + index); + return ERR_INVALID_PARAMETER; + } + + // Reconstruction successful + return ERR_SUCCESS; + } + + // All other actions are not supported + return ERR_NOT_IMPLEMENTED; +} + UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & reconstructed) { if (!index.isValid()) @@ -3710,9 +3771,9 @@ UINT8 FfsEngine::reconstruct(const QModelIndex &index, QByteArray& reconstructed break; case Types::Padding: - // No reconstruction needed - reconstructed = model->header(index).append(model->body(index)); - return ERR_SUCCESS; + result = reconstructPadding(index, reconstructed); + if (result) + return result; break; case Types::Volume: diff --git a/ffsengine.h b/ffsengine.h index c565921..4fe5223 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -83,6 +83,7 @@ public: UINT8 reconstruct(const QModelIndex &index, QByteArray & reconstructed); 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); diff --git a/uefitool.cpp b/uefitool.cpp index 39d77ce..1689387 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -153,7 +153,7 @@ void UEFITool::populateUi(const QModelIndex ¤t) (type == Types::Section && (subtype == EFI_SECTION_COMPRESSION || subtype == EFI_SECTION_GUID_DEFINED || subtype == EFI_SECTION_DISPOSABLE))); ui->actionInsertBefore->setEnabled(type == Types::File || type == Types::Section); ui->actionInsertAfter->setEnabled(type == Types::File || type == Types::Section); - ui->actionReplace->setEnabled((type == Types::Region && subtype != Subtypes::DescriptorRegion) || type == Types::Volume || type == Types::File || type == Types::Section); + ui->actionReplace->setEnabled((type == Types::Region && subtype != Subtypes::DescriptorRegion) || type == Types::Padding || type == Types::Volume || type == Types::File || type == Types::Section); ui->actionReplaceBody->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section); ui->actionMessagesCopy->setEnabled(false); } @@ -327,6 +327,13 @@ void UEFITool::replace(const UINT8 mode) else return; } + else if (model->type(index) == Types::Padding) { + if (mode == REPLACE_MODE_AS_IS) { + path = QFileDialog::getOpenFileName(this, tr("Select padding file to replace selected object"), currentDir, "Padding files (*.pad *.bin);;All files (*)"); + } + else + return; + } else if (model->type(index) == Types::Volume) { if (mode == REPLACE_MODE_AS_IS) { path = QFileDialog::getOpenFileName(this, tr("Select volume file to replace selected object"), currentDir, "Volume files (*.vol *.bin);;All files (*)"); diff --git a/uefitool.ui b/uefitool.ui index 5b5953a..8e0a19d 100644 --- a/uefitool.ui +++ b/uefitool.ui @@ -232,6 +232,8 @@ &Padding + + From 4e8431b1695087817316bb1cdcbabd3f0ac496bf Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sat, 12 Sep 2015 21:01:42 +0200 Subject: [PATCH 14/64] UT 0.21.1 - added replace action for paddings - fixed a rare visual bug (wrong image sizes in reconstructRegion messages) - parts of the new flash region map are defined a bit better --- uefitool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uefitool.cpp b/uefitool.cpp index 1689387..3b63ae2 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.21.0")) +version(tr("0.21.1")) { clipboard = QApplication::clipboard(); From 93881e48920305ad8abb1c65ed680e7807cf3bb7 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sat, 12 Sep 2015 21:40:45 +0200 Subject: [PATCH 15/64] Corrected EC region placement --- descriptor.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/descriptor.h b/descriptor.h index 579e600..0de5476 100644 --- a/descriptor.h +++ b/descriptor.h @@ -129,8 +129,6 @@ typedef struct _FLASH_DESCRIPTOR_REGION_SECTION { UINT16 Region6Limit; // UINT16 Region7Base; // Reserved region UINT16 Region7Limit; // - UINT16 Region8Base; // Reserved region - UINT16 Region8Limit; // UINT16 EcBase; // EC UINT16 EcLimit; // } FLASH_DESCRIPTOR_REGION_SECTION; From ed038c21bfce62c8344a3c8868a2f4193bc9709e Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Thu, 1 Oct 2015 08:24:35 +0200 Subject: [PATCH 16/64] Corrected #34 - padding data was a part of the image, now BIOS region --- ffsengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 6848c3c..1a32bdb 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -589,7 +589,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in return ERR_TRUNCATED_IMAGE; } else if (IntelDataEnd < (UINT32)intelImage.size()) { // Insert padding - QByteArray padding = bios.right(intelImage.size() - IntelDataEnd); + QByteArray padding = intelImage.mid(IntelDataEnd); // Get info name = tr("Padding"); info = tr("Full size: %1h (%2)") From 388dd2509358997e81f36f5fea6e406ce202cf1b Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Fri, 2 Oct 2015 09:14:11 +0200 Subject: [PATCH 17/64] UT 0.21.2 - fixed a bug with tailed files extraction and replacing (#35) - fixed a bug with wrong source of padding after all Intel image regions (#34) --- ffsengine.cpp | 24 +++++++++++++++++------- uefitool.cpp | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 1a32bdb..160dba7 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -1259,7 +1259,7 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U .arg(guidToQString(fileHeader->Name)) .hexarg2(fileHeader->Type, 2) .hexarg2(fileHeader->Attributes, 2) - .hexarg(header.size() + body.size()).arg(header.size() + body.size()) + .hexarg(header.size() + body.size() + tail.size()).arg(header.size() + body.size() + tail.size()) .hexarg(header.size()).arg(header.size()) .hexarg(body.size()).arg(body.size()) .hexarg2(fileHeader->State, 2); @@ -2137,12 +2137,22 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte return ERR_INVALID_FILE; QByteArray newHeader = header; + QByteArray newBody = body; EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*)newHeader.data(); + // Check if the file has a tail + UINT8 tailSize = fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT ? sizeof(UINT16) : 0; + if (tailSize) { + // Remove the tail, it will then be added back for revision 1 volumes + newBody = newBody.left(newBody.size() - tailSize); + // Remove the attribute for rev2+ volumes + if (revision != 1) { + fileHeader->Attributes &= ~(FFS_ATTRIB_TAIL_PRESENT); + } + } // Correct file size - UINT8 tailSize = fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT ? sizeof(UINT16) : 0; - uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + body.size() + tailSize, fileHeader->Size); + uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + newBody.size() + tailSize, fileHeader->Size); // Recalculate header checksum fileHeader->IntegrityCheck.Checksum.Header = 0; @@ -2151,17 +2161,17 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte // Recalculate data checksum, if needed if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) - fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((const UINT8*)body.constData(), body.size()); + fileHeader->IntegrityCheck.Checksum.File = calculateChecksum8((const UINT8*)newBody.constData(), newBody.size()); else if (revision == 1) fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; else fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2; - // Append body - created.append(body); + // Append new body + created.append(newBody); // Append tail, if needed - if (tailSize) { + if (revision ==1 && tailSize) { UINT8 ht = ~fileHeader->IntegrityCheck.Checksum.Header; UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File; created.append(ht).append(ft); diff --git a/uefitool.cpp b/uefitool.cpp index 3b63ae2..c300a89 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.21.1")) +version(tr("0.21.2")) { clipboard = QApplication::clipboard(); From 1ab52fde3599c717964f99a7401d957501d05106 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 4 Oct 2015 21:58:44 +0200 Subject: [PATCH 18/64] UT 0.21.3 / UP 0.3.7 - solved a bug with Gigabyte-specific descriptor settings (BIOS region has size of the whole image), thanks to lordkag for #37 --- UEFIPatch/uefipatch_main.cpp | 2 +- ffsengine.cpp | 24 ++++++++++++++++++++++-- uefitool.cpp | 2 +- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index f1642d0..57f7e25 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.6 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.7 - 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; diff --git a/ffsengine.cpp b/ffsengine.cpp index 160dba7..a71ec4f 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -303,10 +303,18 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in return ERR_INVALID_FLASH_DESCRIPTOR; } biosBegin = meEnd; + // biosEnd will point to the end of the image file + // it may be wrong, but it's pretty hard to detect a padding after BIOS region + // with malformed descriptor + } + // Normal descriptor map + else { + // Calculate biosEnd + biosEnd += biosBegin; } bios = intelImage.mid(biosBegin, biosEnd); - biosEnd += biosBegin; + } else { msg(tr("parseIntelImage: descriptor parsing failed, BIOS region not found in descriptor")); @@ -2843,15 +2851,27 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec QByteArray gbe; UINT32 gbeBegin = calculateRegionOffset(regionSection->GbeBase); UINT32 gbeEnd = gbeBegin + calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit); + QByteArray me; UINT32 meBegin = calculateRegionOffset(regionSection->MeBase); UINT32 meEnd = meBegin + calculateRegionSize(regionSection->MeBase, regionSection->MeLimit); + QByteArray bios; UINT32 biosBegin = calculateRegionOffset(regionSection->BiosBase); - UINT32 biosEnd = biosBegin + calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); + UINT32 biosEnd = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); + // Gigabyte descriptor map + if (biosEnd - biosBegin == model->header(index).size() + model->body(index).size()) { + biosBegin = meEnd; + biosEnd = model->header(index).size() + model->body(index).size(); + } + // Normal descriptor map + else + biosEnd += biosBegin; + QByteArray pdr; UINT32 pdrBegin = calculateRegionOffset(regionSection->PdrBase); UINT32 pdrEnd = pdrBegin + calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit); + QByteArray ec; UINT32 ecBegin = 0; UINT32 ecEnd = 0; diff --git a/uefitool.cpp b/uefitool.cpp index c300a89..99e5cbf 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.21.2")) +version(tr("0.21.3")) { clipboard = QApplication::clipboard(); From 9d0bcd0bed421e312582932772eb70a9c45a8b42 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 4 Oct 2015 22:05:38 +0200 Subject: [PATCH 19/64] Fix a compiler warning --- ffsengine.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index a71ec4f..8a312c8 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -314,7 +314,6 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in } bios = intelImage.mid(biosBegin, biosEnd); - } else { msg(tr("parseIntelImage: descriptor parsing failed, BIOS region not found in descriptor")); @@ -2860,7 +2859,7 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec UINT32 biosBegin = calculateRegionOffset(regionSection->BiosBase); UINT32 biosEnd = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); // Gigabyte descriptor map - if (biosEnd - biosBegin == model->header(index).size() + model->body(index).size()) { + if (biosEnd - biosBegin == (UINT32)(model->header(index).size() + model->body(index).size())) { biosBegin = meEnd; biosEnd = model->header(index).size() + model->body(index).size(); } From 7ebbc58b9bcfef399284b6f3293590025a77946e Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Sun, 4 Oct 2015 22:28:44 +0200 Subject: [PATCH 20/64] UT 0.21.4 / UP 0.3.8 - fixed a bug introduced in 0.21.3 commit --- UEFIPatch/uefipatch_main.cpp | 2 +- ffsengine.cpp | 4 ++-- uefitool.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 57f7e25..419fd97 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.7 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.8 - 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; diff --git a/ffsengine.cpp b/ffsengine.cpp index 8a312c8..aa85da2 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -303,17 +303,17 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in return ERR_INVALID_FLASH_DESCRIPTOR; } biosBegin = meEnd; + bios = intelImage.mid(biosBegin, biosEnd); // biosEnd will point to the end of the image file // it may be wrong, but it's pretty hard to detect a padding after BIOS region // with malformed descriptor } // Normal descriptor map else { + bios = intelImage.mid(biosBegin, biosEnd); // Calculate biosEnd biosEnd += biosBegin; } - - bios = intelImage.mid(biosBegin, biosEnd); } else { msg(tr("parseIntelImage: descriptor parsing failed, BIOS region not found in descriptor")); diff --git a/uefitool.cpp b/uefitool.cpp index 99e5cbf..f9d36f8 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.21.3")) +version(tr("0.21.4")) { clipboard = QApplication::clipboard(); From 19cc0312445145bbde46333bfab593e45d770da2 Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Thu, 12 Nov 2015 09:37:38 +0100 Subject: [PATCH 21/64] UT 0.21.5 /UP 0.3.9 untested - fixed various crashes reported in #39 - changes aren't tested yet, please don't use until #39 is fixed --- basetypes.h | 1 + descriptor.h | 6 +- ffs.h | 2 +- ffsengine.cpp | 197 ++++++++++++++++++++++++++++++++++++++++++++------ uefitool.cpp | 2 +- 5 files changed, 181 insertions(+), 27 deletions(-) diff --git a/basetypes.h b/basetypes.h index e8589ad..3c07309 100644 --- a/basetypes.h +++ b/basetypes.h @@ -86,6 +86,7 @@ typedef unsigned int UINTN; #define ERR_NOTHING_TO_PATCH 41 #define ERR_DEPEX_PARSE_FAILED 42 #define ERR_TRUNCATED_IMAGE 43 +#define ERR_BAD_RELOCATION_ENTRY 44 #define ERR_NOT_IMPLEMENTED 0xFF // UDK porting definitions diff --git a/descriptor.h b/descriptor.h index 0de5476..5bdefd5 100644 --- a/descriptor.h +++ b/descriptor.h @@ -21,7 +21,7 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // Flash descriptor header typedef struct _FLASH_DESCRIPTOR_HEADER { - UINT8 FfVector[16]; // Must be 16 0xFFs + UINT8 FfVector[16]; // Must be 16 0xFFs UINT32 Signature; // 0x0FF0A55A } FLASH_DESCRIPTOR_HEADER; @@ -53,6 +53,8 @@ typedef struct _FLASH_DESCRIPTOR_MAP { UINT32: 16; } FLASH_DESCRIPTOR_MAP; +#define FLASH_DESCRIPTOR_MAX_BASE 0xE0 + // Component section // Flash parameters DWORD structure typedef struct _FLASH_PARAMETERS { @@ -114,7 +116,7 @@ typedef struct _FLASH_DESCRIPTOR_COMPONENT_SECTION_V2 { // If limit is zero - region is not present typedef struct _FLASH_DESCRIPTOR_REGION_SECTION { UINT16 DescriptorBase; // Descriptor - UINT16 DescriptorLimit; // + UINT16 DescriptorLimit; // UINT16 BiosBase; // BIOS UINT16 BiosLimit; // UINT16 MeBase; // ME diff --git a/ffs.h b/ffs.h index 0adc031..946a141 100644 --- a/ffs.h +++ b/ffs.h @@ -109,7 +109,7 @@ typedef struct _EFI_FIRMWARE_VOLUME_HEADER { UINT16 ExtHeaderOffset; //Reserved in Revision 1 UINT8 Reserved; UINT8 Revision; - //EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1]; + //EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[2]; } EFI_FIRMWARE_VOLUME_HEADER; // Standard file system GUIDs diff --git a/ffsengine.cpp b/ffsengine.cpp index aa85da2..7909f10 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -76,6 +76,7 @@ QString errorMessage(UINT8 errorCode) case ERR_NOTHING_TO_PATCH: return QObject::tr("Nothing to patch"); case ERR_DEPEX_PARSE_FAILED: return QObject::tr("Dependency expression parsing failed"); case ERR_TRUNCATED_IMAGE: return QObject::tr("Image is truncated"); + case ERR_BAD_RELOCATION_ENTRY: return QObject::tr("Bad image relocation entry"); default: return QObject::tr("Unknown error %1").arg(errorCode); } } @@ -257,13 +258,31 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in // Check for buffer size to be greater or equal to descriptor region size if (intelImage.size() < FLASH_DESCRIPTOR_SIZE) { - msg(tr("parseIntelImage: input file is smaller then minimum descriptor size of %1h (%2) bytes").hexarg(FLASH_DESCRIPTOR_SIZE).arg(FLASH_DESCRIPTOR_SIZE)); + msg(tr("parseIntelImage: input file is smaller than minimum descriptor size of 1000h (4096) bytes")); return ERR_INVALID_FLASH_DESCRIPTOR; } // Parse descriptor map const FLASH_DESCRIPTOR_MAP* descriptorMap = (const FLASH_DESCRIPTOR_MAP*)(descriptor + sizeof(FLASH_DESCRIPTOR_HEADER)); const FLASH_DESCRIPTOR_UPPER_MAP* upperMap = (const FLASH_DESCRIPTOR_UPPER_MAP*)(descriptor + FLASH_DESCRIPTOR_UPPER_MAP_BASE); + + // Check sanity of base values + if (descriptorMap->MasterBase > FLASH_DESCRIPTOR_MAX_BASE + || descriptorMap->MasterBase == descriptorMap->RegionBase + || descriptorMap->MasterBase == descriptorMap->ComponentBase) { + msg(tr("parseIntelImage: invalid descriptor master base %1h").hexarg2(descriptorMap->MasterBase, 2)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + if (descriptorMap->RegionBase > FLASH_DESCRIPTOR_MAX_BASE + || descriptorMap->RegionBase == descriptorMap->ComponentBase) { + msg(tr("parseIntelImage: invalid descriptor region base %1h").hexarg2(descriptorMap->RegionBase, 2)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + if (descriptorMap->ComponentBase > FLASH_DESCRIPTOR_MAX_BASE) { + msg(tr("parseIntelImage: invalid descriptor component base %1h").hexarg2(descriptorMap->ComponentBase, 2)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8(descriptor, descriptorMap->RegionBase); const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8(descriptor, descriptorMap->ComponentBase); @@ -807,19 +826,21 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent) // Get volume size result = getVolumeSize(bios, volumeOffset, volumeSize, bmVolumeSize); - if (result) + if (result) { + msg(tr("parseBios: getVolumeSize failed with error \"%1\"").arg(errorMessage(result)), parent); return result; + } - // Check reported size - if (volumeSize != bmVolumeSize) - msgSizeMismach = true; - - //Check that volume is fully present in input - if (volumeOffset + volumeSize > (UINT32)bios.size()) { + // Check that volume is fully present in input + if (volumeSize > (UINT32)bios.size() || volumeOffset + volumeSize > (UINT32)bios.size()) { msg(tr("parseBios: one of volumes inside overlaps the end of data"), parent); return ERR_INVALID_VOLUME; } + // Check reported size against a size calculated using block map + if (volumeSize != bmVolumeSize) + msgSizeMismach = true; + // Check volume revision and alignment const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(bios.constData() + volumeOffset); UINT32 alignment; @@ -898,6 +919,10 @@ UINT8 FfsEngine::findNextVolume(const QByteArray & bios, UINT32 volumeOffset, UI UINT8 FfsEngine::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize) { + // 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)) + return ERR_INVALID_VOLUME; + // Populate volume header const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(bios.constData() + volumeOffset); @@ -918,14 +943,37 @@ UINT8 FfsEngine::getVolumeSize(const QByteArray & bios, UINT32 volumeOffset, UIN volumeSize = volumeHeader->FvLength; bmVolumeSize = calcVolumeSize; + + if (volumeSize == 0) + return ERR_INVALID_VOLUME; + return ERR_SUCCESS; } UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent, const UINT8 mode) { + // Check that there is space for the volume header + if ((UINT32)volume.size() < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) { + msg(tr("parseVolume: input volume size %1h (%2) is smaller than volume header size 40h (64)").hexarg(volume.size()).arg(volume.size())); + return ERR_INVALID_VOLUME; + } + // Populate volume header const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)(volume.constData()); + // Check sanity of HeaderLength value + if (ALIGN8(volumeHeader->HeaderLength) > volume.size()) { + msg(tr("parseVolume: volume header overlaps the end of data")); + return ERR_INVALID_VOLUME; + } + + // Check sanity of ExtHeaderOffset value + if (volumeHeader->ExtHeaderOffset > 0 + && (UINT32)volume.size() < ALIGN8(volumeHeader->ExtHeaderOffset + sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER))) { + msg(tr("parseVolume: extended volume header overlaps the end of data")); + return ERR_INVALID_VOLUME; + } + // Calculate volume header size UINT32 headerSize; if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset) { @@ -940,12 +988,10 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Check for volume structure to be known bool volumeIsUnknown = true; - /*UINT8 volumeFfsVersion = 0;*/ // Check for FFS v2 volume if (FFSv2Volumes.contains(QByteArray::fromRawData((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)))) { volumeIsUnknown = false; - /*volumeFfsVersion = 2;*/ } // Check attributes @@ -1139,6 +1185,8 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co UINT8 FfsEngine::getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize) { + if ((UINT32)volume.size() < fileOffset + sizeof(EFI_FFS_FILE_HEADER)) + return ERR_INVALID_VOLUME; const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)(volume.constData() + fileOffset); fileSize = uint24ToUint32(fileHeader->Size); return ERR_SUCCESS; @@ -1332,6 +1380,8 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U UINT8 FfsEngine::getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize) { + if ((UINT32)file.size() < sectionOffset + sizeof(EFI_COMMON_SECTION_HEADER)) + return ERR_INVALID_FILE; const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(file.constData() + sectionOffset); sectionSize = uint24ToUint32(sectionHeader->Size); return ERR_SUCCESS; @@ -1350,6 +1400,9 @@ UINT8 FfsEngine::parseSections(const QByteArray & body, const QModelIndex & pare result = getSectionSize(body, sectionOffset, sectionSize); if (result) return result; + // Exit from loop if no sections left + if (sectionSize == 0) + break; // Parse section QModelIndex sectionIndex; @@ -1531,6 +1584,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c bool msgInvalidCrc = false; bool msgUnknownAuth = false; bool msgSigned = false; + bool msgInvalidSignatureLength = false; bool msgUnknownSignature = false; bool msgUnknownUefiGuidSignature = false; @@ -1594,7 +1648,12 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c else if (QByteArray((const char*)&guidDefinedSectionHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_FIRMWARE_CONTENTS_SIGNED_GUID) { msgSigned = true; const WIN_CERTIFICATE* certificateHeader = (const WIN_CERTIFICATE*)body.constData(); - if (certificateHeader->CertificateType == WIN_CERT_TYPE_EFI_GUID) { + if ((UINT32)body.size() < sizeof(WIN_CERTIFICATE)) { + info += tr("\nSignature type: invalid, wrong length"); + msgInvalidSignatureLength = true; + parseCurrentSection = false; + } + else if (certificateHeader->CertificateType == WIN_CERT_TYPE_EFI_GUID) { info += tr("\nSignature type: UEFI"); const WIN_CERTIFICATE_UEFI_GUID* guidCertificateHeader = (const WIN_CERTIFICATE_UEFI_GUID*)certificateHeader; if (QByteArray((const char*)&guidCertificateHeader->CertType, sizeof(EFI_GUID)) == EFI_CERT_TYPE_RSA2048_SHA256_GUID) { @@ -1619,10 +1678,17 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c msgUnknownSignature = true; } - // Add additional to the header - header.append(body.left(certificateHeader->Length)); - // Get new body - processed = body = body.mid(certificateHeader->Length); + if ((UINT32)body.size() < certificateHeader->Length) { + info += tr("\nSignature type: invalid, wrong length"); + msgInvalidSignatureLength = true; + parseCurrentSection = false; + } + else { + // Add additional data to the header + header.append(body.left(certificateHeader->Length)); + // Get new body + processed = body = body.mid(certificateHeader->Length); + } } // Unknown GUIDed section else { @@ -1665,6 +1731,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c msg(tr("parseSection: signature may become invalid after any modification"), index); if (msgUnknownUefiGuidSignature) msg(tr("parseSection: GUID defined section with unknown signature subtype"), index); + if (msgInvalidSignatureLength) + msg(tr("parseSection: GUID defined section with invalid signature length"), index); if (msgUnknownSignature) msg(tr("parseSection: GUID defined section with unknown signature type"), index); @@ -1796,6 +1864,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c // Get PE info bool msgInvalidDosSignature = false; + bool msgInvalidDosHeader = false; bool msgInvalidPeSignature = false; bool msgUnknownOptionalHeaderSignature = false; @@ -1806,7 +1875,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } else { const EFI_IMAGE_PE_HEADER* peHeader = (EFI_IMAGE_PE_HEADER*)(body.constData() + dosHeader->e_lfanew); - if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) { + if ((UINT32)body.size() < dosHeader->e_lfanew + sizeof(EFI_IMAGE_PE_HEADER)) { + info += tr("\nDOS lfanew: %1h, invalid").hexarg2(dosHeader->e_lfanew, 8); + msgInvalidDosHeader = true; + } + else if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) { info += tr("\nPE signature: %1h, invalid").hexarg2(peHeader->Signature, 8); msgInvalidPeSignature = true; } @@ -1853,6 +1926,9 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c if (msgInvalidDosSignature) { msg("parseSection: PE32 image with invalid DOS signature", index); } + if (msgInvalidDosHeader) { + msg("parseSection: PE32 image with invalid DOS header", index); + } if (msgInvalidPeSignature) { msg("parseSection: PE32 image with invalid PE signature", index); } @@ -2845,16 +2921,40 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec return result; reconstructed.append(descriptor); + // Check descriptor size + if ((UINT32)descriptor.size() < FLASH_DESCRIPTOR_SIZE) { + msg(tr("reconstructIntelImage: descriptor is smaller than minimum size of 1000h (4096) bytes")); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + const FLASH_DESCRIPTOR_MAP* descriptorMap = (const FLASH_DESCRIPTOR_MAP*)(descriptor.constData() + sizeof(FLASH_DESCRIPTOR_HEADER)); + // Check sanity of base values + if (descriptorMap->MasterBase > FLASH_DESCRIPTOR_MAX_BASE + || descriptorMap->MasterBase == descriptorMap->RegionBase + || descriptorMap->MasterBase == descriptorMap->ComponentBase) { + msg(tr("reconstructIntelImage: invalid descriptor master base %1h").hexarg2(descriptorMap->MasterBase, 2)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + if (descriptorMap->RegionBase > FLASH_DESCRIPTOR_MAX_BASE + || descriptorMap->RegionBase == descriptorMap->ComponentBase) { + msg(tr("reconstructIntelImage: invalid descriptor region base %1h").hexarg2(descriptorMap->RegionBase, 2)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + if (descriptorMap->ComponentBase > FLASH_DESCRIPTOR_MAX_BASE) { + msg(tr("reconstructIntelImage: invalid descriptor component base %1h").hexarg2(descriptorMap->ComponentBase, 2)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + + const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->RegionBase); QByteArray gbe; UINT32 gbeBegin = calculateRegionOffset(regionSection->GbeBase); UINT32 gbeEnd = gbeBegin + calculateRegionSize(regionSection->GbeBase, regionSection->GbeLimit); - + QByteArray me; UINT32 meBegin = calculateRegionOffset(regionSection->MeBase); UINT32 meEnd = meBegin + calculateRegionSize(regionSection->MeBase, regionSection->MeLimit); - + QByteArray bios; UINT32 biosBegin = calculateRegionOffset(regionSection->BiosBase); UINT32 biosEnd = calculateRegionSize(regionSection->BiosBase, regionSection->BiosLimit); @@ -2870,7 +2970,7 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec QByteArray pdr; UINT32 pdrBegin = calculateRegionOffset(regionSection->PdrBase); UINT32 pdrEnd = pdrBegin + calculateRegionSize(regionSection->PdrBase, regionSection->PdrLimit); - + QByteArray ec; UINT32 ecBegin = 0; UINT32 ecEnd = 0; @@ -2890,7 +2990,7 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); return ERR_INVALID_FLASH_DESCRIPTOR; } - + UINT32 offset = descriptor.size(); // Reconstruct other regions @@ -3107,6 +3207,12 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon QByteArray body = model->body(index); EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)header.data(); + // Check sanity of HeaderLength + if (volumeHeader->HeaderLength > header.size()) { + msg(tr("reconstructVolume: invalid volume header length, reconstruction is not possible"), index); + return ERR_INVALID_VOLUME; + } + // Recalculate volume header checksum volumeHeader->Checksum = 0; volumeHeader->Checksum = calculateChecksum16((const UINT16*)volumeHeader, volumeHeader->HeaderLength); @@ -3170,8 +3276,8 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon // Calculate relative base address UINT32 relbase = fileOffset + sectionOffset + model->header(image).size(); // Calculate offset of image relative to file base - UINT32 imagebase; - result = getBase(model->body(image), imagebase); + UINT32 imagebase = 0; + result = getBase(model->body(image), imagebase); // imagebase passed by reference if (!result) { // Calculate volume base volumeBase = imagebase - relbase; @@ -3694,6 +3800,12 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base, if (guidDefinedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { // CRC32 section if (QByteArray((const char*)&guidDefinedHeader->SectionDefinitionGuid, sizeof(EFI_GUID)) == EFI_GUIDED_SECTION_CRC32) { + // Check header size + if ((UINT32)header.size() != sizeof(EFI_GUID_DEFINED_SECTION) + sizeof(UINT32)) { + msg(tr("reconstructSection: invalid CRC32 section size %1h (%2)") + .hexarg(header.size()).arg(header.size()), index); + return ERR_INVALID_SECTION; + } // Calculate CRC32 of section data UINT32 crc = crc32(0, (const UINT8*)compressed.constData(), compressed.size()); // Store new CRC32 @@ -3831,6 +3943,10 @@ UINT8 FfsEngine::reconstruct(const QModelIndex &index, QByteArray& reconstructed UINT8 FfsEngine::growVolume(QByteArray & header, const UINT32 size, UINT32 & newSize) { + // Check sanity + if ((UINT32)header.size() < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) + return ERR_INVALID_VOLUME; + // Adjust new size to be representable by current FvBlockMap EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)header.data(); EFI_FV_BLOCK_MAP_ENTRY* blockMap = (EFI_FV_BLOCK_MAP_ENTRY*)(header.data() + sizeof(EFI_FIRMWARE_VOLUME_HEADER)); @@ -4042,11 +4158,15 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base) QByteArray file = executable; // Populate DOS header + if ((UINT32)file.size() < sizeof(EFI_IMAGE_DOS_HEADER)) + return ERR_INVALID_FILE; EFI_IMAGE_DOS_HEADER* dosHeader = (EFI_IMAGE_DOS_HEADER*)file.data(); // Check signature if (dosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE){ UINT32 offset = dosHeader->e_lfanew; + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_PE_HEADER)) + return ERR_UNKNOWN_IMAGE_TYPE; EFI_IMAGE_PE_HEADER* peHeader = (EFI_IMAGE_PE_HEADER*)(file.data() + offset); if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) return ERR_UNKNOWN_IMAGE_TYPE; @@ -4054,8 +4174,12 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base) // Skip file header offset += sizeof(EFI_IMAGE_FILE_HEADER); // Check optional header magic + if ((UINT32)file.size() < offset + sizeof(UINT16)) + return ERR_UNKNOWN_IMAGE_TYPE; UINT16 magic = *(UINT16*)(file.data() + offset); if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) { + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER32)) + return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (EFI_IMAGE_OPTIONAL_HEADER32*)(file.data() + offset); delta = base - optHeader->ImageBase; if (!delta) @@ -4067,6 +4191,8 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base) optHeader->ImageBase = base; } else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER64)) + return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (EFI_IMAGE_OPTIONAL_HEADER64*)(file.data() + offset); delta = base - optHeader->ImageBase; if (!delta) @@ -4082,6 +4208,8 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base) } else if (dosHeader->e_magic == EFI_IMAGE_TE_SIGNATURE){ // Populate TE header + if ((UINT32)file.size() < sizeof(EFI_IMAGE_TE_HEADER)) + return ERR_INVALID_FILE; EFI_IMAGE_TE_HEADER* teHeader = (EFI_IMAGE_TE_HEADER*)file.data(); delta = base - teHeader->ImageBase; if (!delta) @@ -4121,7 +4249,10 @@ UINT8 FfsEngine::rebase(QByteArray &executable, const UINT32 base) // Run this relocation record while (Reloc < RelocEnd) { - UINT8* data = (UINT8*)(file.data() + RelocBase->VirtualAddress - teFixup + (*Reloc & 0x0FFF)); + UINT32 RelocLocation = RelocBase->VirtualAddress - teFixup + (*Reloc & 0x0FFF); + if ((UINT32)file.size() < RelocLocation) + return ERR_BAD_RELOCATION_ENTRY; + UINT8* data = (UINT8*)(file.data() + RelocLocation); switch ((*Reloc) >> 12) { case EFI_IMAGE_REL_BASED_ABSOLUTE: // Do nothing @@ -4197,11 +4328,15 @@ UINT8 FfsEngine::getEntryPoint(const QByteArray &file, UINT32& entryPoint) return ERR_INVALID_FILE; // Populate DOS header + if ((UINT32)file.size() < sizeof(EFI_IMAGE_DOS_HEADER)) + return ERR_INVALID_FILE; const EFI_IMAGE_DOS_HEADER* dosHeader = (const EFI_IMAGE_DOS_HEADER*)file.constData(); // Check signature if (dosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE){ UINT32 offset = dosHeader->e_lfanew; + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_PE_HEADER)) + return ERR_UNKNOWN_IMAGE_TYPE; const EFI_IMAGE_PE_HEADER* peHeader = (const EFI_IMAGE_PE_HEADER*)(file.constData() + offset); if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) return ERR_UNKNOWN_IMAGE_TYPE; @@ -4213,10 +4348,14 @@ UINT8 FfsEngine::getEntryPoint(const QByteArray &file, UINT32& entryPoint) // Check optional header magic const UINT16 magic = *(const UINT16*)(file.constData() + offset); if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) { + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER32)) + return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; const EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER32*)(file.constData() + offset); entryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint; } else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER64)) + return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; const EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER64*)(file.constData() + offset); entryPoint = optHeader->ImageBase + optHeader->AddressOfEntryPoint; } @@ -4225,6 +4364,8 @@ UINT8 FfsEngine::getEntryPoint(const QByteArray &file, UINT32& entryPoint) } else if (dosHeader->e_magic == EFI_IMAGE_TE_SIGNATURE){ // Populate TE header + if ((UINT32)file.size() < sizeof(EFI_IMAGE_TE_HEADER)) + return ERR_INVALID_FILE; const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)file.constData(); UINT32 teFixup = teHeader->StrippedSize - sizeof(EFI_IMAGE_TE_HEADER); entryPoint = teHeader->ImageBase + teHeader->AddressOfEntryPoint - teFixup; @@ -4238,11 +4379,15 @@ UINT8 FfsEngine::getBase(const QByteArray& file, UINT32& base) return ERR_INVALID_FILE; // Populate DOS header + if ((UINT32)file.size() < sizeof(EFI_IMAGE_DOS_HEADER)) + return ERR_INVALID_FILE; const EFI_IMAGE_DOS_HEADER* dosHeader = (const EFI_IMAGE_DOS_HEADER*)file.constData(); // Check signature if (dosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE){ UINT32 offset = dosHeader->e_lfanew; + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_PE_HEADER)) + return ERR_UNKNOWN_IMAGE_TYPE; const EFI_IMAGE_PE_HEADER* peHeader = (const EFI_IMAGE_PE_HEADER*)(file.constData() + offset); if (peHeader->Signature != EFI_IMAGE_PE_SIGNATURE) return ERR_UNKNOWN_IMAGE_TYPE; @@ -4254,10 +4399,14 @@ UINT8 FfsEngine::getBase(const QByteArray& file, UINT32& base) // Check optional header magic const UINT16 magic = *(const UINT16*)(file.constData() + offset); if (magic == EFI_IMAGE_PE_OPTIONAL_HDR32_MAGIC) { + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER32)) + return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; const EFI_IMAGE_OPTIONAL_HEADER32* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER32*)(file.constData() + offset); base = optHeader->ImageBase; } else if (magic == EFI_IMAGE_PE_OPTIONAL_HDR64_MAGIC) { + if ((UINT32)file.size() < offset + sizeof(EFI_IMAGE_OPTIONAL_HEADER64)) + return ERR_UNKNOWN_PE_OPTIONAL_HEADER_TYPE; const EFI_IMAGE_OPTIONAL_HEADER64* optHeader = (const EFI_IMAGE_OPTIONAL_HEADER64*)(file.constData() + offset); base = optHeader->ImageBase; } @@ -4266,6 +4415,8 @@ UINT8 FfsEngine::getBase(const QByteArray& file, UINT32& base) } else if (dosHeader->e_magic == EFI_IMAGE_TE_SIGNATURE){ // Populate TE header + if ((UINT32)file.size() < sizeof(EFI_IMAGE_TE_HEADER)) + return ERR_INVALID_FILE; const EFI_IMAGE_TE_HEADER* teHeader = (const EFI_IMAGE_TE_HEADER*)file.constData(); //!TODO: add handling base = teHeader->ImageBase; diff --git a/uefitool.cpp b/uefitool.cpp index f9d36f8..34ca9e0 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.21.4")) +version(tr("0.21.5")) { clipboard = QApplication::clipboard(); From d54f215e673d1dc338ef3171e82a220376d40c9a Mon Sep 17 00:00:00 2001 From: Nikolaj Schlej Date: Thu, 12 Nov 2015 09:38:14 +0100 Subject: [PATCH 22/64] Forgot to bump UP version --- UEFIPatch/uefipatch_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 419fd97..e14e59f 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.8 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.9 - 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; From 8cfd93c8ebc4258ce785fe563148431beff5ca15 Mon Sep 17 00:00:00 2001 From: Alex Matrosov Date: Sun, 21 Aug 2016 15:48:13 -0700 Subject: [PATCH 23/64] Update patches.txt --- UEFIPatch/patches.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UEFIPatch/patches.txt b/UEFIPatch/patches.txt index 74eac08..f85fbe5 100644 --- a/UEFIPatch/patches.txt +++ b/UEFIPatch/patches.txt @@ -40,3 +40,5 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F # CpuPei | Sandy Bridge with ME 7.xx, old SB-E/IB-E 2BB5AFA9-FF33-417B-8497-CB773C2B93BF 10 P:800018EB050D0080:000018EB050D0000 +# PpmInitialize | Broadwell-E +3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBA6C24400F:0FBA7424400F From b700177e4a8eb9e88efac7c8d04aea037927d8e9 Mon Sep 17 00:00:00 2001 From: Adrian Dumitru Date: Wed, 25 Jan 2017 00:30:53 +0200 Subject: [PATCH 24/64] Add Kaby Lake support. --- UEFIPatch/patches.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/UEFIPatch/patches.txt b/UEFIPatch/patches.txt index f85fbe5..29d156d 100644 --- a/UEFIPatch/patches.txt +++ b/UEFIPatch/patches.txt @@ -42,3 +42,11 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F # PpmInitialize | Broadwell-E 3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBA6C24400F:0FBA7424400F + +# SiInit | Skylake +299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:75080D00800000:EB080D00800000 +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 12 P:81E10080000033C1:9090909090909090 From 5ba63418bde66681ae81b8f1ae890ab65d746752 Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 13 Apr 2017 17:30:44 +0200 Subject: [PATCH 25/64] Add UEFIReplace. --- .gitignore | 3 +- UEFIReplace/uefireplace.cpp | 108 +++++++++++++++++++++++++++++++ UEFIReplace/uefireplace.h | 41 ++++++++++++ UEFIReplace/uefireplace.pro | 42 ++++++++++++ UEFIReplace/uefireplace_main.cpp | 78 ++++++++++++++++++++++ 5 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 UEFIReplace/uefireplace.cpp create mode 100644 UEFIReplace/uefireplace.h create mode 100644 UEFIReplace/uefireplace.pro create mode 100644 UEFIReplace/uefireplace_main.cpp diff --git a/.gitignore b/.gitignore index c7191ed..910d521 100644 --- a/.gitignore +++ b/.gitignore @@ -233,4 +233,5 @@ Makefile UEFIExtract/UEFIExtract UEFIFind/UEFIFind UEFIPatch/UEFIPatch -UEFITool \ No newline at end of file +UEFIReplace/UEFIReplace +UEFITool diff --git a/UEFIReplace/uefireplace.cpp b/UEFIReplace/uefireplace.cpp new file mode 100644 index 0000000..f4ff1ea --- /dev/null +++ b/UEFIReplace/uefireplace.cpp @@ -0,0 +1,108 @@ +/* uefireplace.cpp + +Copyright (c) 2017, mxxxc. 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. + +*/ + +#include "uefireplace.h" + +UEFIReplace::UEFIReplace(QObject *parent) : + QObject(parent) +{ + ffsEngine = new FfsEngine(this); + model = ffsEngine->treeModel(); +} + +UEFIReplace::~UEFIReplace() +{ + delete ffsEngine; +} + +UINT8 UEFIReplace::replace(QString inPath, const QByteArray & guid, const UINT8 sectionType, const QString contentPath) +{ + QFileInfo fileInfo = QFileInfo(inPath); + if (!fileInfo.exists()) + return ERR_FILE_OPEN; + + fileInfo = QFileInfo(contentPath); + if (!fileInfo.exists()) + return ERR_FILE_OPEN; + + QFile inputFile; + inputFile.setFileName(inPath); + + if (!inputFile.open(QFile::ReadOnly)) + return ERR_FILE_READ; + + QByteArray buffer = inputFile.readAll(); + inputFile.close(); + + UINT8 result = ffsEngine->parseImageFile(buffer); + if (result) + return result; + + QFile contentFile; + contentFile.setFileName(contentPath); + + if (!contentFile.open(QFile::ReadOnly)) + return ERR_FILE_READ; + + QByteArray contents = contentFile.readAll(); + contentFile.close(); + + result = replaceInFile(model->index(0, 0), guid, sectionType, contents); + if (result) + return result; + + QByteArray reconstructed; + result = ffsEngine->reconstructImageFile(reconstructed); + if (result) + return result; + if (reconstructed == buffer) + return ERR_NOTHING_TO_PATCH; + + QFile outputFile; + outputFile.setFileName(inPath.append(".patched")); + if (!outputFile.open(QFile::WriteOnly)) + return ERR_FILE_WRITE; + + outputFile.resize(0); + outputFile.write(reconstructed); + outputFile.close(); + + return ERR_SUCCESS; +} + +UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & newData) +{ + if (!model || !index.isValid()) + return ERR_INVALID_PARAMETER; + if (model->subtype(index) == sectionType) { + QModelIndex fileIndex = model->findParentOfType(index, Types::File); + QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID)); + if (fileGuid == guid) { + return ffsEngine->replace(index, newData, REPLACE_MODE_BODY); + } + } + + bool patched = false; + if (model->rowCount(index) > 0) { + for (int i = 0; i < model->rowCount(index); i++) { + UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData); + if (!result) { + patched = true; + break; + } else if (result != ERR_NOTHING_TO_PATCH) + return result; + } + } + + return patched ? ERR_SUCCESS : ERR_NOTHING_TO_PATCH; +} diff --git a/UEFIReplace/uefireplace.h b/UEFIReplace/uefireplace.h new file mode 100644 index 0000000..682a1f6 --- /dev/null +++ b/UEFIReplace/uefireplace.h @@ -0,0 +1,41 @@ +/* uefireplace.h +Copyright (c) 2017, mxxxc. 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. +*/ + +#ifndef __UEFIREPLACE_H__ +#define __UEFIREPLACE_H__ + +#include +#include +#include +#include +#include +#include + +#include "../basetypes.h" +#include "../ffs.h" +#include "../ffsengine.h" + +class UEFIReplace : public QObject +{ + Q_OBJECT + +public: + explicit UEFIReplace(QObject *parent = 0); + ~UEFIReplace(); + + UINT8 replace(const QString inPath, const QByteArray & guid, const UINT8 sectionType, const QString contentPath); + +private: + UINT8 replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & contents); + FfsEngine* ffsEngine; + TreeModel* model; +}; + +#endif diff --git a/UEFIReplace/uefireplace.pro b/UEFIReplace/uefireplace.pro new file mode 100644 index 0000000..e3d853d --- /dev/null +++ b/UEFIReplace/uefireplace.pro @@ -0,0 +1,42 @@ +QT += core +QT -= gui + +TARGET = UEFIReplace +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +DEFINES += _CONSOLE + +SOURCES += uefireplace_main.cpp \ + uefireplace.cpp \ + ../types.cpp \ + ../descriptor.cpp \ + ../ffs.cpp \ + ../ffsengine.cpp \ + ../peimage.cpp \ + ../treeitem.cpp \ + ../treemodel.cpp \ + ../LZMA/LzmaCompress.c \ + ../LZMA/LzmaDecompress.c \ + ../LZMA/SDK/C/LzFind.c \ + ../LZMA/SDK/C/LzmaDec.c \ + ../LZMA/SDK/C/LzmaEnc.c \ + ../Tiano/EfiTianoDecompress.c \ + ../Tiano/EfiTianoCompress.c \ + ../Tiano/EfiTianoCompressLegacy.c + +HEADERS += uefireplace.h \ + ../basetypes.h \ + ../descriptor.h \ + ../gbe.h \ + ../me.h \ + ../ffs.h \ + ../peimage.h \ + ../types.h \ + ../ffsengine.h \ + ../treeitem.h \ + ../treemodel.h \ + ../LZMA/LzmaCompress.h \ + ../LZMA/LzmaDecompress.h \ + ../Tiano/EfiTianoDecompress.h \ + ../Tiano/EfiTianoCompress.h diff --git a/UEFIReplace/uefireplace_main.cpp b/UEFIReplace/uefireplace_main.cpp new file mode 100644 index 0000000..562db22 --- /dev/null +++ b/UEFIReplace/uefireplace_main.cpp @@ -0,0 +1,78 @@ +/* uefireplace_main.cpp + +Copyright (c) 2017, mxxxc. 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. + +*/ +#include +#include +#include +#include +#include "uefireplace.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + a.setOrganizationName("CodeRush"); + a.setOrganizationDomain("coderush.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 << + "Usage: UEFIReplace image_file guid section_type contents_file" << std::endl; + return ERR_SUCCESS; + } + + QUuid uuid = QUuid(args.at(2)); + QByteArray guid = QByteArray::fromRawData((const char*)&uuid.data1, sizeof(EFI_GUID)); + bool converted; + UINT8 sectionType = (UINT8)args.at(3).toUShort(&converted, 16); + if (!converted) + result = ERR_INVALID_PARAMETER; + else + result = r.replace(args.at(1), guid, sectionType, args.at(4)); + + switch (result) { + case ERR_SUCCESS: + std::cout << "File replaced" << std::endl; + break; + case ERR_INVALID_PARAMETER: + std::cout << "Function called with invalid parameter" << std::endl; + break; + case ERR_INVALID_FILE: + std::cout << "Invalid/corrupted file specified" << std::endl; + break; + case ERR_INVALID_SECTION: + std::cout << "Invalid/corrupted section specified" << std::endl; + break; + case ERR_NOTHING_TO_PATCH: + std::cout << "No replacements can be applied to input file" << std::endl; + break; + case ERR_NOT_IMPLEMENTED: + std::cout << "Can't replace body of this section type" << std::endl; + break; + case ERR_FILE_OPEN: + std::cout << "Input file not found" << std::endl; + break; + case ERR_FILE_READ: + std::cout << "Input file can't be read" << std::endl; + break; + case ERR_FILE_WRITE: + std::cout << "Output file can't be written" << std::endl; + break; + default: + std::cout << "Error " << result << std::endl; + } + + return result; +} From 73019876cf489c1b34639d8f67135c7b8e28ef2f Mon Sep 17 00:00:00 2001 From: Alex Matrosov Date: Sun, 10 Dec 2017 16:54:40 -0800 Subject: [PATCH 26/64] add FFSv3 support with large files and large sections --- UEFIPatch/uefipatch_main.cpp | 8 +- ffs.cpp | 23 ++- ffs.h | 14 +- ffsengine.cpp | 295 +++++++++++++++++++++-------------- ffsengine.h | 3 +- uefitool.cpp | 2 +- 6 files changed, 212 insertions(+), 133 deletions(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index e14e59f..aac0ca7 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -1,6 +1,6 @@ /* uefipatch_main.cpp -Copyright (c) 2015, Nikolaj Schlej. All rights reserved. +Copyright (c) 2017, 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 @@ -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("UEFIPatch"); UEFIPatch w; @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.9 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.10 - 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; diff --git a/ffs.cpp b/ffs.cpp index 33410c3..6c3c773 100644 --- a/ffs.cpp +++ b/ffs.cpp @@ -30,7 +30,10 @@ const QVector FFSv3Volumes = const UINT8 ffsAlignmentTable[] = { 0, 4, 7, 9, 10, 12, 15, 16 }; -UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize) +const UINT8 ffsAlignment2Table[] = +{ 17, 18, 19, 20, 21, 22, 23, 24 }; + +UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize) { if (!buffer) return 0; @@ -40,7 +43,15 @@ UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize) while (bufferSize--) counter += buffer[bufferSize]; - return (UINT8)0x100 - counter; + return counter; +} + +UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize) +{ + if (!buffer) + return 0; + + return (UINT8)0x100 - calculateSum8(buffer, bufferSize); } UINT16 calculateChecksum16(const UINT16* buffer, UINT32 bufferSize) @@ -120,6 +131,8 @@ QString fileTypeToQString(const UINT8 type) 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_SMM_STANDALONE: return QObject::tr("SMM standalone"); + case EFI_FV_FILETYPE_SMM_CORE_STANDALONE: return QObject::tr("SMM core standalone"); case EFI_FV_FILETYPE_PAD: return QObject::tr("Pad"); default: return QObject::tr("Unknown"); }; @@ -155,10 +168,10 @@ UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header) if (!header) return 0; - const bool extended = false; - /*if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) { + bool extended = false; + if (uint24ToUint32(header->Size) == EFI_SECTION2_IS_USED) { extended = true; - }*/ + } switch (header->Type) { diff --git a/ffs.h b/ffs.h index 946a141..c761551 100644 --- a/ffs.h +++ b/ffs.h @@ -292,7 +292,7 @@ UINT8 Type; UINT8 Attributes; UINT8 Size[3]; // Set to 0xFFFFFF UINT8 State; -UINT32 ExtendedSize; +UINT64 ExtendedSize; } EFI_FFS_FILE_HEADER2; // Standard data checksum, used if FFS_ATTRIB_CHECKSUM is clear @@ -314,6 +314,8 @@ UINT32 ExtendedSize; #define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B #define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C #define EFI_FV_FILETYPE_SMM_CORE 0x0D +#define EFI_FV_FILETYPE_SMM_STANDALONE 0x0E +#define EFI_FV_FILETYPE_SMM_CORE_STANDALONE 0x0F #define EFI_FV_FILETYPE_OEM_MIN 0xC0 #define EFI_FV_FILETYPE_OEM_MAX 0xDF #define EFI_FV_FILETYPE_DEBUG_MIN 0xE0 @@ -326,6 +328,7 @@ UINT32 ExtendedSize; #define FFS_ATTRIB_TAIL_PRESENT 0x01 // Valid only for revision 1 volumes #define FFS_ATTRIB_RECOVERY 0x02 // Valid only for revision 1 volumes #define FFS_ATTRIB_LARGE_FILE 0x01 // Valid only for FFSv3 volumes +#define FFS_ATTRIB_DATA_ALIGNMENT2 0x02 // Valid only for revision 2 volumes #define FFS_ATTRIB_FIXED 0x04 #define FFS_ATTRIB_DATA_ALIGNMENT 0x38 #define FFS_ATTRIB_CHECKSUM 0x40 @@ -333,6 +336,9 @@ UINT32 ExtendedSize; // FFS alignment table extern const UINT8 ffsAlignmentTable[]; +// Extended FFS alignment table +extern const UINT8 ffsAlignment2Table[]; + // File states #define EFI_FILE_HEADER_CONSTRUCTION 0x01 #define EFI_FILE_HEADER_VALID 0x02 @@ -360,7 +366,9 @@ const QByteArray EFI_FFS_PAD_FILE_GUID // FFS size conversion routines extern VOID uint32ToUint24(UINT32 size, UINT8* ffsSize); extern UINT32 uint24ToUint32(const UINT8* ffsSize); -// FFS file 8bit checksum calculation routine + +// FFS file 8bit checksum calculation routines +extern UINT8 calculateSum8(const UINT8* buffer, UINT32 bufferSize); extern UINT8 calculateChecksum8(const UINT8* buffer, UINT32 bufferSize); //***************************************************************************** @@ -528,7 +536,7 @@ typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2; typedef EFI_COMMON_SECTION_HEADER EFI_USER_INTERFACE_SECTION; typedef EFI_COMMON_SECTION_HEADER2 EFI_USER_INTERFACE_SECTION2; -//Section routines +// Section routines extern UINT32 sizeOfSectionHeader(const EFI_COMMON_SECTION_HEADER* header); //***************************************************************************** diff --git a/ffsengine.cpp b/ffsengine.cpp index 7909f10..9c66dbf 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -287,15 +287,9 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in 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 + UINT8 descriptorVersion = 2; // Skylake+ by default + if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) // Old descriptor descriptorVersion = 1; - else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ) // Skylake+ descriptor - descriptorVersion = 2; - else { - msg(tr("parseIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); - return ERR_INVALID_FLASH_DESCRIPTOR; - } // ME region QByteArray me; @@ -983,15 +977,16 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co else headerSize = volumeHeader->HeaderLength; - // Sanity check after some new crazy MSI images + // Sanity check after some crazy MSI images headerSize = ALIGN8(headerSize); - // Check for volume structure to be known - bool volumeIsUnknown = true; - - // Check for FFS v2 volume - if (FFSv2Volumes.contains(QByteArray::fromRawData((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)))) { - volumeIsUnknown = false; + // Check for FFS v2/v3 volume + UINT8 subtype = Subtypes::UnknownVolume; + if (FFSv2Volumes.contains(QByteArray::fromRawData((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)))){ + subtype = Subtypes::Ffs2Volume; + } + else if (FFSv3Volumes.contains(QByteArray::fromRawData((const char*)volumeHeader->FileSystemGuid.Data, sizeof(EFI_GUID)))) { + subtype = Subtypes::Ffs3Volume; } // Check attributes @@ -1063,10 +1058,10 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Add tree item QByteArray header = volume.left(headerSize); QByteArray body = volume.mid(headerSize, volumeSize - headerSize); - index = model->addItem(Types::Volume, volumeIsUnknown ? Subtypes::UnknownVolume : Subtypes::Ffs2Volume, COMPRESSION_ALGORITHM_NONE, name, text, info, header, body, parent, mode); + index = model->addItem(Types::Volume, subtype, COMPRESSION_ALGORITHM_NONE, name, text, info, header, body, parent, mode); // Show messages - if (volumeIsUnknown) { + if (subtype == Subtypes::UnknownVolume) { msg(tr("parseVolume: unknown file system %1").arg(guidToQString(volumeHeader->FileSystemGuid)), index); // Do not parse unknown volumes return ERR_SUCCESS; @@ -1100,19 +1095,42 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co break; } - result = getFileSize(volume, fileOffset, fileSize); - if (result) - return result; + QByteArray tempFile = volume.mid(fileOffset, sizeof(EFI_FFS_FILE_HEADER)); + const EFI_FFS_FILE_HEADER* tempFileHeader = (const EFI_FFS_FILE_HEADER*)tempFile.constData(); + UINT32 fileHeaderSize = sizeof(EFI_FFS_FILE_HEADER); + fileSize = uint24ToUint32(tempFileHeader->Size); + if (volumeHeader->Revision > 1 && (tempFileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { + // Check if it's possibly the latest file in the volume + if (volumeSize - fileOffset < sizeof(EFI_FFS_FILE_HEADER2)) { + // No files are possible after this point + // All the rest is either free space or non-UEFI data + QByteArray rest = volume.right(volumeSize - fileOffset); + if (rest.count(empty) == rest.size()) { // It's a free space + model->addItem(Types::FreeSpace, 0, COMPRESSION_ALGORITHM_NONE, tr("Volume free space"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index); + } + else { //It's non-UEFI data + QModelIndex dataIndex = model->addItem(Types::Padding, Subtypes::DataPadding, COMPRESSION_ALGORITHM_NONE, tr("Non-UEFI data"), "", tr("Full size: %1h (%2)").hexarg(rest.size()).arg(rest.size()), QByteArray(), rest, index); + msg(tr("parseVolume: non-UEFI data found in volume's free space"), dataIndex); + } + // Exit from loop + break; + } - // Check file size to be at least size of EFI_FFS_FILE_HEADER - if (fileSize < sizeof(EFI_FFS_FILE_HEADER)) { + fileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2); + tempFile = volume.mid(fileOffset, sizeof(EFI_FFS_FILE_HEADER2)); + const EFI_FFS_FILE_HEADER2* tempFileHeader2 = (const EFI_FFS_FILE_HEADER2*)tempFile.constData(); + fileSize = (UINT32)tempFileHeader2->ExtendedSize; + } + + // Check file size to be at least size of the header + if (fileSize < fileHeaderSize) { msg(tr("parseVolume: volume has FFS file with invalid size"), index); return ERR_INVALID_FILE; } - + QByteArray file = volume.mid(fileOffset, fileSize); - QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER)); - + QByteArray header = file.left(fileHeaderSize); + // If we are at empty space in the end of volume if (header.count(empty) == header.size()) { // Check free space to be actually free @@ -1152,8 +1170,11 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Check file alignment const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)header.constData(); UINT8 alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3]; - UINT32 alignment = (UINT32)pow(2.0, alignmentPower); - if ((fileOffset + sizeof(EFI_FFS_FILE_HEADER)) % alignment) + if (volumeHeader->Revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2)) + alignmentPower = ffsAlignment2Table[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3]; + + UINT32 alignment = (UINT32)(1UL << alignmentPower); + if ((fileOffset + fileHeaderSize) % alignment) msgUnalignedFile = true; // Check file GUID @@ -1165,7 +1186,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co // Parse file QModelIndex fileIndex; - result = parseFile(file, fileIndex, empty == '\xFF' ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index); + result = parseFile(file, fileIndex, volumeHeader->Revision, empty == '\xFF' ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index); if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME) msg(tr("parseVolume: FFS file parsing failed with error \"%1\"").arg(errorMessage(result)), index); @@ -1183,16 +1204,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, QModelIndex & index, co return ERR_SUCCESS; } -UINT8 FfsEngine::getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize) -{ - if ((UINT32)volume.size() < fileOffset + sizeof(EFI_FFS_FILE_HEADER)) - return ERR_INVALID_VOLUME; - const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)(volume.constData() + fileOffset); - fileSize = uint24ToUint32(fileHeader->Size); - return ERR_SUCCESS; -} - -UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const UINT8 erasePolarity, const QModelIndex & parent, const UINT8 mode) +UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const UINT8 revision, const UINT8 erasePolarity, const QModelIndex & parent, const UINT8 mode) { bool msgInvalidHeaderChecksum = false; bool msgInvalidDataChecksum = false; @@ -1200,43 +1212,32 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U bool msgInvalidType = false; // Populate file header + if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER)) + return ERR_INVALID_FILE; const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)file.constData(); - // Check file state // Construct empty byte for this file char empty = erasePolarity ? '\xFF' : '\x00'; - // Check header checksum + // Get file header QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER)); - QByteArray tempHeader = header; - EFI_FFS_FILE_HEADER* tempFileHeader = (EFI_FFS_FILE_HEADER*)(tempHeader.data()); - tempFileHeader->IntegrityCheck.Checksum.Header = 0; - tempFileHeader->IntegrityCheck.Checksum.File = 0; - UINT8 calculated = calculateChecksum8((const UINT8*)tempFileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1); - if (fileHeader->IntegrityCheck.Checksum.Header != calculated) + if (revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { + if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2)) + return ERR_INVALID_FILE; + header = file.left(sizeof(EFI_FFS_FILE_HEADER2)); + } + + // Check header checksum + UINT8 calculatedHeader = 0x100 -(calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->IntegrityCheck.Checksum.Header - fileHeader->IntegrityCheck.Checksum.File - fileHeader->State); + if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader) msgInvalidHeaderChecksum = true; - // Check data checksum - // Data checksum must be calculated - if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { - UINT32 bufferSize = file.size() - sizeof(EFI_FFS_FILE_HEADER); - // Exclude file tail from data checksum calculation - if (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) - bufferSize -= sizeof(UINT16); - calculated = calculateChecksum8((const UINT8*)(file.constData() + sizeof(EFI_FFS_FILE_HEADER)), bufferSize); - if (fileHeader->IntegrityCheck.Checksum.File != calculated) - msgInvalidDataChecksum = true; - } - // Data checksum must be one of predefined values - else if (fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM2) - msgInvalidDataChecksum = true; - // Get file body - QByteArray body = file.right(file.size() - sizeof(EFI_FFS_FILE_HEADER)); + QByteArray body = file.mid(header.size()); + // Check for file tail presence QByteArray tail; - if (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) - { + if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { //Check file tail; tail = body.right(sizeof(UINT16)); UINT16 tailValue = *(UINT16*)tail.constData(); @@ -1247,48 +1248,47 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U body = body.left(body.size() - sizeof(UINT16)); } + // Check data checksum + // Data checksum must be calculated + UINT8 calculatedData = 0; + if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + calculatedData = calculateChecksum8((const UINT8*)body.constData(), body.size()); + if (fileHeader->IntegrityCheck.Checksum.File != calculatedData) + msgInvalidDataChecksum = true; + } + // Data checksum must be one of predefined values + else if ((revision == 1 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) + || fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM2) + msgInvalidDataChecksum = true; + // Parse current file by default - bool parseCurrentFile = true; + bool parseCurrentFile = false; bool parseAsBios = false; // Check file type - switch (fileHeader->Type) - { + switch (fileHeader->Type) { case EFI_FV_FILETYPE_ALL: - parseAsBios = true; - break; case EFI_FV_FILETYPE_RAW: parseAsBios = true; - break; case EFI_FV_FILETYPE_FREEFORM: - break; case EFI_FV_FILETYPE_SECURITY_CORE: - break; case EFI_FV_FILETYPE_PEI_CORE: - break; case EFI_FV_FILETYPE_DXE_CORE: - break; case EFI_FV_FILETYPE_PEIM: - break; case EFI_FV_FILETYPE_DRIVER: - break; case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: - break; case EFI_FV_FILETYPE_APPLICATION: - break; case EFI_FV_FILETYPE_SMM: - break; case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: - break; case EFI_FV_FILETYPE_COMBINED_SMM_DXE: - break; case EFI_FV_FILETYPE_SMM_CORE: - break; + case EFI_FV_FILETYPE_SMM_STANDALONE: + case EFI_FV_FILETYPE_SMM_CORE_STANDALONE: case EFI_FV_FILETYPE_PAD: + parseCurrentFile = true; break; default: msgInvalidType = true; - parseCurrentFile = false; }; // Check for empty file @@ -1310,25 +1310,27 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U else name = parseAsNonEmptyPadFile ? tr("Non-empty pad-file") : tr("Pad-file"); - info = tr("File GUID: %1\nType: %2h\nAttributes: %3h\nFull size: %4h (%5)\nHeader size: %6h (%7)\nBody size: %8h (%9)\nState: %10h") + info = tr("File GUID: %1\nType: %2h\nAttributes: %3h\nFull size: %4h (%5)\nHeader size: %6h (%7)\nBody size: %8h (%9)\nState: %10h\nHeader checksum: %11h\nData checksum: %12h") .arg(guidToQString(fileHeader->Name)) .hexarg2(fileHeader->Type, 2) .hexarg2(fileHeader->Attributes, 2) .hexarg(header.size() + body.size() + tail.size()).arg(header.size() + body.size() + tail.size()) .hexarg(header.size()).arg(header.size()) .hexarg(body.size()).arg(body.size()) - .hexarg2(fileHeader->State, 2); + .hexarg2(fileHeader->State, 2) + .hexarg2(fileHeader->IntegrityCheck.Checksum.Header, 2) + .hexarg2(fileHeader->IntegrityCheck.Checksum.File, 2); // Add tree item index = model->addItem(Types::File, fileHeader->Type, COMPRESSION_ALGORITHM_NONE, name, "", info, header, body, parent, mode); // Show messages if (msgInvalidHeaderChecksum) - msg(tr("parseFile: invalid header checksum"), index); + msg(tr("parseFile: invalid header checksum %1h, should be %2h").hexarg2(fileHeader->IntegrityCheck.Checksum.Header, 2).hexarg2(calculatedHeader, 2), index); if (msgInvalidDataChecksum) - msg(tr("parseFile: invalid data checksum"), index); + msg(tr("parseFile: invalid data checksum %1h, should be %2h").hexarg2(fileHeader->IntegrityCheck.Checksum.File, 2).hexarg2(calculatedData, 2), index); if (msgInvalidTailValue) - msg(tr("parseFile: invalid tail value"), index); + msg(tr("parseFile: invalid tail value %1h").hexarg(*(UINT16*)tail.data()), index); if (msgInvalidType) msg(tr("parseFile: unknown file type %1h").arg(fileHeader->Type, 2), index); @@ -1382,8 +1384,15 @@ UINT8 FfsEngine::getSectionSize(const QByteArray & file, const UINT32 sectionOff { if ((UINT32)file.size() < sectionOffset + sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_FILE; + const EFI_COMMON_SECTION_HEADER* sectionHeader = (const EFI_COMMON_SECTION_HEADER*)(file.constData() + sectionOffset); sectionSize = uint24ToUint32(sectionHeader->Size); + // This may introduce a very rare error with a non-extended section of size equal to 0xFFFFFF + if (sectionSize != 0xFFFFFF) + return ERR_SUCCESS; + + const EFI_COMMON_SECTION_HEADER2* sectionHeader2 = (const EFI_COMMON_SECTION_HEADER2*)(file.constData() + sectionOffset); + sectionSize = sectionHeader2->ExtendedSize; return ERR_SUCCESS; } @@ -1670,7 +1679,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } } else if (certificateHeader->CertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { - info += tr("\nSignature type: PCKS7"); + info += tr("\nSignature type: PKCS7"); // TODO: show signature info in Information panel } else { @@ -2219,28 +2228,51 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte if (header.size() != sizeof(EFI_FFS_FILE_HEADER)) return ERR_INVALID_FILE; - QByteArray newHeader = header; - QByteArray newBody = body; - EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*)newHeader.data(); + QByteArray newObject = header + body; + EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*)newObject.data(); + + // Determine correct file header size + bool largeFile = false; + UINT32 headerSize = sizeof(EFI_FFS_FILE_HEADER); + if (revision == 2 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { + largeFile = true; + headerSize = sizeof(EFI_FFS_FILE_HEADER2); + } + + QByteArray newHeader = newObject.left(headerSize); + QByteArray newBody = newObject.mid(headerSize); // Check if the file has a tail - UINT8 tailSize = fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT ? sizeof(UINT16) : 0; + UINT8 tailSize = (revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) ? sizeof(UINT16) : 0; if (tailSize) { // Remove the tail, it will then be added back for revision 1 volumes newBody = newBody.left(newBody.size() - tailSize); - // Remove the attribute for rev2+ volumes - if (revision != 1) { - fileHeader->Attributes &= ~(FFS_ATTRIB_TAIL_PRESENT); - } } // Correct file size - uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + newBody.size() + tailSize, fileHeader->Size); + if (!largeFile) { + if (newBody.size() >= 0xFFFFFF) { + return ERR_INVALID_FILE; + } + + uint32ToUint24(headerSize + newBody.size() + tailSize, fileHeader->Size); + } + else { + uint32ToUint24(0xFFFFFF, fileHeader->Size); + EFI_FFS_FILE_HEADER2* fileHeader2 = (EFI_FFS_FILE_HEADER2*)newHeader.data(); + fileHeader2->ExtendedSize = headerSize + newBody.size() + tailSize; + } + + // Set file state + UINT8 state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION; + if (erasePolarity) + state = ~state; + fileHeader->State = state; // Recalculate header checksum fileHeader->IntegrityCheck.Checksum.Header = 0; fileHeader->IntegrityCheck.Checksum.File = 0; - fileHeader->IntegrityCheck.Checksum.Header = calculateChecksum8((const UINT8*)fileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1); + fileHeader->IntegrityCheck.Checksum.Header = 0x100 - (calculateSum8((const UINT8*)newHeader.constData(), headerSize) - fileHeader->State); // Recalculate data checksum, if needed if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) @@ -2254,23 +2286,17 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte created.append(newBody); // Append tail, if needed - if (revision ==1 && tailSize) { + if (revision == 1 && tailSize) { UINT8 ht = ~fileHeader->IntegrityCheck.Checksum.Header; UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File; created.append(ht).append(ft); } - // Set file state - UINT8 state = EFI_FILE_DATA_VALID | EFI_FILE_HEADER_VALID | EFI_FILE_HEADER_CONSTRUCTION; - if (erasePolarity) - state = ~state; - fileHeader->State = state; - // Prepend header created.prepend(newHeader); // Parse file - result = parseFile(created, fileIndex, erasePolarity ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index, mode); + result = parseFile(created, fileIndex, revision, erasePolarity ? ERASE_POLARITY_TRUE : ERASE_POLARITY_FALSE, index, mode); if (result && result != ERR_VOLUMES_NOT_FOUND && result != ERR_INVALID_VOLUME) return result; @@ -2428,17 +2454,20 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co } else if (model->type(parent) == Types::File) { type = Types::Section; - const EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData(); + const EFI_COMMON_SECTION_HEADER* commonHeader = (const EFI_COMMON_SECTION_HEADER*)object.constData(); headerSize = sizeOfSectionHeader(commonHeader); } else if (model->type(parent) == Types::Section) { type = Types::Section; - const EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)object.constData(); + const EFI_COMMON_SECTION_HEADER* commonHeader = (const EFI_COMMON_SECTION_HEADER*)object.constData(); headerSize = sizeOfSectionHeader(commonHeader); } else return ERR_NOT_IMPLEMENTED; + if ((UINT32)object.size() < headerSize) + return ERR_BUFFER_TOO_SMALL; + return create(index, type, object.left(headerSize), object.right(object.size() - headerSize), mode, Actions::Insert); } @@ -2873,6 +2902,9 @@ UINT8 FfsEngine::constructPadFile(const QByteArray &guid, const UINT32 size, con if (size < sizeof(EFI_FFS_FILE_HEADER) || erasePolarity == ERASE_POLARITY_UNKNOWN) return ERR_INVALID_PARAMETER; + if (size >= 0xFFFFFF) // TODO: large file support + return ERR_INVALID_PARAMETER; + pad = QByteArray(size - guid.size(), erasePolarity == ERASE_POLARITY_TRUE ? '\xFF' : '\x00'); pad.prepend(guid); EFI_FFS_FILE_HEADER* header = (EFI_FFS_FILE_HEADER*)pad.data(); @@ -3265,6 +3297,7 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon model->subtype(index.child(i, 0)) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)){ QModelIndex peiFile = index.child(i, 0); UINT32 sectionOffset = sizeof(EFI_FFS_FILE_HEADER); + // BUGBUG: this parsing is bad and doesn't support large files, but it needs to be performed only for very old images with uncompressed DXE volumes, so whatever // Search for PE32 or TE section for (int j = 0; j < model->rowCount(peiFile); j++) { if (model->subtype(peiFile.child(j, 0)) == EFI_SECTION_PE32 || @@ -3330,6 +3363,9 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon continue; EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*)file.data(); + UINT32 fileHeaderSize = sizeof(EFI_FFS_FILE_HEADER); + if (volumeHeader->Revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) + fileHeaderSize = sizeof(EFI_FFS_FILE_HEADER2); // Pad file if (fileHeader->Type == EFI_FV_FILETYPE_PAD) { @@ -3357,8 +3393,8 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon UINT8 alignmentPower; UINT32 alignmentBase; alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3]; - alignment = (UINT32)pow(2.0, alignmentPower); - alignmentBase = header.size() + offset + sizeof(EFI_FFS_FILE_HEADER); + alignment = (UINT32)(1UL <action(index) == Actions::Rebuild) { QByteArray header = model->header(index); EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*)header.data(); - + // Check erase polarity if (erasePolarity == ERASE_POLARITY_UNKNOWN) { msg(tr("reconstructFile: unknown erase polarity"), index); @@ -3635,6 +3671,10 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision, // File contains sections else { UINT32 offset = 0; + UINT32 headerSize = sizeof(EFI_FFS_FILE_HEADER); + if (revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { + headerSize = sizeof(EFI_FFS_FILE_HEADER2); + } for (int i = 0; i < model->rowCount(index); i++) { // Align to 4 byte boundary @@ -3646,7 +3686,7 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision, } // Calculate section base - UINT32 sectionBase = base ? base + sizeof(EFI_FFS_FILE_HEADER) + offset : 0; + UINT32 sectionBase = base ? base + headerSize + offset : 0; // Reconstruct section QByteArray section; @@ -3668,13 +3708,22 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision, // Correct file size UINT8 tailSize = (revision == 1 && (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT)) ? sizeof(UINT16) : 0; - - uint32ToUint24(sizeof(EFI_FFS_FILE_HEADER) + reconstructed.size() + tailSize, fileHeader->Size); + 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 = calculateChecksum8((const UINT8*)fileHeader, sizeof(EFI_FFS_FILE_HEADER) - 1); + fileHeader->IntegrityCheck.Checksum.Header = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->State); } // Use current file body else @@ -3690,7 +3739,7 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision, fileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM2; // Append tail, if needed - if (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { UINT8 ht = ~fileHeader->IntegrityCheck.Checksum.Header; UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File; reconstructed.append(ht).append(ft); @@ -3732,6 +3781,10 @@ 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) { + extended = true; + } // Reconstruct section with children if (model->rowCount(index)) { @@ -3832,7 +3885,13 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base, } // Correct section size - uint32ToUint24(header.size() + reconstructed.size(), commonHeader->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 diff --git a/ffsengine.h b/ffsengine.h index 4fe5223..32a88ff 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -70,7 +70,7 @@ public: UINT8 parseEcRegion(const QByteArray & ec, QModelIndex & index, const QModelIndex & parent, const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseBios(const QByteArray & bios, const QModelIndex & parent = QModelIndex()); UINT8 parseVolume(const QByteArray & volume, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); - UINT8 parseFile(const QByteArray & file, QModelIndex & index, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); + UINT8 parseFile(const QByteArray & file, QModelIndex & index, const UINT8 revision = 2, const UINT8 erasePolarity = ERASE_POLARITY_UNKNOWN, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); UINT8 parseSections(const QByteArray & body, const QModelIndex & parent = QModelIndex()); UINT8 parseSection(const QByteArray & section, QModelIndex & index, const QModelIndex & parent = QModelIndex(), const UINT8 mode = CREATE_MODE_APPEND); @@ -117,7 +117,6 @@ private: UINT8 parseDepexSection(const QByteArray & body, QString & parsed); UINT8 findNextVolume(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & nextVolumeOffset); UINT8 getVolumeSize(const QByteArray & bios, const UINT32 volumeOffset, UINT32 & volumeSize, UINT32 & bmVolumeSize); - UINT8 getFileSize(const QByteArray & volume, const UINT32 fileOffset, UINT32 & fileSize); UINT8 getSectionSize(const QByteArray & file, const UINT32 sectionOffset, UINT32 & sectionSize); // Reconstruction helpers diff --git a/uefitool.cpp b/uefitool.cpp index 34ca9e0..5fec49a 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.21.5")) +version(tr("0.22.0")) { clipboard = QApplication::clipboard(); From 3ffdae1123b0c3a4c263160f4a123f99fa6c7f64 Mon Sep 17 00:00:00 2001 From: Alex Matrosov Date: Sun, 10 Dec 2017 21:54:50 -0800 Subject: [PATCH 27/64] 0.22.1 multiple FFSv3 support fixes, thanks to @osresearch + multiple FFSv3 support fixes, thanks to @osresearch + fixed removal of FFS files with opposite EP bit value + disabled creation of large sections (too buggy now, will be fixed later) --- UEFIPatch/uefipatch_main.cpp | 2 +- ffs.h | 1 + ffsengine.cpp | 80 ++++++++++++++++++++---------------- uefitool.cpp | 2 +- 4 files changed, 47 insertions(+), 38 deletions(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index aac0ca7..36d4f99 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.10 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.11 - 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; diff --git a/ffs.h b/ffs.h index c761551..d9aca9a 100644 --- a/ffs.h +++ b/ffs.h @@ -346,6 +346,7 @@ extern const UINT8 ffsAlignment2Table[]; #define EFI_FILE_MARKED_FOR_UPDATE 0x08 #define EFI_FILE_DELETED 0x10 #define EFI_FILE_HEADER_INVALID 0x20 +#define EFI_FILE_ERASE_POLARITY 0x80 // Defined as "all other bits must be set to ERASE_POLARITY" in UEFI PI // PEI apriori file const QByteArray EFI_PEI_APRIORI_FILE_GUID diff --git a/ffsengine.cpp b/ffsengine.cpp index 9c66dbf..79bcb47 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -848,7 +848,7 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent) } else if (volumeHeader->Revision == 2) { // Acquire alignment - alignment = (UINT32)pow(2.0, (int)(volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16); + alignment = (UINT32)(1UL << ((volumeHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)); // Check alignment if (volumeOffset % alignment) @@ -1391,6 +1391,9 @@ UINT8 FfsEngine::getSectionSize(const QByteArray & file, const UINT32 sectionOff if (sectionSize != 0xFFFFFF) return ERR_SUCCESS; + if ((UINT32)file.size() < sectionOffset + sizeof(EFI_COMMON_SECTION_HEADER2)) + return ERR_INVALID_FILE; + const EFI_COMMON_SECTION_HEADER2* sectionHeader2 = (const EFI_COMMON_SECTION_HEADER2*)(file.constData() + sectionOffset); sectionSize = sectionHeader2->ExtendedSize; return ERR_SUCCESS; @@ -1545,7 +1548,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c QString info; QByteArray header; QByteArray body; - UINT32 headerSize; + UINT32 headerSize = sizeOfSectionHeader(sectionHeader); UINT8 result; switch (sectionHeader->Type) { @@ -1556,8 +1559,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c QByteArray decompressed; UINT8 algorithm; const EFI_COMPRESSION_SECTION* compressedSectionHeader = (const EFI_COMPRESSION_SECTION*)sectionHeader; - header = section.left(sizeof(EFI_COMPRESSION_SECTION)); - body = section.mid(sizeof(EFI_COMPRESSION_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); algorithm = COMPRESSION_ALGORITHM_UNKNOWN; // Decompress section result = decompress(body, compressedSectionHeader->CompressionType, decompressed, &algorithm); @@ -1597,12 +1600,10 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c bool msgUnknownSignature = false; bool msgUnknownUefiGuidSignature = false; - const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader; - header = section.left(sizeof(EFI_GUID_DEFINED_SECTION)); - guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)(header.constData()); - header = section.left(guidDefinedSectionHeader->DataOffset); - guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)(header.constData()); - body = section.mid(guidDefinedSectionHeader->DataOffset); + header = section.left(headerSize); + body = section.mid(headerSize); + + const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)(header.constData()); QByteArray processed = body; // Get info @@ -1757,8 +1758,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c case EFI_SECTION_DISPOSABLE: { - header = section.left(sizeof(EFI_DISPOSABLE_SECTION)); - body = section.mid(sizeof(EFI_DISPOSABLE_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); // Get info info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)") @@ -1781,7 +1782,6 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c case EFI_SECTION_PEI_DEPEX: case EFI_SECTION_SMM_DEPEX: { bool msgDepexParseFailed = false; - headerSize = sizeOfSectionHeader(sectionHeader); header = section.left(headerSize); body = section.mid(headerSize); @@ -1809,7 +1809,6 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } break; case EFI_SECTION_TE: { - headerSize = sizeOfSectionHeader(sectionHeader); header = section.left(headerSize); body = section.mid(headerSize); @@ -1860,7 +1859,6 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c case EFI_SECTION_PE32: case EFI_SECTION_PIC: { - headerSize = sizeOfSectionHeader(sectionHeader); header = section.left(headerSize); body = section.mid(headerSize); @@ -1956,7 +1954,6 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } break; case EFI_SECTION_COMPATIBILITY16: { - headerSize = sizeOfSectionHeader(sectionHeader); header = section.left(headerSize); body = section.mid(headerSize); @@ -1972,8 +1969,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } break; case EFI_SECTION_FREEFORM_SUBTYPE_GUID: { - header = section.left(sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION)); - body = section.mid(sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); const EFI_FREEFORM_SUBTYPE_GUID_SECTION* fsgHeader = (const EFI_FREEFORM_SUBTYPE_GUID_SECTION*)sectionHeader; // Get info @@ -1992,8 +1989,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } break; case EFI_SECTION_VERSION: { - header = section.left(sizeof(EFI_VERSION_SECTION)); - body = section.mid(sizeof(EFI_VERSION_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); const EFI_VERSION_SECTION* versionHeader = (const EFI_VERSION_SECTION*)sectionHeader; @@ -2011,8 +2008,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } break; case EFI_SECTION_USER_INTERFACE: { - header = section.left(sizeof(EFI_USER_INTERFACE_SECTION)); - body = section.mid(sizeof(EFI_USER_INTERFACE_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); QString text = QString::fromUtf16((const ushort*)body.constData()); // Get info @@ -2031,8 +2028,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } break; case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: { - header = section.left(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION)); - body = section.mid(sizeof(EFI_FIRMWARE_VOLUME_IMAGE_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); // Get info info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)") @@ -2054,8 +2051,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c case EFI_SECTION_RAW: { bool parsed = false; - header = section.left(sizeof(EFI_RAW_SECTION)); - body = section.mid(sizeof(EFI_RAW_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); // Get info info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)") @@ -2109,8 +2106,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c case SCT_SECTION_POSTCODE: case INSYDE_SECTION_POSTCODE: { - header = section.left(sizeof(POSTCODE_SECTION)); - body = section.mid(sizeof(POSTCODE_SECTION)); + header = section.left(headerSize); + body = section.mid(headerSize); const POSTCODE_SECTION* postcodeHeader = (const POSTCODE_SECTION*)sectionHeader; @@ -2127,8 +2124,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c } break; default: - header = section.left(sizeof(EFI_COMMON_SECTION_HEADER)); - body = section.mid(sizeof(EFI_COMMON_SECTION_HEADER)); + header = section.left(headerSize); + body = section.mid(headerSize); // Get info info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)") .hexarg2(sectionHeader->Type, 2) @@ -2234,7 +2231,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte // Determine correct file header size bool largeFile = false; UINT32 headerSize = sizeof(EFI_FFS_FILE_HEADER); - if (revision == 2 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { + if (revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { largeFile = true; headerSize = sizeof(EFI_FFS_FILE_HEADER2); } @@ -2310,12 +2307,17 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte if (model->type(parent) != Types::File && model->type(parent) != Types::Section) return ERR_INVALID_SECTION; - if (header.size() < (int) sizeof(EFI_COMMON_SECTION_HEADER)) + if ((UINT32)header.size() < sizeof(EFI_COMMON_SECTION_HEADER)) return ERR_INVALID_SECTION; QByteArray newHeader = header; EFI_COMMON_SECTION_HEADER* commonHeader = (EFI_COMMON_SECTION_HEADER*)newHeader.data(); + if (uint24ToUint32(commonHeader->Size) == EFI_SECTION2_IS_USED) { + msg(tr("create: creation of large sections not supported yet"), index); + return ERR_NOT_IMPLEMENTED; + } + switch (commonHeader->Type) { case EFI_SECTION_COMPRESSION: { @@ -2547,9 +2549,15 @@ UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, cons extracted.append(model->header(index)); extracted.append(model->body(index)); if (model->type(index) == Types::File) { - //!TODO: add volume revision check, maybe? + UINT8 revision = 2; + QModelIndex parent = model->parent(index); + if (parent.isValid() && model->type(parent) == Types::Volume) { + const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)model->header(parent).constData(); + revision = volumeHeader->Revision; + } + const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)model->header(index).constData(); - if (fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { UINT8 ht = ~fileHeader->IntegrityCheck.Checksum.Header; UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File; extracted.append(ht).append(ft); @@ -3621,9 +3629,9 @@ UINT8 FfsEngine::reconstructFile(const QModelIndex& index, const UINT8 revision, } // Check file state - // Invert it first if erase polarity is true + // Check top reserved bit of file state to determine it's original erase polarity UINT8 state = fileHeader->State; - if (erasePolarity == ERASE_POLARITY_TRUE) + if (state & EFI_FILE_ERASE_POLARITY) state = ~state; // Order of this checks must be preserved diff --git a/uefitool.cpp b/uefitool.cpp index 5fec49a..befe98a 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.22.0")) +version(tr("0.22.1")) { clipboard = QApplication::clipboard(); From 9d623c91e66bb41a4794c34966f3c19e0eab089e Mon Sep 17 00:00:00 2001 From: Alex Matrosov Date: Mon, 22 Jan 2018 23:58:29 -0800 Subject: [PATCH 28/64] fix for #99 --- ffsengine.cpp | 25 ++++++++++++++----------- uefitool.cpp | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 79bcb47..71b786c 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -871,9 +871,8 @@ 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 (%2) differs from calculated using block map %3h (%4)") - .hexarg(volumeSize).arg(volumeSize) - .hexarg(bmVolumeSize).arg(bmVolumeSize), + msg(tr("parseBios: volume size stored in header %1h differs from calculated using block map %3h") + .hexarg(volumeSize).arg(bmVolumeSize), index); // Go to next volume @@ -1219,16 +1218,16 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U // Construct empty byte for this file char empty = erasePolarity ? '\xFF' : '\x00'; - // Get file header + // Get file header QByteArray header = file.left(sizeof(EFI_FFS_FILE_HEADER)); if (revision > 1 && (fileHeader->Attributes & FFS_ATTRIB_LARGE_FILE)) { if ((UINT32)file.size() < sizeof(EFI_FFS_FILE_HEADER2)) return ERR_INVALID_FILE; header = file.left(sizeof(EFI_FFS_FILE_HEADER2)); - } - + } + // Check header checksum - UINT8 calculatedHeader = 0x100 -(calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->IntegrityCheck.Checksum.Header - fileHeader->IntegrityCheck.Checksum.File - fileHeader->State); + UINT8 calculatedHeader = 0x100 - (calculateSum8((const UINT8*)header.constData(), header.size()) - fileHeader->IntegrityCheck.Checksum.Header - fileHeader->IntegrityCheck.Checksum.File - fileHeader->State); if (fileHeader->IntegrityCheck.Checksum.Header != calculatedHeader) msgInvalidHeaderChecksum = true; @@ -1253,12 +1252,16 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, QModelIndex & index, const U UINT8 calculatedData = 0; if (fileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { calculatedData = calculateChecksum8((const UINT8*)body.constData(), body.size()); - if (fileHeader->IntegrityCheck.Checksum.File != calculatedData) - msgInvalidDataChecksum = true; } // Data checksum must be one of predefined values - else if ((revision == 1 && fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) - || fileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM2) + else if (revision == 1) { + calculatedData = FFS_FIXED_CHECKSUM; + } + else { + calculatedData = FFS_FIXED_CHECKSUM2; + } + + if (fileHeader->IntegrityCheck.Checksum.File != calculatedData) msgInvalidDataChecksum = true; // Parse current file by default diff --git a/uefitool.cpp b/uefitool.cpp index befe98a..f3c6ce3 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.22.1")) +version(tr("0.22.2")) { clipboard = QApplication::clipboard(); From df95f0755cf60779a1738463b85a9eb1c0ef3153 Mon Sep 17 00:00:00 2001 From: Cr4sh Date: Thu, 15 Feb 2018 06:04:34 +0300 Subject: [PATCH 29/64] multiple fixes --- UEFIExtract/uefiextract_main.cpp | 8 +- UEFIPatch/patches.txt | 10 ++- UEFIPatch/uefipatch_main.cpp | 4 +- UEFIReplace/uefireplace_main.cpp | 6 +- ffsengine.cpp | 129 +++++++++++++++++++------------ ffsengine.h | 3 +- types.cpp | 4 +- uefitool.cpp | 2 +- 8 files changed, 101 insertions(+), 65 deletions(-) diff --git a/UEFIExtract/uefiextract_main.cpp b/UEFIExtract/uefiextract_main.cpp index 83b8c29..5c98cc8 100644 --- a/UEFIExtract/uefiextract_main.cpp +++ b/UEFIExtract/uefiextract_main.cpp @@ -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 @@ -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; @@ -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; diff --git a/UEFIPatch/patches.txt b/UEFIPatch/patches.txt index 29d156d..4a78a8c 100644 --- a/UEFIPatch/patches.txt +++ b/UEFIPatch/patches.txt @@ -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 @@ -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 \ No newline at end of file diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 36d4f99..9c2af76 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -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 @@ -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; diff --git a/UEFIReplace/uefireplace_main.cpp b/UEFIReplace/uefireplace_main.cpp index 562db22..8ec15a1 100644 --- a/UEFIReplace/uefireplace_main.cpp +++ b/UEFIReplace/uefireplace_main.cpp @@ -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("UEFIReplace"); UEFIReplace r; @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) 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; } diff --git a/ffsengine.cpp b/ffsengine.cpp index 71b786c..f9c319d 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -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); @@ -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; @@ -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); @@ -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 @@ -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()); @@ -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) @@ -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; } @@ -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; @@ -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 @@ -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; @@ -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; diff --git a/ffsengine.h b/ffsengine.h index 32a88ff..129f44b 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -84,7 +84,6 @@ public: 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); @@ -126,7 +125,7 @@ private: // 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 diff --git a/types.cpp b/types.cpp index a9a9300..d8dd01d 100644 --- a/types.cpp +++ b/types.cpp @@ -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"); @@ -153,4 +153,4 @@ QString actionTypeToQString(const UINT8 action) default: return QObject::tr("Unknown"); } -} \ No newline at end of file +} diff --git a/uefitool.cpp b/uefitool.cpp index f3c6ce3..3e9166c 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -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(); From 50ff6dc038bf5466ec369ba960123a4a75bac30e Mon Sep 17 00:00:00 2001 From: Marton Farago Date: Thu, 15 Feb 2018 07:39:34 +0100 Subject: [PATCH 30/64] Fixed patches for Skylake-X D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 is a completly unrelated GUID (UncoreInitPei), so while it contains a code block that looks like an MSR 0xE2 lock, that has nothing to do with it. 3FFCAE95-23CF-4967-94F5-16352F68E43B has a better patch that just jumps over the whole lock enforcing block 01359D99-9446-456D-ADA4-50A711C03ADA also needs a patch, this runs on wake from S3 sleep and lock the register again if not patched. --- UEFIPatch/patches.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/UEFIPatch/patches.txt b/UEFIPatch/patches.txt index 4a78a8c..9a8a4c8 100644 --- a/UEFIPatch/patches.txt +++ b/UEFIPatch/patches.txt @@ -52,9 +52,8 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F 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 +3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:742CB9E2000000:752CB9E2000000 -# PpmInitialize | Skylake-X, Kaby Lake-X -3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBAE80F:0FBAE00F \ No newline at end of file +# CpuInitPei | Skylake-X +01359D99-9446-456D-ADA4-50A711C03ADA 12 P:BE0080000023CE0B:BE0000000023CE0B \ No newline at end of file From ea5ae2f2c881fe2326ce1fa7770c3e4c3fc6058b Mon Sep 17 00:00:00 2001 From: Alex Matrosov Date: Sun, 25 Feb 2018 15:40:14 -0800 Subject: [PATCH 31/64] fixed rebase PEI files with nonstandard alignment --- UEFIPatch/uefipatch_main.cpp | 2 +- ffsengine.cpp | 22 +++++++++++++++++----- uefitool.cpp | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 9c2af76..1b3063f 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.12 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.13 - 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; diff --git a/ffsengine.cpp b/ffsengine.cpp index f9c319d..539d2d9 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -3405,11 +3405,9 @@ UINT8 FfsEngine::reconstructVolume(const QModelIndex & index, QByteArray & recon // Normal file // Ensure correct alignment - UINT8 alignmentPower; - UINT32 alignmentBase; - alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3]; + UINT8 alignmentPower = ffsAlignmentTable[(fileHeader->Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3]; alignment = (UINT32)(1UL <Attributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3]; + UINT32 fileAlignment = (UINT32)(1UL << alignmentPower); + UINT32 alignmentBase = base + headerSize; + if (alignmentBase % fileAlignment) { + // File will be unaligned if added as is, so we must add pad file before it + // Determine pad file size + UINT32 size = fileAlignment - (alignmentBase % fileAlignment); + // Required padding is smaller then minimal pad file size + while (size < sizeof(EFI_FFS_FILE_HEADER)) { + size += fileAlignment; + } + // Adjust file base to incorporate pad file that will be added to align it + sectionBase += size; + } + // Reconstruct section QByteArray section; result = reconstructSection(index.child(i, 0), sectionBase, section); diff --git a/uefitool.cpp b/uefitool.cpp index 3e9166c..fbdc029 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.22.3")) +version(tr("0.22.4")) { clipboard = QApplication::clipboard(); From dcdb85497d5a790d89c26b93e2bec4491c2500d6 Mon Sep 17 00:00:00 2001 From: HackingThings Date: Sat, 14 Apr 2018 10:40:31 -0700 Subject: [PATCH 32/64] Fix EC region parse Fixing Copy&Paste bug --- ffsengine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 539d2d9..0747e90 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -358,9 +358,9 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in UINT32 ecEnd = 0; if (descriptorVersion == 2) { if (regionSection->EcLimit) { - pdrBegin = calculateRegionOffset(regionSection->EcBase); - pdrEnd = calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); - pdr = intelImage.mid(ecBegin, ecEnd); + ecBegin = calculateRegionOffset(regionSection->EcBase); + ecEnd = calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); + ec = intelImage.mid(ecBegin, ecEnd); ecEnd += ecBegin; } } From a5ce9ab3d966b940a88fa92088d44a5872d683a0 Mon Sep 17 00:00:00 2001 From: Alex Matrosov Date: Sun, 29 Apr 2018 22:38:54 -0700 Subject: [PATCH 33/64] bugfix --- LZMA/LzmaCompress.c | 106 +- LZMA/LzmaCompress.h | 4 +- LZMA/LzmaDecompress.c | 90 +- LZMA/LzmaDecompress.h | 8 +- Tiano/EfiTianoCompress.c | 2289 +++++++++++----------- Tiano/EfiTianoCompress.h | 125 +- Tiano/EfiTianoCompressLegacy.c | 3317 ++++++++++++++++---------------- Tiano/EfiTianoDecompress.c | 1044 +++++----- Tiano/EfiTianoDecompress.h | 55 +- UEFIPatch/patches.txt | 9 +- ffsengine.h | 1 + types.cpp | 2 + types.h | 3 +- uefitool.cpp | 16 +- uefitool.h | 1 + uefitool.ui | 19 +- 16 files changed, 3575 insertions(+), 3514 deletions(-) diff --git a/LZMA/LzmaCompress.c b/LZMA/LzmaCompress.c index 622ca86..78c04a3 100644 --- a/LZMA/LzmaCompress.c +++ b/LZMA/LzmaCompress.c @@ -25,8 +25,8 @@ static ISzAlloc SzAllocForLzma = { &AllocForLzma, &FreeForLzma }; SRes OnProgress(void *p, UInt64 inSize, UInt64 outSize) { - (void)p; (void) inSize; (void) outSize; - return SZ_OK; + (void)p; (void)inSize; (void)outSize; + return SZ_OK; } static ICompressProgress g_ProgressCallback = { &OnProgress }; @@ -34,76 +34,76 @@ static ICompressProgress g_ProgressCallback = { &OnProgress }; STATIC UINT64 EFIAPI -RShiftU64( -UINT64 Operand, -UINT32 Count +RShiftU64 ( + UINT64 Operand, + UINT32 Count ) { - return Operand >> Count; + return Operand >> Count; } VOID -SetEncodedSizeOfBuf( -UINT64 EncodedSize, -UINT8 *EncodedData +SetEncodedSizeOfBuf ( + UINT64 EncodedSize, + UINT8 *EncodedData ) { - INT32 Index; + INT32 Index; - EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF; - for (Index = LZMA_PROPS_SIZE + 1; Index <= LZMA_PROPS_SIZE + 7; Index++) - { - EncodedSize = RShiftU64(EncodedSize, 8); - EncodedData[Index] = EncodedSize & 0xFF; - } + EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF; + for (Index = LZMA_PROPS_SIZE + 1; Index <= LZMA_PROPS_SIZE + 7; Index++) + { + EncodedSize = RShiftU64(EncodedSize, 8); + EncodedData[Index] = EncodedSize & 0xFF; + } } INT32 EFIAPI LzmaCompress( -CONST UINT8 *Source, -UINT32 SourceSize, -UINT8 *Destination, -UINT32 *DestinationSize + CONST UINT8 *Source, + UINTN SourceSize, + UINT8 *Destination, + UINTN *DestinationSize ) { - SRes LzmaResult; - CLzmaEncProps props; - SizeT propsSize = LZMA_PROPS_SIZE; - SizeT destLen = SourceSize + SourceSize / 3 + 128; + SRes LzmaResult; + CLzmaEncProps props; + SizeT propsSize = LZMA_PROPS_SIZE; + SizeT destLen = SourceSize + SourceSize / 3 + 128; - if (*DestinationSize < destLen) - { - *DestinationSize = destLen; - return ERR_BUFFER_TOO_SMALL; - } + if (*DestinationSize < destLen) + { + *DestinationSize = destLen; + return ERR_BUFFER_TOO_SMALL; + } - LzmaEncProps_Init(&props); - props.dictSize = LZMA_DICTIONARY_SIZE; - props.level = 9; - props.fb = 273; + LzmaEncProps_Init(&props); + props.dictSize = LZMA_DICTIONARY_SIZE; + props.level = 9; + props.fb = 273; - LzmaResult = LzmaEncode( - (Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE), - &destLen, - Source, - SourceSize, - &props, - (UINT8*)Destination, - &propsSize, - props.writeEndMark, - &g_ProgressCallback, - &SzAllocForLzma, - &SzAllocForLzma); + LzmaResult = LzmaEncode( + (Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE), + &destLen, + Source, + SourceSize, + &props, + (UINT8*)Destination, + &propsSize, + props.writeEndMark, + &g_ProgressCallback, + &SzAllocForLzma, + &SzAllocForLzma); - *DestinationSize = destLen + LZMA_HEADER_SIZE; + *DestinationSize = destLen + LZMA_HEADER_SIZE; - SetEncodedSizeOfBuf((UINT64)SourceSize, Destination); + SetEncodedSizeOfBuf(SourceSize, Destination); - if (LzmaResult == SZ_OK) { - return ERR_SUCCESS; - } - else { - return ERR_INVALID_PARAMETER; - } + if (LzmaResult == SZ_OK) { + return ERR_SUCCESS; + } + else { + return ERR_INVALID_PARAMETER; + } } diff --git a/LZMA/LzmaCompress.h b/LZMA/LzmaCompress.h index 5767d1e..20bc427 100644 --- a/LZMA/LzmaCompress.h +++ b/LZMA/LzmaCompress.h @@ -28,9 +28,9 @@ extern "C" { EFIAPI LzmaCompress( const UINT8 *Source, - UINT32 SourceSize, + UINTN SourceSize, UINT8 *Destination, - UINT32 *DestinationSize + UINTN *DestinationSize ); #ifdef __cplusplus diff --git a/LZMA/LzmaDecompress.c b/LZMA/LzmaDecompress.c index 34e176d..2f97278 100644 --- a/LZMA/LzmaDecompress.c +++ b/LZMA/LzmaDecompress.c @@ -20,11 +20,11 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. UINT64 EFIAPI LShiftU64( -UINT64 Operand, -UINT32 Count + UINT64 Operand, + UINT32 Count ) { - return Operand << Count; + return Operand << Count; } static void * AllocForLzma(void *p, size_t size) { (void)p; return malloc(size); } @@ -40,18 +40,18 @@ Get the size of the uncompressed buffer by parsing EncodeData header. */ UINT64 GetDecodedSizeOfBuf( -UINT8 *EncodedData + UINT8 *EncodedData ) { - UINT64 DecodedSize; - INT32 Index; + UINT64 DecodedSize; + INT32 Index; - // Parse header - DecodedSize = 0; - for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--) - DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; + // Parse header + DecodedSize = 0; + for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--) + DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; - return DecodedSize; + return DecodedSize; } // @@ -88,19 +88,15 @@ buffer was returned ScratchSize. INT32 EFIAPI LzmaGetInfo( -CONST VOID *Source, -UINT32 SourceSize, -UINT32 *DestinationSize + CONST VOID *Source, + UINTN SourceSize, + UINTN *DestinationSize ) { - UInt64 DecodedSize; + ASSERT(SourceSize >= LZMA_HEADER_SIZE); (void)SourceSize; - ASSERT(SourceSize >= LZMA_HEADER_SIZE); (void)SourceSize; - - DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source); - - *DestinationSize = (UINT32)DecodedSize; - return ERR_SUCCESS; + *DestinationSize = (UINTN)GetDecodedSizeOfBuf((UINT8*)Source); + return ERR_SUCCESS; } /* @@ -125,35 +121,35 @@ The source buffer specified by Source is corrupted INT32 EFIAPI LzmaDecompress( -CONST VOID *Source, -UINT32 SourceSize, -VOID *Destination + CONST VOID *Source, + UINTN SourceSize, + VOID *Destination ) { - SRes LzmaResult; - ELzmaStatus Status; - SizeT DecodedBufSize; - SizeT EncodedDataSize; + SRes LzmaResult; + ELzmaStatus Status; + SizeT DecodedBufSize; + SizeT EncodedDataSize; - DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source); - EncodedDataSize = (SizeT)(SourceSize - LZMA_HEADER_SIZE); + DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source); + EncodedDataSize = (SizeT)(SourceSize - LZMA_HEADER_SIZE); - LzmaResult = LzmaDecode( - (Byte*)Destination, - &DecodedBufSize, - (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), - &EncodedDataSize, - (CONST Byte*) Source, - LZMA_PROPS_SIZE, - LZMA_FINISH_END, - &Status, - &SzAllocForLzma - ); + LzmaResult = LzmaDecode( + (Byte*)Destination, + &DecodedBufSize, + (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), + &EncodedDataSize, + (CONST Byte*) Source, + LZMA_PROPS_SIZE, + LZMA_FINISH_END, + &Status, + &SzAllocForLzma + ); - if (LzmaResult == SZ_OK) { - return ERR_SUCCESS; - } - else { - return ERR_INVALID_PARAMETER; - } + if (LzmaResult == SZ_OK) { + return ERR_SUCCESS; + } + else { + return ERR_INVALID_PARAMETER; + } } diff --git a/LZMA/LzmaDecompress.h b/LZMA/LzmaDecompress.h index d8e0fae..78d4ac0 100644 --- a/LZMA/LzmaDecompress.h +++ b/LZMA/LzmaDecompress.h @@ -61,8 +61,8 @@ extern "C" { EFIAPI LzmaGetInfo( const VOID *Source, - UINT32 SourceSize, - UINT32 *DestinationSize + UINTN SourceSize, + UINTN *DestinationSize ); /* @@ -88,8 +88,8 @@ extern "C" { EFIAPI LzmaDecompress( const VOID *Source, - UINT32 SourceSize, - VOID *Destination + UINTN SourceSize, + VOID *Destination ); #ifdef __cplusplus diff --git a/Tiano/EfiTianoCompress.c b/Tiano/EfiTianoCompress.c index 4f70fa5..31c0e37 100644 --- a/Tiano/EfiTianoCompress.c +++ b/Tiano/EfiTianoCompress.c @@ -1,18 +1,18 @@ /** @file -Compression routine. The compression algorithm is a mixture of LZ77 and Huffman -coding. LZ77 transforms the source data into a sequence of Original Characters -and Pointers to repeated strings. This sequence is further divided into Blocks +Compression routine. The compression algorithm is a mixture of LZ77 and Huffman +coding. LZ77 transforms the source data into a sequence of Original Characters +and Pointers to repeated strings. This sequence is further divided into Blocks and Huffman codings are applied to each Block. Copyright (c) 2014, Nikolaj Schlej Copyright (c) 2006 - 2014, Intel Corporation. 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. +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. **/ @@ -52,9 +52,9 @@ UINT8 gPBIT = 4; #define NT (CODE_BIT + 3) #define TBIT 5 #if NT > NP - #define NPT NT +#define NPT NT #else - #define NPT NP +#define NPT NP #endif // @@ -62,177 +62,163 @@ UINT8 gPBIT = 4; // STATIC -VOID +VOID PutDword( - IN UINT32 Data - ); + IN UINT32 Data +); STATIC -EFI_STATUS -AllocateMemory ( - ); +EFI_STATUS +AllocateMemory(VOID); STATIC VOID -FreeMemory ( - ); +FreeMemory(VOID); -STATIC -VOID -InitSlide ( - ); +STATIC +VOID +InitSlide(VOID); -STATIC -NODE -Child ( - IN NODE q, - IN UINT8 c - ); +STATIC +NODE +Child( + IN NODE q, + IN UINT8 c +); -STATIC -VOID -MakeChild ( - IN NODE q, - IN UINT8 c, - IN NODE r - ); - -STATIC -VOID -Split ( - IN NODE Old - ); +STATIC +VOID +MakeChild( + IN NODE q, + IN UINT8 c, + IN NODE r +); -STATIC -VOID -InsertNode ( - ); - -STATIC -VOID -DeleteNode ( - ); +STATIC +VOID +Split( + IN NODE Old +); -STATIC -VOID -GetNextMatch ( - ); - -STATIC -EFI_STATUS -Encode ( - ); +STATIC +VOID +InsertNode(VOID); -STATIC -VOID -CountTFreq ( - ); +STATIC +VOID +DeleteNode(VOID); -STATIC -VOID -WritePTLen ( - IN INT32 n, - IN INT32 nbit, - IN INT32 Special - ); +STATIC +VOID +GetNextMatch(VOID); -STATIC -VOID -WriteCLen ( - ); - -STATIC -VOID -EncodeC ( - IN INT32 c - ); +STATIC +EFI_STATUS +Encode(VOID); -STATIC -VOID -EncodeP ( - IN UINT32 p - ); +STATIC +VOID +CountTFreq(VOID); -STATIC -VOID -SendBlock ( - ); - -STATIC -VOID -Output ( - IN UINT32 c, - IN UINT32 p - ); +STATIC +VOID +WritePTLen( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special +); -STATIC -VOID -HufEncodeStart ( - ); - -STATIC -VOID -HufEncodeEnd ( - ); - -STATIC -VOID -MakeCrcTable ( - ); - -STATIC -VOID -PutBits ( - IN INT32 n, - IN UINT32 x - ); - -STATIC -INT32 -FreadCrc ( - OUT UINT8 *p, - IN INT32 n - ); - -STATIC -VOID -InitPutBits ( - ); - -STATIC -VOID -CountLen ( - IN INT32 i - ); +STATIC +VOID +WriteCLen(VOID); -STATIC -VOID -MakeLen ( - IN INT32 Root - ); - -STATIC -VOID -DownHeap ( - IN INT32 i - ); +STATIC +VOID +EncodeC( + IN INT32 c +); -STATIC -VOID -MakeCode ( - IN INT32 n, - IN UINT8 Len[], - OUT UINT16 Code[] - ); - -STATIC -INT32 -MakeTree ( - IN INT32 NParm, - IN UINT16 FreqParm[], - OUT UINT8 LenParm[], - OUT UINT16 CodeParm[] - ); +STATIC +VOID +EncodeP( + IN UINT32 p +); + +STATIC +VOID +SendBlock(VOID); + +STATIC +VOID +Output( + IN UINT32 c, + IN UINT32 p +); + +STATIC +VOID +HufEncodeStart(VOID); + +STATIC +VOID +HufEncodeEnd(VOID); + +STATIC +VOID +MakeCrcTable(VOID); + +STATIC +VOID +PutBits( + IN INT32 n, + IN UINT32 x +); + +STATIC +INT32 +FreadCrc( + OUT UINT8 *p, + IN INT32 n +); + +STATIC +VOID +InitPutBits(VOID); + +STATIC +VOID +CountLen( + IN INT32 i +); + +STATIC +VOID +MakeLen( + IN INT32 Root +); + +STATIC +VOID +DownHeap( + IN INT32 i +); + +STATIC +VOID +MakeCode( + IN INT32 n, + IN UINT8 Len[], + OUT UINT16 Code[] +); + +STATIC +INT32 +MakeTree( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[], + OUT UINT16 CodeParm[] +); // @@ -248,8 +234,8 @@ STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; STATIC UINT32 mCompSize, mOrigSize; STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], - mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1],mCCode[NC], - mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; +mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1], mCCode[NC], +mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; @@ -259,12 +245,12 @@ STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NU // EFI_STATUS -EfiCompress ( - IN CONST VOID *SrcBuffer, - IN UINT32 SrcSize, - IN VOID *DstBuffer, - IN OUT UINT32 *DstSize - ) +EfiCompress( + IN CONST VOID *SrcBuffer, + IN UINT32 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT32 *DstSize +) /*++ Routine Description: @@ -277,88 +263,89 @@ Arguments: SrcSize - The size of source data DstBuffer - The buffer to store the compressed data DstSize - On input, the size of DstBuffer; On output, - the size of the actual compressed data. + the size of the actual compressed data. Returns: EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, - DstSize contains the size needed. + DstSize contains the size needed. EFI_SUCCESS - Compression is successful. --*/ { - EFI_STATUS Status = EFI_SUCCESS; - - // - // Initializations - // - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; - gPBIT = 4; - - mSrc = (UINT8*)SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst + *DstSize; + EFI_STATUS Status = EFI_SUCCESS; - PutDword(0L); - PutDword(0L); - - MakeCrcTable (); + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + gPBIT = 4; - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; - - // - // Compress it - // - - Status = Encode(); - if (EFI_ERROR (Status)) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } - - // - // Fill in compressed size and original size - // - mDst = DstBuffer; - PutDword(mCompSize+1); - PutDword(mOrigSize); + mSrc = (UINT8*)SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; - // - // Return - // - - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + PutDword(0L); + PutDword(0L); + + MakeCrcTable(); + + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; + + // + // Compress it + // + + Status = Encode(); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize + 1); + PutDword(mOrigSize); + + // + // Return + // + + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } + else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } EFI_STATUS TianoCompress( -IN CONST VOID *SrcBuffer, -IN UINT32 SrcSize, -IN VOID *DstBuffer, -IN OUT UINT32 *DstSize + IN CONST VOID *SrcBuffer, + IN UINT32 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT32 *DstSize ) /*++ @@ -382,118 +369,118 @@ EFI_SUCCESS - Compression is successful. --*/ { - EFI_STATUS Status = EFI_SUCCESS; + EFI_STATUS Status = EFI_SUCCESS; - // - // Initializations - // - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; - gPBIT = 5; + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + gPBIT = 5; - mSrc = (UINT8*)SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst + *DstSize; + mSrc = (UINT8*)SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; - PutDword(0L); - PutDword(0L); + PutDword(0L); + PutDword(0L); - MakeCrcTable(); + MakeCrcTable(); - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; - // - // Compress it - // + // + // Compress it + // - Status = Encode(); - if (EFI_ERROR(Status)) { - return EFI_OUT_OF_RESOURCES; - } + Status = Encode(); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } - // - // Fill in compressed size and original size - // - mDst = DstBuffer; - PutDword(mCompSize + 1); - PutDword(mOrigSize); + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize + 1); + PutDword(mOrigSize); - // - // Return - // + // + // Return + // - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } - else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } + else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } -STATIC -VOID +STATIC +VOID PutDword( - IN UINT32 Data - ) + IN UINT32 Data +) /*++ Routine Description: Put a dword to output stream - + Arguments: Data - the dword to put - + Returns: (VOID) - + --*/ { - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data )) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); + } } STATIC EFI_STATUS -AllocateMemory () +AllocateMemory() /*++ Routine Description: Allocate memory spaces for data structures used in compression process - + Argements: (VOID) Returns: @@ -503,416 +490,421 @@ Returns: --*/ { - UINT32 i; - - mText = malloc (WNDSIZ * 2 + MAXMATCH); - for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) { - mText[i] = 0; - } + UINT32 i; - mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); - mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); - mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); - mParent = malloc (WNDSIZ * 2 * sizeof(*mParent)); - mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev)); - mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext)); - - mBufSiz = 16 * 1024U; - while ((mBuf = malloc(mBufSiz)) == NULL) { - mBufSiz = (mBufSiz / 10U) * 9U; - if (mBufSiz < 4 * 1024U) { - return EFI_OUT_OF_RESOURCES; - } - } - mBuf[0] = 0; - - return EFI_SUCCESS; + mText = malloc(WNDSIZ * 2 + MAXMATCH); + if (NULL == mText) + return EFI_OUT_OF_RESOURCES; + + for (i = 0; i < WNDSIZ * 2 + MAXMATCH; i++) { + mText[i] = 0; + } + + mLevel = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); + mChildCount = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); + mPosition = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); + mParent = malloc(WNDSIZ * 2 * sizeof(*mParent)); + mPrev = malloc(WNDSIZ * 2 * sizeof(*mPrev)); + mNext = malloc((MAX_HASH_VAL + 1) * sizeof(*mNext)); + + mBufSiz = 16 * 1024U; + while ((mBuf = malloc(mBufSiz)) == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + } + mBuf[0] = 0; + + return EFI_SUCCESS; } VOID -FreeMemory () +FreeMemory() /*++ Routine Description: Called when compression is completed to free memory previously allocated. - + Arguments: (VOID) Returns: (VOID) --*/ { - if (mText) { - free (mText); - } - - if (mLevel) { - free (mLevel); - } - - if (mChildCount) { - free (mChildCount); - } - - if (mPosition) { - free (mPosition); - } - - if (mParent) { - free (mParent); - } - - if (mPrev) { - free (mPrev); - } - - if (mNext) { - free (mNext); - } - - if (mBuf) { - free (mBuf); - } + if (mText) { + free(mText); + } - return; + if (mLevel) { + free(mLevel); + } + + if (mChildCount) { + free(mChildCount); + } + + if (mPosition) { + free(mPosition); + } + + if (mParent) { + free(mParent); + } + + if (mPrev) { + free(mPrev); + } + + if (mNext) { + free(mNext); + } + + if (mBuf) { + free(mBuf); + } + + return; } -STATIC -VOID -InitSlide () +STATIC +VOID +InitSlide() /*++ Routine Description: Initialize String Info Log data structures - + Arguments: (VOID) Returns: (VOID) --*/ { - NODE i; + NODE i; - for (i = WNDSIZ; i <= (NODE)(WNDSIZ + UINT8_MAX); i++) { - mLevel[i] = 1; - mPosition[i] = NIL; /* sentinel */ - } - for (i = WNDSIZ; i < (NODE)(WNDSIZ * 2); i++) { - mParent[i] = NIL; - } - mAvail = 1; - for (i = 1; i < (NODE)(WNDSIZ - 1); i++) { - mNext[i] = (NODE)(i + 1); - } - - mNext[WNDSIZ - 1] = NIL; - for (i = WNDSIZ * 2; i <= (NODE)MAX_HASH_VAL; i++) { - mNext[i] = NIL; - } + for (i = WNDSIZ; i <= (NODE)(WNDSIZ + UINT8_MAX); i++) { + mLevel[i] = 1; + mPosition[i] = NIL; /* sentinel */ + } + for (i = WNDSIZ; i < (NODE)(WNDSIZ * 2); i++) { + mParent[i] = NIL; + } + mAvail = 1; + for (i = 1; i < (NODE)(WNDSIZ - 1); i++) { + mNext[i] = (NODE)(i + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (i = WNDSIZ * 2; i <= (NODE)MAX_HASH_VAL; i++) { + mNext[i] = NIL; + } } -STATIC -NODE -Child ( - IN NODE q, - IN UINT8 c - ) +STATIC +NODE +Child( + IN NODE q, + IN UINT8 c +) /*++ Routine Description: Find child node given the parent node and the edge character - + Arguments: q - the parent node c - the edge character - + Returns: - The child node (NIL if not found) - + The child node (NIL if not found) + --*/ { - NODE r; - - r = mNext[HASH(q, c)]; - mParent[NIL] = q; /* sentinel */ - while (mParent[r] != q) { - r = mNext[r]; - } - - return r; + NODE r; + + r = mNext[HASH(q, c)]; + mParent[NIL] = q; /* sentinel */ + while (mParent[r] != q) { + r = mNext[r]; + } + + return r; } -STATIC -VOID -MakeChild ( - IN NODE q, - IN UINT8 c, - IN NODE r - ) +STATIC +VOID +MakeChild( + IN NODE q, + IN UINT8 c, + IN NODE r +) /*++ Routine Description: Create a new child for a given parent node. - + Arguments: q - the parent node c - the edge character r - the child node - + Returns: (VOID) --*/ { - NODE h, t; - - h = (NODE)HASH(q, c); - t = mNext[h]; - mNext[h] = r; - mNext[r] = t; - mPrev[t] = r; - mPrev[r] = h; - mParent[r] = q; - mChildCount[q]++; + NODE h, t; + + h = (NODE)HASH(q, c); + t = mNext[h]; + mNext[h] = r; + mNext[r] = t; + mPrev[t] = r; + mPrev[r] = h; + mParent[r] = q; + mChildCount[q]++; } -STATIC -VOID +STATIC +VOID Split ( - NODE Old - ) + IN NODE Old +) /*++ Routine Description: Split a node. - + Arguments: Old - the node to split - + Returns: (VOID) --*/ { - NODE New, t; + NODE New, t; - New = mAvail; - mAvail = mNext[New]; - mChildCount[New] = 0; - t = mPrev[Old]; - mPrev[New] = t; - mNext[t] = New; - t = mNext[Old]; - mNext[New] = t; - mPrev[t] = New; - mParent[New] = mParent[Old]; - mLevel[New] = (UINT8)mMatchLen; - mPosition[New] = mPos; - MakeChild(New, mText[mMatchPos + mMatchLen], Old); - MakeChild(New, mText[mPos + mMatchLen], mPos); + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + t = mPrev[Old]; + mPrev[New] = t; + mNext[t] = New; + t = mNext[Old]; + mNext[New] = t; + mPrev[t] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8)mMatchLen; + mPosition[New] = mPos; + MakeChild(New, mText[mMatchPos + mMatchLen], Old); + MakeChild(New, mText[mPos + mMatchLen], mPos); } -STATIC -VOID -InsertNode () +STATIC +VOID +InsertNode() /*++ Routine Description: Insert string info for current position into the String Info Log - + Arguments: (VOID) Returns: (VOID) --*/ { - NODE q, r, j, t; - UINT8 c, *t1, *t2; + NODE q, r, j, t; + UINT8 c, *t1, *t2; + + if (mMatchLen >= 4) { + + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Travese the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // in DeleteNode() later. + // + + mMatchLen--; + r = (INT16)((mMatchPos + 1) | WNDSIZ); + while ((q = mParent[r]) == NIL) { + r = mNext[r]; + } + while (mLevel[q] >= mMatchLen) { + r = q; q = mParent[q]; + } + t = q; + while (mPosition[t] < 0) { + mPosition[t] = mPos; + t = mParent[t]; + } + if (t < (NODE)WNDSIZ) { + mPosition[t] = (NODE)(mPos | PERC_FLAG); + } + } + else { + + // + // Locate the target tree + // + + q = (INT16)(mText[mPos] + WNDSIZ); + c = mText[mPos + 1]; + if ((r = Child(q, c)) == NIL) { + MakeChild(q, c, mPos); + mMatchLen = 1; + return; + } + mMatchLen = 2; + } + + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + + for (; ; ) { + if (r >= (NODE)WNDSIZ) { + j = MAXMATCH; + mMatchPos = r; + } + else { + j = mLevel[r]; + mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG); + } + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < j) { + if (*t1 != *t2) { + Split(r); + return; + } + mMatchLen++; + t1++; + t2++; + } + if (mMatchLen >= MAXMATCH) { + break; + } + mPosition[r] = mPos; + q = r; + if ((r = Child(q, *t1)) == NIL) { + MakeChild(q, *t1, mPos); + return; + } + mMatchLen++; + } + t = mPrev[r]; + mPrev[mPos] = t; + mNext[t] = mPos; + t = mNext[r]; + mNext[mPos] = t; + mPrev[t] = mPos; + mParent[mPos] = q; + mParent[r] = NIL; + + // + // Special usage of 'next' + // + mNext[r] = mPos; - if (mMatchLen >= 4) { - - // - // We have just got a long match, the target tree - // can be located by MatchPos + 1. Travese the tree - // from bottom up to get to a proper starting point. - // The usage of PERC_FLAG ensures proper node deletion - // in DeleteNode() later. - // - - mMatchLen--; - r = (INT16)((mMatchPos + 1) | WNDSIZ); - while ((q = mParent[r]) == NIL) { - r = mNext[r]; - } - while (mLevel[q] >= mMatchLen) { - r = q; q = mParent[q]; - } - t = q; - while (mPosition[t] < 0) { - mPosition[t] = mPos; - t = mParent[t]; - } - if (t < (NODE)WNDSIZ) { - mPosition[t] = (NODE)(mPos | PERC_FLAG); - } - } else { - - // - // Locate the target tree - // - - q = (INT16)(mText[mPos] + WNDSIZ); - c = mText[mPos + 1]; - if ((r = Child(q, c)) == NIL) { - MakeChild(q, c, mPos); - mMatchLen = 1; - return; - } - mMatchLen = 2; - } - - // - // Traverse down the tree to find a match. - // Update Position value along the route. - // Node split or creation is involved. - // - - for ( ; ; ) { - if (r >= (NODE)WNDSIZ) { - j = MAXMATCH; - mMatchPos = r; - } else { - j = mLevel[r]; - mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG); - } - if (mMatchPos >= mPos) { - mMatchPos -= WNDSIZ; - } - t1 = &mText[mPos + mMatchLen]; - t2 = &mText[mMatchPos + mMatchLen]; - while (mMatchLen < j) { - if (*t1 != *t2) { - Split(r); - return; - } - mMatchLen++; - t1++; - t2++; - } - if (mMatchLen >= MAXMATCH) { - break; - } - mPosition[r] = mPos; - q = r; - if ((r = Child(q, *t1)) == NIL) { - MakeChild(q, *t1, mPos); - return; - } - mMatchLen++; - } - t = mPrev[r]; - mPrev[mPos] = t; - mNext[t] = mPos; - t = mNext[r]; - mNext[mPos] = t; - mPrev[t] = mPos; - mParent[mPos] = q; - mParent[r] = NIL; - - // - // Special usage of 'next' - // - mNext[r] = mPos; - } -STATIC -VOID -DeleteNode () +STATIC +VOID +DeleteNode() /*++ Routine Description: Delete outdated string info. (The Usage of PERC_FLAG ensures a clean deletion) - + Arguments: (VOID) Returns: (VOID) --*/ { - NODE q, r, s, t, u; + NODE q, r, s, t, u; - if (mParent[mPos] == NIL) { - return; - } - - r = mPrev[mPos]; - s = mNext[mPos]; - mNext[r] = s; - mPrev[s] = r; - r = mParent[mPos]; - mParent[mPos] = NIL; - if (r >= (NODE)WNDSIZ || --mChildCount[r] > 1) { - return; - } - t = (NODE)(mPosition[r] & ~PERC_FLAG); - if (t >= mPos) { - t -= WNDSIZ; - } - s = t; - q = mParent[r]; - while ((u = mPosition[q]) & PERC_FLAG) { - u &= ~PERC_FLAG; - if (u >= mPos) { - u -= WNDSIZ; - } - if (u > s) { - s = u; - } - mPosition[q] = (INT16)(s | WNDSIZ); - q = mParent[q]; - } - if (q < (NODE)WNDSIZ) { - if (u >= mPos) { - u -= WNDSIZ; - } - if (u > s) { - s = u; - } - mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG); - } - s = Child(r, mText[t + mLevel[r]]); - t = mPrev[s]; - u = mNext[s]; - mNext[t] = u; - mPrev[u] = t; - t = mPrev[r]; - mNext[t] = s; - mPrev[s] = t; - t = mNext[r]; - mPrev[t] = s; - mNext[s] = t; - mParent[s] = mParent[r]; - mParent[r] = NIL; - mNext[r] = mAvail; - mAvail = r; + if (mParent[mPos] == NIL) { + return; + } + + r = mPrev[mPos]; + s = mNext[mPos]; + mNext[r] = s; + mPrev[s] = r; + r = mParent[mPos]; + mParent[mPos] = NIL; + if (r >= (NODE)WNDSIZ || --mChildCount[r] > 1) { + return; + } + t = (NODE)(mPosition[r] & ~PERC_FLAG); + if (t >= mPos) { + t -= WNDSIZ; + } + s = t; + q = mParent[r]; + while ((u = mPosition[q]) & PERC_FLAG) { + u &= ~PERC_FLAG; + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ); + q = mParent[q]; + } + if (q < (NODE)WNDSIZ) { + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG); + } + s = Child(r, mText[t + mLevel[r]]); + t = mPrev[s]; + u = mNext[s]; + mNext[t] = u; + mPrev[u] = t; + t = mPrev[r]; + mNext[t] = s; + mPrev[s] = t; + t = mNext[r]; + mPrev[t] = s; + mNext[s] = t; + mParent[s] = mParent[r]; + mParent[r] = NIL; + mNext[r] = mAvail; + mAvail = r; } -STATIC -VOID -GetNextMatch () +STATIC +VOID +GetNextMatch() /*++ Routine Description: @@ -926,22 +918,22 @@ Returns: (VOID) --*/ { - INT32 n; + INT32 n; - mRemainder--; - if (++mPos == WNDSIZ * 2) { - memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); - n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); - mRemainder += n; - mPos = WNDSIZ; - } - DeleteNode(); - InsertNode(); + mRemainder--; + if (++mPos == WNDSIZ * 2) { + memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += n; + mPos = WNDSIZ; + } + DeleteNode(); + InsertNode(); } STATIC EFI_STATUS -Encode () +Encode() /*++ Routine Description: @@ -951,323 +943,338 @@ Routine Description: Arguments: (VOID) Returns: - + EFI_SUCCESS - The compression is successful EFI_OUT_0F_RESOURCES - Not enough memory for compression process --*/ { - EFI_STATUS Status; - INT32 LastMatchLen; - NODE LastMatchPos; + EFI_STATUS Status; + INT32 LastMatchLen; + NODE LastMatchPos; - Status = AllocateMemory(); - if (EFI_ERROR(Status)) { - FreeMemory(); - return Status; - } + Status = AllocateMemory(); + if (EFI_ERROR(Status)) { + FreeMemory(); + return Status; + } - InitSlide(); - - HufEncodeStart(); + InitSlide(); - mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); - - mMatchLen = 0; - mPos = WNDSIZ; - InsertNode(); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - while (mRemainder > 0) { - LastMatchLen = mMatchLen; - LastMatchPos = mMatchPos; - GetNextMatch(); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - - if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { - - // - // Not enough benefits are gained by outputting a pointer, - // so just output the original character - // - - Output(mText[mPos - 1], 0); - } else { - - // - // Outputting a pointer is beneficial enough, do it. - // - - Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), - (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); - while (--LastMatchLen > 0) { - GetNextMatch(); - } - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - } - } - - HufEncodeEnd(); - FreeMemory(); - return EFI_SUCCESS; + HufEncodeStart(); + + mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + + Output(mText[mPos - 1], 0); + } + else { + + // + // Outputting a pointer is beneficial enough, do it. + // + + Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); + while (--LastMatchLen > 0) { + GetNextMatch(); + } + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd(); + FreeMemory(); + return EFI_SUCCESS; } -STATIC -VOID -CountTFreq () +STATIC +VOID +CountTFreq() /*++ Routine Description: Count the frequencies for the Extra Set - + Arguments: (VOID) Returns: (VOID) --*/ { - INT32 i, k, n, Count; + INT32 i, k, n, Count; - for (i = 0; i < NT; i++) { - mTFreq[i] = 0; - } - n = NC; - while (n > 0 && mCLen[n - 1] == 0) { - n--; - } - i = 0; - while (i < n) { - k = mCLen[i++]; - if (k == 0) { - Count = 1; - while (i < n && mCLen[i] == 0) { - i++; - Count++; - } - if (Count <= 2) { - mTFreq[0] = (UINT16)(mTFreq[0] + Count); - } else if (Count <= 18) { - mTFreq[1]++; - } else if (Count == 19) { - mTFreq[0]++; - mTFreq[1]++; - } else { - mTFreq[2]++; - } - } else { - mTFreq[k + 2]++; - } - } + for (i = 0; i < NT; i++) { + mTFreq[i] = 0; + } + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + Count++; + } + if (Count <= 2) { + mTFreq[0] = (UINT16)(mTFreq[0] + Count); + } + else if (Count <= 18) { + mTFreq[1]++; + } + else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } + else { + mTFreq[2]++; + } + } + else { + mTFreq[k + 2]++; + } + } } -STATIC -VOID -WritePTLen ( - IN INT32 n, - IN INT32 nbit, - IN INT32 Special - ) +STATIC +VOID +WritePTLen( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special +) /*++ Routine Description: Outputs the code length array for the Extra Set or the Position Set. - + Arguments: n - the number of symbols nbit - the number of bits needed to represent 'n' Special - the special symbol that needs to be take care of - + Returns: (VOID) --*/ { - INT32 i, k; + INT32 i, k; - while (n > 0 && mPTLen[n - 1] == 0) { - n--; - } - PutBits(nbit, n); - i = 0; - while (i < n) { - k = mPTLen[i++]; - if (k <= 6) { - PutBits(3, k); - } else { - PutBits(k - 3, (1U << (k - 3)) - 2); - } - if (i == Special) { - while (i < 6 && mPTLen[i] == 0) { - i++; - } - PutBits(2, (i - 3) & 3); - } - } + while (n > 0 && mPTLen[n - 1] == 0) { + n--; + } + PutBits(nbit, n); + i = 0; + while (i < n) { + k = mPTLen[i++]; + if (k <= 6) { + PutBits(3, k); + } + else { + PutBits(k - 3, (1U << (k - 3)) - 2); + } + if (i == Special) { + while (i < 6 && mPTLen[i] == 0) { + i++; + } + PutBits(2, (i - 3) & 3); + } + } } -STATIC -VOID -WriteCLen () +STATIC +VOID +WriteCLen() /*++ Routine Description: Outputs the code length array for Char&Length Set - + Arguments: (VOID) Returns: (VOID) --*/ { - INT32 i, k, n, Count; + INT32 i, k, n, Count; - n = NC; - while (n > 0 && mCLen[n - 1] == 0) { - n--; - } - PutBits(CBIT, n); - i = 0; - while (i < n) { - k = mCLen[i++]; - if (k == 0) { - Count = 1; - while (i < n && mCLen[i] == 0) { - i++; - Count++; - } - if (Count <= 2) { - for (k = 0; k < Count; k++) { - PutBits(mPTLen[0], mPTCode[0]); - } - } else if (Count <= 18) { - PutBits(mPTLen[1], mPTCode[1]); - PutBits(4, Count - 3); - } else if (Count == 19) { - PutBits(mPTLen[0], mPTCode[0]); - PutBits(mPTLen[1], mPTCode[1]); - PutBits(4, 15); - } else { - PutBits(mPTLen[2], mPTCode[2]); - PutBits(CBIT, Count - 20); - } - } else { - PutBits(mPTLen[k + 2], mPTCode[k + 2]); - } - } + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + PutBits(CBIT, n); + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + Count++; + } + if (Count <= 2) { + for (k = 0; k < Count; k++) { + PutBits(mPTLen[0], mPTCode[0]); + } + } + else if (Count <= 18) { + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, Count - 3); + } + else if (Count == 19) { + PutBits(mPTLen[0], mPTCode[0]); + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, 15); + } + else { + PutBits(mPTLen[2], mPTCode[2]); + PutBits(CBIT, Count - 20); + } + } + else { + PutBits(mPTLen[k + 2], mPTCode[k + 2]); + } + } } -STATIC -VOID -EncodeC ( - IN INT32 c - ) +STATIC +VOID +EncodeC( + IN INT32 c +) { - PutBits(mCLen[c], mCCode[c]); + PutBits(mCLen[c], mCCode[c]); } -STATIC -VOID -EncodeP ( - IN UINT32 p - ) +STATIC +VOID +EncodeP( + IN UINT32 p +) { - UINT32 c, q; + UINT32 c, q; - c = 0; - q = p; - while (q) { - q >>= 1; - c++; - } - PutBits(mPTLen[c], mPTCode[c]); - if (c > 1) { - PutBits(c - 1, p & (0xFFFFU >> (17 - c))); - } + c = 0; + q = p; + while (q) { + q >>= 1; + c++; + } + PutBits(mPTLen[c], mPTCode[c]); + if (c > 1) { + PutBits(c - 1, p & (0xFFFFU >> (17 - c))); + } } -STATIC -VOID -SendBlock () +STATIC +VOID +SendBlock() /*++ Routine Description: Huffman code the block and output it. - + Argument: (VOID) Returns: (VOID) --*/ { - UINT32 i, k, Flags, Root, Pos, Size; - Flags = 0; + UINT32 i, k, Flags, Root, Pos, Size; + Flags = 0; - Root = MakeTree(NC, mCFreq, mCLen, mCCode); - Size = mCFreq[Root]; - PutBits(16, Size); - if (Root >= NC) { - CountTFreq(); - Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); - if (Root >= NT) { - WritePTLen(NT, TBIT, 3); - } else { - PutBits(TBIT, 0); - PutBits(TBIT, Root); - } - WriteCLen(); - } else { - PutBits(TBIT, 0); - PutBits(TBIT, 0); - PutBits(CBIT, 0); - PutBits(CBIT, Root); - } - Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); - if (Root >= NP) { - WritePTLen(NP, gPBIT, -1); - } else { - PutBits(gPBIT, 0); - PutBits(gPBIT, Root); - } - Pos = 0; - for (i = 0; i < Size; i++) { - if (i % UINT8_BIT == 0) { - Flags = mBuf[Pos++]; - } else { - Flags <<= 1; - } - if (Flags & (1U << (UINT8_BIT - 1))) { - EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); - k = mBuf[Pos++] << UINT8_BIT; - k += mBuf[Pos++]; - EncodeP(k); - } else { - EncodeC(mBuf[Pos++]); - } - } - for (i = 0; i < NC; i++) { - mCFreq[i] = 0; - } - for (i = 0; i < NP; i++) { - mPFreq[i] = 0; - } + Root = MakeTree(NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + PutBits(16, Size); + if (Root >= NC) { + CountTFreq(); + Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen(NT, TBIT, 3); + } + else { + PutBits(TBIT, 0); + PutBits(TBIT, Root); + } + WriteCLen(); + } + else { + PutBits(TBIT, 0); + PutBits(TBIT, 0); + PutBits(CBIT, 0); + PutBits(CBIT, Root); + } + Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen(NP, gPBIT, -1); + } + else { + PutBits(gPBIT, 0); + PutBits(gPBIT, Root); + } + Pos = 0; + for (i = 0; i < Size; i++) { + if (i % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } + else { + Flags <<= 1; + } + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); + k = mBuf[Pos++] << UINT8_BIT; + k += mBuf[Pos++]; + EncodeP(k); + } + else { + EncodeC(mBuf[Pos++]); + } + } + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } } -STATIC -VOID -Output ( - IN UINT32 c, - IN UINT32 p - ) +STATIC +VOID +Output( + IN UINT32 c, + IN UINT32 p +) /*++ Routine Description: @@ -1283,89 +1290,90 @@ Returns: (VOID) --*/ { - STATIC UINT32 CPos; + STATIC UINT32 CPos; - if ((mOutputMask >>= 1) == 0) { - mOutputMask = 1U << (UINT8_BIT - 1); - if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { - SendBlock(); - mOutputPos = 0; - } - CPos = mOutputPos++; - mBuf[CPos] = 0; - } - mBuf[mOutputPos++] = (UINT8) c; - mCFreq[c]++; - if (c >= (1U << UINT8_BIT)) { - mBuf[CPos] |= mOutputMask; - mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT); - mBuf[mOutputPos++] = (UINT8) p; - c = 0; - while (p) { - p >>= 1; - c++; - } - mPFreq[c]++; - } + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { + SendBlock(); + mOutputPos = 0; + } + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + mBuf[mOutputPos++] = (UINT8)c; + mCFreq[c]++; + if (c >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT); + mBuf[mOutputPos++] = (UINT8)p; + c = 0; + while (p) { + p >>= 1; + c++; + } + mPFreq[c]++; + } } STATIC VOID -HufEncodeStart () +HufEncodeStart() { - INT32 i; + INT32 i; - for (i = 0; i < NC; i++) { - mCFreq[i] = 0; - } - for (i = 0; i < NP; i++) { - mPFreq[i] = 0; - } - mOutputPos = mOutputMask = 0; - InitPutBits(); - return; + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } + mOutputPos = mOutputMask = 0; + InitPutBits(); + return; } -STATIC -VOID -HufEncodeEnd () +STATIC +VOID +HufEncodeEnd() { - SendBlock(); - - // - // Flush remaining bits - // - PutBits(UINT8_BIT - 1, 0); - - return; + SendBlock(); + + // + // Flush remaining bits + // + PutBits(UINT8_BIT - 1, 0); + + return; } -STATIC -VOID -MakeCrcTable () +STATIC +VOID +MakeCrcTable() { - UINT32 i, j, r; + UINT32 i, j, r; - for (i = 0; i <= UINT8_MAX; i++) { - r = i; - for (j = 0; j < UINT8_BIT; j++) { - if (r & 1) { - r = (r >> 1) ^ CRCPOLY; - } else { - r >>= 1; - } - } - mCrcTable[i] = (UINT16)r; - } + for (i = 0; i <= UINT8_MAX; i++) { + r = i; + for (j = 0; j < UINT8_BIT; j++) { + if (r & 1) { + r = (r >> 1) ^ CRCPOLY; + } + else { + r >>= 1; + } + } + mCrcTable[i] = (UINT16)r; + } } -STATIC -VOID -PutBits ( - IN INT32 n, - IN UINT32 x - ) +STATIC +VOID +PutBits( + IN INT32 n, + IN UINT32 x +) /*++ Routine Description: @@ -1375,51 +1383,53 @@ Routine Description: Argments: n - the rightmost n bits of the data is used - x - the data + x - the data Returns: (VOID) --*/ { - UINT8 Temp; - - if (n < mBitCount) { - mSubBitBuf |= x << (mBitCount -= n); - } else { - - Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount))); - if (mDst < mDstUpperLimit) { - *mDst++ = Temp; - } - mCompSize++; + UINT8 Temp; - if (n < UINT8_BIT) { - mSubBitBuf = x << (mBitCount = UINT8_BIT - n); - } else { - - Temp = (UINT8)(x >> (n - UINT8_BIT)); - if (mDst < mDstUpperLimit) { - *mDst++ = Temp; - } - mCompSize++; - - mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n); - } - } + if (n < mBitCount) { + mSubBitBuf |= x << (mBitCount -= n); + } + else { + + Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + if (n < UINT8_BIT) { + mSubBitBuf = x << (mBitCount = UINT8_BIT - n); + } + else { + + Temp = (UINT8)(x >> (n - UINT8_BIT)); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n); + } + } } -STATIC -INT32 -FreadCrc ( - OUT UINT8 *p, - IN INT32 n - ) +STATIC +INT32 +FreadCrc( + OUT UINT8 *p, + IN INT32 n +) /*++ Routine Description: Read in source data - + Arguments: p - the buffer to hold the data @@ -1428,156 +1438,157 @@ Arguments: Returns: number of bytes actually read - + --*/ { - INT32 i; + INT32 i; - for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) { - *p++ = *mSrc++; - } - n = i; + for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) { + *p++ = *mSrc++; + } + n = i; - p -= n; - mOrigSize += n; - while (--i >= 0) { - UPDATE_CRC(*p++); - } - return n; + p -= n; + mOrigSize += n; + while (--i >= 0) { + UPDATE_CRC(*p++); + } + return n; } -STATIC -VOID -InitPutBits () +STATIC +VOID +InitPutBits() { - mBitCount = UINT8_BIT; - mSubBitBuf = 0; + mBitCount = UINT8_BIT; + mSubBitBuf = 0; } -STATIC -VOID -CountLen ( - IN INT32 i - ) +STATIC +VOID +CountLen( + IN INT32 i +) /*++ Routine Description: Count the number of each code length for a Huffman tree. - + Arguments: i - the top node - + Returns: (VOID) --*/ { - STATIC INT32 Depth = 0; + STATIC INT32 Depth = 0; - if (i < mN) { - mLenCnt[(Depth < 16) ? Depth : 16]++; - } else { - Depth++; - CountLen(mLeft [i]); - CountLen(mRight[i]); - Depth--; - } + if (i < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } + else { + Depth++; + CountLen(mLeft[i]); + CountLen(mRight[i]); + Depth--; + } } -STATIC -VOID -MakeLen ( - IN INT32 Root - ) +STATIC +VOID +MakeLen( + IN INT32 Root +) /*++ Routine Description: Create code length array for a Huffman tree - + Arguments: Root - the root of the tree --*/ { - INT32 i, k; - UINT32 Cum; + INT32 i, k; + UINT32 Cum; - for (i = 0; i <= 16; i++) { - mLenCnt[i] = 0; - } - CountLen(Root); - - // - // Adjust the length count array so that - // no code will be generated longer than its designated length - // - - Cum = 0; - for (i = 16; i > 0; i--) { - Cum += mLenCnt[i] << (16 - i); - } - while (Cum != (1U << 16)) { - mLenCnt[16]--; - for (i = 15; i > 0; i--) { - if (mLenCnt[i] != 0) { - mLenCnt[i]--; - mLenCnt[i+1] += 2; - break; - } - } - Cum--; - } - for (i = 16; i > 0; i--) { - k = mLenCnt[i]; - while (--k >= 0) { - mLen[*mSortPtr++] = (UINT8)i; - } - } + for (i = 0; i <= 16; i++) { + mLenCnt[i] = 0; + } + CountLen(Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + + Cum = 0; + for (i = 16; i > 0; i--) { + Cum += mLenCnt[i] << (16 - i); + } + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (i = 15; i > 0; i--) { + if (mLenCnt[i] != 0) { + mLenCnt[i]--; + mLenCnt[i + 1] += 2; + break; + } + } + Cum--; + } + for (i = 16; i > 0; i--) { + k = mLenCnt[i]; + while (--k >= 0) { + mLen[*mSortPtr++] = (UINT8)i; + } + } } -STATIC -VOID -DownHeap ( - IN INT32 i - ) +STATIC +VOID +DownHeap( + IN INT32 i +) { - INT32 j, k; + INT32 j, k; - // - // priority queue: send i-th entry down heap - // - - k = mHeap[i]; - while ((j = 2 * i) <= mHeapSize) { - if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) { - j++; - } - if (mFreq[k] <= mFreq[mHeap[j]]) { - break; - } - mHeap[i] = mHeap[j]; - i = j; - } - mHeap[i] = (INT16)k; + // + // priority queue: send i-th entry down heap + // + + k = mHeap[i]; + while ((j = 2 * i) <= mHeapSize) { + if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) { + j++; + } + if (mFreq[k] <= mFreq[mHeap[j]]) { + break; + } + mHeap[i] = mHeap[j]; + i = j; + } + mHeap[i] = (INT16)k; } -STATIC -VOID -MakeCode ( - IN INT32 n, - IN UINT8 Len[], - OUT UINT16 Code[] - ) +STATIC +VOID +MakeCode( + IN INT32 n, + IN UINT8 Len[], + OUT UINT16 Code[] +) /*++ Routine Description: Assign code to each symbol based on the code length array - + Arguments: n - number of symbols @@ -1588,101 +1599,101 @@ Returns: (VOID) --*/ { - INT32 i; - UINT16 Start[18]; + INT32 i; + UINT16 Start[18]; - Start[1] = 0; - for (i = 1; i <= 16; i++) { - Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1); - } - for (i = 0; i < n; i++) { - Code[i] = Start[Len[i]]++; - } + Start[1] = 0; + for (i = 1; i <= 16; i++) { + Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1); + } + for (i = 0; i < n; i++) { + Code[i] = Start[Len[i]]++; + } } -STATIC -INT32 -MakeTree ( - IN INT32 NParm, - IN UINT16 FreqParm[], - OUT UINT8 LenParm[], - OUT UINT16 CodeParm[] - ) +STATIC +INT32 +MakeTree( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[], + OUT UINT16 CodeParm[] +) /*++ Routine Description: Generates Huffman codes given a frequency distribution of symbols - + Arguments: NParm - number of symbols FreqParm - frequency of each symbol LenParm - code length for each symbol CodeParm - code for each symbol - + Returns: Root of the Huffman tree. - + --*/ { - INT32 i, j, k, Avail; - - // - // make tree, calculate len[], return root - // + INT32 i, j, k, Avail; - mN = NParm; - mFreq = FreqParm; - mLen = LenParm; - Avail = mN; - mHeapSize = 0; - mHeap[1] = 0; - for (i = 0; i < mN; i++) { - mLen[i] = 0; - if (mFreq[i]) { - mHeap[++mHeapSize] = (INT16)i; - } - } - if (mHeapSize < 2) { - CodeParm[mHeap[1]] = 0; - return mHeap[1]; - } - for (i = mHeapSize / 2; i >= 1; i--) { - - // - // make priority queue - // - DownHeap(i); - } - mSortPtr = CodeParm; - do { - i = mHeap[1]; - if (i < mN) { - *mSortPtr++ = (UINT16)i; - } - mHeap[1] = mHeap[mHeapSize--]; - DownHeap(1); - j = mHeap[1]; - if (j < mN) { - *mSortPtr++ = (UINT16)j; - } - k = Avail++; - mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]); - mHeap[1] = (INT16)k; - DownHeap(1); - mLeft[k] = (UINT16)i; - mRight[k] = (UINT16)j; - } while (mHeapSize > 1); - - mSortPtr = CodeParm; - MakeLen(k); - MakeCode(NParm, LenParm, CodeParm); - - // - // return root - // - return k; + // + // make tree, calculate len[], return root + // + + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (i = 0; i < mN; i++) { + mLen[i] = 0; + if (mFreq[i]) { + mHeap[++mHeapSize] = (INT16)i; + } + } + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + for (i = mHeapSize / 2; i >= 1; i--) { + + // + // make priority queue + // + DownHeap(i); + } + mSortPtr = CodeParm; + do { + i = mHeap[1]; + if (i < mN) { + *mSortPtr++ = (UINT16)i; + } + mHeap[1] = mHeap[mHeapSize--]; + DownHeap(1); + j = mHeap[1]; + if (j < mN) { + *mSortPtr++ = (UINT16)j; + } + k = Avail++; + mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]); + mHeap[1] = (INT16)k; + DownHeap(1); + mLeft[k] = (UINT16)i; + mRight[k] = (UINT16)j; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen(k); + MakeCode(NParm, LenParm, CodeParm); + + // + // return root + // + return k; } diff --git a/Tiano/EfiTianoCompress.h b/Tiano/EfiTianoCompress.h index e5c2fb9..b317cfd 100644 --- a/Tiano/EfiTianoCompress.h +++ b/Tiano/EfiTianoCompress.h @@ -32,85 +32,82 @@ Header file for compression routine. extern "C" { #endif - /*++ + /*++ - Routine Description: + Routine Description: - Tiano compression routine. + Tiano compression routine. - Arguments: + Arguments: - SrcBuffer - The buffer storing the source data - SrcSize - The size of source data - DstBuffer - The buffer to store the compressed data - DstSize - On input, the size of DstBuffer; On output, - the size of the actual compressed data. + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. - Returns: + Returns: - EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, - DstSize contains the size needed. - EFI_SUCCESS - Compression is successful. - EFI_OUT_OF_RESOURCES - No resource to complete function. - EFI_INVALID_PARAMETER - Parameter supplied is wrong. + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. - --*/ - EFI_STATUS - TianoCompress( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize - ) - ; + --*/ + EFI_STATUS + TianoCompress( + IN CONST VOID *SrcBuffer, + IN UINT32 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT32 *DstSize + ); - EFI_STATUS - TianoCompressLegacy( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize - ) - ; - /*++ + EFI_STATUS + TianoCompressLegacy( + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize + ); + /*++ - Routine Description: + Routine Description: - EFI 1.1 compression routine. + EFI 1.1 compression routine. - Arguments: + Arguments: - SrcBuffer - The buffer storing the source data - SrcSize - The size of source data - DstBuffer - The buffer to store the compressed data - DstSize - On input, the size of DstBuffer; On output, - the size of the actual compressed data. + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. - Returns: + Returns: - EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, - DstSize contains the size needed. - EFI_SUCCESS - Compression is successful. - EFI_OUT_OF_RESOURCES - No resource to complete function. - EFI_INVALID_PARAMETER - Parameter supplied is wrong. + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. - --*/ - EFI_STATUS - EfiCompress( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize - ) - ; - EFI_STATUS - EfiCompressLegacy( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize - ) - ; + --*/ + EFI_STATUS + EfiCompress( + IN CONST VOID *SrcBuffer, + IN UINT32 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT32 *DstSize + ); + + EFI_STATUS + EfiCompressLegacy( + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize + ); #ifdef __cplusplus } diff --git a/Tiano/EfiTianoCompressLegacy.c b/Tiano/EfiTianoCompressLegacy.c index 7142ca8..9aed6f1 100644 --- a/Tiano/EfiTianoCompressLegacy.c +++ b/Tiano/EfiTianoCompressLegacy.c @@ -71,190 +71,190 @@ typedef INT32 NODE; // STATIC - VOID - PutDword( - UINT32 Data - ); - -STATIC - INT32 - AllocateMemory ( - VOID - ); - -STATIC - VOID - FreeMemory ( - VOID - ); - -STATIC - VOID - InitSlide ( - VOID - ); - -STATIC - NODE - Child ( - NODE NodeQ, - UINT8 CharC - ); - -STATIC - VOID - MakeChild ( - NODE NodeQ, - UINT8 CharC, - NODE NodeR - ); - -STATIC - VOID - Split ( - NODE Old - ); - -STATIC - VOID - InsertNode ( - VOID - ); - -STATIC - VOID - DeleteNode ( - VOID - ); - -STATIC - VOID - GetNextMatch ( - VOID - ); - -STATIC - INT32 - Encode ( - VOID - ); - -STATIC - VOID - CountTFreq ( - VOID - ); - -STATIC - VOID - WritePTLen ( - INT32 Number, - INT32 nbit, - INT32 Special - ); - -STATIC - VOID - WriteCLen ( - VOID - ); - -STATIC - VOID - EncodeC ( - INT32 Value - ); - -STATIC - VOID - EncodeP ( - UINT32 Value - ); - -STATIC - VOID - SendBlock ( - VOID - ); - -STATIC - VOID - Output ( - UINT32 c, - UINT32 p - ); - -STATIC - VOID - HufEncodeStart ( - VOID - ); - -STATIC - VOID - HufEncodeEnd ( - VOID - ); - -STATIC - VOID - MakeCrcTable ( - VOID - ); - -STATIC - VOID - PutBits ( - INT32 Number, - UINT32 Value - ); - -STATIC - INT32 - FreadCrc ( - UINT8 *Pointer, - INT32 Number - ); - -STATIC - VOID - InitPutBits ( - VOID - ); - -STATIC - VOID - CountLen ( - INT32 Index - ); - -STATIC - VOID - MakeLen ( - INT32 Root - ); - -STATIC - VOID - DownHeap ( - INT32 Index - ); - -STATIC - VOID - MakeCode ( - INT32 Number, - UINT8 Len[ ], - UINT16 Code[] +VOID +PutDword( + UINT32 Data ); STATIC - INT32 - MakeTree ( - INT32 NParm, - UINT16 FreqParm[], - UINT8 LenParm[ ], - UINT16 CodeParm[] +INT32 +AllocateMemory( + VOID +); + +STATIC +VOID +FreeMemory( + VOID +); + +STATIC +VOID +InitSlide( + VOID +); + +STATIC +NODE +Child( + NODE NodeQ, + UINT8 CharC +); + +STATIC +VOID +MakeChild( + NODE NodeQ, + UINT8 CharC, + NODE NodeR +); + +STATIC +VOID +Split( + NODE Old +); + +STATIC +VOID +InsertNode( + VOID +); + +STATIC +VOID +DeleteNode( + VOID +); + +STATIC +VOID +GetNextMatch( + VOID +); + +STATIC +INT32 +Encode( + VOID +); + +STATIC +VOID +CountTFreq( + VOID +); + +STATIC +VOID +WritePTLen( + INT32 Number, + INT32 nbit, + INT32 Special +); + +STATIC +VOID +WriteCLen( + VOID +); + +STATIC +VOID +EncodeC( + INT32 Value +); + +STATIC +VOID +EncodeP( + UINT32 Value +); + +STATIC +VOID +SendBlock( + VOID +); + +STATIC +VOID +Output( + UINT32 c, + UINT32 p +); + +STATIC +VOID +HufEncodeStart( + VOID +); + +STATIC +VOID +HufEncodeEnd( + VOID +); + +STATIC +VOID +MakeCrcTable( + VOID +); + +STATIC +VOID +PutBits( + INT32 Number, + UINT32 Value +); + +STATIC +INT32 +FreadCrc( + UINT8 *Pointer, + INT32 Number +); + +STATIC +VOID +InitPutBits( + VOID +); + +STATIC +VOID +CountLen( + INT32 Index +); + +STATIC +VOID +MakeLen( + INT32 Root +); + +STATIC +VOID +DownHeap( + INT32 Index +); + +STATIC +VOID +MakeCode( + INT32 Number, + UINT8 Len[], + UINT16 Code[] +); + +STATIC +INT32 +MakeTree( + INT32 NParm, + UINT16 FreqParm[], + UINT8 LenParm[], + UINT16 CodeParm[] ); // @@ -269,7 +269,7 @@ STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; STATIC UINT32 mCompSize, mOrigSize; STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], - mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; +mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; STATIC UINT8 mPbit; @@ -280,10 +280,10 @@ STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NU // EFI_STATUS EfiCompressLegacy( -CONST VOID *SrcBuffer, -UINT32 SrcSize, -VOID *DstBuffer, -UINT32 *DstSize + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize ) /*++ @@ -309,1550 +309,1573 @@ EFI_INVALID_PARAMETER - Parameter supplied is wrong. --*/ { - INT32 Status; + INT32 Status; - // - // Initializations - // - mPbit = 4; + // + // Initializations + // + mPbit = 4; - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; - mSrc = (UINT8*) SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst + *DstSize; + mSrc = (UINT8*)SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; - PutDword(0L); - PutDword(0L); + PutDword(0L); + PutDword(0L); - MakeCrcTable(); + MakeCrcTable(); - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; - // - // Compress it - // - Status = Encode(); - if (Status) { - return EFI_OUT_OF_RESOURCES; - } - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } - // - // Fill compressed size and original size - // - mDst = DstBuffer; - PutDword(mCompSize + 1); - PutDword(mOrigSize); + // + // Compress it + // + Status = Encode(); + if (Status) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize + 1); + PutDword(mOrigSize); - // - // Return - // - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } - else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + // + // Return + // + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } + else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } EFI_STATUS -TianoCompressLegacy ( -CONST VOID *SrcBuffer, -UINT32 SrcSize, -VOID *DstBuffer, -UINT32 *DstSize +TianoCompressLegacy( + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize ) - /*++ +/*++ - Routine Description: +Routine Description: - The internal implementation of [Efi/Tiano]Compress(). +The internal implementation of [Efi/Tiano]Compress(). - Arguments: +Arguments: - SrcBuffer - The buffer storing the source data - SrcSize - The size of source data - DstBuffer - The buffer to store the compressed data - DstSize - On input, the size of DstBuffer; On output, - the size of the actual compressed data. - Version - The version of de/compression algorithm. - Version 1 for UEFI 2.0 de/compression algorithm. - Version 2 for Tiano de/compression algorithm. +SrcBuffer - The buffer storing the source data +SrcSize - The size of source data +DstBuffer - The buffer to store the compressed data +DstSize - On input, the size of DstBuffer; On output, +the size of the actual compressed data. +Version - The version of de/compression algorithm. +Version 1 for UEFI 2.0 de/compression algorithm. +Version 2 for Tiano de/compression algorithm. - Returns: +Returns: - EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, - DstSize contains the size needed. - EFI_SUCCESS - Compression is successful. - EFI_OUT_OF_RESOURCES - No resource to complete function. - EFI_INVALID_PARAMETER - Parameter supplied is wrong. +EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, +DstSize contains the size needed. +EFI_SUCCESS - Compression is successful. +EFI_OUT_OF_RESOURCES - No resource to complete function. +EFI_INVALID_PARAMETER - Parameter supplied is wrong. - --*/ +--*/ { - INT32 Status; + INT32 Status; - // - // Initializations - // - mPbit = 5; + // + // Initializations + // + mPbit = 5; - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; - mSrc = (UINT8*) SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst +*DstSize; + mSrc = (UINT8*)SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; - PutDword (0L); - PutDword (0L); + PutDword(0L); + PutDword(0L); - MakeCrcTable (); + MakeCrcTable(); - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; - // - // Compress it - // - Status = Encode (); - if (Status) { - return EFI_OUT_OF_RESOURCES; - } - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } - // - // Fill compressed size and original size - // - mDst = DstBuffer; - PutDword (mCompSize + 1); - PutDword (mOrigSize); + // + // Compress it + // + Status = Encode(); + if (Status) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize + 1); + PutDword(mOrigSize); - // - // Return - // - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + // + // Return + // + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } + else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } STATIC - VOID - PutDword ( - UINT32 Data - ) - /*++ +VOID +PutDword( + UINT32 Data +) +/*++ - Routine Description: +Routine Description: - Put a DWORD to output stream +Put a DWORD to output stream - Arguments: +Arguments: - Data - the DWORD to put +Data - the DWORD to put - Returns: (VOID) +Returns: (VOID) - --*/ +--*/ { - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); + } } STATIC - INT32 - AllocateMemory ( - VOID - ) - /*++ +INT32 +AllocateMemory( + VOID +) +/*++ - Routine Description: +Routine Description: - Allocate memory spaces for data structures used compression process +Allocate memory spaces for data structures used compression process - Arguments: - VOID +Arguments: +VOID - Returns: +Returns: - EFI_SUCCESS - Memory is allocated successfully - EFI_OUT_OF_RESOURCES - Allocation fails +EFI_SUCCESS - Memory is allocated successfully +EFI_OUT_OF_RESOURCES - Allocation fails - --*/ +--*/ { - UINT32 Index; + UINT32 Index; - mText = malloc (WNDSIZ * 2 + MAXMATCH); - for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { - mText[Index] = 0; - } + mText = malloc(WNDSIZ * 2 + MAXMATCH); + if (NULL == mText) + return EFI_OUT_OF_RESOURCES; - mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); - mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); - mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); - mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); - mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); - mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); + for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { + mText[Index] = 0; + } - mBufSiz = BLKSIZ; - mBuf = malloc (mBufSiz); - while (mBuf == NULL) { - mBufSiz = (mBufSiz / 10U) * 9U; - if (mBufSiz < 4 * 1024U) { - return EFI_OUT_OF_RESOURCES; - } + mLevel = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); + mChildCount = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); + mPosition = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); + mParent = malloc(WNDSIZ * 2 * sizeof(*mParent)); + mPrev = malloc(WNDSIZ * 2 * sizeof(*mPrev)); + mNext = malloc((MAX_HASH_VAL + 1) * sizeof(*mNext)); - mBuf = malloc (mBufSiz); - } + mBufSiz = BLKSIZ; + mBuf = malloc(mBufSiz); + while (mBuf == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } - mBuf[0] = 0; + mBuf = malloc(mBufSiz); + } - return EFI_SUCCESS; + mBuf[0] = 0; + + return EFI_SUCCESS; } VOID - FreeMemory ( - VOID - ) - /*++ - - Routine Description: - - Called when compression is completed to free memory previously allocated. - - Arguments: (VOID) - - Returns: (VOID) - - --*/ -{ - if (mText != NULL) { - free (mText); - } - - if (mLevel != NULL) { - free (mLevel); - } - - if (mChildCount != NULL) { - free (mChildCount); - } - - if (mPosition != NULL) { - free (mPosition); - } - - if (mParent != NULL) { - free (mParent); - } - - if (mPrev != NULL) { - free (mPrev); - } - - if (mNext != NULL) { - free (mNext); - } - - if (mBuf != NULL) { - free (mBuf); - } - - return ; -} - -STATIC - VOID - InitSlide ( - VOID - ) - /*++ - - Routine Description: - - Initialize String Info Log data structures - - Arguments: (VOID) - - Returns: (VOID) - - --*/ -{ - NODE Index; - - for (Index = (NODE) WNDSIZ; Index <= (NODE) WNDSIZ + UINT8_MAX; Index++) { - mLevel[Index] = 1; - mPosition[Index] = NIL; // sentinel - } - - for (Index = (NODE) WNDSIZ; Index < (NODE) WNDSIZ * 2; Index++) { - mParent[Index] = NIL; - } - - mAvail = 1; - for (Index = 1; Index < (NODE) WNDSIZ - 1; Index++) { - mNext[Index] = (NODE) (Index + 1); - } - - mNext[WNDSIZ - 1] = NIL; - for (Index = (NODE) WNDSIZ * 2; Index <= (NODE) MAX_HASH_VAL; Index++) { - mNext[Index] = NIL; - } -} - -STATIC - NODE - Child ( - NODE NodeQ, - UINT8 CharC - ) - /*++ - - Routine Description: - - Find child node given the parent node and the edge character - - Arguments: - - NodeQ - the parent node - CharC - the edge character - - Returns: - - The child node (NIL if not found) - - --*/ -{ - NODE NodeR; - - NodeR = mNext[HASH (NodeQ, CharC)]; - // - // sentinel - // - mParent[NIL] = NodeQ; - while (mParent[NodeR] != NodeQ) { - NodeR = mNext[NodeR]; - } - - return NodeR; -} - -STATIC - VOID - MakeChild ( - NODE Parent, - UINT8 CharC, - NODE Child - ) - /*++ - - Routine Description: - - Create a new child for a given parent node. - - Arguments: - - Parent - the parent node - CharC - the edge character - Child - the child node - - Returns: (VOID) - - --*/ -{ - NODE Node1; - NODE Node2; - - Node1 = (NODE) HASH (Parent, CharC); - Node2 = mNext[Node1]; - mNext[Node1] = Child; - mNext[Child] = Node2; - mPrev[Node2] = Child; - mPrev[Child] = Node1; - mParent[Child] = Parent; - mChildCount[Parent]++; -} - -STATIC - VOID - Split ( - NODE Old - ) - /*++ - - Routine Description: - - Split a node. - - Arguments: - - Old - the node to split - - Returns: (VOID) - - --*/ -{ - NODE New; - NODE TempNode; - - New = mAvail; - mAvail = mNext[New]; - mChildCount[New] = 0; - TempNode = mPrev[Old]; - mPrev[New] = TempNode; - mNext[TempNode] = New; - TempNode = mNext[Old]; - mNext[New] = TempNode; - mPrev[TempNode] = New; - mParent[New] = mParent[Old]; - mLevel[New] = (UINT8) mMatchLen; - mPosition[New] = mPos; - MakeChild (New, mText[mMatchPos + mMatchLen], Old); - MakeChild (New, mText[mPos + mMatchLen], mPos); -} - -STATIC - VOID - InsertNode ( - VOID - ) - /*++ - - Routine Description: - - Insert string info for current position into the String Info Log - - Arguments: (VOID) - - Returns: (VOID) - - --*/ -{ - NODE NodeQ; - NODE NodeR; - NODE Index2; - NODE NodeT; - UINT8 CharC; - UINT8 *t1; - UINT8 *t2; - - if (mMatchLen >= 4) { - // - // We have just got a long match, the target tree - // can be located by MatchPos + 1. Traverse the tree - // from bottom up to get to a proper starting point. - // The usage of PERC_FLAG ensures proper node deletion - // DeleteNode() later. - // - mMatchLen--; - NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); - NodeQ = mParent[NodeR]; - while (NodeQ == NIL) { - NodeR = mNext[NodeR]; - NodeQ = mParent[NodeR]; - } - - while (mLevel[NodeQ] >= mMatchLen) { - NodeR = NodeQ; - NodeQ = mParent[NodeQ]; - } - - NodeT = NodeQ; - while (mPosition[NodeT] < 0) { - mPosition[NodeT] = mPos; - NodeT = mParent[NodeT]; - } - - if (NodeT < (NODE) WNDSIZ) { - mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); - } - } else { - // - // Locate the target tree - // - NodeQ = (NODE) (mText[mPos] + WNDSIZ); - CharC = mText[mPos + 1]; - NodeR = Child (NodeQ, CharC); - if (NodeR == NIL) { - MakeChild (NodeQ, CharC, mPos); - mMatchLen = 1; - return ; - } - - mMatchLen = 2; - } - // - // Traverse down the tree to find a match. - // Update Position value along the route. - // Node split or creation is involved. - // - for (;;) { - if (NodeR >= (NODE) WNDSIZ) { - Index2 = MAXMATCH; - mMatchPos = NodeR; - } else { - Index2 = mLevel[NodeR]; - mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); - } - - if (mMatchPos >= mPos) { - mMatchPos -= WNDSIZ; - } - - t1 = &mText[mPos + mMatchLen]; - t2 = &mText[mMatchPos + mMatchLen]; - while (mMatchLen < Index2) { - if (*t1 != *t2) { - Split (NodeR); - return ; - } - - mMatchLen++; - t1++; - t2++; - } - - if (mMatchLen >= MAXMATCH) { - break; - } - - mPosition[NodeR] = mPos; - NodeQ = NodeR; - NodeR = Child (NodeQ, *t1); - if (NodeR == NIL) { - MakeChild (NodeQ, *t1, mPos); - return ; - } - - mMatchLen++; - } - - NodeT = mPrev[NodeR]; - mPrev[mPos] = NodeT; - mNext[NodeT] = mPos; - NodeT = mNext[NodeR]; - mNext[mPos] = NodeT; - mPrev[NodeT] = mPos; - mParent[mPos] = NodeQ; - mParent[NodeR] = NIL; - - // - // Special usage of 'next' - // - mNext[NodeR] = mPos; - -} - -STATIC - VOID - DeleteNode ( - VOID - ) - /*++ - - Routine Description: - - Delete outdated string info. (The Usage of PERC_FLAG - ensures a clean deletion) - - Arguments: (VOID) - - Returns: (VOID) - - --*/ -{ - NODE NodeQ; - NODE NodeR; - NODE NodeS; - NODE NodeT; - NODE NodeU; - - if (mParent[mPos] == NIL) { - return ; - } - - NodeR = mPrev[mPos]; - NodeS = mNext[mPos]; - mNext[NodeR] = NodeS; - mPrev[NodeS] = NodeR; - NodeR = mParent[mPos]; - mParent[mPos] = NIL; - if (NodeR >= (NODE) WNDSIZ) { - return ; - } - - mChildCount[NodeR]--; - if (mChildCount[NodeR] > 1) { - return ; - } - - NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); - if (NodeT >= mPos) { - NodeT -= WNDSIZ; - } - - NodeS = NodeT; - NodeQ = mParent[NodeR]; - NodeU = mPosition[NodeQ]; - while (NodeU & (UINT32) PERC_FLAG) { - NodeU &= (UINT32)~PERC_FLAG; - if (NodeU >= mPos) { - NodeU -= WNDSIZ; - } - - if (NodeU > NodeS) { - NodeS = NodeU; - } - - mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); - NodeQ = mParent[NodeQ]; - NodeU = mPosition[NodeQ]; - } - - if (NodeQ < (NODE) WNDSIZ) { - if (NodeU >= mPos) { - NodeU -= WNDSIZ; - } - - if (NodeU > NodeS) { - NodeS = NodeU; - } - - mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); - } - - NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); - NodeT = mPrev[NodeS]; - NodeU = mNext[NodeS]; - mNext[NodeT] = NodeU; - mPrev[NodeU] = NodeT; - NodeT = mPrev[NodeR]; - mNext[NodeT] = NodeS; - mPrev[NodeS] = NodeT; - NodeT = mNext[NodeR]; - mPrev[NodeT] = NodeS; - mNext[NodeS] = NodeT; - mParent[NodeS] = mParent[NodeR]; - mParent[NodeR] = NIL; - mNext[NodeR] = mAvail; - mAvail = NodeR; -} - -STATIC - VOID - GetNextMatch ( - VOID - ) - /*++ - - Routine Description: - - Advance the current position (read new data if needed). - Delete outdated string info. Find a match string for current position. - - Arguments: (VOID) - - Returns: (VOID) - - --*/ -{ - INT32 Number; - - mRemainder--; - mPos++; - if (mPos == WNDSIZ * 2) { - memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); - Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); - mRemainder += Number; - mPos = WNDSIZ; - } - - DeleteNode (); - InsertNode (); -} - -STATIC - INT32 - Encode ( - VOID - ) - /*++ - - Routine Description: - - The mac controlling routine for compression process. - - Arguments: (VOID) - - Returns: - - EFI_SUCCESS - The compression is successful - EFI_OUT_0F_RESOURCES - Not enough memory for compression process - - --*/ -{ - INT32 Status; - INT32 LastMatchLen; - NODE LastMatchPos; - - Status = AllocateMemory (); - if (Status) { - FreeMemory (); - return Status; - } - - InitSlide (); - - HufEncodeStart (); - - mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); - - mMatchLen = 0; - mPos = WNDSIZ; - InsertNode (); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - - while (mRemainder > 0) { - LastMatchLen = mMatchLen; - LastMatchPos = mMatchPos; - GetNextMatch (); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - - if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { - // - // Not enough benefits are gained by outputting a pointer, - // so just output the original character - // - Output (mText[mPos - 1], 0); - - } else { - - if (LastMatchLen == THRESHOLD) { - if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { - Output (mText[mPos - 1], 0); - continue; - } - } - // - // Outputting a pointer is beneficial enough, do it. - // - Output ( - LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), - (mPos - LastMatchPos - 2) & (WNDSIZ - 1) - ); - LastMatchLen--; - while (LastMatchLen > 0) { - GetNextMatch (); - LastMatchLen--; - } - - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - } - } - - HufEncodeEnd (); - FreeMemory (); - return EFI_SUCCESS; -} - -STATIC - VOID - CountTFreq ( - VOID - ) - /*++ - - Routine Description: - - Count the frequencies for the Extra Set - - Arguments: (VOID) - - Returns: (VOID) - - --*/ -{ - INT32 Index; - INT32 Index3; - INT32 Number; - INT32 Count; - - for (Index = 0; Index < NT; Index++) { - mTFreq[Index] = 0; - } - - Number = NC; - while (Number > 0 && mCLen[Number - 1] == 0) { - Number--; - } - - Index = 0; - while (Index < Number) { - Index3 = mCLen[Index++]; - if (Index3 == 0) { - Count = 1; - while (Index < Number && mCLen[Index] == 0) { - Index++; - Count++; - } - - if (Count <= 2) { - mTFreq[0] = (UINT16) (mTFreq[0] + Count); - } else if (Count <= 18) { - mTFreq[1]++; - } else if (Count == 19) { - mTFreq[0]++; - mTFreq[1]++; - } else { - mTFreq[2]++; - } - } else { - mTFreq[Index3 + 2]++; - } - } -} - -STATIC - VOID - WritePTLen ( - INT32 Number, - INT32 nbit, - INT32 Special - ) - /*++ - - Routine Description: - - Outputs the code length array for the Extra Set or the Position Set. - - Arguments: - - Number - the number of symbols - nbit - the number of bits needed to represent 'n' - Special - the special symbol that needs to be take care of - - Returns: (VOID) - - --*/ -{ - INT32 Index; - INT32 Index3; - - while (Number > 0 && mPTLen[Number - 1] == 0) { - Number--; - } - - PutBits (nbit, Number); - Index = 0; - while (Index < Number) { - Index3 = mPTLen[Index++]; - if (Index3 <= 6) { - PutBits (3, Index3); - } else { - PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); - } - - if (Index == Special) { - while (Index < 6 && mPTLen[Index] == 0) { - Index++; - } - - PutBits (2, (Index - 3) & 3); - } - } -} - -STATIC - VOID - WriteCLen ( - VOID - ) - /*++ - - Routine Description: - - Outputs the code length array for Char&Length Set - - Arguments: (VOID) - - Returns: (VOID) - - --*/ -{ - INT32 Index; - INT32 Index3; - INT32 Number; - INT32 Count; - - Number = NC; - while (Number > 0 && mCLen[Number - 1] == 0) { - Number--; - } - - PutBits (CBIT, Number); - Index = 0; - while (Index < Number) { - Index3 = mCLen[Index++]; - if (Index3 == 0) { - Count = 1; - while (Index < Number && mCLen[Index] == 0) { - Index++; - Count++; - } - - if (Count <= 2) { - for (Index3 = 0; Index3 < Count; Index3++) { - PutBits (mPTLen[0], mPTCode[0]); - } - } else if (Count <= 18) { - PutBits (mPTLen[1], mPTCode[1]); - PutBits (4, Count - 3); - } else if (Count == 19) { - PutBits (mPTLen[0], mPTCode[0]); - PutBits (mPTLen[1], mPTCode[1]); - PutBits (4, 15); - } else { - PutBits (mPTLen[2], mPTCode[2]); - PutBits (CBIT, Count - 20); - } - } else { - PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); - } - } -} - -STATIC - VOID - EncodeC ( - INT32 Value - ) -{ - PutBits (mCLen[Value], mCCode[Value]); -} - -STATIC - VOID - EncodeP ( - UINT32 Value - ) -{ - UINT32 Index; - UINT32 NodeQ; - - Index = 0; - NodeQ = Value; - while (NodeQ) { - NodeQ >>= 1; - Index++; - } - - PutBits (mPTLen[Index], mPTCode[Index]); - if (Index > 1) { - PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); - } -} - -STATIC - VOID - SendBlock ( - VOID - ) - /*++ - - Routine Description: - - Huffman code the block and output it. - - Arguments: - (VOID) - - Returns: - (VOID) - - --*/ -{ - UINT32 Index; - UINT32 Index2; - UINT32 Index3; - UINT32 Flags; - UINT32 Root; - UINT32 Pos; - UINT32 Size; - Flags = 0; - - Root = MakeTree (NC, mCFreq, mCLen, mCCode); - Size = mCFreq[Root]; - PutBits (16, Size); - if (Root >= NC) { - CountTFreq (); - Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); - if (Root >= NT) { - WritePTLen (NT, TBIT, 3); - } else { - PutBits (TBIT, 0); - PutBits (TBIT, Root); - } - - WriteCLen (); - } else { - PutBits (TBIT, 0); - PutBits (TBIT, 0); - PutBits (CBIT, 0); - PutBits (CBIT, Root); - } - - Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); - if (Root >= NP) { - WritePTLen (NP, mPbit, -1); - } else { - PutBits (mPbit, 0); - PutBits (mPbit, Root); - } - - Pos = 0; - for (Index = 0; Index < Size; Index++) { - if (Index % UINT8_BIT == 0) { - Flags = mBuf[Pos++]; - } else { - Flags <<= 1; - } - - if (Flags & (1U << (UINT8_BIT - 1))) { - EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); - Index3 = mBuf[Pos++]; - for (Index2 = 0; Index2 < 3; Index2++) { - Index3 <<= UINT8_BIT; - Index3 += mBuf[Pos++]; - } - - EncodeP (Index3); - } else { - EncodeC (mBuf[Pos++]); - } - } - - for (Index = 0; Index < NC; Index++) { - mCFreq[Index] = 0; - } - - for (Index = 0; Index < NP; Index++) { - mPFreq[Index] = 0; - } -} - -STATIC - VOID - Output ( - UINT32 CharC, - UINT32 Pos - ) - /*++ - - Routine Description: - - Outputs an Original Character or a Pointer - - Arguments: - - CharC - The original character or the 'String Length' element of a Pointer - Pos - The 'Position' field of a Pointer - - Returns: (VOID) - - --*/ -{ - STATIC UINT32 CPos; - - if ((mOutputMask >>= 1) == 0) { - mOutputMask = 1U << (UINT8_BIT - 1); - // - // Check the buffer overflow per outputting UINT8_BIT symbols - // which is an Original Character or a Pointer. The biggest - // symbol is a Pointer which occupies 5 bytes. - // - if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { - SendBlock (); - mOutputPos = 0; - } - - CPos = mOutputPos++; - mBuf[CPos] = 0; - } - - mBuf[mOutputPos++] = (UINT8) CharC; - mCFreq[CharC]++; - if (CharC >= (1U << UINT8_BIT)) { - mBuf[CPos] |= mOutputMask; - mBuf[mOutputPos++] = (UINT8) (Pos >> 24); - mBuf[mOutputPos++] = (UINT8) (Pos >> 16); - mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); - mBuf[mOutputPos++] = (UINT8) Pos; - CharC = 0; - while (Pos) { - Pos >>= 1; - CharC++; - } - - mPFreq[CharC]++; - } -} - -STATIC - VOID - HufEncodeStart ( - VOID - ) -{ - INT32 Index; - - for (Index = 0; Index < NC; Index++) { - mCFreq[Index] = 0; - } - - for (Index = 0; Index < NP; Index++) { - mPFreq[Index] = 0; - } - - mOutputPos = mOutputMask = 0; - InitPutBits (); - return ; -} - -STATIC - VOID - HufEncodeEnd ( - VOID - ) -{ - SendBlock (); - - // - // Flush remaining bits - // - PutBits (UINT8_BIT - 1, 0); - - return ; -} - -STATIC - VOID - MakeCrcTable ( - VOID - ) -{ - UINT32 Index; - UINT32 Index2; - UINT32 Temp; - - for (Index = 0; Index <= UINT8_MAX; Index++) { - Temp = Index; - for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { - if (Temp & 1) { - Temp = (Temp >> 1) ^ CRCPOLY; - } else { - Temp >>= 1; - } - } - - mCrcTable[Index] = (UINT16) Temp; - } -} - -STATIC - VOID - PutBits ( - INT32 Number, - UINT32 Value - ) - /*++ - - Routine Description: - - Outputs rightmost n bits of x - - Arguments: - - Number - the rightmost n bits of the data is used - x - the data - - Returns: (VOID) - - --*/ -{ - UINT8 Temp; - - while (Number >= mBitCount) { - // - // Number -= mBitCount should never equal to 32 - // - Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); - if (mDst < mDstUpperLimit) { - *mDst++ = Temp; - } - - mCompSize++; - mSubBitBuf = 0; - mBitCount = UINT8_BIT; - } - - mSubBitBuf |= Value << (mBitCount -= Number); -} - -STATIC - INT32 - FreadCrc ( - UINT8 *Pointer, - INT32 Number - ) - /*++ - - Routine Description: - - Read source data - - Arguments: - - Pointer - the buffer to hold the data - Number - number of bytes to read - - Returns: - - number of bytes actually read - - --*/ -{ - INT32 Index; - - for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { - *Pointer++ = *mSrc++; - } - - Number = Index; - - Pointer -= Number; - mOrigSize += Number; - Index--; - while (Index >= 0) { - UPDATE_CRC (*Pointer++); - Index--; - } - - return Number; -} - -STATIC - VOID - InitPutBits ( - VOID - ) -{ - mBitCount = UINT8_BIT; - mSubBitBuf = 0; -} - -STATIC - VOID - CountLen ( - INT32 Index - ) - /*++ - - Routine Description: - - Count the number of each code length for a Huffman tree. - - Arguments: - - Index - the top node - - Returns: (VOID) - - --*/ -{ - STATIC INT32 Depth = 0; - - if (Index < mN) { - mLenCnt[(Depth < 16) ? Depth : 16]++; - } else { - Depth++; - CountLen (mLeft[Index]); - CountLen (mRight[Index]); - Depth--; - } -} - -STATIC - VOID - MakeLen ( - INT32 Root - ) - /*++ - - Routine Description: - - Create code length array for a Huffman tree - - Arguments: - - Root - the root of the tree - - Returns: - - VOID - - --*/ -{ - INT32 Index; - INT32 Index3; - UINT32 Cum; - - for (Index = 0; Index <= 16; Index++) { - mLenCnt[Index] = 0; - } - - CountLen (Root); - - // - // Adjust the length count array so that - // no code will be generated longer than its designated length - // - Cum = 0; - for (Index = 16; Index > 0; Index--) { - Cum += mLenCnt[Index] << (16 - Index); - } - - while (Cum != (1U << 16)) { - mLenCnt[16]--; - for (Index = 15; Index > 0; Index--) { - if (mLenCnt[Index] != 0) { - mLenCnt[Index]--; - mLenCnt[Index + 1] += 2; - break; - } - } - - Cum--; - } - - for (Index = 16; Index > 0; Index--) { - Index3 = mLenCnt[Index]; - Index3--; - while (Index3 >= 0) { - mLen[*mSortPtr++] = (UINT8) Index; - Index3--; - } - } -} - -STATIC - VOID - DownHeap ( - INT32 Index - ) -{ - INT32 Index2; - INT32 Index3; - - // - // priority queue: send Index-th entry down heap - // - Index3 = mHeap[Index]; - Index2 = 2 * Index; - while (Index2 <= mHeapSize) { - if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { - Index2++; - } - - if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { - break; - } - - mHeap[Index] = mHeap[Index2]; - Index = Index2; - Index2 = 2 * Index; - } - - mHeap[Index] = (INT16) Index3; -} - -STATIC - VOID - MakeCode ( - INT32 Number, - UINT8 Len[ ], - UINT16 Code[] +FreeMemory( + VOID ) - /*++ +/*++ - Routine Description: +Routine Description: - Assign code to each symbol based on the code length array +Called when compression is completed to free memory previously allocated. - Arguments: +Arguments: (VOID) - Number - number of symbols - Len - the code length array - Code - stores codes for each symbol +Returns: (VOID) - Returns: (VOID) - - --*/ +--*/ { - INT32 Index; - UINT16 Start[18]; + if (mText != NULL) { + free(mText); + } - Start[1] = 0; - for (Index = 1; Index <= 16; Index++) { - Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); - } + if (mLevel != NULL) { + free(mLevel); + } - for (Index = 0; Index < Number; Index++) { - Code[Index] = Start[Len[Index]]++; - } + if (mChildCount != NULL) { + free(mChildCount); + } + + if (mPosition != NULL) { + free(mPosition); + } + + if (mParent != NULL) { + free(mParent); + } + + if (mPrev != NULL) { + free(mPrev); + } + + if (mNext != NULL) { + free(mNext); + } + + if (mBuf != NULL) { + free(mBuf); + } + + return; } STATIC - INT32 - MakeTree ( - INT32 NParm, - UINT16 FreqParm[], - UINT8 LenParm[ ], - UINT16 CodeParm[] +VOID +InitSlide( + VOID ) - /*++ +/*++ - Routine Description: +Routine Description: - Generates Huffman codes given a frequency distribution of symbols +Initialize String Info Log data structures - Arguments: +Arguments: (VOID) - NParm - number of symbols - FreqParm - frequency of each symbol - LenParm - code length for each symbol - CodeParm - code for each symbol +Returns: (VOID) - Returns: - - Root of the Huffman tree. - - --*/ +--*/ { - INT32 Index; - INT32 Index2; - INT32 Index3; - INT32 Avail; + NODE Index; - // - // make tree, calculate len[], return root - // - mN = NParm; - mFreq = FreqParm; - mLen = LenParm; - Avail = mN; - mHeapSize = 0; - mHeap[1] = 0; - for (Index = 0; Index < mN; Index++) { - mLen[Index] = 0; - if (mFreq[Index]) { - mHeapSize++; - mHeap[mHeapSize] = (INT16) Index; - } - } + for (Index = (NODE)WNDSIZ; Index <= (NODE)WNDSIZ + UINT8_MAX; Index++) { + mLevel[Index] = 1; + mPosition[Index] = NIL; // sentinel + } - if (mHeapSize < 2) { - CodeParm[mHeap[1]] = 0; - return mHeap[1]; - } + for (Index = (NODE)WNDSIZ; Index < (NODE)WNDSIZ * 2; Index++) { + mParent[Index] = NIL; + } - for (Index = mHeapSize / 2; Index >= 1; Index--) { - // - // make priority queue - // - DownHeap (Index); - } + mAvail = 1; + for (Index = 1; Index < (NODE)WNDSIZ - 1; Index++) { + mNext[Index] = (NODE)(Index + 1); + } - mSortPtr = CodeParm; - do { - Index = mHeap[1]; - if (Index < mN) { - *mSortPtr++ = (UINT16) Index; - } - - mHeap[1] = mHeap[mHeapSize--]; - DownHeap (1); - Index2 = mHeap[1]; - if (Index2 < mN) { - *mSortPtr++ = (UINT16) Index2; - } - - Index3 = Avail++; - mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); - mHeap[1] = (INT16) Index3; - DownHeap (1); - mLeft[Index3] = (UINT16) Index; - mRight[Index3] = (UINT16) Index2; - } while (mHeapSize > 1); - - mSortPtr = CodeParm; - MakeLen (Index3); - MakeCode (NParm, LenParm, CodeParm); - - // - // return root - // - return Index3; + mNext[WNDSIZ - 1] = NIL; + for (Index = (NODE)WNDSIZ * 2; Index <= (NODE)MAX_HASH_VAL; Index++) { + mNext[Index] = NIL; + } +} + +STATIC +NODE +Child( + NODE NodeQ, + UINT8 CharC +) +/*++ + +Routine Description: + +Find child node given the parent node and the edge character + +Arguments: + +NodeQ - the parent node +CharC - the edge character + +Returns: + +The child node (NIL if not found) + +--*/ +{ + NODE NodeR; + + NodeR = mNext[HASH(NodeQ, CharC)]; + // + // sentinel + // + mParent[NIL] = NodeQ; + while (mParent[NodeR] != NodeQ) { + NodeR = mNext[NodeR]; + } + + return NodeR; +} + +STATIC +VOID +MakeChild( + NODE Parent, + UINT8 CharC, + NODE Child +) +/*++ + +Routine Description: + +Create a new child for a given parent node. + +Arguments: + +Parent - the parent node +CharC - the edge character +Child - the child node + +Returns: (VOID) + +--*/ +{ + NODE Node1; + NODE Node2; + + Node1 = (NODE)HASH(Parent, CharC); + Node2 = mNext[Node1]; + mNext[Node1] = Child; + mNext[Child] = Node2; + mPrev[Node2] = Child; + mPrev[Child] = Node1; + mParent[Child] = Parent; + mChildCount[Parent]++; +} + +STATIC +VOID +Split( + NODE Old +) +/*++ + +Routine Description: + +Split a node. + +Arguments: + +Old - the node to split + +Returns: (VOID) + +--*/ +{ + NODE New; + NODE TempNode; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + TempNode = mPrev[Old]; + mPrev[New] = TempNode; + mNext[TempNode] = New; + TempNode = mNext[Old]; + mNext[New] = TempNode; + mPrev[TempNode] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8)mMatchLen; + mPosition[New] = mPos; + MakeChild(New, mText[mMatchPos + mMatchLen], Old); + MakeChild(New, mText[mPos + mMatchLen], mPos); +} + +STATIC +VOID +InsertNode( + VOID +) +/*++ + +Routine Description: + +Insert string info for current position into the String Info Log + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE Index2; + NODE NodeT; + UINT8 CharC; + UINT8 *t1; + UINT8 *t2; + + if (mMatchLen >= 4) { + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Traverse the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // DeleteNode() later. + // + mMatchLen--; + NodeR = (NODE)((mMatchPos + 1) | WNDSIZ); + NodeQ = mParent[NodeR]; + while (NodeQ == NIL) { + NodeR = mNext[NodeR]; + NodeQ = mParent[NodeR]; + } + + while (mLevel[NodeQ] >= mMatchLen) { + NodeR = NodeQ; + NodeQ = mParent[NodeQ]; + } + + NodeT = NodeQ; + while (mPosition[NodeT] < 0) { + mPosition[NodeT] = mPos; + NodeT = mParent[NodeT]; + } + + if (NodeT < (NODE)WNDSIZ) { + mPosition[NodeT] = (NODE)(mPos | (UINT32)PERC_FLAG); + } + } + else { + // + // Locate the target tree + // + NodeQ = (NODE)(mText[mPos] + WNDSIZ); + CharC = mText[mPos + 1]; + NodeR = Child(NodeQ, CharC); + if (NodeR == NIL) { + MakeChild(NodeQ, CharC, mPos); + mMatchLen = 1; + return; + } + + mMatchLen = 2; + } + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + for (;;) { + if (NodeR >= (NODE)WNDSIZ) { + Index2 = MAXMATCH; + mMatchPos = NodeR; + } + else { + Index2 = mLevel[NodeR]; + mMatchPos = (NODE)(mPosition[NodeR] & (UINT32)~PERC_FLAG); + } + + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < Index2) { + if (*t1 != *t2) { + Split(NodeR); + return; + } + + mMatchLen++; + t1++; + t2++; + } + + if (mMatchLen >= MAXMATCH) { + break; + } + + mPosition[NodeR] = mPos; + NodeQ = NodeR; + NodeR = Child(NodeQ, *t1); + if (NodeR == NIL) { + MakeChild(NodeQ, *t1, mPos); + return; + } + + mMatchLen++; + } + + NodeT = mPrev[NodeR]; + mPrev[mPos] = NodeT; + mNext[NodeT] = mPos; + NodeT = mNext[NodeR]; + mNext[mPos] = NodeT; + mPrev[NodeT] = mPos; + mParent[mPos] = NodeQ; + mParent[NodeR] = NIL; + + // + // Special usage of 'next' + // + mNext[NodeR] = mPos; + +} + +STATIC +VOID +DeleteNode( + VOID +) +/*++ + +Routine Description: + +Delete outdated string info. (The Usage of PERC_FLAG +ensures a clean deletion) + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE NodeS; + NODE NodeT; + NODE NodeU; + + if (mParent[mPos] == NIL) { + return; + } + + NodeR = mPrev[mPos]; + NodeS = mNext[mPos]; + mNext[NodeR] = NodeS; + mPrev[NodeS] = NodeR; + NodeR = mParent[mPos]; + mParent[mPos] = NIL; + if (NodeR >= (NODE)WNDSIZ) { + return; + } + + mChildCount[NodeR]--; + if (mChildCount[NodeR] > 1) { + return; + } + + NodeT = (NODE)(mPosition[NodeR] & (UINT32)~PERC_FLAG); + if (NodeT >= mPos) { + NodeT -= WNDSIZ; + } + + NodeS = NodeT; + NodeQ = mParent[NodeR]; + NodeU = mPosition[NodeQ]; + while (NodeU & (UINT32)PERC_FLAG) { + NodeU &= (UINT32)~PERC_FLAG; + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE)(NodeS | WNDSIZ); + NodeQ = mParent[NodeQ]; + NodeU = mPosition[NodeQ]; + } + + if (NodeQ < (NODE)WNDSIZ) { + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE)(NodeS | WNDSIZ | (UINT32)PERC_FLAG); + } + + NodeS = Child(NodeR, mText[NodeT + mLevel[NodeR]]); + NodeT = mPrev[NodeS]; + NodeU = mNext[NodeS]; + mNext[NodeT] = NodeU; + mPrev[NodeU] = NodeT; + NodeT = mPrev[NodeR]; + mNext[NodeT] = NodeS; + mPrev[NodeS] = NodeT; + NodeT = mNext[NodeR]; + mPrev[NodeT] = NodeS; + mNext[NodeS] = NodeT; + mParent[NodeS] = mParent[NodeR]; + mParent[NodeR] = NIL; + mNext[NodeR] = mAvail; + mAvail = NodeR; +} + +STATIC +VOID +GetNextMatch( + VOID +) +/*++ + +Routine Description: + +Advance the current position (read new data if needed). +Delete outdated string info. Find a match string for current position. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Number; + + mRemainder--; + mPos++; + if (mPos == WNDSIZ * 2) { + memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + Number = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += Number; + mPos = WNDSIZ; + } + + DeleteNode(); + InsertNode(); +} + +STATIC +INT32 +Encode( + VOID +) +/*++ + +Routine Description: + +The mac controlling routine for compression process. + +Arguments: (VOID) + +Returns: + +EFI_SUCCESS - The compression is successful +EFI_OUT_0F_RESOURCES - Not enough memory for compression process + +--*/ +{ + INT32 Status; + INT32 LastMatchLen; + NODE LastMatchPos; + + Status = AllocateMemory(); + if (Status) { + FreeMemory(); + return Status; + } + + InitSlide(); + + HufEncodeStart(); + + mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + Output(mText[mPos - 1], 0); + + } + else { + + if (LastMatchLen == THRESHOLD) { + if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { + Output(mText[mPos - 1], 0); + continue; + } + } + // + // Outputting a pointer is beneficial enough, do it. + // + Output( + LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1) + ); + LastMatchLen--; + while (LastMatchLen > 0) { + GetNextMatch(); + LastMatchLen--; + } + + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd(); + FreeMemory(); + return EFI_SUCCESS; +} + +STATIC +VOID +CountTFreq( + VOID +) +/*++ + +Routine Description: + +Count the frequencies for the Extra Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + for (Index = 0; Index < NT; Index++) { + mTFreq[Index] = 0; + } + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + mTFreq[0] = (UINT16)(mTFreq[0] + Count); + } + else if (Count <= 18) { + mTFreq[1]++; + } + else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } + else { + mTFreq[2]++; + } + } + else { + mTFreq[Index3 + 2]++; + } + } +} + +STATIC +VOID +WritePTLen( + INT32 Number, + INT32 nbit, + INT32 Special +) +/*++ + +Routine Description: + +Outputs the code length array for the Extra Set or the Position Set. + +Arguments: + +Number - the number of symbols +nbit - the number of bits needed to represent 'n' +Special - the special symbol that needs to be take care of + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + + while (Number > 0 && mPTLen[Number - 1] == 0) { + Number--; + } + + PutBits(nbit, Number); + Index = 0; + while (Index < Number) { + Index3 = mPTLen[Index++]; + if (Index3 <= 6) { + PutBits(3, Index3); + } + else { + PutBits(Index3 - 3, (1U << (Index3 - 3)) - 2); + } + + if (Index == Special) { + while (Index < 6 && mPTLen[Index] == 0) { + Index++; + } + + PutBits(2, (Index - 3) & 3); + } + } +} + +STATIC +VOID +WriteCLen( + VOID +) +/*++ + +Routine Description: + +Outputs the code length array for Char&Length Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + PutBits(CBIT, Number); + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + for (Index3 = 0; Index3 < Count; Index3++) { + PutBits(mPTLen[0], mPTCode[0]); + } + } + else if (Count <= 18) { + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, Count - 3); + } + else if (Count == 19) { + PutBits(mPTLen[0], mPTCode[0]); + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, 15); + } + else { + PutBits(mPTLen[2], mPTCode[2]); + PutBits(CBIT, Count - 20); + } + } + else { + PutBits(mPTLen[Index3 + 2], mPTCode[Index3 + 2]); + } + } +} + +STATIC +VOID +EncodeC( + INT32 Value +) +{ + PutBits(mCLen[Value], mCCode[Value]); +} + +STATIC +VOID +EncodeP( + UINT32 Value +) +{ + UINT32 Index; + UINT32 NodeQ; + + Index = 0; + NodeQ = Value; + while (NodeQ) { + NodeQ >>= 1; + Index++; + } + + PutBits(mPTLen[Index], mPTCode[Index]); + if (Index > 1) { + PutBits(Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); + } +} + +STATIC +VOID +SendBlock( + VOID +) +/*++ + +Routine Description: + +Huffman code the block and output it. + +Arguments: +(VOID) + +Returns: +(VOID) + +--*/ +{ + UINT32 Index; + UINT32 Index2; + UINT32 Index3; + UINT32 Flags; + UINT32 Root; + UINT32 Pos; + UINT32 Size; + Flags = 0; + + Root = MakeTree(NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + PutBits(16, Size); + if (Root >= NC) { + CountTFreq(); + Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen(NT, TBIT, 3); + } + else { + PutBits(TBIT, 0); + PutBits(TBIT, Root); + } + + WriteCLen(); + } + else { + PutBits(TBIT, 0); + PutBits(TBIT, 0); + PutBits(CBIT, 0); + PutBits(CBIT, Root); + } + + Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen(NP, mPbit, -1); + } + else { + PutBits(mPbit, 0); + PutBits(mPbit, Root); + } + + Pos = 0; + for (Index = 0; Index < Size; Index++) { + if (Index % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } + else { + Flags <<= 1; + } + + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); + Index3 = mBuf[Pos++]; + for (Index2 = 0; Index2 < 3; Index2++) { + Index3 <<= UINT8_BIT; + Index3 += mBuf[Pos++]; + } + + EncodeP(Index3); + } + else { + EncodeC(mBuf[Pos++]); + } + } + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } +} + +STATIC +VOID +Output( + UINT32 CharC, + UINT32 Pos +) +/*++ + +Routine Description: + +Outputs an Original Character or a Pointer + +Arguments: + +CharC - The original character or the 'String Length' element of a Pointer +Pos - The 'Position' field of a Pointer + +Returns: (VOID) + +--*/ +{ + STATIC UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + // + // Check the buffer overflow per outputting UINT8_BIT symbols + // which is an Original Character or a Pointer. The biggest + // symbol is a Pointer which occupies 5 bytes. + // + if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { + SendBlock(); + mOutputPos = 0; + } + + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + + mBuf[mOutputPos++] = (UINT8)CharC; + mCFreq[CharC]++; + if (CharC >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8)(Pos >> 24); + mBuf[mOutputPos++] = (UINT8)(Pos >> 16); + mBuf[mOutputPos++] = (UINT8)(Pos >> (UINT8_BIT)); + mBuf[mOutputPos++] = (UINT8)Pos; + CharC = 0; + while (Pos) { + Pos >>= 1; + CharC++; + } + + mPFreq[CharC]++; + } +} + +STATIC +VOID +HufEncodeStart( + VOID +) +{ + INT32 Index; + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } + + mOutputPos = mOutputMask = 0; + InitPutBits(); + return; +} + +STATIC +VOID +HufEncodeEnd( + VOID +) +{ + SendBlock(); + + // + // Flush remaining bits + // + PutBits(UINT8_BIT - 1, 0); + + return; +} + +STATIC +VOID +MakeCrcTable( + VOID +) +{ + UINT32 Index; + UINT32 Index2; + UINT32 Temp; + + for (Index = 0; Index <= UINT8_MAX; Index++) { + Temp = Index; + for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { + if (Temp & 1) { + Temp = (Temp >> 1) ^ CRCPOLY; + } + else { + Temp >>= 1; + } + } + + mCrcTable[Index] = (UINT16)Temp; + } +} + +STATIC +VOID +PutBits( + INT32 Number, + UINT32 Value +) +/*++ + +Routine Description: + +Outputs rightmost n bits of x + +Arguments: + +Number - the rightmost n bits of the data is used +x - the data + +Returns: (VOID) + +--*/ +{ + UINT8 Temp; + + while (Number >= mBitCount) { + // + // Number -= mBitCount should never equal to 32 + // + Temp = (UINT8)(mSubBitBuf | (Value >> (Number -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + + mCompSize++; + mSubBitBuf = 0; + mBitCount = UINT8_BIT; + } + + mSubBitBuf |= Value << (mBitCount -= Number); +} + +STATIC +INT32 +FreadCrc( + UINT8 *Pointer, + INT32 Number +) +/*++ + +Routine Description: + +Read source data + +Arguments: + +Pointer - the buffer to hold the data +Number - number of bytes to read + +Returns: + +number of bytes actually read + +--*/ +{ + INT32 Index; + + for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { + *Pointer++ = *mSrc++; + } + + Number = Index; + + Pointer -= Number; + mOrigSize += Number; + Index--; + while (Index >= 0) { + UPDATE_CRC(*Pointer++); + Index--; + } + + return Number; +} + +STATIC +VOID +InitPutBits( + VOID +) +{ + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +STATIC +VOID +CountLen( + INT32 Index +) +/*++ + +Routine Description: + +Count the number of each code length for a Huffman tree. + +Arguments: + +Index - the top node + +Returns: (VOID) + +--*/ +{ + STATIC INT32 Depth = 0; + + if (Index < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } + else { + Depth++; + CountLen(mLeft[Index]); + CountLen(mRight[Index]); + Depth--; + } +} + +STATIC +VOID +MakeLen( + INT32 Root +) +/*++ + +Routine Description: + +Create code length array for a Huffman tree + +Arguments: + +Root - the root of the tree + +Returns: + +VOID + +--*/ +{ + INT32 Index; + INT32 Index3; + UINT32 Cum; + + for (Index = 0; Index <= 16; Index++) { + mLenCnt[Index] = 0; + } + + CountLen(Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + Cum = 0; + for (Index = 16; Index > 0; Index--) { + Cum += mLenCnt[Index] << (16 - Index); + } + + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (Index = 15; Index > 0; Index--) { + if (mLenCnt[Index] != 0) { + mLenCnt[Index]--; + mLenCnt[Index + 1] += 2; + break; + } + } + + Cum--; + } + + for (Index = 16; Index > 0; Index--) { + Index3 = mLenCnt[Index]; + Index3--; + while (Index3 >= 0) { + mLen[*mSortPtr++] = (UINT8)Index; + Index3--; + } + } +} + +STATIC +VOID +DownHeap( + INT32 Index +) +{ + INT32 Index2; + INT32 Index3; + + // + // priority queue: send Index-th entry down heap + // + Index3 = mHeap[Index]; + Index2 = 2 * Index; + while (Index2 <= mHeapSize) { + if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { + Index2++; + } + + if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { + break; + } + + mHeap[Index] = mHeap[Index2]; + Index = Index2; + Index2 = 2 * Index; + } + + mHeap[Index] = (INT16)Index3; +} + +STATIC +VOID +MakeCode( + INT32 Number, + UINT8 Len[], + UINT16 Code[] +) +/*++ + +Routine Description: + +Assign code to each symbol based on the code length array + +Arguments: + +Number - number of symbols +Len - the code length array +Code - stores codes for each symbol + +Returns: (VOID) + +--*/ +{ + INT32 Index; + UINT16 Start[18]; + + Start[1] = 0; + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16)((Start[Index] + mLenCnt[Index]) << 1); + } + + for (Index = 0; Index < Number; Index++) { + Code[Index] = Start[Len[Index]]++; + } +} + +STATIC +INT32 +MakeTree( + INT32 NParm, + UINT16 FreqParm[], + UINT8 LenParm[], + UINT16 CodeParm[] +) +/*++ + +Routine Description: + +Generates Huffman codes given a frequency distribution of symbols + +Arguments: + +NParm - number of symbols +FreqParm - frequency of each symbol +LenParm - code length for each symbol +CodeParm - code for each symbol + +Returns: + +Root of the Huffman tree. + +--*/ +{ + INT32 Index; + INT32 Index2; + INT32 Index3; + INT32 Avail; + + // + // make tree, calculate len[], return root + // + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (Index = 0; Index < mN; Index++) { + mLen[Index] = 0; + if (mFreq[Index]) { + mHeapSize++; + mHeap[mHeapSize] = (INT16)Index; + } + } + + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + + for (Index = mHeapSize / 2; Index >= 1; Index--) { + // + // make priority queue + // + DownHeap(Index); + } + + mSortPtr = CodeParm; + do { + Index = mHeap[1]; + if (Index < mN) { + *mSortPtr++ = (UINT16)Index; + } + + mHeap[1] = mHeap[mHeapSize--]; + DownHeap(1); + Index2 = mHeap[1]; + if (Index2 < mN) { + *mSortPtr++ = (UINT16)Index2; + } + + Index3 = Avail++; + mFreq[Index3] = (UINT16)(mFreq[Index] + mFreq[Index2]); + mHeap[1] = (INT16)Index3; + DownHeap(1); + mLeft[Index3] = (UINT16)Index; + mRight[Index3] = (UINT16)Index2; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen(Index3); + MakeCode(NParm, LenParm, CodeParm); + + // + // return root + // + return Index3; } diff --git a/Tiano/EfiTianoDecompress.c b/Tiano/EfiTianoDecompress.c index 156392c..7300bb5 100644 --- a/Tiano/EfiTianoDecompress.c +++ b/Tiano/EfiTianoDecompress.c @@ -50,40 +50,40 @@ Decompressor. Algorithm Ported from OPSD code (Decomp.asm) #endif typedef struct { - UINT8 *mSrcBase; // Starting address of compressed data - UINT8 *mDstBase; // Starting address of decompressed data - UINT32 mOutBuf; - UINT32 mInBuf; + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; - UINT16 mBitCount; - UINT32 mBitBuf; - UINT32 mSubBitBuf; - UINT16 mBlockSize; - UINT32 mCompSize; - UINT32 mOrigSize; + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; - UINT16 mBadTableFlag; + UINT16 mBadTableFlag; - UINT16 mLeft[2 * NC - 1]; - UINT16 mRight[2 * NC - 1]; - UINT8 mCLen[NC]; - UINT8 mPTLen[NPT]; - UINT16 mCTable[4096]; - UINT16 mPTTable[256]; + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; - // - // The length of the field 'Position Set Code Length Array Size' in Block Header. - // For EFI 1.1 de/compression algorithm, mPBit = 4 - // For Tiano de/compression algorithm, mPBit = 5 - // - UINT8 mPBit; + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm, mPBit = 4 + // For Tiano de/compression algorithm, mPBit = 5 + // + UINT8 mPBit; } SCRATCH_DATA; STATIC VOID FillBuf( -IN SCRATCH_DATA *Sd, -IN UINT16 NumOfBits + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits ) /*++ @@ -100,38 +100,38 @@ Returns: (VOID) --*/ { - Sd->mBitBuf = (UINT32)(Sd->mBitBuf << NumOfBits); + Sd->mBitBuf = (UINT32)(Sd->mBitBuf << NumOfBits); - while (NumOfBits > Sd->mBitCount) { - Sd->mBitBuf |= (UINT32)(Sd->mSubBitBuf << (NumOfBits = (UINT16)(NumOfBits - Sd->mBitCount))); + while (NumOfBits > Sd->mBitCount) { + Sd->mBitBuf |= (UINT32)(Sd->mSubBitBuf << (NumOfBits = (UINT16)(NumOfBits - Sd->mBitCount))); - if (Sd->mCompSize > 0) { - // - // Get 1 byte into SubBitBuf - // - Sd->mCompSize--; - Sd->mSubBitBuf = 0; - Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; - Sd->mBitCount = 8; - } - else { - // - // No more bits from the source, just pad zero bit. - // - Sd->mSubBitBuf = 0; - Sd->mBitCount = 8; - } - } + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + } + else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + } + } - Sd->mBitCount = (UINT16)(Sd->mBitCount - NumOfBits); - Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; + Sd->mBitCount = (UINT16)(Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; } STATIC UINT32 GetBits( -IN SCRATCH_DATA *Sd, -IN UINT16 NumOfBits + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits ) /*++ @@ -152,23 +152,23 @@ The bits that are popped out. --*/ { - UINT32 OutBits; + UINT32 OutBits; - OutBits = (UINT32)(Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + OutBits = (UINT32)(Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); - FillBuf(Sd, NumOfBits); + FillBuf(Sd, NumOfBits); - return OutBits; + return OutBits; } STATIC UINT16 MakeTable( -IN SCRATCH_DATA *Sd, -IN UINT16 NumOfChar, -IN UINT8 *BitLen, -IN UINT16 TableBits, -OUT UINT16 *Table + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table ) /*++ @@ -191,140 +191,140 @@ BAD_TABLE - The table is corrupted. --*/ { - UINT16 Count[17]; - UINT16 Weight[17]; - UINT16 Start[18]; - UINT16 *Pointer; - UINT16 Index3; - UINT16 Index; - UINT16 Len; - UINT16 Char; - UINT16 JuBits; - UINT16 Avail; - UINT16 NextCode; - UINT16 Mask; + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; - // - // TableBits should not be greater than 16. - // - if (TableBits >= (sizeof(Count) / sizeof(UINT16))) { - return (UINT16)BAD_TABLE; - } + // + // TableBits should not be greater than 16. + // + if (TableBits >= (sizeof(Count) / sizeof(UINT16))) { + return (UINT16)BAD_TABLE; + } - // - // Initialize Count array starting from Index 0, as there is a possibility of Count array being uninitialized. - // - for (Index = 0; Index <= 16; Index++) { - Count[Index] = 0; - } + // + // Initialize Count array starting from Index 0, as there is a possibility of Count array being uninitialized. + // + for (Index = 0; Index <= 16; Index++) { + Count[Index] = 0; + } - for (Index = 0; Index < NumOfChar; Index++) { - // - // Count array index should not be greater than or equal to its size. - // - if (BitLen[Index] < (sizeof(Count) / sizeof(UINT16))) { - Count[BitLen[Index]]++; - } - else { - return (UINT16)BAD_TABLE; - } - } + for (Index = 0; Index < NumOfChar; Index++) { + // + // Count array index should not be greater than or equal to its size. + // + if (BitLen[Index] < (sizeof(Count) / sizeof(UINT16))) { + Count[BitLen[Index]]++; + } + else { + return (UINT16)BAD_TABLE; + } + } - Start[0] = 0; - Start[1] = 0; + Start[0] = 0; + Start[1] = 0; - for (Index = 1; Index <= 16; Index++) { - Start[Index + 1] = (UINT16)(Start[Index] + (Count[Index] << (16 - Index))); - } + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16)(Start[Index] + (Count[Index] << (16 - Index))); + } - if (Start[17] != 0) { - /*(1U << 16)*/ - return (UINT16)BAD_TABLE; - } + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16)BAD_TABLE; + } - JuBits = (UINT16)(16 - TableBits); + JuBits = (UINT16)(16 - TableBits); - for (Index = 1; Index <= TableBits; Index++) { - Start[Index] >>= JuBits; - Weight[Index] = (UINT16)(1U << (TableBits - Index)); - } + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16)(1U << (TableBits - Index)); + } - while (Index <= 16) { - Weight[Index] = (UINT16)(1U << (16 - Index)); - Index++; - } + while (Index <= 16) { + Weight[Index] = (UINT16)(1U << (16 - Index)); + Index++; + } - Index = (UINT16)(Start[TableBits + 1] >> JuBits); + Index = (UINT16)(Start[TableBits + 1] >> JuBits); - if (Index != 0) { - Index3 = (UINT16)(1U << TableBits); - while (Index != Index3) { - Table[Index++] = 0; - } - } + if (Index != 0) { + Index3 = (UINT16)(1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } - Avail = NumOfChar; - Mask = (UINT16)(1U << (15 - TableBits)); + Avail = NumOfChar; + Mask = (UINT16)(1U << (15 - TableBits)); - for (Char = 0; Char < NumOfChar; Char++) { - Len = BitLen[Char]; - if (Len == 0 || Len >= 17) { - continue; - } + for (Char = 0; Char < NumOfChar; Char++) { + Len = BitLen[Char]; + if (Len == 0 || Len >= 17) { + continue; + } - NextCode = (UINT16)(Start[Len] + Weight[Len]); + NextCode = (UINT16)(Start[Len] + Weight[Len]); - if (Len <= TableBits) { - for (Index = Start[Len]; Index < NextCode; Index++) { - // Check to prevent possible heap corruption - if (Index >= (UINT16)(1U << TableBits)) - return (UINT16)BAD_TABLE; - Table[Index] = Char; - } - } - else { - Index3 = Start[Len]; - Pointer = &Table[Index3 >> JuBits]; - Index = (UINT16)(Len - TableBits); + if (Len <= TableBits) { + for (Index = Start[Len]; Index < NextCode; Index++) { + // Check to prevent possible heap corruption + if (Index >= (UINT16)(1U << TableBits)) + return (UINT16)BAD_TABLE; + Table[Index] = Char; + } + } + else { + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16)(Len - TableBits); - while (Index != 0) { - // - // Avail should be lesser than size of mRight and mLeft to prevent buffer overflow. - // - if ((*Pointer == 0) && (Avail < sizeof(Sd->mRight) / sizeof(UINT16)) && (Avail < sizeof(Sd->mLeft) / sizeof(UINT16))) { - Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; - *Pointer = Avail++; - } + while (Index != 0) { + // + // Avail should be lesser than size of mRight and mLeft to prevent buffer overflow. + // + if ((*Pointer == 0) && (Avail < sizeof(Sd->mRight) / sizeof(UINT16)) && (Avail < sizeof(Sd->mLeft) / sizeof(UINT16))) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } - // - // *Pointer should be lesser than size of mRight and mLeft to prevent buffer overflow. - // - if ((Index3 & Mask) && (*Pointer < (sizeof(Sd->mRight) / sizeof(UINT16)))) { - Pointer = &Sd->mRight[*Pointer]; - } - else if (*Pointer < (sizeof(Sd->mLeft) / sizeof(UINT16))) { - Pointer = &Sd->mLeft[*Pointer]; - } + // + // *Pointer should be lesser than size of mRight and mLeft to prevent buffer overflow. + // + if ((Index3 & Mask) && (*Pointer < (sizeof(Sd->mRight) / sizeof(UINT16)))) { + Pointer = &Sd->mRight[*Pointer]; + } + else if (*Pointer < (sizeof(Sd->mLeft) / sizeof(UINT16))) { + Pointer = &Sd->mLeft[*Pointer]; + } - Index3 <<= 1; - Index--; - } + Index3 <<= 1; + Index--; + } - *Pointer = Char; - } + *Pointer = Char; + } - Start[Len] = NextCode; - } - // - // Succeeds - // - return 0; + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; } STATIC UINT32 DecodeP( -IN SCRATCH_DATA *Sd + IN SCRATCH_DATA *Sd ) /*++ @@ -342,46 +342,46 @@ The position value decoded. --*/ { - UINT16 Val; - UINT32 Mask; - UINT32 Pos; + UINT16 Val; + UINT32 Mask; + UINT32 Pos; - Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; - if (Val >= MAXNP) { - Mask = 1U << (BITBUFSIZ - 1 - 8); + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); - do { - if (Sd->mBitBuf & Mask) { - Val = Sd->mRight[Val]; - } - else { - Val = Sd->mLeft[Val]; - } + do { + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } + else { + Val = Sd->mLeft[Val]; + } - Mask >>= 1; - } while (Val >= MAXNP); - } - // - // Advance what we have read - // - FillBuf(Sd, Sd->mPTLen[Val]); + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf(Sd, Sd->mPTLen[Val]); - Pos = Val; - if (Val > 1) { - Pos = (UINT32)((1U << (Val - 1)) + GetBits(Sd, (UINT16)(Val - 1))); - } + Pos = Val; + if (Val > 1) { + Pos = (UINT32)((1U << (Val - 1)) + GetBits(Sd, (UINT16)(Val - 1))); + } - return Pos; + return Pos; } STATIC UINT16 ReadPTLen( -IN SCRATCH_DATA *Sd, -IN UINT16 nn, -IN UINT16 nbit, -IN UINT16 Special + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special ) /*++ @@ -403,76 +403,76 @@ BAD_TABLE - Table is corrupted. --*/ { - UINT16 Number; - UINT16 CharC; - UINT16 Index; - UINT32 Mask; + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; - Number = (UINT16)GetBits(Sd, nbit); + Number = (UINT16)GetBits(Sd, nbit); - if ((Number > sizeof(Sd->mPTLen)) || (nn > sizeof(Sd->mPTLen))) { - // - // Fail if Number or nn is greater than size of mPTLen - // - return (UINT16)BAD_TABLE; - } + if ((Number > sizeof(Sd->mPTLen)) || (nn > sizeof(Sd->mPTLen))) { + // + // Fail if Number or nn is greater than size of mPTLen + // + return (UINT16)BAD_TABLE; + } - if (Number == 0) { - CharC = (UINT16)GetBits(Sd, nbit); + if (Number == 0) { + CharC = (UINT16)GetBits(Sd, nbit); - for (Index = 0; Index < 256; Index++) { - Sd->mPTTable[Index] = CharC; - } + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } - for (Index = 0; Index < nn; Index++) { - Sd->mPTLen[Index] = 0; - } + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } - return 0; - } + return 0; + } - Index = 0; + Index = 0; - while (Index < Number) { - CharC = (UINT16)(Sd->mBitBuf >> (BITBUFSIZ - 3)); + while (Index < Number) { + CharC = (UINT16)(Sd->mBitBuf >> (BITBUFSIZ - 3)); - if (CharC == 7) { - Mask = 1U << (BITBUFSIZ - 1 - 3); - while (Mask & Sd->mBitBuf) { - Mask >>= 1; - CharC += 1; - } - } + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } - FillBuf(Sd, (UINT16)((CharC < 7) ? 3 : CharC - 3)); + FillBuf(Sd, (UINT16)((CharC < 7) ? 3 : CharC - 3)); - Sd->mPTLen[Index++] = (UINT8)CharC; + Sd->mPTLen[Index++] = (UINT8)CharC; - if (Index == Special) { - CharC = (UINT16)GetBits(Sd, 2); - while ((INT16)(--CharC) >= 0) { - if (Index >= sizeof(Sd->mPTLen)) { - // - // Fail if Index is greater than or equal to mPTLen - // - return (UINT16)BAD_TABLE; - } - Sd->mPTLen[Index++] = 0; - } - } - } + if (Index == Special) { + CharC = (UINT16)GetBits(Sd, 2); + while ((INT16)(--CharC) >= 0) { + if (Index >= sizeof(Sd->mPTLen)) { + // + // Fail if Index is greater than or equal to mPTLen + // + return (UINT16)BAD_TABLE; + } + Sd->mPTLen[Index++] = 0; + } + } + } - while (Index < nn) { - Sd->mPTLen[Index++] = 0; - } + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } - return MakeTable(Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); + return MakeTable(Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); } STATIC VOID ReadCLen( -SCRATCH_DATA *Sd + SCRATCH_DATA *Sd ) /*++ @@ -488,82 +488,82 @@ Returns: (VOID) --*/ { - UINT16 Number; - UINT16 CharC; - UINT16 Index; - UINT32 Mask; + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; - Number = (UINT16)GetBits(Sd, CBIT); + Number = (UINT16)GetBits(Sd, CBIT); - if (Number == 0) { - CharC = (UINT16)GetBits(Sd, CBIT); + if (Number == 0) { + CharC = (UINT16)GetBits(Sd, CBIT); - for (Index = 0; Index < NC; Index++) { - Sd->mCLen[Index] = 0; - } + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } - for (Index = 0; Index < 4096; Index++) { - Sd->mCTable[Index] = CharC; - } + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } - return; - } + return; + } - Index = 0; - while (Index < Number) { - CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; - if (CharC >= NT) { - Mask = 1U << (BITBUFSIZ - 1 - 8); + Index = 0; + while (Index < Number) { + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); - do { - if (Mask & Sd->mBitBuf) { - CharC = Sd->mRight[CharC]; - } - else { - CharC = Sd->mLeft[CharC]; - } + do { + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } + else { + CharC = Sd->mLeft[CharC]; + } - Mask >>= 1; - } while (CharC >= NT); - } - // - // Advance what we have read - // - FillBuf(Sd, Sd->mPTLen[CharC]); + Mask >>= 1; + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf(Sd, Sd->mPTLen[CharC]); - if (CharC <= 2) { - if (CharC == 0) { - CharC = 1; - } - else if (CharC == 1) { - CharC = (UINT16)(GetBits(Sd, 4) + 3); - } - else if (CharC == 2) { - CharC = (UINT16)(GetBits(Sd, CBIT) + 20); - } + if (CharC <= 2) { + if (CharC == 0) { + CharC = 1; + } + else if (CharC == 1) { + CharC = (UINT16)(GetBits(Sd, 4) + 3); + } + else if (CharC == 2) { + CharC = (UINT16)(GetBits(Sd, CBIT) + 20); + } - while ((INT16)(--CharC) >= 0) { - Sd->mCLen[Index++] = 0; - } - } - else { - Sd->mCLen[Index++] = (UINT8)(CharC - 2); - } - } + while ((INT16)(--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + } + else { + Sd->mCLen[Index++] = (UINT8)(CharC - 2); + } + } - while (Index < NC) { - Sd->mCLen[Index++] = 0; - } + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } - MakeTable(Sd, NC, Sd->mCLen, 12, Sd->mCTable); + MakeTable(Sd, NC, Sd->mCLen, 12, Sd->mCTable); - return; + return; } STATIC UINT16 DecodeC( -SCRATCH_DATA *Sd + SCRATCH_DATA *Sd ) /*++ @@ -581,56 +581,56 @@ The value decoded. --*/ { - UINT16 Index2; - UINT32 Mask; + UINT16 Index2; + UINT32 Mask; - if (Sd->mBlockSize == 0) { - // - // Starting a new block - // - Sd->mBlockSize = (UINT16)GetBits(Sd, 16); - Sd->mBadTableFlag = ReadPTLen(Sd, NT, TBIT, 3); - if (Sd->mBadTableFlag != 0) { - return 0; - } + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16)GetBits(Sd, 16); + Sd->mBadTableFlag = ReadPTLen(Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } - ReadCLen(Sd); + ReadCLen(Sd); - Sd->mBadTableFlag = ReadPTLen(Sd, MAXNP, Sd->mPBit, (UINT16)(-1)); - if (Sd->mBadTableFlag != 0) { - return 0; - } - } + Sd->mBadTableFlag = ReadPTLen(Sd, MAXNP, Sd->mPBit, (UINT16)(-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } - Sd->mBlockSize--; - Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; - if (Index2 >= NC) { - Mask = 1U << (BITBUFSIZ - 1 - 12); + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); - do { - if (Sd->mBitBuf & Mask) { - Index2 = Sd->mRight[Index2]; - } - else { - Index2 = Sd->mLeft[Index2]; - } + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } + else { + Index2 = Sd->mLeft[Index2]; + } - Mask >>= 1; - } while (Index2 >= NC); - } - // - // Advance what we have read - // - FillBuf(Sd, Sd->mCLen[Index2]); + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf(Sd, Sd->mCLen[Index2]); - return Index2; + return Index2; } STATIC VOID Decode( -SCRATCH_DATA *Sd + SCRATCH_DATA *Sd ) /*++ @@ -646,66 +646,66 @@ Returns: (VOID) --*/ { - UINT16 BytesRemain; - UINT32 DataIdx; - UINT16 CharC; + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; - BytesRemain = (UINT16)(-1); + BytesRemain = (UINT16)(-1); - DataIdx = 0; + DataIdx = 0; - for (;;) { - CharC = DecodeC(Sd); - if (Sd->mBadTableFlag != 0) { - return; - } + for (;;) { + CharC = DecodeC(Sd); + if (Sd->mBadTableFlag != 0) { + return; + } - if (CharC < 256) { - // - // Process an Original character - // - if (Sd->mOutBuf >= Sd->mOrigSize) { - return; - } - else { - Sd->mDstBase[Sd->mOutBuf++] = (UINT8)CharC; - } - } - else { - // - // Process a Pointer - // - CharC = (UINT16)(CharC - (UINT8_MAX + 1 - THRESHOLD)); + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return; + } + else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8)CharC; + } + } + else { + // + // Process a Pointer + // + CharC = (UINT16)(CharC - (UINT8_MAX + 1 - THRESHOLD)); - BytesRemain = CharC; + BytesRemain = CharC; - DataIdx = Sd->mOutBuf - DecodeP(Sd) - 1; + DataIdx = Sd->mOutBuf - DecodeP(Sd) - 1; - // Check to prevent possible heap corruption - if (DataIdx >= Sd->mOrigSize - BytesRemain) { - Sd->mBadTableFlag = 1; - return; - } + // Check to prevent possible heap corruption + if (DataIdx >= Sd->mOrigSize - BytesRemain) { + Sd->mBadTableFlag = 1; + return; + } - BytesRemain--; - while ((INT16)(BytesRemain) >= 0) { - Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; - if (Sd->mOutBuf >= Sd->mOrigSize) { - return; - } + BytesRemain--; + while ((INT16)(BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return; + } - BytesRemain--; - } - } - } + BytesRemain--; + } + } + } } EFI_STATUS GetInfo( -IN const VOID *Source, -IN UINT32 SrcSize, -OUT UINT32 *DstSize, -OUT UINT32 *ScratchSize + IN const VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize ) /*++ @@ -727,28 +727,28 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - const UINT8 *Src; + const UINT8 *Src; - *ScratchSize = sizeof(SCRATCH_DATA); + *ScratchSize = sizeof(SCRATCH_DATA); - Src = Source; - if (SrcSize < 8) { - return EFI_INVALID_PARAMETER; - } + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } - *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); - return EFI_SUCCESS; + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + return EFI_SUCCESS; } EFI_STATUS Decompress( -IN const VOID *Source, -IN UINT32 SrcSize, -IN OUT VOID *Destination, -IN UINT32 DstSize, -IN OUT VOID *Scratch, -IN UINT32 ScratchSize, -IN UINT8 Version + IN const VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize, + IN UINT8 Version ) /*++ @@ -775,104 +775,104 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - UINT32 Index; - UINT32 CompSize; - UINT32 OrigSize; - EFI_STATUS Status; - SCRATCH_DATA *Sd; - const UINT8 *Src; - UINT8 *Dst; + UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + EFI_STATUS Status; + SCRATCH_DATA *Sd; + const UINT8 *Src; + UINT8 *Dst; - Status = EFI_SUCCESS; - Src = Source; - Dst = Destination; + Status = EFI_SUCCESS; + Src = Source; + Dst = Destination; - if (ScratchSize < sizeof(SCRATCH_DATA)) { - return EFI_INVALID_PARAMETER; - } + if (ScratchSize < sizeof(SCRATCH_DATA)) { + return EFI_INVALID_PARAMETER; + } - Sd = (SCRATCH_DATA *)Scratch; + Sd = (SCRATCH_DATA *)Scratch; - if (SrcSize < 8) { - return EFI_INVALID_PARAMETER; - } + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } - CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); - OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); - // - // If compressed file size is 0, return - // - if (OrigSize == 0) { - return Status; - } + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return Status; + } - if (SrcSize < CompSize + 8) { - return EFI_INVALID_PARAMETER; - } + if (SrcSize < CompSize + 8) { + return EFI_INVALID_PARAMETER; + } - if (DstSize != OrigSize) { - return EFI_INVALID_PARAMETER; - } + if (DstSize != OrigSize) { + return EFI_INVALID_PARAMETER; + } - Src = Src + 8; + Src = Src + 8; - for (Index = 0; Index < sizeof(SCRATCH_DATA); Index++) { - ((UINT8 *)Sd)[Index] = 0; - } - // - // The length of the field 'Position Set Code Length Array Size' in Block Header. - // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 - // For Tiano de/compression algorithm(Version 2), mPBit = 5 - // - switch (Version) { - case 1: - Sd->mPBit = 4; - break; + for (Index = 0; Index < sizeof(SCRATCH_DATA); Index++) { + ((UINT8 *)Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1: + Sd->mPBit = 4; + break; - case 2: - Sd->mPBit = 5; - break; + case 2: + Sd->mPBit = 5; + break; - default: - // - // Currently, only have 2 versions - // - return EFI_INVALID_PARAMETER; - } + default: + // + // Currently, only have 2 versions + // + return EFI_INVALID_PARAMETER; + } - Sd->mSrcBase = (UINT8*)Src; - Sd->mDstBase = Dst; - Sd->mCompSize = CompSize; - Sd->mOrigSize = OrigSize; + Sd->mSrcBase = (UINT8*)Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; - // - // Fill the first BITBUFSIZ bits - // - FillBuf(Sd, BITBUFSIZ); + // + // Fill the first BITBUFSIZ bits + // + FillBuf(Sd, BITBUFSIZ); - // - // Decompress it - // - Decode(Sd); + // + // Decompress it + // + Decode(Sd); - if (Sd->mBadTableFlag != 0) { - // - // Something wrong with the source - // - Status = EFI_INVALID_PARAMETER; - } + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + Status = EFI_INVALID_PARAMETER; + } - return Status; + return Status; } EFI_STATUS EFIAPI EfiTianoGetInfo( -IN const VOID *Source, -IN UINT32 SrcSize, -OUT UINT32 *DstSize, -OUT UINT32 *ScratchSize + IN const VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize ) /*++ @@ -895,23 +895,23 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - return GetInfo( - Source, - SrcSize, - DstSize, - ScratchSize - ); + return GetInfo( + Source, + SrcSize, + DstSize, + ScratchSize + ); } EFI_STATUS EFIAPI EfiDecompress( -IN const VOID *Source, -IN UINT32 SrcSize, -IN OUT VOID *Destination, -IN UINT32 DstSize, -IN OUT VOID *Scratch, -IN UINT32 ScratchSize + IN const VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize ) /*++ @@ -936,29 +936,29 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - // - // For EFI 1.1 de/compression algorithm, the version is 1. - // - return Decompress( - Source, - SrcSize, - Destination, - DstSize, - Scratch, - ScratchSize, - 1 - ); + // + // For EFI 1.1 de/compression algorithm, the version is 1. + // + return Decompress( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 1 + ); } EFI_STATUS EFIAPI TianoDecompress( -IN const VOID *Source, -IN UINT32 SrcSize, -IN OUT VOID *Destination, -IN UINT32 DstSize, -IN OUT VOID *Scratch, -IN UINT32 ScratchSize + IN const VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize ) /*++ @@ -983,16 +983,16 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - // - // For Tiano de/compression algorithm, the version is 2. - // - return Decompress( - Source, - SrcSize, - Destination, - DstSize, - Scratch, - ScratchSize, - 2 - ); + // + // For Tiano de/compression algorithm, the version is 2. + // + return Decompress( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 2 + ); } diff --git a/Tiano/EfiTianoDecompress.h b/Tiano/EfiTianoDecompress.h index 8fa3dcf..fe0eba5 100644 --- a/Tiano/EfiTianoDecompress.h +++ b/Tiano/EfiTianoDecompress.h @@ -37,14 +37,13 @@ extern "C" { UINT32 OrigSize; } EFI_TIANO_HEADER; - EFI_STATUS - EFIAPI - EfiTianoGetInfo( - const VOID *Source, - UINT32 SrcSize, - UINT32 *DstSize, - UINT32 *ScratchSize - ) + EFI_STATUS + EfiTianoGetInfo( + IN const VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) /*++ Routine Description: @@ -67,16 +66,16 @@ extern "C" { --*/ ; - EFI_STATUS - EFIAPI - EfiDecompress( - const VOID *Source, - UINT32 SrcSize, - VOID *Destination, - UINT32 DstSize, - VOID *Scratch, - UINT32 ScratchSize - ) + EFI_STATUS + EFIAPI + EfiDecompress( + IN const VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) /*++ Routine Description: @@ -101,16 +100,16 @@ extern "C" { --*/ ; - EFI_STATUS - EFIAPI - TianoDecompress( - const VOID *Source, - UINT32 SrcSize, - VOID *Destination, - UINT32 DstSize, - VOID *Scratch, - UINT32 ScratchSize - ) + EFI_STATUS + EFIAPI + TianoDecompress( + IN const VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) /*++ Routine Description: diff --git a/UEFIPatch/patches.txt b/UEFIPatch/patches.txt index 9a8a4c8..4a78a8c 100644 --- a/UEFIPatch/patches.txt +++ b/UEFIPatch/patches.txt @@ -52,8 +52,9 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F 299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:81E10080000033C1:9090909090909090 299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 12 P:81E10080000033C1:9090909090909090 -# PpmInitialize | Skylake-X -3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:742CB9E2000000:752CB9E2000000 +# SiInit | Skylake-X +D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 10 P:81E10080000033C1:9090909090909090 +D71C8BA4-4AF2-4D0D-B1BA-F2409F0C20D3 12 P:81E10080000033C1:9090909090909090 -# CpuInitPei | Skylake-X -01359D99-9446-456D-ADA4-50A711C03ADA 12 P:BE0080000023CE0B:BE0000000023CE0B \ No newline at end of file +# PpmInitialize | Skylake-X, Kaby Lake-X +3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBAE80F:0FBAE00F \ No newline at end of file diff --git a/ffsengine.h b/ffsengine.h index 129f44b..8b2f327 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -95,6 +95,7 @@ public: UINT8 replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode); UINT8 remove(const QModelIndex & index); UINT8 rebuild(const QModelIndex & index); + UINT8 doNotRebuild(const QModelIndex & index); UINT8 dump(const QModelIndex & index, const QString & path, const QString & filter = QString()); UINT8 patch(const QModelIndex & index, const QVector & patches); diff --git a/types.cpp b/types.cpp index d8dd01d..99442c1 100644 --- a/types.cpp +++ b/types.cpp @@ -150,6 +150,8 @@ QString actionTypeToQString(const UINT8 action) return QObject::tr("Rebuild"); case Actions::Rebase: return QObject::tr("Rebase"); + case Actions::DoNotRebuild: + return QObject::tr("Do not rebuild"); default: return QObject::tr("Unknown"); } diff --git a/types.h b/types.h index 7d71953..a5823cb 100644 --- a/types.h +++ b/types.h @@ -26,7 +26,8 @@ namespace Actions Replace, Remove, Rebuild, - Rebase + Rebase, + DoNotRebuild }; } diff --git a/uefitool.cpp b/uefitool.cpp index fbdc029..c4a84d7 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.22.4")) +version(tr("0.23.0")) { clipboard = QApplication::clipboard(); @@ -43,6 +43,7 @@ version(tr("0.22.4")) connect(ui->actionReplaceBody, SIGNAL(triggered()), this, SLOT(replaceBody())); connect(ui->actionRemove, SIGNAL(triggered()), this, SLOT(remove())); connect(ui->actionRebuild, SIGNAL(triggered()), this, SLOT(rebuild())); + connect(ui->actionDoNotRebuild, SIGNAL(triggered()), this, SLOT(doNotRebuild())); connect(ui->actionMessagesCopy, SIGNAL(triggered()), this, SLOT(copyMessage())); connect(ui->actionMessagesCopyAll, SIGNAL(triggered()), this, SLOT(copyAllMessages())); connect(ui->actionMessagesClear, SIGNAL(triggered()), this, SLOT(clearMessages())); @@ -146,6 +147,7 @@ void UEFITool::populateUi(const QModelIndex ¤t) // Enable actions ui->actionExtract->setDisabled(model->hasEmptyHeader(current) && model->hasEmptyBody(current)); ui->actionRebuild->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section); + ui->actionDoNotRebuild->setEnabled(type== Types::Region || type == Types::Volume || type == Types::File || type == Types::Section); ui->actionExtractBody->setDisabled(model->hasEmptyBody(current)); ui->actionRemove->setEnabled(type == Types::Volume || type == Types::File || type == Types::Section); ui->actionInsertInto->setEnabled((type == Types::Volume && subtype != Subtypes::UnknownVolume) || @@ -220,6 +222,18 @@ void UEFITool::rebuild() ui->actionSaveImageFile->setEnabled(true); } +void UEFITool::doNotRebuild() +{ + QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); + if (!index.isValid()) + return; + + UINT8 result = ffsEngine->doNotRebuild(index); + + if (result == ERR_SUCCESS) + ui->actionSaveImageFile->setEnabled(true); +} + void UEFITool::remove() { QModelIndex index = ui->structureTreeView->selectionModel()->currentIndex(); diff --git a/uefitool.h b/uefitool.h index edac83b..ac7b00a 100644 --- a/uefitool.h +++ b/uefitool.h @@ -78,6 +78,7 @@ public: void replaceBody(); void rebuild(); + void doNotRebuild(); void remove(); diff --git a/uefitool.ui b/uefitool.ui index 8e0a19d..c921129 100644 --- a/uefitool.ui +++ b/uefitool.ui @@ -180,7 +180,7 @@ 0 0 800 - 21 + 31
@@ -225,6 +225,8 @@ + + @@ -243,6 +245,7 @@ + @@ -257,6 +260,7 @@ + @@ -275,6 +279,7 @@ + @@ -284,7 +289,6 @@ - @@ -536,6 +540,17 @@ Ctrl+Shift+O + + + false + + + &Do not rebuild + + + Ctrl+Shift+Space + + From 462f693ad65f23f83bdd6069302a95cf30ad9750 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 1 May 2018 23:27:35 +0300 Subject: [PATCH 34/64] Recover Skylake patches --- UEFIPatch/patches.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/UEFIPatch/patches.txt b/UEFIPatch/patches.txt index 4a78a8c..a097f03 100644 --- a/UEFIPatch/patches.txt +++ b/UEFIPatch/patches.txt @@ -52,9 +52,8 @@ F7731B4C-58A2-4DF4-8980-5645D39ECE58 10 P:0FBA6C24380F:0FBA7424380F 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 +3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:742CB9E2000000:752CB9E2000000 -# PpmInitialize | Skylake-X, Kaby Lake-X -3FFCAE95-23CF-4967-94F5-16352F68E43B 10 P:0FBAE80F:0FBAE00F \ No newline at end of file +# CpuInitPei | Skylake-X +01359D99-9446-456D-ADA4-50A711C03ADA 12 P:BE0080000023CE0B:BE0000000023CE0B From fd4d75957ef965336ee71416b02e4d00d9e9e411 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Thu, 3 May 2018 19:33:55 +0300 Subject: [PATCH 35/64] Fix rebuild reversion --- ffsengine.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ffsengine.cpp b/ffsengine.cpp index 0747e90..3d09216 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -2662,6 +2662,17 @@ UINT8 FfsEngine::rebuild(const QModelIndex & index) return ERR_SUCCESS; } +UINT8 FfsEngine::doNotRebuild(const QModelIndex & index) +{ + if (!index.isValid()) + return ERR_INVALID_PARAMETER; + + // Set action for the item + model->setAction(index, Actions::DoNotRebuild); + + return ERR_SUCCESS; +} + // Compression routines UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm) { From 32847379526a3551a76e5944fa6d87859291a3ec Mon Sep 17 00:00:00 2001 From: vit9696 Date: Thu, 3 May 2018 21:12:24 +0300 Subject: [PATCH 36/64] Implement mac builds with deploy --- .travis.yml | 50 +++++++++++++++++++++++++++++++-------- macbuild.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 10 deletions(-) create mode 100755 macbuild.sh diff --git a/.travis.yml b/.travis.yml index bd25b50..80c26e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,44 @@ language: cpp +matrix: + include: + - os: osx + osx_image: xcode9.2 -compiler: - - clang - - gcc + compiler: clang -before_install: - - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - - sudo apt-get update -qq - - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev + script: + - ./macbuild.sh -script: - - qmake -qt=qt5 uefitool.pro - - make + deploy: + provider: releases + skip_cleanup: true + file: "dist/*.zip" + file_glob: true + api_key: + secure: "TODO" + on: + tags: true + + - os: linux + compiler: clang + + before_install: + - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa + - sudo apt-get update -qq + - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev + + script: + - qmake -qt=qt5 uefitool.pro + - make + + - os: linux + compiler: gcc + + before_install: + - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa + - sudo apt-get update -qq + - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev + + script: + - qmake -qt=qt5 uefitool.pro + - make diff --git a/macbuild.sh b/macbuild.sh new file mode 100755 index 0000000..d3e9964 --- /dev/null +++ b/macbuild.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +if [ ! -d /opt/qt56sm ]; then + curl -L -o /tmp/qt-5.6.3-static-mac.zip https://github.com/distdb/qtbuilds/blob/master/qt-5.6.3-static-mac.zip?raw=true || exit 1 + qtsum=$(shasum -a 256 /tmp/qt-5.6.3-static-mac.zip | cut -f1 -d' ') + qtexpsum="214d22d8572ea6162753c8dd251d79275f3b22d49204718c637d722409e0cfcb" + if [ "$qtsum" != "$qtexpsum" ]; then + echo "Qt hash $qtsum does not match $qtexpsum" + exit 1 + fi + sudo mkdir -p /opt || exit 1 + cd /opt || exit 1 + sudo unzip -q /tmp/qt-5.6.3-static-mac.zip || exit 1 + cd - || exit 1 +fi + +export PATH="/opt/qt56sm/bin:$PATH" + +echo "Attempting to build UEFITool for macOS..." + +UEFITOOL_VER=$(cat uefitool.cpp | grep ^version | cut -d'"' -f2) +UEFIEXTRACT_VER=$(cat UEFIExtract/uefiextract_main.cpp | grep '"UEFIExtract [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) +UEFIFIND_VER=$(cat UEFIFind/uefifind_main.cpp | grep '"UEFIFind [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) +UEFIPATCH_VER=$(cat UEFIPatch/uefipatch_main.cpp | grep '"UEFIPatch [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) +UEFIREPLACE_VER=$(cat UEFIReplace/uefireplace_main.cpp | grep '"UEFIReplace [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) + +build_tool() { + echo "Building $1 $2" + # Check version + if [ "$(echo "$2" | grep '^[0-9]*\.[0-9]*\.[0-9]*$')" != "$2" ]; then + echo "Invalid $1 version!" + exit 1 + fi + # Tools are in subdirectories + if [ "$1" != "UEFITool" ]; then + cd "$1" || exit 1 + fi + + # Build + qmake $3 QMAKE_CXXFLAGS+=-flto QMAKE_LFLAGS+=-flto CONFIG+=optimize_size || exit 1 + make || exit 1 + + # Archive + if [ "$1" = "UEFITool" ]; then + strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1 + zip -qry dist/"UEFITool_${UEFITOOL_VER}_mac.zip" UEFITool.app "${4}" || exit 1 + else + strip -x "$1" || exit 1 + zip -qry ../dist/"${1}_${2}_mac.zip" "${1}" "${4}" || exit 1 + fi + + # Return to parent + if [ "$1" != "UEFITool" ]; then + cd - || exit 1 + fi +} + +rm -rf dist +mkdir -p dist || exit 1 + +build_tool UEFITool "$UEFITOOL_VER" uefitool.pro +build_tool UEFIExtract "$UEFIEXTRACT_VER" uefiextract.pro +build_tool UEFIFind "$UEFIFIND_VER" uefifind.pro +build_tool UEFIPatch "$UEFIPATCH_VER" uefipatch.pro patches.txt +build_tool UEFIReplace "$UEFIREPLACE_VER" uefireplace.pro + +exit 0 From 7da3f6b79311e4844f4889b2a6d16a878a1fdf50 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Fri, 4 May 2018 06:40:04 +0300 Subject: [PATCH 37/64] Add deploy key --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 80c26e8..99a9946 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ matrix: file: "dist/*.zip" file_glob: true api_key: - secure: "TODO" + secure: "WjYd93lVLKHULBpUXS/WtGrkdXyAwxHOUnLJotyDmQipAQP5Ox7Kj12JwkSJGEmVOEdcbIQJyi0QxPjn1UYbYsAt6Op8zrjnYLS4G4fMdBtcxprWzid85uTW7oAAIFs7ygMVhpzxRKpu70yNb683vbThqNmaOu6RyG9aJOLtPAg=" on: tags: true From fe13f1efe9dbbdb068dcdfde7584619bac5f900a Mon Sep 17 00:00:00 2001 From: vit9696 Date: Fri, 4 May 2018 20:46:06 +0300 Subject: [PATCH 38/64] Backport TianoDecompress fix for Xcode (https://bugzilla.tianocore.org/show_bug.cgi?id=635) --- Tiano/EfiTianoDecompress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tiano/EfiTianoDecompress.c b/Tiano/EfiTianoDecompress.c index 7300bb5..10449f1 100644 --- a/Tiano/EfiTianoDecompress.c +++ b/Tiano/EfiTianoDecompress.c @@ -100,10 +100,10 @@ Returns: (VOID) --*/ { - Sd->mBitBuf = (UINT32)(Sd->mBitBuf << NumOfBits); + Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits); while (NumOfBits > Sd->mBitCount) { - Sd->mBitBuf |= (UINT32)(Sd->mSubBitBuf << (NumOfBits = (UINT16)(NumOfBits - Sd->mBitCount))); + Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); if (Sd->mCompSize > 0) { // From dd28665644a41189de9c9978a5351cd126e4eac5 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Fri, 4 May 2018 21:42:54 +0300 Subject: [PATCH 39/64] Remove legacy UEFIFind and UEFIExtract in favour of new_engine branch --- UEFIExtract/uefiextract.cpp | 49 ---------- UEFIExtract/uefiextract.h | 43 --------- UEFIExtract/uefiextract.pro | 43 --------- UEFIExtract/uefiextract_main.cpp | 60 ------------ UEFIFind/uefifind.cpp | 160 ------------------------------- UEFIFind/uefifind.h | 52 ---------- UEFIFind/uefifind.pro | 43 --------- UEFIFind/uefifind_main.cpp | 72 -------------- macbuild.sh | 4 - 9 files changed, 526 deletions(-) delete mode 100644 UEFIExtract/uefiextract.cpp delete mode 100644 UEFIExtract/uefiextract.h delete mode 100644 UEFIExtract/uefiextract.pro delete mode 100644 UEFIExtract/uefiextract_main.cpp delete mode 100644 UEFIFind/uefifind.cpp delete mode 100644 UEFIFind/uefifind.h delete mode 100644 UEFIFind/uefifind.pro delete mode 100644 UEFIFind/uefifind_main.cpp diff --git a/UEFIExtract/uefiextract.cpp b/UEFIExtract/uefiextract.cpp deleted file mode 100644 index 1fd2557..0000000 --- a/UEFIExtract/uefiextract.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* uefiextract.cpp - -Copyright (c) 2014, 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. - -*/ - -#include "uefiextract.h" - -UEFIExtract::UEFIExtract(QObject *parent) : - QObject(parent) -{ - ffsEngine = new FfsEngine(this); -} - -UEFIExtract::~UEFIExtract() -{ - delete ffsEngine; -} - -UINT8 UEFIExtract::init(const QString & path) -{ - fileInfo = QFileInfo(path); - - if (!fileInfo.exists()) - return ERR_FILE_OPEN; - - QFile inputFile; - inputFile.setFileName(path); - - if (!inputFile.open(QFile::ReadOnly)) - return ERR_FILE_OPEN; - - QByteArray buffer = inputFile.readAll(); - inputFile.close(); - - return ffsEngine->parseImageFile(buffer); -} - -UINT8 UEFIExtract::extract(QString guid) -{ - return ffsEngine->dump(ffsEngine->treeModel()->index(0, 0), fileInfo.fileName().append(".dump"), guid); -} \ No newline at end of file diff --git a/UEFIExtract/uefiextract.h b/UEFIExtract/uefiextract.h deleted file mode 100644 index 9cf9c40..0000000 --- a/UEFIExtract/uefiextract.h +++ /dev/null @@ -1,43 +0,0 @@ -/* uefiextract.h - -Copyright (c) 2014, 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. - -*/ - -#ifndef __UEFIEXTRACT_H__ -#define __UEFIEXTRACT_H__ - -#include -#include -#include -#include -#include - -#include "../basetypes.h" -#include "../ffsengine.h" - -class UEFIExtract : public QObject -{ - Q_OBJECT - -public: - explicit UEFIExtract(QObject *parent = 0); - ~UEFIExtract(); - - UINT8 init(const QString & path); - UINT8 extract(QString guid = QString()); - -private: - FfsEngine* ffsEngine; - QFileInfo fileInfo; - -}; - -#endif diff --git a/UEFIExtract/uefiextract.pro b/UEFIExtract/uefiextract.pro deleted file mode 100644 index bc72ff7..0000000 --- a/UEFIExtract/uefiextract.pro +++ /dev/null @@ -1,43 +0,0 @@ -QT += core -QT -= gui - -TARGET = UEFIExtract -TEMPLATE = app -CONFIG += console -CONFIG -= app_bundle -DEFINES += _CONSOLE - -SOURCES += uefiextract_main.cpp \ - uefiextract.cpp \ - ../types.cpp \ - ../descriptor.cpp \ - ../ffs.cpp \ - ../ffsengine.cpp \ - ../peimage.cpp \ - ../treeitem.cpp \ - ../treemodel.cpp \ - ../LZMA/LzmaCompress.c \ - ../LZMA/LzmaDecompress.c \ - ../LZMA/SDK/C/LzFind.c \ - ../LZMA/SDK/C/LzmaDec.c \ - ../LZMA/SDK/C/LzmaEnc.c \ - ../Tiano/EfiTianoDecompress.c \ - ../Tiano/EfiTianoCompress.c \ - ../Tiano/EfiTianoCompressLegacy.c - -HEADERS += uefiextract.h \ - ../basetypes.h \ - ../descriptor.h \ - ../gbe.h \ - ../me.h \ - ../ffs.h \ - ../peimage.h \ - ../types.h \ - ../ffsengine.h \ - ../treeitem.h \ - ../treemodel.h \ - ../LZMA/LzmaCompress.h \ - ../LZMA/LzmaDecompress.h \ - ../Tiano/EfiTianoDecompress.h \ - ../Tiano/EfiTianoCompress.h - diff --git a/UEFIExtract/uefiextract_main.cpp b/UEFIExtract/uefiextract_main.cpp deleted file mode 100644 index 5c98cc8..0000000 --- a/UEFIExtract/uefiextract_main.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* uefiextract_main.cpp - -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 -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. - -*/ -#include -#include -#include -#include -#include "uefiextract.h" - -int main(int argc, char *argv[]) -{ - QCoreApplication a(argc, argv); - a.setOrganizationName("LongSoft"); - a.setOrganizationDomain("longsoft.me"); - a.setApplicationName("UEFIExtract"); - - UEFIExtract w; - UINT8 result = ERR_SUCCESS; - UINT32 returned = 0; - - if (a.arguments().length() > 32) { - std::cout << "Too many arguments" << std::endl; - return 1; - } - - if (a.arguments().length() > 1 ) { - if (w.init(a.arguments().at(1))) - return 1; - - if (a.arguments().length() == 2) { - result = w.extract(); - if (result) - return 2; - } - else { - for (int i = 2; i < a.arguments().length(); i++) { - result = w.extract(a.arguments().at(i)); - if (result) - returned |= (1 << (i - 1)); - } - return returned; - } - - } - else { - 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; - } -} diff --git a/UEFIFind/uefifind.cpp b/UEFIFind/uefifind.cpp deleted file mode 100644 index 2adfafb..0000000 --- a/UEFIFind/uefifind.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* uefifind.cpp - -Copyright (c) 2014, 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. - -*/ - -#include "uefifind.h" - -UEFIFind::UEFIFind(QObject *parent) : - QObject(parent) -{ - ffsEngine = new FfsEngine(this); - model = ffsEngine->treeModel(); - initDone = false; -} - -UEFIFind::~UEFIFind() -{ - model = NULL; - delete ffsEngine; -} - -UINT8 UEFIFind::init(const QString & path) -{ - UINT8 result; - - fileInfo = QFileInfo(path); - - if (!fileInfo.exists()) - return ERR_FILE_OPEN; - - QFile inputFile; - inputFile.setFileName(path); - - if (!inputFile.open(QFile::ReadOnly)) - return ERR_FILE_OPEN; - - QByteArray buffer = inputFile.readAll(); - inputFile.close(); - - result = ffsEngine->parseImageFile(buffer); - if (result) - return result; - - initDone = true; - return ERR_SUCCESS; -} - -QString UEFIFind::guidToQString(const UINT8* guid) -{ - const UINT32 u32 = *(const UINT32*)guid; - const UINT16 u16_1 = *(const UINT16*)(guid + 4); - const UINT16 u16_2 = *(const UINT16*)(guid + 6); - const UINT8 u8_1 = *(const UINT8*)(guid + 8); - const UINT8 u8_2 = *(const UINT8*)(guid + 9); - const UINT8 u8_3 = *(const UINT8*)(guid + 10); - const UINT8 u8_4 = *(const UINT8*)(guid + 11); - const UINT8 u8_5 = *(const UINT8*)(guid + 12); - const UINT8 u8_6 = *(const UINT8*)(guid + 13); - const UINT8 u8_7 = *(const UINT8*)(guid + 14); - const UINT8 u8_8 = *(const UINT8*)(guid + 15); - - return QString("%1-%2-%3-%4%5-%6%7%8%9%10%11").hexarg2(u32, 8).hexarg2(u16_1, 4).hexarg2(u16_2, 4).hexarg2(u8_1, 2).hexarg2(u8_2, 2) - .hexarg2(u8_3, 2).hexarg2(u8_4, 2).hexarg2(u8_5, 2).hexarg2(u8_6, 2).hexarg2(u8_7, 2).hexarg2(u8_8, 2); -} - -UINT8 UEFIFind::find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result) -{ - QModelIndex root = model->index(0, 0); - QSet > files; - - result.clear(); - - UINT8 returned = findFileRecursive(root, hexPattern, mode, files); - if (returned) - return returned; - - if (count) { - if (files.count()) - result.append(QString("%1\n").arg(files.count())); - return ERR_SUCCESS; - } - - QPair indexes; - Q_FOREACH(indexes, files) { - QByteArray data = model->header(indexes.first).left(16); - result.append(guidToQString((const UINT8*)data.constData())); - - // Special case of freeform subtype GUID files - if (indexes.second.isValid() && model->subtype(indexes.second) == EFI_SECTION_FREEFORM_SUBTYPE_GUID) { - data = model->header(indexes.second).left(sizeof(EFI_FREEFORM_SUBTYPE_GUID_SECTION)); - result.append(" ").append(guidToQString((const UINT8*)data.constData() + sizeof(EFI_COMMON_SECTION_HEADER))); - } - - result.append("\n"); - - } - return ERR_SUCCESS; -} - -UINT8 UEFIFind::findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet > & files) -{ - if (!index.isValid()) - return ERR_SUCCESS; - - if (hexPattern.isEmpty()) - return ERR_INVALID_PARAMETER; - - // Check for "all substrings" pattern - if (hexPattern.count('.') == hexPattern.length()) - return ERR_SUCCESS; - - bool hasChildren = (model->rowCount(index) > 0); - for (int i = 0; i < model->rowCount(index); i++) { - findFileRecursive(index.child(i, index.column()), hexPattern, mode, files); - } - - QByteArray data; - if (hasChildren) { - if (mode == SEARCH_MODE_HEADER || mode == SEARCH_MODE_ALL) - data.append(model->header(index)); - } - else { - if (mode == SEARCH_MODE_HEADER) - data.append(model->header(index)); - else if (mode == SEARCH_MODE_BODY) - data.append(model->body(index)); - else - data.append(model->header(index)).append(model->body(index)); - } - - QString hexBody = QString(data.toHex()); - QRegExp regexp = QRegExp(QString(hexPattern), Qt::CaseInsensitive); - INT32 offset = regexp.indexIn(hexBody); - while (offset >= 0) { - if (offset % 2 == 0) { - if (model->type(index) != Types::File) { - QModelIndex ffs = model->findParentOfType(index, Types::File); - if (model->type(index) == Types::Section && model->subtype(index) == EFI_SECTION_FREEFORM_SUBTYPE_GUID) - files.insert(QPair(ffs, index)); - else - files.insert(QPair(ffs, QModelIndex())); - } - else - files.insert(QPair(index, QModelIndex())); - - break; - } - offset = regexp.indexIn(hexBody, offset + 1); - } - - return ERR_SUCCESS; -} \ No newline at end of file diff --git a/UEFIFind/uefifind.h b/UEFIFind/uefifind.h deleted file mode 100644 index 69eee52..0000000 --- a/UEFIFind/uefifind.h +++ /dev/null @@ -1,52 +0,0 @@ -/* uefifind.h - -Copyright (c) 2014, 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. - -*/ - -#ifndef __UEFIFIND_H__ -#define __UEFIFIND_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../basetypes.h" -#include "../ffsengine.h" -#include "../ffs.h" - -class UEFIFind : public QObject -{ - Q_OBJECT - -public: - explicit UEFIFind(QObject *parent = 0); - ~UEFIFind(); - - UINT8 init(const QString & path); - UINT8 find(const UINT8 mode, const bool count, const QString & hexPattern, QString & result); - -private: - UINT8 findFileRecursive(const QModelIndex index, const QString & hexPattern, const UINT8 mode, QSet > & files); - QString guidToQString(const UINT8* guid); - - FfsEngine* ffsEngine; - TreeModel* model; - QFileInfo fileInfo; - bool initDone; -}; - -#endif diff --git a/UEFIFind/uefifind.pro b/UEFIFind/uefifind.pro deleted file mode 100644 index 177c742..0000000 --- a/UEFIFind/uefifind.pro +++ /dev/null @@ -1,43 +0,0 @@ -QT += core -QT -= gui - -TARGET = UEFIFind -TEMPLATE = app -CONFIG += console -CONFIG -= app_bundle -DEFINES += _CONSOLE _DISABLE_ENGINE_MESSAGES - -SOURCES += uefifind_main.cpp \ - uefifind.cpp \ - ../types.cpp \ - ../descriptor.cpp \ - ../ffs.cpp \ - ../ffsengine.cpp \ - ../peimage.cpp \ - ../treeitem.cpp \ - ../treemodel.cpp \ - ../LZMA/LzmaCompress.c \ - ../LZMA/LzmaDecompress.c \ - ../LZMA/SDK/C/LzFind.c \ - ../LZMA/SDK/C/LzmaDec.c \ - ../LZMA/SDK/C/LzmaEnc.c \ - ../Tiano/EfiTianoDecompress.c \ - ../Tiano/EfiTianoCompress.c \ - ../Tiano/EfiTianoCompressLegacy.c - -HEADERS += uefifind.h \ - ../basetypes.h \ - ../descriptor.h \ - ../gbe.h \ - ../me.h \ - ../ffs.h \ - ../peimage.h \ - ../types.h \ - ../ffsengine.h \ - ../treeitem.h \ - ../treemodel.h \ - ../LZMA/LzmaCompress.h \ - ../LZMA/LzmaDecompress.h \ - ../Tiano/EfiTianoDecompress.h \ - ../Tiano/EfiTianoCompress.h - diff --git a/UEFIFind/uefifind_main.cpp b/UEFIFind/uefifind_main.cpp deleted file mode 100644 index ebe87b7..0000000 --- a/UEFIFind/uefifind_main.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* uefifind_main.cpp - -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. - -*/ -#include -#include -#include "uefifind.h" - -int main(int argc, char *argv[]) -{ - QCoreApplication a(argc, argv); - a.setOrganizationName("CodeRush"); - a.setOrganizationDomain("coderush.me"); - a.setApplicationName("UEFIFind"); - - UEFIFind w; - UINT8 result; - - if (a.arguments().length() == 5) { - result = w.init(a.arguments().at(4)); - if (result) - return result; - - // Get search mode - UINT8 mode; - if (a.arguments().at(1) == QString("header")) - mode = SEARCH_MODE_HEADER; - else if (a.arguments().at(1) == QString("body")) - mode = SEARCH_MODE_BODY; - else if (a.arguments().at(1) == QString("all")) - mode = SEARCH_MODE_ALL; - else - return ERR_INVALID_PARAMETER; - - // Get result type - bool count; - if (a.arguments().at(2) == QString("list")) - count = false; - else if (a.arguments().at(2) == QString("count")) - count = true; - else - return ERR_INVALID_PARAMETER; - - // Go find the supplied pattern - QString found; - result = w.find(mode, count, a.arguments().at(3), found); - if (result) - return result; - - // Nothing was found - if (found.isEmpty()) - return ERR_ITEM_NOT_FOUND; - - // Print result - std::cout << found.toStdString(); - return ERR_SUCCESS; - } - else { - std::cout << "UEFIFind 0.3.4" << std::endl << std::endl << - "Usage: uefifind {header | body | all} {list | count} pattern imagefile\n"; - return ERR_INVALID_PARAMETER; - } -} - diff --git a/macbuild.sh b/macbuild.sh index d3e9964..2675323 100755 --- a/macbuild.sh +++ b/macbuild.sh @@ -19,8 +19,6 @@ export PATH="/opt/qt56sm/bin:$PATH" echo "Attempting to build UEFITool for macOS..." UEFITOOL_VER=$(cat uefitool.cpp | grep ^version | cut -d'"' -f2) -UEFIEXTRACT_VER=$(cat UEFIExtract/uefiextract_main.cpp | grep '"UEFIExtract [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) -UEFIFIND_VER=$(cat UEFIFind/uefifind_main.cpp | grep '"UEFIFind [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) UEFIPATCH_VER=$(cat UEFIPatch/uefipatch_main.cpp | grep '"UEFIPatch [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) UEFIREPLACE_VER=$(cat UEFIReplace/uefireplace_main.cpp | grep '"UEFIReplace [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) @@ -59,8 +57,6 @@ rm -rf dist mkdir -p dist || exit 1 build_tool UEFITool "$UEFITOOL_VER" uefitool.pro -build_tool UEFIExtract "$UEFIEXTRACT_VER" uefiextract.pro -build_tool UEFIFind "$UEFIFIND_VER" uefifind.pro build_tool UEFIPatch "$UEFIPATCH_VER" uefipatch.pro patches.txt build_tool UEFIReplace "$UEFIREPLACE_VER" uefireplace.pro From 5e81b20c85be2c89df8f06e7d1e4137f3a76a614 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Fri, 4 May 2018 21:49:56 +0300 Subject: [PATCH 40/64] Version bump --- UEFIPatch/uefipatch_main.cpp | 2 +- UEFIReplace/uefireplace_main.cpp | 2 +- uefitool.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 1b3063f..3edb0f6 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1)); } else { - std::cout << "UEFIPatch 0.3.13 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.14 - 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; diff --git a/UEFIReplace/uefireplace_main.cpp b/UEFIReplace/uefireplace_main.cpp index 8ec15a1..6d53a2b 100644 --- a/UEFIReplace/uefireplace_main.cpp +++ b/UEFIReplace/uefireplace_main.cpp @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) QStringList args = a.arguments(); if (args.length() < 5) { - std::cout << "UEFIReplace 0.1.1 - UEFI image file replacement utility" << std::endl << std::endl << + std::cout << "UEFIReplace 0.1.2 - UEFI image file replacement utility" << std::endl << std::endl << "Usage: UEFIReplace image_file guid section_type contents_file" << std::endl; return ERR_SUCCESS; } diff --git a/uefitool.cpp b/uefitool.cpp index c4a84d7..c2eac33 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.23.0")) +version(tr("0.23.1")) { clipboard = QApplication::clipboard(); From 539408c6675303a6941f8bb1b8b114c7de8efe08 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 6 May 2018 11:31:39 +0300 Subject: [PATCH 41/64] Recognise B360MHD3.F3 descriptor version --- ffsengine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 3d09216..8831391 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -3039,7 +3039,8 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) { // Old descriptor descriptorVersion = 1; } - else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ) { // Skylake+ descriptor + else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ || // Skylake+ descriptor + componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_50MHZ_30MHZ) { // Coffee Lake+ descriptor descriptorVersion = 2; ecBegin = calculateRegionOffset(regionSection->EcBase); ecEnd = ecBegin + calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); From 03274ff47c7e70d2d4de44d287d95d974f26c5ef Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 6 May 2018 15:11:21 +0300 Subject: [PATCH 42/64] Properly read Intel descriptor version, thx @platomav --- descriptor.h | 18 ++++++++++++++++++ ffsengine.cpp | 36 ++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/descriptor.h b/descriptor.h index 5bdefd5..1c496db 100644 --- a/descriptor.h +++ b/descriptor.h @@ -31,6 +31,22 @@ typedef struct _FLASH_DESCRIPTOR_HEADER { // Descriptor region size #define FLASH_DESCRIPTOR_SIZE 0x1000 +// Descriptor version was reserved in older firmware +#define FLASH_DESCRIPTOR_VERSION_INVALID 0xFFFFFFFF + +// Descriptor version present in Coffee Lake and newer +typedef struct _FLASH_DESCRIPTOR_VERSION_V3 { + UINT32 Reserved : 14; + UINT32 VersionMinor : 7; + UINT32 VersionMajor : 11; +} FLASH_DESCRIPTOR_VERSION_V3; + +// Descripror version +typedef union _FLASH_DESCRIPTOR_VERSION { + UINT32 RawValue; + FLASH_DESCRIPTOR_VERSION_V3 V3; +} FLASH_DESCRIPTOR_VERSION; + // Descriptor map // Base fields are storing bits [11:4] of actual base addresses, all other bits are 0 typedef struct _FLASH_DESCRIPTOR_MAP { @@ -51,6 +67,8 @@ typedef struct _FLASH_DESCRIPTOR_MAP { UINT32 ProcStrapsBase : 8; UINT32 NumberOfProcStraps : 8; // One-based number of UINT32s to read as processor straps, min=0, max=255 (1 Kb) UINT32: 16; + // FLMAP 3 + FLASH_DESCRIPTOR_VERSION Version; // Reserved prior to v3 } FLASH_DESCRIPTOR_MAP; #define FLASH_DESCRIPTOR_MAX_BASE 0xE0 diff --git a/ffsengine.cpp b/ffsengine.cpp index 8831391..94bca3d 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -3033,23 +3033,35 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec UINT32 ecBegin = 0; UINT32 ecEnd = 0; - const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), 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; + if (descriptorMap->Version.RawValue != FLASH_DESCRIPTOR_VERSION_INVALID) { + // Normally this is 1.0, check only the major value to avoid unnecessary future incompatibilities. + if (descriptorMap->Version.V3.VersionMajor != 1) { + msg(tr("reconstructIntelImage: unknown descriptor version: %1.%2").arg(descriptorMap->Version.V3.VersionMajor) + .arg(descriptorMap->Version.V3.VersionMinor)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + descriptorVersion = 3; } - else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ || // Skylake+ descriptor - componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_50MHZ_30MHZ) { // Coffee Lake+ descriptor - descriptorVersion = 2; + else { + // Check legacy descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency + const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->ComponentBase); + if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) { // Old descriptor + descriptorVersion = 1; + } + else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ) { // Skylake+ descriptor + descriptorVersion = 2; + } + else { + msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); + return ERR_INVALID_FLASH_DESCRIPTOR; + } + } + + if (descriptorVersion >= 2) { ecBegin = calculateRegionOffset(regionSection->EcBase); ecEnd = ecBegin + calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); } - else { - msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); - return ERR_INVALID_FLASH_DESCRIPTOR; - } - UINT32 offset = descriptor.size(); // Reconstruct other regions From acb1a4d09920709a4a78ad236b115548e90ea7ed Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 6 May 2018 15:26:53 +0300 Subject: [PATCH 43/64] Fix Intel descriptor version parsing at reading --- ffsengine.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 94bca3d..71605c2 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -286,10 +286,14 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8(descriptor, descriptorMap->RegionBase); const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8(descriptor, descriptorMap->ComponentBase); + UINT8 descriptorVersion = 0; + if (descriptorMap->Version.RawValue != FLASH_DESCRIPTOR_VERSION_INVALID) // Kaby Lake+ descriptor + descriptorVersion = 3; // Check descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency - UINT8 descriptorVersion = 2; // Skylake+ by default - if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) // Old descriptor + else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) // Old descriptor descriptorVersion = 1; + else // Skylake+ descriptor + descriptorVersion = 2; // ME region QByteArray me; @@ -356,7 +360,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in QByteArray ec; UINT32 ecBegin = 0; UINT32 ecEnd = 0; - if (descriptorVersion == 2) { + if (descriptorVersion >= 2) { if (regionSection->EcLimit) { ecBegin = calculateRegionOffset(regionSection->EcBase); ecEnd = calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); @@ -383,7 +387,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, descriptor region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion == 2 && hasIntersection(descriptorBegin, descriptorEnd, ecBegin, ecEnd)) { + if (descriptorVersion >= 2 && hasIntersection(descriptorBegin, descriptorEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, descriptor region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -400,7 +404,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, GbE region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion == 2 && hasIntersection(gbeBegin, gbeEnd, ecBegin, ecEnd)) { + if (descriptorVersion >= 2 && hasIntersection(gbeBegin, gbeEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, GbE region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -413,7 +417,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, ME region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion == 2 && hasIntersection(meBegin, meEnd, ecBegin, ecEnd)) { + if (descriptorVersion >= 2 && hasIntersection(meBegin, meEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, ME region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -422,12 +426,12 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, BIOS region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion == 2 && hasIntersection(biosBegin, biosEnd, ecBegin, ecEnd)) { + if (descriptorVersion >= 2 && hasIntersection(biosBegin, biosEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, BIOS region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } // PDR - if (descriptorVersion == 2 && hasIntersection(pdrBegin, pdrEnd, ecBegin, ecEnd)) { + if (descriptorVersion >= 2 && hasIntersection(pdrBegin, pdrEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, PDR region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -470,7 +474,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in offsets.append(pdrBegin); info += tr("\nPDR region offset: %1h").hexarg(pdrBegin); } - if (descriptorVersion == 2 && regionSection->EcLimit) { + if (descriptorVersion >= 2 && regionSection->EcLimit) { offsets.append(ecBegin); info += tr("\nEC region offset: %1h").hexarg(ecBegin); } @@ -504,7 +508,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No ") .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No "); } - else if (descriptorVersion == 2) { + else if (descriptorVersion >= 2) { const FLASH_DESCRIPTOR_MASTER_SECTION_V2* masterSection = (const FLASH_DESCRIPTOR_MASTER_SECTION_V2*)calculateAddress8(descriptor, descriptorMap->MasterBase); info += tr("\nRegion access settings:"); info += tr("\nBIOS: %1h %2h ME: %3h %4h\nGbE: %5h %6h EC: %7h %8h") @@ -580,7 +584,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in result = parsePdrRegion(pdr, pdrIndex, index); } // Parse EC region - else if (descriptorVersion == 2 && offsets.at(i) == ecBegin) { + else if (descriptorVersion >= 2 && offsets.at(i) == ecBegin) { QModelIndex ecIndex; result = parseEcRegion(ec, ecIndex, index); } @@ -599,7 +603,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in IntelDataEnd = biosEnd; else if (LastRegionOffset == pdrBegin) IntelDataEnd = pdrEnd; - else if (descriptorVersion == 2 && LastRegionOffset == ecBegin) + else if (descriptorVersion >= 2 && LastRegionOffset == ecBegin) IntelDataEnd = ecEnd; if (IntelDataEnd > (UINT32)intelImage.size()) { // Image file is truncated From 3993bd7090273a6be8b447f12a01bea0cc0e451a Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 6 May 2018 23:14:30 +0300 Subject: [PATCH 44/64] Improve descriptor version handling --- descriptor.h | 17 +++++------ ffsengine.cpp | 78 ++++++++++++++++++++++++--------------------------- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/descriptor.h b/descriptor.h index 1c496db..a54d4a8 100644 --- a/descriptor.h +++ b/descriptor.h @@ -33,18 +33,15 @@ typedef struct _FLASH_DESCRIPTOR_HEADER { // Descriptor version was reserved in older firmware #define FLASH_DESCRIPTOR_VERSION_INVALID 0xFFFFFFFF +// The only known version found in Coffee Lake +#define FLASH_DESCRIPTOR_VERSION_MAJOR 1 +#define FLASH_DESCRIPTOR_VERSION_MINOR 0 // Descriptor version present in Coffee Lake and newer -typedef struct _FLASH_DESCRIPTOR_VERSION_V3 { +typedef struct _FLASH_DESCRIPTOR_VERSION { UINT32 Reserved : 14; - UINT32 VersionMinor : 7; - UINT32 VersionMajor : 11; -} FLASH_DESCRIPTOR_VERSION_V3; - -// Descripror version -typedef union _FLASH_DESCRIPTOR_VERSION { - UINT32 RawValue; - FLASH_DESCRIPTOR_VERSION_V3 V3; + UINT32 Minor : 7; + UINT32 Major : 11; } FLASH_DESCRIPTOR_VERSION; // Descriptor map @@ -68,7 +65,7 @@ typedef struct _FLASH_DESCRIPTOR_MAP { UINT32 NumberOfProcStraps : 8; // One-based number of UINT32s to read as processor straps, min=0, max=255 (1 Kb) UINT32: 16; // FLMAP 3 - FLASH_DESCRIPTOR_VERSION Version; // Reserved prior to v3 + UINT32 DescriptorVersion; // Reserved prior to Coffee Lake } FLASH_DESCRIPTOR_MAP; #define FLASH_DESCRIPTOR_MAX_BASE 0xE0 diff --git a/ffsengine.cpp b/ffsengine.cpp index 71605c2..21d72ee 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -286,14 +286,10 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in const FLASH_DESCRIPTOR_REGION_SECTION* regionSection = (const FLASH_DESCRIPTOR_REGION_SECTION*)calculateAddress8(descriptor, descriptorMap->RegionBase); const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8(descriptor, descriptorMap->ComponentBase); - UINT8 descriptorVersion = 0; - if (descriptorMap->Version.RawValue != FLASH_DESCRIPTOR_VERSION_INVALID) // Kaby Lake+ descriptor - descriptorVersion = 3; - // Check descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency - else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) // Old descriptor + // Check for legacy descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency + UINT8 descriptorVersion = 2; // Skylake+ descriptor + if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) // Legacy descriptor descriptorVersion = 1; - else // Skylake+ descriptor - descriptorVersion = 2; // ME region QByteArray me; @@ -360,7 +356,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in QByteArray ec; UINT32 ecBegin = 0; UINT32 ecEnd = 0; - if (descriptorVersion >= 2) { + if (descriptorVersion == 2) { if (regionSection->EcLimit) { ecBegin = calculateRegionOffset(regionSection->EcBase); ecEnd = calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); @@ -387,7 +383,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, descriptor region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion >= 2 && hasIntersection(descriptorBegin, descriptorEnd, ecBegin, ecEnd)) { + if (descriptorVersion == 2 && hasIntersection(descriptorBegin, descriptorEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, descriptor region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -404,7 +400,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, GbE region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion >= 2 && hasIntersection(gbeBegin, gbeEnd, ecBegin, ecEnd)) { + if (descriptorVersion == 2 && hasIntersection(gbeBegin, gbeEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, GbE region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -417,7 +413,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, ME region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion >= 2 && hasIntersection(meBegin, meEnd, ecBegin, ecEnd)) { + if (descriptorVersion == 2 && hasIntersection(meBegin, meEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, ME region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -426,12 +422,12 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in msg(tr("parseIntelImage: descriptor parsing failed, BIOS region has intersection with PDR region")); return ERR_INVALID_FLASH_DESCRIPTOR; } - if (descriptorVersion >= 2 && hasIntersection(biosBegin, biosEnd, ecBegin, ecEnd)) { + if (descriptorVersion == 2 && hasIntersection(biosBegin, biosEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, BIOS region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } // PDR - if (descriptorVersion >= 2 && hasIntersection(pdrBegin, pdrEnd, ecBegin, ecEnd)) { + if (descriptorVersion == 2 && hasIntersection(pdrBegin, pdrEnd, ecBegin, ecEnd)) { msg(tr("parseIntelImage: descriptor parsing failed, PDR region has intersection with EC region")); return ERR_INVALID_FLASH_DESCRIPTOR; } @@ -474,7 +470,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in offsets.append(pdrBegin); info += tr("\nPDR region offset: %1h").hexarg(pdrBegin); } - if (descriptorVersion >= 2 && regionSection->EcLimit) { + if (descriptorVersion == 2 && regionSection->EcLimit) { offsets.append(ecBegin); info += tr("\nEC region offset: %1h").hexarg(ecBegin); } @@ -508,7 +504,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No ") .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_PDR ? "Yes " : "No "); } - else if (descriptorVersion >= 2) { + else if (descriptorVersion == 2) { const FLASH_DESCRIPTOR_MASTER_SECTION_V2* masterSection = (const FLASH_DESCRIPTOR_MASTER_SECTION_V2*)calculateAddress8(descriptor, descriptorMap->MasterBase); info += tr("\nRegion access settings:"); info += tr("\nBIOS: %1h %2h ME: %3h %4h\nGbE: %5h %6h EC: %7h %8h") @@ -540,6 +536,17 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in info += tr("\nEC %1 %2") .arg(masterSection->BiosRead & FLASH_DESCRIPTOR_REGION_ACCESS_EC ? "Yes " : "No ") .arg(masterSection->BiosWrite & FLASH_DESCRIPTOR_REGION_ACCESS_EC ? "Yes " : "No "); + + // Prepend descriptor version if present + if (descriptorMap->DescriptorVersion != FLASH_DESCRIPTOR_VERSION_INVALID) { + const FLASH_DESCRIPTOR_VERSION* version = (const FLASH_DESCRIPTOR_VERSION*)&descriptorMap->DescriptorVersion; + QString versionStr = tr("Flash descriptor version: %1.%2").arg(version->Major).arg(version->Minor); + if (version->Major != FLASH_DESCRIPTOR_VERSION_MAJOR || version->Minor != FLASH_DESCRIPTOR_VERSION_MINOR) { + versionStr += tr(", unknown"); + msg(tr("parseIntelImage: unknown flash descriptor version %1.%2").arg(version->Major).arg(version->Minor)); + } + info = versionStr + "\n" + info; + } } // VSCC table @@ -584,7 +591,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in result = parsePdrRegion(pdr, pdrIndex, index); } // Parse EC region - else if (descriptorVersion >= 2 && offsets.at(i) == ecBegin) { + else if (descriptorVersion == 2 && offsets.at(i) == ecBegin) { QModelIndex ecIndex; result = parseEcRegion(ec, ecIndex, index); } @@ -603,7 +610,7 @@ UINT8 FfsEngine::parseIntelImage(const QByteArray & intelImage, QModelIndex & in IntelDataEnd = biosEnd; else if (LastRegionOffset == pdrBegin) IntelDataEnd = pdrEnd; - else if (descriptorVersion >= 2 && LastRegionOffset == ecBegin) + else if (descriptorVersion == 2 && LastRegionOffset == ecBegin) IntelDataEnd = ecEnd; if (IntelDataEnd > (UINT32)intelImage.size()) { // Image file is truncated @@ -3037,32 +3044,21 @@ UINT8 FfsEngine::reconstructIntelImage(const QModelIndex& index, QByteArray& rec UINT32 ecBegin = 0; UINT32 ecEnd = 0; - UINT8 descriptorVersion = 0; - if (descriptorMap->Version.RawValue != FLASH_DESCRIPTOR_VERSION_INVALID) { - // Normally this is 1.0, check only the major value to avoid unnecessary future incompatibilities. - if (descriptorMap->Version.V3.VersionMajor != 1) { - msg(tr("reconstructIntelImage: unknown descriptor version: %1.%2").arg(descriptorMap->Version.V3.VersionMajor) - .arg(descriptorMap->Version.V3.VersionMinor)); - return ERR_INVALID_FLASH_DESCRIPTOR; - } - descriptorVersion = 3; - } - else { - // Check legacy descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency - const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->ComponentBase); - if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) { // Old descriptor - descriptorVersion = 1; - } - else if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_17MHZ) { // Skylake+ descriptor - descriptorVersion = 2; - } - else { - msg(tr("reconstructIntelImage: unknown descriptor version with ReadClockFrequency %1h").hexarg(componentSection->FlashParameters.ReadClockFrequency)); - return ERR_INVALID_FLASH_DESCRIPTOR; - } + // Check for legacy descriptor version by getting hardcoded value of FlashParameters.ReadClockFrequency + UINT8 descriptorVersion = 2; // Skylake+ descriptor + const FLASH_DESCRIPTOR_COMPONENT_SECTION* componentSection = (const FLASH_DESCRIPTOR_COMPONENT_SECTION*)calculateAddress8((const UINT8*)descriptor.constData(), descriptorMap->ComponentBase); + if (componentSection->FlashParameters.ReadClockFrequency == FLASH_FREQUENCY_20MHZ) // Legacy descriptor + descriptorVersion = 1; + + if (descriptorVersion == 2 && descriptorMap->DescriptorVersion != FLASH_DESCRIPTOR_VERSION_INVALID) { + // Warn about incompatible version descriptor in case it is different. + const FLASH_DESCRIPTOR_VERSION *version = (const FLASH_DESCRIPTOR_VERSION *)&descriptorMap->DescriptorVersion; + if (version->Major != FLASH_DESCRIPTOR_VERSION_MAJOR || version->Minor != FLASH_DESCRIPTOR_VERSION_MINOR) + msg(tr("reconstructIntelImage: discovered unexpected %1.%2 descriptor version, trying to continue...") + .arg(version->Major).arg(version->Minor)); } - if (descriptorVersion >= 2) { + if (descriptorVersion == 2) { ecBegin = calculateRegionOffset(regionSection->EcBase); ecEnd = ecBegin + calculateRegionSize(regionSection->EcBase, regionSection->EcLimit); } From e25ed49b277e1f430c6505b65220b9797daa1035 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Mon, 7 May 2018 08:01:09 +0300 Subject: [PATCH 45/64] Do not try to rebase removed sections, fixes #92 --- ffsengine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index 21d72ee..2ea6bb0 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -2448,7 +2448,8 @@ void FfsEngine::rebasePeiFiles(const QModelIndex & index) // If section stores PE32 or TE image if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE) // Set rebase action - model->setAction(currentSectionIndex, Actions::Rebase); + if (model->action(currentSectionIndex) != Actions::Remove) + model->setAction(currentSectionIndex, Actions::Rebase); } } } From 3395cc7a1a4799fcfc8ffd54a55375f0a1cb1cd5 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Mon, 7 May 2018 21:36:24 +0300 Subject: [PATCH 46/64] Add Linux x86-64 CI support --- .travis.yml | 26 +++++++++++------ macbuild.sh | 63 ---------------------------------------- unixbuild.sh | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 72 deletions(-) delete mode 100755 macbuild.sh create mode 100755 unixbuild.sh diff --git a/.travis.yml b/.travis.yml index 99a9946..91f88f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ matrix: compiler: clang script: - - ./macbuild.sh + - ./unixbuild.sh deploy: provider: releases @@ -20,25 +20,33 @@ matrix: tags: true - os: linux + dist: trusty compiler: clang before_install: - - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - sudo apt-get update -qq - - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev + - sudo apt-get install -qq qt5-default qt5-qmake qtbase5-dev-tools cmake script: - - qmake -qt=qt5 uefitool.pro - - make + - ./unixbuild.sh - os: linux + dist: trusty compiler: gcc before_install: - - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - sudo apt-get update -qq - - sudo apt-get install -qq qt5-qmake qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev + - sudo apt-get install -qq qt5-default qt5-qmake qtbase5-dev-tools cmake script: - - qmake -qt=qt5 uefitool.pro - - make + - ./unixbuild.sh + + deploy: + provider: releases + skip_cleanup: true + file: "dist/*.zip" + file_glob: true + api_key: + secure: "WjYd93lVLKHULBpUXS/WtGrkdXyAwxHOUnLJotyDmQipAQP5Ox7Kj12JwkSJGEmVOEdcbIQJyi0QxPjn1UYbYsAt6Op8zrjnYLS4G4fMdBtcxprWzid85uTW7oAAIFs7ygMVhpzxRKpu70yNb683vbThqNmaOu6RyG9aJOLtPAg=" + on: + tags: true diff --git a/macbuild.sh b/macbuild.sh deleted file mode 100755 index 2675323..0000000 --- a/macbuild.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash - -if [ ! -d /opt/qt56sm ]; then - curl -L -o /tmp/qt-5.6.3-static-mac.zip https://github.com/distdb/qtbuilds/blob/master/qt-5.6.3-static-mac.zip?raw=true || exit 1 - qtsum=$(shasum -a 256 /tmp/qt-5.6.3-static-mac.zip | cut -f1 -d' ') - qtexpsum="214d22d8572ea6162753c8dd251d79275f3b22d49204718c637d722409e0cfcb" - if [ "$qtsum" != "$qtexpsum" ]; then - echo "Qt hash $qtsum does not match $qtexpsum" - exit 1 - fi - sudo mkdir -p /opt || exit 1 - cd /opt || exit 1 - sudo unzip -q /tmp/qt-5.6.3-static-mac.zip || exit 1 - cd - || exit 1 -fi - -export PATH="/opt/qt56sm/bin:$PATH" - -echo "Attempting to build UEFITool for macOS..." - -UEFITOOL_VER=$(cat uefitool.cpp | grep ^version | cut -d'"' -f2) -UEFIPATCH_VER=$(cat UEFIPatch/uefipatch_main.cpp | grep '"UEFIPatch [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) -UEFIREPLACE_VER=$(cat UEFIReplace/uefireplace_main.cpp | grep '"UEFIReplace [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) - -build_tool() { - echo "Building $1 $2" - # Check version - if [ "$(echo "$2" | grep '^[0-9]*\.[0-9]*\.[0-9]*$')" != "$2" ]; then - echo "Invalid $1 version!" - exit 1 - fi - # Tools are in subdirectories - if [ "$1" != "UEFITool" ]; then - cd "$1" || exit 1 - fi - - # Build - qmake $3 QMAKE_CXXFLAGS+=-flto QMAKE_LFLAGS+=-flto CONFIG+=optimize_size || exit 1 - make || exit 1 - - # Archive - if [ "$1" = "UEFITool" ]; then - strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1 - zip -qry dist/"UEFITool_${UEFITOOL_VER}_mac.zip" UEFITool.app "${4}" || exit 1 - else - strip -x "$1" || exit 1 - zip -qry ../dist/"${1}_${2}_mac.zip" "${1}" "${4}" || exit 1 - fi - - # Return to parent - if [ "$1" != "UEFITool" ]; then - cd - || exit 1 - fi -} - -rm -rf dist -mkdir -p dist || exit 1 - -build_tool UEFITool "$UEFITOOL_VER" uefitool.pro -build_tool UEFIPatch "$UEFIPATCH_VER" uefipatch.pro patches.txt -build_tool UEFIReplace "$UEFIREPLACE_VER" uefireplace.pro - -exit 0 diff --git a/unixbuild.sh b/unixbuild.sh new file mode 100755 index 0000000..d54b077 --- /dev/null +++ b/unixbuild.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +UTARGET=$(uname) + +if [ "$UTARGET" = "Darwin" ]; then + export UPLATFORM="mac" +elif [ "$UTARGET" = "Linux" ]; then + export UPLATFORM="linux_$(uname -m)" +else + # Fallback to something... + export UPLATFORM="$UTARGET" +fi + +if [ "$UPLATFORM" = "mac" ]; then + if [ ! -d /opt/qt56sm ]; then + curl -L -o /tmp/qt-5.6.3-static-mac.zip https://github.com/distdb/qtbuilds/blob/master/qt-5.6.3-static-mac.zip?raw=true || exit 1 + qtsum=$(shasum -a 256 /tmp/qt-5.6.3-static-mac.zip | cut -f1 -d' ') + qtexpsum="214d22d8572ea6162753c8dd251d79275f3b22d49204718c637d722409e0cfcb" + if [ "$qtsum" != "$qtexpsum" ]; then + echo "Qt hash $qtsum does not match $qtexpsum" + exit 1 + fi + sudo mkdir -p /opt || exit 1 + cd /opt || exit 1 + sudo unzip -q /tmp/qt-5.6.3-static-mac.zip || exit 1 + cd - || exit 1 + fi + + export PATH="/opt/qt56sm/bin:$PATH" +fi + +echo "Attempting to build UEFITool NE for ${UPLATFORM}..." + +UEFITOOL_VER=$(cat uefitool.cpp | grep ^version | cut -d'"' -f2) +UEFIPATCH_VER=$(cat UEFIPatch/uefipatch_main.cpp | grep '"UEFIPatch [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) +UEFIREPLACE_VER=$(cat UEFIReplace/uefireplace_main.cpp | grep '"UEFIReplace [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) + +build_tool() { + echo "Building $1 $2" + # Check version + if [ "$(echo "$2" | grep '^[0-9]*\.[0-9]*\.[0-9]*$')" != "$2" ]; then + echo "Invalid $1 version!" + exit 1 + fi + # Tools are in subdirectories + if [ "$1" != "UEFITool" ]; then + cd "$1" || exit 1 + fi + + # Build + # -flto is flawed on CI atm + if [ "$UPLATFORM" = "mac" ]; then + qmake $3 QMAKE_CXXFLAGS+=-flto QMAKE_LFLAGS+=-flto CONFIG+=optimize_size || exit 1 + else + qmake $3 CONFIG+=optimize_size || exit 1 + fi + + make || exit 1 + + # Archive + if [ "$1" = "UEFITool" ] && [ "$UPLATFORM" = "mac" ]; then + strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1 + zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" UEFITool.app "${4}" || exit 1 + else + strip -x "$1" || exit 1 + zip -qry ../dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" "${4}" || exit 1 + fi + + # Return to parent + if [ "$1" != "UEFITool" ]; then + cd - || exit 1 + fi +} + +rm -rf dist +mkdir -p dist || exit 1 + +build_tool UEFITool "$UEFITOOL_VER" uefitool.pro +build_tool UEFIPatch "$UEFIPATCH_VER" uefipatch.pro patches.txt +build_tool UEFIReplace "$UEFIREPLACE_VER" uefireplace.pro + +exit 0 From 912a1b25b2efb981d2a49566086013e5a624f2b9 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Mon, 7 May 2018 21:37:44 +0300 Subject: [PATCH 47/64] Fix compiler warning, closes #121 --- LZMA/LzmaCompress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LZMA/LzmaCompress.c b/LZMA/LzmaCompress.c index 78c04a3..d2b5f5e 100644 --- a/LZMA/LzmaCompress.c +++ b/LZMA/LzmaCompress.c @@ -74,7 +74,7 @@ LzmaCompress( if (*DestinationSize < destLen) { - *DestinationSize = destLen; + *DestinationSize = (UINTN)destLen; return ERR_BUFFER_TOO_SMALL; } From f3836460339d30ba7cc6c0c6dd08cf9e38fd9467 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Mon, 7 May 2018 21:41:42 +0300 Subject: [PATCH 48/64] Fix UEFITool path on Linux --- unixbuild.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/unixbuild.sh b/unixbuild.sh index d54b077..1b545fb 100755 --- a/unixbuild.sh +++ b/unixbuild.sh @@ -58,9 +58,14 @@ build_tool() { make || exit 1 # Archive - if [ "$1" = "UEFITool" ] && [ "$UPLATFORM" = "mac" ]; then - strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1 - zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" UEFITool.app "${4}" || exit 1 + if [ "$1" = "UEFITool" ]; then + if [ "$UPLATFORM" = "mac" ]; then + strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1 + zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" UEFITool.app "${4}" || exit 1 + else + strip -x "$1" || exit 1 + zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" "${4}" || exit 1 + fi else strip -x "$1" || exit 1 zip -qry ../dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" "${4}" || exit 1 From 66c9d4a2cf928f901338f298fc97267bfc67beee Mon Sep 17 00:00:00 2001 From: vit9696 Date: Mon, 7 May 2018 22:01:17 +0300 Subject: [PATCH 49/64] Implement external patches.txt path for UEFIPatch --- UEFIPatch/uefipatch.cpp | 6 +++--- UEFIPatch/uefipatch.h | 2 +- UEFIPatch/uefipatch_main.cpp | 15 ++++++++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/UEFIPatch/uefipatch.cpp b/UEFIPatch/uefipatch.cpp index c2e3a20..522a8ed 100644 --- a/UEFIPatch/uefipatch.cpp +++ b/UEFIPatch/uefipatch.cpp @@ -25,15 +25,15 @@ UEFIPatch::~UEFIPatch() delete ffsEngine; } -UINT8 UEFIPatch::patchFromFile(QString path) +UINT8 UEFIPatch::patchFromFile(QString path, QString patches) { - QFileInfo patchInfo = QFileInfo("patches.txt"); + QFileInfo patchInfo = QFileInfo(patches); if (!patchInfo.exists()) return ERR_INVALID_FILE; QFile file; - file.setFileName("patches.txt"); + file.setFileName(patches); if (!file.open(QFile::ReadOnly | QFile::Text)) return ERR_INVALID_FILE; diff --git a/UEFIPatch/uefipatch.h b/UEFIPatch/uefipatch.h index 3d94ca2..dd1cdb8 100644 --- a/UEFIPatch/uefipatch.h +++ b/UEFIPatch/uefipatch.h @@ -33,7 +33,7 @@ public: explicit UEFIPatch(QObject *parent = 0); ~UEFIPatch(); - UINT8 patchFromFile(QString path); + UINT8 patchFromFile(QString path, QString patches); UINT8 patch(QString path, QString fileGuid, QString findPattern, QString replacePattern); private: diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 3edb0f6..5e7ed4b 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include "uefipatch.h" int main(int argc, char *argv[]) @@ -27,13 +28,17 @@ int main(int argc, char *argv[]) UINT8 result = ERR_SUCCESS; UINT32 argumentsCount = a.arguments().length(); - if (argumentsCount == 2) { - result = w.patchFromFile(a.arguments().at(1)); + QString patches = "patches.txt"; + if (argumentsCount == 3) + patches = a.arguments().at(2); + + if (argumentsCount == 2 || argumentsCount == 3) { + result = w.patchFromFile(a.arguments().at(1), patches); } else { std::cout << "UEFIPatch 0.3.14 - 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"; + "Usage: UEFIPatch image_file [patches.txt]" << std::endl << std::endl << + "Patches will be read from patches.txt file by default\n"; return ERR_SUCCESS; } @@ -57,7 +62,7 @@ int main(int argc, char *argv[]) std::cout << "Pattern format mismatch" << std::endl; break; case ERR_INVALID_FILE: - std::cout << "patches.txt file not found or can't be read" << std::endl; + std::cout << patches.toStdString() << " file not found or can't be read" << std::endl; break; case ERR_FILE_OPEN: std::cout << "Input file not found" << std::endl; From f321a6c7a82a3406d55a38235570662d654a91fd Mon Sep 17 00:00:00 2001 From: vit9696 Date: Mon, 7 May 2018 22:12:50 +0300 Subject: [PATCH 50/64] Add misc patches unrelated to Intel PowerManagement --- UEFIPatch/patches-misc.txt | 37 +++++++++++++++++++++++++++++++++++++ unixbuild.sh | 8 ++++---- 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 UEFIPatch/patches-misc.txt diff --git a/UEFIPatch/patches-misc.txt b/UEFIPatch/patches-misc.txt new file mode 100644 index 0000000..68305ce --- /dev/null +++ b/UEFIPatch/patches-misc.txt @@ -0,0 +1,37 @@ +# Patch string format +# FileGuid SectionType PatchType:FindPatternOrOffset:ReplacePattern +# Please ensure that the latest symbol in patch string is space + +# Possible section types: +# PE32 image 10 +# Position-independent code 11 +# TE Image 12 +# DXE Dependency 13 +# Version information 14 +# User interface string 15 +# 16-bit code 16 +# Guided freeform 18 +# Raw data 19 +# PEI Dependency 1B +# SMM Dependency 1C +# Please do not try another section types, it can make the resulting image broken + +# Possible patch types: +# P - pattern-based, first parameter is a pattern to find, second - a pattern to replace +# O - offset-based, first parameter is hexadecimal offset, second - a pattern to replace +# Patterns can have . as "any possible value" symbol + +#---------------------------------------------------------------------------------- +# Set IA32_FEATURE_CONTROL.SGX_LC +#---------------------------------------------------------------------------------- + +# SiInit | Gemini Lake +299D6F8B-2EC9-4E40-9EC6-DDAA7EBF5FD9 10 P:B93A0000000F320D00000400:B93A0000000F320D00000600 + +#---------------------------------------------------------------------------------- +# Broken EFI_SIMPLE_POINTER_PROTOCOL implementation patches +# Fixes incorrect pointer position update/click condition on Z87 chips +#---------------------------------------------------------------------------------- + +# UHCD | ASUS Z87-Pro +580DD900-385D-11D7-883A-00500473D4EB 10 P:807A3200745C807A4000:807A32007506807A4000 diff --git a/unixbuild.sh b/unixbuild.sh index 1b545fb..c3a57a3 100755 --- a/unixbuild.sh +++ b/unixbuild.sh @@ -61,14 +61,14 @@ build_tool() { if [ "$1" = "UEFITool" ]; then if [ "$UPLATFORM" = "mac" ]; then strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1 - zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" UEFITool.app "${4}" || exit 1 + zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" UEFITool.app ${4} || exit 1 else strip -x "$1" || exit 1 - zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" "${4}" || exit 1 + zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" ${4} || exit 1 fi else strip -x "$1" || exit 1 - zip -qry ../dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" "${4}" || exit 1 + zip -qry ../dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" ${4} || exit 1 fi # Return to parent @@ -81,7 +81,7 @@ rm -rf dist mkdir -p dist || exit 1 build_tool UEFITool "$UEFITOOL_VER" uefitool.pro -build_tool UEFIPatch "$UEFIPATCH_VER" uefipatch.pro patches.txt +build_tool UEFIPatch "$UEFIPATCH_VER" uefipatch.pro patches*.txt build_tool UEFIReplace "$UEFIREPLACE_VER" uefireplace.pro exit 0 From b3f7beb2360eed49b5ffff527006b86e192af5e4 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 8 May 2018 01:31:29 +0300 Subject: [PATCH 51/64] Initial Windows build support --- .appveyor.yml | 21 +++++++++++++++++++++ unixbuild.sh | 41 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..80d9d67 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,21 @@ +image: Visual Studio 2015 + +environment: + matrix: + - MSYS2_ARCH: i686 + MSYSTEM: MINGW32 + +clone_depth: 10 + +build_script: + - cd %APPVEYOR_BUILD_FOLDER% + - set PATH=C:\msys64\mingw32\bin;C:\msys64\usr\bin;%PATH% + - bash ./unixbuild.sh + +deploy: + provider: GitHub + auth_token: + secure: zSJnpSnrKY1NO5RPVBaD/uq7UPyc+GW7ecjPFqEMsLjtnd6H+iNfROdoeuxJgt5T + artifact: /dist\\.*\.zip/ + on: + appveyor_repo_tag: true diff --git a/unixbuild.sh b/unixbuild.sh index c3a57a3..13a5559 100755 --- a/unixbuild.sh +++ b/unixbuild.sh @@ -1,11 +1,15 @@ #!/bin/bash UTARGET=$(uname) +BINSUFFIX="" if [ "$UTARGET" = "Darwin" ]; then export UPLATFORM="mac" elif [ "$UTARGET" = "Linux" ]; then export UPLATFORM="linux_$(uname -m)" +elif [ "${UTARGET/MINGW32/}" != "$UTARGET" ]; then + export UPLATFORM="win32" + export BINSUFFIX=".exe" else # Fallback to something... export UPLATFORM="$UTARGET" @@ -27,6 +31,28 @@ if [ "$UPLATFORM" = "mac" ]; then fi export PATH="/opt/qt56sm/bin:$PATH" +elif [ "$UPLATFORM" = "win32" ]; then + # Install missing dependencies + pacman -S --noconfirm --needed zip unzip curl perl mingw-w64-i686-toolchain mingw-w64-i686-cmake || exit 1 + + # Fix PATH to support running shasum. + export PATH="/usr/bin/core_perl:$PATH" + + if [ ! -d "/c/Qt/5.6/mingw49_32_release_static/" ]; then + curl -L -o /tmp/qt-5.6.3-static-win32.zip https://github.com/distdb/qtbuilds/blob/master/qt-5.6.3-static-win32.zip?raw=true || exit 1 + qtsum=$(shasum -a 256 /tmp/qt-5.6.3-static-win32.zip | cut -f1 -d' ') + qtexpsum="bcd85145d6fed00da37498c08c49d763c6fa883337f754880b5c786899e6bb1d" + if [ "$qtsum" != "$qtexpsum" ]; then + echo "Qt hash $qtsum does not match $qtexpsum" + exit 1 + fi + mkdir -p /c/Qt/5.6 || exit 1 + cd /c/Qt/5.6 || exit 1 + unzip -q /tmp/qt-5.6.3-static-win32.zip || exit 1 + cd - || exit 1 + fi + + export PATH="/c/Qt/5.6/mingw49_32_release_static/bin:$PATH" fi echo "Attempting to build UEFITool NE for ${UPLATFORM}..." @@ -51,24 +77,31 @@ build_tool() { # -flto is flawed on CI atm if [ "$UPLATFORM" = "mac" ]; then qmake $3 QMAKE_CXXFLAGS+=-flto QMAKE_LFLAGS+=-flto CONFIG+=optimize_size || exit 1 + elif [ "$UPLATFORM" = "win32" ]; then + qmake $3 QMAKE_CXXFLAGS="-static -flto -Os" QMAKE_LFLAGS="-static -flto -Os" CONFIG+=optimize_size CONFIG+=staticlib CONFIG+=static || exit 1 else qmake $3 CONFIG+=optimize_size || exit 1 fi make || exit 1 + # Move the binary out of the dir + if [ "$UPLATFORM" = "win32" ]; then + mv "release/${1}${BINSUFFIX}" "${1}${BINSUFFIX}" || exit 1 + fi + # Archive if [ "$1" = "UEFITool" ]; then if [ "$UPLATFORM" = "mac" ]; then strip -x UEFITool.app/Contents/MacOS/UEFITool || exit 1 zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" UEFITool.app ${4} || exit 1 else - strip -x "$1" || exit 1 - zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" ${4} || exit 1 + strip -x "${1}${BINSUFFIX}" || exit 1 + zip -qry dist/"${1}_${2}_${UPLATFORM}.zip" "${1}${BINSUFFIX}" ${4} || exit 1 fi else - strip -x "$1" || exit 1 - zip -qry ../dist/"${1}_${2}_${UPLATFORM}.zip" "${1}" ${4} || exit 1 + strip -x "${1}${BINSUFFIX}" || exit 1 + zip -qry ../dist/"${1}_${2}_${UPLATFORM}.zip" "${1}${BINSUFFIX}" ${4} || exit 1 fi # Return to parent From f507d71ead4dcc516d6be1b5b3cd61f900abb4a4 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 8 May 2018 19:22:07 +0300 Subject: [PATCH 52/64] Backport decompression updates from new_engine --- LZMA/LzmaCompress.c | 109 +- LZMA/LzmaCompress.h | 19 +- LZMA/LzmaDecompress.c | 115 +- LZMA/LzmaDecompress.h | 34 +- Tiano/EfiTianoCompress.c | 2280 ++++++++++++++------------- Tiano/EfiTianoCompress.h | 131 +- Tiano/EfiTianoCompressLegacy.c | 2696 ++++++++++++++++---------------- Tiano/EfiTianoDecompress.c | 1044 ++++++------- Tiano/EfiTianoDecompress.h | 158 +- basetypes.h | 3 +- ffsengine.cpp | 19 +- 11 files changed, 3296 insertions(+), 3312 deletions(-) diff --git a/LZMA/LzmaCompress.c b/LZMA/LzmaCompress.c index d2b5f5e..f6fc545 100644 --- a/LZMA/LzmaCompress.c +++ b/LZMA/LzmaCompress.c @@ -25,8 +25,8 @@ static ISzAlloc SzAllocForLzma = { &AllocForLzma, &FreeForLzma }; SRes OnProgress(void *p, UInt64 inSize, UInt64 outSize) { - (void)p; (void)inSize; (void)outSize; - return SZ_OK; + (void)p; (void)inSize; (void)outSize; + return SZ_OK; } static ICompressProgress g_ProgressCallback = { &OnProgress }; @@ -35,75 +35,76 @@ STATIC UINT64 EFIAPI RShiftU64 ( - UINT64 Operand, - UINT32 Count + UINT64 Operand, + UINT32 Count ) { - return Operand >> Count; + return Operand >> Count; } VOID -SetEncodedSizeOfBuf ( - UINT64 EncodedSize, - UINT8 *EncodedData +SetEncodedSizeOfBuf( + UINT64 EncodedSize, + UINT8* EncodedData ) { - INT32 Index; + INT32 Index; - EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF; - for (Index = LZMA_PROPS_SIZE + 1; Index <= LZMA_PROPS_SIZE + 7; Index++) - { - EncodedSize = RShiftU64(EncodedSize, 8); - EncodedData[Index] = EncodedSize & 0xFF; - } + EncodedData[LZMA_PROPS_SIZE] = EncodedSize & 0xFF; + for (Index = LZMA_PROPS_SIZE + 1; Index <= LZMA_PROPS_SIZE + 7; Index++) + { + EncodedSize = RShiftU64(EncodedSize, 8); + EncodedData[Index] = EncodedSize & 0xFF; + } } -INT32 +EFI_STATUS EFIAPI -LzmaCompress( - CONST UINT8 *Source, - UINTN SourceSize, - UINT8 *Destination, - UINTN *DestinationSize +LzmaCompress ( + CONST UINT8 *Source, + UINT32 SourceSize, + UINT8 *Destination, + UINT32 *DestinationSize ) { - SRes LzmaResult; - CLzmaEncProps props; - SizeT propsSize = LZMA_PROPS_SIZE; - SizeT destLen = SourceSize + SourceSize / 3 + 128; + SRes LzmaResult; + CLzmaEncProps props; + SizeT propsSize = LZMA_PROPS_SIZE; + SizeT destLen = SourceSize + SourceSize / 3 + 128; - if (*DestinationSize < destLen) - { - *DestinationSize = (UINTN)destLen; - return ERR_BUFFER_TOO_SMALL; - } + if (*DestinationSize < (UINT32)destLen) + { + *DestinationSize = (UINT32)destLen; + return EFI_BUFFER_TOO_SMALL; + } - LzmaEncProps_Init(&props); - props.dictSize = LZMA_DICTIONARY_SIZE; - props.level = 9; - props.fb = 273; + LzmaEncProps_Init(&props); + // TODO: need to detect this instead of hardcoding + props.dictSize = LZMA_DICTIONARY_SIZE; + props.level = 9; + props.fb = 273; - LzmaResult = LzmaEncode( - (Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE), - &destLen, - Source, - SourceSize, - &props, - (UINT8*)Destination, - &propsSize, - props.writeEndMark, - &g_ProgressCallback, - &SzAllocForLzma, - &SzAllocForLzma); + LzmaResult = LzmaEncode( + (Byte*)((UINT8*)Destination + LZMA_HEADER_SIZE), + &destLen, + Source, + (SizeT)SourceSize, + &props, + (UINT8*)Destination, + &propsSize, + props.writeEndMark, + &g_ProgressCallback, + &SzAllocForLzma, + &SzAllocForLzma); - *DestinationSize = destLen + LZMA_HEADER_SIZE; + *DestinationSize = (UINT32)(destLen + LZMA_HEADER_SIZE); - SetEncodedSizeOfBuf(SourceSize, Destination); + SetEncodedSizeOfBuf(SourceSize, Destination); - if (LzmaResult == SZ_OK) { - return ERR_SUCCESS; - } - else { - return ERR_INVALID_PARAMETER; - } + if (LzmaResult == SZ_OK) { + return EFI_SUCCESS; + } + else { + return EFI_INVALID_PARAMETER; + } } diff --git a/LZMA/LzmaCompress.h b/LZMA/LzmaCompress.h index 20bc427..bc098b1 100644 --- a/LZMA/LzmaCompress.h +++ b/LZMA/LzmaCompress.h @@ -11,8 +11,8 @@ */ -#ifndef __LZMACOMPRESS_H__ -#define __LZMACOMPRESS_H__ +#ifndef LZMACOMPRESS_H +#define LZMACOMPRESS_H #include "SDK/C/Types.h" #include "../basetypes.h" @@ -24,16 +24,17 @@ extern "C" { #define LZMA_DICTIONARY_SIZE 0x800000 #define _LZMA_SIZE_OPT - INT32 + EFI_STATUS EFIAPI - LzmaCompress( - const UINT8 *Source, - UINTN SourceSize, - UINT8 *Destination, - UINTN *DestinationSize + LzmaCompress ( + const UINT8 *Source, + UINT32 SourceSize, + UINT8 *Destination, + UINT32 *DestinationSize ); #ifdef __cplusplus } #endif -#endif + +#endif // LZMACOMPRESS_H diff --git a/LZMA/LzmaDecompress.c b/LZMA/LzmaDecompress.c index 2f97278..17aac44 100644 --- a/LZMA/LzmaDecompress.c +++ b/LZMA/LzmaDecompress.c @@ -19,12 +19,12 @@ WITHWARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. UINT64 EFIAPI -LShiftU64( - UINT64 Operand, - UINT32 Count -) +LShiftU64 ( + UINT64 Operand, + UINT32 Count + ) { - return Operand << Count; + return Operand << Count; } static void * AllocForLzma(void *p, size_t size) { (void)p; return malloc(size); } @@ -39,19 +39,19 @@ Get the size of the uncompressed buffer by parsing EncodeData header. @return The size of the uncompressed buffer. */ UINT64 -GetDecodedSizeOfBuf( - UINT8 *EncodedData -) +GetDecodedSizeOfBuf ( + UINT8 *EncodedData + ) { - UINT64 DecodedSize; - INT32 Index; + UINT64 DecodedSize; + INT32 Index; - // Parse header - DecodedSize = 0; - for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--) - DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; + // Parse header + DecodedSize = 0; + for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--) + DecodedSize = LShiftU64(DecodedSize, 8) + EncodedData[Index]; - return DecodedSize; + return DecodedSize; } // @@ -85,18 +85,27 @@ DestinationSize and the size of the scratch buffer was returned ScratchSize. */ -INT32 +EFI_STATUS EFIAPI -LzmaGetInfo( - CONST VOID *Source, - UINTN SourceSize, - UINTN *DestinationSize -) +LzmaGetInfo ( + CONST VOID *Source, + UINT32 SourceSize, + UINT32 *DestinationSize + ) { - ASSERT(SourceSize >= LZMA_HEADER_SIZE); (void)SourceSize; + UINT64 DecodedSize; + ASSERT(SourceSize >= LZMA_HEADER_SIZE); + (void)SourceSize; - *DestinationSize = (UINTN)GetDecodedSizeOfBuf((UINT8*)Source); - return ERR_SUCCESS; + DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source); + + if (DecodedSize <= UINT32_MAX) { + *DestinationSize = (UINT32)DecodedSize; + return ERR_SUCCESS; + } + else { + return ERR_INVALID_PARAMETER; + } } /* @@ -118,38 +127,38 @@ the uncompressed buffer is returned Destination. The source buffer specified by Source is corrupted (not a valid compressed format). */ -INT32 +EFI_STATUS EFIAPI -LzmaDecompress( - CONST VOID *Source, - UINTN SourceSize, - VOID *Destination -) +LzmaDecompress ( + CONST VOID *Source, + UINT32 SourceSize, + VOID *Destination + ) { - SRes LzmaResult; - ELzmaStatus Status; - SizeT DecodedBufSize; - SizeT EncodedDataSize; + SRes LzmaResult; + ELzmaStatus Status; + SizeT DecodedBufSize; + SizeT EncodedDataSize; - DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source); - EncodedDataSize = (SizeT)(SourceSize - LZMA_HEADER_SIZE); + DecodedBufSize = (SizeT)GetDecodedSizeOfBuf((UINT8*)Source); + EncodedDataSize = (SizeT)(SourceSize - LZMA_HEADER_SIZE); - LzmaResult = LzmaDecode( - (Byte*)Destination, - &DecodedBufSize, - (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), - &EncodedDataSize, - (CONST Byte*) Source, - LZMA_PROPS_SIZE, - LZMA_FINISH_END, - &Status, - &SzAllocForLzma - ); + LzmaResult = LzmaDecode( + (Byte*)Destination, + &DecodedBufSize, + (Byte*)((UINT8*)Source + LZMA_HEADER_SIZE), + &EncodedDataSize, + (CONST Byte*) Source, + LZMA_PROPS_SIZE, + LZMA_FINISH_END, + &Status, + &SzAllocForLzma + ); - if (LzmaResult == SZ_OK) { - return ERR_SUCCESS; - } - else { - return ERR_INVALID_PARAMETER; - } + if (LzmaResult == SZ_OK) { + return ERR_SUCCESS; + } + else { + return ERR_INVALID_PARAMETER; + } } diff --git a/LZMA/LzmaDecompress.h b/LZMA/LzmaDecompress.h index 78d4ac0..b7b0f0f 100644 --- a/LZMA/LzmaDecompress.h +++ b/LZMA/LzmaDecompress.h @@ -11,8 +11,8 @@ */ -#ifndef __LZMADECOMPRESS_H__ -#define __LZMADECOMPRESS_H__ +#ifndef LZMADECOMPRESS_H +#define LZMADECOMPRESS_H #include "../basetypes.h" #include "SDK/C/LzmaDec.h" @@ -23,13 +23,6 @@ extern "C" { #define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) - UINT64 - EFIAPI - LShiftU64( - UINT64 Operand, - UINT32 Count - ); - /* Given a Lzma compressed source buffer, this function retrieves the size of the uncompressed buffer and the size of the scratch buffer required @@ -57,12 +50,12 @@ extern "C" { buffer was returned ScratchSize. */ - INT32 + EFI_STATUS EFIAPI - LzmaGetInfo( - const VOID *Source, - UINTN SourceSize, - UINTN *DestinationSize + LzmaGetInfo ( + CONST VOID *Source, + UINT32 SourceSize, + UINT32 *DestinationSize ); /* @@ -84,15 +77,16 @@ extern "C" { The source buffer specified by Source is corrupted (not a valid compressed format). */ - INT32 + EFI_STATUS EFIAPI - LzmaDecompress( - const VOID *Source, - UINTN SourceSize, - VOID *Destination + LzmaDecompress ( + CONST VOID *Source, + UINT32 SourceSize, + VOID *Destination ); #ifdef __cplusplus } #endif -#endif + +#endif // LZMADECOMPRESS_H diff --git a/Tiano/EfiTianoCompress.c b/Tiano/EfiTianoCompress.c index 31c0e37..afd2ec2 100644 --- a/Tiano/EfiTianoCompress.c +++ b/Tiano/EfiTianoCompress.c @@ -1,18 +1,18 @@ /** @file -Compression routine. The compression algorithm is a mixture of LZ77 and Huffman -coding. LZ77 transforms the source data into a sequence of Original Characters -and Pointers to repeated strings. This sequence is further divided into Blocks +Compression routine. The compression algorithm is a mixture of LZ77 and Huffman +coding. LZ77 transforms the source data into a sequence of Original Characters +and Pointers to repeated strings. This sequence is further divided into Blocks and Huffman codings are applied to each Block. Copyright (c) 2014, Nikolaj Schlej Copyright (c) 2006 - 2014, Intel Corporation. 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. +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. **/ @@ -52,9 +52,9 @@ UINT8 gPBIT = 4; #define NT (CODE_BIT + 3) #define TBIT 5 #if NT > NP -#define NPT NT + #define NPT NT #else -#define NPT NP + #define NPT NP #endif // @@ -62,163 +62,163 @@ UINT8 gPBIT = 4; // STATIC -VOID +VOID PutDword( - IN UINT32 Data -); + IN UINT32 Data + ); STATIC -EFI_STATUS -AllocateMemory(VOID); +EFI_STATUS +AllocateMemory (VOID); STATIC VOID -FreeMemory(VOID); +FreeMemory (VOID); -STATIC -VOID -InitSlide(VOID); +STATIC +VOID +InitSlide (VOID); -STATIC -NODE -Child( - IN NODE q, - IN UINT8 c -); +STATIC +NODE +Child ( + IN NODE q, + IN UINT8 c + ); -STATIC -VOID -MakeChild( - IN NODE q, - IN UINT8 c, - IN NODE r -); +STATIC +VOID +MakeChild ( + IN NODE q, + IN UINT8 c, + IN NODE r + ); + +STATIC +VOID +Split ( + IN NODE Old + ); -STATIC -VOID -Split( - IN NODE Old -); +STATIC +VOID +InsertNode (VOID); + +STATIC +VOID +DeleteNode (VOID); -STATIC -VOID -InsertNode(VOID); +STATIC +VOID +GetNextMatch (VOID); + +STATIC +EFI_STATUS +Encode (VOID); -STATIC -VOID -DeleteNode(VOID); +STATIC +VOID +CountTFreq (VOID); -STATIC -VOID -GetNextMatch(VOID); +STATIC +VOID +WritePTLen ( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special + ); -STATIC -EFI_STATUS -Encode(VOID); +STATIC +VOID +WriteCLen (VOID); + +STATIC +VOID +EncodeC ( + IN INT32 c + ); -STATIC -VOID -CountTFreq(VOID); +STATIC +VOID +EncodeP ( + IN UINT32 p + ); -STATIC -VOID -WritePTLen( - IN INT32 n, - IN INT32 nbit, - IN INT32 Special -); +STATIC +VOID +SendBlock (VOID); + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ); -STATIC -VOID -WriteCLen(VOID); +STATIC +VOID +HufEncodeStart (VOID); + +STATIC +VOID +HufEncodeEnd (VOID); + +STATIC +VOID +MakeCrcTable (VOID); + +STATIC +VOID +PutBits ( + IN INT32 n, + IN UINT32 x + ); + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *p, + IN INT32 n + ); + +STATIC +VOID +InitPutBits (VOID); + +STATIC +VOID +CountLen ( + IN INT32 i + ); -STATIC -VOID -EncodeC( - IN INT32 c -); +STATIC +VOID +MakeLen ( + IN INT32 Root + ); + +STATIC +VOID +DownHeap ( + IN INT32 i + ); -STATIC -VOID -EncodeP( - IN UINT32 p -); - -STATIC -VOID -SendBlock(VOID); - -STATIC -VOID -Output( - IN UINT32 c, - IN UINT32 p -); - -STATIC -VOID -HufEncodeStart(VOID); - -STATIC -VOID -HufEncodeEnd(VOID); - -STATIC -VOID -MakeCrcTable(VOID); - -STATIC -VOID -PutBits( - IN INT32 n, - IN UINT32 x -); - -STATIC -INT32 -FreadCrc( - OUT UINT8 *p, - IN INT32 n -); - -STATIC -VOID -InitPutBits(VOID); - -STATIC -VOID -CountLen( - IN INT32 i -); - -STATIC -VOID -MakeLen( - IN INT32 Root -); - -STATIC -VOID -DownHeap( - IN INT32 i -); - -STATIC -VOID -MakeCode( - IN INT32 n, - IN UINT8 Len[], - OUT UINT16 Code[] -); - -STATIC -INT32 -MakeTree( - IN INT32 NParm, - IN UINT16 FreqParm[], - OUT UINT8 LenParm[], - OUT UINT16 CodeParm[] -); +STATIC +VOID +MakeCode ( + IN INT32 n, + IN UINT8 Len[], + OUT UINT16 Code[] + ); + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[], + OUT UINT16 CodeParm[] + ); // @@ -234,8 +234,8 @@ STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; STATIC UINT32 mCompSize, mOrigSize; STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], -mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1], mCCode[NC], -mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; + mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1],mCCode[NC], + mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; @@ -245,12 +245,12 @@ STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NU // EFI_STATUS -EfiCompress( - IN CONST VOID *SrcBuffer, - IN UINT32 SrcSize, - IN VOID *DstBuffer, - IN OUT UINT32 *DstSize -) +EfiCompress ( + IN CONST VOID *SrcBuffer, + IN UINT32 SrcSize, + IN VOID *DstBuffer, + IN OUT UINT32 *DstSize + ) /*++ Routine Description: @@ -263,89 +263,88 @@ Arguments: SrcSize - The size of source data DstBuffer - The buffer to store the compressed data DstSize - On input, the size of DstBuffer; On output, - the size of the actual compressed data. + the size of the actual compressed data. Returns: EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, - DstSize contains the size needed. + DstSize contains the size needed. EFI_SUCCESS - Compression is successful. --*/ { - EFI_STATUS Status = EFI_SUCCESS; + EFI_STATUS Status = EFI_SUCCESS; + + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + gPBIT = 4; + + mSrc = (UINT8*)SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; - // - // Initializations - // - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; - gPBIT = 4; + PutDword(0L); + PutDword(0L); + + MakeCrcTable (); - mSrc = (UINT8*)SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst + *DstSize; + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; + + // + // Compress it + // + + Status = Encode(); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize+1); + PutDword(mOrigSize); - PutDword(0L); - PutDword(0L); - - MakeCrcTable(); - - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; - - // - // Compress it - // - - Status = Encode(); - if (EFI_ERROR(Status)) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } - - // - // Fill in compressed size and original size - // - mDst = DstBuffer; - PutDword(mCompSize + 1); - PutDword(mOrigSize); - - // - // Return - // - - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } - else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + // + // Return + // + + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } EFI_STATUS TianoCompress( - IN CONST VOID *SrcBuffer, - IN UINT32 SrcSize, - IN VOID *DstBuffer, - IN OUT UINT32 *DstSize +IN CONST VOID *SrcBuffer, +IN UINT32 SrcSize, +IN VOID *DstBuffer, +IN OUT UINT32 *DstSize ) /*++ @@ -369,118 +368,118 @@ EFI_SUCCESS - Compression is successful. --*/ { - EFI_STATUS Status = EFI_SUCCESS; + EFI_STATUS Status = EFI_SUCCESS; - // - // Initializations - // - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; - gPBIT = 5; + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + gPBIT = 5; - mSrc = (UINT8*)SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst + *DstSize; + mSrc = (UINT8*)SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; - PutDword(0L); - PutDword(0L); + PutDword(0L); + PutDword(0L); - MakeCrcTable(); + MakeCrcTable(); - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; - // - // Compress it - // + // + // Compress it + // - Status = Encode(); - if (EFI_ERROR(Status)) { - return EFI_OUT_OF_RESOURCES; - } + Status = Encode(); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } - // - // Fill in compressed size and original size - // - mDst = DstBuffer; - PutDword(mCompSize + 1); - PutDword(mOrigSize); + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize + 1); + PutDword(mOrigSize); - // - // Return - // + // + // Return + // - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } - else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } + else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } -STATIC -VOID +STATIC +VOID PutDword( - IN UINT32 Data -) + IN UINT32 Data + ) /*++ Routine Description: Put a dword to output stream - + Arguments: Data - the dword to put - + Returns: (VOID) - + --*/ { - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data )) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); + } } STATIC EFI_STATUS -AllocateMemory() +AllocateMemory () /*++ Routine Description: Allocate memory spaces for data structures used in compression process - + Argements: (VOID) Returns: @@ -490,421 +489,423 @@ Returns: --*/ { - UINT32 i; + UINT32 i; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + if (!mText) return EFI_OUT_OF_RESOURCES; + for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) { + mText[i] = 0; + } - mText = malloc(WNDSIZ * 2 + MAXMATCH); - if (NULL == mText) - return EFI_OUT_OF_RESOURCES; + mLevel = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); + if (!mLevel) return EFI_OUT_OF_RESOURCES; + mChildCount = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); + if (!mChildCount) return EFI_OUT_OF_RESOURCES; + mPosition = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); + if (!mPosition) return EFI_OUT_OF_RESOURCES; + mParent = malloc(WNDSIZ * 2 * sizeof(*mParent)); + if (!mParent) return EFI_OUT_OF_RESOURCES; + mPrev = malloc(WNDSIZ * 2 * sizeof(*mPrev)); + if (!mPrev) return EFI_OUT_OF_RESOURCES; + mNext = malloc((MAX_HASH_VAL + 1) * sizeof(*mNext)); + if (!mNext) return EFI_OUT_OF_RESOURCES; - for (i = 0; i < WNDSIZ * 2 + MAXMATCH; i++) { - mText[i] = 0; - } - - mLevel = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); - mChildCount = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); - mPosition = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); - mParent = malloc(WNDSIZ * 2 * sizeof(*mParent)); - mPrev = malloc(WNDSIZ * 2 * sizeof(*mPrev)); - mNext = malloc((MAX_HASH_VAL + 1) * sizeof(*mNext)); - - mBufSiz = 16 * 1024U; - while ((mBuf = malloc(mBufSiz)) == NULL) { - mBufSiz = (mBufSiz / 10U) * 9U; - if (mBufSiz < 4 * 1024U) { - return EFI_OUT_OF_RESOURCES; - } - } - mBuf[0] = 0; - - return EFI_SUCCESS; + mBufSiz = 16 * 1024U; + while ((mBuf = malloc(mBufSiz)) == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + } + mBuf[0] = 0; + + return EFI_SUCCESS; } VOID -FreeMemory() +FreeMemory () /*++ Routine Description: Called when compression is completed to free memory previously allocated. - + Arguments: (VOID) Returns: (VOID) --*/ { - if (mText) { - free(mText); - } + if (mText) { + free (mText); + } + + if (mLevel) { + free (mLevel); + } + + if (mChildCount) { + free (mChildCount); + } + + if (mPosition) { + free (mPosition); + } + + if (mParent) { + free (mParent); + } + + if (mPrev) { + free (mPrev); + } + + if (mNext) { + free (mNext); + } + + if (mBuf) { + free (mBuf); + } - if (mLevel) { - free(mLevel); - } - - if (mChildCount) { - free(mChildCount); - } - - if (mPosition) { - free(mPosition); - } - - if (mParent) { - free(mParent); - } - - if (mPrev) { - free(mPrev); - } - - if (mNext) { - free(mNext); - } - - if (mBuf) { - free(mBuf); - } - - return; + return; } -STATIC -VOID -InitSlide() +STATIC +VOID +InitSlide () /*++ Routine Description: Initialize String Info Log data structures - + Arguments: (VOID) Returns: (VOID) --*/ { - NODE i; + NODE i; - for (i = WNDSIZ; i <= (NODE)(WNDSIZ + UINT8_MAX); i++) { - mLevel[i] = 1; - mPosition[i] = NIL; /* sentinel */ - } - for (i = WNDSIZ; i < (NODE)(WNDSIZ * 2); i++) { - mParent[i] = NIL; - } - mAvail = 1; - for (i = 1; i < (NODE)(WNDSIZ - 1); i++) { - mNext[i] = (NODE)(i + 1); - } - - mNext[WNDSIZ - 1] = NIL; - for (i = WNDSIZ * 2; i <= (NODE)MAX_HASH_VAL; i++) { - mNext[i] = NIL; - } + for (i = WNDSIZ; i <= (NODE)(WNDSIZ + UINT8_MAX); i++) { + mLevel[i] = 1; + mPosition[i] = NIL; /* sentinel */ + } + for (i = WNDSIZ; i < (NODE)(WNDSIZ * 2); i++) { + mParent[i] = NIL; + } + mAvail = 1; + for (i = 1; i < (NODE)(WNDSIZ - 1); i++) { + mNext[i] = (NODE)(i + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (i = WNDSIZ * 2; i <= (NODE)MAX_HASH_VAL; i++) { + mNext[i] = NIL; + } } -STATIC -NODE -Child( - IN NODE q, - IN UINT8 c -) +STATIC +NODE +Child ( + IN NODE q, + IN UINT8 c + ) /*++ Routine Description: Find child node given the parent node and the edge character - + Arguments: q - the parent node c - the edge character - + Returns: - The child node (NIL if not found) - + The child node (NIL if not found) + --*/ { - NODE r; - - r = mNext[HASH(q, c)]; - mParent[NIL] = q; /* sentinel */ - while (mParent[r] != q) { - r = mNext[r]; - } - - return r; + NODE r; + + r = mNext[HASH(q, c)]; + mParent[NIL] = q; /* sentinel */ + while (mParent[r] != q) { + r = mNext[r]; + } + + return r; } -STATIC -VOID -MakeChild( - IN NODE q, - IN UINT8 c, - IN NODE r -) +STATIC +VOID +MakeChild ( + IN NODE q, + IN UINT8 c, + IN NODE r + ) /*++ Routine Description: Create a new child for a given parent node. - + Arguments: q - the parent node c - the edge character r - the child node - + Returns: (VOID) --*/ { - NODE h, t; - - h = (NODE)HASH(q, c); - t = mNext[h]; - mNext[h] = r; - mNext[r] = t; - mPrev[t] = r; - mPrev[r] = h; - mParent[r] = q; - mChildCount[q]++; + NODE h, t; + + h = (NODE)HASH(q, c); + t = mNext[h]; + mNext[h] = r; + mNext[r] = t; + mPrev[t] = r; + mPrev[r] = h; + mParent[r] = q; + mChildCount[q]++; } -STATIC -VOID +STATIC +VOID Split ( - IN NODE Old -) + NODE Old + ) /*++ Routine Description: Split a node. - + Arguments: Old - the node to split - + Returns: (VOID) --*/ { - NODE New, t; + NODE New, t; - New = mAvail; - mAvail = mNext[New]; - mChildCount[New] = 0; - t = mPrev[Old]; - mPrev[New] = t; - mNext[t] = New; - t = mNext[Old]; - mNext[New] = t; - mPrev[t] = New; - mParent[New] = mParent[Old]; - mLevel[New] = (UINT8)mMatchLen; - mPosition[New] = mPos; - MakeChild(New, mText[mMatchPos + mMatchLen], Old); - MakeChild(New, mText[mPos + mMatchLen], mPos); + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + t = mPrev[Old]; + mPrev[New] = t; + mNext[t] = New; + t = mNext[Old]; + mNext[New] = t; + mPrev[t] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8)mMatchLen; + mPosition[New] = mPos; + MakeChild(New, mText[mMatchPos + mMatchLen], Old); + MakeChild(New, mText[mPos + mMatchLen], mPos); } -STATIC -VOID -InsertNode() +STATIC +VOID +InsertNode () /*++ Routine Description: Insert string info for current position into the String Info Log - + Arguments: (VOID) Returns: (VOID) --*/ { - NODE q, r, j, t; - UINT8 c, *t1, *t2; - - if (mMatchLen >= 4) { - - // - // We have just got a long match, the target tree - // can be located by MatchPos + 1. Travese the tree - // from bottom up to get to a proper starting point. - // The usage of PERC_FLAG ensures proper node deletion - // in DeleteNode() later. - // - - mMatchLen--; - r = (INT16)((mMatchPos + 1) | WNDSIZ); - while ((q = mParent[r]) == NIL) { - r = mNext[r]; - } - while (mLevel[q] >= mMatchLen) { - r = q; q = mParent[q]; - } - t = q; - while (mPosition[t] < 0) { - mPosition[t] = mPos; - t = mParent[t]; - } - if (t < (NODE)WNDSIZ) { - mPosition[t] = (NODE)(mPos | PERC_FLAG); - } - } - else { - - // - // Locate the target tree - // - - q = (INT16)(mText[mPos] + WNDSIZ); - c = mText[mPos + 1]; - if ((r = Child(q, c)) == NIL) { - MakeChild(q, c, mPos); - mMatchLen = 1; - return; - } - mMatchLen = 2; - } - - // - // Traverse down the tree to find a match. - // Update Position value along the route. - // Node split or creation is involved. - // - - for (; ; ) { - if (r >= (NODE)WNDSIZ) { - j = MAXMATCH; - mMatchPos = r; - } - else { - j = mLevel[r]; - mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG); - } - if (mMatchPos >= mPos) { - mMatchPos -= WNDSIZ; - } - t1 = &mText[mPos + mMatchLen]; - t2 = &mText[mMatchPos + mMatchLen]; - while (mMatchLen < j) { - if (*t1 != *t2) { - Split(r); - return; - } - mMatchLen++; - t1++; - t2++; - } - if (mMatchLen >= MAXMATCH) { - break; - } - mPosition[r] = mPos; - q = r; - if ((r = Child(q, *t1)) == NIL) { - MakeChild(q, *t1, mPos); - return; - } - mMatchLen++; - } - t = mPrev[r]; - mPrev[mPos] = t; - mNext[t] = mPos; - t = mNext[r]; - mNext[mPos] = t; - mPrev[t] = mPos; - mParent[mPos] = q; - mParent[r] = NIL; - - // - // Special usage of 'next' - // - mNext[r] = mPos; + NODE q, r, j, t; + UINT8 c, *t1, *t2; + if (mMatchLen >= 4) { + + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Travese the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // in DeleteNode() later. + // + + mMatchLen--; + r = (INT16)((mMatchPos + 1) | WNDSIZ); + while ((q = mParent[r]) == NIL) { + r = mNext[r]; + } + while (mLevel[q] >= mMatchLen) { + r = q; q = mParent[q]; + } + t = q; + while (mPosition[t] < 0) { + mPosition[t] = mPos; + t = mParent[t]; + } + if (t < (NODE)WNDSIZ) { + mPosition[t] = (NODE)(mPos | PERC_FLAG); + } + } else { + + // + // Locate the target tree + // + + q = (INT16)(mText[mPos] + WNDSIZ); + c = mText[mPos + 1]; + if ((r = Child(q, c)) == NIL) { + MakeChild(q, c, mPos); + mMatchLen = 1; + return; + } + mMatchLen = 2; + } + + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + + for ( ; ; ) { + if (r >= (NODE)WNDSIZ) { + j = MAXMATCH; + mMatchPos = r; + } else { + j = mLevel[r]; + mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG); + } + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < j) { + if (*t1 != *t2) { + Split(r); + return; + } + mMatchLen++; + t1++; + t2++; + } + if (mMatchLen >= MAXMATCH) { + break; + } + mPosition[r] = mPos; + q = r; + if ((r = Child(q, *t1)) == NIL) { + MakeChild(q, *t1, mPos); + return; + } + mMatchLen++; + } + t = mPrev[r]; + mPrev[mPos] = t; + mNext[t] = mPos; + t = mNext[r]; + mNext[mPos] = t; + mPrev[t] = mPos; + mParent[mPos] = q; + mParent[r] = NIL; + + // + // Special usage of 'next' + // + mNext[r] = mPos; + } -STATIC -VOID -DeleteNode() +STATIC +VOID +DeleteNode () /*++ Routine Description: Delete outdated string info. (The Usage of PERC_FLAG ensures a clean deletion) - + Arguments: (VOID) Returns: (VOID) --*/ { - NODE q, r, s, t, u; + NODE q, r, s, t, u; - if (mParent[mPos] == NIL) { - return; - } - - r = mPrev[mPos]; - s = mNext[mPos]; - mNext[r] = s; - mPrev[s] = r; - r = mParent[mPos]; - mParent[mPos] = NIL; - if (r >= (NODE)WNDSIZ || --mChildCount[r] > 1) { - return; - } - t = (NODE)(mPosition[r] & ~PERC_FLAG); - if (t >= mPos) { - t -= WNDSIZ; - } - s = t; - q = mParent[r]; - while ((u = mPosition[q]) & PERC_FLAG) { - u &= ~PERC_FLAG; - if (u >= mPos) { - u -= WNDSIZ; - } - if (u > s) { - s = u; - } - mPosition[q] = (INT16)(s | WNDSIZ); - q = mParent[q]; - } - if (q < (NODE)WNDSIZ) { - if (u >= mPos) { - u -= WNDSIZ; - } - if (u > s) { - s = u; - } - mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG); - } - s = Child(r, mText[t + mLevel[r]]); - t = mPrev[s]; - u = mNext[s]; - mNext[t] = u; - mPrev[u] = t; - t = mPrev[r]; - mNext[t] = s; - mPrev[s] = t; - t = mNext[r]; - mPrev[t] = s; - mNext[s] = t; - mParent[s] = mParent[r]; - mParent[r] = NIL; - mNext[r] = mAvail; - mAvail = r; + if (mParent[mPos] == NIL) { + return; + } + + r = mPrev[mPos]; + s = mNext[mPos]; + mNext[r] = s; + mPrev[s] = r; + r = mParent[mPos]; + mParent[mPos] = NIL; + if (r >= (NODE)WNDSIZ || --mChildCount[r] > 1) { + return; + } + t = (NODE)(mPosition[r] & ~PERC_FLAG); + if (t >= mPos) { + t -= WNDSIZ; + } + s = t; + q = mParent[r]; + while ((u = mPosition[q]) & PERC_FLAG) { + u &= ~PERC_FLAG; + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ); + q = mParent[q]; + } + if (q < (NODE)WNDSIZ) { + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG); + } + s = Child(r, mText[t + mLevel[r]]); + t = mPrev[s]; + u = mNext[s]; + mNext[t] = u; + mPrev[u] = t; + t = mPrev[r]; + mNext[t] = s; + mPrev[s] = t; + t = mNext[r]; + mPrev[t] = s; + mNext[s] = t; + mParent[s] = mParent[r]; + mParent[r] = NIL; + mNext[r] = mAvail; + mAvail = r; } -STATIC -VOID -GetNextMatch() +STATIC +VOID +GetNextMatch () /*++ Routine Description: @@ -918,22 +919,22 @@ Returns: (VOID) --*/ { - INT32 n; + INT32 n; - mRemainder--; - if (++mPos == WNDSIZ * 2) { - memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); - n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); - mRemainder += n; - mPos = WNDSIZ; - } - DeleteNode(); - InsertNode(); + mRemainder--; + if (++mPos == WNDSIZ * 2) { + memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += n; + mPos = WNDSIZ; + } + DeleteNode(); + InsertNode(); } STATIC EFI_STATUS -Encode() +Encode () /*++ Routine Description: @@ -943,338 +944,323 @@ Routine Description: Arguments: (VOID) Returns: - + EFI_SUCCESS - The compression is successful EFI_OUT_0F_RESOURCES - Not enough memory for compression process --*/ { - EFI_STATUS Status; - INT32 LastMatchLen; - NODE LastMatchPos; + EFI_STATUS Status; + INT32 LastMatchLen; + NODE LastMatchPos; - Status = AllocateMemory(); - if (EFI_ERROR(Status)) { - FreeMemory(); - return Status; - } + Status = AllocateMemory(); + if (EFI_ERROR(Status)) { + FreeMemory(); + return Status; + } - InitSlide(); + InitSlide(); + + HufEncodeStart(); - HufEncodeStart(); - - mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); - - mMatchLen = 0; - mPos = WNDSIZ; - InsertNode(); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - while (mRemainder > 0) { - LastMatchLen = mMatchLen; - LastMatchPos = mMatchPos; - GetNextMatch(); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - - if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { - - // - // Not enough benefits are gained by outputting a pointer, - // so just output the original character - // - - Output(mText[mPos - 1], 0); - } - else { - - // - // Outputting a pointer is beneficial enough, do it. - // - - Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), - (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); - while (--LastMatchLen > 0) { - GetNextMatch(); - } - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - } - } - - HufEncodeEnd(); - FreeMemory(); - return EFI_SUCCESS; + mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + + Output(mText[mPos - 1], 0); + } else { + + // + // Outputting a pointer is beneficial enough, do it. + // + + Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); + while (--LastMatchLen > 0) { + GetNextMatch(); + } + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd(); + FreeMemory(); + return EFI_SUCCESS; } -STATIC -VOID -CountTFreq() +STATIC +VOID +CountTFreq () /*++ Routine Description: Count the frequencies for the Extra Set - + Arguments: (VOID) Returns: (VOID) --*/ { - INT32 i, k, n, Count; + INT32 i, k, n, Count; - for (i = 0; i < NT; i++) { - mTFreq[i] = 0; - } - n = NC; - while (n > 0 && mCLen[n - 1] == 0) { - n--; - } - i = 0; - while (i < n) { - k = mCLen[i++]; - if (k == 0) { - Count = 1; - while (i < n && mCLen[i] == 0) { - i++; - Count++; - } - if (Count <= 2) { - mTFreq[0] = (UINT16)(mTFreq[0] + Count); - } - else if (Count <= 18) { - mTFreq[1]++; - } - else if (Count == 19) { - mTFreq[0]++; - mTFreq[1]++; - } - else { - mTFreq[2]++; - } - } - else { - mTFreq[k + 2]++; - } - } + for (i = 0; i < NT; i++) { + mTFreq[i] = 0; + } + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + Count++; + } + if (Count <= 2) { + mTFreq[0] = (UINT16)(mTFreq[0] + Count); + } else if (Count <= 18) { + mTFreq[1]++; + } else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } else { + mTFreq[2]++; + } + } else { + mTFreq[k + 2]++; + } + } } -STATIC -VOID -WritePTLen( - IN INT32 n, - IN INT32 nbit, - IN INT32 Special -) +STATIC +VOID +WritePTLen ( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special + ) /*++ Routine Description: Outputs the code length array for the Extra Set or the Position Set. - + Arguments: n - the number of symbols nbit - the number of bits needed to represent 'n' Special - the special symbol that needs to be take care of - + Returns: (VOID) --*/ { - INT32 i, k; + INT32 i, k; - while (n > 0 && mPTLen[n - 1] == 0) { - n--; - } - PutBits(nbit, n); - i = 0; - while (i < n) { - k = mPTLen[i++]; - if (k <= 6) { - PutBits(3, k); - } - else { - PutBits(k - 3, (1U << (k - 3)) - 2); - } - if (i == Special) { - while (i < 6 && mPTLen[i] == 0) { - i++; - } - PutBits(2, (i - 3) & 3); - } - } + while (n > 0 && mPTLen[n - 1] == 0) { + n--; + } + PutBits(nbit, n); + i = 0; + while (i < n) { + k = mPTLen[i++]; + if (k <= 6) { + PutBits(3, k); + } else { + PutBits(k - 3, (1U << (k - 3)) - 2); + } + if (i == Special) { + while (i < 6 && mPTLen[i] == 0) { + i++; + } + PutBits(2, (i - 3) & 3); + } + } } -STATIC -VOID -WriteCLen() +STATIC +VOID +WriteCLen () /*++ Routine Description: Outputs the code length array for Char&Length Set - + Arguments: (VOID) Returns: (VOID) --*/ { - INT32 i, k, n, Count; + INT32 i, k, n, Count; - n = NC; - while (n > 0 && mCLen[n - 1] == 0) { - n--; - } - PutBits(CBIT, n); - i = 0; - while (i < n) { - k = mCLen[i++]; - if (k == 0) { - Count = 1; - while (i < n && mCLen[i] == 0) { - i++; - Count++; - } - if (Count <= 2) { - for (k = 0; k < Count; k++) { - PutBits(mPTLen[0], mPTCode[0]); - } - } - else if (Count <= 18) { - PutBits(mPTLen[1], mPTCode[1]); - PutBits(4, Count - 3); - } - else if (Count == 19) { - PutBits(mPTLen[0], mPTCode[0]); - PutBits(mPTLen[1], mPTCode[1]); - PutBits(4, 15); - } - else { - PutBits(mPTLen[2], mPTCode[2]); - PutBits(CBIT, Count - 20); - } - } - else { - PutBits(mPTLen[k + 2], mPTCode[k + 2]); - } - } + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + PutBits(CBIT, n); + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + Count++; + } + if (Count <= 2) { + for (k = 0; k < Count; k++) { + PutBits(mPTLen[0], mPTCode[0]); + } + } else if (Count <= 18) { + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, Count - 3); + } else if (Count == 19) { + PutBits(mPTLen[0], mPTCode[0]); + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, 15); + } else { + PutBits(mPTLen[2], mPTCode[2]); + PutBits(CBIT, Count - 20); + } + } else { + PutBits(mPTLen[k + 2], mPTCode[k + 2]); + } + } } -STATIC -VOID -EncodeC( - IN INT32 c -) +STATIC +VOID +EncodeC ( + IN INT32 c + ) { - PutBits(mCLen[c], mCCode[c]); + PutBits(mCLen[c], mCCode[c]); } -STATIC -VOID -EncodeP( - IN UINT32 p -) +STATIC +VOID +EncodeP ( + IN UINT32 p + ) { - UINT32 c, q; + UINT32 c, q; - c = 0; - q = p; - while (q) { - q >>= 1; - c++; - } - PutBits(mPTLen[c], mPTCode[c]); - if (c > 1) { - PutBits(c - 1, p & (0xFFFFU >> (17 - c))); - } + c = 0; + q = p; + while (q) { + q >>= 1; + c++; + } + PutBits(mPTLen[c], mPTCode[c]); + if (c > 1) { + PutBits(c - 1, p & (0xFFFFU >> (17 - c))); + } } -STATIC -VOID -SendBlock() +STATIC +VOID +SendBlock () /*++ Routine Description: Huffman code the block and output it. - + Argument: (VOID) Returns: (VOID) --*/ { - UINT32 i, k, Flags, Root, Pos, Size; - Flags = 0; + UINT32 i, k, Flags, Root, Pos, Size; + Flags = 0; - Root = MakeTree(NC, mCFreq, mCLen, mCCode); - Size = mCFreq[Root]; - PutBits(16, Size); - if (Root >= NC) { - CountTFreq(); - Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); - if (Root >= NT) { - WritePTLen(NT, TBIT, 3); - } - else { - PutBits(TBIT, 0); - PutBits(TBIT, Root); - } - WriteCLen(); - } - else { - PutBits(TBIT, 0); - PutBits(TBIT, 0); - PutBits(CBIT, 0); - PutBits(CBIT, Root); - } - Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); - if (Root >= NP) { - WritePTLen(NP, gPBIT, -1); - } - else { - PutBits(gPBIT, 0); - PutBits(gPBIT, Root); - } - Pos = 0; - for (i = 0; i < Size; i++) { - if (i % UINT8_BIT == 0) { - Flags = mBuf[Pos++]; - } - else { - Flags <<= 1; - } - if (Flags & (1U << (UINT8_BIT - 1))) { - EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); - k = mBuf[Pos++] << UINT8_BIT; - k += mBuf[Pos++]; - EncodeP(k); - } - else { - EncodeC(mBuf[Pos++]); - } - } - for (i = 0; i < NC; i++) { - mCFreq[i] = 0; - } - for (i = 0; i < NP; i++) { - mPFreq[i] = 0; - } + Root = MakeTree(NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + PutBits(16, Size); + if (Root >= NC) { + CountTFreq(); + Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen(NT, TBIT, 3); + } else { + PutBits(TBIT, 0); + PutBits(TBIT, Root); + } + WriteCLen(); + } else { + PutBits(TBIT, 0); + PutBits(TBIT, 0); + PutBits(CBIT, 0); + PutBits(CBIT, Root); + } + Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen(NP, gPBIT, -1); + } else { + PutBits(gPBIT, 0); + PutBits(gPBIT, Root); + } + Pos = 0; + for (i = 0; i < Size; i++) { + if (i % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); + k = mBuf[Pos++] << UINT8_BIT; + k += mBuf[Pos++]; + EncodeP(k); + } else { + EncodeC(mBuf[Pos++]); + } + } + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } } -STATIC -VOID -Output( - IN UINT32 c, - IN UINT32 p -) +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ) /*++ Routine Description: @@ -1290,90 +1276,89 @@ Returns: (VOID) --*/ { - STATIC UINT32 CPos; + STATIC UINT32 CPos; - if ((mOutputMask >>= 1) == 0) { - mOutputMask = 1U << (UINT8_BIT - 1); - if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { - SendBlock(); - mOutputPos = 0; - } - CPos = mOutputPos++; - mBuf[CPos] = 0; - } - mBuf[mOutputPos++] = (UINT8)c; - mCFreq[c]++; - if (c >= (1U << UINT8_BIT)) { - mBuf[CPos] |= mOutputMask; - mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT); - mBuf[mOutputPos++] = (UINT8)p; - c = 0; - while (p) { - p >>= 1; - c++; - } - mPFreq[c]++; - } + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { + SendBlock(); + mOutputPos = 0; + } + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + mBuf[mOutputPos++] = (UINT8) c; + mCFreq[c]++; + if (c >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT); + mBuf[mOutputPos++] = (UINT8) p; + c = 0; + while (p) { + p >>= 1; + c++; + } + mPFreq[c]++; + } } STATIC VOID -HufEncodeStart() +HufEncodeStart () { - INT32 i; + INT32 i; - for (i = 0; i < NC; i++) { - mCFreq[i] = 0; - } - for (i = 0; i < NP; i++) { - mPFreq[i] = 0; - } - mOutputPos = mOutputMask = 0; - InitPutBits(); - return; + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } + mOutputPos = mOutputMask = 0; + InitPutBits(); + return; } -STATIC -VOID -HufEncodeEnd() +STATIC +VOID +HufEncodeEnd () { - SendBlock(); - - // - // Flush remaining bits - // - PutBits(UINT8_BIT - 1, 0); - - return; + SendBlock(); + + // + // Flush remaining bits + // + PutBits(UINT8_BIT - 1, 0); + + return; } -STATIC -VOID -MakeCrcTable() +STATIC +VOID +MakeCrcTable () { - UINT32 i, j, r; + UINT32 i, j, r; - for (i = 0; i <= UINT8_MAX; i++) { - r = i; - for (j = 0; j < UINT8_BIT; j++) { - if (r & 1) { - r = (r >> 1) ^ CRCPOLY; - } - else { - r >>= 1; - } - } - mCrcTable[i] = (UINT16)r; - } + for (i = 0; i <= UINT8_MAX; i++) { + r = i; + for (j = 0; j < UINT8_BIT; j++) { + if (r & 1) { + r = (r >> 1) ^ CRCPOLY; + } else { + r >>= 1; + } + } + mCrcTable[i] = (UINT16)r; + } } -STATIC -VOID -PutBits( - IN INT32 n, - IN UINT32 x -) +STATIC +VOID +PutBits ( + IN INT32 n, + IN UINT32 x + ) /*++ Routine Description: @@ -1383,53 +1368,51 @@ Routine Description: Argments: n - the rightmost n bits of the data is used - x - the data + x - the data Returns: (VOID) --*/ { - UINT8 Temp; + UINT8 Temp; + + if (n < mBitCount) { + mSubBitBuf |= x << (mBitCount -= n); + } else { + + Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; - if (n < mBitCount) { - mSubBitBuf |= x << (mBitCount -= n); - } - else { - - Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount))); - if (mDst < mDstUpperLimit) { - *mDst++ = Temp; - } - mCompSize++; - - if (n < UINT8_BIT) { - mSubBitBuf = x << (mBitCount = UINT8_BIT - n); - } - else { - - Temp = (UINT8)(x >> (n - UINT8_BIT)); - if (mDst < mDstUpperLimit) { - *mDst++ = Temp; - } - mCompSize++; - - mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n); - } - } + if (n < UINT8_BIT) { + mSubBitBuf = x << (mBitCount = UINT8_BIT - n); + } else { + + Temp = (UINT8)(x >> (n - UINT8_BIT)); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n); + } + } } -STATIC -INT32 -FreadCrc( - OUT UINT8 *p, - IN INT32 n -) +STATIC +INT32 +FreadCrc ( + OUT UINT8 *p, + IN INT32 n + ) /*++ Routine Description: Read in source data - + Arguments: p - the buffer to hold the data @@ -1438,157 +1421,156 @@ Arguments: Returns: number of bytes actually read - + --*/ { - INT32 i; + INT32 i; - for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) { - *p++ = *mSrc++; - } - n = i; + for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) { + *p++ = *mSrc++; + } + n = i; - p -= n; - mOrigSize += n; - while (--i >= 0) { - UPDATE_CRC(*p++); - } - return n; + p -= n; + mOrigSize += n; + while (--i >= 0) { + UPDATE_CRC(*p++); + } + return n; } -STATIC -VOID -InitPutBits() +STATIC +VOID +InitPutBits () { - mBitCount = UINT8_BIT; - mSubBitBuf = 0; + mBitCount = UINT8_BIT; + mSubBitBuf = 0; } -STATIC -VOID -CountLen( - IN INT32 i -) +STATIC +VOID +CountLen ( + IN INT32 i + ) /*++ Routine Description: Count the number of each code length for a Huffman tree. - + Arguments: i - the top node - + Returns: (VOID) --*/ { - STATIC INT32 Depth = 0; + STATIC INT32 Depth = 0; - if (i < mN) { - mLenCnt[(Depth < 16) ? Depth : 16]++; - } - else { - Depth++; - CountLen(mLeft[i]); - CountLen(mRight[i]); - Depth--; - } + if (i < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } else { + Depth++; + CountLen(mLeft [i]); + CountLen(mRight[i]); + Depth--; + } } -STATIC -VOID -MakeLen( - IN INT32 Root -) +STATIC +VOID +MakeLen ( + IN INT32 Root + ) /*++ Routine Description: Create code length array for a Huffman tree - + Arguments: Root - the root of the tree --*/ { - INT32 i, k; - UINT32 Cum; + INT32 i, k; + UINT32 Cum; - for (i = 0; i <= 16; i++) { - mLenCnt[i] = 0; - } - CountLen(Root); - - // - // Adjust the length count array so that - // no code will be generated longer than its designated length - // - - Cum = 0; - for (i = 16; i > 0; i--) { - Cum += mLenCnt[i] << (16 - i); - } - while (Cum != (1U << 16)) { - mLenCnt[16]--; - for (i = 15; i > 0; i--) { - if (mLenCnt[i] != 0) { - mLenCnt[i]--; - mLenCnt[i + 1] += 2; - break; - } - } - Cum--; - } - for (i = 16; i > 0; i--) { - k = mLenCnt[i]; - while (--k >= 0) { - mLen[*mSortPtr++] = (UINT8)i; - } - } + for (i = 0; i <= 16; i++) { + mLenCnt[i] = 0; + } + CountLen(Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + + Cum = 0; + for (i = 16; i > 0; i--) { + Cum += mLenCnt[i] << (16 - i); + } + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (i = 15; i > 0; i--) { + if (mLenCnt[i] != 0) { + mLenCnt[i]--; + mLenCnt[i+1] += 2; + break; + } + } + Cum--; + } + for (i = 16; i > 0; i--) { + k = mLenCnt[i]; + while (--k >= 0) { + mLen[*mSortPtr++] = (UINT8)i; + } + } } -STATIC -VOID -DownHeap( - IN INT32 i -) +STATIC +VOID +DownHeap ( + IN INT32 i + ) { - INT32 j, k; + INT32 j, k; - // - // priority queue: send i-th entry down heap - // - - k = mHeap[i]; - while ((j = 2 * i) <= mHeapSize) { - if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) { - j++; - } - if (mFreq[k] <= mFreq[mHeap[j]]) { - break; - } - mHeap[i] = mHeap[j]; - i = j; - } - mHeap[i] = (INT16)k; + // + // priority queue: send i-th entry down heap + // + + k = mHeap[i]; + while ((j = 2 * i) <= mHeapSize) { + if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) { + j++; + } + if (mFreq[k] <= mFreq[mHeap[j]]) { + break; + } + mHeap[i] = mHeap[j]; + i = j; + } + mHeap[i] = (INT16)k; } -STATIC -VOID -MakeCode( - IN INT32 n, - IN UINT8 Len[], - OUT UINT16 Code[] -) +STATIC +VOID +MakeCode ( + IN INT32 n, + IN UINT8 Len[], + OUT UINT16 Code[] + ) /*++ Routine Description: Assign code to each symbol based on the code length array - + Arguments: n - number of symbols @@ -1599,101 +1581,101 @@ Returns: (VOID) --*/ { - INT32 i; - UINT16 Start[18]; + INT32 i; + UINT16 Start[18]; - Start[1] = 0; - for (i = 1; i <= 16; i++) { - Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1); - } - for (i = 0; i < n; i++) { - Code[i] = Start[Len[i]]++; - } + Start[1] = 0; + for (i = 1; i <= 16; i++) { + Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1); + } + for (i = 0; i < n; i++) { + Code[i] = Start[Len[i]]++; + } } -STATIC -INT32 -MakeTree( - IN INT32 NParm, - IN UINT16 FreqParm[], - OUT UINT8 LenParm[], - OUT UINT16 CodeParm[] -) +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[], + OUT UINT16 CodeParm[] + ) /*++ Routine Description: Generates Huffman codes given a frequency distribution of symbols - + Arguments: NParm - number of symbols FreqParm - frequency of each symbol LenParm - code length for each symbol CodeParm - code for each symbol - + Returns: Root of the Huffman tree. - + --*/ { - INT32 i, j, k, Avail; + INT32 i, j, k, Avail; + + // + // make tree, calculate len[], return root + // - // - // make tree, calculate len[], return root - // - - mN = NParm; - mFreq = FreqParm; - mLen = LenParm; - Avail = mN; - mHeapSize = 0; - mHeap[1] = 0; - for (i = 0; i < mN; i++) { - mLen[i] = 0; - if (mFreq[i]) { - mHeap[++mHeapSize] = (INT16)i; - } - } - if (mHeapSize < 2) { - CodeParm[mHeap[1]] = 0; - return mHeap[1]; - } - for (i = mHeapSize / 2; i >= 1; i--) { - - // - // make priority queue - // - DownHeap(i); - } - mSortPtr = CodeParm; - do { - i = mHeap[1]; - if (i < mN) { - *mSortPtr++ = (UINT16)i; - } - mHeap[1] = mHeap[mHeapSize--]; - DownHeap(1); - j = mHeap[1]; - if (j < mN) { - *mSortPtr++ = (UINT16)j; - } - k = Avail++; - mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]); - mHeap[1] = (INT16)k; - DownHeap(1); - mLeft[k] = (UINT16)i; - mRight[k] = (UINT16)j; - } while (mHeapSize > 1); - - mSortPtr = CodeParm; - MakeLen(k); - MakeCode(NParm, LenParm, CodeParm); - - // - // return root - // - return k; + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (i = 0; i < mN; i++) { + mLen[i] = 0; + if (mFreq[i]) { + mHeap[++mHeapSize] = (INT16)i; + } + } + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + for (i = mHeapSize / 2; i >= 1; i--) { + + // + // make priority queue + // + DownHeap(i); + } + mSortPtr = CodeParm; + do { + i = mHeap[1]; + if (i < mN) { + *mSortPtr++ = (UINT16)i; + } + mHeap[1] = mHeap[mHeapSize--]; + DownHeap(1); + j = mHeap[1]; + if (j < mN) { + *mSortPtr++ = (UINT16)j; + } + k = Avail++; + mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]); + mHeap[1] = (INT16)k; + DownHeap(1); + mLeft[k] = (UINT16)i; + mRight[k] = (UINT16)j; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen(k); + MakeCode(NParm, LenParm, CodeParm); + + // + // return root + // + return k; } diff --git a/Tiano/EfiTianoCompress.h b/Tiano/EfiTianoCompress.h index b317cfd..9dc042e 100644 --- a/Tiano/EfiTianoCompress.h +++ b/Tiano/EfiTianoCompress.h @@ -20,8 +20,8 @@ Header file for compression routine. */ -#ifndef _EFITIANOCOMPRESS_H_ -#define _EFITIANOCOMPRESS_H_ +#ifndef EFITIANOCOMPRESS_H +#define EFITIANOCOMPRESS_H #include #include @@ -32,84 +32,87 @@ Header file for compression routine. extern "C" { #endif - /*++ + /*++ - Routine Description: + Routine Description: - Tiano compression routine. + Tiano compression routine. - Arguments: + Arguments: - SrcBuffer - The buffer storing the source data - SrcSize - The size of source data - DstBuffer - The buffer to store the compressed data - DstSize - On input, the size of DstBuffer; On output, - the size of the actual compressed data. + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. - Returns: + Returns: - EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, - DstSize contains the size needed. - EFI_SUCCESS - Compression is successful. - EFI_OUT_OF_RESOURCES - No resource to complete function. - EFI_INVALID_PARAMETER - Parameter supplied is wrong. + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. - --*/ - EFI_STATUS - TianoCompress( - IN CONST VOID *SrcBuffer, - IN UINT32 SrcSize, - IN VOID *DstBuffer, - IN OUT UINT32 *DstSize - ); + --*/ + EFI_STATUS + TianoCompress( + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize + ) + ; - EFI_STATUS - TianoCompressLegacy( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize - ); - /*++ + EFI_STATUS + TianoCompressLegacy( + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize + ) + ; + /*++ - Routine Description: + Routine Description: - EFI 1.1 compression routine. + EFI 1.1 compression routine. - Arguments: + Arguments: - SrcBuffer - The buffer storing the source data - SrcSize - The size of source data - DstBuffer - The buffer to store the compressed data - DstSize - On input, the size of DstBuffer; On output, - the size of the actual compressed data. + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. - Returns: + Returns: - EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, - DstSize contains the size needed. - EFI_SUCCESS - Compression is successful. - EFI_OUT_OF_RESOURCES - No resource to complete function. - EFI_INVALID_PARAMETER - Parameter supplied is wrong. + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. - --*/ - EFI_STATUS - EfiCompress( - IN CONST VOID *SrcBuffer, - IN UINT32 SrcSize, - IN VOID *DstBuffer, - IN OUT UINT32 *DstSize - ); - - EFI_STATUS - EfiCompressLegacy( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize - ); + --*/ + EFI_STATUS + EfiCompress( + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize + ) + ; + EFI_STATUS + EfiCompressLegacy( + CONST VOID *SrcBuffer, + UINT32 SrcSize, + VOID *DstBuffer, + UINT32 *DstSize + ) + ; #ifdef __cplusplus } #endif -#endif +#endif // EFITIANOCOMPRESS_H diff --git a/Tiano/EfiTianoCompressLegacy.c b/Tiano/EfiTianoCompressLegacy.c index 9aed6f1..11e071c 100644 --- a/Tiano/EfiTianoCompressLegacy.c +++ b/Tiano/EfiTianoCompressLegacy.c @@ -71,190 +71,190 @@ typedef INT32 NODE; // STATIC -VOID -PutDword( - UINT32 Data + VOID + PutDword( + UINT32 Data + ); + +STATIC + INT32 + AllocateMemory ( + VOID + ); + +STATIC + VOID + FreeMemory ( + VOID + ); + +STATIC + VOID + InitSlide ( + VOID + ); + +STATIC + NODE + Child ( + NODE NodeQ, + UINT8 CharC + ); + +STATIC + VOID + MakeChild ( + NODE NodeQ, + UINT8 CharC, + NODE NodeR + ); + +STATIC + VOID + Split ( + NODE Old + ); + +STATIC + VOID + InsertNode ( + VOID + ); + +STATIC + VOID + DeleteNode ( + VOID + ); + +STATIC + VOID + GetNextMatch ( + VOID + ); + +STATIC + INT32 + Encode ( + VOID + ); + +STATIC + VOID + CountTFreq ( + VOID + ); + +STATIC + VOID + WritePTLen ( + INT32 Number, + INT32 nbit, + INT32 Special + ); + +STATIC + VOID + WriteCLen ( + VOID + ); + +STATIC + VOID + EncodeC ( + INT32 Value + ); + +STATIC + VOID + EncodeP ( + UINT32 Value + ); + +STATIC + VOID + SendBlock ( + VOID + ); + +STATIC + VOID + Output ( + UINT32 c, + UINT32 p + ); + +STATIC + VOID + HufEncodeStart ( + VOID + ); + +STATIC + VOID + HufEncodeEnd ( + VOID + ); + +STATIC + VOID + MakeCrcTable ( + VOID + ); + +STATIC + VOID + PutBits ( + INT32 Number, + UINT32 Value + ); + +STATIC + INT32 + FreadCrc ( + UINT8 *Pointer, + INT32 Number + ); + +STATIC + VOID + InitPutBits ( + VOID + ); + +STATIC + VOID + CountLen ( + INT32 Index + ); + +STATIC + VOID + MakeLen ( + INT32 Root + ); + +STATIC + VOID + DownHeap ( + INT32 Index + ); + +STATIC + VOID + MakeCode ( + INT32 Number, + UINT8 Len[ ], + UINT16 Code[] ); STATIC -INT32 -AllocateMemory( - VOID -); - -STATIC -VOID -FreeMemory( - VOID -); - -STATIC -VOID -InitSlide( - VOID -); - -STATIC -NODE -Child( - NODE NodeQ, - UINT8 CharC -); - -STATIC -VOID -MakeChild( - NODE NodeQ, - UINT8 CharC, - NODE NodeR -); - -STATIC -VOID -Split( - NODE Old -); - -STATIC -VOID -InsertNode( - VOID -); - -STATIC -VOID -DeleteNode( - VOID -); - -STATIC -VOID -GetNextMatch( - VOID -); - -STATIC -INT32 -Encode( - VOID -); - -STATIC -VOID -CountTFreq( - VOID -); - -STATIC -VOID -WritePTLen( - INT32 Number, - INT32 nbit, - INT32 Special -); - -STATIC -VOID -WriteCLen( - VOID -); - -STATIC -VOID -EncodeC( - INT32 Value -); - -STATIC -VOID -EncodeP( - UINT32 Value -); - -STATIC -VOID -SendBlock( - VOID -); - -STATIC -VOID -Output( - UINT32 c, - UINT32 p -); - -STATIC -VOID -HufEncodeStart( - VOID -); - -STATIC -VOID -HufEncodeEnd( - VOID -); - -STATIC -VOID -MakeCrcTable( - VOID -); - -STATIC -VOID -PutBits( - INT32 Number, - UINT32 Value -); - -STATIC -INT32 -FreadCrc( - UINT8 *Pointer, - INT32 Number -); - -STATIC -VOID -InitPutBits( - VOID -); - -STATIC -VOID -CountLen( - INT32 Index -); - -STATIC -VOID -MakeLen( - INT32 Root -); - -STATIC -VOID -DownHeap( - INT32 Index -); - -STATIC -VOID -MakeCode( - INT32 Number, - UINT8 Len[], - UINT16 Code[] -); - -STATIC -INT32 -MakeTree( - INT32 NParm, - UINT16 FreqParm[], - UINT8 LenParm[], - UINT16 CodeParm[] + INT32 + MakeTree ( + INT32 NParm, + UINT16 FreqParm[], + UINT8 LenParm[ ], + UINT16 CodeParm[] ); // @@ -269,7 +269,7 @@ STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; STATIC UINT32 mCompSize, mOrigSize; STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], -mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; + mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; STATIC UINT8 mPbit; @@ -280,10 +280,10 @@ STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NU // EFI_STATUS EfiCompressLegacy( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize +CONST VOID *SrcBuffer, +UINT32 SrcSize, +VOID *DstBuffer, +UINT32 *DstSize ) /*++ @@ -309,1573 +309,1557 @@ EFI_INVALID_PARAMETER - Parameter supplied is wrong. --*/ { - INT32 Status; + INT32 Status; - // - // Initializations - // - mPbit = 4; + // + // Initializations + // + mPbit = 4; - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; - mSrc = (UINT8*)SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst + *DstSize; + mSrc = (UINT8*) SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; - PutDword(0L); - PutDword(0L); + PutDword(0L); + PutDword(0L); - MakeCrcTable(); + MakeCrcTable(); - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; - // - // Compress it - // - Status = Encode(); - if (Status) { - return EFI_OUT_OF_RESOURCES; - } - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } - // - // Fill compressed size and original size - // - mDst = DstBuffer; - PutDword(mCompSize + 1); - PutDword(mOrigSize); + // + // Compress it + // + Status = Encode(); + if (Status) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize + 1); + PutDword(mOrigSize); - // - // Return - // - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } - else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + // + // Return + // + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } + else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } EFI_STATUS -TianoCompressLegacy( - CONST VOID *SrcBuffer, - UINT32 SrcSize, - VOID *DstBuffer, - UINT32 *DstSize +TianoCompressLegacy ( +CONST VOID *SrcBuffer, +UINT32 SrcSize, +VOID *DstBuffer, +UINT32 *DstSize ) -/*++ + /*++ -Routine Description: + Routine Description: -The internal implementation of [Efi/Tiano]Compress(). + The internal implementation of [Efi/Tiano]Compress(). -Arguments: + Arguments: -SrcBuffer - The buffer storing the source data -SrcSize - The size of source data -DstBuffer - The buffer to store the compressed data -DstSize - On input, the size of DstBuffer; On output, -the size of the actual compressed data. -Version - The version of de/compression algorithm. -Version 1 for UEFI 2.0 de/compression algorithm. -Version 2 for Tiano de/compression algorithm. + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + Version - The version of de/compression algorithm. + Version 1 for UEFI 2.0 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. -Returns: + Returns: -EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, -DstSize contains the size needed. -EFI_SUCCESS - Compression is successful. -EFI_OUT_OF_RESOURCES - No resource to complete function. -EFI_INVALID_PARAMETER - Parameter supplied is wrong. + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. ---*/ + --*/ { - INT32 Status; + INT32 Status; - // - // Initializations - // - mPbit = 5; + // + // Initializations + // + mPbit = 5; - mBufSiz = 0; - mBuf = NULL; - mText = NULL; - mLevel = NULL; - mChildCount = NULL; - mPosition = NULL; - mParent = NULL; - mPrev = NULL; - mNext = NULL; + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; - mSrc = (UINT8*)SrcBuffer; - mSrcUpperLimit = mSrc + SrcSize; - mDst = DstBuffer; - mDstUpperLimit = mDst + *DstSize; + mSrc = (UINT8*) SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst +*DstSize; - PutDword(0L); - PutDword(0L); + PutDword (0L); + PutDword (0L); - MakeCrcTable(); + MakeCrcTable (); - mOrigSize = mCompSize = 0; - mCrc = INIT_CRC; + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; - // - // Compress it - // - Status = Encode(); - if (Status) { - return EFI_OUT_OF_RESOURCES; - } - // - // Null terminate the compressed data - // - if (mDst < mDstUpperLimit) { - *mDst++ = 0; - } - // - // Fill compressed size and original size - // - mDst = DstBuffer; - PutDword(mCompSize + 1); - PutDword(mOrigSize); + // + // Compress it + // + Status = Encode (); + if (Status) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill compressed size and original size + // + mDst = DstBuffer; + PutDword (mCompSize + 1); + PutDword (mOrigSize); - // - // Return - // - if (mCompSize + 1 + 8 > *DstSize) { - *DstSize = mCompSize + 1 + 8; - return EFI_BUFFER_TOO_SMALL; - } - else { - *DstSize = mCompSize + 1 + 8; - return EFI_SUCCESS; - } + // + // Return + // + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } } STATIC -VOID -PutDword( - UINT32 Data -) -/*++ + VOID + PutDword ( + UINT32 Data + ) + /*++ -Routine Description: + Routine Description: -Put a DWORD to output stream + Put a DWORD to output stream -Arguments: + Arguments: -Data - the DWORD to put + Data - the DWORD to put -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); + } - if (mDst < mDstUpperLimit) { - *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); - } + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); + } } STATIC -INT32 -AllocateMemory( - VOID -) -/*++ + INT32 + AllocateMemory ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Allocate memory spaces for data structures used compression process + Allocate memory spaces for data structures used compression process -Arguments: -VOID + Arguments: + VOID -Returns: + Returns: -EFI_SUCCESS - Memory is allocated successfully -EFI_OUT_OF_RESOURCES - Allocation fails + EFI_SUCCESS - Memory is allocated successfully + EFI_OUT_OF_RESOURCES - Allocation fails ---*/ + --*/ { - UINT32 Index; + UINT32 Index; - mText = malloc(WNDSIZ * 2 + MAXMATCH); - if (NULL == mText) - return EFI_OUT_OF_RESOURCES; + mText = malloc (WNDSIZ * 2 + MAXMATCH); + if (!mText) return EFI_OUT_OF_RESOURCES; + for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { + mText[Index] = 0; + } - for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { - mText[Index] = 0; - } + mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); + if (!mLevel) return EFI_OUT_OF_RESOURCES; + mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); + if (!mChildCount) return EFI_OUT_OF_RESOURCES; + mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); + if (!mPosition) return EFI_OUT_OF_RESOURCES; + mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); + if (!mParent) return EFI_OUT_OF_RESOURCES; + mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); + if (!mPrev) return EFI_OUT_OF_RESOURCES; + mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); + if (!mNext) return EFI_OUT_OF_RESOURCES; - mLevel = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); - mChildCount = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); - mPosition = malloc((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); - mParent = malloc(WNDSIZ * 2 * sizeof(*mParent)); - mPrev = malloc(WNDSIZ * 2 * sizeof(*mPrev)); - mNext = malloc((MAX_HASH_VAL + 1) * sizeof(*mNext)); + mBufSiz = BLKSIZ; + mBuf = malloc (mBufSiz); + while (mBuf == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } - mBufSiz = BLKSIZ; - mBuf = malloc(mBufSiz); - while (mBuf == NULL) { - mBufSiz = (mBufSiz / 10U) * 9U; - if (mBufSiz < 4 * 1024U) { - return EFI_OUT_OF_RESOURCES; - } + mBuf = malloc (mBufSiz); + } - mBuf = malloc(mBufSiz); - } + mBuf[0] = 0; - mBuf[0] = 0; - - return EFI_SUCCESS; + return EFI_SUCCESS; } VOID -FreeMemory( - VOID -) -/*++ + FreeMemory ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Called when compression is completed to free memory previously allocated. + Called when compression is completed to free memory previously allocated. -Arguments: (VOID) + Arguments: (VOID) -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - if (mText != NULL) { - free(mText); - } + if (mText != NULL) { + free (mText); + } - if (mLevel != NULL) { - free(mLevel); - } + if (mLevel != NULL) { + free (mLevel); + } - if (mChildCount != NULL) { - free(mChildCount); - } + if (mChildCount != NULL) { + free (mChildCount); + } - if (mPosition != NULL) { - free(mPosition); - } + if (mPosition != NULL) { + free (mPosition); + } - if (mParent != NULL) { - free(mParent); - } + if (mParent != NULL) { + free (mParent); + } - if (mPrev != NULL) { - free(mPrev); - } + if (mPrev != NULL) { + free (mPrev); + } - if (mNext != NULL) { - free(mNext); - } + if (mNext != NULL) { + free (mNext); + } - if (mBuf != NULL) { - free(mBuf); - } + if (mBuf != NULL) { + free (mBuf); + } - return; + return ; } STATIC -VOID -InitSlide( - VOID -) -/*++ + VOID + InitSlide ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Initialize String Info Log data structures + Initialize String Info Log data structures -Arguments: (VOID) + Arguments: (VOID) -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - NODE Index; + NODE Index; - for (Index = (NODE)WNDSIZ; Index <= (NODE)WNDSIZ + UINT8_MAX; Index++) { - mLevel[Index] = 1; - mPosition[Index] = NIL; // sentinel - } + for (Index = (NODE) WNDSIZ; Index <= (NODE) WNDSIZ + UINT8_MAX; Index++) { + mLevel[Index] = 1; + mPosition[Index] = NIL; // sentinel + } - for (Index = (NODE)WNDSIZ; Index < (NODE)WNDSIZ * 2; Index++) { - mParent[Index] = NIL; - } + for (Index = (NODE) WNDSIZ; Index < (NODE) WNDSIZ * 2; Index++) { + mParent[Index] = NIL; + } - mAvail = 1; - for (Index = 1; Index < (NODE)WNDSIZ - 1; Index++) { - mNext[Index] = (NODE)(Index + 1); - } + mAvail = 1; + for (Index = 1; Index < (NODE) WNDSIZ - 1; Index++) { + mNext[Index] = (NODE) (Index + 1); + } - mNext[WNDSIZ - 1] = NIL; - for (Index = (NODE)WNDSIZ * 2; Index <= (NODE)MAX_HASH_VAL; Index++) { - mNext[Index] = NIL; - } + mNext[WNDSIZ - 1] = NIL; + for (Index = (NODE) WNDSIZ * 2; Index <= (NODE) MAX_HASH_VAL; Index++) { + mNext[Index] = NIL; + } } STATIC -NODE -Child( - NODE NodeQ, - UINT8 CharC -) -/*++ + NODE + Child ( + NODE NodeQ, + UINT8 CharC + ) + /*++ -Routine Description: + Routine Description: -Find child node given the parent node and the edge character + Find child node given the parent node and the edge character -Arguments: + Arguments: -NodeQ - the parent node -CharC - the edge character + NodeQ - the parent node + CharC - the edge character -Returns: + Returns: -The child node (NIL if not found) + The child node (NIL if not found) ---*/ + --*/ { - NODE NodeR; + NODE NodeR; - NodeR = mNext[HASH(NodeQ, CharC)]; - // - // sentinel - // - mParent[NIL] = NodeQ; - while (mParent[NodeR] != NodeQ) { - NodeR = mNext[NodeR]; - } + NodeR = mNext[HASH (NodeQ, CharC)]; + // + // sentinel + // + mParent[NIL] = NodeQ; + while (mParent[NodeR] != NodeQ) { + NodeR = mNext[NodeR]; + } - return NodeR; + return NodeR; } STATIC -VOID -MakeChild( - NODE Parent, - UINT8 CharC, - NODE Child -) -/*++ + VOID + MakeChild ( + NODE Parent, + UINT8 CharC, + NODE Child + ) + /*++ -Routine Description: + Routine Description: -Create a new child for a given parent node. + Create a new child for a given parent node. -Arguments: + Arguments: -Parent - the parent node -CharC - the edge character -Child - the child node + Parent - the parent node + CharC - the edge character + Child - the child node -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - NODE Node1; - NODE Node2; + NODE Node1; + NODE Node2; - Node1 = (NODE)HASH(Parent, CharC); - Node2 = mNext[Node1]; - mNext[Node1] = Child; - mNext[Child] = Node2; - mPrev[Node2] = Child; - mPrev[Child] = Node1; - mParent[Child] = Parent; - mChildCount[Parent]++; + Node1 = (NODE) HASH (Parent, CharC); + Node2 = mNext[Node1]; + mNext[Node1] = Child; + mNext[Child] = Node2; + mPrev[Node2] = Child; + mPrev[Child] = Node1; + mParent[Child] = Parent; + mChildCount[Parent]++; } STATIC -VOID -Split( - NODE Old -) -/*++ + VOID + Split ( + NODE Old + ) + /*++ -Routine Description: + Routine Description: -Split a node. + Split a node. -Arguments: + Arguments: -Old - the node to split + Old - the node to split -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - NODE New; - NODE TempNode; + NODE New; + NODE TempNode; - New = mAvail; - mAvail = mNext[New]; - mChildCount[New] = 0; - TempNode = mPrev[Old]; - mPrev[New] = TempNode; - mNext[TempNode] = New; - TempNode = mNext[Old]; - mNext[New] = TempNode; - mPrev[TempNode] = New; - mParent[New] = mParent[Old]; - mLevel[New] = (UINT8)mMatchLen; - mPosition[New] = mPos; - MakeChild(New, mText[mMatchPos + mMatchLen], Old); - MakeChild(New, mText[mPos + mMatchLen], mPos); + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + TempNode = mPrev[Old]; + mPrev[New] = TempNode; + mNext[TempNode] = New; + TempNode = mNext[Old]; + mNext[New] = TempNode; + mPrev[TempNode] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8) mMatchLen; + mPosition[New] = mPos; + MakeChild (New, mText[mMatchPos + mMatchLen], Old); + MakeChild (New, mText[mPos + mMatchLen], mPos); } STATIC -VOID -InsertNode( - VOID -) -/*++ + VOID + InsertNode ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Insert string info for current position into the String Info Log + Insert string info for current position into the String Info Log -Arguments: (VOID) + Arguments: (VOID) -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - NODE NodeQ; - NODE NodeR; - NODE Index2; - NODE NodeT; - UINT8 CharC; - UINT8 *t1; - UINT8 *t2; + NODE NodeQ; + NODE NodeR; + NODE Index2; + NODE NodeT; + UINT8 CharC; + UINT8 *t1; + UINT8 *t2; - if (mMatchLen >= 4) { - // - // We have just got a long match, the target tree - // can be located by MatchPos + 1. Traverse the tree - // from bottom up to get to a proper starting point. - // The usage of PERC_FLAG ensures proper node deletion - // DeleteNode() later. - // - mMatchLen--; - NodeR = (NODE)((mMatchPos + 1) | WNDSIZ); - NodeQ = mParent[NodeR]; - while (NodeQ == NIL) { - NodeR = mNext[NodeR]; - NodeQ = mParent[NodeR]; - } + if (mMatchLen >= 4) { + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Traverse the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // DeleteNode() later. + // + mMatchLen--; + NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); + NodeQ = mParent[NodeR]; + while (NodeQ == NIL) { + NodeR = mNext[NodeR]; + NodeQ = mParent[NodeR]; + } - while (mLevel[NodeQ] >= mMatchLen) { - NodeR = NodeQ; - NodeQ = mParent[NodeQ]; - } + while (mLevel[NodeQ] >= mMatchLen) { + NodeR = NodeQ; + NodeQ = mParent[NodeQ]; + } - NodeT = NodeQ; - while (mPosition[NodeT] < 0) { - mPosition[NodeT] = mPos; - NodeT = mParent[NodeT]; - } + NodeT = NodeQ; + while (mPosition[NodeT] < 0) { + mPosition[NodeT] = mPos; + NodeT = mParent[NodeT]; + } - if (NodeT < (NODE)WNDSIZ) { - mPosition[NodeT] = (NODE)(mPos | (UINT32)PERC_FLAG); - } - } - else { - // - // Locate the target tree - // - NodeQ = (NODE)(mText[mPos] + WNDSIZ); - CharC = mText[mPos + 1]; - NodeR = Child(NodeQ, CharC); - if (NodeR == NIL) { - MakeChild(NodeQ, CharC, mPos); - mMatchLen = 1; - return; - } + if (NodeT < (NODE) WNDSIZ) { + mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); + } + } else { + // + // Locate the target tree + // + NodeQ = (NODE) (mText[mPos] + WNDSIZ); + CharC = mText[mPos + 1]; + NodeR = Child (NodeQ, CharC); + if (NodeR == NIL) { + MakeChild (NodeQ, CharC, mPos); + mMatchLen = 1; + return ; + } - mMatchLen = 2; - } - // - // Traverse down the tree to find a match. - // Update Position value along the route. - // Node split or creation is involved. - // - for (;;) { - if (NodeR >= (NODE)WNDSIZ) { - Index2 = MAXMATCH; - mMatchPos = NodeR; - } - else { - Index2 = mLevel[NodeR]; - mMatchPos = (NODE)(mPosition[NodeR] & (UINT32)~PERC_FLAG); - } + mMatchLen = 2; + } + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + for (;;) { + if (NodeR >= (NODE) WNDSIZ) { + Index2 = MAXMATCH; + mMatchPos = NodeR; + } else { + Index2 = mLevel[NodeR]; + mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + } - if (mMatchPos >= mPos) { - mMatchPos -= WNDSIZ; - } + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } - t1 = &mText[mPos + mMatchLen]; - t2 = &mText[mMatchPos + mMatchLen]; - while (mMatchLen < Index2) { - if (*t1 != *t2) { - Split(NodeR); - return; - } + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < Index2) { + if (*t1 != *t2) { + Split (NodeR); + return ; + } - mMatchLen++; - t1++; - t2++; - } + mMatchLen++; + t1++; + t2++; + } - if (mMatchLen >= MAXMATCH) { - break; - } + if (mMatchLen >= MAXMATCH) { + break; + } - mPosition[NodeR] = mPos; - NodeQ = NodeR; - NodeR = Child(NodeQ, *t1); - if (NodeR == NIL) { - MakeChild(NodeQ, *t1, mPos); - return; - } + mPosition[NodeR] = mPos; + NodeQ = NodeR; + NodeR = Child (NodeQ, *t1); + if (NodeR == NIL) { + MakeChild (NodeQ, *t1, mPos); + return ; + } - mMatchLen++; - } + mMatchLen++; + } - NodeT = mPrev[NodeR]; - mPrev[mPos] = NodeT; - mNext[NodeT] = mPos; - NodeT = mNext[NodeR]; - mNext[mPos] = NodeT; - mPrev[NodeT] = mPos; - mParent[mPos] = NodeQ; - mParent[NodeR] = NIL; + NodeT = mPrev[NodeR]; + mPrev[mPos] = NodeT; + mNext[NodeT] = mPos; + NodeT = mNext[NodeR]; + mNext[mPos] = NodeT; + mPrev[NodeT] = mPos; + mParent[mPos] = NodeQ; + mParent[NodeR] = NIL; - // - // Special usage of 'next' - // - mNext[NodeR] = mPos; + // + // Special usage of 'next' + // + mNext[NodeR] = mPos; } STATIC -VOID -DeleteNode( - VOID -) -/*++ + VOID + DeleteNode ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Delete outdated string info. (The Usage of PERC_FLAG -ensures a clean deletion) + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion) -Arguments: (VOID) + Arguments: (VOID) -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - NODE NodeQ; - NODE NodeR; - NODE NodeS; - NODE NodeT; - NODE NodeU; + NODE NodeQ; + NODE NodeR; + NODE NodeS; + NODE NodeT; + NODE NodeU; - if (mParent[mPos] == NIL) { - return; - } + if (mParent[mPos] == NIL) { + return ; + } - NodeR = mPrev[mPos]; - NodeS = mNext[mPos]; - mNext[NodeR] = NodeS; - mPrev[NodeS] = NodeR; - NodeR = mParent[mPos]; - mParent[mPos] = NIL; - if (NodeR >= (NODE)WNDSIZ) { - return; - } + NodeR = mPrev[mPos]; + NodeS = mNext[mPos]; + mNext[NodeR] = NodeS; + mPrev[NodeS] = NodeR; + NodeR = mParent[mPos]; + mParent[mPos] = NIL; + if (NodeR >= (NODE) WNDSIZ) { + return ; + } - mChildCount[NodeR]--; - if (mChildCount[NodeR] > 1) { - return; - } + mChildCount[NodeR]--; + if (mChildCount[NodeR] > 1) { + return ; + } - NodeT = (NODE)(mPosition[NodeR] & (UINT32)~PERC_FLAG); - if (NodeT >= mPos) { - NodeT -= WNDSIZ; - } + NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + if (NodeT >= mPos) { + NodeT -= WNDSIZ; + } - NodeS = NodeT; - NodeQ = mParent[NodeR]; - NodeU = mPosition[NodeQ]; - while (NodeU & (UINT32)PERC_FLAG) { - NodeU &= (UINT32)~PERC_FLAG; - if (NodeU >= mPos) { - NodeU -= WNDSIZ; - } + NodeS = NodeT; + NodeQ = mParent[NodeR]; + NodeU = mPosition[NodeQ]; + while (NodeU & (UINT32) PERC_FLAG) { + NodeU &= (UINT32)~PERC_FLAG; + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } - if (NodeU > NodeS) { - NodeS = NodeU; - } + if (NodeU > NodeS) { + NodeS = NodeU; + } - mPosition[NodeQ] = (NODE)(NodeS | WNDSIZ); - NodeQ = mParent[NodeQ]; - NodeU = mPosition[NodeQ]; - } + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); + NodeQ = mParent[NodeQ]; + NodeU = mPosition[NodeQ]; + } - if (NodeQ < (NODE)WNDSIZ) { - if (NodeU >= mPos) { - NodeU -= WNDSIZ; - } + if (NodeQ < (NODE) WNDSIZ) { + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } - if (NodeU > NodeS) { - NodeS = NodeU; - } + if (NodeU > NodeS) { + NodeS = NodeU; + } - mPosition[NodeQ] = (NODE)(NodeS | WNDSIZ | (UINT32)PERC_FLAG); - } + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); + } - NodeS = Child(NodeR, mText[NodeT + mLevel[NodeR]]); - NodeT = mPrev[NodeS]; - NodeU = mNext[NodeS]; - mNext[NodeT] = NodeU; - mPrev[NodeU] = NodeT; - NodeT = mPrev[NodeR]; - mNext[NodeT] = NodeS; - mPrev[NodeS] = NodeT; - NodeT = mNext[NodeR]; - mPrev[NodeT] = NodeS; - mNext[NodeS] = NodeT; - mParent[NodeS] = mParent[NodeR]; - mParent[NodeR] = NIL; - mNext[NodeR] = mAvail; - mAvail = NodeR; + NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); + NodeT = mPrev[NodeS]; + NodeU = mNext[NodeS]; + mNext[NodeT] = NodeU; + mPrev[NodeU] = NodeT; + NodeT = mPrev[NodeR]; + mNext[NodeT] = NodeS; + mPrev[NodeS] = NodeT; + NodeT = mNext[NodeR]; + mPrev[NodeT] = NodeS; + mNext[NodeS] = NodeT; + mParent[NodeS] = mParent[NodeR]; + mParent[NodeR] = NIL; + mNext[NodeR] = mAvail; + mAvail = NodeR; } STATIC -VOID -GetNextMatch( - VOID -) -/*++ + VOID + GetNextMatch ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Advance the current position (read new data if needed). -Delete outdated string info. Find a match string for current position. + Advance the current position (read new data if needed). + Delete outdated string info. Find a match string for current position. -Arguments: (VOID) + Arguments: (VOID) -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - INT32 Number; + INT32 Number; - mRemainder--; - mPos++; - if (mPos == WNDSIZ * 2) { - memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); - Number = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); - mRemainder += Number; - mPos = WNDSIZ; - } + mRemainder--; + mPos++; + if (mPos == WNDSIZ * 2) { + memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += Number; + mPos = WNDSIZ; + } - DeleteNode(); - InsertNode(); + DeleteNode (); + InsertNode (); } STATIC -INT32 -Encode( - VOID -) -/*++ + INT32 + Encode ( + VOID + ) + /*++ -Routine Description: + Routine Description: -The mac controlling routine for compression process. + The mac controlling routine for compression process. -Arguments: (VOID) + Arguments: (VOID) -Returns: + Returns: -EFI_SUCCESS - The compression is successful -EFI_OUT_0F_RESOURCES - Not enough memory for compression process + EFI_SUCCESS - The compression is successful + EFI_OUT_0F_RESOURCES - Not enough memory for compression process ---*/ + --*/ { - INT32 Status; - INT32 LastMatchLen; - NODE LastMatchPos; + INT32 Status; + INT32 LastMatchLen; + NODE LastMatchPos; - Status = AllocateMemory(); - if (Status) { - FreeMemory(); - return Status; - } + Status = AllocateMemory (); + if (Status) { + FreeMemory (); + return Status; + } - InitSlide(); + InitSlide (); - HufEncodeStart(); + HufEncodeStart (); - mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); + mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); - mMatchLen = 0; - mPos = WNDSIZ; - InsertNode(); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } - while (mRemainder > 0) { - LastMatchLen = mMatchLen; - LastMatchPos = mMatchPos; - GetNextMatch(); - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } - if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { - // - // Not enough benefits are gained by outputting a pointer, - // so just output the original character - // - Output(mText[mPos - 1], 0); + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + Output (mText[mPos - 1], 0); - } - else { + } else { - if (LastMatchLen == THRESHOLD) { - if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { - Output(mText[mPos - 1], 0); - continue; - } - } - // - // Outputting a pointer is beneficial enough, do it. - // - Output( - LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), - (mPos - LastMatchPos - 2) & (WNDSIZ - 1) - ); - LastMatchLen--; - while (LastMatchLen > 0) { - GetNextMatch(); - LastMatchLen--; - } + if (LastMatchLen == THRESHOLD) { + if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { + Output (mText[mPos - 1], 0); + continue; + } + } + // + // Outputting a pointer is beneficial enough, do it. + // + Output ( + LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1) + ); + LastMatchLen--; + while (LastMatchLen > 0) { + GetNextMatch (); + LastMatchLen--; + } - if (mMatchLen > mRemainder) { - mMatchLen = mRemainder; - } - } - } + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } - HufEncodeEnd(); - FreeMemory(); - return EFI_SUCCESS; + HufEncodeEnd (); + FreeMemory (); + return EFI_SUCCESS; } STATIC -VOID -CountTFreq( - VOID -) -/*++ + VOID + CountTFreq ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Count the frequencies for the Extra Set + Count the frequencies for the Extra Set -Arguments: (VOID) + Arguments: (VOID) -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - INT32 Index; - INT32 Index3; - INT32 Number; - INT32 Count; + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; - for (Index = 0; Index < NT; Index++) { - mTFreq[Index] = 0; - } + for (Index = 0; Index < NT; Index++) { + mTFreq[Index] = 0; + } - Number = NC; - while (Number > 0 && mCLen[Number - 1] == 0) { - Number--; - } + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } - Index = 0; - while (Index < Number) { - Index3 = mCLen[Index++]; - if (Index3 == 0) { - Count = 1; - while (Index < Number && mCLen[Index] == 0) { - Index++; - Count++; - } + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } - if (Count <= 2) { - mTFreq[0] = (UINT16)(mTFreq[0] + Count); - } - else if (Count <= 18) { - mTFreq[1]++; - } - else if (Count == 19) { - mTFreq[0]++; - mTFreq[1]++; - } - else { - mTFreq[2]++; - } - } - else { - mTFreq[Index3 + 2]++; - } - } + if (Count <= 2) { + mTFreq[0] = (UINT16) (mTFreq[0] + Count); + } else if (Count <= 18) { + mTFreq[1]++; + } else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } else { + mTFreq[2]++; + } + } else { + mTFreq[Index3 + 2]++; + } + } } STATIC -VOID -WritePTLen( - INT32 Number, - INT32 nbit, - INT32 Special -) -/*++ + VOID + WritePTLen ( + INT32 Number, + INT32 nbit, + INT32 Special + ) + /*++ -Routine Description: + Routine Description: -Outputs the code length array for the Extra Set or the Position Set. + Outputs the code length array for the Extra Set or the Position Set. -Arguments: + Arguments: -Number - the number of symbols -nbit - the number of bits needed to represent 'n' -Special - the special symbol that needs to be take care of + Number - the number of symbols + nbit - the number of bits needed to represent 'n' + Special - the special symbol that needs to be take care of -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - INT32 Index; - INT32 Index3; + INT32 Index; + INT32 Index3; - while (Number > 0 && mPTLen[Number - 1] == 0) { - Number--; - } + while (Number > 0 && mPTLen[Number - 1] == 0) { + Number--; + } - PutBits(nbit, Number); - Index = 0; - while (Index < Number) { - Index3 = mPTLen[Index++]; - if (Index3 <= 6) { - PutBits(3, Index3); - } - else { - PutBits(Index3 - 3, (1U << (Index3 - 3)) - 2); - } + PutBits (nbit, Number); + Index = 0; + while (Index < Number) { + Index3 = mPTLen[Index++]; + if (Index3 <= 6) { + PutBits (3, Index3); + } else { + PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); + } - if (Index == Special) { - while (Index < 6 && mPTLen[Index] == 0) { - Index++; - } + if (Index == Special) { + while (Index < 6 && mPTLen[Index] == 0) { + Index++; + } - PutBits(2, (Index - 3) & 3); - } - } + PutBits (2, (Index - 3) & 3); + } + } } STATIC -VOID -WriteCLen( - VOID -) -/*++ + VOID + WriteCLen ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Outputs the code length array for Char&Length Set + Outputs the code length array for Char&Length Set -Arguments: (VOID) + Arguments: (VOID) -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - INT32 Index; - INT32 Index3; - INT32 Number; - INT32 Count; + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; - Number = NC; - while (Number > 0 && mCLen[Number - 1] == 0) { - Number--; - } + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } - PutBits(CBIT, Number); - Index = 0; - while (Index < Number) { - Index3 = mCLen[Index++]; - if (Index3 == 0) { - Count = 1; - while (Index < Number && mCLen[Index] == 0) { - Index++; - Count++; - } + PutBits (CBIT, Number); + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } - if (Count <= 2) { - for (Index3 = 0; Index3 < Count; Index3++) { - PutBits(mPTLen[0], mPTCode[0]); - } - } - else if (Count <= 18) { - PutBits(mPTLen[1], mPTCode[1]); - PutBits(4, Count - 3); - } - else if (Count == 19) { - PutBits(mPTLen[0], mPTCode[0]); - PutBits(mPTLen[1], mPTCode[1]); - PutBits(4, 15); - } - else { - PutBits(mPTLen[2], mPTCode[2]); - PutBits(CBIT, Count - 20); - } - } - else { - PutBits(mPTLen[Index3 + 2], mPTCode[Index3 + 2]); - } - } + if (Count <= 2) { + for (Index3 = 0; Index3 < Count; Index3++) { + PutBits (mPTLen[0], mPTCode[0]); + } + } else if (Count <= 18) { + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, Count - 3); + } else if (Count == 19) { + PutBits (mPTLen[0], mPTCode[0]); + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, 15); + } else { + PutBits (mPTLen[2], mPTCode[2]); + PutBits (CBIT, Count - 20); + } + } else { + PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); + } + } } STATIC -VOID -EncodeC( - INT32 Value -) + VOID + EncodeC ( + INT32 Value + ) { - PutBits(mCLen[Value], mCCode[Value]); + PutBits (mCLen[Value], mCCode[Value]); } STATIC -VOID -EncodeP( - UINT32 Value -) + VOID + EncodeP ( + UINT32 Value + ) { - UINT32 Index; - UINT32 NodeQ; + UINT32 Index; + UINT32 NodeQ; - Index = 0; - NodeQ = Value; - while (NodeQ) { - NodeQ >>= 1; - Index++; - } + Index = 0; + NodeQ = Value; + while (NodeQ) { + NodeQ >>= 1; + Index++; + } - PutBits(mPTLen[Index], mPTCode[Index]); - if (Index > 1) { - PutBits(Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); - } + PutBits (mPTLen[Index], mPTCode[Index]); + if (Index > 1) { + PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); + } } STATIC -VOID -SendBlock( - VOID -) -/*++ + VOID + SendBlock ( + VOID + ) + /*++ -Routine Description: + Routine Description: -Huffman code the block and output it. + Huffman code the block and output it. -Arguments: -(VOID) + Arguments: + (VOID) -Returns: -(VOID) + Returns: + (VOID) ---*/ + --*/ { - UINT32 Index; - UINT32 Index2; - UINT32 Index3; - UINT32 Flags; - UINT32 Root; - UINT32 Pos; - UINT32 Size; - Flags = 0; + UINT32 Index; + UINT32 Index2; + UINT32 Index3; + UINT32 Flags; + UINT32 Root; + UINT32 Pos; + UINT32 Size; + Flags = 0; - Root = MakeTree(NC, mCFreq, mCLen, mCCode); - Size = mCFreq[Root]; - PutBits(16, Size); - if (Root >= NC) { - CountTFreq(); - Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); - if (Root >= NT) { - WritePTLen(NT, TBIT, 3); - } - else { - PutBits(TBIT, 0); - PutBits(TBIT, Root); - } + Root = MakeTree (NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + PutBits (16, Size); + if (Root >= NC) { + CountTFreq (); + Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen (NT, TBIT, 3); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, Root); + } - WriteCLen(); - } - else { - PutBits(TBIT, 0); - PutBits(TBIT, 0); - PutBits(CBIT, 0); - PutBits(CBIT, Root); - } + WriteCLen (); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, 0); + PutBits (CBIT, 0); + PutBits (CBIT, Root); + } - Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); - if (Root >= NP) { - WritePTLen(NP, mPbit, -1); - } - else { - PutBits(mPbit, 0); - PutBits(mPbit, Root); - } + Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen (NP, mPbit, -1); + } else { + PutBits (mPbit, 0); + PutBits (mPbit, Root); + } - Pos = 0; - for (Index = 0; Index < Size; Index++) { - if (Index % UINT8_BIT == 0) { - Flags = mBuf[Pos++]; - } - else { - Flags <<= 1; - } + Pos = 0; + for (Index = 0; Index < Size; Index++) { + if (Index % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } - if (Flags & (1U << (UINT8_BIT - 1))) { - EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); - Index3 = mBuf[Pos++]; - for (Index2 = 0; Index2 < 3; Index2++) { - Index3 <<= UINT8_BIT; - Index3 += mBuf[Pos++]; - } + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); + Index3 = mBuf[Pos++]; + for (Index2 = 0; Index2 < 3; Index2++) { + Index3 <<= UINT8_BIT; + Index3 += mBuf[Pos++]; + } - EncodeP(Index3); - } - else { - EncodeC(mBuf[Pos++]); - } - } + EncodeP (Index3); + } else { + EncodeC (mBuf[Pos++]); + } + } - for (Index = 0; Index < NC; Index++) { - mCFreq[Index] = 0; - } + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } - for (Index = 0; Index < NP; Index++) { - mPFreq[Index] = 0; - } + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } } STATIC -VOID -Output( - UINT32 CharC, - UINT32 Pos -) -/*++ + VOID + Output ( + UINT32 CharC, + UINT32 Pos + ) + /*++ -Routine Description: + Routine Description: -Outputs an Original Character or a Pointer + Outputs an Original Character or a Pointer -Arguments: + Arguments: -CharC - The original character or the 'String Length' element of a Pointer -Pos - The 'Position' field of a Pointer + CharC - The original character or the 'String Length' element of a Pointer + Pos - The 'Position' field of a Pointer -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - STATIC UINT32 CPos; + STATIC UINT32 CPos; - if ((mOutputMask >>= 1) == 0) { - mOutputMask = 1U << (UINT8_BIT - 1); - // - // Check the buffer overflow per outputting UINT8_BIT symbols - // which is an Original Character or a Pointer. The biggest - // symbol is a Pointer which occupies 5 bytes. - // - if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { - SendBlock(); - mOutputPos = 0; - } + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + // + // Check the buffer overflow per outputting UINT8_BIT symbols + // which is an Original Character or a Pointer. The biggest + // symbol is a Pointer which occupies 5 bytes. + // + if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { + SendBlock (); + mOutputPos = 0; + } - CPos = mOutputPos++; - mBuf[CPos] = 0; - } + CPos = mOutputPos++; + mBuf[CPos] = 0; + } - mBuf[mOutputPos++] = (UINT8)CharC; - mCFreq[CharC]++; - if (CharC >= (1U << UINT8_BIT)) { - mBuf[CPos] |= mOutputMask; - mBuf[mOutputPos++] = (UINT8)(Pos >> 24); - mBuf[mOutputPos++] = (UINT8)(Pos >> 16); - mBuf[mOutputPos++] = (UINT8)(Pos >> (UINT8_BIT)); - mBuf[mOutputPos++] = (UINT8)Pos; - CharC = 0; - while (Pos) { - Pos >>= 1; - CharC++; - } + mBuf[mOutputPos++] = (UINT8) CharC; + mCFreq[CharC]++; + if (CharC >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8) (Pos >> 24); + mBuf[mOutputPos++] = (UINT8) (Pos >> 16); + mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); + mBuf[mOutputPos++] = (UINT8) Pos; + CharC = 0; + while (Pos) { + Pos >>= 1; + CharC++; + } - mPFreq[CharC]++; - } + mPFreq[CharC]++; + } } STATIC -VOID -HufEncodeStart( - VOID -) + VOID + HufEncodeStart ( + VOID + ) { - INT32 Index; + INT32 Index; - for (Index = 0; Index < NC; Index++) { - mCFreq[Index] = 0; - } + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } - for (Index = 0; Index < NP; Index++) { - mPFreq[Index] = 0; - } + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } - mOutputPos = mOutputMask = 0; - InitPutBits(); - return; + mOutputPos = mOutputMask = 0; + InitPutBits (); + return ; } STATIC -VOID -HufEncodeEnd( - VOID -) + VOID + HufEncodeEnd ( + VOID + ) { - SendBlock(); + SendBlock (); - // - // Flush remaining bits - // - PutBits(UINT8_BIT - 1, 0); + // + // Flush remaining bits + // + PutBits (UINT8_BIT - 1, 0); - return; + return ; } STATIC -VOID -MakeCrcTable( - VOID -) + VOID + MakeCrcTable ( + VOID + ) { - UINT32 Index; - UINT32 Index2; - UINT32 Temp; + UINT32 Index; + UINT32 Index2; + UINT32 Temp; - for (Index = 0; Index <= UINT8_MAX; Index++) { - Temp = Index; - for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { - if (Temp & 1) { - Temp = (Temp >> 1) ^ CRCPOLY; - } - else { - Temp >>= 1; - } - } + for (Index = 0; Index <= UINT8_MAX; Index++) { + Temp = Index; + for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { + if (Temp & 1) { + Temp = (Temp >> 1) ^ CRCPOLY; + } else { + Temp >>= 1; + } + } - mCrcTable[Index] = (UINT16)Temp; - } + mCrcTable[Index] = (UINT16) Temp; + } } STATIC -VOID -PutBits( - INT32 Number, - UINT32 Value -) -/*++ + VOID + PutBits ( + INT32 Number, + UINT32 Value + ) + /*++ -Routine Description: + Routine Description: -Outputs rightmost n bits of x + Outputs rightmost n bits of x -Arguments: + Arguments: -Number - the rightmost n bits of the data is used -x - the data + Number - the rightmost n bits of the data is used + x - the data -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - UINT8 Temp; + UINT8 Temp; - while (Number >= mBitCount) { - // - // Number -= mBitCount should never equal to 32 - // - Temp = (UINT8)(mSubBitBuf | (Value >> (Number -= mBitCount))); - if (mDst < mDstUpperLimit) { - *mDst++ = Temp; - } + while (Number >= mBitCount) { + // + // Number -= mBitCount should never equal to 32 + // + Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } - mCompSize++; - mSubBitBuf = 0; - mBitCount = UINT8_BIT; - } + mCompSize++; + mSubBitBuf = 0; + mBitCount = UINT8_BIT; + } - mSubBitBuf |= Value << (mBitCount -= Number); + mSubBitBuf |= Value << (mBitCount -= Number); } STATIC -INT32 -FreadCrc( - UINT8 *Pointer, - INT32 Number -) -/*++ + INT32 + FreadCrc ( + UINT8 *Pointer, + INT32 Number + ) + /*++ -Routine Description: + Routine Description: -Read source data + Read source data -Arguments: + Arguments: -Pointer - the buffer to hold the data -Number - number of bytes to read + Pointer - the buffer to hold the data + Number - number of bytes to read -Returns: + Returns: -number of bytes actually read + number of bytes actually read ---*/ + --*/ { - INT32 Index; + INT32 Index; - for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { - *Pointer++ = *mSrc++; - } + for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { + *Pointer++ = *mSrc++; + } - Number = Index; + Number = Index; - Pointer -= Number; - mOrigSize += Number; - Index--; - while (Index >= 0) { - UPDATE_CRC(*Pointer++); - Index--; - } + Pointer -= Number; + mOrigSize += Number; + Index--; + while (Index >= 0) { + UPDATE_CRC (*Pointer++); + Index--; + } - return Number; + return Number; } STATIC -VOID -InitPutBits( - VOID -) + VOID + InitPutBits ( + VOID + ) { - mBitCount = UINT8_BIT; - mSubBitBuf = 0; + mBitCount = UINT8_BIT; + mSubBitBuf = 0; } STATIC -VOID -CountLen( - INT32 Index -) -/*++ + VOID + CountLen ( + INT32 Index + ) + /*++ -Routine Description: + Routine Description: -Count the number of each code length for a Huffman tree. + Count the number of each code length for a Huffman tree. -Arguments: + Arguments: -Index - the top node + Index - the top node -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - STATIC INT32 Depth = 0; + STATIC INT32 Depth = 0; - if (Index < mN) { - mLenCnt[(Depth < 16) ? Depth : 16]++; - } - else { - Depth++; - CountLen(mLeft[Index]); - CountLen(mRight[Index]); - Depth--; - } + if (Index < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } else { + Depth++; + CountLen (mLeft[Index]); + CountLen (mRight[Index]); + Depth--; + } } STATIC -VOID -MakeLen( - INT32 Root -) -/*++ + VOID + MakeLen ( + INT32 Root + ) + /*++ -Routine Description: + Routine Description: -Create code length array for a Huffman tree + Create code length array for a Huffman tree -Arguments: + Arguments: -Root - the root of the tree + Root - the root of the tree -Returns: + Returns: -VOID + VOID ---*/ + --*/ { - INT32 Index; - INT32 Index3; - UINT32 Cum; + INT32 Index; + INT32 Index3; + UINT32 Cum; - for (Index = 0; Index <= 16; Index++) { - mLenCnt[Index] = 0; - } + for (Index = 0; Index <= 16; Index++) { + mLenCnt[Index] = 0; + } - CountLen(Root); + CountLen (Root); - // - // Adjust the length count array so that - // no code will be generated longer than its designated length - // - Cum = 0; - for (Index = 16; Index > 0; Index--) { - Cum += mLenCnt[Index] << (16 - Index); - } + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + Cum = 0; + for (Index = 16; Index > 0; Index--) { + Cum += mLenCnt[Index] << (16 - Index); + } - while (Cum != (1U << 16)) { - mLenCnt[16]--; - for (Index = 15; Index > 0; Index--) { - if (mLenCnt[Index] != 0) { - mLenCnt[Index]--; - mLenCnt[Index + 1] += 2; - break; - } - } + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (Index = 15; Index > 0; Index--) { + if (mLenCnt[Index] != 0) { + mLenCnt[Index]--; + mLenCnt[Index + 1] += 2; + break; + } + } - Cum--; - } + Cum--; + } - for (Index = 16; Index > 0; Index--) { - Index3 = mLenCnt[Index]; - Index3--; - while (Index3 >= 0) { - mLen[*mSortPtr++] = (UINT8)Index; - Index3--; - } - } + for (Index = 16; Index > 0; Index--) { + Index3 = mLenCnt[Index]; + Index3--; + while (Index3 >= 0) { + mLen[*mSortPtr++] = (UINT8) Index; + Index3--; + } + } } STATIC -VOID -DownHeap( - INT32 Index -) + VOID + DownHeap ( + INT32 Index + ) { - INT32 Index2; - INT32 Index3; + INT32 Index2; + INT32 Index3; - // - // priority queue: send Index-th entry down heap - // - Index3 = mHeap[Index]; - Index2 = 2 * Index; - while (Index2 <= mHeapSize) { - if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { - Index2++; - } + // + // priority queue: send Index-th entry down heap + // + Index3 = mHeap[Index]; + Index2 = 2 * Index; + while (Index2 <= mHeapSize) { + if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { + Index2++; + } - if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { - break; - } + if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { + break; + } - mHeap[Index] = mHeap[Index2]; - Index = Index2; - Index2 = 2 * Index; - } + mHeap[Index] = mHeap[Index2]; + Index = Index2; + Index2 = 2 * Index; + } - mHeap[Index] = (INT16)Index3; + mHeap[Index] = (INT16) Index3; } STATIC -VOID -MakeCode( - INT32 Number, - UINT8 Len[], - UINT16 Code[] + VOID + MakeCode ( + INT32 Number, + UINT8 Len[ ], + UINT16 Code[] ) -/*++ + /*++ -Routine Description: + Routine Description: -Assign code to each symbol based on the code length array + Assign code to each symbol based on the code length array -Arguments: + Arguments: -Number - number of symbols -Len - the code length array -Code - stores codes for each symbol + Number - number of symbols + Len - the code length array + Code - stores codes for each symbol -Returns: (VOID) + Returns: (VOID) ---*/ + --*/ { - INT32 Index; - UINT16 Start[18]; + INT32 Index; + UINT16 Start[18]; - Start[1] = 0; - for (Index = 1; Index <= 16; Index++) { - Start[Index + 1] = (UINT16)((Start[Index] + mLenCnt[Index]) << 1); - } + Start[1] = 0; + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); + } - for (Index = 0; Index < Number; Index++) { - Code[Index] = Start[Len[Index]]++; - } + for (Index = 0; Index < Number; Index++) { + Code[Index] = Start[Len[Index]]++; + } } STATIC -INT32 -MakeTree( - INT32 NParm, - UINT16 FreqParm[], - UINT8 LenParm[], - UINT16 CodeParm[] + INT32 + MakeTree ( + INT32 NParm, + UINT16 FreqParm[], + UINT8 LenParm[ ], + UINT16 CodeParm[] ) -/*++ + /*++ -Routine Description: + Routine Description: -Generates Huffman codes given a frequency distribution of symbols + Generates Huffman codes given a frequency distribution of symbols -Arguments: + Arguments: -NParm - number of symbols -FreqParm - frequency of each symbol -LenParm - code length for each symbol -CodeParm - code for each symbol + NParm - number of symbols + FreqParm - frequency of each symbol + LenParm - code length for each symbol + CodeParm - code for each symbol -Returns: + Returns: -Root of the Huffman tree. + Root of the Huffman tree. ---*/ + --*/ { - INT32 Index; - INT32 Index2; - INT32 Index3; - INT32 Avail; + INT32 Index; + INT32 Index2; + INT32 Index3; + INT32 Avail; - // - // make tree, calculate len[], return root - // - mN = NParm; - mFreq = FreqParm; - mLen = LenParm; - Avail = mN; - mHeapSize = 0; - mHeap[1] = 0; - for (Index = 0; Index < mN; Index++) { - mLen[Index] = 0; - if (mFreq[Index]) { - mHeapSize++; - mHeap[mHeapSize] = (INT16)Index; - } - } + // + // make tree, calculate len[], return root + // + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (Index = 0; Index < mN; Index++) { + mLen[Index] = 0; + if (mFreq[Index]) { + mHeapSize++; + mHeap[mHeapSize] = (INT16) Index; + } + } - if (mHeapSize < 2) { - CodeParm[mHeap[1]] = 0; - return mHeap[1]; - } + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } - for (Index = mHeapSize / 2; Index >= 1; Index--) { - // - // make priority queue - // - DownHeap(Index); - } + for (Index = mHeapSize / 2; Index >= 1; Index--) { + // + // make priority queue + // + DownHeap (Index); + } - mSortPtr = CodeParm; - do { - Index = mHeap[1]; - if (Index < mN) { - *mSortPtr++ = (UINT16)Index; - } + mSortPtr = CodeParm; + do { + Index = mHeap[1]; + if (Index < mN) { + *mSortPtr++ = (UINT16) Index; + } - mHeap[1] = mHeap[mHeapSize--]; - DownHeap(1); - Index2 = mHeap[1]; - if (Index2 < mN) { - *mSortPtr++ = (UINT16)Index2; - } + mHeap[1] = mHeap[mHeapSize--]; + DownHeap (1); + Index2 = mHeap[1]; + if (Index2 < mN) { + *mSortPtr++ = (UINT16) Index2; + } - Index3 = Avail++; - mFreq[Index3] = (UINT16)(mFreq[Index] + mFreq[Index2]); - mHeap[1] = (INT16)Index3; - DownHeap(1); - mLeft[Index3] = (UINT16)Index; - mRight[Index3] = (UINT16)Index2; - } while (mHeapSize > 1); + Index3 = Avail++; + mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); + mHeap[1] = (INT16) Index3; + DownHeap (1); + mLeft[Index3] = (UINT16) Index; + mRight[Index3] = (UINT16) Index2; + } while (mHeapSize > 1); - mSortPtr = CodeParm; - MakeLen(Index3); - MakeCode(NParm, LenParm, CodeParm); + mSortPtr = CodeParm; + MakeLen (Index3); + MakeCode (NParm, LenParm, CodeParm); - // - // return root - // - return Index3; + // + // return root + // + return Index3; } diff --git a/Tiano/EfiTianoDecompress.c b/Tiano/EfiTianoDecompress.c index 10449f1..7f2f31a 100644 --- a/Tiano/EfiTianoDecompress.c +++ b/Tiano/EfiTianoDecompress.c @@ -50,40 +50,40 @@ Decompressor. Algorithm Ported from OPSD code (Decomp.asm) #endif typedef struct { - UINT8 *mSrcBase; // Starting address of compressed data - UINT8 *mDstBase; // Starting address of decompressed data - UINT32 mOutBuf; - UINT32 mInBuf; + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; - UINT16 mBitCount; - UINT32 mBitBuf; - UINT32 mSubBitBuf; - UINT16 mBlockSize; - UINT32 mCompSize; - UINT32 mOrigSize; + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; - UINT16 mBadTableFlag; + UINT16 mBadTableFlag; - UINT16 mLeft[2 * NC - 1]; - UINT16 mRight[2 * NC - 1]; - UINT8 mCLen[NC]; - UINT8 mPTLen[NPT]; - UINT16 mCTable[4096]; - UINT16 mPTTable[256]; + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; - // - // The length of the field 'Position Set Code Length Array Size' in Block Header. - // For EFI 1.1 de/compression algorithm, mPBit = 4 - // For Tiano de/compression algorithm, mPBit = 5 - // - UINT8 mPBit; + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm, mPBit = 4 + // For Tiano de/compression algorithm, mPBit = 5 + // + UINT8 mPBit; } SCRATCH_DATA; STATIC VOID FillBuf( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfBits +IN SCRATCH_DATA *Sd, +IN UINT16 NumOfBits ) /*++ @@ -100,38 +100,38 @@ Returns: (VOID) --*/ { - Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits); + Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits); - while (NumOfBits > Sd->mBitCount) { - Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + while (NumOfBits > Sd->mBitCount) { + Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); - if (Sd->mCompSize > 0) { - // - // Get 1 byte into SubBitBuf - // - Sd->mCompSize--; - Sd->mSubBitBuf = 0; - Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; - Sd->mBitCount = 8; - } - else { - // - // No more bits from the source, just pad zero bit. - // - Sd->mSubBitBuf = 0; - Sd->mBitCount = 8; - } - } + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + } + else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + } + } - Sd->mBitCount = (UINT16)(Sd->mBitCount - NumOfBits); - Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; + Sd->mBitCount = (UINT16)(Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; } STATIC UINT32 GetBits( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfBits +IN SCRATCH_DATA *Sd, +IN UINT16 NumOfBits ) /*++ @@ -152,23 +152,23 @@ The bits that are popped out. --*/ { - UINT32 OutBits; + UINT32 OutBits; - OutBits = (UINT32)(Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + OutBits = (UINT32)(Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); - FillBuf(Sd, NumOfBits); + FillBuf(Sd, NumOfBits); - return OutBits; + return OutBits; } STATIC UINT16 MakeTable( - IN SCRATCH_DATA *Sd, - IN UINT16 NumOfChar, - IN UINT8 *BitLen, - IN UINT16 TableBits, - OUT UINT16 *Table +IN SCRATCH_DATA *Sd, +IN UINT16 NumOfChar, +IN UINT8 *BitLen, +IN UINT16 TableBits, +OUT UINT16 *Table ) /*++ @@ -191,140 +191,140 @@ BAD_TABLE - The table is corrupted. --*/ { - UINT16 Count[17]; - UINT16 Weight[17]; - UINT16 Start[18]; - UINT16 *Pointer; - UINT16 Index3; - UINT16 Index; - UINT16 Len; - UINT16 Char; - UINT16 JuBits; - UINT16 Avail; - UINT16 NextCode; - UINT16 Mask; + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; - // - // TableBits should not be greater than 16. - // - if (TableBits >= (sizeof(Count) / sizeof(UINT16))) { - return (UINT16)BAD_TABLE; - } + // + // TableBits should not be greater than 16. + // + if (TableBits >= (sizeof(Count) / sizeof(UINT16))) { + return (UINT16)BAD_TABLE; + } - // - // Initialize Count array starting from Index 0, as there is a possibility of Count array being uninitialized. - // - for (Index = 0; Index <= 16; Index++) { - Count[Index] = 0; - } + // + // Initialize Count array starting from Index 0, as there is a possibility of Count array being uninitialized. + // + for (Index = 0; Index <= 16; Index++) { + Count[Index] = 0; + } - for (Index = 0; Index < NumOfChar; Index++) { - // - // Count array index should not be greater than or equal to its size. - // - if (BitLen[Index] < (sizeof(Count) / sizeof(UINT16))) { - Count[BitLen[Index]]++; - } - else { - return (UINT16)BAD_TABLE; - } - } + for (Index = 0; Index < NumOfChar; Index++) { + // + // Count array index should not be greater than or equal to its size. + // + if (BitLen[Index] < (sizeof(Count) / sizeof(UINT16))) { + Count[BitLen[Index]]++; + } + else { + return (UINT16)BAD_TABLE; + } + } - Start[0] = 0; - Start[1] = 0; + Start[0] = 0; + Start[1] = 0; - for (Index = 1; Index <= 16; Index++) { - Start[Index + 1] = (UINT16)(Start[Index] + (Count[Index] << (16 - Index))); - } + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16)(Start[Index] + (Count[Index] << (16 - Index))); + } - if (Start[17] != 0) { - /*(1U << 16)*/ - return (UINT16)BAD_TABLE; - } + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16)BAD_TABLE; + } - JuBits = (UINT16)(16 - TableBits); + JuBits = (UINT16)(16 - TableBits); - for (Index = 1; Index <= TableBits; Index++) { - Start[Index] >>= JuBits; - Weight[Index] = (UINT16)(1U << (TableBits - Index)); - } + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16)(1U << (TableBits - Index)); + } - while (Index <= 16) { - Weight[Index] = (UINT16)(1U << (16 - Index)); - Index++; - } + while (Index <= 16) { + Weight[Index] = (UINT16)(1U << (16 - Index)); + Index++; + } - Index = (UINT16)(Start[TableBits + 1] >> JuBits); + Index = (UINT16)(Start[TableBits + 1] >> JuBits); - if (Index != 0) { - Index3 = (UINT16)(1U << TableBits); - while (Index != Index3) { - Table[Index++] = 0; - } - } + if (Index != 0) { + Index3 = (UINT16)(1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } - Avail = NumOfChar; - Mask = (UINT16)(1U << (15 - TableBits)); + Avail = NumOfChar; + Mask = (UINT16)(1U << (15 - TableBits)); - for (Char = 0; Char < NumOfChar; Char++) { - Len = BitLen[Char]; - if (Len == 0 || Len >= 17) { - continue; - } + for (Char = 0; Char < NumOfChar; Char++) { + Len = BitLen[Char]; + if (Len == 0 || Len >= 17) { + continue; + } - NextCode = (UINT16)(Start[Len] + Weight[Len]); + NextCode = (UINT16)(Start[Len] + Weight[Len]); - if (Len <= TableBits) { - for (Index = Start[Len]; Index < NextCode; Index++) { - // Check to prevent possible heap corruption - if (Index >= (UINT16)(1U << TableBits)) - return (UINT16)BAD_TABLE; - Table[Index] = Char; - } - } - else { - Index3 = Start[Len]; - Pointer = &Table[Index3 >> JuBits]; - Index = (UINT16)(Len - TableBits); + if (Len <= TableBits) { + for (Index = Start[Len]; Index < NextCode; Index++) { + // Check to prevent possible heap corruption + if (Index >= (UINT16)(1U << TableBits)) + return (UINT16)BAD_TABLE; + Table[Index] = Char; + } + } + else { + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16)(Len - TableBits); - while (Index != 0) { - // - // Avail should be lesser than size of mRight and mLeft to prevent buffer overflow. - // - if ((*Pointer == 0) && (Avail < sizeof(Sd->mRight) / sizeof(UINT16)) && (Avail < sizeof(Sd->mLeft) / sizeof(UINT16))) { - Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; - *Pointer = Avail++; - } + while (Index != 0) { + // + // Avail should be lesser than size of mRight and mLeft to prevent buffer overflow. + // + if ((*Pointer == 0) && (Avail < sizeof(Sd->mRight) / sizeof(UINT16)) && (Avail < sizeof(Sd->mLeft) / sizeof(UINT16))) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } - // - // *Pointer should be lesser than size of mRight and mLeft to prevent buffer overflow. - // - if ((Index3 & Mask) && (*Pointer < (sizeof(Sd->mRight) / sizeof(UINT16)))) { - Pointer = &Sd->mRight[*Pointer]; - } - else if (*Pointer < (sizeof(Sd->mLeft) / sizeof(UINT16))) { - Pointer = &Sd->mLeft[*Pointer]; - } + // + // *Pointer should be lesser than size of mRight and mLeft to prevent buffer overflow. + // + if ((Index3 & Mask) && (*Pointer < (sizeof(Sd->mRight) / sizeof(UINT16)))) { + Pointer = &Sd->mRight[*Pointer]; + } + else if (*Pointer < (sizeof(Sd->mLeft) / sizeof(UINT16))) { + Pointer = &Sd->mLeft[*Pointer]; + } - Index3 <<= 1; - Index--; - } + Index3 <<= 1; + Index--; + } - *Pointer = Char; - } + *Pointer = Char; + } - Start[Len] = NextCode; - } - // - // Succeeds - // - return 0; + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; } STATIC UINT32 DecodeP( - IN SCRATCH_DATA *Sd +IN SCRATCH_DATA *Sd ) /*++ @@ -342,46 +342,46 @@ The position value decoded. --*/ { - UINT16 Val; - UINT32 Mask; - UINT32 Pos; + UINT16 Val; + UINT32 Mask; + UINT32 Pos; - Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; - if (Val >= MAXNP) { - Mask = 1U << (BITBUFSIZ - 1 - 8); + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); - do { - if (Sd->mBitBuf & Mask) { - Val = Sd->mRight[Val]; - } - else { - Val = Sd->mLeft[Val]; - } + do { + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } + else { + Val = Sd->mLeft[Val]; + } - Mask >>= 1; - } while (Val >= MAXNP); - } - // - // Advance what we have read - // - FillBuf(Sd, Sd->mPTLen[Val]); + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf(Sd, Sd->mPTLen[Val]); - Pos = Val; - if (Val > 1) { - Pos = (UINT32)((1U << (Val - 1)) + GetBits(Sd, (UINT16)(Val - 1))); - } + Pos = Val; + if (Val > 1) { + Pos = (UINT32)((1U << (Val - 1)) + GetBits(Sd, (UINT16)(Val - 1))); + } - return Pos; + return Pos; } STATIC UINT16 ReadPTLen( - IN SCRATCH_DATA *Sd, - IN UINT16 nn, - IN UINT16 nbit, - IN UINT16 Special +IN SCRATCH_DATA *Sd, +IN UINT16 nn, +IN UINT16 nbit, +IN UINT16 Special ) /*++ @@ -403,76 +403,76 @@ BAD_TABLE - Table is corrupted. --*/ { - UINT16 Number; - UINT16 CharC; - UINT16 Index; - UINT32 Mask; + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; - Number = (UINT16)GetBits(Sd, nbit); + Number = (UINT16)GetBits(Sd, nbit); - if ((Number > sizeof(Sd->mPTLen)) || (nn > sizeof(Sd->mPTLen))) { - // - // Fail if Number or nn is greater than size of mPTLen - // - return (UINT16)BAD_TABLE; - } + if ((Number > sizeof(Sd->mPTLen)) || (nn > sizeof(Sd->mPTLen))) { + // + // Fail if Number or nn is greater than size of mPTLen + // + return (UINT16)BAD_TABLE; + } - if (Number == 0) { - CharC = (UINT16)GetBits(Sd, nbit); + if (Number == 0) { + CharC = (UINT16)GetBits(Sd, nbit); - for (Index = 0; Index < 256; Index++) { - Sd->mPTTable[Index] = CharC; - } + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } - for (Index = 0; Index < nn; Index++) { - Sd->mPTLen[Index] = 0; - } + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } - return 0; - } + return 0; + } - Index = 0; + Index = 0; - while (Index < Number) { - CharC = (UINT16)(Sd->mBitBuf >> (BITBUFSIZ - 3)); + while (Index < Number) { + CharC = (UINT16)(Sd->mBitBuf >> (BITBUFSIZ - 3)); - if (CharC == 7) { - Mask = 1U << (BITBUFSIZ - 1 - 3); - while (Mask & Sd->mBitBuf) { - Mask >>= 1; - CharC += 1; - } - } + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } - FillBuf(Sd, (UINT16)((CharC < 7) ? 3 : CharC - 3)); + FillBuf(Sd, (UINT16)((CharC < 7) ? 3 : CharC - 3)); - Sd->mPTLen[Index++] = (UINT8)CharC; + Sd->mPTLen[Index++] = (UINT8)CharC; - if (Index == Special) { - CharC = (UINT16)GetBits(Sd, 2); - while ((INT16)(--CharC) >= 0) { - if (Index >= sizeof(Sd->mPTLen)) { - // - // Fail if Index is greater than or equal to mPTLen - // - return (UINT16)BAD_TABLE; - } - Sd->mPTLen[Index++] = 0; - } - } - } + if (Index == Special) { + CharC = (UINT16)GetBits(Sd, 2); + while ((INT16)(--CharC) >= 0) { + if (Index >= sizeof(Sd->mPTLen)) { + // + // Fail if Index is greater than or equal to mPTLen + // + return (UINT16)BAD_TABLE; + } + Sd->mPTLen[Index++] = 0; + } + } + } - while (Index < nn) { - Sd->mPTLen[Index++] = 0; - } + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } - return MakeTable(Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); + return MakeTable(Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); } STATIC VOID ReadCLen( - SCRATCH_DATA *Sd +SCRATCH_DATA *Sd ) /*++ @@ -488,82 +488,82 @@ Returns: (VOID) --*/ { - UINT16 Number; - UINT16 CharC; - UINT16 Index; - UINT32 Mask; + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; - Number = (UINT16)GetBits(Sd, CBIT); + Number = (UINT16)GetBits(Sd, CBIT); - if (Number == 0) { - CharC = (UINT16)GetBits(Sd, CBIT); + if (Number == 0) { + CharC = (UINT16)GetBits(Sd, CBIT); - for (Index = 0; Index < NC; Index++) { - Sd->mCLen[Index] = 0; - } + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } - for (Index = 0; Index < 4096; Index++) { - Sd->mCTable[Index] = CharC; - } + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } - return; - } + return; + } - Index = 0; - while (Index < Number) { - CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; - if (CharC >= NT) { - Mask = 1U << (BITBUFSIZ - 1 - 8); + Index = 0; + while (Index < Number) { + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); - do { - if (Mask & Sd->mBitBuf) { - CharC = Sd->mRight[CharC]; - } - else { - CharC = Sd->mLeft[CharC]; - } + do { + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } + else { + CharC = Sd->mLeft[CharC]; + } - Mask >>= 1; - } while (CharC >= NT); - } - // - // Advance what we have read - // - FillBuf(Sd, Sd->mPTLen[CharC]); + Mask >>= 1; + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf(Sd, Sd->mPTLen[CharC]); - if (CharC <= 2) { - if (CharC == 0) { - CharC = 1; - } - else if (CharC == 1) { - CharC = (UINT16)(GetBits(Sd, 4) + 3); - } - else if (CharC == 2) { - CharC = (UINT16)(GetBits(Sd, CBIT) + 20); - } + if (CharC <= 2) { + if (CharC == 0) { + CharC = 1; + } + else if (CharC == 1) { + CharC = (UINT16)(GetBits(Sd, 4) + 3); + } + else if (CharC == 2) { + CharC = (UINT16)(GetBits(Sd, CBIT) + 20); + } - while ((INT16)(--CharC) >= 0) { - Sd->mCLen[Index++] = 0; - } - } - else { - Sd->mCLen[Index++] = (UINT8)(CharC - 2); - } - } + while ((INT16)(--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + } + else { + Sd->mCLen[Index++] = (UINT8)(CharC - 2); + } + } - while (Index < NC) { - Sd->mCLen[Index++] = 0; - } + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } - MakeTable(Sd, NC, Sd->mCLen, 12, Sd->mCTable); + MakeTable(Sd, NC, Sd->mCLen, 12, Sd->mCTable); - return; + return; } STATIC UINT16 DecodeC( - SCRATCH_DATA *Sd +SCRATCH_DATA *Sd ) /*++ @@ -581,56 +581,56 @@ The value decoded. --*/ { - UINT16 Index2; - UINT32 Mask; + UINT16 Index2; + UINT32 Mask; - if (Sd->mBlockSize == 0) { - // - // Starting a new block - // - Sd->mBlockSize = (UINT16)GetBits(Sd, 16); - Sd->mBadTableFlag = ReadPTLen(Sd, NT, TBIT, 3); - if (Sd->mBadTableFlag != 0) { - return 0; - } + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16)GetBits(Sd, 16); + Sd->mBadTableFlag = ReadPTLen(Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } - ReadCLen(Sd); + ReadCLen(Sd); - Sd->mBadTableFlag = ReadPTLen(Sd, MAXNP, Sd->mPBit, (UINT16)(-1)); - if (Sd->mBadTableFlag != 0) { - return 0; - } - } + Sd->mBadTableFlag = ReadPTLen(Sd, MAXNP, Sd->mPBit, (UINT16)(-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } - Sd->mBlockSize--; - Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; - if (Index2 >= NC) { - Mask = 1U << (BITBUFSIZ - 1 - 12); + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); - do { - if (Sd->mBitBuf & Mask) { - Index2 = Sd->mRight[Index2]; - } - else { - Index2 = Sd->mLeft[Index2]; - } + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } + else { + Index2 = Sd->mLeft[Index2]; + } - Mask >>= 1; - } while (Index2 >= NC); - } - // - // Advance what we have read - // - FillBuf(Sd, Sd->mCLen[Index2]); + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf(Sd, Sd->mCLen[Index2]); - return Index2; + return Index2; } STATIC VOID Decode( - SCRATCH_DATA *Sd +SCRATCH_DATA *Sd ) /*++ @@ -646,66 +646,66 @@ Returns: (VOID) --*/ { - UINT16 BytesRemain; - UINT32 DataIdx; - UINT16 CharC; + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; - BytesRemain = (UINT16)(-1); + BytesRemain = (UINT16)(-1); - DataIdx = 0; + DataIdx = 0; - for (;;) { - CharC = DecodeC(Sd); - if (Sd->mBadTableFlag != 0) { - return; - } + for (;;) { + CharC = DecodeC(Sd); + if (Sd->mBadTableFlag != 0) { + return; + } - if (CharC < 256) { - // - // Process an Original character - // - if (Sd->mOutBuf >= Sd->mOrigSize) { - return; - } - else { - Sd->mDstBase[Sd->mOutBuf++] = (UINT8)CharC; - } - } - else { - // - // Process a Pointer - // - CharC = (UINT16)(CharC - (UINT8_MAX + 1 - THRESHOLD)); + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return; + } + else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8)CharC; + } + } + else { + // + // Process a Pointer + // + CharC = (UINT16)(CharC - (UINT8_MAX + 1 - THRESHOLD)); - BytesRemain = CharC; + BytesRemain = CharC; - DataIdx = Sd->mOutBuf - DecodeP(Sd) - 1; + DataIdx = Sd->mOutBuf - DecodeP(Sd) - 1; - // Check to prevent possible heap corruption - if (DataIdx >= Sd->mOrigSize - BytesRemain) { - Sd->mBadTableFlag = 1; - return; - } + // Check to prevent possible heap corruption + if (DataIdx >= Sd->mOrigSize - BytesRemain) { + Sd->mBadTableFlag = 1; + return; + } - BytesRemain--; - while ((INT16)(BytesRemain) >= 0) { - Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; - if (Sd->mOutBuf >= Sd->mOrigSize) { - return; - } + BytesRemain--; + while ((INT16)(BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return; + } - BytesRemain--; - } - } - } + BytesRemain--; + } + } + } } EFI_STATUS GetInfo( - IN const VOID *Source, - IN UINT32 SrcSize, - OUT UINT32 *DstSize, - OUT UINT32 *ScratchSize +IN const VOID *Source, +IN UINT32 SrcSize, +OUT UINT32 *DstSize, +OUT UINT32 *ScratchSize ) /*++ @@ -727,28 +727,28 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - const UINT8 *Src; + const UINT8 *Src; - *ScratchSize = sizeof(SCRATCH_DATA); + *ScratchSize = sizeof(SCRATCH_DATA); - Src = Source; - if (SrcSize < 8) { - return EFI_INVALID_PARAMETER; - } + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } - *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); - return EFI_SUCCESS; + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + return EFI_SUCCESS; } EFI_STATUS Decompress( - IN const VOID *Source, - IN UINT32 SrcSize, - IN OUT VOID *Destination, - IN UINT32 DstSize, - IN OUT VOID *Scratch, - IN UINT32 ScratchSize, - IN UINT8 Version +IN const VOID *Source, +IN UINT32 SrcSize, +IN OUT VOID *Destination, +IN UINT32 DstSize, +IN OUT VOID *Scratch, +IN UINT32 ScratchSize, +IN UINT8 Version ) /*++ @@ -775,104 +775,104 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - UINT32 Index; - UINT32 CompSize; - UINT32 OrigSize; - EFI_STATUS Status; - SCRATCH_DATA *Sd; - const UINT8 *Src; - UINT8 *Dst; + UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + EFI_STATUS Status; + SCRATCH_DATA *Sd; + const UINT8 *Src; + UINT8 *Dst; - Status = EFI_SUCCESS; - Src = Source; - Dst = Destination; + Status = EFI_SUCCESS; + Src = Source; + Dst = Destination; - if (ScratchSize < sizeof(SCRATCH_DATA)) { - return EFI_INVALID_PARAMETER; - } + if (ScratchSize < sizeof(SCRATCH_DATA)) { + return EFI_INVALID_PARAMETER; + } - Sd = (SCRATCH_DATA *)Scratch; + Sd = (SCRATCH_DATA *)Scratch; - if (SrcSize < 8) { - return EFI_INVALID_PARAMETER; - } + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } - CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); - OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); - // - // If compressed file size is 0, return - // - if (OrigSize == 0) { - return Status; - } + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return Status; + } - if (SrcSize < CompSize + 8) { - return EFI_INVALID_PARAMETER; - } + if (SrcSize < CompSize + 8) { + return EFI_INVALID_PARAMETER; + } - if (DstSize != OrigSize) { - return EFI_INVALID_PARAMETER; - } + if (DstSize != OrigSize) { + return EFI_INVALID_PARAMETER; + } - Src = Src + 8; + Src = Src + 8; - for (Index = 0; Index < sizeof(SCRATCH_DATA); Index++) { - ((UINT8 *)Sd)[Index] = 0; - } - // - // The length of the field 'Position Set Code Length Array Size' in Block Header. - // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 - // For Tiano de/compression algorithm(Version 2), mPBit = 5 - // - switch (Version) { - case 1: - Sd->mPBit = 4; - break; + for (Index = 0; Index < sizeof(SCRATCH_DATA); Index++) { + ((UINT8 *)Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1: + Sd->mPBit = 4; + break; - case 2: - Sd->mPBit = 5; - break; + case 2: + Sd->mPBit = 5; + break; - default: - // - // Currently, only have 2 versions - // - return EFI_INVALID_PARAMETER; - } + default: + // + // Currently, only have 2 versions + // + return EFI_INVALID_PARAMETER; + } - Sd->mSrcBase = (UINT8*)Src; - Sd->mDstBase = Dst; - Sd->mCompSize = CompSize; - Sd->mOrigSize = OrigSize; + Sd->mSrcBase = (UINT8*)Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; - // - // Fill the first BITBUFSIZ bits - // - FillBuf(Sd, BITBUFSIZ); + // + // Fill the first BITBUFSIZ bits + // + FillBuf(Sd, BITBUFSIZ); - // - // Decompress it - // - Decode(Sd); + // + // Decompress it + // + Decode(Sd); - if (Sd->mBadTableFlag != 0) { - // - // Something wrong with the source - // - Status = EFI_INVALID_PARAMETER; - } + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + Status = EFI_INVALID_PARAMETER; + } - return Status; + return Status; } EFI_STATUS EFIAPI EfiTianoGetInfo( - IN const VOID *Source, - IN UINT32 SrcSize, - OUT UINT32 *DstSize, - OUT UINT32 *ScratchSize +IN const VOID *Source, +IN UINT32 SrcSize, +OUT UINT32 *DstSize, +OUT UINT32 *ScratchSize ) /*++ @@ -895,23 +895,23 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - return GetInfo( - Source, - SrcSize, - DstSize, - ScratchSize - ); + return GetInfo( + Source, + SrcSize, + DstSize, + ScratchSize + ); } EFI_STATUS EFIAPI EfiDecompress( - IN const VOID *Source, - IN UINT32 SrcSize, - IN OUT VOID *Destination, - IN UINT32 DstSize, - IN OUT VOID *Scratch, - IN UINT32 ScratchSize +IN const VOID *Source, +IN UINT32 SrcSize, +IN OUT VOID *Destination, +IN UINT32 DstSize, +IN OUT VOID *Scratch, +IN UINT32 ScratchSize ) /*++ @@ -936,29 +936,29 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - // - // For EFI 1.1 de/compression algorithm, the version is 1. - // - return Decompress( - Source, - SrcSize, - Destination, - DstSize, - Scratch, - ScratchSize, - 1 - ); + // + // For EFI 1.1 de/compression algorithm, the version is 1. + // + return Decompress( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 1 + ); } EFI_STATUS EFIAPI TianoDecompress( - IN const VOID *Source, - IN UINT32 SrcSize, - IN OUT VOID *Destination, - IN UINT32 DstSize, - IN OUT VOID *Scratch, - IN UINT32 ScratchSize +IN const VOID *Source, +IN UINT32 SrcSize, +IN OUT VOID *Destination, +IN UINT32 DstSize, +IN OUT VOID *Scratch, +IN UINT32 ScratchSize ) /*++ @@ -983,16 +983,16 @@ EFI_INVALID_PARAMETER - The source data is corrupted --*/ { - // - // For Tiano de/compression algorithm, the version is 2. - // - return Decompress( - Source, - SrcSize, - Destination, - DstSize, - Scratch, - ScratchSize, - 2 - ); + // + // For Tiano de/compression algorithm, the version is 2. + // + return Decompress( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 2 + ); } diff --git a/Tiano/EfiTianoDecompress.h b/Tiano/EfiTianoDecompress.h index fe0eba5..f6efd6e 100644 --- a/Tiano/EfiTianoDecompress.h +++ b/Tiano/EfiTianoDecompress.h @@ -21,8 +21,8 @@ Providing both EFI and Tiano decompress algorithms. --*/ -#ifndef _EFITIANODECOMPRESS_H_ -#define _EFITIANODECOMPRESS_H_ +#ifndef EFITIANODECOMPRESS_H +#define EFITIANODECOMPRESS_H #include #include @@ -32,109 +32,107 @@ Providing both EFI and Tiano decompress algorithms. extern "C" { #endif - typedef struct { - UINT32 CompSize; - UINT32 OrigSize; - } EFI_TIANO_HEADER; +typedef struct EFI_TIANO_HEADER_ { + UINT32 CompSize; + UINT32 OrigSize; +} EFI_TIANO_HEADER; - EFI_STATUS - EfiTianoGetInfo( - IN const VOID *Source, - IN UINT32 SrcSize, - OUT UINT32 *DstSize, - OUT UINT32 *ScratchSize - ) - /*++ +EFI_STATUS +EFIAPI +EfiTianoGetInfo( + const VOID *Source, + UINT32 SrcSize, + UINT32 *DstSize, + UINT32 *ScratchSize + ) +/*++ - Routine Description: +Routine Description: - The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo(). +The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo(). - Arguments: +Arguments: - This - The protocol instance pointer - Source - The source buffer containing the compressed data. - SrcSize - The size of source buffer - DstSize - The size of destination buffer. - ScratchSize - The size of scratch buffer. +Source - The source buffer containing the compressed data. +SrcSize - The size of source buffer +DstSize - The size of destination buffer. +ScratchSize - The size of scratch buffer. - Returns: +Returns: - EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. - EFI_INVALID_PARAMETER - The source data is corrupted +EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. +EFI_INVALID_PARAMETER - The source data is corrupted - --*/ - ; +--*/ +; - EFI_STATUS - EFIAPI - EfiDecompress( - IN const VOID *Source, - IN UINT32 SrcSize, - IN OUT VOID *Destination, - IN UINT32 DstSize, - IN OUT VOID *Scratch, - IN UINT32 ScratchSize - ) - /*++ +EFI_STATUS +EFIAPI +EfiDecompress( + const VOID *Source, + UINT32 SrcSize, + VOID *Destination, + UINT32 DstSize, + VOID *Scratch, + UINT32 ScratchSize + ); +/*++ - Routine Description: +Routine Description: - The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress(). +The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress(). - Arguments: +Arguments: - This - The protocol instance pointer - Source - The source buffer containing the compressed data. - SrcSize - The size of source buffer - Destination - The destination buffer to store the decompressed data - DstSize - The size of destination buffer. - Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. - ScratchSize - The size of scratch buffer. +Source - The source buffer containing the compressed data. +SrcSize - The size of source buffer +Destination - The destination buffer to store the decompressed data +DstSize - The size of destination buffer. +Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. +ScratchSize - The size of scratch buffer. - Returns: +Returns: - EFI_SUCCESS - Decompression is successful - EFI_INVALID_PARAMETER - The source data is corrupted +EFI_SUCCESS - Decompression is successful +EFI_INVALID_PARAMETER - The source data is corrupted - --*/ - ; +--*/ +; - EFI_STATUS - EFIAPI - TianoDecompress( - IN const VOID *Source, - IN UINT32 SrcSize, - IN OUT VOID *Destination, - IN UINT32 DstSize, - IN OUT VOID *Scratch, - IN UINT32 ScratchSize - ) - /*++ +EFI_STATUS +EFIAPI +TianoDecompress( + const VOID *Source, + UINT32 SrcSize, + VOID *Destination, + UINT32 DstSize, + VOID *Scratch, + UINT32 ScratchSize + ) +/*++ - Routine Description: +Routine Description: - The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). +The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). - Arguments: +Arguments: - This - The protocol instance pointer - Source - The source buffer containing the compressed data. - SrcSize - The size of source buffer - Destination - The destination buffer to store the decompressed data - DstSize - The size of destination buffer. - Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. - ScratchSize - The size of scratch buffer. +Source - The source buffer containing the compressed data. +SrcSize - The size of source buffer +Destination - The destination buffer to store the decompressed data +DstSize - The size of destination buffer. +Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. +ScratchSize - The size of scratch buffer. - Returns: +Returns: - EFI_SUCCESS - Decompression is successful - EFI_INVALID_PARAMETER - The source data is corrupted +EFI_SUCCESS - Decompression is successful +EFI_INVALID_PARAMETER - The source data is corrupted - --*/ - ; +--*/ +; #ifdef __cplusplus } #endif -#endif +#endif // EFITIANODECOMPRESS_H diff --git a/basetypes.h b/basetypes.h index 3c07309..04c65b2 100644 --- a/basetypes.h +++ b/basetypes.h @@ -16,6 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include typedef uint8_t BOOLEAN; typedef int8_t INT8; @@ -28,7 +29,7 @@ typedef int64_t INT64; typedef uint64_t UINT64; typedef char CHAR8; typedef uint16_t CHAR16; -typedef unsigned int UINTN; +typedef size_t UINTN; #define CONST const #define VOID void diff --git a/ffsengine.cpp b/ffsengine.cpp index 2ea6bb0..ea7c172 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -2741,7 +2741,13 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr else if (algorithm) *algorithm = COMPRESSION_ALGORITHM_TIANO; - decompressedData = QByteArray((const char*)decompressed, decompressedSize); + if (decompressedSize > INT32_MAX) { + delete[] decompressed; + delete[] scratch; + return ERR_STANDARD_DECOMPRESSION_FAILED; + } + + decompressedData = QByteArray((const char*)decompressed, (int)decompressedSize); delete[] decompressed; delete[] scratch; @@ -2778,7 +2784,8 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr } // Decompress section data again - if (ERR_SUCCESS != LzmaDecompress(data, dataSize, decompressed)) { + if (ERR_SUCCESS != LzmaDecompress(data, dataSize, decompressed) + || decompressedSize > INT32_MAX) { if (algorithm) *algorithm = COMPRESSION_ALGORITHM_UNKNOWN; delete[] decompressed; @@ -2787,13 +2794,17 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr else { if (algorithm) *algorithm = COMPRESSION_ALGORITHM_IMLZMA; - decompressedData = QByteArray((const char*)decompressed, decompressedSize); + decompressedData = QByteArray((const char*)decompressed, (int)decompressedSize); } } else { + if (decompressedSize > INT32_MAX) { + delete[] decompressed; + return ERR_CUSTOMIZED_DECOMPRESSION_FAILED; + } if (algorithm) *algorithm = COMPRESSION_ALGORITHM_LZMA; - decompressedData = QByteArray((const char*)decompressed, decompressedSize); + decompressedData = QByteArray((const char*)decompressed, (int)decompressedSize); } delete[] decompressed; From 63e40c058a249d510e1deea4b7dd6a2e73b60940 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 8 May 2018 21:49:11 +0300 Subject: [PATCH 53/64] Increment version --- .appveyor.yml | 8 +++++++- UEFIPatch/uefipatch_main.cpp | 2 +- UEFIReplace/uefireplace_main.cpp | 2 +- uefitool.cpp | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 80d9d67..0324998 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,8 +14,14 @@ build_script: deploy: provider: GitHub + force_update: true auth_token: secure: zSJnpSnrKY1NO5RPVBaD/uq7UPyc+GW7ecjPFqEMsLjtnd6H+iNfROdoeuxJgt5T - artifact: /dist\\.*\.zip/ + artifact: Binaries on: appveyor_repo_tag: true + +artifacts: + - path: dist\**\*.zip + name: Binaries + diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 5e7ed4b..6a7e50f 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) result = w.patchFromFile(a.arguments().at(1), patches); } else { - std::cout << "UEFIPatch 0.3.14 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch 0.3.15 - UEFI image file patching utility" << std::endl << std::endl << "Usage: UEFIPatch image_file [patches.txt]" << std::endl << std::endl << "Patches will be read from patches.txt file by default\n"; return ERR_SUCCESS; diff --git a/UEFIReplace/uefireplace_main.cpp b/UEFIReplace/uefireplace_main.cpp index 6d53a2b..aae90d7 100644 --- a/UEFIReplace/uefireplace_main.cpp +++ b/UEFIReplace/uefireplace_main.cpp @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) QStringList args = a.arguments(); if (args.length() < 5) { - std::cout << "UEFIReplace 0.1.2 - UEFI image file replacement utility" << std::endl << std::endl << + std::cout << "UEFIReplace 0.1.3 - UEFI image file replacement utility" << std::endl << std::endl << "Usage: UEFIReplace image_file guid section_type contents_file" << std::endl; return ERR_SUCCESS; } diff --git a/uefitool.cpp b/uefitool.cpp index c2eac33..9127e87 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -17,7 +17,7 @@ UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.23.1")) +version(tr("0.24.0")) { clipboard = QApplication::clipboard(); From 8db52ea51adac8d8feaeba5854efde4279c392a2 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sat, 19 May 2018 18:35:38 +0300 Subject: [PATCH 54/64] Implement replace all and add -o (--output) path to UEFIReplace --- .gitignore | 3 +++ UEFIReplace/uefireplace.cpp | 22 +++++++++++++--------- UEFIReplace/uefireplace.h | 4 ++-- UEFIReplace/uefireplace_main.cpp | 23 +++++++++++++++++++---- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 910d521..c84a076 100644 --- a/.gitignore +++ b/.gitignore @@ -235,3 +235,6 @@ UEFIFind/UEFIFind UEFIPatch/UEFIPatch UEFIReplace/UEFIReplace UEFITool +.qmake.stash +UEFITool.app/ +uefitool_plugin_import.cpp diff --git a/UEFIReplace/uefireplace.cpp b/UEFIReplace/uefireplace.cpp index f4ff1ea..97eaafb 100644 --- a/UEFIReplace/uefireplace.cpp +++ b/UEFIReplace/uefireplace.cpp @@ -25,7 +25,7 @@ UEFIReplace::~UEFIReplace() delete ffsEngine; } -UINT8 UEFIReplace::replace(QString inPath, const QByteArray & guid, const UINT8 sectionType, const QString contentPath) +UINT8 UEFIReplace::replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceOnce) { QFileInfo fileInfo = QFileInfo(inPath); if (!fileInfo.exists()) @@ -57,7 +57,7 @@ UINT8 UEFIReplace::replace(QString inPath, const QByteArray & guid, const UINT8 QByteArray contents = contentFile.readAll(); contentFile.close(); - result = replaceInFile(model->index(0, 0), guid, sectionType, contents); + result = replaceInFile(model->index(0, 0), guid, sectionType, contents, replaceOnce); if (result) return result; @@ -69,7 +69,7 @@ UINT8 UEFIReplace::replace(QString inPath, const QByteArray & guid, const UINT8 return ERR_NOTHING_TO_PATCH; QFile outputFile; - outputFile.setFileName(inPath.append(".patched")); + outputFile.setFileName(outPath); if (!outputFile.open(QFile::WriteOnly)) return ERR_FILE_WRITE; @@ -80,7 +80,7 @@ UINT8 UEFIReplace::replace(QString inPath, const QByteArray & guid, const UINT8 return ERR_SUCCESS; } -UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & newData) +UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & newData, bool replaceOnce) { if (!model || !index.isValid()) return ERR_INVALID_PARAMETER; @@ -88,19 +88,23 @@ UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & g QModelIndex fileIndex = model->findParentOfType(index, Types::File); QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID)); if (fileGuid == guid) { - return ffsEngine->replace(index, newData, REPLACE_MODE_BODY); + UINT8 result = ffsEngine->replace(index, newData, REPLACE_MODE_BODY); + if (replaceOnce || (result != ERR_SUCCESS && result != ERR_NOTHING_TO_PATCH)) + return result; } } bool patched = false; if (model->rowCount(index) > 0) { for (int i = 0; i < model->rowCount(index); i++) { - UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData); - if (!result) { + UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData, replaceOnce); + if (result == ERR_SUCCESS) { patched = true; - break; - } else if (result != ERR_NOTHING_TO_PATCH) + if (replaceOnce) + break; + } else if (result != ERR_NOTHING_TO_PATCH) { return result; + } } } diff --git a/UEFIReplace/uefireplace.h b/UEFIReplace/uefireplace.h index 682a1f6..d70ac2b 100644 --- a/UEFIReplace/uefireplace.h +++ b/UEFIReplace/uefireplace.h @@ -30,10 +30,10 @@ public: explicit UEFIReplace(QObject *parent = 0); ~UEFIReplace(); - UINT8 replace(const QString inPath, const QByteArray & guid, const UINT8 sectionType, const QString contentPath); + UINT8 replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceOnce); private: - UINT8 replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & contents); + UINT8 replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & contents, bool replaceOnce); FfsEngine* ffsEngine; TreeModel* model; }; diff --git a/UEFIReplace/uefireplace_main.cpp b/UEFIReplace/uefireplace_main.cpp index aae90d7..dfd8bf0 100644 --- a/UEFIReplace/uefireplace_main.cpp +++ b/UEFIReplace/uefireplace_main.cpp @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) if (args.length() < 5) { std::cout << "UEFIReplace 0.1.3 - 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 [-o output] [-all]" << std::endl; return ERR_SUCCESS; } @@ -37,10 +37,25 @@ int main(int argc, char *argv[]) QByteArray guid = QByteArray::fromRawData((const char*)&uuid.data1, sizeof(EFI_GUID)); bool converted; UINT8 sectionType = (UINT8)args.at(3).toUShort(&converted, 16); - if (!converted) + if (!converted) { result = ERR_INVALID_PARAMETER; - else - result = r.replace(args.at(1), guid, sectionType, args.at(4)); + } else { + QString output = args.at(1) + ".patched"; + bool replaceOnce = true; + for (int i = 5, sz = args.size(); i < sz; i++) { + if ((args.at(i) == "-o" || args.at(i) == "--output") && i + 1 < sz) { + output = args.at(i+1); + i++; + } else if (args.at(i) == "-all") { + replaceOnce = false; + } else { + result = ERR_INVALID_PARAMETER; + } + } + if (result == ERR_SUCCESS) { + result = r.replace(args.at(1), guid, sectionType, args.at(4), output, replaceOnce); + } + } switch (result) { case ERR_SUCCESS: From b5961a7155ad4d3c7c87996e9fb7c30b4131839d Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sat, 19 May 2018 18:55:51 +0300 Subject: [PATCH 55/64] Add -o / --output flag to UEFIPatch --- UEFIPatch/uefipatch.cpp | 4 ++-- UEFIPatch/uefipatch.h | 4 +--- UEFIPatch/uefipatch_main.cpp | 32 ++++++++++++++++++++++---------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/UEFIPatch/uefipatch.cpp b/UEFIPatch/uefipatch.cpp index 522a8ed..19129a0 100644 --- a/UEFIPatch/uefipatch.cpp +++ b/UEFIPatch/uefipatch.cpp @@ -25,7 +25,7 @@ UEFIPatch::~UEFIPatch() delete ffsEngine; } -UINT8 UEFIPatch::patchFromFile(QString path, QString patches) +UINT8 UEFIPatch::patchFromFile(const QString & path, const QString & patches, const QString & outputPath) { QFileInfo patchInfo = QFileInfo(patches); @@ -110,7 +110,7 @@ UINT8 UEFIPatch::patchFromFile(QString path, QString patches) return ERR_NOTHING_TO_PATCH; QFile outputFile; - outputFile.setFileName(path.append(".patched")); + outputFile.setFileName(outputPath); if (!outputFile.open(QFile::WriteOnly)) return ERR_FILE_WRITE; diff --git a/UEFIPatch/uefipatch.h b/UEFIPatch/uefipatch.h index dd1cdb8..d42b31d 100644 --- a/UEFIPatch/uefipatch.h +++ b/UEFIPatch/uefipatch.h @@ -33,9 +33,7 @@ public: explicit UEFIPatch(QObject *parent = 0); ~UEFIPatch(); - UINT8 patchFromFile(QString path, QString patches); - UINT8 patch(QString path, QString fileGuid, QString findPattern, QString replacePattern); - + UINT8 patchFromFile(const QString & path, const QString & patches, const QString & outputPath); private: UINT8 patchFile(const QModelIndex & index, const QByteArray & fileGuid, const UINT8 sectionType, const QVector & patches); FfsEngine* ffsEngine; diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index 6a7e50f..ff9177f 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -26,22 +26,34 @@ int main(int argc, char *argv[]) UEFIPatch w; UINT8 result = ERR_SUCCESS; - UINT32 argumentsCount = a.arguments().length(); - - QString patches = "patches.txt"; - if (argumentsCount == 3) - patches = a.arguments().at(2); + const QStringList &args = a.arguments(); + UINT32 argumentsCount = args.length(); - if (argumentsCount == 2 || argumentsCount == 3) { - result = w.patchFromFile(a.arguments().at(1), patches); - } - else { + if (argumentsCount < 2) { std::cout << "UEFIPatch 0.3.15 - UEFI image file patching utility" << std::endl << std::endl << - "Usage: UEFIPatch image_file [patches.txt]" << std::endl << std::endl << + "Usage: UEFIPatch image_file [patches.txt] [-o output]" << std::endl << std::endl << "Patches will be read from patches.txt file by default\n"; return ERR_SUCCESS; } + QString inputPath = a.arguments().at(1); + QString patches = "patches.txt"; + QString outputPath = inputPath + ".patched"; + for (UINT32 i = 2; i < argumentsCount; i++) { + if ((args.at(i) == "-o" || args.at(i) == "--output") && i + 1 < argumentsCount) { + outputPath = args.at(i+1); + i++; + } else if (patches == "patches.txt") { + patches = args.at(i); + } else { + result = ERR_INVALID_PARAMETER; + } + } + + if (result == ERR_SUCCESS) { + result = w.patchFromFile(inputPath, patches, outputPath); + } + switch (result) { case ERR_SUCCESS: std::cout << "Image patched" << std::endl; From dd90367387bd199452f96d105ea09b4e6de5d02f Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sat, 19 May 2018 23:35:57 +0300 Subject: [PATCH 56/64] Fix recursion in UEFIReplace --- UEFIReplace/uefireplace.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/UEFIReplace/uefireplace.cpp b/UEFIReplace/uefireplace.cpp index 97eaafb..36978cf 100644 --- a/UEFIReplace/uefireplace.cpp +++ b/UEFIReplace/uefireplace.cpp @@ -84,17 +84,18 @@ UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & g { if (!model || !index.isValid()) return ERR_INVALID_PARAMETER; + bool patched = false; if (model->subtype(index) == sectionType) { QModelIndex fileIndex = model->findParentOfType(index, Types::File); QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID)); - if (fileGuid == guid) { + if (fileGuid == guid && model->action(index) != Actions::Replace) { UINT8 result = ffsEngine->replace(index, newData, REPLACE_MODE_BODY); if (replaceOnce || (result != ERR_SUCCESS && result != ERR_NOTHING_TO_PATCH)) return result; + patched = result == ERR_SUCCESS; } } - bool patched = false; if (model->rowCount(index) > 0) { for (int i = 0; i < model->rowCount(index); i++) { UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData, replaceOnce); From 65263f1000868575df5fc8833b1370a1db6f4b78 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sat, 19 May 2018 23:53:21 +0300 Subject: [PATCH 57/64] Allow subguid matching for UEFIReplace --- UEFIReplace/uefireplace.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/UEFIReplace/uefireplace.cpp b/UEFIReplace/uefireplace.cpp index 36978cf..68eca38 100644 --- a/UEFIReplace/uefireplace.cpp +++ b/UEFIReplace/uefireplace.cpp @@ -84,15 +84,20 @@ UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & g { if (!model || !index.isValid()) return ERR_INVALID_PARAMETER; - bool patched = false; + bool patched = false; if (model->subtype(index) == sectionType) { QModelIndex fileIndex = model->findParentOfType(index, Types::File); QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID)); - if (fileGuid == guid && model->action(index) != Actions::Replace) { + bool guidMatch = fileGuid == guid; + if (!guidMatch && sectionType == EFI_SECTION_FREEFORM_SUBTYPE_GUID) { + QByteArray subGuid = model->header(index).mid(sizeof(uint32_t), sizeof(EFI_GUID)); + guidMatch = subGuid == guid; + } + if (guidMatch && model->action(index) != Actions::Replace) { UINT8 result = ffsEngine->replace(index, newData, REPLACE_MODE_BODY); if (replaceOnce || (result != ERR_SUCCESS && result != ERR_NOTHING_TO_PATCH)) return result; - patched = result == ERR_SUCCESS; + patched = result == ERR_SUCCESS; } } From e5d868977e0b14c184d85ec760561c8553223aaa Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 20 May 2018 00:02:35 +0300 Subject: [PATCH 58/64] Deploy as prerelease to avoid confusion --- .appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor.yml b/.appveyor.yml index 0324998..68b313b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -18,6 +18,7 @@ deploy: auth_token: secure: zSJnpSnrKY1NO5RPVBaD/uq7UPyc+GW7ecjPFqEMsLjtnd6H+iNfROdoeuxJgt5T artifact: Binaries + prerelease: true on: appveyor_repo_tag: true From 8ea96ffd5d4faf93954088401baa565ad8a4210b Mon Sep 17 00:00:00 2001 From: vit9696 Date: Mon, 21 May 2018 10:07:33 +0300 Subject: [PATCH 59/64] Support replacing raw sections and ffs via -asis --- UEFIReplace/uefireplace.cpp | 18 +++++++++++------- UEFIReplace/uefireplace.h | 4 ++-- UEFIReplace/uefireplace_main.cpp | 7 +++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/UEFIReplace/uefireplace.cpp b/UEFIReplace/uefireplace.cpp index 68eca38..d4ba092 100644 --- a/UEFIReplace/uefireplace.cpp +++ b/UEFIReplace/uefireplace.cpp @@ -25,7 +25,7 @@ UEFIReplace::~UEFIReplace() delete ffsEngine; } -UINT8 UEFIReplace::replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceOnce) +UINT8 UEFIReplace::replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceAsIs, bool replaceOnce) { QFileInfo fileInfo = QFileInfo(inPath); if (!fileInfo.exists()) @@ -57,7 +57,8 @@ UINT8 UEFIReplace::replace(const QString & inPath, const QByteArray & guid, cons QByteArray contents = contentFile.readAll(); contentFile.close(); - result = replaceInFile(model->index(0, 0), guid, sectionType, contents, replaceOnce); + result = replaceInFile(model->index(0, 0), guid, sectionType, contents, + replaceAsIs ? REPLACE_MODE_AS_IS : REPLACE_MODE_BODY, replaceOnce); if (result) return result; @@ -80,21 +81,24 @@ UINT8 UEFIReplace::replace(const QString & inPath, const QByteArray & guid, cons return ERR_SUCCESS; } -UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & newData, bool replaceOnce) +UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & newData, const UINT8 mode, bool replaceOnce) { if (!model || !index.isValid()) return ERR_INVALID_PARAMETER; bool patched = false; if (model->subtype(index) == sectionType) { - QModelIndex fileIndex = model->findParentOfType(index, Types::File); + QModelIndex fileIndex = index; + if (model->type(index) != Types::File) + fileIndex = model->findParentOfType(index, Types::File); QByteArray fileGuid = model->header(fileIndex).left(sizeof(EFI_GUID)); + bool guidMatch = fileGuid == guid; if (!guidMatch && sectionType == EFI_SECTION_FREEFORM_SUBTYPE_GUID) { - QByteArray subGuid = model->header(index).mid(sizeof(uint32_t), sizeof(EFI_GUID)); + QByteArray subGuid = model->header(index).mid(sizeof(UINT32), sizeof(EFI_GUID)); guidMatch = subGuid == guid; } if (guidMatch && model->action(index) != Actions::Replace) { - UINT8 result = ffsEngine->replace(index, newData, REPLACE_MODE_BODY); + UINT8 result = ffsEngine->replace(index, newData, mode); if (replaceOnce || (result != ERR_SUCCESS && result != ERR_NOTHING_TO_PATCH)) return result; patched = result == ERR_SUCCESS; @@ -103,7 +107,7 @@ UINT8 UEFIReplace::replaceInFile(const QModelIndex & index, const QByteArray & g if (model->rowCount(index) > 0) { for (int i = 0; i < model->rowCount(index); i++) { - UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData, replaceOnce); + UINT8 result = replaceInFile(index.child(i, 0), guid, sectionType, newData, mode, replaceOnce); if (result == ERR_SUCCESS) { patched = true; if (replaceOnce) diff --git a/UEFIReplace/uefireplace.h b/UEFIReplace/uefireplace.h index d70ac2b..c79ae52 100644 --- a/UEFIReplace/uefireplace.h +++ b/UEFIReplace/uefireplace.h @@ -30,10 +30,10 @@ public: explicit UEFIReplace(QObject *parent = 0); ~UEFIReplace(); - UINT8 replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceOnce); + UINT8 replace(const QString & inPath, const QByteArray & guid, const UINT8 sectionType, const QString & contentPath, const QString & outPath, bool replaceAsIs, bool replaceOnce); private: - UINT8 replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & contents, bool replaceOnce); + UINT8 replaceInFile(const QModelIndex & index, const QByteArray & guid, const UINT8 sectionType, const QByteArray & contents, const UINT8 mode, bool replaceOnce); FfsEngine* ffsEngine; TreeModel* model; }; diff --git a/UEFIReplace/uefireplace_main.cpp b/UEFIReplace/uefireplace_main.cpp index dfd8bf0..93c72ec 100644 --- a/UEFIReplace/uefireplace_main.cpp +++ b/UEFIReplace/uefireplace_main.cpp @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) if (args.length() < 5) { std::cout << "UEFIReplace 0.1.3 - UEFI image file replacement utility" << std::endl << std::endl << - "Usage: UEFIReplace image_file guid section_type contents_file [-o output] [-all]" << std::endl; + "Usage: UEFIReplace image_file guid section_type contents_file [-o output] [-all] [-asis]" << std::endl; return ERR_SUCCESS; } @@ -42,18 +42,21 @@ int main(int argc, char *argv[]) } else { QString output = args.at(1) + ".patched"; bool replaceOnce = true; + bool replaceAsIs = false; for (int i = 5, sz = args.size(); i < sz; i++) { if ((args.at(i) == "-o" || args.at(i) == "--output") && i + 1 < sz) { output = args.at(i+1); i++; } else if (args.at(i) == "-all") { replaceOnce = false; + } else if (args.at(i) == "-asis") { + replaceAsIs = true; } else { result = ERR_INVALID_PARAMETER; } } if (result == ERR_SUCCESS) { - result = r.replace(args.at(1), guid, sectionType, args.at(4), output, replaceOnce); + result = r.replace(args.at(1), guid, sectionType, args.at(4), output, replaceAsIs, replaceOnce); } } From 4bb759780fb0e293cb762b77f56adbd1e27fe11e Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 22 May 2018 00:43:34 +0300 Subject: [PATCH 60/64] Unify version scheme --- .gitignore | 2 ++ UEFIPatch/uefipatch.pro | 1 + UEFIPatch/uefipatch_main.cpp | 4 +++- UEFIReplace/uefireplace.pro | 3 ++- UEFIReplace/uefireplace_main.cpp | 4 +++- uefitool.cpp | 3 ++- uefitool.pro | 1 + unixbuild.sh | 12 +++++------- version.h | 19 +++++++++++++++++++ 9 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 version.h diff --git a/.gitignore b/.gitignore index c84a076..04fe0e1 100644 --- a/.gitignore +++ b/.gitignore @@ -238,3 +238,5 @@ UEFITool .qmake.stash UEFITool.app/ uefitool_plugin_import.cpp +DerivedData +*.xcodeproj diff --git a/UEFIPatch/uefipatch.pro b/UEFIPatch/uefipatch.pro index 5465b31..9e53160 100644 --- a/UEFIPatch/uefipatch.pro +++ b/UEFIPatch/uefipatch.pro @@ -36,6 +36,7 @@ HEADERS += uefipatch.h \ ../ffsengine.h \ ../treeitem.h \ ../treemodel.h \ + ../version.h \ ../LZMA/LzmaCompress.h \ ../LZMA/LzmaDecompress.h \ ../Tiano/EfiTianoDecompress.h \ diff --git a/UEFIPatch/uefipatch_main.cpp b/UEFIPatch/uefipatch_main.cpp index ff9177f..ee1c9c9 100644 --- a/UEFIPatch/uefipatch_main.cpp +++ b/UEFIPatch/uefipatch_main.cpp @@ -15,6 +15,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include + +#include "../version.h" #include "uefipatch.h" int main(int argc, char *argv[]) @@ -30,7 +32,7 @@ int main(int argc, char *argv[]) UINT32 argumentsCount = args.length(); if (argumentsCount < 2) { - std::cout << "UEFIPatch 0.3.15 - UEFI image file patching utility" << std::endl << std::endl << + std::cout << "UEFIPatch " PROGRAM_VERSION " - UEFI image file patching utility" << std::endl << std::endl << "Usage: UEFIPatch image_file [patches.txt] [-o output]" << std::endl << std::endl << "Patches will be read from patches.txt file by default\n"; return ERR_SUCCESS; diff --git a/UEFIReplace/uefireplace.pro b/UEFIReplace/uefireplace.pro index e3d853d..d63072b 100644 --- a/UEFIReplace/uefireplace.pro +++ b/UEFIReplace/uefireplace.pro @@ -36,7 +36,8 @@ HEADERS += uefireplace.h \ ../ffsengine.h \ ../treeitem.h \ ../treemodel.h \ + ../version.h \ ../LZMA/LzmaCompress.h \ ../LZMA/LzmaDecompress.h \ ../Tiano/EfiTianoDecompress.h \ - ../Tiano/EfiTianoCompress.h + ../Tiano/EfiTianoCompress.h \ No newline at end of file diff --git a/UEFIReplace/uefireplace_main.cpp b/UEFIReplace/uefireplace_main.cpp index 93c72ec..78baca4 100644 --- a/UEFIReplace/uefireplace_main.cpp +++ b/UEFIReplace/uefireplace_main.cpp @@ -14,6 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include + +#include "../version.h" #include "uefireplace.h" int main(int argc, char *argv[]) @@ -28,7 +30,7 @@ int main(int argc, char *argv[]) QStringList args = a.arguments(); if (args.length() < 5) { - std::cout << "UEFIReplace 0.1.3 - UEFI image file replacement utility" << std::endl << std::endl << + std::cout << "UEFIReplace " PROGRAM_VERSION " - UEFI image file replacement utility" << std::endl << std::endl << "Usage: UEFIReplace image_file guid section_type contents_file [-o output] [-all] [-asis]" << std::endl; return ERR_SUCCESS; } diff --git a/uefitool.cpp b/uefitool.cpp index 9127e87..8813f60 100644 --- a/uefitool.cpp +++ b/uefitool.cpp @@ -11,13 +11,14 @@ */ +#include "version.h" #include "uefitool.h" #include "ui_uefitool.h" UEFITool::UEFITool(QWidget *parent) : QMainWindow(parent), ui(new Ui::UEFITool), -version(tr("0.24.0")) +version(tr(PROGRAM_VERSION)) { clipboard = QApplication::clipboard(); diff --git a/uefitool.pro b/uefitool.pro index 59f6c21..f17f30a 100644 --- a/uefitool.pro +++ b/uefitool.pro @@ -39,6 +39,7 @@ HEADERS += uefitool.h \ treemodel.h \ messagelistitem.h \ guidlineedit.h \ + version.h \ LZMA/LzmaCompress.h \ LZMA/LzmaDecompress.h \ Tiano/EfiTianoDecompress.h \ diff --git a/unixbuild.sh b/unixbuild.sh index 13a5559..d81df31 100755 --- a/unixbuild.sh +++ b/unixbuild.sh @@ -55,11 +55,9 @@ elif [ "$UPLATFORM" = "win32" ]; then export PATH="/c/Qt/5.6/mingw49_32_release_static/bin:$PATH" fi -echo "Attempting to build UEFITool NE for ${UPLATFORM}..." +echo "Attempting to build UEFITool for ${UPLATFORM}..." -UEFITOOL_VER=$(cat uefitool.cpp | grep ^version | cut -d'"' -f2) -UEFIPATCH_VER=$(cat UEFIPatch/uefipatch_main.cpp | grep '"UEFIPatch [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) -UEFIREPLACE_VER=$(cat UEFIReplace/uefireplace_main.cpp | grep '"UEFIReplace [0-9]' | cut -d'"' -f2 | cut -d' ' -f2) +UEFITOOL_VER=$(cat version.h | grep PROGRAM_VERSION | cut -d'"' -f2) build_tool() { echo "Building $1 $2" @@ -113,8 +111,8 @@ build_tool() { rm -rf dist mkdir -p dist || exit 1 -build_tool UEFITool "$UEFITOOL_VER" uefitool.pro -build_tool UEFIPatch "$UEFIPATCH_VER" uefipatch.pro patches*.txt -build_tool UEFIReplace "$UEFIREPLACE_VER" uefireplace.pro +build_tool UEFITool "$UEFITOOL_VER" uefitool.pro +build_tool UEFIPatch "$UEFITOOL_VER" uefipatch.pro patches*.txt +build_tool UEFIReplace "$UEFITOOL_VER" uefireplace.pro exit 0 diff --git a/version.h b/version.h new file mode 100644 index 0000000..9d0a434 --- /dev/null +++ b/version.h @@ -0,0 +1,19 @@ +/* types.h + +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. + +*/ + +#ifndef __VERSION_H__ +#define __VERSION_H__ + +#define PROGRAM_VERSION "0.25.0" + +#endif \ No newline at end of file From c4567dcffce4cf2dca47f5290722ded6f2bac615 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sat, 23 Jun 2018 00:39:51 +0300 Subject: [PATCH 61/64] Attempt to workaround #137 --- ffsengine.h | 2 +- treeitem.cpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ffsengine.h b/ffsengine.h index 8b2f327..0a2130d 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -95,7 +95,7 @@ public: UINT8 replace(const QModelIndex & index, const QByteArray & object, const UINT8 mode); UINT8 remove(const QModelIndex & index); UINT8 rebuild(const QModelIndex & index); - UINT8 doNotRebuild(const QModelIndex & index); + UINT8 doNotRebuild(const QModelIndex & index); UINT8 dump(const QModelIndex & index, const QString & path, const QString & filter = QString()); UINT8 patch(const QModelIndex & index, const QVector & patches); diff --git a/treeitem.cpp b/treeitem.cpp index 925d95b..cdee8c2 100644 --- a/treeitem.cpp +++ b/treeitem.cpp @@ -209,7 +209,22 @@ void TreeItem::setAction(const UINT8 action) // Set rebuild action for parent, if it has no action now if (parentItem && parentItem->type() != Types::Root - && parentItem->action() == Actions::NoAction) + && parentItem->action() == Actions::NoAction) { parentItem->setAction(Actions::Rebuild); -} + // Set rebuild action for subsequent items after parent. + // This is a little ugly, but fixes UEFIReplace image corruption, + // where one cannot manually choose the targets for rebuild. + // See: https://github.com/LongSoft/UEFITool/issues/137 + TreeItem *grandParent = parentItem->parentItem; + if (grandParent) { + QList &parentCousins = grandParent->childItems; + int count = parentCousins.count(); + for (int i = parentCousins.indexOf(parentItem) + 1; i < count; i++) { + TreeItem *parentCousin = parentCousins.value(i, NULL); + if (parentCousin && parentCousin->action() == Actions::NoAction) + parentCousin->setAction(Actions::Rebuild); + } + } + } +} From 35c207dd8c31215fe11b56dbe2542674ccee6b6b Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sat, 23 Jun 2018 19:46:56 +0300 Subject: [PATCH 62/64] More proper solution to #137 --- ffsengine.cpp | 26 ++++++++++++++++++++++++++ treeitem.cpp | 18 +----------------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/ffsengine.cpp b/ffsengine.cpp index ea7c172..b9e9c26 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -2453,6 +2453,32 @@ void FfsEngine::rebasePeiFiles(const QModelIndex & index) } } } + + // Rebase VTF in subsequent volumes. + QModelIndex parent = index.parent(); + while (parent.isValid() && model->type(parent) != Types::Volume) + parent = parent.parent(); + if (parent.isValid()) { + QModelIndex volumeContainer = parent.parent(); + // Iterate over volumes starting from the one after. + for (int i = parent.row() + 1; i < model->rowCount(volumeContainer); i++) { + QModelIndex currentVolumeIndex = volumeContainer.child(i, 0); + // Iterate over files within each volume after the current one. + for (int j = 0; j < model->rowCount(currentVolumeIndex); j++) { + QModelIndex currentFileIndex = currentVolumeIndex.child(j, 0); + if (model->header(currentFileIndex).left(sizeof(EFI_GUID)) == EFI_FFS_VOLUME_TOP_FILE_GUID) { + for (int k = 0; k < model->rowCount(currentFileIndex); k++) { + QModelIndex currentSectionIndex = currentFileIndex.child(k, 0); + // If section stores PE32 or TE image + if (model->subtype(currentSectionIndex) == EFI_SECTION_PE32 || model->subtype(currentSectionIndex) == EFI_SECTION_TE) + // Set rebase action + if (model->action(currentSectionIndex) != Actions::Remove) + model->setAction(currentSectionIndex, Actions::Rebase); + } + } + } + } + } } UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, const UINT8 mode) diff --git a/treeitem.cpp b/treeitem.cpp index cdee8c2..2c3cc34 100644 --- a/treeitem.cpp +++ b/treeitem.cpp @@ -209,22 +209,6 @@ void TreeItem::setAction(const UINT8 action) // Set rebuild action for parent, if it has no action now if (parentItem && parentItem->type() != Types::Root - && parentItem->action() == Actions::NoAction) { + && parentItem->action() == Actions::NoAction) parentItem->setAction(Actions::Rebuild); - - // Set rebuild action for subsequent items after parent. - // This is a little ugly, but fixes UEFIReplace image corruption, - // where one cannot manually choose the targets for rebuild. - // See: https://github.com/LongSoft/UEFITool/issues/137 - TreeItem *grandParent = parentItem->parentItem; - if (grandParent) { - QList &parentCousins = grandParent->childItems; - int count = parentCousins.count(); - for (int i = parentCousins.indexOf(parentItem) + 1; i < count; i++) { - TreeItem *parentCousin = parentCousins.value(i, NULL); - if (parentCousin && parentCousin->action() == Actions::NoAction) - parentCousin->setAction(Actions::Rebuild); - } - } - } } From e6f84f9f7ddd61a95a968a2b3a89df39038f4f03 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 24 Jun 2018 17:07:52 +0300 Subject: [PATCH 63/64] Version bump --- version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.h b/version.h index 9d0a434..a0b8c46 100644 --- a/version.h +++ b/version.h @@ -14,6 +14,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef __VERSION_H__ #define __VERSION_H__ -#define PROGRAM_VERSION "0.25.0" +#define PROGRAM_VERSION "0.25.1" #endif \ No newline at end of file From 4bee991c949b458739ffa96b88dbc589192c7689 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Sun, 30 Dec 2018 18:37:27 +0300 Subject: [PATCH 64/64] Implement custom LZMA dictionary size support, fixes #154 --- LZMA/LzmaCompress.c | 6 ++-- LZMA/LzmaCompress.h | 5 ++-- ffsengine.cpp | 67 +++++++++++++++++++++++++++++++-------------- ffsengine.h | 2 +- treeitem.cpp | 11 ++++++++ treeitem.h | 4 +++ treemodel.cpp | 18 ++++++++++++ treemodel.h | 5 ++-- version.h | 8 +++--- 9 files changed, 93 insertions(+), 33 deletions(-) diff --git a/LZMA/LzmaCompress.c b/LZMA/LzmaCompress.c index f6fc545..51072ca 100644 --- a/LZMA/LzmaCompress.c +++ b/LZMA/LzmaCompress.c @@ -64,7 +64,8 @@ LzmaCompress ( CONST UINT8 *Source, UINT32 SourceSize, UINT8 *Destination, - UINT32 *DestinationSize + UINT32 *DestinationSize, + UINT32 DictionarySize ) { SRes LzmaResult; @@ -79,8 +80,7 @@ LzmaCompress ( } LzmaEncProps_Init(&props); - // TODO: need to detect this instead of hardcoding - props.dictSize = LZMA_DICTIONARY_SIZE; + props.dictSize = DictionarySize; props.level = 9; props.fb = 273; diff --git a/LZMA/LzmaCompress.h b/LZMA/LzmaCompress.h index bc098b1..aa90ede 100644 --- a/LZMA/LzmaCompress.h +++ b/LZMA/LzmaCompress.h @@ -21,7 +21,7 @@ extern "C" { #endif -#define LZMA_DICTIONARY_SIZE 0x800000 +#define DEFAULT_LZMA_DICTIONARY_SIZE 0x800000 #define _LZMA_SIZE_OPT EFI_STATUS @@ -30,7 +30,8 @@ extern "C" { const UINT8 *Source, UINT32 SourceSize, UINT8 *Destination, - UINT32 *DestinationSize + UINT32 *DestinationSize, + UINT32 DictionarySize ); #ifdef __cplusplus diff --git a/ffsengine.cpp b/ffsengine.cpp index b9e9c26..4fa625c 100644 --- a/ffsengine.cpp +++ b/ffsengine.cpp @@ -1590,8 +1590,16 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .arg(compressionTypeToQString(algorithm)) .hexarg(compressedSectionHeader->UncompressedLength).arg(compressedSectionHeader->UncompressedLength); + UINT32 dictionarySize = DEFAULT_LZMA_DICTIONARY_SIZE; + if (algorithm == COMPRESSION_ALGORITHM_LZMA) { + // Dictionary size is stored in bytes 1-4 of LZMA-compressed data + dictionarySize = *(UINT32*)(body.constData() + 1); + info += tr("\nLZMA dictionary size: %1h").hexarg(dictionarySize); + } + // Add tree item index = model->addItem(Types::Section, sectionHeader->Type, algorithm, name, "", info, header, body, parent, mode); + model->setDictionarySize(index, dictionarySize); // Show message if (!parseCurrentSection) @@ -1632,6 +1640,8 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c .hexarg2(guidDefinedSectionHeader->Attributes, 4); UINT8 algorithm = COMPRESSION_ALGORITHM_NONE; + UINT32 dictionarySize = DEFAULT_LZMA_DICTIONARY_SIZE; + // Check if section requires processing if (guidDefinedSectionHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) { // Tiano compressed section @@ -1664,6 +1674,10 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c if (algorithm == COMPRESSION_ALGORITHM_LZMA) { info += tr("\nCompression type: LZMA"); info += tr("\nDecompressed size: %1h (%2)").hexarg(processed.length()).arg(processed.length()); + + // Dictionary size is stored in bytes 1-4 of LZMA-compressed data + dictionarySize = *(UINT32*)(body.constData() + 1); + info += tr("\nLZMA dictionary size: %1h").hexarg(dictionarySize); } else info += tr("\nCompression type: unknown"); @@ -1743,6 +1757,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, QModelIndex & index, c // Add tree item index = model->addItem(Types::Section, sectionHeader->Type, algorithm, name, "", info, header, body, parent, mode); + model->setDictionarySize(index, dictionarySize); // Show messages if (msgUnknownGuid) @@ -2164,6 +2179,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte QByteArray created; UINT8 result; QModelIndex fileIndex; + UINT32 defaultDictionarySize = DEFAULT_LZMA_DICTIONARY_SIZE; if (!index.isValid() || !index.parent().isValid()) return ERR_INVALID_PARAMETER; @@ -2344,18 +2360,21 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte sectionHeader->UncompressedLength = body.size(); // Set compression type - if (algorithm == COMPRESSION_ALGORITHM_NONE) + if (algorithm == COMPRESSION_ALGORITHM_NONE) { sectionHeader->CompressionType = EFI_NOT_COMPRESSED; - else if (algorithm == COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO) + } + else if (algorithm == COMPRESSION_ALGORITHM_EFI11 || algorithm == COMPRESSION_ALGORITHM_TIANO) { sectionHeader->CompressionType = EFI_STANDARD_COMPRESSION; - else if (algorithm == COMPRESSION_ALGORITHM_LZMA || algorithm == COMPRESSION_ALGORITHM_IMLZMA) + } + else if (algorithm == COMPRESSION_ALGORITHM_LZMA || algorithm == COMPRESSION_ALGORITHM_IMLZMA) { sectionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION; + } else return ERR_UNKNOWN_COMPRESSION_ALGORITHM; // Compress body QByteArray compressed; - result = compress(body, algorithm, compressed); + result = compress(body, algorithm, defaultDictionarySize, compressed); if (result) return result; @@ -2381,7 +2400,7 @@ UINT8 FfsEngine::create(const QModelIndex & index, const UINT8 type, const QByte case EFI_SECTION_GUID_DEFINED:{ // Compress body QByteArray compressed; - result = compress(body, algorithm, compressed); + result = compress(body, algorithm, defaultDictionarySize, compressed); if (result) return result; @@ -2843,7 +2862,7 @@ UINT8 FfsEngine::decompress(const QByteArray & compressedData, const UINT8 compr } } -UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData) +UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, const UINT32 dictionarySize, QByteArray & compressedData) { UINT8* compressed; @@ -2933,10 +2952,10 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA case COMPRESSION_ALGORITHM_LZMA: { UINT32 compressedSize = 0; - if (LzmaCompress((const UINT8*)data.constData(), data.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL) + if (LzmaCompress((const UINT8*)data.constData(), data.size(), NULL, &compressedSize, dictionarySize) != ERR_BUFFER_TOO_SMALL) return ERR_CUSTOMIZED_COMPRESSION_FAILED; compressed = new UINT8[compressedSize]; - if (LzmaCompress((const UINT8*)data.constData(), data.size(), compressed, &compressedSize) != ERR_SUCCESS) { + if (LzmaCompress((const UINT8*)data.constData(), data.size(), compressed, &compressedSize, dictionarySize) != ERR_SUCCESS) { delete[] compressed; return ERR_CUSTOMIZED_COMPRESSION_FAILED; } @@ -2953,10 +2972,10 @@ UINT8 FfsEngine::compress(const QByteArray & data, const UINT8 algorithm, QByteA UINT32 headerSize = sizeOfSectionHeader(sectionHeader); header = data.left(headerSize); QByteArray newData = data.mid(headerSize); - if (LzmaCompress((const UINT8*)newData.constData(), newData.size(), NULL, &compressedSize) != ERR_BUFFER_TOO_SMALL) + if (LzmaCompress((const UINT8*)newData.constData(), newData.size(), NULL, &compressedSize, dictionarySize) != ERR_BUFFER_TOO_SMALL) return ERR_CUSTOMIZED_COMPRESSION_FAILED; compressed = new UINT8[compressedSize]; - if (LzmaCompress((const UINT8*)newData.constData(), newData.size(), compressed, &compressedSize) != ERR_SUCCESS) { + if (LzmaCompress((const UINT8*)newData.constData(), newData.size(), compressed, &compressedSize, dictionarySize) != ERR_SUCCESS) { delete[] compressed; return ERR_CUSTOMIZED_COMPRESSION_FAILED; } @@ -3919,21 +3938,29 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base, EFI_COMPRESSION_SECTION* compessionHeader = (EFI_COMPRESSION_SECTION*)header.data(); // Set new uncompressed size compessionHeader->UncompressedLength = reconstructed.size(); - // Compress new section body - QByteArray compressed; - result = compress(reconstructed, model->compression(index), compressed); - if (result) - return result; + // Correct compression type - if (model->compression(index) == COMPRESSION_ALGORITHM_NONE) + if (model->compression(index) == COMPRESSION_ALGORITHM_NONE) { compessionHeader->CompressionType = EFI_NOT_COMPRESSED; - else if (model->compression(index) == COMPRESSION_ALGORITHM_LZMA || model->compression(index) == COMPRESSION_ALGORITHM_IMLZMA) - compessionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION; - else if (model->compression(index) == COMPRESSION_ALGORITHM_EFI11 || model->compression(index) == COMPRESSION_ALGORITHM_TIANO) + } + else if (model->compression(index) == COMPRESSION_ALGORITHM_EFI11 || model->compression(index) == COMPRESSION_ALGORITHM_TIANO) { compessionHeader->CompressionType = EFI_STANDARD_COMPRESSION; + } + else if (model->compression(index) == COMPRESSION_ALGORITHM_LZMA) { + compessionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION; + } + else if (model->compression(index) == COMPRESSION_ALGORITHM_IMLZMA) { + compessionHeader->CompressionType = EFI_CUSTOMIZED_COMPRESSION; + } else return ERR_UNKNOWN_COMPRESSION_ALGORITHM; + // Compress new section body + QByteArray compressed; + result = compress(reconstructed, model->compression(index), model->dictionarySize(index), compressed); + if (result) + return result; + // Replace new section body reconstructed = compressed; } @@ -3941,7 +3968,7 @@ UINT8 FfsEngine::reconstructSection(const QModelIndex& index, const UINT32 base, EFI_GUID_DEFINED_SECTION* guidDefinedHeader = (EFI_GUID_DEFINED_SECTION*)header.data(); // Compress new section body QByteArray compressed; - result = compress(reconstructed, model->compression(index), compressed); + result = compress(reconstructed, model->compression(index), model->dictionarySize(index), compressed); if (result) return result; // Check for authentication status valid attribute diff --git a/ffsengine.h b/ffsengine.h index 0a2130d..ddd7139 100644 --- a/ffsengine.h +++ b/ffsengine.h @@ -76,7 +76,7 @@ public: // Compression routines UINT8 decompress(const QByteArray & compressed, const UINT8 compressionType, QByteArray & decompressedData, UINT8 * algorithm = NULL); - UINT8 compress(const QByteArray & data, const UINT8 algorithm, QByteArray & compressedData); + UINT8 compress(const QByteArray & data, const UINT8 algorithm, const UINT32 dictionarySize, QByteArray & compressedData); // Construction routines UINT8 reconstructImageFile(QByteArray &reconstructed); diff --git a/treeitem.cpp b/treeitem.cpp index 2c3cc34..27f509f 100644 --- a/treeitem.cpp +++ b/treeitem.cpp @@ -23,6 +23,7 @@ TreeItem::TreeItem(const UINT8 type, const UINT8 subtype, const UINT8 compressio itemType(type), itemSubtype(subtype), itemCompression(compression), + itemDictionarySize(0), itemName(name), itemText(text), itemInfo(info), @@ -198,6 +199,16 @@ UINT8 TreeItem::action() const return itemAction; } +UINT32 TreeItem::dictionarySize() const +{ + return itemDictionarySize; +} + +void TreeItem::setDictionarySize(const UINT32 dictionarySize) +{ + itemDictionarySize = dictionarySize; +} + void TreeItem::setAction(const UINT8 action) { itemAction = action; diff --git a/treeitem.h b/treeitem.h index 58015f4..9972d2b 100644 --- a/treeitem.h +++ b/treeitem.h @@ -72,12 +72,16 @@ public: UINT8 compression() const; + UINT32 dictionarySize() const; + void setDictionarySize(const UINT32 dictionarySize); + private: QList childItems; UINT8 itemAction; UINT8 itemType; UINT8 itemSubtype; UINT8 itemCompression; + UINT32 itemDictionarySize; QString itemName; QString itemText; QString itemInfo; diff --git a/treemodel.cpp b/treemodel.cpp index a82724b..94a0df2 100644 --- a/treemodel.cpp +++ b/treemodel.cpp @@ -218,6 +218,14 @@ UINT8 TreeModel::compression(const QModelIndex &index) const return item->compression(); } +UINT32 TreeModel::dictionarySize(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + TreeItem *item = static_cast(index.internalPointer()); + return item->dictionarySize(); +} + void TreeModel::setSubtype(const QModelIndex & index, const UINT8 subtype) { if (!index.isValid()) @@ -268,6 +276,16 @@ void TreeModel::setAction(const QModelIndex &index, const UINT8 action) emit dataChanged(this->index(0, 0), index); } +void TreeModel::setDictionarySize(const QModelIndex &index, const UINT32 dictionarySize) +{ + if (!index.isValid()) + return; + + TreeItem *item = static_cast(index.internalPointer()); + item->setDictionarySize(dictionarySize); + emit dataChanged(this->index(0, 0), index); +} + QModelIndex TreeModel::addItem(const UINT8 type, const UINT8 subtype, const UINT8 compression, const QString & name, const QString & text, const QString & info, const QByteArray & header, const QByteArray & body, const QModelIndex & parent, const UINT8 mode) diff --git a/treemodel.h b/treemodel.h index ae9c717..0596ac6 100644 --- a/treemodel.h +++ b/treemodel.h @@ -47,7 +47,7 @@ public: void setSubtype(const QModelIndex &index, const UINT8 subtype); void setName(const QModelIndex &index, const QString &name); void setText(const QModelIndex &index, const QString &text); - void setParsingData(const QModelIndex &index, const QByteArray &data); + void setDictionarySize(const QModelIndex &index, const UINT32 dictionarySize); QString name(const QModelIndex &index) const; QString text(const QModelIndex &index) const; @@ -58,10 +58,9 @@ public: bool hasEmptyHeader(const QModelIndex &index) const; QByteArray body(const QModelIndex &index) const; bool hasEmptyBody(const QModelIndex &index) const; - QByteArray parsingData(const QModelIndex &index) const; - bool hasEmptyParsingData(const QModelIndex &index) const; UINT8 action(const QModelIndex &index) const; UINT8 compression(const QModelIndex &index) const; + UINT32 dictionarySize(const QModelIndex &index) const; QModelIndex addItem(const UINT8 type, const UINT8 subtype = 0, const UINT8 compression = COMPRESSION_ALGORITHM_NONE, const QString & name = QString(), const QString & text = QString(), const QString & info = QString(), diff --git a/version.h b/version.h index a0b8c46..1bdb437 100644 --- a/version.h +++ b/version.h @@ -11,9 +11,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. */ -#ifndef __VERSION_H__ -#define __VERSION_H__ +#ifndef VERSION_H +#define VERSION_H -#define PROGRAM_VERSION "0.25.1" +#define PROGRAM_VERSION "0.26.0" -#endif \ No newline at end of file +#endif // VERSION_H