| 2626 | } |
| 2627 | |
| 2628 | UINT8 FfsEngine::extract(const QModelIndex & index, QByteArray & extracted, const UINT8 mode) |
| 2629 | { |
| 2630 | if (!index.isValid()) |
| 2631 | return ERR_INVALID_PARAMETER; |
| 2632 | |
| 2633 | if (mode == EXTRACT_MODE_AS_IS) { |
| 2634 | // Extract as is, with header and body |
| 2635 | extracted.clear(); |
| 2636 | extracted.append(model->header(index)); |
| 2637 | extracted.append(model->body(index)); |
| 2638 | if (model->type(index) == Types::File) { |
| 2639 | UINT8 revision = 2; |
| 2640 | QModelIndex parent = model->parent(index); |
| 2641 | if (parent.isValid() && model->type(parent) == Types::Volume) { |
| 2642 | const EFI_FIRMWARE_VOLUME_HEADER* volumeHeader = (const EFI_FIRMWARE_VOLUME_HEADER*)model->header(parent).constData(); |
| 2643 | revision = volumeHeader->Revision; |
| 2644 | } |
| 2645 | |
| 2646 | const EFI_FFS_FILE_HEADER* fileHeader = (const EFI_FFS_FILE_HEADER*)model->header(index).constData(); |
| 2647 | if (revision == 1 && fileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { |
| 2648 | UINT8 ht = ~fileHeader->IntegrityCheck.Checksum.Header; |
| 2649 | UINT8 ft = ~fileHeader->IntegrityCheck.Checksum.File; |
| 2650 | extracted.append(ht).append(ft); |
| 2651 | } |
| 2652 | } |
| 2653 | } |
| 2654 | else if (mode == EXTRACT_MODE_BODY) { |
| 2655 | // Extract without header and tail |
| 2656 | extracted.clear(); |
| 2657 | // Special case of compressed bodies |
| 2658 | if (model->type(index) == Types::Section) { |
| 2659 | QByteArray decompressed; |
| 2660 | UINT8 result; |
| 2661 | if (model->subtype(index) == EFI_SECTION_COMPRESSION) { |
| 2662 | const EFI_COMPRESSION_SECTION* compressedHeader = (const EFI_COMPRESSION_SECTION*)model->header(index).constData(); |
| 2663 | result = decompress(model->body(index), compressedHeader->CompressionType, decompressed); |
| 2664 | if (result) |
| 2665 | return result; |
| 2666 | extracted.append(decompressed); |
| 2667 | return ERR_SUCCESS; |
| 2668 | } |
| 2669 | else if (model->subtype(index) == EFI_SECTION_GUID_DEFINED) { |
| 2670 | QByteArray decompressed; |
| 2671 | // Check if section requires processing |
| 2672 | const EFI_GUID_DEFINED_SECTION* guidDefinedSectionHeader = (const EFI_GUID_DEFINED_SECTION*)model->header(index).constData(); |
| 2673 | if (guidDefinedSectionHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) { |
| 2674 | // Try to decompress section body using both known compression algorithms |
| 2675 | result = decompress(model->body(index), EFI_STANDARD_COMPRESSION, decompressed); |
| 2676 | if (result) { |
| 2677 | result = decompress(model->body(index), EFI_CUSTOMIZED_COMPRESSION, decompressed); |
| 2678 | if (result) |
| 2679 | return result; |
| 2680 | } |
| 2681 | extracted.append(decompressed); |
| 2682 | return ERR_SUCCESS; |
| 2683 | } |
| 2684 | } |
| 2685 | } |