mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-10 14:23:31 +01:00
238 lines
7.3 KiB
C
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;
|
||
|
}
|