diff --git a/UEFIExtract/ffsdumper.cpp b/UEFIExtract/ffsdumper.cpp index b495315..14c021f 100644 --- a/UEFIExtract/ffsdumper.cpp +++ b/UEFIExtract/ffsdumper.cpp @@ -22,10 +22,10 @@ FfsDumper::~FfsDumper() { } -STATUS FfsDumper::dump(const QModelIndex & root, const QString & path) +STATUS FfsDumper::dump(const QModelIndex & root, const QString & path, const QString & guid) { dumped = false; - UINT8 result = recursiveDump(root, path); + UINT8 result = recursiveDump(root, path, guid); if (result) return result; else if (!dumped) @@ -33,56 +33,60 @@ STATUS FfsDumper::dump(const QModelIndex & root, const QString & path) return ERR_SUCCESS; } -STATUS FfsDumper::recursiveDump(const QModelIndex & index, const QString & path) +STATUS FfsDumper::recursiveDump(const QModelIndex & index, const QString & path, const QString & guid) { if (!index.isValid()) return ERR_INVALID_PARAMETER; QDir dir; + 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; + if (dir.cd(path)) + return ERR_DIR_ALREADY_EXIST; - if (!dir.mkpath(path)) - return ERR_DIR_CREATE; + if (!dir.mkpath(path)) + return ERR_DIR_CREATE; - QFile file; - if (!model->header(index).isEmpty()) { - file.setFileName(tr("%1/header.bin").arg(path)); - if (!file.open(QFile::WriteOnly)) + QFile file; + if (!model->header(index).isEmpty()) { + file.setFileName(tr("%1/header.bin").arg(path)); + if (!file.open(QFile::WriteOnly)) + return ERR_FILE_OPEN; + + file.write(model->header(index)); + file.close(); + } + + if (!model->body(index).isEmpty()) { + file.setFileName(tr("%1/body.bin").arg(path)); + if (!file.open(QFile::WriteOnly)) + return ERR_FILE_OPEN; + + file.write(model->body(index)); + file.close(); + } + + QString info = tr("Type: %1\nSubtype: %2\n%3%4") + .arg(itemTypeToQString(model->type(index))) + .arg(itemSubtypeToQString(model->type(index), model->subtype(index))) + .arg(model->text(index).isEmpty() ? "" : tr("Text: %1\n").arg(model->text(index))) + .arg(model->info(index)); + file.setFileName(tr("%1/info.txt").arg(path)); + if (!file.open(QFile::Text | QFile::WriteOnly)) return ERR_FILE_OPEN; - file.write(model->header(index)); + file.write(info.toLatin1()); file.close(); + dumped = true; } - if (!model->body(index).isEmpty()) { - file.setFileName(tr("%1/body.bin").arg(path)); - if (!file.open(QFile::WriteOnly)) - return ERR_FILE_OPEN; - - file.write(model->body(index)); - file.close(); - } - - QString info = tr("Type: %1\nSubtype: %2\n%3%4") - .arg(itemTypeToQString(model->type(index))) - .arg(itemSubtypeToQString(model->type(index), model->subtype(index))) - .arg(model->text(index).isEmpty() ? "" : tr("Text: %1\n").arg(model->text(index))) - .arg(model->info(index)); - file.setFileName(tr("%1/info.txt").arg(path)); - if (!file.open(QFile::Text | QFile::WriteOnly)) - return ERR_FILE_OPEN; - - file.write(info.toLatin1()); - file.close(); - dumped = true; - UINT8 result; for (int i = 0; i < model->rowCount(index); i++) { QModelIndex childIndex = index.child(i, 0); QString childPath = QString("%1/%2 %3").arg(path).arg(i).arg(model->text(childIndex).isEmpty() ? model->name(childIndex) : model->text(childIndex)); - result = recursiveDump(childIndex, childPath); + result = recursiveDump(childIndex, childPath, guid); if (result) return result; } diff --git a/UEFIExtract/ffsdumper.h b/UEFIExtract/ffsdumper.h index 5c10d28..817a9bd 100644 --- a/UEFIExtract/ffsdumper.h +++ b/UEFIExtract/ffsdumper.h @@ -23,6 +23,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "../common/basetypes.h" #include "../common/treemodel.h" +#include "../common/ffs.h" class FfsDumper : public QObject { @@ -31,11 +32,11 @@ class FfsDumper : public QObject public: explicit FfsDumper(TreeModel * treeModel, QObject *parent = 0); ~FfsDumper(); - - STATUS dump(const QModelIndex & root, const QString & path); - + + STATUS dump(const QModelIndex & root, const QString & path, const QString & guid = QString()); + private: - STATUS recursiveDump(const QModelIndex & root, const QString & path); + STATUS recursiveDump(const QModelIndex & root, const QString & path, const QString & guid); TreeModel* model; bool dumped; }; diff --git a/UEFIExtract/uefiextract_main.cpp b/UEFIExtract/uefiextract_main.cpp index daa5eb9..0c56b92 100644 --- a/UEFIExtract/uefiextract_main.cpp +++ b/UEFIExtract/uefiextract_main.cpp @@ -28,6 +28,11 @@ int main(int argc, char *argv[]) a.setOrganizationDomain("coderush.me"); a.setApplicationName("UEFIExtract"); + if (a.arguments().length() > 32) { + std::cout << "Too many arguments" << std::endl; + return 1; + } + if (a.arguments().length() > 1) { QString path = a.arguments().at(1); QFileInfo fileInfo(path); @@ -55,11 +60,24 @@ int main(int argc, char *argv[]) } FfsDumper ffsDumper(&model); - return ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")); + + if (a.arguments().length() == 2) { + return (ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump")) != ERR_SUCCESS); + } + else { + UINT32 returned = 0; + for (int i = 2; i < a.arguments().length(); i++) { + result = ffsDumper.dump(model.index(0, 0), fileInfo.fileName().append(".dump"), a.arguments().at(i)); + if (result) + returned |= (1 << (i - 1)); + } + return returned; + } } else { - std::cout << "UEFIExtract 0.10.0" << std::endl << std::endl - << "Usage: uefiextract imagefile" << std::endl; + std::cout << "UEFIExtract 0.10.1" << std::endl << std::endl + << "Usage: uefiextract imagefile [FileGUID_1 FileGUID_2 ... FileGUID_31]" << std::endl + << "Return value is a bit mask where 0 at position N means that file with GUID_N was found and unpacked, 1 otherwise" << std::endl; return 1; } } diff --git a/common/ffsparser.cpp b/common/ffsparser.cpp index 94407a5..e824c28 100644 --- a/common/ffsparser.cpp +++ b/common/ffsparser.cpp @@ -1715,12 +1715,12 @@ STATUS FfsParser::parsePostcodeSectionHeader(const QByteArray & section, const U // Get info QString name = sectionTypeToQString(sectionHeader->Type) + tr(" section"); - QString info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nPostcode: %8\n") + QString info = tr("Type: %1h\nFull size: %2h (%3)\nHeader size: %4h (%5)\nBody size: %6h (%7)\nPostcode: %8h\n") .hexarg2(postcodeHeader->Type, 2) .hexarg(section.size()).arg(section.size()) .hexarg(header.size()).arg(header.size()) .hexarg(body.size()).arg(body.size()) - .arg(postCode); + .hexarg(postCode); // Construct parsing data pdata.offset += parentOffset;