1*f6dc9357SAndroid Build Coastguard Worker // UefiHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
8*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
9*f6dc9357SAndroid Build Coastguard Worker #endif
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/7zCrc.h"
12*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/LzmaDec.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
15*f6dc9357SAndroid Build Coastguard Worker
16*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/AutoPtr.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringConvert.h"
21*f6dc9357SAndroid Build Coastguard Worker
22*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
23*f6dc9357SAndroid Build Coastguard Worker
24*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
25*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
26*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
27*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
28*f6dc9357SAndroid Build Coastguard Worker
29*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
30*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/LzhDecoder.h"
31*f6dc9357SAndroid Build Coastguard Worker
32*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
33*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
34*f6dc9357SAndroid Build Coastguard Worker #else
35*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
36*f6dc9357SAndroid Build Coastguard Worker #endif
37*f6dc9357SAndroid Build Coastguard Worker
38*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetUi16(p)
39*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetUi32(p)
40*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetUi64(p)
41*f6dc9357SAndroid Build Coastguard Worker #define Get24(p) (Get32(p) & 0xFFFFFF)
42*f6dc9357SAndroid Build Coastguard Worker
43*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
44*f6dc9357SAndroid Build Coastguard Worker namespace NUefi {
45*f6dc9357SAndroid Build Coastguard Worker
46*f6dc9357SAndroid Build Coastguard Worker static const size_t kBufTotalSizeMax = 1 << 29;
47*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumFilesMax = 1 << 18;
48*f6dc9357SAndroid Build Coastguard Worker static const unsigned kLevelMax = 64;
49*f6dc9357SAndroid Build Coastguard Worker
50*f6dc9357SAndroid Build Coastguard Worker static const Byte k_IntelMeSignature[] =
51*f6dc9357SAndroid Build Coastguard Worker {
52*f6dc9357SAndroid Build Coastguard Worker 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
53*f6dc9357SAndroid Build Coastguard Worker 0x5A, 0xA5, 0xF0, 0x0F
54*f6dc9357SAndroid Build Coastguard Worker };
55*f6dc9357SAndroid Build Coastguard Worker
IsIntelMe(const Byte * p)56*f6dc9357SAndroid Build Coastguard Worker static bool IsIntelMe(const Byte *p)
57*f6dc9357SAndroid Build Coastguard Worker {
58*f6dc9357SAndroid Build Coastguard Worker return memcmp(p, k_IntelMeSignature, sizeof(k_IntelMeSignature)) == 0;
59*f6dc9357SAndroid Build Coastguard Worker }
60*f6dc9357SAndroid Build Coastguard Worker
61*f6dc9357SAndroid Build Coastguard Worker static const unsigned kFvHeaderSize = 0x38;
62*f6dc9357SAndroid Build Coastguard Worker
63*f6dc9357SAndroid Build Coastguard Worker static const unsigned kGuidSize = 16;
64*f6dc9357SAndroid Build Coastguard Worker
65*f6dc9357SAndroid Build Coastguard Worker #define CAPSULE_SIGNATURE 0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0
66*f6dc9357SAndroid Build Coastguard Worker #define CAPSULE2_SIGNATURE 0x8B,0xA6,0x3C,0x4A,0x23,0x77,0xFB,0x48,0x80,0x3D,0x57,0x8C,0xC1,0xFE,0xC4,0x4D
67*f6dc9357SAndroid Build Coastguard Worker #define CAPSULE_UEFI_SIGNATURE 0xB9,0x82,0x91,0x53,0xB5,0xAB,0x91,0x43,0xB6,0x9A,0xE3,0xA9,0x43,0xF7,0x2F,0xCC
68*f6dc9357SAndroid Build Coastguard Worker /*
69*f6dc9357SAndroid Build Coastguard Worker 6dcbd5ed-e82d-4c44-bda1-7194199ad92a : Firmware Management `
70*f6dc9357SAndroid Build Coastguard Worker */
71*f6dc9357SAndroid Build Coastguard Worker
72*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Guids_Capsules[][kGuidSize] =
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker { CAPSULE_SIGNATURE },
75*f6dc9357SAndroid Build Coastguard Worker { CAPSULE2_SIGNATURE },
76*f6dc9357SAndroid Build Coastguard Worker { CAPSULE_UEFI_SIGNATURE }
77*f6dc9357SAndroid Build Coastguard Worker };
78*f6dc9357SAndroid Build Coastguard Worker
79*f6dc9357SAndroid Build Coastguard Worker
80*f6dc9357SAndroid Build Coastguard Worker static const unsigned kFfsGuidOffset = 16;
81*f6dc9357SAndroid Build Coastguard Worker
82*f6dc9357SAndroid Build Coastguard Worker #define FFS1_SIGNATURE 0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF
83*f6dc9357SAndroid Build Coastguard Worker #define FFS2_SIGNATURE 0x78,0xE5,0x8C,0x8C,0x3D,0x8A,0x1C,0x4F,0x99,0x35,0x89,0x61,0x85,0xC3,0x2D,0xD3
84*f6dc9357SAndroid Build Coastguard Worker #define MACFS_SIGNATURE 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A
85*f6dc9357SAndroid Build Coastguard Worker // APPLE_BOOT
86*f6dc9357SAndroid Build Coastguard Worker /*
87*f6dc9357SAndroid Build Coastguard Worker "FFS3": "5473c07a-3dcb-4dca-bd6f-1e9689e7349a",
88*f6dc9357SAndroid Build Coastguard Worker "NVRAM_EVSA": "fff12b8d-7696-4c8b-a985-2747075b4f50",
89*f6dc9357SAndroid Build Coastguard Worker "NVRAM_NVAR": "cef5b9a3-476d-497f-9fdc-e98143e0422c",
90*f6dc9357SAndroid Build Coastguard Worker "NVRAM_EVSA2": "00504624-8a59-4eeb-bd0f-6b36e96128e0",
91*f6dc9357SAndroid Build Coastguard Worker static const Byte k_NVRAM_NVAR_Guid[kGuidSize] =
92*f6dc9357SAndroid Build Coastguard Worker { 0xA3,0xB9,0xF5,0xCE,0x6D,0x47,0x7F,0x49,0x9F,0xDC,0xE9,0x81,0x43,0xE0,0x42,0x2C };
93*f6dc9357SAndroid Build Coastguard Worker */
94*f6dc9357SAndroid Build Coastguard Worker
95*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Guids_FS[][kGuidSize] =
96*f6dc9357SAndroid Build Coastguard Worker {
97*f6dc9357SAndroid Build Coastguard Worker { FFS1_SIGNATURE },
98*f6dc9357SAndroid Build Coastguard Worker { FFS2_SIGNATURE },
99*f6dc9357SAndroid Build Coastguard Worker { MACFS_SIGNATURE }
100*f6dc9357SAndroid Build Coastguard Worker };
101*f6dc9357SAndroid Build Coastguard Worker
102*f6dc9357SAndroid Build Coastguard Worker
103*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kFvSignature = 0x4856465F; // "_FVH"
104*f6dc9357SAndroid Build Coastguard Worker
105*f6dc9357SAndroid Build Coastguard Worker static const Byte kGuids[][kGuidSize] =
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker { 0xB0,0xCD,0x1B,0xFC,0x31,0x7D,0xAA,0x49,0x93,0x6A,0xA4,0x60,0x0D,0x9D,0xD0,0x83 },
108*f6dc9357SAndroid Build Coastguard Worker { 0x2E,0x06,0xA0,0x1B,0x79,0xC7,0x82,0x45,0x85,0x66,0x33,0x6A,0xE8,0xF7,0x8F,0x09 },
109*f6dc9357SAndroid Build Coastguard Worker { 0x25,0x4E,0x37,0x7E,0x01,0x8E,0xEE,0x4F,0x87,0xf2,0x39,0x0C,0x23,0xC6,0x06,0xCD },
110*f6dc9357SAndroid Build Coastguard Worker { 0x97,0xE5,0x1B,0x16,0xC5,0xE9,0xDB,0x49,0xAE,0x50,0xC4,0x62,0xAB,0x54,0xEE,0xDA },
111*f6dc9357SAndroid Build Coastguard Worker { 0xDB,0x7F,0xAD,0x77,0x2A,0xDF,0x02,0x43,0x88,0x98,0xC7,0x2E,0x4C,0xDB,0xD0,0xF4 },
112*f6dc9357SAndroid Build Coastguard Worker { 0xAB,0x71,0xCF,0xF5,0x4B,0xB0,0x7E,0x4B,0x98,0x8A,0xD8,0xA0,0xD4,0x98,0xE6,0x92 },
113*f6dc9357SAndroid Build Coastguard Worker { 0x91,0x45,0x53,0x7A,0xCE,0x37,0x81,0x48,0xB3,0xC9,0x71,0x38,0x14,0xF4,0x5D,0x6B },
114*f6dc9357SAndroid Build Coastguard Worker { 0x84,0xE6,0x7A,0x36,0x5D,0x33,0x71,0x46,0xA1,0x6D,0x89,0x9D,0xBF,0xEA,0x6B,0x88 },
115*f6dc9357SAndroid Build Coastguard Worker { 0x98,0x07,0x40,0x24,0x07,0x38,0x42,0x4A,0xB4,0x13,0xA1,0xEC,0xEE,0x20,0x5D,0xD8 },
116*f6dc9357SAndroid Build Coastguard Worker { 0xEE,0xA2,0x3F,0x28,0x2C,0x53,0x4D,0x48,0x93,0x83,0x9F,0x93,0xB3,0x6F,0x0B,0x7E },
117*f6dc9357SAndroid Build Coastguard Worker { 0x9B,0xD5,0xB8,0x98,0xBA,0xE8,0xEE,0x48,0x98,0xDD,0xC2,0x95,0x39,0x2F,0x1E,0xDB },
118*f6dc9357SAndroid Build Coastguard Worker { 0x09,0x6D,0xE3,0xC3,0x94,0x82,0x97,0x4B,0xA8,0x57,0xD5,0x28,0x8F,0xE3,0x3E,0x28 },
119*f6dc9357SAndroid Build Coastguard Worker { 0x18,0x88,0x53,0x4A,0xE0,0x5A,0xB2,0x4E,0xB2,0xEB,0x48,0x8B,0x23,0x65,0x70,0x22 }
120*f6dc9357SAndroid Build Coastguard Worker };
121*f6dc9357SAndroid Build Coastguard Worker
122*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Guid_LZMA_COMPRESSED[kGuidSize] =
123*f6dc9357SAndroid Build Coastguard Worker { 0x98,0x58,0x4E,0xEE,0x14,0x39,0x59,0x42,0x9D,0x6E,0xDC,0x7B,0xD7,0x94,0x03,0xCF };
124*f6dc9357SAndroid Build Coastguard Worker
125*f6dc9357SAndroid Build Coastguard Worker static const char * const kGuidNames[] =
126*f6dc9357SAndroid Build Coastguard Worker {
127*f6dc9357SAndroid Build Coastguard Worker "CRC"
128*f6dc9357SAndroid Build Coastguard Worker , "VolumeTopFile"
129*f6dc9357SAndroid Build Coastguard Worker , "ACPI"
130*f6dc9357SAndroid Build Coastguard Worker , "ACPI2"
131*f6dc9357SAndroid Build Coastguard Worker , "Main"
132*f6dc9357SAndroid Build Coastguard Worker , "Intel32"
133*f6dc9357SAndroid Build Coastguard Worker , "Intel64"
134*f6dc9357SAndroid Build Coastguard Worker , "Intel32c"
135*f6dc9357SAndroid Build Coastguard Worker , "Intel64c"
136*f6dc9357SAndroid Build Coastguard Worker , "MacVolume"
137*f6dc9357SAndroid Build Coastguard Worker , "MacUpdate.txt"
138*f6dc9357SAndroid Build Coastguard Worker , "MacName"
139*f6dc9357SAndroid Build Coastguard Worker , "Insyde"
140*f6dc9357SAndroid Build Coastguard Worker };
141*f6dc9357SAndroid Build Coastguard Worker
142*f6dc9357SAndroid Build Coastguard Worker enum
143*f6dc9357SAndroid Build Coastguard Worker {
144*f6dc9357SAndroid Build Coastguard Worker kGuidIndex_CRC = 0
145*f6dc9357SAndroid Build Coastguard Worker };
146*f6dc9357SAndroid Build Coastguard Worker
147*f6dc9357SAndroid Build Coastguard Worker struct CSigExtPair
148*f6dc9357SAndroid Build Coastguard Worker {
149*f6dc9357SAndroid Build Coastguard Worker const char *ext;
150*f6dc9357SAndroid Build Coastguard Worker unsigned sigSize;
151*f6dc9357SAndroid Build Coastguard Worker Byte sig[16];
152*f6dc9357SAndroid Build Coastguard Worker };
153*f6dc9357SAndroid Build Coastguard Worker
154*f6dc9357SAndroid Build Coastguard Worker static const CSigExtPair g_Sigs[] =
155*f6dc9357SAndroid Build Coastguard Worker {
156*f6dc9357SAndroid Build Coastguard Worker { "bmp", 2, { 'B','M' } },
157*f6dc9357SAndroid Build Coastguard Worker { "riff", 4, { 'R','I','F','F' } },
158*f6dc9357SAndroid Build Coastguard Worker { "pe", 2, { 'M','Z'} },
159*f6dc9357SAndroid Build Coastguard Worker { "gif", 6, { 'G','I','F','8','9', 'a' } },
160*f6dc9357SAndroid Build Coastguard Worker { "png", 8, { 0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A } },
161*f6dc9357SAndroid Build Coastguard Worker { "jpg", 10, { 0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46 } },
162*f6dc9357SAndroid Build Coastguard Worker { "rom", 2, { 0x55,0xAA } }
163*f6dc9357SAndroid Build Coastguard Worker };
164*f6dc9357SAndroid Build Coastguard Worker
165*f6dc9357SAndroid Build Coastguard Worker enum
166*f6dc9357SAndroid Build Coastguard Worker {
167*f6dc9357SAndroid Build Coastguard Worker kSig_BMP,
168*f6dc9357SAndroid Build Coastguard Worker kSig_RIFF,
169*f6dc9357SAndroid Build Coastguard Worker kSig_PE
170*f6dc9357SAndroid Build Coastguard Worker };
171*f6dc9357SAndroid Build Coastguard Worker
FindExt(const Byte * p,size_t size)172*f6dc9357SAndroid Build Coastguard Worker static const char *FindExt(const Byte *p, size_t size)
173*f6dc9357SAndroid Build Coastguard Worker {
174*f6dc9357SAndroid Build Coastguard Worker unsigned i;
175*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < Z7_ARRAY_SIZE(g_Sigs); i++)
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker const CSigExtPair &pair = g_Sigs[i];
178*f6dc9357SAndroid Build Coastguard Worker if (size >= pair.sigSize)
179*f6dc9357SAndroid Build Coastguard Worker if (memcmp(p, pair.sig, pair.sigSize) == 0)
180*f6dc9357SAndroid Build Coastguard Worker break;
181*f6dc9357SAndroid Build Coastguard Worker }
182*f6dc9357SAndroid Build Coastguard Worker if (i == Z7_ARRAY_SIZE(g_Sigs))
183*f6dc9357SAndroid Build Coastguard Worker return NULL;
184*f6dc9357SAndroid Build Coastguard Worker switch (i)
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker case kSig_BMP:
187*f6dc9357SAndroid Build Coastguard Worker if (GetUi32(p + 2) > size || GetUi32(p + 0xA) > size)
188*f6dc9357SAndroid Build Coastguard Worker return NULL;
189*f6dc9357SAndroid Build Coastguard Worker break;
190*f6dc9357SAndroid Build Coastguard Worker case kSig_RIFF:
191*f6dc9357SAndroid Build Coastguard Worker if (GetUi32(p + 8) == 0x45564157 || GetUi32(p + 0xC) == 0x20746D66 )
192*f6dc9357SAndroid Build Coastguard Worker return "wav";
193*f6dc9357SAndroid Build Coastguard Worker break;
194*f6dc9357SAndroid Build Coastguard Worker case kSig_PE:
195*f6dc9357SAndroid Build Coastguard Worker {
196*f6dc9357SAndroid Build Coastguard Worker if (size < 512)
197*f6dc9357SAndroid Build Coastguard Worker return NULL;
198*f6dc9357SAndroid Build Coastguard Worker UInt32 peOffset = GetUi32(p + 0x3C);
199*f6dc9357SAndroid Build Coastguard Worker if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)
200*f6dc9357SAndroid Build Coastguard Worker return NULL;
201*f6dc9357SAndroid Build Coastguard Worker if (GetUi32(p + peOffset) != 0x00004550)
202*f6dc9357SAndroid Build Coastguard Worker return NULL;
203*f6dc9357SAndroid Build Coastguard Worker break;
204*f6dc9357SAndroid Build Coastguard Worker }
205*f6dc9357SAndroid Build Coastguard Worker }
206*f6dc9357SAndroid Build Coastguard Worker return g_Sigs[i].ext;
207*f6dc9357SAndroid Build Coastguard Worker }
208*f6dc9357SAndroid Build Coastguard Worker
AreGuidsEq(const Byte * p1,const Byte * p2)209*f6dc9357SAndroid Build Coastguard Worker static bool AreGuidsEq(const Byte *p1, const Byte *p2)
210*f6dc9357SAndroid Build Coastguard Worker {
211*f6dc9357SAndroid Build Coastguard Worker return memcmp(p1, p2, kGuidSize) == 0;
212*f6dc9357SAndroid Build Coastguard Worker }
213*f6dc9357SAndroid Build Coastguard Worker
FindGuid(const Byte * p)214*f6dc9357SAndroid Build Coastguard Worker static int FindGuid(const Byte *p)
215*f6dc9357SAndroid Build Coastguard Worker {
216*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(kGuids); i++)
217*f6dc9357SAndroid Build Coastguard Worker if (AreGuidsEq(p, kGuids[i]))
218*f6dc9357SAndroid Build Coastguard Worker return (int)i;
219*f6dc9357SAndroid Build Coastguard Worker return -1;
220*f6dc9357SAndroid Build Coastguard Worker }
221*f6dc9357SAndroid Build Coastguard Worker
IsFfs(const Byte * p)222*f6dc9357SAndroid Build Coastguard Worker static bool IsFfs(const Byte *p)
223*f6dc9357SAndroid Build Coastguard Worker {
224*f6dc9357SAndroid Build Coastguard Worker if (Get32(p + 0x28) != kFvSignature)
225*f6dc9357SAndroid Build Coastguard Worker return false;
226*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_Guids_FS); i++)
227*f6dc9357SAndroid Build Coastguard Worker if (AreGuidsEq(p + kFfsGuidOffset, k_Guids_FS[i]))
228*f6dc9357SAndroid Build Coastguard Worker return true;
229*f6dc9357SAndroid Build Coastguard Worker return false;
230*f6dc9357SAndroid Build Coastguard Worker }
231*f6dc9357SAndroid Build Coastguard Worker
232*f6dc9357SAndroid Build Coastguard Worker #define FVB_ERASE_POLARITY (1 << 11)
233*f6dc9357SAndroid Build Coastguard Worker
234*f6dc9357SAndroid Build Coastguard Worker /*
235*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_FV_Attribs[] =
236*f6dc9357SAndroid Build Coastguard Worker {
237*f6dc9357SAndroid Build Coastguard Worker { 0, "ReadDisabledCap" },
238*f6dc9357SAndroid Build Coastguard Worker { 1, "ReadEnabledCap" },
239*f6dc9357SAndroid Build Coastguard Worker { 2, "ReadEnabled" },
240*f6dc9357SAndroid Build Coastguard Worker { 3, "WriteDisabledCap" },
241*f6dc9357SAndroid Build Coastguard Worker { 4, "WriteEnabledCap" },
242*f6dc9357SAndroid Build Coastguard Worker { 5, "WriteEnabled" },
243*f6dc9357SAndroid Build Coastguard Worker { 6, "LockCap" },
244*f6dc9357SAndroid Build Coastguard Worker { 7, "Locked" },
245*f6dc9357SAndroid Build Coastguard Worker
246*f6dc9357SAndroid Build Coastguard Worker { 9, "StickyWrite" },
247*f6dc9357SAndroid Build Coastguard Worker { 10, "MemoryMapped" },
248*f6dc9357SAndroid Build Coastguard Worker { 11, "ErasePolarity" },
249*f6dc9357SAndroid Build Coastguard Worker
250*f6dc9357SAndroid Build Coastguard Worker { 12, "ReadLockCap" },
251*f6dc9357SAndroid Build Coastguard Worker { 13, "WriteLockCap" },
252*f6dc9357SAndroid Build Coastguard Worker { 14, "WriteLockCap" }
253*f6dc9357SAndroid Build Coastguard Worker };
254*f6dc9357SAndroid Build Coastguard Worker */
255*f6dc9357SAndroid Build Coastguard Worker
256*f6dc9357SAndroid Build Coastguard Worker enum
257*f6dc9357SAndroid Build Coastguard Worker {
258*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_ALL,
259*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_RAW,
260*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_FREEFORM,
261*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_SECURITY_CORE,
262*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_PEI_CORE,
263*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_DXE_CORE,
264*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_PEIM,
265*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_DRIVER,
266*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_COMBINED_PEIM_DRIVER,
267*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_APPLICATION,
268*f6dc9357SAndroid Build Coastguard Worker // The value 0x0A is reserved and should not be used
269*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B,
270*f6dc9357SAndroid Build Coastguard Worker // types 0xF0 - 0xFF are FFS file types
271*f6dc9357SAndroid Build Coastguard Worker FV_FILETYPE_FFS_PAD = 0xF0
272*f6dc9357SAndroid Build Coastguard Worker };
273*f6dc9357SAndroid Build Coastguard Worker
274*f6dc9357SAndroid Build Coastguard Worker static const char * const g_FileTypes[] =
275*f6dc9357SAndroid Build Coastguard Worker {
276*f6dc9357SAndroid Build Coastguard Worker "ALL"
277*f6dc9357SAndroid Build Coastguard Worker , "RAW"
278*f6dc9357SAndroid Build Coastguard Worker , "FREEFORM"
279*f6dc9357SAndroid Build Coastguard Worker , "SECURITY_CORE"
280*f6dc9357SAndroid Build Coastguard Worker , "PEI_CORE"
281*f6dc9357SAndroid Build Coastguard Worker , "DXE_CORE"
282*f6dc9357SAndroid Build Coastguard Worker , "PEIM"
283*f6dc9357SAndroid Build Coastguard Worker , "DRIVER"
284*f6dc9357SAndroid Build Coastguard Worker , "COMBINED_PEIM_DRIVER"
285*f6dc9357SAndroid Build Coastguard Worker , "APPLICATION"
286*f6dc9357SAndroid Build Coastguard Worker , "0xA"
287*f6dc9357SAndroid Build Coastguard Worker , "VOLUME"
288*f6dc9357SAndroid Build Coastguard Worker };
289*f6dc9357SAndroid Build Coastguard Worker
290*f6dc9357SAndroid Build Coastguard Worker // typedef Byte FFS_FILE_ATTRIBUTES;
291*f6dc9357SAndroid Build Coastguard Worker // FFS File Attributes
292*f6dc9357SAndroid Build Coastguard Worker #define FFS_ATTRIB_TAIL_PRESENT 0x01
293*f6dc9357SAndroid Build Coastguard Worker // #define FFS_ATTRIB_RECOVERY 0x02
294*f6dc9357SAndroid Build Coastguard Worker // #define FFS_ATTRIB_HEADER_EXTENSION 0x04
295*f6dc9357SAndroid Build Coastguard Worker // #define FFS_ATTRIB_DATA_ALIGNMENT 0x38
296*f6dc9357SAndroid Build Coastguard Worker #define FFS_ATTRIB_CHECKSUM 0x40
297*f6dc9357SAndroid Build Coastguard Worker
298*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_FFS_FILE_ATTRIBUTES[] =
299*f6dc9357SAndroid Build Coastguard Worker {
300*f6dc9357SAndroid Build Coastguard Worker { 0, "" /* "TAIL" */ },
301*f6dc9357SAndroid Build Coastguard Worker { 1, "RECOVERY" },
302*f6dc9357SAndroid Build Coastguard Worker // { 2, "HEADER_EXTENSION" }, // reserved for future
303*f6dc9357SAndroid Build Coastguard Worker { 6, "" /* "CHECKSUM" */ }
304*f6dc9357SAndroid Build Coastguard Worker };
305*f6dc9357SAndroid Build Coastguard Worker
306*f6dc9357SAndroid Build Coastguard Worker // static const Byte g_Allignment[8] = { 3, 4, 7, 9, 10, 12, 15, 16 };
307*f6dc9357SAndroid Build Coastguard Worker
308*f6dc9357SAndroid Build Coastguard Worker // typedef Byte FFS_FILE_STATE;
309*f6dc9357SAndroid Build Coastguard Worker
310*f6dc9357SAndroid Build Coastguard Worker // Look also FVB_ERASE_POLARITY.
311*f6dc9357SAndroid Build Coastguard Worker // Lower-order State bits are superceded by higher-order State bits.
312*f6dc9357SAndroid Build Coastguard Worker
313*f6dc9357SAndroid Build Coastguard Worker // #define FILE_HEADER_CONSTRUCTION 0x01
314*f6dc9357SAndroid Build Coastguard Worker // #define FILE_HEADER_VALID 0x02
315*f6dc9357SAndroid Build Coastguard Worker #define FILE_DATA_VALID 0x04
316*f6dc9357SAndroid Build Coastguard Worker // #define FILE_MARKED_FOR_UPDATE 0x08
317*f6dc9357SAndroid Build Coastguard Worker // #define FILE_DELETED 0x10
318*f6dc9357SAndroid Build Coastguard Worker // #define FILE_HEADER_INVALID 0x20
319*f6dc9357SAndroid Build Coastguard Worker
320*f6dc9357SAndroid Build Coastguard Worker // SECTION_TYPE
321*f6dc9357SAndroid Build Coastguard Worker
322*f6dc9357SAndroid Build Coastguard Worker // #define SECTION_ALL 0x00
323*f6dc9357SAndroid Build Coastguard Worker
324*f6dc9357SAndroid Build Coastguard Worker #define SECTION_COMPRESSION 0x01
325*f6dc9357SAndroid Build Coastguard Worker #define SECTION_GUID_DEFINED 0x02
326*f6dc9357SAndroid Build Coastguard Worker
327*f6dc9357SAndroid Build Coastguard Worker // Leaf section Type values
328*f6dc9357SAndroid Build Coastguard Worker // #define SECTION_PE32 0x10
329*f6dc9357SAndroid Build Coastguard Worker // #define SECTION_PIC 0x11
330*f6dc9357SAndroid Build Coastguard Worker // #define SECTION_TE 0x12
331*f6dc9357SAndroid Build Coastguard Worker #define SECTION_DXE_DEPEX 0x13
332*f6dc9357SAndroid Build Coastguard Worker #define SECTION_VERSION 0x14
333*f6dc9357SAndroid Build Coastguard Worker #define SECTION_USER_INTERFACE 0x15
334*f6dc9357SAndroid Build Coastguard Worker // #define SECTION_COMPATIBILITY16 0x16
335*f6dc9357SAndroid Build Coastguard Worker #define SECTION_FIRMWARE_VOLUME_IMAGE 0x17
336*f6dc9357SAndroid Build Coastguard Worker #define SECTION_FREEFORM_SUBTYPE_GUID 0x18
337*f6dc9357SAndroid Build Coastguard Worker #define SECTION_RAW 0x19
338*f6dc9357SAndroid Build Coastguard Worker #define SECTION_PEI_DEPEX 0x1B
339*f6dc9357SAndroid Build Coastguard Worker
340*f6dc9357SAndroid Build Coastguard Worker
341*f6dc9357SAndroid Build Coastguard Worker // #define GUIDED_SECTION_PROCESSING_REQUIRED 0x01
342*f6dc9357SAndroid Build Coastguard Worker // #define GUIDED_SECTION_AUTH_STATUS_VALID 0x02
343*f6dc9357SAndroid Build Coastguard Worker
344*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_GUIDED_SECTION_ATTRIBUTES[] =
345*f6dc9357SAndroid Build Coastguard Worker {
346*f6dc9357SAndroid Build Coastguard Worker { 0, "PROCESSING_REQUIRED" },
347*f6dc9357SAndroid Build Coastguard Worker { 1, "AUTH" }
348*f6dc9357SAndroid Build Coastguard Worker };
349*f6dc9357SAndroid Build Coastguard Worker
350*f6dc9357SAndroid Build Coastguard Worker static const CUInt32PCharPair g_SECTION_TYPE[] =
351*f6dc9357SAndroid Build Coastguard Worker {
352*f6dc9357SAndroid Build Coastguard Worker { 0x01, "COMPRESSION" },
353*f6dc9357SAndroid Build Coastguard Worker { 0x02, "GUID" },
354*f6dc9357SAndroid Build Coastguard Worker { 0x10, "efi" },
355*f6dc9357SAndroid Build Coastguard Worker { 0x11, "PIC" },
356*f6dc9357SAndroid Build Coastguard Worker { 0x12, "te" },
357*f6dc9357SAndroid Build Coastguard Worker { 0x13, "DXE_DEPEX" },
358*f6dc9357SAndroid Build Coastguard Worker { 0x14, "VERSION" },
359*f6dc9357SAndroid Build Coastguard Worker { 0x15, "USER_INTERFACE" },
360*f6dc9357SAndroid Build Coastguard Worker { 0x16, "COMPATIBILITY16" },
361*f6dc9357SAndroid Build Coastguard Worker { 0x17, "VOLUME" },
362*f6dc9357SAndroid Build Coastguard Worker { 0x18, "FREEFORM_SUBTYPE_GUID" },
363*f6dc9357SAndroid Build Coastguard Worker { 0x19, "raw" },
364*f6dc9357SAndroid Build Coastguard Worker { 0x1B, "PEI_DEPEX" }
365*f6dc9357SAndroid Build Coastguard Worker };
366*f6dc9357SAndroid Build Coastguard Worker
367*f6dc9357SAndroid Build Coastguard Worker #define COMPRESSION_TYPE_NONE 0
368*f6dc9357SAndroid Build Coastguard Worker #define COMPRESSION_TYPE_LZH 1
369*f6dc9357SAndroid Build Coastguard Worker #define COMPRESSION_TYPE_LZMA 2
370*f6dc9357SAndroid Build Coastguard Worker
371*f6dc9357SAndroid Build Coastguard Worker static const char * const g_Methods[] =
372*f6dc9357SAndroid Build Coastguard Worker {
373*f6dc9357SAndroid Build Coastguard Worker "COPY"
374*f6dc9357SAndroid Build Coastguard Worker , "LZH"
375*f6dc9357SAndroid Build Coastguard Worker , "LZMA"
376*f6dc9357SAndroid Build Coastguard Worker };
377*f6dc9357SAndroid Build Coastguard Worker
378*f6dc9357SAndroid Build Coastguard Worker
AddGuid(AString & dest,const Byte * p,bool full)379*f6dc9357SAndroid Build Coastguard Worker static void AddGuid(AString &dest, const Byte *p, bool full)
380*f6dc9357SAndroid Build Coastguard Worker {
381*f6dc9357SAndroid Build Coastguard Worker char s[64];
382*f6dc9357SAndroid Build Coastguard Worker ::RawLeGuidToString(p, s);
383*f6dc9357SAndroid Build Coastguard Worker // MyStringUpper_Ascii(s);
384*f6dc9357SAndroid Build Coastguard Worker if (!full)
385*f6dc9357SAndroid Build Coastguard Worker s[8] = 0;
386*f6dc9357SAndroid Build Coastguard Worker dest += s;
387*f6dc9357SAndroid Build Coastguard Worker }
388*f6dc9357SAndroid Build Coastguard Worker
389*f6dc9357SAndroid Build Coastguard Worker static const char * const kExpressionCommands[] =
390*f6dc9357SAndroid Build Coastguard Worker {
391*f6dc9357SAndroid Build Coastguard Worker "BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR"
392*f6dc9357SAndroid Build Coastguard Worker };
393*f6dc9357SAndroid Build Coastguard Worker
ParseDepedencyExpression(const Byte * p,UInt32 size,AString & res)394*f6dc9357SAndroid Build Coastguard Worker static bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res)
395*f6dc9357SAndroid Build Coastguard Worker {
396*f6dc9357SAndroid Build Coastguard Worker res.Empty();
397*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < size;)
398*f6dc9357SAndroid Build Coastguard Worker {
399*f6dc9357SAndroid Build Coastguard Worker unsigned command = p[i++];
400*f6dc9357SAndroid Build Coastguard Worker if (command > Z7_ARRAY_SIZE(kExpressionCommands))
401*f6dc9357SAndroid Build Coastguard Worker return false;
402*f6dc9357SAndroid Build Coastguard Worker res += kExpressionCommands[command];
403*f6dc9357SAndroid Build Coastguard Worker if (command < 3)
404*f6dc9357SAndroid Build Coastguard Worker {
405*f6dc9357SAndroid Build Coastguard Worker if (i + kGuidSize > size)
406*f6dc9357SAndroid Build Coastguard Worker return false;
407*f6dc9357SAndroid Build Coastguard Worker res.Add_Space();
408*f6dc9357SAndroid Build Coastguard Worker AddGuid(res, p + i, false);
409*f6dc9357SAndroid Build Coastguard Worker i += kGuidSize;
410*f6dc9357SAndroid Build Coastguard Worker }
411*f6dc9357SAndroid Build Coastguard Worker res += "; ";
412*f6dc9357SAndroid Build Coastguard Worker }
413*f6dc9357SAndroid Build Coastguard Worker return true;
414*f6dc9357SAndroid Build Coastguard Worker }
415*f6dc9357SAndroid Build Coastguard Worker
ParseUtf16zString(const Byte * p,UInt32 size,UString & res)416*f6dc9357SAndroid Build Coastguard Worker static bool ParseUtf16zString(const Byte *p, UInt32 size, UString &res)
417*f6dc9357SAndroid Build Coastguard Worker {
418*f6dc9357SAndroid Build Coastguard Worker if ((size & 1) != 0)
419*f6dc9357SAndroid Build Coastguard Worker return false;
420*f6dc9357SAndroid Build Coastguard Worker res.Empty();
421*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
422*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < size; i += 2)
423*f6dc9357SAndroid Build Coastguard Worker {
424*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(p + i);
425*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
426*f6dc9357SAndroid Build Coastguard Worker break;
427*f6dc9357SAndroid Build Coastguard Worker res += c;
428*f6dc9357SAndroid Build Coastguard Worker }
429*f6dc9357SAndroid Build Coastguard Worker return (i == size - 2);
430*f6dc9357SAndroid Build Coastguard Worker }
431*f6dc9357SAndroid Build Coastguard Worker
ParseUtf16zString2(const Byte * p,UInt32 size,AString & res)432*f6dc9357SAndroid Build Coastguard Worker static bool ParseUtf16zString2(const Byte *p, UInt32 size, AString &res)
433*f6dc9357SAndroid Build Coastguard Worker {
434*f6dc9357SAndroid Build Coastguard Worker UString s;
435*f6dc9357SAndroid Build Coastguard Worker if (!ParseUtf16zString(p, size, s))
436*f6dc9357SAndroid Build Coastguard Worker return false;
437*f6dc9357SAndroid Build Coastguard Worker res = UnicodeStringToMultiByte(s);
438*f6dc9357SAndroid Build Coastguard Worker return true;
439*f6dc9357SAndroid Build Coastguard Worker }
440*f6dc9357SAndroid Build Coastguard Worker
441*f6dc9357SAndroid Build Coastguard Worker #define FLAGS_TO_STRING(pairs, value) FlagsToString(pairs, Z7_ARRAY_SIZE(pairs), value)
442*f6dc9357SAndroid Build Coastguard Worker #define TYPE_TO_STRING(table, value) TypeToString(table, Z7_ARRAY_SIZE(table), value)
443*f6dc9357SAndroid Build Coastguard Worker #define TYPE_PAIR_TO_STRING(table, value) TypePairToString(table, Z7_ARRAY_SIZE(table), value)
444*f6dc9357SAndroid Build Coastguard Worker
445*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kFileHeaderSize = 24;
446*f6dc9357SAndroid Build Coastguard Worker
AddSpaceAndString(AString & res,const AString & newString)447*f6dc9357SAndroid Build Coastguard Worker static void AddSpaceAndString(AString &res, const AString &newString)
448*f6dc9357SAndroid Build Coastguard Worker {
449*f6dc9357SAndroid Build Coastguard Worker if (!newString.IsEmpty())
450*f6dc9357SAndroid Build Coastguard Worker {
451*f6dc9357SAndroid Build Coastguard Worker res.Add_Space_if_NotEmpty();
452*f6dc9357SAndroid Build Coastguard Worker res += newString;
453*f6dc9357SAndroid Build Coastguard Worker }
454*f6dc9357SAndroid Build Coastguard Worker }
455*f6dc9357SAndroid Build Coastguard Worker
456*f6dc9357SAndroid Build Coastguard Worker class CFfsFileHeader
457*f6dc9357SAndroid Build Coastguard Worker {
458*f6dc9357SAndroid Build Coastguard Worker PRF(public:)
459*f6dc9357SAndroid Build Coastguard Worker Byte CheckHeader;
460*f6dc9357SAndroid Build Coastguard Worker Byte CheckFile;
461*f6dc9357SAndroid Build Coastguard Worker Byte Attrib;
462*f6dc9357SAndroid Build Coastguard Worker Byte State;
463*f6dc9357SAndroid Build Coastguard Worker
GetTailReference() const464*f6dc9357SAndroid Build Coastguard Worker UInt16 GetTailReference() const { return (UInt16)(CheckHeader | ((UInt16)CheckFile << 8)); }
GetTailSize() const465*f6dc9357SAndroid Build Coastguard Worker UInt32 GetTailSize() const { return IsThereTail() ? 2 : 0; }
IsThereFileChecksum() const466*f6dc9357SAndroid Build Coastguard Worker bool IsThereFileChecksum() const { return (Attrib & FFS_ATTRIB_CHECKSUM) != 0; }
IsThereTail() const467*f6dc9357SAndroid Build Coastguard Worker bool IsThereTail() const { return (Attrib & FFS_ATTRIB_TAIL_PRESENT) != 0; }
468*f6dc9357SAndroid Build Coastguard Worker public:
469*f6dc9357SAndroid Build Coastguard Worker Byte GuidName[kGuidSize];
470*f6dc9357SAndroid Build Coastguard Worker Byte Type;
471*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
472*f6dc9357SAndroid Build Coastguard Worker
Parse(const Byte * p)473*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p)
474*f6dc9357SAndroid Build Coastguard Worker {
475*f6dc9357SAndroid Build Coastguard Worker unsigned i;
476*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < kFileHeaderSize; i++)
477*f6dc9357SAndroid Build Coastguard Worker if (p[i] != 0xFF)
478*f6dc9357SAndroid Build Coastguard Worker break;
479*f6dc9357SAndroid Build Coastguard Worker if (i == kFileHeaderSize)
480*f6dc9357SAndroid Build Coastguard Worker return false;
481*f6dc9357SAndroid Build Coastguard Worker memcpy(GuidName, p, kGuidSize);
482*f6dc9357SAndroid Build Coastguard Worker CheckHeader = p[0x10];
483*f6dc9357SAndroid Build Coastguard Worker CheckFile = p[0x11];
484*f6dc9357SAndroid Build Coastguard Worker Type = p[0x12];
485*f6dc9357SAndroid Build Coastguard Worker Attrib = p[0x13];
486*f6dc9357SAndroid Build Coastguard Worker Size = Get24(p + 0x14);
487*f6dc9357SAndroid Build Coastguard Worker State = p[0x17];
488*f6dc9357SAndroid Build Coastguard Worker return true;
489*f6dc9357SAndroid Build Coastguard Worker }
490*f6dc9357SAndroid Build Coastguard Worker
GetDataSize() const491*f6dc9357SAndroid Build Coastguard Worker UInt32 GetDataSize() const { return Size - kFileHeaderSize - GetTailSize(); }
GetDataSize2(UInt32 rem) const492*f6dc9357SAndroid Build Coastguard Worker UInt32 GetDataSize2(UInt32 rem) const { return rem - kFileHeaderSize - GetTailSize(); }
493*f6dc9357SAndroid Build Coastguard Worker
Check(const Byte * p,UInt32 size)494*f6dc9357SAndroid Build Coastguard Worker bool Check(const Byte *p, UInt32 size)
495*f6dc9357SAndroid Build Coastguard Worker {
496*f6dc9357SAndroid Build Coastguard Worker if (Size > size)
497*f6dc9357SAndroid Build Coastguard Worker return false;
498*f6dc9357SAndroid Build Coastguard Worker UInt32 tailSize = GetTailSize();
499*f6dc9357SAndroid Build Coastguard Worker if (Size < kFileHeaderSize + tailSize)
500*f6dc9357SAndroid Build Coastguard Worker return false;
501*f6dc9357SAndroid Build Coastguard Worker
502*f6dc9357SAndroid Build Coastguard Worker {
503*f6dc9357SAndroid Build Coastguard Worker unsigned checkSum = 0;
504*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < kFileHeaderSize; i++)
505*f6dc9357SAndroid Build Coastguard Worker checkSum += p[i];
506*f6dc9357SAndroid Build Coastguard Worker checkSum -= p[0x17];
507*f6dc9357SAndroid Build Coastguard Worker checkSum -= p[0x11];
508*f6dc9357SAndroid Build Coastguard Worker if ((Byte)checkSum != 0)
509*f6dc9357SAndroid Build Coastguard Worker return false;
510*f6dc9357SAndroid Build Coastguard Worker }
511*f6dc9357SAndroid Build Coastguard Worker
512*f6dc9357SAndroid Build Coastguard Worker if (IsThereFileChecksum())
513*f6dc9357SAndroid Build Coastguard Worker {
514*f6dc9357SAndroid Build Coastguard Worker unsigned checkSum = 0;
515*f6dc9357SAndroid Build Coastguard Worker UInt32 checkSize = Size - tailSize;
516*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < checkSize; i++)
517*f6dc9357SAndroid Build Coastguard Worker checkSum += p[i];
518*f6dc9357SAndroid Build Coastguard Worker checkSum -= p[0x17];
519*f6dc9357SAndroid Build Coastguard Worker if ((Byte)checkSum != 0)
520*f6dc9357SAndroid Build Coastguard Worker return false;
521*f6dc9357SAndroid Build Coastguard Worker }
522*f6dc9357SAndroid Build Coastguard Worker
523*f6dc9357SAndroid Build Coastguard Worker if (IsThereTail())
524*f6dc9357SAndroid Build Coastguard Worker if (GetTailReference() != (UInt16)~Get16(p + Size - 2))
525*f6dc9357SAndroid Build Coastguard Worker return false;
526*f6dc9357SAndroid Build Coastguard Worker
527*f6dc9357SAndroid Build Coastguard Worker int polarity = 0;
528*f6dc9357SAndroid Build Coastguard Worker int i;
529*f6dc9357SAndroid Build Coastguard Worker for (i = 5; i >= 0; i--)
530*f6dc9357SAndroid Build Coastguard Worker if (((State >> i) & 1) == polarity)
531*f6dc9357SAndroid Build Coastguard Worker {
532*f6dc9357SAndroid Build Coastguard Worker // AddSpaceAndString(s, g_FFS_FILE_STATE_Flags[i]);
533*f6dc9357SAndroid Build Coastguard Worker if ((1 << i) != FILE_DATA_VALID)
534*f6dc9357SAndroid Build Coastguard Worker return false;
535*f6dc9357SAndroid Build Coastguard Worker break;
536*f6dc9357SAndroid Build Coastguard Worker }
537*f6dc9357SAndroid Build Coastguard Worker if (i < 0)
538*f6dc9357SAndroid Build Coastguard Worker return false;
539*f6dc9357SAndroid Build Coastguard Worker
540*f6dc9357SAndroid Build Coastguard Worker return true;
541*f6dc9357SAndroid Build Coastguard Worker }
542*f6dc9357SAndroid Build Coastguard Worker
GetCharacts() const543*f6dc9357SAndroid Build Coastguard Worker AString GetCharacts() const
544*f6dc9357SAndroid Build Coastguard Worker {
545*f6dc9357SAndroid Build Coastguard Worker AString s;
546*f6dc9357SAndroid Build Coastguard Worker if (Type == FV_FILETYPE_FFS_PAD)
547*f6dc9357SAndroid Build Coastguard Worker s += "PAD";
548*f6dc9357SAndroid Build Coastguard Worker else
549*f6dc9357SAndroid Build Coastguard Worker s += TYPE_TO_STRING(g_FileTypes, Type);
550*f6dc9357SAndroid Build Coastguard Worker AddSpaceAndString(s, FLAGS_TO_STRING(g_FFS_FILE_ATTRIBUTES, Attrib & 0xC7));
551*f6dc9357SAndroid Build Coastguard Worker /*
552*f6dc9357SAndroid Build Coastguard Worker int align = (Attrib >> 3) & 7;
553*f6dc9357SAndroid Build Coastguard Worker if (align != 0)
554*f6dc9357SAndroid Build Coastguard Worker {
555*f6dc9357SAndroid Build Coastguard Worker s += " Align:";
556*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32((UInt32)1 << g_Allignment[align]);
557*f6dc9357SAndroid Build Coastguard Worker }
558*f6dc9357SAndroid Build Coastguard Worker */
559*f6dc9357SAndroid Build Coastguard Worker return s;
560*f6dc9357SAndroid Build Coastguard Worker }
561*f6dc9357SAndroid Build Coastguard Worker };
562*f6dc9357SAndroid Build Coastguard Worker
563*f6dc9357SAndroid Build Coastguard Worker #define G32(_offs_, dest) dest = Get32(p + (_offs_))
564*f6dc9357SAndroid Build Coastguard Worker #define G16(_offs_, dest) dest = Get16(p + (_offs_))
565*f6dc9357SAndroid Build Coastguard Worker
566*f6dc9357SAndroid Build Coastguard Worker struct CCapsuleHeader
567*f6dc9357SAndroid Build Coastguard Worker {
568*f6dc9357SAndroid Build Coastguard Worker UInt32 HeaderSize;
569*f6dc9357SAndroid Build Coastguard Worker UInt32 Flags;
570*f6dc9357SAndroid Build Coastguard Worker UInt32 CapsuleImageSize;
571*f6dc9357SAndroid Build Coastguard Worker UInt32 SequenceNumber;
572*f6dc9357SAndroid Build Coastguard Worker // Guid InstanceId;
573*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToSplitInformation;
574*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToCapsuleBody;
575*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToOemDefinedHeader;
576*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToAuthorInformation;
577*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToRevisionInformation;
578*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToShortDescription;
579*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToLongDescription;
580*f6dc9357SAndroid Build Coastguard Worker UInt32 OffsetToApplicableDevices;
581*f6dc9357SAndroid Build Coastguard Worker
ClearNArchive::NUefi::CCapsuleHeader582*f6dc9357SAndroid Build Coastguard Worker void Clear() { memset(this, 0, sizeof(*this)); }
583*f6dc9357SAndroid Build Coastguard Worker
ParseNArchive::NUefi::CCapsuleHeader584*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p)
585*f6dc9357SAndroid Build Coastguard Worker {
586*f6dc9357SAndroid Build Coastguard Worker Clear();
587*f6dc9357SAndroid Build Coastguard Worker G32(0x10, HeaderSize);
588*f6dc9357SAndroid Build Coastguard Worker G32(0x14, Flags);
589*f6dc9357SAndroid Build Coastguard Worker G32(0x18, CapsuleImageSize);
590*f6dc9357SAndroid Build Coastguard Worker if (HeaderSize < 0x1C)
591*f6dc9357SAndroid Build Coastguard Worker return false;
592*f6dc9357SAndroid Build Coastguard Worker if (AreGuidsEq(p, k_Guids_Capsules[0]))
593*f6dc9357SAndroid Build Coastguard Worker {
594*f6dc9357SAndroid Build Coastguard Worker const unsigned kHeaderSize = 80;
595*f6dc9357SAndroid Build Coastguard Worker if (HeaderSize != kHeaderSize)
596*f6dc9357SAndroid Build Coastguard Worker return false;
597*f6dc9357SAndroid Build Coastguard Worker G32(0x1C, SequenceNumber);
598*f6dc9357SAndroid Build Coastguard Worker G32(0x30, OffsetToSplitInformation);
599*f6dc9357SAndroid Build Coastguard Worker G32(0x34, OffsetToCapsuleBody);
600*f6dc9357SAndroid Build Coastguard Worker G32(0x38, OffsetToOemDefinedHeader);
601*f6dc9357SAndroid Build Coastguard Worker G32(0x3C, OffsetToAuthorInformation);
602*f6dc9357SAndroid Build Coastguard Worker G32(0x40, OffsetToRevisionInformation);
603*f6dc9357SAndroid Build Coastguard Worker G32(0x44, OffsetToShortDescription);
604*f6dc9357SAndroid Build Coastguard Worker G32(0x48, OffsetToLongDescription);
605*f6dc9357SAndroid Build Coastguard Worker G32(0x4C, OffsetToApplicableDevices);
606*f6dc9357SAndroid Build Coastguard Worker return true;
607*f6dc9357SAndroid Build Coastguard Worker }
608*f6dc9357SAndroid Build Coastguard Worker else if (AreGuidsEq(p, k_Guids_Capsules[1]))
609*f6dc9357SAndroid Build Coastguard Worker {
610*f6dc9357SAndroid Build Coastguard Worker // capsule v2
611*f6dc9357SAndroid Build Coastguard Worker G16(0x1C, OffsetToCapsuleBody);
612*f6dc9357SAndroid Build Coastguard Worker G16(0x1E, OffsetToOemDefinedHeader);
613*f6dc9357SAndroid Build Coastguard Worker return true;
614*f6dc9357SAndroid Build Coastguard Worker }
615*f6dc9357SAndroid Build Coastguard Worker else if (AreGuidsEq(p, k_Guids_Capsules[2]))
616*f6dc9357SAndroid Build Coastguard Worker {
617*f6dc9357SAndroid Build Coastguard Worker OffsetToCapsuleBody = HeaderSize;
618*f6dc9357SAndroid Build Coastguard Worker return true;
619*f6dc9357SAndroid Build Coastguard Worker }
620*f6dc9357SAndroid Build Coastguard Worker else
621*f6dc9357SAndroid Build Coastguard Worker {
622*f6dc9357SAndroid Build Coastguard Worker // here we must check for another capsule types
623*f6dc9357SAndroid Build Coastguard Worker return false;
624*f6dc9357SAndroid Build Coastguard Worker }
625*f6dc9357SAndroid Build Coastguard Worker }
626*f6dc9357SAndroid Build Coastguard Worker };
627*f6dc9357SAndroid Build Coastguard Worker
628*f6dc9357SAndroid Build Coastguard Worker
629*f6dc9357SAndroid Build Coastguard Worker struct CItem
630*f6dc9357SAndroid Build Coastguard Worker {
631*f6dc9357SAndroid Build Coastguard Worker AString Name;
632*f6dc9357SAndroid Build Coastguard Worker AString Characts;
633*f6dc9357SAndroid Build Coastguard Worker int Parent;
634*f6dc9357SAndroid Build Coastguard Worker int Method;
635*f6dc9357SAndroid Build Coastguard Worker int NameIndex;
636*f6dc9357SAndroid Build Coastguard Worker unsigned NumChilds;
637*f6dc9357SAndroid Build Coastguard Worker bool IsDir;
638*f6dc9357SAndroid Build Coastguard Worker bool Skip;
639*f6dc9357SAndroid Build Coastguard Worker bool ThereAreSubDirs;
640*f6dc9357SAndroid Build Coastguard Worker bool ThereIsUniqueName;
641*f6dc9357SAndroid Build Coastguard Worker bool KeepName;
642*f6dc9357SAndroid Build Coastguard Worker
643*f6dc9357SAndroid Build Coastguard Worker unsigned BufIndex;
644*f6dc9357SAndroid Build Coastguard Worker UInt32 Offset;
645*f6dc9357SAndroid Build Coastguard Worker UInt32 Size;
646*f6dc9357SAndroid Build Coastguard Worker
CItemNArchive::NUefi::CItem647*f6dc9357SAndroid Build Coastguard Worker CItem(): Parent(-1), Method(-1), NameIndex(-1), NumChilds(0),
648*f6dc9357SAndroid Build Coastguard Worker IsDir(false), Skip(false), ThereAreSubDirs(false), ThereIsUniqueName(false), KeepName(true) {}
649*f6dc9357SAndroid Build Coastguard Worker void SetGuid(const Byte *guidName, bool full = false);
650*f6dc9357SAndroid Build Coastguard Worker AString GetName(int numChildsInParent) const;
651*f6dc9357SAndroid Build Coastguard Worker };
652*f6dc9357SAndroid Build Coastguard Worker
SetGuid(const Byte * guidName,bool full)653*f6dc9357SAndroid Build Coastguard Worker void CItem::SetGuid(const Byte *guidName, bool full)
654*f6dc9357SAndroid Build Coastguard Worker {
655*f6dc9357SAndroid Build Coastguard Worker ThereIsUniqueName = true;
656*f6dc9357SAndroid Build Coastguard Worker int index = FindGuid(guidName);
657*f6dc9357SAndroid Build Coastguard Worker if (index >= 0)
658*f6dc9357SAndroid Build Coastguard Worker Name = kGuidNames[(unsigned)index];
659*f6dc9357SAndroid Build Coastguard Worker else
660*f6dc9357SAndroid Build Coastguard Worker {
661*f6dc9357SAndroid Build Coastguard Worker Name.Empty();
662*f6dc9357SAndroid Build Coastguard Worker AddGuid(Name, guidName, full);
663*f6dc9357SAndroid Build Coastguard Worker }
664*f6dc9357SAndroid Build Coastguard Worker }
665*f6dc9357SAndroid Build Coastguard Worker
GetName(int numChildsInParent) const666*f6dc9357SAndroid Build Coastguard Worker AString CItem::GetName(int numChildsInParent) const
667*f6dc9357SAndroid Build Coastguard Worker {
668*f6dc9357SAndroid Build Coastguard Worker if (numChildsInParent <= 1 || NameIndex < 0)
669*f6dc9357SAndroid Build Coastguard Worker return Name;
670*f6dc9357SAndroid Build Coastguard Worker char sz[32];
671*f6dc9357SAndroid Build Coastguard Worker char sz2[32];
672*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString((unsigned)NameIndex, sz);
673*f6dc9357SAndroid Build Coastguard Worker ConvertUInt32ToString((unsigned)numChildsInParent - 1, sz2);
674*f6dc9357SAndroid Build Coastguard Worker const int numZeros = (int)strlen(sz2) - (int)strlen(sz);
675*f6dc9357SAndroid Build Coastguard Worker AString res;
676*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < numZeros; i++)
677*f6dc9357SAndroid Build Coastguard Worker res += '0';
678*f6dc9357SAndroid Build Coastguard Worker res += sz;
679*f6dc9357SAndroid Build Coastguard Worker res.Add_Dot();
680*f6dc9357SAndroid Build Coastguard Worker res += Name;
681*f6dc9357SAndroid Build Coastguard Worker return res;
682*f6dc9357SAndroid Build Coastguard Worker }
683*f6dc9357SAndroid Build Coastguard Worker
684*f6dc9357SAndroid Build Coastguard Worker struct CItem2
685*f6dc9357SAndroid Build Coastguard Worker {
686*f6dc9357SAndroid Build Coastguard Worker AString Name;
687*f6dc9357SAndroid Build Coastguard Worker AString Characts;
688*f6dc9357SAndroid Build Coastguard Worker unsigned MainIndex;
689*f6dc9357SAndroid Build Coastguard Worker int Parent;
690*f6dc9357SAndroid Build Coastguard Worker
CItem2NArchive::NUefi::CItem2691*f6dc9357SAndroid Build Coastguard Worker CItem2(): Parent(-1) {}
692*f6dc9357SAndroid Build Coastguard Worker };
693*f6dc9357SAndroid Build Coastguard Worker
694*f6dc9357SAndroid Build Coastguard Worker
695*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
696*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream
697*f6dc9357SAndroid Build Coastguard Worker )
698*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CItem> _items;
699*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CItem2> _items2;
700*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CByteBuffer> _bufs;
701*f6dc9357SAndroid Build Coastguard Worker UString _comment;
702*f6dc9357SAndroid Build Coastguard Worker UInt32 _methodsMask;
703*f6dc9357SAndroid Build Coastguard Worker bool _capsuleMode;
704*f6dc9357SAndroid Build Coastguard Worker bool _headersError;
705*f6dc9357SAndroid Build Coastguard Worker
706*f6dc9357SAndroid Build Coastguard Worker size_t _totalBufsSize;
707*f6dc9357SAndroid Build Coastguard Worker CCapsuleHeader _h;
708*f6dc9357SAndroid Build Coastguard Worker UInt64 _phySize;
709*f6dc9357SAndroid Build Coastguard Worker
710*f6dc9357SAndroid Build Coastguard Worker void AddCommentString(const char *name, UInt32 pos);
711*f6dc9357SAndroid Build Coastguard Worker unsigned AddItem(const CItem &item);
712*f6dc9357SAndroid Build Coastguard Worker unsigned AddFileItemWithIndex(CItem &item);
713*f6dc9357SAndroid Build Coastguard Worker unsigned AddDirItem(CItem &item);
714*f6dc9357SAndroid Build Coastguard Worker unsigned AddBuf(size_t size);
715*f6dc9357SAndroid Build Coastguard Worker
716*f6dc9357SAndroid Build Coastguard Worker HRESULT DecodeLzma(const Byte *data, size_t inputSize);
717*f6dc9357SAndroid Build Coastguard Worker
718*f6dc9357SAndroid Build Coastguard Worker HRESULT ParseSections(unsigned bufIndex, UInt32 pos,
719*f6dc9357SAndroid Build Coastguard Worker UInt32 size,
720*f6dc9357SAndroid Build Coastguard Worker int parent, int method, unsigned level,
721*f6dc9357SAndroid Build Coastguard Worker bool &error);
722*f6dc9357SAndroid Build Coastguard Worker
723*f6dc9357SAndroid Build Coastguard Worker HRESULT ParseIntelMe(unsigned bufIndex, UInt32 posBase,
724*f6dc9357SAndroid Build Coastguard Worker UInt32 exactSize, UInt32 limitSize,
725*f6dc9357SAndroid Build Coastguard Worker int parent, int method, unsigned level);
726*f6dc9357SAndroid Build Coastguard Worker
727*f6dc9357SAndroid Build Coastguard Worker HRESULT ParseVolume(unsigned bufIndex, UInt32 posBase,
728*f6dc9357SAndroid Build Coastguard Worker UInt32 exactSize, UInt32 limitSize,
729*f6dc9357SAndroid Build Coastguard Worker int parent, int method, unsigned level);
730*f6dc9357SAndroid Build Coastguard Worker
731*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenCapsule(IInStream *stream);
732*f6dc9357SAndroid Build Coastguard Worker HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);
733*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);
734*f6dc9357SAndroid Build Coastguard Worker public:
735*f6dc9357SAndroid Build Coastguard Worker CHandler(bool capsuleMode): _capsuleMode(capsuleMode) {}
736*f6dc9357SAndroid Build Coastguard Worker };
737*f6dc9357SAndroid Build Coastguard Worker
738*f6dc9357SAndroid Build Coastguard Worker
739*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
740*f6dc9357SAndroid Build Coastguard Worker {
741*f6dc9357SAndroid Build Coastguard Worker kpidPath,
742*f6dc9357SAndroid Build Coastguard Worker kpidIsDir,
743*f6dc9357SAndroid Build Coastguard Worker kpidSize,
744*f6dc9357SAndroid Build Coastguard Worker // kpidOffset,
745*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
746*f6dc9357SAndroid Build Coastguard Worker kpidCharacts
747*f6dc9357SAndroid Build Coastguard Worker };
748*f6dc9357SAndroid Build Coastguard Worker
749*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] =
750*f6dc9357SAndroid Build Coastguard Worker {
751*f6dc9357SAndroid Build Coastguard Worker kpidComment,
752*f6dc9357SAndroid Build Coastguard Worker kpidMethod,
753*f6dc9357SAndroid Build Coastguard Worker kpidCharacts
754*f6dc9357SAndroid Build Coastguard Worker };
755*f6dc9357SAndroid Build Coastguard Worker
756*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
757*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps
758*f6dc9357SAndroid Build Coastguard Worker
759*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
760*f6dc9357SAndroid Build Coastguard Worker {
761*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
762*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CPropVariant prop;
763*f6dc9357SAndroid Build Coastguard Worker const CItem2 &item2 = _items2[index];
764*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[item2.MainIndex];
765*f6dc9357SAndroid Build Coastguard Worker switch (propID)
766*f6dc9357SAndroid Build Coastguard Worker {
767*f6dc9357SAndroid Build Coastguard Worker case kpidPath:
768*f6dc9357SAndroid Build Coastguard Worker {
769*f6dc9357SAndroid Build Coastguard Worker AString path (item2.Name);
770*f6dc9357SAndroid Build Coastguard Worker int cur = item2.Parent;
771*f6dc9357SAndroid Build Coastguard Worker while (cur >= 0)
772*f6dc9357SAndroid Build Coastguard Worker {
773*f6dc9357SAndroid Build Coastguard Worker const CItem2 &item3 = _items2[cur];
774*f6dc9357SAndroid Build Coastguard Worker path.InsertAtFront(CHAR_PATH_SEPARATOR);
775*f6dc9357SAndroid Build Coastguard Worker path.Insert(0, item3.Name);
776*f6dc9357SAndroid Build Coastguard Worker cur = item3.Parent;
777*f6dc9357SAndroid Build Coastguard Worker }
778*f6dc9357SAndroid Build Coastguard Worker prop = path;
779*f6dc9357SAndroid Build Coastguard Worker break;
780*f6dc9357SAndroid Build Coastguard Worker }
781*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir; break;
782*f6dc9357SAndroid Build Coastguard Worker case kpidMethod: if (item.Method >= 0) prop = g_Methods[(unsigned)item.Method]; break;
783*f6dc9357SAndroid Build Coastguard Worker case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break;
784*f6dc9357SAndroid Build Coastguard Worker case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break;
785*f6dc9357SAndroid Build Coastguard Worker // case kpidOffset: if (!item.IsDir) prop = item.Offset; break;
786*f6dc9357SAndroid Build Coastguard Worker }
787*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
788*f6dc9357SAndroid Build Coastguard Worker return S_OK;
789*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
790*f6dc9357SAndroid Build Coastguard Worker }
791*f6dc9357SAndroid Build Coastguard Worker
792*f6dc9357SAndroid Build Coastguard Worker void CHandler::AddCommentString(const char *name, UInt32 pos)
793*f6dc9357SAndroid Build Coastguard Worker {
794*f6dc9357SAndroid Build Coastguard Worker UString s;
795*f6dc9357SAndroid Build Coastguard Worker if (pos < _h.HeaderSize)
796*f6dc9357SAndroid Build Coastguard Worker return;
797*f6dc9357SAndroid Build Coastguard Worker if (pos >= _h.OffsetToCapsuleBody)
798*f6dc9357SAndroid Build Coastguard Worker return;
799*f6dc9357SAndroid Build Coastguard Worker UInt32 limit = (_h.OffsetToCapsuleBody - pos) & ~(UInt32)1;
800*f6dc9357SAndroid Build Coastguard Worker const Byte *buf = _bufs[0] + pos;
801*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0;;)
802*f6dc9357SAndroid Build Coastguard Worker {
803*f6dc9357SAndroid Build Coastguard Worker if (s.Len() > (1 << 16) || i >= limit)
804*f6dc9357SAndroid Build Coastguard Worker return;
805*f6dc9357SAndroid Build Coastguard Worker wchar_t c = Get16(buf + i);
806*f6dc9357SAndroid Build Coastguard Worker i += 2;
807*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
808*f6dc9357SAndroid Build Coastguard Worker {
809*f6dc9357SAndroid Build Coastguard Worker if (i >= limit)
810*f6dc9357SAndroid Build Coastguard Worker return;
811*f6dc9357SAndroid Build Coastguard Worker c = Get16(buf + i);
812*f6dc9357SAndroid Build Coastguard Worker i += 2;
813*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
814*f6dc9357SAndroid Build Coastguard Worker break;
815*f6dc9357SAndroid Build Coastguard Worker s.Add_LF();
816*f6dc9357SAndroid Build Coastguard Worker }
817*f6dc9357SAndroid Build Coastguard Worker s += c;
818*f6dc9357SAndroid Build Coastguard Worker }
819*f6dc9357SAndroid Build Coastguard Worker if (s.IsEmpty())
820*f6dc9357SAndroid Build Coastguard Worker return;
821*f6dc9357SAndroid Build Coastguard Worker _comment.Add_LF();
822*f6dc9357SAndroid Build Coastguard Worker _comment += name;
823*f6dc9357SAndroid Build Coastguard Worker _comment += ": ";
824*f6dc9357SAndroid Build Coastguard Worker _comment += s;
825*f6dc9357SAndroid Build Coastguard Worker }
826*f6dc9357SAndroid Build Coastguard Worker
827*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
828*f6dc9357SAndroid Build Coastguard Worker {
829*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
830*f6dc9357SAndroid Build Coastguard Worker NWindows::NCOM::CPropVariant prop;
831*f6dc9357SAndroid Build Coastguard Worker switch (propID)
832*f6dc9357SAndroid Build Coastguard Worker {
833*f6dc9357SAndroid Build Coastguard Worker case kpidMethod:
834*f6dc9357SAndroid Build Coastguard Worker {
835*f6dc9357SAndroid Build Coastguard Worker AString s;
836*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < 32; i++)
837*f6dc9357SAndroid Build Coastguard Worker if ((_methodsMask & ((UInt32)1 << i)) != 0)
838*f6dc9357SAndroid Build Coastguard Worker AddSpaceAndString(s, (AString)g_Methods[i]);
839*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty())
840*f6dc9357SAndroid Build Coastguard Worker prop = s;
841*f6dc9357SAndroid Build Coastguard Worker break;
842*f6dc9357SAndroid Build Coastguard Worker }
843*f6dc9357SAndroid Build Coastguard Worker case kpidComment: if (!_comment.IsEmpty()) prop = _comment; break;
844*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = (UInt64)_phySize; break;
845*f6dc9357SAndroid Build Coastguard Worker
846*f6dc9357SAndroid Build Coastguard Worker case kpidErrorFlags:
847*f6dc9357SAndroid Build Coastguard Worker {
848*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0;
849*f6dc9357SAndroid Build Coastguard Worker if (_headersError) v |= kpv_ErrorFlags_HeadersError;
850*f6dc9357SAndroid Build Coastguard Worker if (v != 0)
851*f6dc9357SAndroid Build Coastguard Worker prop = v;
852*f6dc9357SAndroid Build Coastguard Worker break;
853*f6dc9357SAndroid Build Coastguard Worker }
854*f6dc9357SAndroid Build Coastguard Worker }
855*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value);
856*f6dc9357SAndroid Build Coastguard Worker return S_OK;
857*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
858*f6dc9357SAndroid Build Coastguard Worker }
859*f6dc9357SAndroid Build Coastguard Worker
860*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
861*f6dc9357SAndroid Build Coastguard Worker static void PrintLevel(unsigned level)
862*f6dc9357SAndroid Build Coastguard Worker {
863*f6dc9357SAndroid Build Coastguard Worker PRF(printf("\n"));
864*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < level; i++)
865*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" "));
866*f6dc9357SAndroid Build Coastguard Worker }
867*f6dc9357SAndroid Build Coastguard Worker static void MyPrint(UInt32 posBase, UInt32 size, unsigned level, const char *name)
868*f6dc9357SAndroid Build Coastguard Worker {
869*f6dc9357SAndroid Build Coastguard Worker PrintLevel(level);
870*f6dc9357SAndroid Build Coastguard Worker PRF(printf("%s, pos = %6x, size = %6x", name, posBase, size));
871*f6dc9357SAndroid Build Coastguard Worker }
872*f6dc9357SAndroid Build Coastguard Worker #else
873*f6dc9357SAndroid Build Coastguard Worker #define PrintLevel(level)
874*f6dc9357SAndroid Build Coastguard Worker #define MyPrint(posBase, size, level, name)
875*f6dc9357SAndroid Build Coastguard Worker #endif
876*f6dc9357SAndroid Build Coastguard Worker
877*f6dc9357SAndroid Build Coastguard Worker
878*f6dc9357SAndroid Build Coastguard Worker
879*f6dc9357SAndroid Build Coastguard Worker unsigned CHandler::AddItem(const CItem &item)
880*f6dc9357SAndroid Build Coastguard Worker {
881*f6dc9357SAndroid Build Coastguard Worker if (_items.Size() >= kNumFilesMax)
882*f6dc9357SAndroid Build Coastguard Worker throw 2;
883*f6dc9357SAndroid Build Coastguard Worker return _items.Add(item);
884*f6dc9357SAndroid Build Coastguard Worker }
885*f6dc9357SAndroid Build Coastguard Worker
886*f6dc9357SAndroid Build Coastguard Worker unsigned CHandler::AddFileItemWithIndex(CItem &item)
887*f6dc9357SAndroid Build Coastguard Worker {
888*f6dc9357SAndroid Build Coastguard Worker unsigned nameIndex = _items.Size();
889*f6dc9357SAndroid Build Coastguard Worker if (item.Parent >= 0)
890*f6dc9357SAndroid Build Coastguard Worker nameIndex = _items[item.Parent].NumChilds++;
891*f6dc9357SAndroid Build Coastguard Worker item.NameIndex = (int)nameIndex;
892*f6dc9357SAndroid Build Coastguard Worker return AddItem(item);
893*f6dc9357SAndroid Build Coastguard Worker }
894*f6dc9357SAndroid Build Coastguard Worker
895*f6dc9357SAndroid Build Coastguard Worker unsigned CHandler::AddDirItem(CItem &item)
896*f6dc9357SAndroid Build Coastguard Worker {
897*f6dc9357SAndroid Build Coastguard Worker if (item.Parent >= 0)
898*f6dc9357SAndroid Build Coastguard Worker _items[item.Parent].ThereAreSubDirs = true;
899*f6dc9357SAndroid Build Coastguard Worker item.IsDir = true;
900*f6dc9357SAndroid Build Coastguard Worker item.Size = 0;
901*f6dc9357SAndroid Build Coastguard Worker return AddItem(item);
902*f6dc9357SAndroid Build Coastguard Worker }
903*f6dc9357SAndroid Build Coastguard Worker
904*f6dc9357SAndroid Build Coastguard Worker unsigned CHandler::AddBuf(size_t size)
905*f6dc9357SAndroid Build Coastguard Worker {
906*f6dc9357SAndroid Build Coastguard Worker if (size > kBufTotalSizeMax - _totalBufsSize)
907*f6dc9357SAndroid Build Coastguard Worker throw 1;
908*f6dc9357SAndroid Build Coastguard Worker _totalBufsSize += size;
909*f6dc9357SAndroid Build Coastguard Worker unsigned index = _bufs.Size();
910*f6dc9357SAndroid Build Coastguard Worker _bufs.AddNew().Alloc(size);
911*f6dc9357SAndroid Build Coastguard Worker return index;
912*f6dc9357SAndroid Build Coastguard Worker }
913*f6dc9357SAndroid Build Coastguard Worker
914*f6dc9357SAndroid Build Coastguard Worker
915*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::DecodeLzma(const Byte *data, size_t inputSize)
916*f6dc9357SAndroid Build Coastguard Worker {
917*f6dc9357SAndroid Build Coastguard Worker if (inputSize < 5 + 8)
918*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
919*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackSize = Get64(data + 5);
920*f6dc9357SAndroid Build Coastguard Worker if (unpackSize > ((UInt32)1 << 30))
921*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
922*f6dc9357SAndroid Build Coastguard Worker SizeT destLen = (SizeT)unpackSize;
923*f6dc9357SAndroid Build Coastguard Worker const unsigned newBufIndex = AddBuf((size_t)unpackSize);
924*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &buf = _bufs[newBufIndex];
925*f6dc9357SAndroid Build Coastguard Worker ELzmaStatus status;
926*f6dc9357SAndroid Build Coastguard Worker SizeT srcLen = inputSize - (5 + 8);
927*f6dc9357SAndroid Build Coastguard Worker const SizeT srcLen2 = srcLen;
928*f6dc9357SAndroid Build Coastguard Worker SRes res = LzmaDecode(buf, &destLen, data + 13, &srcLen,
929*f6dc9357SAndroid Build Coastguard Worker data, 5, LZMA_FINISH_END, &status, &g_Alloc);
930*f6dc9357SAndroid Build Coastguard Worker if (res != 0)
931*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
932*f6dc9357SAndroid Build Coastguard Worker if (srcLen != srcLen2 || destLen != unpackSize || (
933*f6dc9357SAndroid Build Coastguard Worker status != LZMA_STATUS_FINISHED_WITH_MARK &&
934*f6dc9357SAndroid Build Coastguard Worker status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
935*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
936*f6dc9357SAndroid Build Coastguard Worker return S_OK;
937*f6dc9357SAndroid Build Coastguard Worker }
938*f6dc9357SAndroid Build Coastguard Worker
939*f6dc9357SAndroid Build Coastguard Worker
940*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ParseSections(unsigned bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level, bool &error)
941*f6dc9357SAndroid Build Coastguard Worker {
942*f6dc9357SAndroid Build Coastguard Worker error = false;
943*f6dc9357SAndroid Build Coastguard Worker
944*f6dc9357SAndroid Build Coastguard Worker if (level > kLevelMax)
945*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
946*f6dc9357SAndroid Build Coastguard Worker MyPrint(posBase, size, level, "Sections");
947*f6dc9357SAndroid Build Coastguard Worker level++;
948*f6dc9357SAndroid Build Coastguard Worker const Byte *bufData = _bufs[bufIndex];
949*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = 0;
950*f6dc9357SAndroid Build Coastguard Worker for (;;)
951*f6dc9357SAndroid Build Coastguard Worker {
952*f6dc9357SAndroid Build Coastguard Worker if (size == pos)
953*f6dc9357SAndroid Build Coastguard Worker return S_OK;
954*f6dc9357SAndroid Build Coastguard Worker PrintLevel(level);
955*f6dc9357SAndroid Build Coastguard Worker PRF(printf("%s, abs = %6x, relat = %6x", "Sect", posBase + pos, pos));
956*f6dc9357SAndroid Build Coastguard Worker pos = (pos + 3) & ~(UInt32)3;
957*f6dc9357SAndroid Build Coastguard Worker if (pos > size)
958*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
959*f6dc9357SAndroid Build Coastguard Worker UInt32 rem = size - pos;
960*f6dc9357SAndroid Build Coastguard Worker if (rem == 0)
961*f6dc9357SAndroid Build Coastguard Worker return S_OK;
962*f6dc9357SAndroid Build Coastguard Worker if (rem < 4)
963*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
964*f6dc9357SAndroid Build Coastguard Worker
965*f6dc9357SAndroid Build Coastguard Worker const Byte *p = bufData + posBase + pos;
966*f6dc9357SAndroid Build Coastguard Worker
967*f6dc9357SAndroid Build Coastguard Worker const UInt32 sectSize = Get24(p);
968*f6dc9357SAndroid Build Coastguard Worker const Byte type = p[3];
969*f6dc9357SAndroid Build Coastguard Worker
970*f6dc9357SAndroid Build Coastguard Worker // PrintLevel(level);
971*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" type = %2x, sectSize = %6x", type, sectSize));
972*f6dc9357SAndroid Build Coastguard Worker
973*f6dc9357SAndroid Build Coastguard Worker if (sectSize > rem || sectSize < 4)
974*f6dc9357SAndroid Build Coastguard Worker {
975*f6dc9357SAndroid Build Coastguard Worker _headersError = true;
976*f6dc9357SAndroid Build Coastguard Worker error = true;
977*f6dc9357SAndroid Build Coastguard Worker return S_OK;
978*f6dc9357SAndroid Build Coastguard Worker // return S_FALSE;
979*f6dc9357SAndroid Build Coastguard Worker }
980*f6dc9357SAndroid Build Coastguard Worker
981*f6dc9357SAndroid Build Coastguard Worker CItem item;
982*f6dc9357SAndroid Build Coastguard Worker item.Method = method;
983*f6dc9357SAndroid Build Coastguard Worker item.BufIndex = bufIndex;
984*f6dc9357SAndroid Build Coastguard Worker item.Parent = parent;
985*f6dc9357SAndroid Build Coastguard Worker item.Offset = posBase + pos + 4;
986*f6dc9357SAndroid Build Coastguard Worker UInt32 sectDataSize = sectSize - 4;
987*f6dc9357SAndroid Build Coastguard Worker item.Size = sectDataSize;
988*f6dc9357SAndroid Build Coastguard Worker item.Name = TYPE_PAIR_TO_STRING(g_SECTION_TYPE, type);
989*f6dc9357SAndroid Build Coastguard Worker
990*f6dc9357SAndroid Build Coastguard Worker if (type == SECTION_COMPRESSION)
991*f6dc9357SAndroid Build Coastguard Worker {
992*f6dc9357SAndroid Build Coastguard Worker if (sectSize < 4 + 5)
993*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
994*f6dc9357SAndroid Build Coastguard Worker const UInt32 uncompressedSize = Get32(p + 4);
995*f6dc9357SAndroid Build Coastguard Worker const Byte compressionType = p[8];
996*f6dc9357SAndroid Build Coastguard Worker
997*f6dc9357SAndroid Build Coastguard Worker UInt32 newSectSize = sectSize - 9;
998*f6dc9357SAndroid Build Coastguard Worker UInt32 newOffset = posBase + pos + 9;
999*f6dc9357SAndroid Build Coastguard Worker const Byte *pStart = p + 9;
1000*f6dc9357SAndroid Build Coastguard Worker
1001*f6dc9357SAndroid Build Coastguard Worker item.KeepName = false;
1002*f6dc9357SAndroid Build Coastguard Worker if (compressionType > 2)
1003*f6dc9357SAndroid Build Coastguard Worker {
1004*f6dc9357SAndroid Build Coastguard Worker // AddFileItemWithIndex(item);
1005*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1006*f6dc9357SAndroid Build Coastguard Worker }
1007*f6dc9357SAndroid Build Coastguard Worker else
1008*f6dc9357SAndroid Build Coastguard Worker {
1009*f6dc9357SAndroid Build Coastguard Worker item.Name = g_Methods[compressionType];
1010*f6dc9357SAndroid Build Coastguard Worker // int parent = AddDirItem(item);
1011*f6dc9357SAndroid Build Coastguard Worker if (compressionType == COMPRESSION_TYPE_NONE)
1012*f6dc9357SAndroid Build Coastguard Worker {
1013*f6dc9357SAndroid Build Coastguard Worker bool error2;
1014*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level, error2))
1015*f6dc9357SAndroid Build Coastguard Worker }
1016*f6dc9357SAndroid Build Coastguard Worker else if (compressionType == COMPRESSION_TYPE_LZH)
1017*f6dc9357SAndroid Build Coastguard Worker {
1018*f6dc9357SAndroid Build Coastguard Worker const unsigned newBufIndex = AddBuf(uncompressedSize);
1019*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &buf = _bufs[newBufIndex];
1020*f6dc9357SAndroid Build Coastguard Worker CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;
1021*f6dc9357SAndroid Build Coastguard Worker lzhDecoder.Create_if_Empty();
1022*f6dc9357SAndroid Build Coastguard Worker {
1023*f6dc9357SAndroid Build Coastguard Worker const Byte *src = pStart;
1024*f6dc9357SAndroid Build Coastguard Worker if (newSectSize < 8)
1025*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1026*f6dc9357SAndroid Build Coastguard Worker UInt32 packSize = Get32(src);
1027*f6dc9357SAndroid Build Coastguard Worker const UInt32 unpackSize = Get32(src + 4);
1028*f6dc9357SAndroid Build Coastguard Worker
1029*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" LZH packSize = %6x, unpackSize = %6x", packSize, unpackSize));
1030*f6dc9357SAndroid Build Coastguard Worker
1031*f6dc9357SAndroid Build Coastguard Worker if (uncompressedSize != unpackSize || newSectSize - 8 != packSize)
1032*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1033*f6dc9357SAndroid Build Coastguard Worker if (packSize < 1)
1034*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1035*f6dc9357SAndroid Build Coastguard Worker packSize--;
1036*f6dc9357SAndroid Build Coastguard Worker src += 8;
1037*f6dc9357SAndroid Build Coastguard Worker if (src[packSize] != 0)
1038*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1039*f6dc9357SAndroid Build Coastguard Worker
1040*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<IInStream, CBufInStream> inStream;
1041*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;
1042*f6dc9357SAndroid Build Coastguard Worker // const UInt64 uncompressedSize64 = uncompressedSize;
1043*f6dc9357SAndroid Build Coastguard Worker // lzhDecoder->FinishMode = true;
1044*f6dc9357SAndroid Build Coastguard Worker /*
1045*f6dc9357SAndroid Build Coastguard Worker EFI 1.1 probably used LZH with small dictionary and (pbit = 4). It was named "Efi compression".
1046*f6dc9357SAndroid Build Coastguard Worker New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary.
1047*f6dc9357SAndroid Build Coastguard Worker But maybe LZH decoder in UEFI decoder supports larger than (1 << 19) dictionary.
1048*f6dc9357SAndroid Build Coastguard Worker We check both LZH versions: Tiano and then Efi.
1049*f6dc9357SAndroid Build Coastguard Worker */
1050*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_FALSE;
1051*f6dc9357SAndroid Build Coastguard Worker for (unsigned m = 0 ; m < 2; m++)
1052*f6dc9357SAndroid Build Coastguard Worker {
1053*f6dc9357SAndroid Build Coastguard Worker inStream->Init(src, packSize);
1054*f6dc9357SAndroid Build Coastguard Worker outStream->Init(buf, uncompressedSize);
1055*f6dc9357SAndroid Build Coastguard Worker lzhDecoder->SetDictSize(m == 0 ? ((UInt32)1 << 19) : ((UInt32)1 << 14));
1056*f6dc9357SAndroid Build Coastguard Worker res = lzhDecoder->Code(inStream, outStream, uncompressedSize, NULL);
1057*f6dc9357SAndroid Build Coastguard Worker if (res == S_OK)
1058*f6dc9357SAndroid Build Coastguard Worker break;
1059*f6dc9357SAndroid Build Coastguard Worker }
1060*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
1061*f6dc9357SAndroid Build Coastguard Worker }
1062*f6dc9357SAndroid Build Coastguard Worker bool error2;
1063*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level, error2))
1064*f6dc9357SAndroid Build Coastguard Worker }
1065*f6dc9357SAndroid Build Coastguard Worker else
1066*f6dc9357SAndroid Build Coastguard Worker {
1067*f6dc9357SAndroid Build Coastguard Worker if (newSectSize < 4 + 5 + 8)
1068*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1069*f6dc9357SAndroid Build Coastguard Worker unsigned addSize = 4;
1070*f6dc9357SAndroid Build Coastguard Worker if (pStart[0] == 0x5d && pStart[1] == 0 && pStart[2] == 0 && pStart[3] == 0x80 && pStart[4] == 0)
1071*f6dc9357SAndroid Build Coastguard Worker {
1072*f6dc9357SAndroid Build Coastguard Worker addSize = 0;
1073*f6dc9357SAndroid Build Coastguard Worker // some archives have such header
1074*f6dc9357SAndroid Build Coastguard Worker }
1075*f6dc9357SAndroid Build Coastguard Worker else
1076*f6dc9357SAndroid Build Coastguard Worker {
1077*f6dc9357SAndroid Build Coastguard Worker // normal BIOS contains uncompressed size here
1078*f6dc9357SAndroid Build Coastguard Worker // UInt32 uncompressedSize2 = Get24(pStart);
1079*f6dc9357SAndroid Build Coastguard Worker // Byte firstSectType = p[9 + 3];
1080*f6dc9357SAndroid Build Coastguard Worker // firstSectType can be 0 in some archives
1081*f6dc9357SAndroid Build Coastguard Worker }
1082*f6dc9357SAndroid Build Coastguard Worker pStart += addSize;
1083*f6dc9357SAndroid Build Coastguard Worker
1084*f6dc9357SAndroid Build Coastguard Worker RINOK(DecodeLzma(pStart, newSectSize - addSize))
1085*f6dc9357SAndroid Build Coastguard Worker const size_t lzmaUncompressedSize = _bufs.Back().Size();
1086*f6dc9357SAndroid Build Coastguard Worker // if (lzmaUncompressedSize != uncompressedSize)
1087*f6dc9357SAndroid Build Coastguard Worker if (lzmaUncompressedSize < uncompressedSize)
1088*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1089*f6dc9357SAndroid Build Coastguard Worker bool error2;
1090*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseSections(_bufs.Size() - 1, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level, error2))
1091*f6dc9357SAndroid Build Coastguard Worker }
1092*f6dc9357SAndroid Build Coastguard Worker _methodsMask |= (1 << compressionType);
1093*f6dc9357SAndroid Build Coastguard Worker }
1094*f6dc9357SAndroid Build Coastguard Worker }
1095*f6dc9357SAndroid Build Coastguard Worker else if (type == SECTION_GUID_DEFINED)
1096*f6dc9357SAndroid Build Coastguard Worker {
1097*f6dc9357SAndroid Build Coastguard Worker const unsigned kHeaderSize = 4 + kGuidSize + 4;
1098*f6dc9357SAndroid Build Coastguard Worker if (sectSize < kHeaderSize)
1099*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1100*f6dc9357SAndroid Build Coastguard Worker item.SetGuid(p + 4);
1101*f6dc9357SAndroid Build Coastguard Worker const UInt32 dataOffset = Get16(p + 4 + kGuidSize);
1102*f6dc9357SAndroid Build Coastguard Worker const UInt32 attrib = Get16(p + 4 + kGuidSize + 2);
1103*f6dc9357SAndroid Build Coastguard Worker if (dataOffset > sectSize || dataOffset < kHeaderSize)
1104*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1105*f6dc9357SAndroid Build Coastguard Worker UInt32 newSectSize = sectSize - dataOffset;
1106*f6dc9357SAndroid Build Coastguard Worker item.Size = newSectSize;
1107*f6dc9357SAndroid Build Coastguard Worker UInt32 newOffset = posBase + pos + dataOffset;
1108*f6dc9357SAndroid Build Coastguard Worker item.Offset = newOffset;
1109*f6dc9357SAndroid Build Coastguard Worker const UInt32 propsSize = dataOffset - kHeaderSize;
1110*f6dc9357SAndroid Build Coastguard Worker AddSpaceAndString(item.Characts, FLAGS_TO_STRING(g_GUIDED_SECTION_ATTRIBUTES, attrib));
1111*f6dc9357SAndroid Build Coastguard Worker
1112*f6dc9357SAndroid Build Coastguard Worker bool needDir = true;
1113*f6dc9357SAndroid Build Coastguard Worker unsigned newBufIndex = bufIndex;
1114*f6dc9357SAndroid Build Coastguard Worker int newMethod = method;
1115*f6dc9357SAndroid Build Coastguard Worker
1116*f6dc9357SAndroid Build Coastguard Worker if (AreGuidsEq(p + 0x4, k_Guid_LZMA_COMPRESSED))
1117*f6dc9357SAndroid Build Coastguard Worker {
1118*f6dc9357SAndroid Build Coastguard Worker // item.Name = "guid.lzma";
1119*f6dc9357SAndroid Build Coastguard Worker // AddItem(item);
1120*f6dc9357SAndroid Build Coastguard Worker const Byte *pStart = bufData + newOffset;
1121*f6dc9357SAndroid Build Coastguard Worker // do we need correct pStart here for lzma steram offset?
1122*f6dc9357SAndroid Build Coastguard Worker RINOK(DecodeLzma(pStart, newSectSize))
1123*f6dc9357SAndroid Build Coastguard Worker _methodsMask |= (1 << COMPRESSION_TYPE_LZMA);
1124*f6dc9357SAndroid Build Coastguard Worker newBufIndex = _bufs.Size() - 1;
1125*f6dc9357SAndroid Build Coastguard Worker newOffset = 0;
1126*f6dc9357SAndroid Build Coastguard Worker newSectSize = (UInt32)_bufs.Back().Size();
1127*f6dc9357SAndroid Build Coastguard Worker newMethod = COMPRESSION_TYPE_LZMA;
1128*f6dc9357SAndroid Build Coastguard Worker }
1129*f6dc9357SAndroid Build Coastguard Worker else if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4)
1130*f6dc9357SAndroid Build Coastguard Worker {
1131*f6dc9357SAndroid Build Coastguard Worker needDir = false;
1132*f6dc9357SAndroid Build Coastguard Worker item.KeepName = false;
1133*f6dc9357SAndroid Build Coastguard Worker if (CrcCalc(bufData + newOffset, newSectSize) != Get32(p + kHeaderSize))
1134*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1135*f6dc9357SAndroid Build Coastguard Worker }
1136*f6dc9357SAndroid Build Coastguard Worker else
1137*f6dc9357SAndroid Build Coastguard Worker {
1138*f6dc9357SAndroid Build Coastguard Worker if (propsSize != 0)
1139*f6dc9357SAndroid Build Coastguard Worker {
1140*f6dc9357SAndroid Build Coastguard Worker CItem item2 = item;
1141*f6dc9357SAndroid Build Coastguard Worker item2.Name += ".prop";
1142*f6dc9357SAndroid Build Coastguard Worker item2.Size = propsSize;
1143*f6dc9357SAndroid Build Coastguard Worker item2.Offset = posBase + pos + kHeaderSize;
1144*f6dc9357SAndroid Build Coastguard Worker AddItem(item2);
1145*f6dc9357SAndroid Build Coastguard Worker }
1146*f6dc9357SAndroid Build Coastguard Worker }
1147*f6dc9357SAndroid Build Coastguard Worker
1148*f6dc9357SAndroid Build Coastguard Worker int newParent = parent;
1149*f6dc9357SAndroid Build Coastguard Worker if (needDir)
1150*f6dc9357SAndroid Build Coastguard Worker newParent = (int)AddDirItem(item);
1151*f6dc9357SAndroid Build Coastguard Worker bool error2;
1152*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseSections(newBufIndex, newOffset, newSectSize, newParent, newMethod, level, error2))
1153*f6dc9357SAndroid Build Coastguard Worker }
1154*f6dc9357SAndroid Build Coastguard Worker else if (type == SECTION_FIRMWARE_VOLUME_IMAGE)
1155*f6dc9357SAndroid Build Coastguard Worker {
1156*f6dc9357SAndroid Build Coastguard Worker item.KeepName = false;
1157*f6dc9357SAndroid Build Coastguard Worker const int newParent = (int)AddDirItem(item);
1158*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseVolume(bufIndex, posBase + pos + 4,
1159*f6dc9357SAndroid Build Coastguard Worker sectSize - 4,
1160*f6dc9357SAndroid Build Coastguard Worker sectSize - 4,
1161*f6dc9357SAndroid Build Coastguard Worker newParent, method, level))
1162*f6dc9357SAndroid Build Coastguard Worker }
1163*f6dc9357SAndroid Build Coastguard Worker else
1164*f6dc9357SAndroid Build Coastguard Worker {
1165*f6dc9357SAndroid Build Coastguard Worker bool needAdd = true;
1166*f6dc9357SAndroid Build Coastguard Worker switch (type)
1167*f6dc9357SAndroid Build Coastguard Worker {
1168*f6dc9357SAndroid Build Coastguard Worker case SECTION_RAW:
1169*f6dc9357SAndroid Build Coastguard Worker {
1170*f6dc9357SAndroid Build Coastguard Worker const UInt32 kInsydeOffset = 12;
1171*f6dc9357SAndroid Build Coastguard Worker if (sectDataSize >= kFvHeaderSize + kInsydeOffset)
1172*f6dc9357SAndroid Build Coastguard Worker {
1173*f6dc9357SAndroid Build Coastguard Worker if (IsFfs(p + 4 + kInsydeOffset) &&
1174*f6dc9357SAndroid Build Coastguard Worker sectDataSize - kInsydeOffset == Get64(p + 4 + kInsydeOffset + 0x20))
1175*f6dc9357SAndroid Build Coastguard Worker {
1176*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
1177*f6dc9357SAndroid Build Coastguard Worker item.Name = "vol";
1178*f6dc9357SAndroid Build Coastguard Worker const unsigned newParent = AddDirItem(item);
1179*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseVolume(bufIndex, posBase + pos + 4 + kInsydeOffset,
1180*f6dc9357SAndroid Build Coastguard Worker sectDataSize - kInsydeOffset,
1181*f6dc9357SAndroid Build Coastguard Worker sectDataSize - kInsydeOffset,
1182*f6dc9357SAndroid Build Coastguard Worker (int)newParent, method, level))
1183*f6dc9357SAndroid Build Coastguard Worker }
1184*f6dc9357SAndroid Build Coastguard Worker
1185*f6dc9357SAndroid Build Coastguard Worker if (needAdd)
1186*f6dc9357SAndroid Build Coastguard Worker {
1187*f6dc9357SAndroid Build Coastguard Worker const char *ext = FindExt(p + 4, sectDataSize);
1188*f6dc9357SAndroid Build Coastguard Worker if (ext)
1189*f6dc9357SAndroid Build Coastguard Worker item.Name = ext;
1190*f6dc9357SAndroid Build Coastguard Worker }
1191*f6dc9357SAndroid Build Coastguard Worker }
1192*f6dc9357SAndroid Build Coastguard Worker break;
1193*f6dc9357SAndroid Build Coastguard Worker }
1194*f6dc9357SAndroid Build Coastguard Worker case SECTION_DXE_DEPEX:
1195*f6dc9357SAndroid Build Coastguard Worker case SECTION_PEI_DEPEX:
1196*f6dc9357SAndroid Build Coastguard Worker {
1197*f6dc9357SAndroid Build Coastguard Worker AString s;
1198*f6dc9357SAndroid Build Coastguard Worker if (ParseDepedencyExpression(p + 4, sectDataSize, s))
1199*f6dc9357SAndroid Build Coastguard Worker {
1200*f6dc9357SAndroid Build Coastguard Worker if (s.Len() < (1 << 9))
1201*f6dc9357SAndroid Build Coastguard Worker {
1202*f6dc9357SAndroid Build Coastguard Worker s.InsertAtFront('[');
1203*f6dc9357SAndroid Build Coastguard Worker s += ']';
1204*f6dc9357SAndroid Build Coastguard Worker AddSpaceAndString(_items[item.Parent].Characts, s);
1205*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
1206*f6dc9357SAndroid Build Coastguard Worker }
1207*f6dc9357SAndroid Build Coastguard Worker else
1208*f6dc9357SAndroid Build Coastguard Worker {
1209*f6dc9357SAndroid Build Coastguard Worker item.BufIndex = AddBuf(s.Len());
1210*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &buf0 = _bufs[item.BufIndex];
1211*f6dc9357SAndroid Build Coastguard Worker if (s.Len() != 0)
1212*f6dc9357SAndroid Build Coastguard Worker memcpy(buf0, s, s.Len());
1213*f6dc9357SAndroid Build Coastguard Worker item.Offset = 0;
1214*f6dc9357SAndroid Build Coastguard Worker item.Size = s.Len();
1215*f6dc9357SAndroid Build Coastguard Worker }
1216*f6dc9357SAndroid Build Coastguard Worker }
1217*f6dc9357SAndroid Build Coastguard Worker break;
1218*f6dc9357SAndroid Build Coastguard Worker }
1219*f6dc9357SAndroid Build Coastguard Worker case SECTION_VERSION:
1220*f6dc9357SAndroid Build Coastguard Worker {
1221*f6dc9357SAndroid Build Coastguard Worker if (sectDataSize > 2)
1222*f6dc9357SAndroid Build Coastguard Worker {
1223*f6dc9357SAndroid Build Coastguard Worker AString s;
1224*f6dc9357SAndroid Build Coastguard Worker if (ParseUtf16zString2(p + 6, sectDataSize - 2, s))
1225*f6dc9357SAndroid Build Coastguard Worker {
1226*f6dc9357SAndroid Build Coastguard Worker AString s2 ("ver:");
1227*f6dc9357SAndroid Build Coastguard Worker s2.Add_UInt32(Get16(p + 4));
1228*f6dc9357SAndroid Build Coastguard Worker s2.Add_Space();
1229*f6dc9357SAndroid Build Coastguard Worker s2 += s;
1230*f6dc9357SAndroid Build Coastguard Worker AddSpaceAndString(_items[item.Parent].Characts, s2);
1231*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
1232*f6dc9357SAndroid Build Coastguard Worker }
1233*f6dc9357SAndroid Build Coastguard Worker }
1234*f6dc9357SAndroid Build Coastguard Worker break;
1235*f6dc9357SAndroid Build Coastguard Worker }
1236*f6dc9357SAndroid Build Coastguard Worker case SECTION_USER_INTERFACE:
1237*f6dc9357SAndroid Build Coastguard Worker {
1238*f6dc9357SAndroid Build Coastguard Worker AString s;
1239*f6dc9357SAndroid Build Coastguard Worker if (ParseUtf16zString2(p + 4, sectDataSize, s))
1240*f6dc9357SAndroid Build Coastguard Worker {
1241*f6dc9357SAndroid Build Coastguard Worker _items[parent].Name = s;
1242*f6dc9357SAndroid Build Coastguard Worker needAdd = false;
1243*f6dc9357SAndroid Build Coastguard Worker }
1244*f6dc9357SAndroid Build Coastguard Worker break;
1245*f6dc9357SAndroid Build Coastguard Worker }
1246*f6dc9357SAndroid Build Coastguard Worker case SECTION_FREEFORM_SUBTYPE_GUID:
1247*f6dc9357SAndroid Build Coastguard Worker {
1248*f6dc9357SAndroid Build Coastguard Worker if (sectDataSize >= kGuidSize)
1249*f6dc9357SAndroid Build Coastguard Worker {
1250*f6dc9357SAndroid Build Coastguard Worker item.SetGuid(p + 4);
1251*f6dc9357SAndroid Build Coastguard Worker item.Size = sectDataSize - kGuidSize;
1252*f6dc9357SAndroid Build Coastguard Worker item.Offset = posBase + pos + 4 + kGuidSize;
1253*f6dc9357SAndroid Build Coastguard Worker }
1254*f6dc9357SAndroid Build Coastguard Worker break;
1255*f6dc9357SAndroid Build Coastguard Worker }
1256*f6dc9357SAndroid Build Coastguard Worker }
1257*f6dc9357SAndroid Build Coastguard Worker
1258*f6dc9357SAndroid Build Coastguard Worker if (needAdd)
1259*f6dc9357SAndroid Build Coastguard Worker AddFileItemWithIndex(item);
1260*f6dc9357SAndroid Build Coastguard Worker }
1261*f6dc9357SAndroid Build Coastguard Worker
1262*f6dc9357SAndroid Build Coastguard Worker pos += sectSize;
1263*f6dc9357SAndroid Build Coastguard Worker }
1264*f6dc9357SAndroid Build Coastguard Worker }
1265*f6dc9357SAndroid Build Coastguard Worker
1266*f6dc9357SAndroid Build Coastguard Worker static UInt32 Count_FF_Bytes(const Byte *p, UInt32 size)
1267*f6dc9357SAndroid Build Coastguard Worker {
1268*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
1269*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < size && p[i] == 0xFF; i++);
1270*f6dc9357SAndroid Build Coastguard Worker return i;
1271*f6dc9357SAndroid Build Coastguard Worker }
1272*f6dc9357SAndroid Build Coastguard Worker
1273*f6dc9357SAndroid Build Coastguard Worker static bool Is_FF_Stream(const Byte *p, UInt32 size)
1274*f6dc9357SAndroid Build Coastguard Worker {
1275*f6dc9357SAndroid Build Coastguard Worker return (Count_FF_Bytes(p, size) == size);
1276*f6dc9357SAndroid Build Coastguard Worker }
1277*f6dc9357SAndroid Build Coastguard Worker
1278*f6dc9357SAndroid Build Coastguard Worker struct CVolFfsHeader
1279*f6dc9357SAndroid Build Coastguard Worker {
1280*f6dc9357SAndroid Build Coastguard Worker UInt32 HeaderLen;
1281*f6dc9357SAndroid Build Coastguard Worker UInt64 VolSize;
1282*f6dc9357SAndroid Build Coastguard Worker
1283*f6dc9357SAndroid Build Coastguard Worker bool Parse(const Byte *p);
1284*f6dc9357SAndroid Build Coastguard Worker };
1285*f6dc9357SAndroid Build Coastguard Worker
1286*f6dc9357SAndroid Build Coastguard Worker bool CVolFfsHeader::Parse(const Byte *p)
1287*f6dc9357SAndroid Build Coastguard Worker {
1288*f6dc9357SAndroid Build Coastguard Worker if (Get32(p + 0x28) != kFvSignature)
1289*f6dc9357SAndroid Build Coastguard Worker return false;
1290*f6dc9357SAndroid Build Coastguard Worker
1291*f6dc9357SAndroid Build Coastguard Worker UInt32 attribs = Get32(p + 0x2C);
1292*f6dc9357SAndroid Build Coastguard Worker if ((attribs & FVB_ERASE_POLARITY) == 0)
1293*f6dc9357SAndroid Build Coastguard Worker return false;
1294*f6dc9357SAndroid Build Coastguard Worker VolSize = Get64(p + 0x20);
1295*f6dc9357SAndroid Build Coastguard Worker HeaderLen = Get16(p + 0x30);
1296*f6dc9357SAndroid Build Coastguard Worker if (HeaderLen < kFvHeaderSize || (HeaderLen & 0x7) != 0 || VolSize < HeaderLen)
1297*f6dc9357SAndroid Build Coastguard Worker return false;
1298*f6dc9357SAndroid Build Coastguard Worker return true;
1299*f6dc9357SAndroid Build Coastguard Worker }
1300*f6dc9357SAndroid Build Coastguard Worker
1301*f6dc9357SAndroid Build Coastguard Worker
1302*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ParseVolume(
1303*f6dc9357SAndroid Build Coastguard Worker unsigned bufIndex, UInt32 posBase,
1304*f6dc9357SAndroid Build Coastguard Worker UInt32 exactSize, UInt32 limitSize,
1305*f6dc9357SAndroid Build Coastguard Worker int parent, int method, unsigned level)
1306*f6dc9357SAndroid Build Coastguard Worker {
1307*f6dc9357SAndroid Build Coastguard Worker if (level > kLevelMax)
1308*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1309*f6dc9357SAndroid Build Coastguard Worker MyPrint(posBase, exactSize, level, "Volume");
1310*f6dc9357SAndroid Build Coastguard Worker level++;
1311*f6dc9357SAndroid Build Coastguard Worker if (exactSize < kFvHeaderSize)
1312*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1313*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _bufs[bufIndex] + posBase;
1314*f6dc9357SAndroid Build Coastguard Worker // first 16 bytes must be zeros, but they are not zeros sometimes.
1315*f6dc9357SAndroid Build Coastguard Worker if (!IsFfs(p))
1316*f6dc9357SAndroid Build Coastguard Worker {
1317*f6dc9357SAndroid Build Coastguard Worker CItem item;
1318*f6dc9357SAndroid Build Coastguard Worker item.Method = method;
1319*f6dc9357SAndroid Build Coastguard Worker item.BufIndex = bufIndex;
1320*f6dc9357SAndroid Build Coastguard Worker item.Parent = parent;
1321*f6dc9357SAndroid Build Coastguard Worker item.Offset = posBase;
1322*f6dc9357SAndroid Build Coastguard Worker item.Size = exactSize;
1323*f6dc9357SAndroid Build Coastguard Worker if (!Is_FF_Stream(p + kFfsGuidOffset, 16))
1324*f6dc9357SAndroid Build Coastguard Worker item.SetGuid(p + kFfsGuidOffset);
1325*f6dc9357SAndroid Build Coastguard Worker // if (item.Name.IsEmpty())
1326*f6dc9357SAndroid Build Coastguard Worker item.Name += "[VOL]";
1327*f6dc9357SAndroid Build Coastguard Worker AddItem(item);
1328*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1329*f6dc9357SAndroid Build Coastguard Worker }
1330*f6dc9357SAndroid Build Coastguard Worker
1331*f6dc9357SAndroid Build Coastguard Worker CVolFfsHeader ffsHeader;
1332*f6dc9357SAndroid Build Coastguard Worker if (!ffsHeader.Parse(p))
1333*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1334*f6dc9357SAndroid Build Coastguard Worker // if (parent >= 0) AddSpaceAndString(_items[parent].Characts, FLAGS_TO_STRING(g_FV_Attribs, attribs));
1335*f6dc9357SAndroid Build Coastguard Worker
1336*f6dc9357SAndroid Build Coastguard Worker // VolSize > exactSize (fh.Size) for some UEFI archives (is it correct UEFI?)
1337*f6dc9357SAndroid Build Coastguard Worker // so we check VolSize for limitSize instead.
1338*f6dc9357SAndroid Build Coastguard Worker
1339*f6dc9357SAndroid Build Coastguard Worker if (ffsHeader.HeaderLen > limitSize || ffsHeader.VolSize > limitSize)
1340*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1341*f6dc9357SAndroid Build Coastguard Worker
1342*f6dc9357SAndroid Build Coastguard Worker {
1343*f6dc9357SAndroid Build Coastguard Worker UInt32 checkCalc = 0;
1344*f6dc9357SAndroid Build Coastguard Worker for (UInt32 i = 0; i < ffsHeader.HeaderLen; i += 2)
1345*f6dc9357SAndroid Build Coastguard Worker checkCalc += Get16(p + i);
1346*f6dc9357SAndroid Build Coastguard Worker if ((checkCalc & 0xFFFF) != 0)
1347*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1348*f6dc9357SAndroid Build Coastguard Worker }
1349*f6dc9357SAndroid Build Coastguard Worker
1350*f6dc9357SAndroid Build Coastguard Worker // 3 reserved bytes are not zeros sometimes.
1351*f6dc9357SAndroid Build Coastguard Worker // UInt16 ExtHeaderOffset; // in new SPECIFICATION?
1352*f6dc9357SAndroid Build Coastguard Worker // Byte revision = p[0x37];
1353*f6dc9357SAndroid Build Coastguard Worker
1354*f6dc9357SAndroid Build Coastguard Worker UInt32 pos = kFvHeaderSize;
1355*f6dc9357SAndroid Build Coastguard Worker for (;;)
1356*f6dc9357SAndroid Build Coastguard Worker {
1357*f6dc9357SAndroid Build Coastguard Worker if (pos >= ffsHeader.HeaderLen)
1358*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1359*f6dc9357SAndroid Build Coastguard Worker UInt32 numBlocks = Get32(p + pos);
1360*f6dc9357SAndroid Build Coastguard Worker UInt32 length = Get32(p + pos + 4);
1361*f6dc9357SAndroid Build Coastguard Worker pos += 8;
1362*f6dc9357SAndroid Build Coastguard Worker if (numBlocks == 0 && length == 0)
1363*f6dc9357SAndroid Build Coastguard Worker break;
1364*f6dc9357SAndroid Build Coastguard Worker }
1365*f6dc9357SAndroid Build Coastguard Worker if (pos != ffsHeader.HeaderLen)
1366*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1367*f6dc9357SAndroid Build Coastguard Worker
1368*f6dc9357SAndroid Build Coastguard Worker CRecordVector<UInt32> guidsVector;
1369*f6dc9357SAndroid Build Coastguard Worker
1370*f6dc9357SAndroid Build Coastguard Worker for (;;)
1371*f6dc9357SAndroid Build Coastguard Worker {
1372*f6dc9357SAndroid Build Coastguard Worker UInt32 rem = (UInt32)ffsHeader.VolSize - pos;
1373*f6dc9357SAndroid Build Coastguard Worker if (rem < kFileHeaderSize)
1374*f6dc9357SAndroid Build Coastguard Worker break;
1375*f6dc9357SAndroid Build Coastguard Worker pos = (pos + 7) & ~7u;
1376*f6dc9357SAndroid Build Coastguard Worker rem = (UInt32)ffsHeader.VolSize - pos;
1377*f6dc9357SAndroid Build Coastguard Worker if (rem < kFileHeaderSize)
1378*f6dc9357SAndroid Build Coastguard Worker break;
1379*f6dc9357SAndroid Build Coastguard Worker
1380*f6dc9357SAndroid Build Coastguard Worker CItem item;
1381*f6dc9357SAndroid Build Coastguard Worker item.Method = method;
1382*f6dc9357SAndroid Build Coastguard Worker item.BufIndex = bufIndex;
1383*f6dc9357SAndroid Build Coastguard Worker item.Parent = parent;
1384*f6dc9357SAndroid Build Coastguard Worker
1385*f6dc9357SAndroid Build Coastguard Worker const Byte *pFile = p + pos;
1386*f6dc9357SAndroid Build Coastguard Worker CFfsFileHeader fh;
1387*f6dc9357SAndroid Build Coastguard Worker if (!fh.Parse(pFile))
1388*f6dc9357SAndroid Build Coastguard Worker {
1389*f6dc9357SAndroid Build Coastguard Worker UInt32 num_FF_bytes = Count_FF_Bytes(pFile, rem);
1390*f6dc9357SAndroid Build Coastguard Worker if (num_FF_bytes != rem)
1391*f6dc9357SAndroid Build Coastguard Worker {
1392*f6dc9357SAndroid Build Coastguard Worker item.Name = "[junk]";
1393*f6dc9357SAndroid Build Coastguard Worker item.Offset = posBase + pos + num_FF_bytes;
1394*f6dc9357SAndroid Build Coastguard Worker item.Size = rem - num_FF_bytes;
1395*f6dc9357SAndroid Build Coastguard Worker AddItem(item);
1396*f6dc9357SAndroid Build Coastguard Worker }
1397*f6dc9357SAndroid Build Coastguard Worker PrintLevel(level); PRF(printf("== FF FF reminder"));
1398*f6dc9357SAndroid Build Coastguard Worker
1399*f6dc9357SAndroid Build Coastguard Worker break;
1400*f6dc9357SAndroid Build Coastguard Worker }
1401*f6dc9357SAndroid Build Coastguard Worker
1402*f6dc9357SAndroid Build Coastguard Worker PrintLevel(level); PRF(printf("%s, type = %3d, pos = %7x, size = %7x", "FILE", fh.Type, posBase + pos, fh.Size));
1403*f6dc9357SAndroid Build Coastguard Worker
1404*f6dc9357SAndroid Build Coastguard Worker if (!fh.Check(pFile, rem))
1405*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1406*f6dc9357SAndroid Build Coastguard Worker
1407*f6dc9357SAndroid Build Coastguard Worker UInt32 offset = posBase + pos + kFileHeaderSize;
1408*f6dc9357SAndroid Build Coastguard Worker UInt32 sectSize = fh.GetDataSize();
1409*f6dc9357SAndroid Build Coastguard Worker item.Offset = offset;
1410*f6dc9357SAndroid Build Coastguard Worker item.Size = sectSize;
1411*f6dc9357SAndroid Build Coastguard Worker
1412*f6dc9357SAndroid Build Coastguard Worker pos += fh.Size;
1413*f6dc9357SAndroid Build Coastguard Worker
1414*f6dc9357SAndroid Build Coastguard Worker if (fh.Type == FV_FILETYPE_FFS_PAD)
1415*f6dc9357SAndroid Build Coastguard Worker if (Is_FF_Stream(pFile + kFileHeaderSize, sectSize))
1416*f6dc9357SAndroid Build Coastguard Worker continue;
1417*f6dc9357SAndroid Build Coastguard Worker
1418*f6dc9357SAndroid Build Coastguard Worker UInt32 guid32 = Get32(fh.GuidName);
1419*f6dc9357SAndroid Build Coastguard Worker bool full = true;
1420*f6dc9357SAndroid Build Coastguard Worker if (guidsVector.FindInSorted(guid32) < 0)
1421*f6dc9357SAndroid Build Coastguard Worker {
1422*f6dc9357SAndroid Build Coastguard Worker guidsVector.AddToUniqueSorted(guid32);
1423*f6dc9357SAndroid Build Coastguard Worker full = false;
1424*f6dc9357SAndroid Build Coastguard Worker }
1425*f6dc9357SAndroid Build Coastguard Worker item.SetGuid(fh.GuidName, full);
1426*f6dc9357SAndroid Build Coastguard Worker
1427*f6dc9357SAndroid Build Coastguard Worker item.Characts = fh.GetCharacts();
1428*f6dc9357SAndroid Build Coastguard Worker // PrintLevel(level);
1429*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" : %s", item.Characts));
1430*f6dc9357SAndroid Build Coastguard Worker
1431*f6dc9357SAndroid Build Coastguard Worker {
1432*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" attrib = %2d State = %3d ", (unsigned)fh.Attrib, (unsigned)fh.State));
1433*f6dc9357SAndroid Build Coastguard Worker PRF(char s[64]);
1434*f6dc9357SAndroid Build Coastguard Worker PRF(RawLeGuidToString(fh.GuidName, s));
1435*f6dc9357SAndroid Build Coastguard Worker PRF(printf(" : %s ", s));
1436*f6dc9357SAndroid Build Coastguard Worker }
1437*f6dc9357SAndroid Build Coastguard Worker
1438*f6dc9357SAndroid Build Coastguard Worker if (fh.Type == FV_FILETYPE_FFS_PAD ||
1439*f6dc9357SAndroid Build Coastguard Worker fh.Type == FV_FILETYPE_RAW)
1440*f6dc9357SAndroid Build Coastguard Worker {
1441*f6dc9357SAndroid Build Coastguard Worker bool isVolume = false;
1442*f6dc9357SAndroid Build Coastguard Worker if (fh.Type == FV_FILETYPE_RAW)
1443*f6dc9357SAndroid Build Coastguard Worker {
1444*f6dc9357SAndroid Build Coastguard Worker if (sectSize >= kFvHeaderSize)
1445*f6dc9357SAndroid Build Coastguard Worker if (IsFfs(pFile + kFileHeaderSize))
1446*f6dc9357SAndroid Build Coastguard Worker isVolume = true;
1447*f6dc9357SAndroid Build Coastguard Worker }
1448*f6dc9357SAndroid Build Coastguard Worker if (isVolume)
1449*f6dc9357SAndroid Build Coastguard Worker {
1450*f6dc9357SAndroid Build Coastguard Worker const unsigned newParent = AddDirItem(item);
1451*f6dc9357SAndroid Build Coastguard Worker const UInt32 limSize = fh.GetDataSize2(rem);
1452*f6dc9357SAndroid Build Coastguard Worker // volume.VolSize > fh.Size for some UEFI archives (is it correct UEFI?)
1453*f6dc9357SAndroid Build Coastguard Worker // so we will check VolSize for limitSize instead.
1454*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseVolume(bufIndex, offset, sectSize, limSize, (int)newParent, method, level))
1455*f6dc9357SAndroid Build Coastguard Worker }
1456*f6dc9357SAndroid Build Coastguard Worker else
1457*f6dc9357SAndroid Build Coastguard Worker AddItem(item);
1458*f6dc9357SAndroid Build Coastguard Worker }
1459*f6dc9357SAndroid Build Coastguard Worker else
1460*f6dc9357SAndroid Build Coastguard Worker {
1461*f6dc9357SAndroid Build Coastguard Worker /*
1462*f6dc9357SAndroid Build Coastguard Worker if (fh.Type == FV_FILETYPE_FREEFORM)
1463*f6dc9357SAndroid Build Coastguard Worker {
1464*f6dc9357SAndroid Build Coastguard Worker // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections)
1465*f6dc9357SAndroid Build Coastguard Worker // AddItem(item);
1466*f6dc9357SAndroid Build Coastguard Worker }
1467*f6dc9357SAndroid Build Coastguard Worker else
1468*f6dc9357SAndroid Build Coastguard Worker */
1469*f6dc9357SAndroid Build Coastguard Worker {
1470*f6dc9357SAndroid Build Coastguard Worker const unsigned newParent = AddDirItem(item);
1471*f6dc9357SAndroid Build Coastguard Worker bool error2;
1472*f6dc9357SAndroid Build Coastguard Worker RINOK(ParseSections(bufIndex, offset, sectSize, (int)newParent, method, level + 1, error2))
1473*f6dc9357SAndroid Build Coastguard Worker if (error2)
1474*f6dc9357SAndroid Build Coastguard Worker {
1475*f6dc9357SAndroid Build Coastguard Worker // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections)
1476*f6dc9357SAndroid Build Coastguard Worker item.IsDir = false;
1477*f6dc9357SAndroid Build Coastguard Worker item.Size = sectSize;
1478*f6dc9357SAndroid Build Coastguard Worker item.Name.Insert(0, "[ERROR]");
1479*f6dc9357SAndroid Build Coastguard Worker AddItem(item);
1480*f6dc9357SAndroid Build Coastguard Worker }
1481*f6dc9357SAndroid Build Coastguard Worker }
1482*f6dc9357SAndroid Build Coastguard Worker }
1483*f6dc9357SAndroid Build Coastguard Worker }
1484*f6dc9357SAndroid Build Coastguard Worker
1485*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1486*f6dc9357SAndroid Build Coastguard Worker }
1487*f6dc9357SAndroid Build Coastguard Worker
1488*f6dc9357SAndroid Build Coastguard Worker
1489*f6dc9357SAndroid Build Coastguard Worker static const char * const kRegionName[] =
1490*f6dc9357SAndroid Build Coastguard Worker {
1491*f6dc9357SAndroid Build Coastguard Worker "Descriptor"
1492*f6dc9357SAndroid Build Coastguard Worker , "BIOS"
1493*f6dc9357SAndroid Build Coastguard Worker , "ME"
1494*f6dc9357SAndroid Build Coastguard Worker , "GbE"
1495*f6dc9357SAndroid Build Coastguard Worker , "PDR"
1496*f6dc9357SAndroid Build Coastguard Worker , "Region5"
1497*f6dc9357SAndroid Build Coastguard Worker , "Region6"
1498*f6dc9357SAndroid Build Coastguard Worker , "Region7"
1499*f6dc9357SAndroid Build Coastguard Worker };
1500*f6dc9357SAndroid Build Coastguard Worker
1501*f6dc9357SAndroid Build Coastguard Worker
1502*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::ParseIntelMe(
1503*f6dc9357SAndroid Build Coastguard Worker unsigned bufIndex, UInt32 posBase,
1504*f6dc9357SAndroid Build Coastguard Worker UInt32 exactSize, UInt32 limitSize,
1505*f6dc9357SAndroid Build Coastguard Worker int parent, int method, unsigned /* level */)
1506*f6dc9357SAndroid Build Coastguard Worker {
1507*f6dc9357SAndroid Build Coastguard Worker UNUSED_VAR(limitSize)
1508*f6dc9357SAndroid Build Coastguard Worker // level++;
1509*f6dc9357SAndroid Build Coastguard Worker
1510*f6dc9357SAndroid Build Coastguard Worker const Byte *p = _bufs[bufIndex] + posBase;
1511*f6dc9357SAndroid Build Coastguard Worker if (exactSize < 16 + 16)
1512*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1513*f6dc9357SAndroid Build Coastguard Worker if (!IsIntelMe(p))
1514*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1515*f6dc9357SAndroid Build Coastguard Worker
1516*f6dc9357SAndroid Build Coastguard Worker UInt32 v0 = GetUi32(p + 20);
1517*f6dc9357SAndroid Build Coastguard Worker // UInt32 numRegions = (v0 >> 24) & 0x7;
1518*f6dc9357SAndroid Build Coastguard Worker UInt32 regAddr = (v0 >> 12) & 0xFF0;
1519*f6dc9357SAndroid Build Coastguard Worker // UInt32 numComps = (v0 >> 8) & 0x3;
1520*f6dc9357SAndroid Build Coastguard Worker // UInt32 fcba = (v0 << 4) & 0xFF0;
1521*f6dc9357SAndroid Build Coastguard Worker
1522*f6dc9357SAndroid Build Coastguard Worker // (numRegions == 0) in header in some new images.
1523*f6dc9357SAndroid Build Coastguard Worker // So we don't use the value from header
1524*f6dc9357SAndroid Build Coastguard Worker UInt32 numRegions = 7;
1525*f6dc9357SAndroid Build Coastguard Worker
1526*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i <= numRegions; i++)
1527*f6dc9357SAndroid Build Coastguard Worker {
1528*f6dc9357SAndroid Build Coastguard Worker UInt32 offset = regAddr + i * 4;
1529*f6dc9357SAndroid Build Coastguard Worker if (offset + 4 > exactSize)
1530*f6dc9357SAndroid Build Coastguard Worker break;
1531*f6dc9357SAndroid Build Coastguard Worker UInt32 val = GetUi32(p + offset);
1532*f6dc9357SAndroid Build Coastguard Worker
1533*f6dc9357SAndroid Build Coastguard Worker // only 12 bits probably are OK.
1534*f6dc9357SAndroid Build Coastguard Worker // How does it work for files larger than 16 MB?
1535*f6dc9357SAndroid Build Coastguard Worker const UInt32 kMask = 0xFFF;
1536*f6dc9357SAndroid Build Coastguard Worker // const UInt32 kMask = 0xFFFF; // 16-bit is more logical
1537*f6dc9357SAndroid Build Coastguard Worker const UInt32 lim = (val >> 16) & kMask;
1538*f6dc9357SAndroid Build Coastguard Worker const UInt32 base = (val & kMask);
1539*f6dc9357SAndroid Build Coastguard Worker
1540*f6dc9357SAndroid Build Coastguard Worker /*
1541*f6dc9357SAndroid Build Coastguard Worker strange combinations:
1542*f6dc9357SAndroid Build Coastguard Worker PDR: base = 0x1FFF lim = 0;
1543*f6dc9357SAndroid Build Coastguard Worker empty: base = 0xFFFF lim = 0xFFFF;
1544*f6dc9357SAndroid Build Coastguard Worker
1545*f6dc9357SAndroid Build Coastguard Worker PDR: base = 0x7FFF lim = 0;
1546*f6dc9357SAndroid Build Coastguard Worker empty: base = 0x7FFF lim = 0;
1547*f6dc9357SAndroid Build Coastguard Worker */
1548*f6dc9357SAndroid Build Coastguard Worker if (base == kMask && lim == 0)
1549*f6dc9357SAndroid Build Coastguard Worker continue; // unused
1550*f6dc9357SAndroid Build Coastguard Worker
1551*f6dc9357SAndroid Build Coastguard Worker if (lim < base)
1552*f6dc9357SAndroid Build Coastguard Worker continue; // unused
1553*f6dc9357SAndroid Build Coastguard Worker
1554*f6dc9357SAndroid Build Coastguard Worker CItem item;
1555*f6dc9357SAndroid Build Coastguard Worker item.Name = kRegionName[i];
1556*f6dc9357SAndroid Build Coastguard Worker item.Method = method;
1557*f6dc9357SAndroid Build Coastguard Worker item.BufIndex = bufIndex;
1558*f6dc9357SAndroid Build Coastguard Worker item.Parent = parent;
1559*f6dc9357SAndroid Build Coastguard Worker item.Offset = posBase + (base << 12);
1560*f6dc9357SAndroid Build Coastguard Worker if (item.Offset > exactSize)
1561*f6dc9357SAndroid Build Coastguard Worker continue;
1562*f6dc9357SAndroid Build Coastguard Worker item.Size = (lim + 1 - base) << 12;
1563*f6dc9357SAndroid Build Coastguard Worker // item.SetGuid(p + kFfsGuidOffset);
1564*f6dc9357SAndroid Build Coastguard Worker // item.Name += " [VOLUME]";
1565*f6dc9357SAndroid Build Coastguard Worker AddItem(item);
1566*f6dc9357SAndroid Build Coastguard Worker }
1567*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1568*f6dc9357SAndroid Build Coastguard Worker }
1569*f6dc9357SAndroid Build Coastguard Worker
1570*f6dc9357SAndroid Build Coastguard Worker
1571*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::OpenCapsule(IInStream *stream)
1572*f6dc9357SAndroid Build Coastguard Worker {
1573*f6dc9357SAndroid Build Coastguard Worker const unsigned kHeaderSize = 80;
1574*f6dc9357SAndroid Build Coastguard Worker Byte buf[kHeaderSize];
1575*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))
1576*f6dc9357SAndroid Build Coastguard Worker if (!_h.Parse(buf))
1577*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1578*f6dc9357SAndroid Build Coastguard Worker if (_h.CapsuleImageSize < kHeaderSize
1579*f6dc9357SAndroid Build Coastguard Worker || _h.CapsuleImageSize < _h.HeaderSize
1580*f6dc9357SAndroid Build Coastguard Worker || _h.OffsetToCapsuleBody < _h.HeaderSize
1581*f6dc9357SAndroid Build Coastguard Worker || _h.OffsetToCapsuleBody > _h.CapsuleImageSize
1582*f6dc9357SAndroid Build Coastguard Worker || _h.CapsuleImageSize > (1u << 30) // to reduce false detection
1583*f6dc9357SAndroid Build Coastguard Worker || _h.HeaderSize > (1u << 28) // to reduce false detection
1584*f6dc9357SAndroid Build Coastguard Worker )
1585*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1586*f6dc9357SAndroid Build Coastguard Worker _phySize = _h.CapsuleImageSize;
1587*f6dc9357SAndroid Build Coastguard Worker
1588*f6dc9357SAndroid Build Coastguard Worker if (_h.SequenceNumber != 0 ||
1589*f6dc9357SAndroid Build Coastguard Worker _h.OffsetToSplitInformation != 0 )
1590*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
1591*f6dc9357SAndroid Build Coastguard Worker
1592*f6dc9357SAndroid Build Coastguard Worker const unsigned bufIndex = AddBuf(_h.CapsuleImageSize);
1593*f6dc9357SAndroid Build Coastguard Worker CByteBuffer &buf0 = _bufs[bufIndex];
1594*f6dc9357SAndroid Build Coastguard Worker memcpy(buf0, buf, kHeaderSize);
1595*f6dc9357SAndroid Build Coastguard Worker ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize);
1596*f6dc9357SAndroid Build Coastguard Worker
1597*f6dc9357SAndroid Build Coastguard Worker AddCommentString("Author", _h.OffsetToAuthorInformation);
1598*f6dc9357SAndroid Build Coastguard Worker AddCommentString("Revision", _h.OffsetToRevisionInformation);
1599*f6dc9357SAndroid Build Coastguard Worker AddCommentString("Short Description", _h.OffsetToShortDescription);
1600*f6dc9357SAndroid Build Coastguard Worker AddCommentString("Long Description", _h.OffsetToLongDescription);
1601*f6dc9357SAndroid Build Coastguard Worker
1602*f6dc9357SAndroid Build Coastguard Worker
1603*f6dc9357SAndroid Build Coastguard Worker const UInt32 size = _h.CapsuleImageSize - _h.OffsetToCapsuleBody;
1604*f6dc9357SAndroid Build Coastguard Worker
1605*f6dc9357SAndroid Build Coastguard Worker if (size >= 32 && IsIntelMe(buf0 + _h.OffsetToCapsuleBody))
1606*f6dc9357SAndroid Build Coastguard Worker return ParseIntelMe(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0);
1607*f6dc9357SAndroid Build Coastguard Worker
1608*f6dc9357SAndroid Build Coastguard Worker return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0);
1609*f6dc9357SAndroid Build Coastguard Worker }
1610*f6dc9357SAndroid Build Coastguard Worker
1611*f6dc9357SAndroid Build Coastguard Worker
1612*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* callback */)
1613*f6dc9357SAndroid Build Coastguard Worker {
1614*f6dc9357SAndroid Build Coastguard Worker Byte buf[kFvHeaderSize];
1615*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf, kFvHeaderSize))
1616*f6dc9357SAndroid Build Coastguard Worker if (!IsFfs(buf))
1617*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1618*f6dc9357SAndroid Build Coastguard Worker CVolFfsHeader ffsHeader;
1619*f6dc9357SAndroid Build Coastguard Worker if (!ffsHeader.Parse(buf))
1620*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1621*f6dc9357SAndroid Build Coastguard Worker if (ffsHeader.VolSize > ((UInt32)1 << 30))
1622*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1623*f6dc9357SAndroid Build Coastguard Worker _phySize = ffsHeader.VolSize;
1624*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekToBegin(stream))
1625*f6dc9357SAndroid Build Coastguard Worker UInt32 fvSize32 = (UInt32)ffsHeader.VolSize;
1626*f6dc9357SAndroid Build Coastguard Worker unsigned bufIndex = AddBuf(fvSize32);
1627*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, _bufs[bufIndex], fvSize32))
1628*f6dc9357SAndroid Build Coastguard Worker return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0);
1629*f6dc9357SAndroid Build Coastguard Worker }
1630*f6dc9357SAndroid Build Coastguard Worker
1631*f6dc9357SAndroid Build Coastguard Worker
1632*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
1633*f6dc9357SAndroid Build Coastguard Worker {
1634*f6dc9357SAndroid Build Coastguard Worker if (_capsuleMode)
1635*f6dc9357SAndroid Build Coastguard Worker {
1636*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenCapsule(stream))
1637*f6dc9357SAndroid Build Coastguard Worker }
1638*f6dc9357SAndroid Build Coastguard Worker else
1639*f6dc9357SAndroid Build Coastguard Worker {
1640*f6dc9357SAndroid Build Coastguard Worker RINOK(OpenFv(stream, maxCheckStartPosition, callback))
1641*f6dc9357SAndroid Build Coastguard Worker }
1642*f6dc9357SAndroid Build Coastguard Worker
1643*f6dc9357SAndroid Build Coastguard Worker const unsigned num = _items.Size();
1644*f6dc9357SAndroid Build Coastguard Worker CIntArr numChilds(num);
1645*f6dc9357SAndroid Build Coastguard Worker
1646*f6dc9357SAndroid Build Coastguard Worker unsigned i;
1647*f6dc9357SAndroid Build Coastguard Worker
1648*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < num; i++)
1649*f6dc9357SAndroid Build Coastguard Worker numChilds[i] = 0;
1650*f6dc9357SAndroid Build Coastguard Worker
1651*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < num; i++)
1652*f6dc9357SAndroid Build Coastguard Worker {
1653*f6dc9357SAndroid Build Coastguard Worker const int parent = _items[i].Parent;
1654*f6dc9357SAndroid Build Coastguard Worker if (parent >= 0)
1655*f6dc9357SAndroid Build Coastguard Worker numChilds[(unsigned)parent]++;
1656*f6dc9357SAndroid Build Coastguard Worker }
1657*f6dc9357SAndroid Build Coastguard Worker
1658*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < num; i++)
1659*f6dc9357SAndroid Build Coastguard Worker {
1660*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[i];
1661*f6dc9357SAndroid Build Coastguard Worker const int parent = item.Parent;
1662*f6dc9357SAndroid Build Coastguard Worker if (parent >= 0)
1663*f6dc9357SAndroid Build Coastguard Worker {
1664*f6dc9357SAndroid Build Coastguard Worker CItem &parentItem = _items[(unsigned)parent];
1665*f6dc9357SAndroid Build Coastguard Worker if (numChilds[(unsigned)parent] == 1)
1666*f6dc9357SAndroid Build Coastguard Worker if (!item.ThereIsUniqueName || !parentItem.ThereIsUniqueName || !parentItem.ThereAreSubDirs)
1667*f6dc9357SAndroid Build Coastguard Worker parentItem.Skip = true;
1668*f6dc9357SAndroid Build Coastguard Worker }
1669*f6dc9357SAndroid Build Coastguard Worker }
1670*f6dc9357SAndroid Build Coastguard Worker
1671*f6dc9357SAndroid Build Coastguard Worker CUIntVector mainToReduced;
1672*f6dc9357SAndroid Build Coastguard Worker
1673*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < _items.Size(); i++)
1674*f6dc9357SAndroid Build Coastguard Worker {
1675*f6dc9357SAndroid Build Coastguard Worker mainToReduced.Add(_items2.Size());
1676*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[i];
1677*f6dc9357SAndroid Build Coastguard Worker if (item.Skip)
1678*f6dc9357SAndroid Build Coastguard Worker continue;
1679*f6dc9357SAndroid Build Coastguard Worker AString name;
1680*f6dc9357SAndroid Build Coastguard Worker int numItems = -1;
1681*f6dc9357SAndroid Build Coastguard Worker int parent = item.Parent;
1682*f6dc9357SAndroid Build Coastguard Worker if (parent >= 0)
1683*f6dc9357SAndroid Build Coastguard Worker numItems = numChilds[(unsigned)parent];
1684*f6dc9357SAndroid Build Coastguard Worker AString name2 (item.GetName(numItems));
1685*f6dc9357SAndroid Build Coastguard Worker AString characts2 (item.Characts);
1686*f6dc9357SAndroid Build Coastguard Worker if (item.KeepName)
1687*f6dc9357SAndroid Build Coastguard Worker name = name2;
1688*f6dc9357SAndroid Build Coastguard Worker
1689*f6dc9357SAndroid Build Coastguard Worker while (parent >= 0)
1690*f6dc9357SAndroid Build Coastguard Worker {
1691*f6dc9357SAndroid Build Coastguard Worker const CItem &item3 = _items[(unsigned)parent];
1692*f6dc9357SAndroid Build Coastguard Worker if (!item3.Skip)
1693*f6dc9357SAndroid Build Coastguard Worker break;
1694*f6dc9357SAndroid Build Coastguard Worker if (item3.KeepName)
1695*f6dc9357SAndroid Build Coastguard Worker {
1696*f6dc9357SAndroid Build Coastguard Worker AString name3 (item3.GetName(-1));
1697*f6dc9357SAndroid Build Coastguard Worker if (name.IsEmpty())
1698*f6dc9357SAndroid Build Coastguard Worker name = name3;
1699*f6dc9357SAndroid Build Coastguard Worker else
1700*f6dc9357SAndroid Build Coastguard Worker name = name3 + '.' + name;
1701*f6dc9357SAndroid Build Coastguard Worker }
1702*f6dc9357SAndroid Build Coastguard Worker AddSpaceAndString(characts2, item3.Characts);
1703*f6dc9357SAndroid Build Coastguard Worker parent = item3.Parent;
1704*f6dc9357SAndroid Build Coastguard Worker }
1705*f6dc9357SAndroid Build Coastguard Worker
1706*f6dc9357SAndroid Build Coastguard Worker if (name.IsEmpty())
1707*f6dc9357SAndroid Build Coastguard Worker name = name2;
1708*f6dc9357SAndroid Build Coastguard Worker
1709*f6dc9357SAndroid Build Coastguard Worker CItem2 item2;
1710*f6dc9357SAndroid Build Coastguard Worker item2.MainIndex = i;
1711*f6dc9357SAndroid Build Coastguard Worker item2.Name = name;
1712*f6dc9357SAndroid Build Coastguard Worker item2.Characts = characts2;
1713*f6dc9357SAndroid Build Coastguard Worker if (parent >= 0)
1714*f6dc9357SAndroid Build Coastguard Worker item2.Parent = (int)mainToReduced[(unsigned)parent];
1715*f6dc9357SAndroid Build Coastguard Worker _items2.Add(item2);
1716*f6dc9357SAndroid Build Coastguard Worker /*
1717*f6dc9357SAndroid Build Coastguard Worker CItem2 item2;
1718*f6dc9357SAndroid Build Coastguard Worker item2.MainIndex = i;
1719*f6dc9357SAndroid Build Coastguard Worker item2.Name = item.Name;
1720*f6dc9357SAndroid Build Coastguard Worker item2.Parent = item.Parent;
1721*f6dc9357SAndroid Build Coastguard Worker _items2.Add(item2);
1722*f6dc9357SAndroid Build Coastguard Worker */
1723*f6dc9357SAndroid Build Coastguard Worker }
1724*f6dc9357SAndroid Build Coastguard Worker
1725*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1726*f6dc9357SAndroid Build Coastguard Worker }
1727*f6dc9357SAndroid Build Coastguard Worker
1728*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *inStream,
1729*f6dc9357SAndroid Build Coastguard Worker const UInt64 *maxCheckStartPosition,
1730*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback *callback))
1731*f6dc9357SAndroid Build Coastguard Worker {
1732*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1733*f6dc9357SAndroid Build Coastguard Worker Close();
1734*f6dc9357SAndroid Build Coastguard Worker {
1735*f6dc9357SAndroid Build Coastguard Worker HRESULT res = Open2(inStream, maxCheckStartPosition, callback);
1736*f6dc9357SAndroid Build Coastguard Worker if (res == E_NOTIMPL)
1737*f6dc9357SAndroid Build Coastguard Worker res = S_FALSE;
1738*f6dc9357SAndroid Build Coastguard Worker return res;
1739*f6dc9357SAndroid Build Coastguard Worker }
1740*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1741*f6dc9357SAndroid Build Coastguard Worker }
1742*f6dc9357SAndroid Build Coastguard Worker
1743*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
1744*f6dc9357SAndroid Build Coastguard Worker {
1745*f6dc9357SAndroid Build Coastguard Worker _phySize = 0;
1746*f6dc9357SAndroid Build Coastguard Worker _totalBufsSize = 0;
1747*f6dc9357SAndroid Build Coastguard Worker _methodsMask = 0;
1748*f6dc9357SAndroid Build Coastguard Worker _items.Clear();
1749*f6dc9357SAndroid Build Coastguard Worker _items2.Clear();
1750*f6dc9357SAndroid Build Coastguard Worker _bufs.Clear();
1751*f6dc9357SAndroid Build Coastguard Worker _comment.Empty();
1752*f6dc9357SAndroid Build Coastguard Worker _headersError = false;
1753*f6dc9357SAndroid Build Coastguard Worker _h.Clear();
1754*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1755*f6dc9357SAndroid Build Coastguard Worker }
1756*f6dc9357SAndroid Build Coastguard Worker
1757*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
1758*f6dc9357SAndroid Build Coastguard Worker {
1759*f6dc9357SAndroid Build Coastguard Worker *numItems = _items2.Size();
1760*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1761*f6dc9357SAndroid Build Coastguard Worker }
1762*f6dc9357SAndroid Build Coastguard Worker
1763*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
1764*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback))
1765*f6dc9357SAndroid Build Coastguard Worker {
1766*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1767*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
1768*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode)
1769*f6dc9357SAndroid Build Coastguard Worker numItems = _items2.Size();
1770*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0)
1771*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1772*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0;
1773*f6dc9357SAndroid Build Coastguard Worker UInt32 i;
1774*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++)
1775*f6dc9357SAndroid Build Coastguard Worker totalSize += _items[_items2[allFilesMode ? i : indices[i]].MainIndex].Size;
1776*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize))
1777*f6dc9357SAndroid Build Coastguard Worker totalSize = 0;
1778*f6dc9357SAndroid Build Coastguard Worker
1779*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
1780*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false);
1781*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;
1782*f6dc9357SAndroid Build Coastguard Worker
1783*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++)
1784*f6dc9357SAndroid Build Coastguard Worker {
1785*f6dc9357SAndroid Build Coastguard Worker lps->InSize = lps->OutSize = totalSize;
1786*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur())
1787*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems)
1788*f6dc9357SAndroid Build Coastguard Worker break;
1789*f6dc9357SAndroid Build Coastguard Worker Int32 opRes;
1790*f6dc9357SAndroid Build Coastguard Worker {
1791*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream;
1792*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ?
1793*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest :
1794*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract;
1795*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i];
1796*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[_items2[index].MainIndex];
1797*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode))
1798*f6dc9357SAndroid Build Coastguard Worker totalSize += item.Size;
1799*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream)
1800*f6dc9357SAndroid Build Coastguard Worker continue;
1801*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode))
1802*f6dc9357SAndroid Build Coastguard Worker if (testMode || item.IsDir)
1803*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kOK;
1804*f6dc9357SAndroid Build Coastguard Worker else
1805*f6dc9357SAndroid Build Coastguard Worker {
1806*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError;
1807*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> inStream;
1808*f6dc9357SAndroid Build Coastguard Worker GetStream(index, &inStream);
1809*f6dc9357SAndroid Build Coastguard Worker if (inStream)
1810*f6dc9357SAndroid Build Coastguard Worker {
1811*f6dc9357SAndroid Build Coastguard Worker RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))
1812*f6dc9357SAndroid Build Coastguard Worker if (copyCoder->TotalSize == item.Size)
1813*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kOK;
1814*f6dc9357SAndroid Build Coastguard Worker }
1815*f6dc9357SAndroid Build Coastguard Worker }
1816*f6dc9357SAndroid Build Coastguard Worker }
1817*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes))
1818*f6dc9357SAndroid Build Coastguard Worker }
1819*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1820*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1821*f6dc9357SAndroid Build Coastguard Worker }
1822*f6dc9357SAndroid Build Coastguard Worker
1823*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))
1824*f6dc9357SAndroid Build Coastguard Worker {
1825*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN
1826*f6dc9357SAndroid Build Coastguard Worker const CItem &item = _items[_items2[index].MainIndex];
1827*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir)
1828*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1829*f6dc9357SAndroid Build Coastguard Worker CBufInStream *streamSpec = new CBufInStream;
1830*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> streamTemp = streamSpec;
1831*f6dc9357SAndroid Build Coastguard Worker const CByteBuffer &buf = _bufs[item.BufIndex];
1832*f6dc9357SAndroid Build Coastguard Worker if (item.Offset > buf.Size())
1833*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
1834*f6dc9357SAndroid Build Coastguard Worker size_t size = buf.Size() - item.Offset;
1835*f6dc9357SAndroid Build Coastguard Worker if (size > item.Size)
1836*f6dc9357SAndroid Build Coastguard Worker size = item.Size;
1837*f6dc9357SAndroid Build Coastguard Worker streamSpec->Init(buf + item.Offset, size, (IInArchive *)this);
1838*f6dc9357SAndroid Build Coastguard Worker *stream = streamTemp.Detach();
1839*f6dc9357SAndroid Build Coastguard Worker return S_OK;
1840*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END
1841*f6dc9357SAndroid Build Coastguard Worker }
1842*f6dc9357SAndroid Build Coastguard Worker
1843*f6dc9357SAndroid Build Coastguard Worker
1844*f6dc9357SAndroid Build Coastguard Worker namespace UEFIc {
1845*f6dc9357SAndroid Build Coastguard Worker
1846*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Capsule_Signatures[] =
1847*f6dc9357SAndroid Build Coastguard Worker {
1848*f6dc9357SAndroid Build Coastguard Worker 16, CAPSULE_SIGNATURE,
1849*f6dc9357SAndroid Build Coastguard Worker 16, CAPSULE2_SIGNATURE,
1850*f6dc9357SAndroid Build Coastguard Worker 16, CAPSULE_UEFI_SIGNATURE
1851*f6dc9357SAndroid Build Coastguard Worker };
1852*f6dc9357SAndroid Build Coastguard Worker
1853*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I_CLS(
1854*f6dc9357SAndroid Build Coastguard Worker CHandler(true),
1855*f6dc9357SAndroid Build Coastguard Worker "UEFIc", "scap", NULL, 0xD0,
1856*f6dc9357SAndroid Build Coastguard Worker k_Capsule_Signatures,
1857*f6dc9357SAndroid Build Coastguard Worker 0,
1858*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kMultiSignature |
1859*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kFindSignature,
1860*f6dc9357SAndroid Build Coastguard Worker NULL)
1861*f6dc9357SAndroid Build Coastguard Worker
1862*f6dc9357SAndroid Build Coastguard Worker }
1863*f6dc9357SAndroid Build Coastguard Worker
1864*f6dc9357SAndroid Build Coastguard Worker namespace UEFIf {
1865*f6dc9357SAndroid Build Coastguard Worker
1866*f6dc9357SAndroid Build Coastguard Worker static const Byte k_FFS_Signatures[] =
1867*f6dc9357SAndroid Build Coastguard Worker {
1868*f6dc9357SAndroid Build Coastguard Worker 16, FFS1_SIGNATURE,
1869*f6dc9357SAndroid Build Coastguard Worker 16, FFS2_SIGNATURE
1870*f6dc9357SAndroid Build Coastguard Worker };
1871*f6dc9357SAndroid Build Coastguard Worker
1872*f6dc9357SAndroid Build Coastguard Worker
1873*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I_CLS(
1874*f6dc9357SAndroid Build Coastguard Worker CHandler(false),
1875*f6dc9357SAndroid Build Coastguard Worker "UEFIf", "uefif", NULL, 0xD1,
1876*f6dc9357SAndroid Build Coastguard Worker k_FFS_Signatures,
1877*f6dc9357SAndroid Build Coastguard Worker kFfsGuidOffset,
1878*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kMultiSignature |
1879*f6dc9357SAndroid Build Coastguard Worker NArcInfoFlags::kFindSignature,
1880*f6dc9357SAndroid Build Coastguard Worker NULL)
1881*f6dc9357SAndroid Build Coastguard Worker
1882*f6dc9357SAndroid Build Coastguard Worker }
1883*f6dc9357SAndroid Build Coastguard Worker
1884*f6dc9357SAndroid Build Coastguard Worker }}
1885