2 Routines supporting partition discovery and
5 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <IndustryStandard/Mbr.h>
12 #include "FatLitePeim.h"
15 Test to see if the Mbr buffer is a valid MBR
17 @param[in] Mbr Parent Handle
18 @param[in] LastLba Last Lba address on the device.
20 @retval TRUE Mbr is a Valid MBR
21 @retval FALSE Mbr is not a Valid MBR
26 IN MASTER_BOOT_RECORD
*Mbr
,
27 IN EFI_PEI_LBA LastLba
37 if (Mbr
->Signature
!= MBR_SIGNATURE
) {
41 // The BPB also has this signature, so it can not be used alone.
44 for (Index1
= 0; Index1
< MAX_MBR_PARTITIONS
; Index1
++) {
45 if (Mbr
->Partition
[Index1
].OSIndicator
== 0x00 || UNPACK_UINT32 (Mbr
->Partition
[Index1
].SizeInLBA
) == 0) {
50 StartingLBA
= UNPACK_UINT32 (Mbr
->Partition
[Index1
].StartingLBA
);
51 EndingLBA
= StartingLBA
+ UNPACK_UINT32 (Mbr
->Partition
[Index1
].SizeInLBA
) - 1;
52 if (EndingLBA
> LastLba
) {
54 // Compatability Errata:
55 // Some systems try to hide drive space with their INT 13h driver
56 // This does not hide space from the OS driver. This means the MBR
57 // that gets created from DOS is smaller than the MBR created from
58 // a real OS (NT & Win98). This leads to BlockIo->LastBlock being
59 // wrong on some systems FDISKed by the OS.
61 // return FALSE Because no block devices on a system are implemented
67 for (Index2
= Index1
+ 1; Index2
< MAX_MBR_PARTITIONS
; Index2
++) {
68 if (Mbr
->Partition
[Index2
].OSIndicator
== 0x00 || UNPACK_INT32 (Mbr
->Partition
[Index2
].SizeInLBA
) == 0) {
72 NewEndingLBA
= UNPACK_UINT32 (Mbr
->Partition
[Index2
].StartingLBA
) + UNPACK_UINT32 (Mbr
->Partition
[Index2
].SizeInLBA
) - 1;
73 if (NewEndingLBA
>= StartingLBA
&& UNPACK_UINT32 (Mbr
->Partition
[Index2
].StartingLBA
) <= EndingLBA
) {
75 // This region overlaps with the Index1'th region
82 // Non of the regions overlapped so MBR is O.K.
88 This function finds Mbr partitions. Main algorithm
89 is ported from DXE partition driver.
91 @param[in] PrivateData The global memory map
92 @param[in] ParentBlockDevNo The parent block device
94 @retval TRUE New partitions are detected and logical block devices
95 are added to block device array
96 @retval FALSE No new partitions are added
100 FatFindMbrPartitions (
101 IN PEI_FAT_PRIVATE_DATA
*PrivateData
,
102 IN UINTN ParentBlockDevNo
106 MASTER_BOOT_RECORD
*Mbr
;
109 PEI_FAT_BLOCK_DEVICE
*ParentBlockDev
;
110 PEI_FAT_BLOCK_DEVICE
*BlockDev
;
112 if (ParentBlockDevNo
> PEI_FAT_MAX_BLOCK_DEVICE
- 1) {
116 ParentBlockDev
= &(PrivateData
->BlockDevice
[ParentBlockDevNo
]);
118 if (ParentBlockDev
->BlockSize
> PEI_FAT_MAX_BLOCK_SIZE
) {
119 DEBUG((DEBUG_ERROR
, "Device BlockSize %x exceeds FAT_MAX_BLOCK_SIZE\n", ParentBlockDev
->BlockSize
));
124 Mbr
= (MASTER_BOOT_RECORD
*) PrivateData
->BlockData
;
126 Status
= FatReadBlock (
130 ParentBlockDev
->BlockSize
,
134 if (EFI_ERROR (Status
) || !PartitionValidMbr (Mbr
, ParentBlockDev
->LastBlock
)) {
138 // We have a valid mbr - add each partition
140 for (Index
= 0; Index
< MAX_MBR_PARTITIONS
; Index
++) {
141 if (Mbr
->Partition
[Index
].OSIndicator
== 0x00 || UNPACK_INT32 (Mbr
->Partition
[Index
].SizeInLBA
) == 0) {
143 // Don't use null MBR entries
148 // Register this partition
150 if (PrivateData
->BlockDeviceCount
< PEI_FAT_MAX_BLOCK_DEVICE
) {
154 BlockDev
= &(PrivateData
->BlockDevice
[PrivateData
->BlockDeviceCount
]);
156 BlockDev
->BlockSize
= MBR_SIZE
;
157 BlockDev
->LastBlock
= UNPACK_INT32 (Mbr
->Partition
[Index
].SizeInLBA
) - 1;
158 BlockDev
->IoAlign
= ParentBlockDev
->IoAlign
;
159 BlockDev
->Logical
= TRUE
;
160 BlockDev
->PartitionChecked
= FALSE
;
161 BlockDev
->StartingPos
= MultU64x32 (
162 UNPACK_INT32 (Mbr
->Partition
[Index
].StartingLBA
),
163 ParentBlockDev
->BlockSize
165 BlockDev
->ParentDevNo
= ParentBlockDevNo
;
167 PrivateData
->BlockDeviceCount
++;
173 ParentBlockDev
->PartitionChecked
= TRUE
;