@@ -372,11 +372,10 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
372372 UINT32 prevVolumeOffset;
373373 UINT8 result;
374374 result = findNextVolume (bios, 0 , prevVolumeOffset);
375- if (result == ERR_VOLUMES_NOT_FOUND)
376- {
377- // msg(tr("No volumes found in BIOS space"));
375+ if (result == ERR_VOLUMES_NOT_FOUND) {
378376 return result;
379377 }
378+
380379 // First volume is not at the beginning of BIOS space
381380 QString name;
382381 QString info;
@@ -514,8 +513,21 @@ UINT8 FfsEngine::parseBios(const QByteArray & bios, const QModelIndex & parent)
514513 prevVolumeSize = volumeSize;
515514
516515 result = findNextVolume (bios, volumeOffset + prevVolumeSize, volumeOffset);
517- if (result == ERR_VOLUMES_NOT_FOUND)
516+ if (result) {
517+ UINT32 endPaddingSize = bios.size () - prevVolumeOffset - prevVolumeSize;
518+ // Padding at the end of BIOS space
519+ if (endPaddingSize > 0 ) {
520+ QByteArray padding = bios.right (endPaddingSize);
521+ // Get info
522+ name = tr (" Padding" );
523+ info = tr (" Size: %2" )
524+ .arg (padding.size (), 8 , 16 , QChar (' 0' ));
525+ // Add tree item
526+ treeModel->addItem (TreeItem::Padding, 0 , COMPRESSION_ALGORITHM_NONE, name, " " , info, QByteArray (), padding, parent);
527+ }
518528 break ;
529+ }
530+
519531 }
520532
521533 return ERR_SUCCESS;
@@ -576,7 +588,7 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
576588 msg (tr (" parseBios: Volume header checksum is invalid" ));
577589 }
578590
579- // Check for presence of extended header, only if header revision is not 1
591+ // Check for presence of extended header, only if header revision is greater then 1
580592 UINT32 headerSize;
581593 if (volumeHeader->Revision > 1 && volumeHeader->ExtHeaderOffset ) {
582594 EFI_FIRMWARE_VOLUME_EXT_HEADER* extendedHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER*) ((UINT8*) volumeHeader + volumeHeader->ExtHeaderOffset );
@@ -598,10 +610,16 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
598610 QByteArray body = volume.mid (headerSize, volumeHeader->FvLength - headerSize);
599611 QModelIndex index = treeModel->addItem (TreeItem::Volume, 0 , COMPRESSION_ALGORITHM_NONE, name, " " , info, header, body, parent, mode);
600612
613+ // Do not parse volumes with unknown FS
614+ if (!parseCurrentVolume)
615+ return ERR_SUCCESS;
616+
601617 // Search for and parse all files
602618 UINT32 fileOffset = headerSize;
603619 UINT32 fileSize;
604620 UINT8 result;
621+ QQueue<QByteArray> files;
622+
605623 while (true ) {
606624 result = getFileSize (volume, fileOffset, fileSize);
607625 if (result)
@@ -616,9 +634,9 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
616634 QByteArray file = volume.mid (fileOffset, fileSize);
617635 QByteArray header = file.left (sizeof (EFI_FFS_FILE_HEADER));
618636
619- // We are now at empty space in the end of volume
637+ // If we are at empty space in the end of volume
620638 if (header.count (empty) == header.size ())
621- break ;
639+ break ; // Exit from loop
622640
623641 // Check file alignment
624642 EFI_FFS_FILE_HEADER* fileHeader = (EFI_FFS_FILE_HEADER*) header.constData ();
@@ -628,6 +646,14 @@ UINT8 FfsEngine::parseVolume(const QByteArray & volume, const QModelIndex & par
628646 msg (tr (" parseVolume: %1, unaligned file" ).arg (guidToQString (fileHeader->Name )));
629647 }
630648
649+ // Check file GUID
650+ if (fileHeader->Type != EFI_FV_FILETYPE_PAD && files.indexOf (header.left (sizeof (EFI_GUID))) != -1 )
651+ msg (tr (" %1: file with duplicate GUID" ).arg (guidToQString (fileHeader->Name )));
652+
653+ // Add file GUID to queue
654+ files.enqueue (header.left (sizeof (EFI_GUID)));
655+
656+ // Parse file
631657 result = parseFile (file, volumeHeader->Revision , empty, index);
632658 if (result)
633659 msg (tr (" parseVolume: Parse FFS file failed (%1)" ).arg (result));
@@ -790,13 +816,13 @@ UINT8 FfsEngine::parseFile(const QByteArray & file, UINT8 revision, const char e
790816 result = parseBios (body, index);
791817 if (result && result != ERR_VOLUMES_NOT_FOUND)
792818 msg (tr (" parseVolume: Parse file as BIOS failed (%1)" ).arg (result));
819+ return ERR_SUCCESS;
793820 }
821+
794822 // Parse sections
795- else {
796- result = parseSections (body, revision, empty, index);
797- if (result)
798- return result;
799- }
823+ result = parseSections (body, revision, empty, index);
824+ if (result)
825+ return result;
800826
801827 return ERR_SUCCESS;
802828}
@@ -959,11 +985,11 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
959985 case EFI_SECTION_PIC:
960986 case EFI_SECTION_TE:
961987 case EFI_SECTION_VERSION:
962- case EFI_SECTION_COMPATIBILITY16:
963988 case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
964989 case EFI_SECTION_DXE_DEPEX:
965990 case EFI_SECTION_PEI_DEPEX:
966991 case EFI_SECTION_SMM_DEPEX:
992+ case EFI_SECTION_COMPATIBILITY16:
967993 headerSize = sizeOfSectionHeaderOfType (sectionHeader->Type );
968994 header = section.left (headerSize);
969995 body = section.mid (headerSize, sectionSize - headerSize);
@@ -997,6 +1023,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
9971023 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
9981024 header = section.left (sizeof (EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
9991025 body = section.mid (sizeof (EFI_FIRMWARE_VOLUME_IMAGE_SECTION), sectionSize - sizeof (EFI_FIRMWARE_VOLUME_IMAGE_SECTION));
1026+
10001027 // Get info
10011028 info = tr (" Type: %1\n Size: %2" )
10021029 .arg (sectionHeader->Type , 2 , 16 , QChar (' 0' ))
@@ -1015,6 +1042,7 @@ UINT8 FfsEngine::parseSection(const QByteArray & section, const UINT8 revision,
10151042 case EFI_SECTION_RAW:
10161043 header = section.left (sizeof (EFI_RAW_SECTION));
10171044 body = section.mid (sizeof (EFI_RAW_SECTION), sectionSize - sizeof (EFI_RAW_SECTION));
1045+
10181046 // Get info
10191047 info = tr (" Type: %1\n Size: %2" )
10201048 .arg (sectionHeader->Type , 2 , 16 , QChar (' 0' ))
@@ -1055,22 +1083,21 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
10551083 // Only files and sections can now be inserted
10561084 if (type == TreeItem::File) {
10571085 QModelIndex parent;
1058- if (mode == ADD_MODE_APPEND || mode == ADD_MODE_PREPEND)
1059- parent = index;
1060- else
1086+ if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
10611087 parent = index.parent ();
1088+ else
1089+ parent = index;
10621090
10631091 // Parent type must be volume
10641092 TreeItem * parentItem = static_cast <TreeItem*>(parent.internalPointer ());
10651093 if (parentItem->type () != TreeItem::Volume) {
1066- msg (tr (" insertInto : file can't be inserted into something that is not volume" ));
1094+ msg (tr (" insert : file can't be inserted into something that is not volume" ));
10671095 return ERR_INVALID_VOLUME;
10681096 }
10691097
10701098 EFI_FIRMWARE_VOLUME_HEADER* header = (EFI_FIRMWARE_VOLUME_HEADER*) parentItem->header ().constData ();
10711099
10721100 // Parse file
1073- // !TODO: add check for same GUIDs
10741101 UINT8 result = parseFile (object, header->Revision , header->Attributes & EFI_FVB_ERASE_POLARITY ? ' \xFF ' : ' \x00 ' , index, mode);
10751102 if (result)
10761103 return result;
@@ -1081,7 +1108,40 @@ UINT8 FfsEngine::insert(const QModelIndex & index, const QByteArray & object, co
10811108
10821109 }
10831110 else if (type == TreeItem::Section) {
1084- return ERR_NOT_IMPLEMENTED;
1111+ QModelIndex parent;
1112+ if (mode == INSERT_MODE_BEFORE || mode == INSERT_MODE_AFTER)
1113+ parent = index.parent ();
1114+ else
1115+ parent = index;
1116+
1117+ // Parent type must be file or encapsulation section
1118+ TreeItem * parentItem = static_cast <TreeItem*>(parent.internalPointer ());
1119+ if (parentItem->type () == TreeItem::File || (parentItem->type () == TreeItem::Section &&
1120+ (parentItem->subtype () == EFI_SECTION_COMPRESSION ||
1121+ parentItem->subtype () == EFI_SECTION_GUID_DEFINED ||
1122+ parentItem->subtype () == EFI_SECTION_DISPOSABLE))) {
1123+ QModelIndex volumeIndex = findParentOfType (TreeItem::Volume, parent);
1124+ if (!volumeIndex.isValid ()) {
1125+ msg (tr (" insert: Parent volume not found" ));
1126+ return ERR_INVALID_VOLUME;
1127+ }
1128+
1129+ TreeItem * volumeItem = static_cast <TreeItem*>(volumeIndex.internalPointer ());
1130+ EFI_FIRMWARE_VOLUME_HEADER* header = (EFI_FIRMWARE_VOLUME_HEADER*) volumeItem->header ().constData ();
1131+
1132+ // Parse section
1133+ UINT8 result = parseSection (object, header->Revision , header->Attributes & EFI_FVB_ERASE_POLARITY ? ' \xFF ' : ' \x00 ' , index, mode);
1134+ if (result)
1135+ return result;
1136+
1137+ // Set reconstruct action for all parents
1138+ for (;parent.isValid (); parent = parent.parent ())
1139+ treeModel->setItemAction (TreeItem::Reconstruct, parent);
1140+ }
1141+ else {
1142+ msg (tr (" insert: section can't be inserted into something that is not file or encapsulation section" ));
1143+ return ERR_INVALID_FILE;
1144+ }
10851145 }
10861146 else
10871147 return ERR_NOT_IMPLEMENTED;
0 commit comments