17#include <Protocol/BlockIo.h>
19#include <Library/BaseMemoryLib.h>
20#include <Library/DebugLib.h>
21#include <Library/DevicePathLib.h>
22#include <Library/MemoryAllocationLib.h>
26#include <Library/PrintLib.h>
27#include <Library/UefiBootServicesTableLib.h>
31#define DMG_FILE_PATH_LEN (L_STR_LEN (L"DMG_.dmg") + 16 + 1)
35typedef PACKED
struct {
40typedef PACKED
struct {
48typedef PACKED
struct {
52 EFI_DEVICE_PATH_PROTOCOL
End;
57#define OC_APPLE_DISK_IMAGE_MOUNTED_DATA_SIGNATURE \
58 SIGNATURE_32('D','m','g','I')
60#define OC_APPLE_DISK_IMAGE_MOUNTED_DATA_FROM_THIS(This) \
63 OC_APPLE_DISK_IMAGE_MOUNTED_DATA, \
81 IN EFI_BLOCK_IO_PROTOCOL *This,
82 IN BOOLEAN ExtendedVerification
92 IN EFI_BLOCK_IO_PROTOCOL *This,
102 if ((This == NULL) || (
Buffer == NULL)) {
103 return EFI_INVALID_PARAMETER;
107 return EFI_BAD_BUFFER_SIZE;
112 return EFI_UNSUPPORTED;
118 return EFI_INVALID_PARAMETER;
128 return EFI_DEVICE_ERROR;
138 IN EFI_BLOCK_IO_PROTOCOL *This,
145 return EFI_WRITE_PROTECTED;
152 IN EFI_BLOCK_IO_PROTOCOL *This
167 UINT64 RamDmgAddress;
169 CHAR16 *UnicodeDevPath;
171 ASSERT (DiskImageData != NULL);
172 ASSERT (DiskImageData->ImageContext);
174 RamDmgAddress = (UINTN)DiskImageData->ImageContext->ExtentTable;
176 DevPath = &DiskImageData->DevicePath;
178 DevPath->RamDisk.Vendor.Vendor.Header.Type = HARDWARE_DEVICE_PATH;
179 DevPath->RamDisk.Vendor.Vendor.Header.SubType = HW_VENDOR_DP;
181 &DevPath->RamDisk.Vendor.Vendor.Guid,
185 SetDevicePathNodeLength (
186 &DevPath->RamDisk.Vendor,
187 sizeof (DevPath->RamDisk.Vendor)
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;
195 SetDevicePathNodeLength (&DevPath->RamDisk.MemMap, sizeof (DevPath->RamDisk.MemMap));
197 DevPath->FilePath.Header.Type = MEDIA_DEVICE_PATH;
198 DevPath->FilePath.Header.SubType = MEDIA_FILEPATH_DP;
199 SetDevicePathNodeLength (&DevPath->FilePath, sizeof (DevPath->FilePath));
201 DevPath->FilePath.PathName,
202 sizeof (DevPath->FilePath.PathName),
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));
212 (VOID *)&DevPath->Size.Vendor.Guid,
216 SetDevicePathEndNode (&DevPath->End);
220 IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *)DevPath,
sizeof (*DevPath))
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);
233 EFI_BLOCK_IO_PROTOCOL_REVISION,
245 OUT CONST EFI_DEVICE_PATH_PROTOCOL **DevicePath OPTIONAL,
246 OUT UINTN *DevicePathSize OPTIONAL
249 EFI_HANDLE BlockIoHandle;
257 DiskImageData = AllocateZeroPool (
sizeof (*DiskImageData));
258 if (DiskImageData == NULL) {
259 DEBUG ((DEBUG_INFO,
"OCDI: Failed to allocate DMG mount context\n"));
268 sizeof (DiskImageData->
BlockIo)
275 DiskImageData->
BlockIoMedia.LastBlock = (Context->SectorCount - 1);
279 BlockIoHandle = NULL;
280 Status =
gBS->InstallMultipleProtocolInterfaces (
288 if (EFI_ERROR (Status)) {
289 DEBUG ((DEBUG_INFO,
"OCDI: Failed to install protocols %r\n", Status));
290 FreePool (DiskImageData);
294 Status =
gBS->ConnectController (BlockIoHandle, NULL, NULL, TRUE);
295 if (!EFI_ERROR (Status)) {
298 DEBUG ((DEBUG_INFO,
"OCDI: Failed to connect DMG handle %r\n", Status));
300 Status =
gBS->UninstallMultipleProtocolInterfaces (
308 if (!EFI_ERROR (Status)) {
309 FreePool (DiskImageData);
311 DEBUG ((DEBUG_INFO,
"OCDI: Failed to uninstall protocols %r\n", Status));
318 if (DevicePath != NULL) {
319 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&DiskImageData->
DevicePath;
321 if (DevicePathSize != NULL) {
322 *DevicePathSize =
sizeof (DiskImageData->
DevicePath);
326 return BlockIoHandle;
332 IN VOID *BlockIoHandle
336 EFI_BLOCK_IO_PROTOCOL *BlockIo;
340 ASSERT (BlockIoHandle != NULL);
342 Status =
gBS->HandleProtocol (
347 if (EFI_ERROR (Status)) {
348 DEBUG ((DEBUG_INFO,
"OCDI: Invalid handle for Block I/O uninstall\n"));
354 Status =
gBS->DisconnectController (BlockIoHandle, NULL, NULL);
355 Status |=
gBS->UninstallMultipleProtocolInterfaces (
363 if (!EFI_ERROR (Status)) {
364 FreePool (DiskImageData);
368 "OCDI: Failed to disconnect DMG controller or uninstal protocols\n"
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)
#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)
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)
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
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
EFI_BLOCK_IO_MEDIA BlockIoMedia
EFI_BLOCK_IO_PROTOCOL BlockIo
OC_APPLE_DISK_IMAGE_CONTEXT * ImageContext
DMG_DEVICE_PATH DevicePath