OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcAppleDiskImageBlockIo.c
Go to the documentation of this file.
1
13#include <Uefi.h>
14
17#include <Protocol/BlockIo.h>
18
19#include <Library/BaseMemoryLib.h>
20#include <Library/DebugLib.h>
21#include <Library/DevicePathLib.h>
22#include <Library/MemoryAllocationLib.h>
23#include <Library/OcApfsLib.h>
25#include <Library/OcStringLib.h>
26#include <Library/PrintLib.h>
27#include <Library/UefiBootServicesTableLib.h>
28
30
31#define DMG_FILE_PATH_LEN (L_STR_LEN (L"DMG_.dmg") + 16 + 1)
32
33#pragma pack(push, 1)
34
35typedef PACKED struct {
36 VENDOR_DEFINED_DEVICE_PATH Vendor;
37 UINT64 Length;
39
40typedef PACKED struct {
41 EFI_DEVICE_PATH_PROTOCOL Header;
47
48typedef PACKED struct {
52 EFI_DEVICE_PATH_PROTOCOL End;
54
55#pragma pack(pop)
56
57#define OC_APPLE_DISK_IMAGE_MOUNTED_DATA_SIGNATURE \
58 SIGNATURE_32('D','m','g','I')
59
60#define OC_APPLE_DISK_IMAGE_MOUNTED_DATA_FROM_THIS(This) \
61 BASE_CR ( \
62 (This), \
63 OC_APPLE_DISK_IMAGE_MOUNTED_DATA, \
64 BlockIo \
65 )
66
76
77STATIC
78EFI_STATUS
79EFIAPI
81 IN EFI_BLOCK_IO_PROTOCOL *This,
82 IN BOOLEAN ExtendedVerification
83 )
84{
85 return EFI_SUCCESS;
86}
87
88STATIC
89EFI_STATUS
90EFIAPI
92 IN EFI_BLOCK_IO_PROTOCOL *This,
93 IN UINT32 MediaId,
94 IN EFI_LBA Lba,
95 IN UINTN BufferSize,
96 OUT VOID *Buffer
97 )
98{
100 BOOLEAN Result;
101
102 if ((This == NULL) || (Buffer == NULL)) {
103 return EFI_INVALID_PARAMETER;
104 }
105
106 if ((BufferSize % APPLE_DISK_IMAGE_SECTOR_SIZE) != 0) {
107 return EFI_BAD_BUFFER_SIZE;
108 }
109
110 DiskImageData = OC_APPLE_DISK_IMAGE_MOUNTED_DATA_FROM_THIS (This);
111 if (DiskImageData->Signature == 0) {
112 return EFI_UNSUPPORTED;
113 }
114
116
117 if (Lba >= DiskImageData->ImageContext->SectorCount) {
118 return EFI_INVALID_PARAMETER;
119 }
120
121 Result = OcAppleDiskImageRead (
122 DiskImageData->ImageContext,
123 (UINTN)Lba,
124 BufferSize,
125 Buffer
126 );
127 if (!Result) {
128 return EFI_DEVICE_ERROR;
129 }
130
131 return EFI_SUCCESS;
132}
133
134STATIC
135EFI_STATUS
136EFIAPI
138 IN EFI_BLOCK_IO_PROTOCOL *This,
139 IN UINT32 MediaId,
140 IN EFI_LBA Lba,
141 IN UINTN BufferSize,
142 IN VOID *Buffer
143 )
144{
145 return EFI_WRITE_PROTECTED;
146}
147
148STATIC
149EFI_STATUS
150EFIAPI
152 IN EFI_BLOCK_IO_PROTOCOL *This
153 )
154{
155 return EFI_SUCCESS;
156}
157
158STATIC UINT32 mDmgCounter;
159
160STATIC
161VOID
163 IN OUT OC_APPLE_DISK_IMAGE_MOUNTED_DATA *DiskImageData,
164 IN UINTN FileSize
165 )
166{
167 UINT64 RamDmgAddress;
168 DMG_DEVICE_PATH *DevPath;
169 CHAR16 *UnicodeDevPath;
170
171 ASSERT (DiskImageData != NULL);
172 ASSERT (DiskImageData->ImageContext);
173
174 RamDmgAddress = (UINTN)DiskImageData->ImageContext->ExtentTable;
175
176 DevPath = &DiskImageData->DevicePath;
177
178 DevPath->RamDisk.Vendor.Vendor.Header.Type = HARDWARE_DEVICE_PATH;
179 DevPath->RamDisk.Vendor.Vendor.Header.SubType = HW_VENDOR_DP;
180 CopyGuid (
181 &DevPath->RamDisk.Vendor.Vendor.Guid,
183 );
184 DevPath->RamDisk.Vendor.Counter = mDmgCounter++;
185 SetDevicePathNodeLength (
186 &DevPath->RamDisk.Vendor,
187 sizeof (DevPath->RamDisk.Vendor)
188 );
189
190 DevPath->RamDisk.MemMap.Header.Type = HARDWARE_DEVICE_PATH;
191 DevPath->RamDisk.MemMap.Header.SubType = HW_MEMMAP_DP;
192 DevPath->RamDisk.MemMap.MemoryType = EfiACPIMemoryNVS;
193 DevPath->RamDisk.MemMap.StartingAddress = RamDmgAddress;
194 DevPath->RamDisk.MemMap.EndingAddress = RamDmgAddress + sizeof (APPLE_RAM_DISK_EXTENT_TABLE);
195 SetDevicePathNodeLength (&DevPath->RamDisk.MemMap, sizeof (DevPath->RamDisk.MemMap));
196
197 DevPath->FilePath.Header.Type = MEDIA_DEVICE_PATH;
198 DevPath->FilePath.Header.SubType = MEDIA_FILEPATH_DP;
199 SetDevicePathNodeLength (&DevPath->FilePath, sizeof (DevPath->FilePath));
200 UnicodeSPrint (
201 DevPath->FilePath.PathName,
202 sizeof (DevPath->FilePath.PathName),
203 L"DMG_%16X.dmg",
204 FileSize
205 );
206
207 DevPath->Size.Vendor.Header.Type = MESSAGING_DEVICE_PATH;
208 DevPath->Size.Vendor.Header.SubType = MSG_VENDOR_DP;
209 DevPath->Size.Length = FileSize;
210 SetDevicePathNodeLength (&DevPath->Size, sizeof (DevPath->Size));
211 CopyGuid (
212 (VOID *)&DevPath->Size.Vendor.Guid,
214 );
215
216 SetDevicePathEndNode (&DevPath->End);
217
218 DEBUG_CODE_BEGIN ();
219 ASSERT (
220 IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)DevPath, sizeof (*DevPath))
221 );
222
223 UnicodeDevPath = ConvertDevicePathToText ((EFI_DEVICE_PATH_PROTOCOL *)DevPath, FALSE, FALSE);
224 DEBUG ((DEBUG_INFO, "OCDI: Built DMG DP: %s\n", UnicodeDevPath != NULL ? UnicodeDevPath : L"<NULL>"));
225 if (UnicodeDevPath != NULL) {
226 FreePool (UnicodeDevPath);
227 }
228
229 DEBUG_CODE_END ();
230}
231
232STATIC CONST EFI_BLOCK_IO_PROTOCOL mDiskImageBlockIo = {
233 EFI_BLOCK_IO_PROTOCOL_REVISION,
234 NULL,
239};
240
241EFI_HANDLE
243 IN OC_APPLE_DISK_IMAGE_CONTEXT *Context,
244 IN UINTN FileSize,
245 OUT CONST EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL,
246 OUT UINTN *DevicePathSize OPTIONAL
247 )
248{
249 EFI_HANDLE BlockIoHandle;
250
251 EFI_STATUS Status;
253
254 ASSERT (Context != NULL);
255 ASSERT (FileSize > 0);
256
257 DiskImageData = AllocateZeroPool (sizeof (*DiskImageData));
258 if (DiskImageData == NULL) {
259 DEBUG ((DEBUG_INFO, "OCDI: Failed to allocate DMG mount context\n"));
260 return NULL;
261 }
262
264 DiskImageData->ImageContext = Context;
265 CopyMem (
266 &DiskImageData->BlockIo,
268 sizeof (DiskImageData->BlockIo)
269 );
270
271 DiskImageData->BlockIo.Media = &DiskImageData->BlockIoMedia;
272 DiskImageData->BlockIoMedia.MediaPresent = TRUE;
273 DiskImageData->BlockIoMedia.ReadOnly = TRUE;
274 DiskImageData->BlockIoMedia.BlockSize = APPLE_DISK_IMAGE_SECTOR_SIZE;
275 DiskImageData->BlockIoMedia.LastBlock = (Context->SectorCount - 1);
276
277 InternalConstructDmgDevicePath (DiskImageData, FileSize);
278
279 BlockIoHandle = NULL;
280 Status = gBS->InstallMultipleProtocolInterfaces (
281 &BlockIoHandle,
283 &DiskImageData->DevicePath,
285 &DiskImageData->BlockIo,
286 NULL
287 );
288 if (EFI_ERROR (Status)) {
289 DEBUG ((DEBUG_INFO, "OCDI: Failed to install protocols %r\n", Status));
290 FreePool (DiskImageData);
291 return NULL;
292 }
293
294 Status = gBS->ConnectController (BlockIoHandle, NULL, NULL, TRUE);
295 if (!EFI_ERROR (Status)) {
296 OcApfsConnectParentDevice (BlockIoHandle, FALSE);
297 } else {
298 DEBUG ((DEBUG_INFO, "OCDI: Failed to connect DMG handle %r\n", Status));
299
300 Status = gBS->UninstallMultipleProtocolInterfaces (
301 BlockIoHandle,
303 &DiskImageData->DevicePath,
305 &DiskImageData->BlockIo,
306 NULL
307 );
308 if (!EFI_ERROR (Status)) {
309 FreePool (DiskImageData);
310 } else {
311 DEBUG ((DEBUG_INFO, "OCDI: Failed to uninstall protocols %r\n", Status));
312 DiskImageData->Signature = 0;
313 }
314
315 return NULL;
316 }
317
318 if (DevicePath != NULL) {
319 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&DiskImageData->DevicePath;
320
321 if (DevicePathSize != NULL) {
322 *DevicePathSize = sizeof (DiskImageData->DevicePath);
323 }
324 }
325
326 return BlockIoHandle;
327}
328
329VOID
331 IN OC_APPLE_DISK_IMAGE_CONTEXT *Context,
332 IN VOID *BlockIoHandle
333 )
334{
335 EFI_STATUS Status;
336 EFI_BLOCK_IO_PROTOCOL *BlockIo;
338
339 ASSERT (Context != NULL);
340 ASSERT (BlockIoHandle != NULL);
341
342 Status = gBS->HandleProtocol (
343 BlockIoHandle,
345 (VOID **)&BlockIo
346 );
347 if (EFI_ERROR (Status)) {
348 DEBUG ((DEBUG_INFO, "OCDI: Invalid handle for Block I/O uninstall\n"));
349 return;
350 }
351
352 DiskImageData = OC_APPLE_DISK_IMAGE_MOUNTED_DATA_FROM_THIS (BlockIo);
353
354 Status = gBS->DisconnectController (BlockIoHandle, NULL, NULL);
355 Status |= gBS->UninstallMultipleProtocolInterfaces (
356 BlockIoHandle,
358 &DiskImageData->BlockIo,
360 &DiskImageData->DevicePath,
361 NULL
362 );
363 if (!EFI_ERROR (Status)) {
364 FreePool (DiskImageData);
365 } else {
366 DEBUG ((
367 DEBUG_INFO,
368 "OCDI: Failed to disconnect DMG controller or uninstal protocols\n"
369 ));
370 DiskImageData->Signature = 0;
371 }
372}
EFI_GUID gAppleRamDiskProtocolGuid
PACKED struct @57 APPLE_RAM_DISK_DP_HEADER
PACKED struct @54 APPLE_RAM_DISK_EXTENT_TABLE
#define APPLE_DISK_IMAGE_SECTOR_SIZE
EFI_STATUS OcApfsConnectParentDevice(IN EFI_HANDLE Handle OPTIONAL, IN BOOLEAN VerifyPolicy)
Definition OcApfsLib.c:90
#define OC_APPLE_DISK_IMAGE_MOUNTED_DATA_SIGNATURE
CHAR16 PathName[DMG_FILE_PATH_LEN]
EFI_DEVICE_PATH_PROTOCOL Header
PACKED struct @80 DMG_SIZE_DEVICE_PATH
STATIC EFI_STATUS EFIAPI DiskImageBlockIoReset(IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
VOID OcAppleDiskImageUninstallBlockIo(IN OC_APPLE_DISK_IMAGE_CONTEXT *Context, IN VOID *BlockIoHandle)
PACKED struct @82 DMG_DEVICE_PATH
STATIC EFI_STATUS EFIAPI DiskImageBlockIoWriteBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, IN VOID *Buffer)
DMG_FILEPATH_DEVICE_PATH FilePath
STATIC UINT32 mDmgCounter
FIXME: This should exist on a protocol basis!
APPLE_RAM_DISK_DP_HEADER RamDisk
STATIC EFI_STATUS EFIAPI DiskImageBlockIoFlushBlocks(IN EFI_BLOCK_IO_PROTOCOL *This)
EFI_DEVICE_PATH_PROTOCOL End
DMG_SIZE_DEVICE_PATH Size
STATIC VOID InternalConstructDmgDevicePath(IN OUT OC_APPLE_DISK_IMAGE_MOUNTED_DATA *DiskImageData, IN UINTN FileSize)
VENDOR_DEFINED_DEVICE_PATH Vendor
EFI_HANDLE OcAppleDiskImageInstallBlockIo(IN OC_APPLE_DISK_IMAGE_CONTEXT *Context, IN UINTN FileSize, OUT CONST EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL, OUT UINTN *DevicePathSize OPTIONAL)
UINT64 Length
STATIC CONST EFI_BLOCK_IO_PROTOCOL mDiskImageBlockIo
STATIC EFI_STATUS EFIAPI DiskImageBlockIoReadBlocks(IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, OUT VOID *Buffer)
PACKED struct @81 DMG_FILEPATH_DEVICE_PATH
#define OC_APPLE_DISK_IMAGE_MOUNTED_DATA_FROM_THIS(This)
#define DMG_FILE_PATH_LEN
BOOLEAN OcAppleDiskImageRead(IN OC_APPLE_DISK_IMAGE_CONTEXT *Context, IN UINTN Lba, IN UINTN BufferSize, OUT VOID *Buffer)
EFI_BOOT_SERVICES * gBS
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
EFI_GUID gAppleDiskImageProtocolGuid
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
EFI_GUID gEfiBlockIoProtocolGuid
EFI_GUID gEfiDevicePathProtocolGuid
#define ASSERT(x)
Definition coder.h:55
OC_APPLE_DISK_IMAGE_CONTEXT * ImageContext