summaryrefslogtreecommitdiff
path: root/FatPkg/FatPei/Mbr.c
diff options
context:
space:
mode:
Diffstat (limited to 'FatPkg/FatPei/Mbr.c')
-rw-r--r--FatPkg/FatPei/Mbr.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/FatPkg/FatPei/Mbr.c b/FatPkg/FatPei/Mbr.c
new file mode 100644
index 0000000..acad6e7
--- /dev/null
+++ b/FatPkg/FatPei/Mbr.c
@@ -0,0 +1,181 @@
+/** @file
+ Routines supporting partition discovery and
+ logical device reading
+
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <IndustryStandard/Mbr.h>
+#include "FatLitePeim.h"
+
+/**
+ Test to see if the Mbr buffer is a valid MBR
+
+ @param[in] Mbr Parent Handle
+ @param[in] LastLba Last Lba address on the device.
+
+ @retval TRUE Mbr is a Valid MBR
+ @retval FALSE Mbr is not a Valid MBR
+
+**/
+BOOLEAN
+PartitionValidMbr (
+ IN MASTER_BOOT_RECORD *Mbr,
+ IN EFI_PEI_LBA LastLba
+ )
+{
+ UINT32 StartingLBA;
+ UINT32 EndingLBA;
+ UINT32 NewEndingLBA;
+ INTN Index1;
+ INTN Index2;
+ BOOLEAN MbrValid;
+
+ if (Mbr->Signature != MBR_SIGNATURE) {
+ return FALSE;
+ }
+ //
+ // The BPB also has this signature, so it can not be used alone.
+ //
+ MbrValid = FALSE;
+ for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
+ if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {
+ continue;
+ }
+
+ MbrValid = TRUE;
+ StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
+ EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
+ if (EndingLBA > LastLba) {
+ //
+ // Compatability Errata:
+ // Some systems try to hide drive space with thier INT 13h driver
+ // This does not hide space from the OS driver. This means the MBR
+ // that gets created from DOS is smaller than the MBR created from
+ // a real OS (NT & Win98). This leads to BlockIo->LastBlock being
+ // wrong on some systems FDISKed by the OS.
+ //
+ // return FALSE Because no block devices on a system are implemented
+ // with INT 13h
+ //
+ return FALSE;
+ }
+
+ for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
+ if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {
+ continue;
+ }
+
+ NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
+ if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {
+ //
+ // This region overlaps with the Index1'th region
+ //
+ return FALSE;
+ }
+ }
+ }
+ //
+ // Non of the regions overlapped so MBR is O.K.
+ //
+ return MbrValid;
+}
+
+/**
+ This function finds Mbr partitions. Main algorithm
+ is ported from DXE partition driver.
+
+ @param[in] PrivateData The global memory map
+ @param[in] ParentBlockDevNo The parent block device
+
+ @retval TRUE New partitions are detected and logical block devices
+ are added to block device array
+ @retval FALSE No new partitions are added
+
+**/
+BOOLEAN
+FatFindMbrPartitions (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN ParentBlockDevNo
+ )
+{
+ EFI_STATUS Status;
+ MASTER_BOOT_RECORD *Mbr;
+ UINTN Index;
+ BOOLEAN Found;
+ PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
+ PEI_FAT_BLOCK_DEVICE *BlockDev;
+
+ if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
+ return FALSE;
+ }
+
+ ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
+
+ if (ParentBlockDev->BlockSize > PEI_FAT_MAX_BLOCK_SIZE) {
+ DEBUG((DEBUG_ERROR, "Device BlockSize %x exceeds FAT_MAX_BLOCK_SIZE\n", ParentBlockDev->BlockSize));
+ return FALSE;
+ }
+
+ Found = FALSE;
+ Mbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData;
+
+ Status = FatReadBlock (
+ PrivateData,
+ ParentBlockDevNo,
+ 0,
+ ParentBlockDev->BlockSize,
+ Mbr
+ );
+
+ if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {
+ goto Done;
+ }
+ //
+ // We have a valid mbr - add each partition
+ //
+ for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
+ if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
+ //
+ // Don't use null MBR entries
+ //
+ continue;
+ }
+ //
+ // Register this partition
+ //
+ if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
+
+ Found = TRUE;
+
+ BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
+
+ BlockDev->BlockSize = MBR_SIZE;
+ BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;
+ BlockDev->IoAlign = ParentBlockDev->IoAlign;
+ BlockDev->Logical = TRUE;
+ BlockDev->PartitionChecked = FALSE;
+ BlockDev->StartingPos = MultU64x32 (
+ UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),
+ ParentBlockDev->BlockSize
+ );
+ BlockDev->ParentDevNo = ParentBlockDevNo;
+
+ PrivateData->BlockDeviceCount++;
+ }
+ }
+
+Done:
+
+ ParentBlockDev->PartitionChecked = TRUE;
+ return Found;
+}