From 7e1e1ab61ea9db4c5e292eb33105c7e8b8609e01 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Wed, 10 Oct 2018 17:20:00 +0300 Subject: [PATCH] Bugfixes for #147 --- UEFIExtract/ffsdumper.cpp | 28 ++++++++++++++++------------ UEFIExtract/ffsdumper.h | 1 + UEFIExtract/uefidump.cpp | 2 +- UEFIExtract/uefiextract_main.cpp | 6 +++--- UEFIFind/uefifind.cpp | 4 ++-- common/bstrlib/bstrwrap.h | 29 ++++++++++++++++++----------- common/ffsparser.cpp | 6 +++--- common/filesystem.h | 17 +++++++++++++++++ common/nvramparser.cpp | 4 ++-- common/utility.cpp | 2 +- 10 files changed, 64 insertions(+), 35 deletions(-) diff --git a/UEFIExtract/ffsdumper.cpp b/UEFIExtract/ffsdumper.cpp index fde0765..61d7794 100644 --- a/UEFIExtract/ffsdumper.cpp +++ b/UEFIExtract/ffsdumper.cpp @@ -38,16 +38,15 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path if (guid.isEmpty() || (model->subtype(index) == EFI_SECTION_FREEFORM_SUBTYPE_GUID && - guidToUString(*(const EFI_GUID*)(model->header(index).constData() + sizeof(EFI_COMMON_SECTION_HEADER))) == guid) || - guidToUString(*(const EFI_GUID*)model->header(index).constData()) == guid || - guidToUString(*(const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData()) == guid) { + guidToUString(readMisaligned((const EFI_GUID*)(model->header(index).constData() + sizeof(EFI_COMMON_SECTION_HEADER)))) == guid) || + guidToUString(readMisaligned((const EFI_GUID*)model->header(index).constData())) == guid || + guidToUString(readMisaligned((const EFI_GUID*)model->header(model->findParentOfType(index, Types::File)).constData())) == guid) { if (!changeDirectory(path) && !makeDirectory(path)) return U_DIR_CREATE; counterHeader = counterBody = counterRaw = counterInfo = 0; - std::ofstream file; if (dumpMode == DUMP_ALL || model->rowCount(index) == 0) { // Dump if leaf item or dumpAll is true if (dumpMode == DUMP_ALL || dumpMode == DUMP_CURRENT || dumpMode == DUMP_HEADER) { if (!model->header(index).isEmpty() && (sectionType == IgnoreSectionType || model->subtype(index) == sectionType)) { @@ -57,10 +56,11 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path else filename = usprintf("%s/header_%d.bin", path.toLocal8Bit(), counterHeader); counterHeader++; - file.open(filename.toLocal8Bit(), std::ofstream::binary); + std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary); + if (!file) + return U_FILE_OPEN; const UByteArray &data = model->header(index); file.write(data.constData(), data.size()); - file.close(); } } @@ -72,10 +72,12 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path else filename = usprintf("%s/body_%d.bin", path.toLocal8Bit(), counterBody); counterBody++; - file.open(filename.toLocal8Bit(), std::ofstream::binary); + errno = 0; + std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary); + if (!file) + return U_FILE_OPEN; const UByteArray &data = model->body(index); file.write(data.constData(), data.size()); - file.close(); } } @@ -89,14 +91,15 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path else filename = usprintf("%s/file_%d.bin", path.toLocal8Bit(), counterRaw); counterRaw++; - file.open(filename.toLocal8Bit(), std::ofstream::binary); + std::ofstream file(filename.toLocal8Bit(), std::ofstream::binary); + if (!file) + return U_FILE_OPEN; const UByteArray &headerData = model->header(index); const UByteArray &bodyData = model->body(index); const UByteArray &tailData = model->tail(index); file.write(headerData.constData(), headerData.size()); file.write(bodyData.constData(), bodyData.size()); file.write(tailData.constData(), tailData.size()); - file.close(); } } @@ -115,9 +118,10 @@ USTATUS FfsDumper::recursiveDump(const UModelIndex & index, const UString & path else filename = usprintf("%s/info_%d.txt", path.toLocal8Bit(), counterInfo); counterInfo++; - file.open(filename.toLocal8Bit()); + std::ofstream file(filename.toLocal8Bit()); + if (!file) + return U_FILE_OPEN; file << info.toLocal8Bit(); - file.close(); } dumped = true; diff --git a/UEFIExtract/ffsdumper.h b/UEFIExtract/ffsdumper.h index b09be31..a002af3 100644 --- a/UEFIExtract/ffsdumper.h +++ b/UEFIExtract/ffsdumper.h @@ -19,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "../common/treemodel.h" #include "../common/ffs.h" #include "../common/filesystem.h" +#include "../common/utility.h" class FfsDumper { diff --git a/UEFIExtract/uefidump.cpp b/UEFIExtract/uefidump.cpp index ac362ca..84a006c 100644 --- a/UEFIExtract/uefidump.cpp +++ b/UEFIExtract/uefidump.cpp @@ -51,7 +51,7 @@ USTATUS UEFIDumper::dump(const UByteArray & buffer, const UString & inPath, cons std::vector, UModelIndex > > fitTable = ffsParser.getFitTable(); if (fitTable.size()) { std::cout << "-------------------------------------------------------------------------" << std::endl; - std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl; + std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl; std::cout << "-------------------------------------------------------------------------" << std::endl; for (size_t i = 0; i < fitTable.size(); i++) { std::cout << fitTable[i].first[0].toLocal8Bit() << " | " diff --git a/UEFIExtract/uefiextract_main.cpp b/UEFIExtract/uefiextract_main.cpp index b48d7d5..3623dfb 100644 --- a/UEFIExtract/uefiextract_main.cpp +++ b/UEFIExtract/uefiextract_main.cpp @@ -38,7 +38,7 @@ int main(int argc, char *argv[]) // Check that input file exists USTATUS result; UByteArray buffer; - UString path = argv[1]; + UString path = getAbsPath(argv[1]); result = readFileIntoBuffer(path, buffer); if (result) return result; @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) std::vector, UModelIndex > > fitTable = ffsParser.getFitTable(); if (fitTable.size()) { std::cout << "---------------------------------------------------------------------------" << std::endl; - std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl; + std::cout << " Address | Size | Ver | CS | Type / Info " << std::endl; std::cout << "---------------------------------------------------------------------------" << std::endl; for (size_t i = 0; i < fitTable.size(); i++) { std::cout << fitTable[i].first[0].toLocal8Bit() << " | " @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) if (readType == READ_INPUT) { inputs.push_back(arg); } else if (readType == READ_OUTPUT) { - outputs.push_back(arg); + outputs.push_back(getAbsPath(arg)); } else if (readType == READ_MODE) { if (!std::strcmp(arg, "all")) modes.push_back(FfsDumper::DUMP_ALL); diff --git a/UEFIFind/uefifind.cpp b/UEFIFind/uefifind.cpp index 2115d49..7d5233e 100644 --- a/UEFIFind/uefifind.cpp +++ b/UEFIFind/uefifind.cpp @@ -67,12 +67,12 @@ USTATUS UEFIFind::find(const UINT8 mode, const bool count, const UString & hexPa std::pair indexes = *citer; if (!model->hasEmptyHeader(indexes.first)) data = model->header(indexes.first).left(16); - result += guidToUString(*(const EFI_GUID*)data.constData()); + result += guidToUString(readMisaligned((const EFI_GUID*)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); - result += UString(" ") + (guidToUString(*(const EFI_GUID*)(data.constData() + sizeof(EFI_COMMON_SECTION_HEADER)))); + result += UString(" ") + (guidToUString(readMisaligned((const EFI_GUID*)(data.constData() + sizeof(EFI_COMMON_SECTION_HEADER))))); } result += UString("\n"); diff --git a/common/bstrlib/bstrwrap.h b/common/bstrlib/bstrwrap.h index e8e0d16..4c3c890 100644 --- a/common/bstrlib/bstrwrap.h +++ b/common/bstrlib/bstrwrap.h @@ -361,17 +361,24 @@ struct CBString : public tagbstring { int gets (bNgetc getcPtr, void * parm, char terminator = '\n'); int read (bNread readPtr, void * parm); - // QString compatibility methods - const char *toLocal8Bit() const { return *this; } - bool contains(const char *str) { return find(str) >= 0; } - bool isEmpty() const { return slen == 0; } - void clear() { *this = ""; } - CBString left(int len) const { return midstr(0, len); } - CBString mid(int pos, int len) const { return midstr(pos, len); } - static CBString fromUtf16(const unsigned short* str) { // Naive implementation assuming that only ASCII part of UCS2 is used - CBString msg; while (*str) { msg += *(char*)str; str++; } return msg; - } - CBString leftJustified(int length) { if (length > slen) { return *this + CBString(' ', length - slen); } return *this; } + // QString compatibility methods + const char *toLocal8Bit() const { return *this; } + bool contains(const char *str) { return find(str) >= 0; } + bool isEmpty() const { return slen == 0; } + void clear() { *this = ""; } + CBString left(int len) const { return midstr(0, len); } + CBString mid(int pos, int len) const { return midstr(pos, len); } + static CBString fromUtf16(const unsigned short* str) { + // Naive implementation assuming that only ASCII LE part of UCS2 is used, str may not be aligned. + CBString msg; + const char *str8 = reinterpret_cast(str); + while (str8[0]) { + msg += str8[0]; + str8 += 2; + } + return msg; + } + CBString leftJustified(int length) { if (length > slen) { return *this + CBString(' ', length - slen); } return *this; } }; extern const CBString operator + (const char *a, const CBString& b); extern const CBString operator + (const unsigned char *a, const CBString& b); diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index d19ed3a..5522524 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -2449,8 +2449,8 @@ USTATUS FfsParser::parseCompressedSectionBody(const UModelIndex & index) if (model->hasEmptyParsingData(index) == false) { UByteArray data = model->parsingData(index); const COMPRESSED_SECTION_PARSING_DATA* pdata = (const COMPRESSED_SECTION_PARSING_DATA*)data.constData(); - compressionType = pdata->compressionType; - uncompressedSize = pdata->uncompressedSize; + compressionType = readMisaligned(pdata).compressionType; + uncompressedSize = readMisaligned(pdata).uncompressedSize; } // Decompress section @@ -3449,7 +3449,7 @@ USTATUS FfsParser::parseFit(const UModelIndex & index) // Add FIT header std::vector currentStrings; - currentStrings.push_back(UString("_FIT_ ")); + currentStrings.push_back(UString("_FIT_ ")); currentStrings.push_back(usprintf("%08Xh", fitSize)); currentStrings.push_back(usprintf("%04Xh", fitHeader->Version)); currentStrings.push_back(usprintf("%02Xh", fitHeader->Checksum)); diff --git a/common/filesystem.h b/common/filesystem.h index 2d29e29..eb67f65 100644 --- a/common/filesystem.h +++ b/common/filesystem.h @@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifdef WIN32 #include +#include static inline bool isExistOnFs(const UString & path) { struct _stat buf; return (_stat(path.toLocal8Bit(), &buf) == 0); @@ -34,8 +35,16 @@ static inline bool makeDirectory(const UString & dir) { static inline bool changeDirectory(const UString & dir) { return (_chdir(dir.toLocal8Bit()) == 0); } + +static inline UString getAbsPath(const UString * path) { + char abs[1024] = {}; + if (_fullpath(abs, path.toLocal8Bit(), sizeof(abs))) + UString(abs); + return path; +} #else #include +#include static inline bool isExistOnFs(const UString & path) { struct stat buf; return (stat(path.toLocal8Bit(), &buf) == 0); @@ -48,6 +57,14 @@ static inline bool makeDirectory(const UString & dir) { static inline bool changeDirectory(const UString & dir) { return (chdir(dir.toLocal8Bit()) == 0); } + +static inline UString getAbsPath(const UString & path) { + char abs[PATH_MAX] = {}; + // Last is a non-standard extension for non-existent files. + if (realpath(path.toLocal8Bit(), abs) || abs[0] != '\0') + return UString(abs); + return path; +} #endif static inline USTATUS readFileIntoBuffer(const UString & inPath, UByteArray &buf) { diff --git a/common/nvramparser.cpp b/common/nvramparser.cpp index e2dc9fa..887be86 100644 --- a/common/nvramparser.cpp +++ b/common/nvramparser.cpp @@ -39,7 +39,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) if (parentFileIndex.isValid() && model->hasEmptyParsingData(parentFileIndex) == false) { UByteArray data = model->parsingData(parentFileIndex); const FILE_PARSING_DATA* pdata = (const FILE_PARSING_DATA*)data.constData(); - emptyByte = pdata->emptyByte; + emptyByte = readMisaligned(pdata).emptyByte; } // Rename parent file @@ -365,7 +365,7 @@ USTATUS NvramParser::parseNvarStore(const UModelIndex & index) // Try parsing the entry data as NVAR storage if it begins with NVAR signature if ((subtype == Subtypes::DataNvarEntry || subtype == Subtypes::FullNvarEntry) - && body.size() >= 4 && *(const UINT32*)body.constData() == NVRAM_NVAR_ENTRY_SIGNATURE) + && body.size() >= 4 && readMisaligned((const UINT32*)body.constData()) == NVRAM_NVAR_ENTRY_SIGNATURE) parseNvarStore(varIndex); // Move to next exntry diff --git a/common/utility.cpp b/common/utility.cpp index 0232a07..2b67c9c 100644 --- a/common/utility.cpp +++ b/common/utility.cpp @@ -384,7 +384,7 @@ static inline int char2hex(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') - return c - 'A'; + return c - 'A' + 10; if (c == '.') return -2; return -1;