OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcAppleDiskImageLibInternal.c
Go to the documentation of this file.
1
13#include <Uefi.h>
14
15#include <Library/BaseLib.h>
16#include <Library/BaseOverflowLib.h>
17#include <Library/DebugLib.h>
18#include <Library/MemoryAllocationLib.h>
20#include <Library/OcXmlLib.h>
21
23
24STATIC
25BOOLEAN
27 IN XML_NODE *Node,
28 IN CHAR8 *KeyName,
29 OUT XML_NODE **Key,
30 OUT XML_NODE **Value
31 )
32{
33 UINT32 ChildCount;
34 XML_NODE *ChildValue;
35 XML_NODE *ChildKey;
36 CONST CHAR8 *ChildKeyName;
37 UINT32 Index;
38
39 ASSERT (Node != NULL);
40 ASSERT (KeyName != NULL);
41 ASSERT (Key != NULL);
42 ASSERT (Value != NULL);
43
44 ChildCount = PlistDictChildren (Node);
45 for (Index = 0; Index < ChildCount; ++Index) {
46 ChildKey = PlistDictChild (Node, Index, &ChildValue);
47 if (ChildKey == NULL) {
48 break;
49 }
50
51 ChildKeyName = PlistKeyValue (ChildKey);
52 if (ChildKeyName == NULL) {
53 break;
54 }
55
56 if (AsciiStrCmp (ChildKeyName, KeyName) == 0) {
57 *Key = ChildKey;
58 *Value = ChildValue;
59 return TRUE;
60 }
61 }
62
63 return FALSE;
64}
65
66STATIC
67BOOLEAN
69 IN OUT APPLE_DISK_IMAGE_BLOCK_DATA *BlockData,
70 IN UINT32 MaxSize,
71 IN UINTN SectorCount,
72 IN UINTN DataForkOffset,
73 IN UINTN DataForkSize
74 )
75{
76 UINT32 ChunksSize;
77 UINTN MaxOffset;
78 BOOLEAN Result;
80 UINT32 Index;
81 UINT64 BlockSectorTop;
82 UINT64 ChunkSectorTop;
83 UINT64 OffsetTop;
84
85 ASSERT (MaxSize >= sizeof (*BlockData));
86
87 BlockData->ChunkCount = SwapBytes32 (BlockData->ChunkCount);
88
89 Result = BaseOverflowMulU32 (
90 BlockData->ChunkCount,
91 sizeof (*BlockData->Chunks),
92 &ChunksSize
93 );
94 if (Result || (ChunksSize > (MaxSize - sizeof (*BlockData)))) {
95 return FALSE;
96 }
97
98 MaxOffset = (DataForkOffset + DataForkSize);
99
100 BlockData->Version = SwapBytes32 (BlockData->Version);
101 BlockData->SectorNumber = SwapBytes64 (BlockData->SectorNumber);
102 BlockData->SectorCount = SwapBytes64 (BlockData->SectorCount);
103 BlockData->DataOffset = SwapBytes64 (BlockData->DataOffset);
104 BlockData->BuffersNeeded = SwapBytes32 (BlockData->BuffersNeeded);
105 BlockData->BlockDescriptors = SwapBytes32 (BlockData->BlockDescriptors);
106 BlockData->Checksum.Type = SwapBytes32 (BlockData->Checksum.Type);
107 BlockData->Checksum.Size = SwapBytes32 (BlockData->Checksum.Size);
108
109 if ( (BlockData->DataOffset > DataForkOffset)
110 || (BlockData->Checksum.Size > (sizeof (BlockData->Checksum.Data) * 8))
111 || (BlockData->DataOffset > MaxOffset))
112 {
113 return FALSE;
114 }
115
116 Result = BaseOverflowAddU64 (
117 BlockData->SectorNumber,
118 BlockData->SectorCount,
119 &BlockSectorTop
120 );
121 if (Result || (BlockSectorTop > SectorCount)) {
122 DEBUG ((DEBUG_ERROR, "OCDI: Block sectors exceed DMG sectors %lu %lu\n", BlockSectorTop, SectorCount));
123 return FALSE;
124 }
125
126 for (Index = 0; Index < APPLE_DISK_IMAGE_CHECKSUM_SIZE; ++Index) {
127 BlockData->Checksum.Data[Index] = SwapBytes32 (
128 BlockData->Checksum.Data[Index]
129 );
130 }
131
132 for (Index = 0; Index < BlockData->ChunkCount; ++Index) {
133 Chunk = &BlockData->Chunks[Index];
134
135 Chunk->Type = SwapBytes32 (Chunk->Type);
136 Chunk->Comment = SwapBytes32 (Chunk->Comment);
137 Chunk->SectorNumber = SwapBytes64 (Chunk->SectorNumber);
138 Chunk->SectorCount = SwapBytes64 (Chunk->SectorCount);
141
142 Result = BaseOverflowAddU64 (
143 Chunk->SectorNumber,
144 Chunk->SectorCount,
145 &ChunkSectorTop
146 );
147 if (Result || (ChunkSectorTop > BlockSectorTop)) {
148 return FALSE;
149 }
150
151 Result = BaseOverflowAddU64 (
152 Chunk->CompressedOffset,
153 Chunk->CompressedLength,
154 &OffsetTop
155 );
156 if (Result || (OffsetTop > MaxOffset)) {
157 return FALSE;
158 }
159 }
160
161 return TRUE;
162}
163
164BOOLEAN
166 IN CHAR8 *Plist,
167 IN UINT32 PlistSize,
168 IN UINTN SectorCount,
169 IN UINTN DataForkOffset,
170 IN UINTN DataForkSize,
171 OUT UINT32 *BlockCount,
172 OUT APPLE_DISK_IMAGE_BLOCK_DATA ***Blocks
173 )
174{
175 BOOLEAN Result;
176
177 XML_DOCUMENT *XmlPlistDoc;
178 XML_NODE *NodeRoot;
179 XML_NODE *NodeResourceForkKey;
180 XML_NODE *NodeResourceForkValue;
181 XML_NODE *NodeBlockListKey;
182 XML_NODE *NodeBlockListValue;
183
184 XML_NODE *NodeBlockDict;
185 XML_NODE *BlockDictChildKey;
186 XML_NODE *BlockDictChildValue;
187 UINT32 BlockDictChildDataSize;
188
189 UINT32 NumDmgBlocks;
190 UINT32 DmgBlocksSize;
191 APPLE_DISK_IMAGE_BLOCK_DATA **DmgBlocks;
193
194 UINT32 Index;
195
196 ASSERT (Plist != NULL);
197 ASSERT (PlistSize > 0);
198 ASSERT (BlockCount != NULL);
199 ASSERT (Blocks != NULL);
200
201 DmgBlocks = NULL;
202
203 XmlPlistDoc = NULL;
204
205 XmlPlistDoc = XmlDocumentParse (Plist, PlistSize, FALSE);
206 if (XmlPlistDoc == NULL) {
207 Result = FALSE;
208 goto DONE_ERROR;
209 }
210
211 NodeRoot = PlistDocumentRoot (XmlPlistDoc);
212 if (NodeRoot == NULL) {
213 Result = FALSE;
214 goto DONE_ERROR;
215 }
216
218 NodeRoot,
220 &NodeResourceForkKey,
221 &NodeResourceForkValue
222 );
223 if (!Result) {
224 goto DONE_ERROR;
225 }
226
228 NodeResourceForkValue,
230 &NodeBlockListKey,
231 &NodeBlockListValue
232 );
233 if (!Result) {
234 goto DONE_ERROR;
235 }
236
237 NumDmgBlocks = XmlNodeChildren (NodeBlockListValue);
238 if (NumDmgBlocks == 0) {
239 Result = FALSE;
240 goto DONE_ERROR;
241 }
242
243 Result = !BaseOverflowMulU32 (NumDmgBlocks, sizeof (*DmgBlocks), &DmgBlocksSize);
244 if (!Result) {
246 goto DONE_ERROR;
247 }
248
249 DmgBlocks = AllocatePool (DmgBlocksSize);
250 if (DmgBlocks == NULL) {
251 Result = FALSE;
252 goto DONE_ERROR;
253 }
254
255 for (Index = 0; Index < NumDmgBlocks; ++Index) {
256 NodeBlockDict = XmlNodeChild (NodeBlockListValue, Index);
257
259 NodeBlockDict,
261 &BlockDictChildKey,
262 &BlockDictChildValue
263 );
264 if (!Result) {
265 goto DONE_ERROR;
266 }
267
268 Result = PlistDataSize (BlockDictChildValue, &BlockDictChildDataSize);
269 if (!Result || (BlockDictChildDataSize < sizeof (*Block))) {
270 Result = FALSE;
271 goto DONE_ERROR;
272 }
273
274 Block = AllocatePool (BlockDictChildDataSize);
275 if (Block == NULL) {
276 Result = FALSE;
277 goto DONE_ERROR;
278 }
279
280 DmgBlocks[Index] = Block;
281
282 Result = PlistDataValue (
283 BlockDictChildValue,
284 (UINT8 *)Block,
285 &BlockDictChildDataSize
286 );
287 if (!Result) {
288 FreePool (Block);
289 goto DONE_ERROR;
290 }
291
292 Result = InternalSwapBlockData (
293 Block,
294 BlockDictChildDataSize,
295 SectorCount,
296 DataForkOffset,
297 DataForkSize
298 );
299 if (!Result) {
300 FreePool (Block);
301 goto DONE_ERROR;
302 }
303 }
304
305 *BlockCount = NumDmgBlocks;
306 *Blocks = DmgBlocks;
307 Result = TRUE;
308
309DONE_ERROR:
310 if (!Result && (DmgBlocks != NULL)) {
311 while ((Index--) != 0) {
312 FreePool (DmgBlocks[Index]);
313 }
314
315 FreePool (DmgBlocks);
316 }
317
318 if (XmlPlistDoc != NULL) {
319 XmlDocumentFree (XmlPlistDoc);
320 }
321
322 return Result;
323}
324
325BOOLEAN
327 IN OC_APPLE_DISK_IMAGE_CONTEXT *Context,
328 IN UINTN Lba,
330 OUT APPLE_DISK_IMAGE_CHUNK **Chunk
331 )
332{
333 UINT32 BlockIndex;
334 UINT32 ChunkIndex;
336 APPLE_DISK_IMAGE_CHUNK *BlockChunk;
337
338 for (BlockIndex = 0; BlockIndex < Context->BlockCount; ++BlockIndex) {
339 BlockData = Context->Blocks[BlockIndex];
340
341 if ( (Lba >= BlockData->SectorNumber)
342 && (Lba < (BlockData->SectorNumber + BlockData->SectorCount)))
343 {
344 for (ChunkIndex = 0; ChunkIndex < BlockData->ChunkCount; ++ChunkIndex) {
345 BlockChunk = &BlockData->Chunks[ChunkIndex];
346
347 if ( (Lba >= DMG_SECTOR_START_ABS (BlockData, BlockChunk))
348 && (Lba < (DMG_SECTOR_START_ABS (BlockData, BlockChunk) + BlockChunk->SectorCount)))
349 {
350 *Data = BlockData;
351 *Chunk = BlockChunk;
352 return TRUE;
353 }
354 }
355 }
356 }
357
358 return FALSE;
359}
#define APPLE_DISK_IMAGE_CHECKSUM_SIZE
STATIC BOOLEAN InternalFindPlistDictChild(IN XML_NODE *Node, IN CHAR8 *KeyName, OUT XML_NODE **Key, OUT XML_NODE **Value)
BOOLEAN InternalParsePlist(IN CHAR8 *Plist, IN UINT32 PlistSize, IN UINTN SectorCount, IN UINTN DataForkOffset, IN UINTN DataForkSize, OUT UINT32 *BlockCount, OUT APPLE_DISK_IMAGE_BLOCK_DATA ***Blocks)
BOOLEAN InternalGetBlockChunk(IN OC_APPLE_DISK_IMAGE_CONTEXT *Context, IN UINTN Lba, OUT APPLE_DISK_IMAGE_BLOCK_DATA **Data, OUT APPLE_DISK_IMAGE_CHUNK **Chunk)
STATIC BOOLEAN InternalSwapBlockData(IN OUT APPLE_DISK_IMAGE_BLOCK_DATA *BlockData, IN UINT32 MaxSize, IN UINTN SectorCount, IN UINTN DataForkOffset, IN UINTN DataForkSize)
#define DMG_PLIST_BLOCK_LIST_KEY
#define DMG_PLIST_DATA
#define DMG_PLIST_RESOURCE_FORK_KEY
#define DMG_SECTOR_START_ABS(b, c)
BOOLEAN PlistDataSize(IN XML_NODE *Node OPTIONAL, OUT UINT32 *Size)
Definition OcXmlLib.c:2102
XML_DOCUMENT * XmlDocumentParse(IN OUT CHAR8 *Buffer, IN UINT32 Length, IN BOOLEAN WithRefs)
Definition OcXmlLib.c:1308
CONST CHAR8 * PlistKeyValue(IN XML_NODE *Node OPTIONAL)
Definition OcXmlLib.c:1841
UINT32 XmlNodeChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1493
UINT32 PlistDictChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1813
XML_NODE * PlistDocumentRoot(IN CONST XML_DOCUMENT *Document)
Definition OcXmlLib.c:1736
BOOLEAN PlistDataValue(IN XML_NODE *Node OPTIONAL, OUT UINT8 *Buffer, IN OUT UINT32 *Size)
Definition OcXmlLib.c:1886
XML_NODE * XmlNodeChild(IN CONST XML_NODE *Node, IN UINT32 Child)
Definition OcXmlLib.c:1503
VOID XmlDocumentFree(IN OUT XML_DOCUMENT *Document)
Definition OcXmlLib.c:1435
XML_NODE * PlistDictChild(IN CONST XML_NODE *Node, IN UINT32 Child, OUT XML_NODE **Value OPTIONAL)
Definition OcXmlLib.c:1823
UINT64 SwapBytes64(UINT64 Operand)
Definition UserMath.c:125
#define ASSERT(x)
Definition coder.h:55
APPLE_DISK_IMAGE_CHUNK Chunks[]