CloverBootloader/Drivers/PartitionDxe/Apple.c
2019-09-03 12:58:42 +03:00

238 lines
7.3 KiB
C

/** @file
Decode an Apple formatted partition table
Copyright (c) 2009-2010, Oracle Corporation
**/
#include "Partition.h"
#define DPISTRLEN 32
#pragma pack(1)
typedef struct APPLE_PT_HEADER {
UINT16 sbSig; /* must be BE 0x4552 */
UINT16 sbBlkSize; /* block size of device */
UINT32 sbBlkCount; /* number of blocks on device */
UINT16 sbDevType; /* device type */
UINT16 sbDevId; /* device id */
UINT32 sbData; /* not used */
UINT16 sbDrvrCount; /* driver descriptor count */
UINT16 sbMap[247]; /* descriptor map */
} APPLE_PT_HEADER;
typedef struct APPLE_PT_ENTRY {
UINT16 signature ; /* must be BE 0x504D for new style PT */
UINT16 reserved_1 ;
UINT32 map_entries ; /* how many PT entries are there */
UINT32 pblock_start ; /* first physical block */
UINT32 pblocks ; /* number of physical blocks */
char name[DPISTRLEN] ; /* name of partition */
char type[DPISTRLEN] ; /* type of partition */
/* Some more data we don't really need */
} APPLE_PT_ENTRY;
#pragma pack()
/**
Install child handles if the Handle supports Apple partition table format.
@param[in] This Calling context.
@param[in] Handle Parent Handle
@param[in] DiskIo Parent DiskIo interface
@param[in] BlockIo Parent BlockIo interface
@param[in] DevicePath Parent Device Path
@retval EFI_SUCCESS Child handle(s) was added
@retval EFI_MEDIA_CHANGED Media changed Detected
@retval other no child handle was added
**/
EFI_STATUS
PartitionInstallAppleChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
EFI_STATUS Status;
UINT32 Lba;
EFI_BLOCK_IO_MEDIA *Media;
VOID *Block;
//UINTN MaxIndex;
/** @todo: wrong, as this PT can be on both HDD or CD */
CDROM_DEVICE_PATH CdDev;
//EFI_DEVICE_PATH_PROTOCOL Dev;
EFI_STATUS Found;
UINT32 Partition;
UINT32 PartitionEntries;
UINT32 VolSpaceSize;
UINT32 SubBlockSize;
UINT32 BlkPerSec;
UINT32 MediaId;
UINT32 BlockSize;
EFI_LBA LastBlock;
EFI_DISK_IO2_TOKEN DiskIo2Token;
Found = EFI_NOT_FOUND;
VolSpaceSize = 0;
if (BlockIo2 != NULL)
{
Media = BlockIo2->Media;
BlockSize = BlockIo2->Media->BlockSize;
LastBlock = BlockIo2->Media->LastBlock;
MediaId = BlockIo2->Media->MediaId;
} else {
Media = BlockIo->Media;
BlockSize = BlockIo->Media->BlockSize;
LastBlock = BlockIo->Media->LastBlock;
MediaId = BlockIo->Media->MediaId;
}
Block = AllocatePool ((UINTN)BlockSize);
if (Block == NULL) {
return EFI_NOT_FOUND;
}
do {
APPLE_PT_HEADER * Header;
/* read PT header first */
Lba = 0;
if (DiskIo2 != NULL)
{
Status = DiskIo2->ReadDiskEx (
DiskIo2,
MediaId,
MultU64x32 (Lba, BlockSize),
&DiskIo2Token,
BlockSize,
Block
);
} else {
Status = DiskIo->ReadDisk (
DiskIo,
MediaId,
MultU64x32 (Lba, BlockSize),
BlockSize,
Block
);
}
if (EFI_ERROR (Status)) {
Found = Status;
break;
}
Header = (APPLE_PT_HEADER *)Block;
if (SwapBytes16(Header->sbSig) != 0x4552) {
break;
}
SubBlockSize = SwapBytes16(Header->sbBlkSize);
BlkPerSec = BlockSize / SubBlockSize;
/* Fail if media block size isn't an exact multiple */
if (BlockSize != SubBlockSize * BlkPerSec) {
break;
}
/* Now iterate over PT entries and install child handles */
PartitionEntries = 1;
for (Partition = 1; Partition <= PartitionEntries; Partition++) {
APPLE_PT_ENTRY * Entry;
UINT32 StartLba;
UINT32 SizeLbs;
if (DiskIo2 != NULL)
{
Status = DiskIo2->ReadDiskEx (
DiskIo2,
MediaId,
MultU64x32 (Partition, SubBlockSize),
&DiskIo2Token,
SubBlockSize,
Block
);
} else {
Status = DiskIo->ReadDisk (
DiskIo,
MediaId,
MultU64x32 (Partition, SubBlockSize),
SubBlockSize,
Block
);
}
if (EFI_ERROR (Status)) {
Status = EFI_NOT_FOUND;
goto done; /* would break, but ... */
}
Entry = (APPLE_PT_ENTRY *)Block;
if (SwapBytes16(Entry->signature) != 0x504D) {
Print(L"Not a new PT entry: %x", Entry->signature);
continue;
}
/* First partition contains partitions count */
if (Partition == 1) {
PartitionEntries = SwapBytes32(Entry->map_entries);
}
StartLba = SwapBytes32(Entry->pblock_start);
SizeLbs = SwapBytes32(Entry->pblocks);
/* if (0 && CompareMem("Apple_HFS", Entry->type, 10) == 0)
Print(L"HFS partition (%d of %d) at LBA 0x%x size=%dM\n",
Partition, PartitionEntries, StartLba,
(UINT32)(MultU64x32(SizeLbs, SubBlockSize) / (1024 * 1024)));
*/
//
// Create child device handle
//
ZeroMem (&CdDev, sizeof (CdDev));
CdDev.Header.Type = MEDIA_DEVICE_PATH;
CdDev.Header.SubType = MEDIA_CDROM_DP;
SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
CdDev.BootEntry = 0;
/* Convert from partition to media blocks */
CdDev.PartitionStart = StartLba / BlkPerSec; /* start, LBA */
CdDev.PartitionSize = SizeLbs / BlkPerSec; /* size, LBs */
Status = PartitionInstallChildHandle (
This,
Handle,
DiskIo,
DiskIo2,
BlockIo,
BlockIo2,
DevicePath,
(EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
CdDev.PartitionStart,
CdDev.PartitionStart + CdDev.PartitionSize - 1,
SubBlockSize,
FALSE
);
if (!EFI_ERROR (Status)) {
Found = EFI_SUCCESS;
}
}
} while (0);
done:
FreePool (Block);
return Found;
}