823 lines
19 KiB
C
823 lines
19 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
arcdisk.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Provides the routines for collecting the disk information for all the ARC
|
|||
|
disks visible in the ARC environment.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 3-Nov-1993
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Vijay Jayaseelan (vijayj) 2-April-2000
|
|||
|
|
|||
|
- Added EFI partition table support
|
|||
|
|
|||
|
--*/
|
|||
|
#include "bootlib.h"
|
|||
|
|
|||
|
#ifdef i386
|
|||
|
#include "bldrx86.h"
|
|||
|
#endif
|
|||
|
|
|||
|
#if defined(_IA64_)
|
|||
|
#include "bldria64.h"
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef EFI_PARTITION_SUPPORT
|
|||
|
|
|||
|
//
|
|||
|
// EFI partition entries
|
|||
|
//
|
|||
|
UNALIGNED EFI_PARTITION_ENTRY EfiPartitionBuffer[128] = {0};
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlpEnumerateDisks(
|
|||
|
IN PCONFIGURATION_COMPONENT_DATA ConfigData
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
#if defined(_X86_) && !defined(ARCI386)
|
|||
|
|
|||
|
static
|
|||
|
VOID
|
|||
|
BlpEnumerateXInt13(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine will go through all the enumerated disks and record
|
|||
|
their ability to support xInt13.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR Partition[100];
|
|||
|
ULONG DiskId;
|
|||
|
ARC_STATUS Status;
|
|||
|
PARC_DISK_SIGNATURE DiskSignature;
|
|||
|
PARC_DISK_INFORMATION DiskInfo;
|
|||
|
PLIST_ENTRY Entry;
|
|||
|
|
|||
|
DiskInfo = BlLoaderBlock->ArcDiskInformation;
|
|||
|
Entry = DiskInfo->DiskSignatures.Flink;
|
|||
|
|
|||
|
while (Entry != &DiskInfo->DiskSignatures) {
|
|||
|
DiskSignature = CONTAINING_RECORD(Entry,ARC_DISK_SIGNATURE,ListEntry);
|
|||
|
|
|||
|
//
|
|||
|
// Open partition0 on the disk and get it's device ID.
|
|||
|
//
|
|||
|
strcpy(Partition, DiskSignature->ArcName);
|
|||
|
strcat(Partition, "partition(0)");
|
|||
|
|
|||
|
Status = ArcOpen(Partition, ArcOpenReadOnly, &DiskId);
|
|||
|
|
|||
|
if( Status == ESUCCESS ) {
|
|||
|
//
|
|||
|
// Now we've got the DiskId. Fortunately, someone
|
|||
|
// has been keeping track of all the DiskIds on the
|
|||
|
// machine and whether or not they've got xint13 support.
|
|||
|
// All we need to do now is go lookup our diskid in
|
|||
|
// that database and get the xint13 BOOLEAN.
|
|||
|
//
|
|||
|
DiskSignature->xInt13 = BlFileTable[DiskId].u.DriveContext.xInt13;
|
|||
|
|
|||
|
//
|
|||
|
// We don't need you anymore.
|
|||
|
//
|
|||
|
ArcClose(DiskId);
|
|||
|
} else {
|
|||
|
DiskSignature->xInt13 = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
Entry = Entry->Flink;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#endif // for defined(_X86_) && !defined(ARCI386)
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
BlGetArcDiskInformation(
|
|||
|
BOOLEAN XInt13Support
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Enumerates the ARC disks present in the system and collects the identifying disk
|
|||
|
information from each one.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
XInt13Support : Indicates whether to find XInt13 support or not
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PARC_DISK_INFORMATION DiskInfo;
|
|||
|
|
|||
|
DiskInfo = BlAllocateHeap(sizeof(ARC_DISK_INFORMATION));
|
|||
|
if (DiskInfo==NULL) {
|
|||
|
return(ENOMEM);
|
|||
|
}
|
|||
|
|
|||
|
InitializeListHead(&DiskInfo->DiskSignatures);
|
|||
|
|
|||
|
BlLoaderBlock->ArcDiskInformation = DiskInfo;
|
|||
|
|
|||
|
BlSearchConfigTree(BlLoaderBlock->ConfigurationRoot,
|
|||
|
PeripheralClass,
|
|||
|
DiskPeripheral,
|
|||
|
(ULONG)-1,
|
|||
|
BlpEnumerateDisks);
|
|||
|
|
|||
|
#if defined(_X86_) && !defined(ARCI386)
|
|||
|
|
|||
|
//
|
|||
|
// Enumerate XInt13 support on X86 only if asked for
|
|||
|
//
|
|||
|
if (XInt13Support) {
|
|||
|
BlpEnumerateXInt13();
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
return(ESUCCESS);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlpEnumerateDisks(
|
|||
|
IN PCONFIGURATION_COMPONENT_DATA ConfigData
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Callback routine for enumerating the disks in the ARC firmware tree. It
|
|||
|
reads all the necessary information from the disk to uniquely identify
|
|||
|
it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ConfigData - Supplies a pointer to the disk's ARC component data.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - continue searching
|
|||
|
|
|||
|
FALSE - stop searching tree.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CHAR DiskName[100];
|
|||
|
|
|||
|
BlGetPathnameFromComponent(ConfigData, DiskName);
|
|||
|
return(BlReadSignature(DiskName,FALSE));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlReadSignature(
|
|||
|
IN PCHAR DiskName,
|
|||
|
IN BOOLEAN IsCdRom
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Given an ARC disk name, reads the MBR and adds its signature to the list of
|
|||
|
disks.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Diskname - Supplies the name of the disk.
|
|||
|
|
|||
|
IsCdRom - Indicates whether the disk is a CD-ROM.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - Success
|
|||
|
|
|||
|
FALSE - Failure
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PARC_DISK_SIGNATURE Signature;
|
|||
|
BOOLEAN Status = FALSE;
|
|||
|
|
|||
|
Signature = BlAllocateHeap(sizeof(ARC_DISK_SIGNATURE));
|
|||
|
if (Signature==NULL) {
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
Signature->ArcName = BlAllocateHeap(strlen(DiskName)+2);
|
|||
|
if (Signature->ArcName==NULL) {
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
#if defined(i386)
|
|||
|
Status = BlFindDiskSignature(DiskName, Signature);
|
|||
|
#endif
|
|||
|
|
|||
|
if(!Status) {
|
|||
|
Status = BlGetDiskSignature(DiskName, IsCdRom, Signature);
|
|||
|
}
|
|||
|
|
|||
|
if (Status) {
|
|||
|
InsertHeadList(&BlLoaderBlock->ArcDiskInformation->DiskSignatures,
|
|||
|
&Signature->ListEntry);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
ArcDiskGPTDiskReadCallback(
|
|||
|
ULONGLONG StartingLBA,
|
|||
|
ULONG BytesToRead,
|
|||
|
PVOID pContext,
|
|||
|
UNALIGNED PVOID OutputBuffer
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is a callback for reading data for a routine that
|
|||
|
validates the GPT partition table.
|
|||
|
|
|||
|
NOTE: This routine changes the seek position on disk, and you must seek
|
|||
|
back to your original seek position if you plan on reading from the
|
|||
|
disk after making this call.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
StartingLBA - starting logical block address to read from.
|
|||
|
|
|||
|
BytesToRead - Indicates how many bytes are to be read.
|
|||
|
|
|||
|
pContext - context pointer for hte function (in this case, a pointer to the disk id.)
|
|||
|
|
|||
|
OutputBuffer - a buffer that receives the data. It's assumed that it is at least
|
|||
|
BytesToRead big enough.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - success, data has been read
|
|||
|
|
|||
|
FALSE - failed, data has not been read.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ARC_STATUS Status;
|
|||
|
LARGE_INTEGER SeekPosition;
|
|||
|
PUSHORT DataPointer;
|
|||
|
ULONG DiskId;
|
|||
|
ULONG ReadCount = 0;
|
|||
|
|
|||
|
|
|||
|
DiskId = *((PULONG)pContext);
|
|||
|
//
|
|||
|
// read the second LBA on the disk
|
|||
|
//
|
|||
|
SeekPosition.QuadPart = StartingLBA * SECTOR_SIZE;
|
|||
|
|
|||
|
Status = ArcSeek(DiskId,
|
|||
|
&SeekPosition,
|
|||
|
SeekAbsolute );
|
|||
|
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
DataPointer = OutputBuffer;
|
|||
|
|
|||
|
Status = ArcRead(
|
|||
|
DiskId,
|
|||
|
DataPointer,
|
|||
|
BytesToRead,
|
|||
|
&ReadCount);
|
|||
|
|
|||
|
if ((Status == ESUCCESS) && (ReadCount == BytesToRead)) {
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
return(FALSE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlGetDiskSignature(
|
|||
|
IN PCHAR DiskName,
|
|||
|
IN BOOLEAN IsCdRom,
|
|||
|
PARC_DISK_SIGNATURE Signature
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine gets the NTFT disk signature for a specified partition or
|
|||
|
path.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DiskName - Supplies the arcname of the partition or drive.
|
|||
|
|
|||
|
IsCdRom - Indicates whether the disk is a CD-ROM.
|
|||
|
|
|||
|
Signature - Returns a full ARC_DISK_SIGNATURE.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - success, Signature will be filled in.
|
|||
|
|
|||
|
FALSE - failed, Signature will not be filled in.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UCHAR SectorBuffer[2048+256] = {0};
|
|||
|
UCHAR Partition[100];
|
|||
|
ULONG DiskId;
|
|||
|
ULONG Status;
|
|||
|
LARGE_INTEGER SeekValue;
|
|||
|
PUCHAR Sector;
|
|||
|
ULONG i;
|
|||
|
ULONG Sum;
|
|||
|
ULONG Count;
|
|||
|
ULONG SectorSize;
|
|||
|
EFI_PARTITION_TABLE *EfiHdr;
|
|||
|
|
|||
|
if (IsCdRom) {
|
|||
|
SectorSize = 2048;
|
|||
|
} else {
|
|||
|
SectorSize = 512;
|
|||
|
}
|
|||
|
|
|||
|
#if defined(_i386_)
|
|||
|
//
|
|||
|
// NTDETECT creates an "eisa(0)..." arcname for detected
|
|||
|
// BIOS disks on an EISA machine. Change this to "multi(0)..."
|
|||
|
// in order to be consistent with the rest of the system
|
|||
|
// (particularly the arcname in boot.ini)
|
|||
|
//
|
|||
|
if (_strnicmp(DiskName,"eisa",4)==0) {
|
|||
|
strcpy(Signature->ArcName,"multi");
|
|||
|
strcpy(Partition,"multi");
|
|||
|
strcat(Signature->ArcName,DiskName+4);
|
|||
|
strcat(Partition,DiskName+4);
|
|||
|
} else {
|
|||
|
strcpy(Signature->ArcName, DiskName);
|
|||
|
strcpy(Partition, DiskName);
|
|||
|
}
|
|||
|
#else
|
|||
|
strcpy(Signature->ArcName, DiskName);
|
|||
|
strcpy(Partition, DiskName);
|
|||
|
#endif
|
|||
|
|
|||
|
strcat(Partition, "partition(0)");
|
|||
|
|
|||
|
Status = ArcOpen(Partition, ArcOpenReadOnly, &DiskId);
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Read in the first sector
|
|||
|
//
|
|||
|
Sector = ALIGN_BUFFER(SectorBuffer);
|
|||
|
if (IsCdRom) {
|
|||
|
//
|
|||
|
// For a CD-ROM, the interesting data starts at 0x8000.
|
|||
|
//
|
|||
|
SeekValue.QuadPart = 0x8000;
|
|||
|
} else {
|
|||
|
SeekValue.QuadPart = 0;
|
|||
|
}
|
|||
|
Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
|
|||
|
if (Status == ESUCCESS) {
|
|||
|
Status = ArcRead(DiskId,
|
|||
|
Sector,
|
|||
|
SectorSize,
|
|||
|
&Count);
|
|||
|
}
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
ArcClose(DiskId);
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Check to see whether this disk has a valid partition table signature or not.
|
|||
|
//
|
|||
|
if (((PUSHORT)Sector)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) {
|
|||
|
Signature->ValidPartitionTable = FALSE;
|
|||
|
} else {
|
|||
|
Signature->ValidPartitionTable = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
Signature->Signature = ((PULONG)Sector)[PARTITION_TABLE_OFFSET/2-1];
|
|||
|
|
|||
|
//
|
|||
|
// compute the checksum
|
|||
|
//
|
|||
|
Sum = 0;
|
|||
|
for (i=0; i<(SectorSize/4); i++) {
|
|||
|
Sum += ((PULONG)Sector)[i];
|
|||
|
}
|
|||
|
Signature->CheckSum = ~Sum + 1;
|
|||
|
|
|||
|
//
|
|||
|
// Check for GPT disk.
|
|||
|
//
|
|||
|
Signature->IsGpt = FALSE;
|
|||
|
|
|||
|
if (!IsCdRom) {
|
|||
|
SeekValue.QuadPart = 1 * SectorSize;
|
|||
|
Status = ArcSeek(DiskId, &SeekValue, SeekAbsolute);
|
|||
|
if (Status == ESUCCESS) {
|
|||
|
Status = ArcRead(DiskId,
|
|||
|
Sector,
|
|||
|
SectorSize,
|
|||
|
&Count);
|
|||
|
if (Status == ESUCCESS) {
|
|||
|
ULONG tmpDiskId = DiskId;
|
|||
|
|
|||
|
//
|
|||
|
// verify EFI partition table
|
|||
|
//
|
|||
|
EfiHdr = (EFI_PARTITION_TABLE *)Sector;
|
|||
|
|
|||
|
if (BlIsValidGUIDPartitionTable(
|
|||
|
EfiHdr,
|
|||
|
1,
|
|||
|
&tmpDiskId,
|
|||
|
ArcDiskGPTDiskReadCallback)) {
|
|||
|
Signature->IsGpt = TRUE;
|
|||
|
memcpy(
|
|||
|
Signature->GptSignature,
|
|||
|
EfiHdr->DiskGuid,
|
|||
|
sizeof(EfiHdr->DiskGuid) );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ArcClose(DiskId);
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#ifdef EFI_PARTITION_SUPPORT
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
void DbgOut(PWSTR Str);
|
|||
|
|
|||
|
//#define DBG_PRINT(x) DbgOut(x);
|
|||
|
ULONG BlGetKey();
|
|||
|
|
|||
|
#if defined(_IA64_)
|
|||
|
|
|||
|
#define STR_PREFIX L
|
|||
|
|
|||
|
#define DBG_PRINT(x) DbgOut(x)
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
#define STR_PREFIX
|
|||
|
|
|||
|
#define DBG_PRINT(x) \
|
|||
|
{\
|
|||
|
BlPrint(x); \
|
|||
|
while (!BlGetKey()); \
|
|||
|
}
|
|||
|
|
|||
|
#endif // _IA64_
|
|||
|
*/
|
|||
|
|
|||
|
#define DBG_PRINT(x)
|
|||
|
#define STR_PREFIX
|
|||
|
|
|||
|
UNALIGNED EFI_PARTITION_ENTRY *
|
|||
|
BlLocateGPTPartition(
|
|||
|
IN UCHAR PartitionNumber,
|
|||
|
IN UCHAR MaxPartitions,
|
|||
|
IN PUCHAR ValidPartCount
|
|||
|
)
|
|||
|
{
|
|||
|
UNALIGNED EFI_PARTITION_ENTRY *PartEntry = NULL;
|
|||
|
UCHAR NullGuid[16] = {0};
|
|||
|
UCHAR PartIdx = 0;
|
|||
|
UCHAR PartCount = 0;
|
|||
|
|
|||
|
#if 0
|
|||
|
BlPrint("BlLocateGPTPartition(%d,%d,%d)\r\n",
|
|||
|
PartitionNumber,
|
|||
|
MaxPartitions,
|
|||
|
ValidPartCount ? *ValidPartCount : 0);
|
|||
|
while (!BlGetKey());
|
|||
|
#endif
|
|||
|
|
|||
|
if (ARGUMENT_PRESENT(ValidPartCount)) {
|
|||
|
PartCount = *ValidPartCount;
|
|||
|
}
|
|||
|
|
|||
|
PartitionNumber++; // convert to one based index
|
|||
|
|
|||
|
//
|
|||
|
// Locate the requested valid partition
|
|||
|
//
|
|||
|
while ((PartIdx < MaxPartitions) && (PartCount < PartitionNumber)) {
|
|||
|
DBG_PRINT(STR_PREFIX"Verifying GPT Partition Entry\r\n");
|
|||
|
|
|||
|
PartEntry = (UNALIGNED EFI_PARTITION_ENTRY *)(EfiPartitionBuffer + PartIdx);
|
|||
|
|
|||
|
if ((memcmp(PartEntry->Type, NullGuid, 16)) &&
|
|||
|
(memcmp(PartEntry->Id, NullGuid, 16)) &&
|
|||
|
(PartEntry->StartingLBA != 0) && (PartEntry->EndingLBA != 0)) {
|
|||
|
DBG_PRINT(STR_PREFIX"Found Valid GPT Partition Entry\r\n");
|
|||
|
PartCount++;
|
|||
|
|
|||
|
if (ARGUMENT_PRESENT(ValidPartCount)) {
|
|||
|
(*ValidPartCount)++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get hold of the partition entry
|
|||
|
//
|
|||
|
if (PartCount == PartitionNumber) {
|
|||
|
break;
|
|||
|
} else {
|
|||
|
PartEntry = NULL;
|
|||
|
}
|
|||
|
} else {
|
|||
|
PartEntry = NULL;
|
|||
|
}
|
|||
|
|
|||
|
PartIdx++;
|
|||
|
}
|
|||
|
|
|||
|
return PartEntry;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
BlDiskOpenGPTDiskReadCallback(
|
|||
|
ULONGLONG StartingLBA,
|
|||
|
ULONG BytesToRead,
|
|||
|
PVOID pContext,
|
|||
|
UNALIGNED PVOID OutputBuffer
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is a callback for reading data for a routine that
|
|||
|
validates the GPT partition table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
StartingLBA - starting logical block address to read from.
|
|||
|
|
|||
|
BytesToRead - Indicates how many bytes are to be read.
|
|||
|
|
|||
|
pContext - context pointer for hte function (in this case, a pointer to the disk id.)
|
|||
|
|
|||
|
OutputBuffer - a buffer that receives the data. It's assumed that it is at least
|
|||
|
BytesToRead big enough.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - success, data has been read
|
|||
|
|
|||
|
FALSE - failed, data has not been read.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ARC_STATUS Status;
|
|||
|
LARGE_INTEGER SeekPosition;
|
|||
|
PUSHORT DataPointer;
|
|||
|
ULONG DiskId;
|
|||
|
ULONG ReadCount = 0;
|
|||
|
|
|||
|
|
|||
|
DiskId = *((PULONG)pContext);
|
|||
|
//
|
|||
|
// read the second LBA on the disk
|
|||
|
//
|
|||
|
SeekPosition.QuadPart = StartingLBA * SECTOR_SIZE;
|
|||
|
|
|||
|
Status = (BlFileTable[DiskId].DeviceEntryTable->Seek)(DiskId,
|
|||
|
&SeekPosition,
|
|||
|
SeekAbsolute );
|
|||
|
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
DataPointer = OutputBuffer;
|
|||
|
|
|||
|
Status = (BlFileTable[DiskId].DeviceEntryTable->Read)(DiskId,
|
|||
|
DataPointer,
|
|||
|
BytesToRead,
|
|||
|
&ReadCount);
|
|||
|
|
|||
|
if ((Status == ESUCCESS) && (ReadCount == BytesToRead)) {
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
return(FALSE);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
BlOpenGPTDiskPartition(
|
|||
|
IN ULONG FileId,
|
|||
|
IN ULONG DiskId,
|
|||
|
IN UCHAR PartitionNumber
|
|||
|
)
|
|||
|
{
|
|||
|
ARC_STATUS Status;
|
|||
|
LARGE_INTEGER SeekPosition;
|
|||
|
UCHAR DataBuffer[SECTOR_SIZE * 2] = {0};
|
|||
|
ULONG ReadCount = 0;
|
|||
|
UCHAR NullGuid[16] = {0};
|
|||
|
UCHAR PartIdx;
|
|||
|
UCHAR PartCount;
|
|||
|
UNALIGNED EFI_PARTITION_TABLE *EfiHdr;
|
|||
|
UNALIGNED EFI_PARTITION_ENTRY *PartEntry;
|
|||
|
ULONG tmpDiskId = DiskId;
|
|||
|
|
|||
|
|
|||
|
if (PartitionNumber >= 128)
|
|||
|
return EINVAL;
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Seeking GPT PT\r\n");
|
|||
|
|
|||
|
//
|
|||
|
// read the second LBA on the disk
|
|||
|
//
|
|||
|
SeekPosition.QuadPart = 1 * SECTOR_SIZE;
|
|||
|
|
|||
|
Status = (BlFileTable[DiskId].DeviceEntryTable->Seek)(DiskId,
|
|||
|
&SeekPosition,
|
|||
|
SeekAbsolute );
|
|||
|
|
|||
|
if (Status != ESUCCESS)
|
|||
|
return Status;
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Reading GPT PT\r\n");
|
|||
|
|
|||
|
Status = (BlFileTable[DiskId].DeviceEntryTable->Read)(DiskId,
|
|||
|
DataBuffer,
|
|||
|
SECTOR_SIZE,
|
|||
|
&ReadCount);
|
|||
|
|
|||
|
if (Status != ESUCCESS)
|
|||
|
return Status;
|
|||
|
|
|||
|
if (ReadCount != SECTOR_SIZE) {
|
|||
|
Status = EIO;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
EfiHdr = (UNALIGNED EFI_PARTITION_TABLE *)DataBuffer;
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Verifying GPT PT\r\n");
|
|||
|
|
|||
|
//
|
|||
|
// verify EFI partition table
|
|||
|
//
|
|||
|
if (!BlIsValidGUIDPartitionTable(
|
|||
|
EfiHdr,
|
|||
|
1,
|
|||
|
&tmpDiskId,
|
|||
|
BlDiskOpenGPTDiskReadCallback)) {
|
|||
|
Status = EBADF;
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Locate and read the partition entry
|
|||
|
// which is requested
|
|||
|
//
|
|||
|
SeekPosition.QuadPart = EfiHdr->PartitionEntryLBA * SECTOR_SIZE;
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Seeking GPT Partition Entries\r\n");
|
|||
|
|
|||
|
Status = (BlFileTable[DiskId].DeviceEntryTable->Seek)(DiskId,
|
|||
|
&SeekPosition,
|
|||
|
SeekAbsolute );
|
|||
|
|
|||
|
if (Status != ESUCCESS)
|
|||
|
return Status;
|
|||
|
|
|||
|
RtlZeroMemory(EfiPartitionBuffer, sizeof(EfiPartitionBuffer));
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Reading GPT Partition Entries\r\n");
|
|||
|
|
|||
|
Status = (BlFileTable[DiskId].DeviceEntryTable->Read)(DiskId,
|
|||
|
EfiPartitionBuffer,
|
|||
|
sizeof(EfiPartitionBuffer),
|
|||
|
&ReadCount);
|
|||
|
|
|||
|
if (Status != ESUCCESS)
|
|||
|
return Status;
|
|||
|
|
|||
|
if (ReadCount != sizeof(EfiPartitionBuffer)) {
|
|||
|
Status = EIO;
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Locating the correct GPT partition entry\r\n");
|
|||
|
|
|||
|
PartEntry = (UNALIGNED EFI_PARTITION_ENTRY *)BlLocateGPTPartition(PartitionNumber, 128, NULL);
|
|||
|
|
|||
|
if (PartEntry) {
|
|||
|
DBG_PRINT(STR_PREFIX"Verifying GPT Partition Entry\r\n");
|
|||
|
|
|||
|
if ((memcmp(PartEntry->Type, NullGuid, 16)) &&
|
|||
|
(memcmp(PartEntry->Id, NullGuid, 16)) &&
|
|||
|
(PartEntry->StartingLBA != 0) && (PartEntry->EndingLBA != 0)) {
|
|||
|
PPARTITION_CONTEXT PartContext = &(BlFileTable[FileId].u.PartitionContext);
|
|||
|
ULONG SectorCount = (ULONG)(PartEntry->EndingLBA - PartEntry->StartingLBA);
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Initializing GPT Partition Entry Context\r\n");
|
|||
|
|
|||
|
//
|
|||
|
// Fill the partition context structure
|
|||
|
//
|
|||
|
PartContext->PartitionLength.QuadPart = SectorCount * SECTOR_SIZE;
|
|||
|
PartContext->StartingSector = (ULONG)(PartEntry->StartingLBA);
|
|||
|
PartContext->EndingSector = (ULONG)(PartEntry->EndingLBA);
|
|||
|
PartContext->DiskId = (UCHAR)DiskId;
|
|||
|
|
|||
|
BlFileTable[FileId].Position.QuadPart = 0;
|
|||
|
|
|||
|
#if 0
|
|||
|
BlPrint("GPT Partition opened:L:%ld,%ld:%ld,SS:%ld,ES:%ld\n",
|
|||
|
PartitionNumber,
|
|||
|
(ULONG)PartContext->PartitionLength.QuadPart,
|
|||
|
(ULONG)PartContext->StartingSector,
|
|||
|
(ULONG)PartContext->EndingSector);
|
|||
|
|
|||
|
while (!GET_KEY());
|
|||
|
#endif
|
|||
|
|
|||
|
Status = ESUCCESS;
|
|||
|
} else {
|
|||
|
Status = EBADF;
|
|||
|
}
|
|||
|
} else {
|
|||
|
Status = EBADF;
|
|||
|
}
|
|||
|
|
|||
|
DBG_PRINT(STR_PREFIX"Returning from BlOpenGPTDiskPartition(...)\r\n");
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
#endif // for EFI_PARTITION_SUPPORT
|