1 | /** @file
|
---|
2 | Routines supporting partition discovery and
|
---|
3 | logical device reading
|
---|
4 |
|
---|
5 | Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
|
---|
6 |
|
---|
7 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
8 |
|
---|
9 | **/
|
---|
10 |
|
---|
11 | #include <IndustryStandard/Mbr.h>
|
---|
12 | #include "FatLitePeim.h"
|
---|
13 |
|
---|
14 | /**
|
---|
15 | Test to see if the Mbr buffer is a valid MBR
|
---|
16 |
|
---|
17 | @param[in] Mbr Parent Handle
|
---|
18 | @param[in] LastLba Last Lba address on the device.
|
---|
19 |
|
---|
20 | @retval TRUE Mbr is a Valid MBR
|
---|
21 | @retval FALSE Mbr is not a Valid MBR
|
---|
22 |
|
---|
23 | **/
|
---|
24 | BOOLEAN
|
---|
25 | PartitionValidMbr (
|
---|
26 | IN MASTER_BOOT_RECORD *Mbr,
|
---|
27 | IN EFI_PEI_LBA LastLba
|
---|
28 | )
|
---|
29 | {
|
---|
30 | UINT32 StartingLBA;
|
---|
31 | UINT32 EndingLBA;
|
---|
32 | UINT32 NewEndingLBA;
|
---|
33 | INTN Index1;
|
---|
34 | INTN Index2;
|
---|
35 | BOOLEAN MbrValid;
|
---|
36 |
|
---|
37 | if (Mbr->Signature != MBR_SIGNATURE) {
|
---|
38 | return FALSE;
|
---|
39 | }
|
---|
40 |
|
---|
41 | //
|
---|
42 | // The BPB also has this signature, so it can not be used alone.
|
---|
43 | //
|
---|
44 | MbrValid = FALSE;
|
---|
45 | for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
|
---|
46 | if ((Mbr->Partition[Index1].OSIndicator == 0x00) || (UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0)) {
|
---|
47 | continue;
|
---|
48 | }
|
---|
49 |
|
---|
50 | MbrValid = TRUE;
|
---|
51 | StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
|
---|
52 | EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
|
---|
53 | if (EndingLBA > LastLba) {
|
---|
54 | //
|
---|
55 | // Compatibility Errata:
|
---|
56 | // Some systems try to hide drive space with their INT 13h driver
|
---|
57 | // This does not hide space from the OS driver. This means the MBR
|
---|
58 | // that gets created from DOS is smaller than the MBR created from
|
---|
59 | // a real OS (NT & Win98). This leads to BlockIo->LastBlock being
|
---|
60 | // wrong on some systems FDISKed by the OS.
|
---|
61 | //
|
---|
62 | // return FALSE Because no block devices on a system are implemented
|
---|
63 | // with INT 13h
|
---|
64 | //
|
---|
65 | return FALSE;
|
---|
66 | }
|
---|
67 |
|
---|
68 | for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
|
---|
69 | if ((Mbr->Partition[Index2].OSIndicator == 0x00) || (UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0)) {
|
---|
70 | continue;
|
---|
71 | }
|
---|
72 |
|
---|
73 | NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
|
---|
74 | if ((NewEndingLBA >= StartingLBA) && (UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA)) {
|
---|
75 | //
|
---|
76 | // This region overlaps with the Index1'th region
|
---|
77 | //
|
---|
78 | return FALSE;
|
---|
79 | }
|
---|
80 | }
|
---|
81 | }
|
---|
82 |
|
---|
83 | //
|
---|
84 | // Non of the regions overlapped so MBR is O.K.
|
---|
85 | //
|
---|
86 | return MbrValid;
|
---|
87 | }
|
---|
88 |
|
---|
89 | /**
|
---|
90 | This function finds Mbr partitions. Main algorithm
|
---|
91 | is ported from DXE partition driver.
|
---|
92 |
|
---|
93 | @param[in] PrivateData The global memory map
|
---|
94 | @param[in] ParentBlockDevNo The parent block device
|
---|
95 |
|
---|
96 | @retval TRUE New partitions are detected and logical block devices
|
---|
97 | are added to block device array
|
---|
98 | @retval FALSE No new partitions are added
|
---|
99 |
|
---|
100 | **/
|
---|
101 | BOOLEAN
|
---|
102 | FatFindMbrPartitions (
|
---|
103 | IN PEI_FAT_PRIVATE_DATA *PrivateData,
|
---|
104 | IN UINTN ParentBlockDevNo
|
---|
105 | )
|
---|
106 | {
|
---|
107 | EFI_STATUS Status;
|
---|
108 | MASTER_BOOT_RECORD *Mbr;
|
---|
109 | UINTN Index;
|
---|
110 | BOOLEAN Found;
|
---|
111 | PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
|
---|
112 | PEI_FAT_BLOCK_DEVICE *BlockDev;
|
---|
113 |
|
---|
114 | if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
|
---|
115 | return FALSE;
|
---|
116 | }
|
---|
117 |
|
---|
118 | ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
|
---|
119 |
|
---|
120 | if (ParentBlockDev->BlockSize > PEI_FAT_MAX_BLOCK_SIZE) {
|
---|
121 | DEBUG ((DEBUG_ERROR, "Device BlockSize %x exceeds FAT_MAX_BLOCK_SIZE\n", ParentBlockDev->BlockSize));
|
---|
122 | return FALSE;
|
---|
123 | }
|
---|
124 |
|
---|
125 | Found = FALSE;
|
---|
126 | Mbr = (MASTER_BOOT_RECORD *)PrivateData->BlockData;
|
---|
127 |
|
---|
128 | Status = FatReadBlock (
|
---|
129 | PrivateData,
|
---|
130 | ParentBlockDevNo,
|
---|
131 | 0,
|
---|
132 | ParentBlockDev->BlockSize,
|
---|
133 | Mbr
|
---|
134 | );
|
---|
135 |
|
---|
136 | if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {
|
---|
137 | goto Done;
|
---|
138 | }
|
---|
139 |
|
---|
140 | //
|
---|
141 | // We have a valid mbr - add each partition
|
---|
142 | //
|
---|
143 | for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
|
---|
144 | if ((Mbr->Partition[Index].OSIndicator == 0x00) || (UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0)) {
|
---|
145 | //
|
---|
146 | // Don't use null MBR entries
|
---|
147 | //
|
---|
148 | continue;
|
---|
149 | }
|
---|
150 |
|
---|
151 | //
|
---|
152 | // Register this partition
|
---|
153 | //
|
---|
154 | if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
|
---|
155 | Found = TRUE;
|
---|
156 |
|
---|
157 | BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
|
---|
158 |
|
---|
159 | BlockDev->BlockSize = MBR_SIZE;
|
---|
160 | BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;
|
---|
161 | BlockDev->IoAlign = ParentBlockDev->IoAlign;
|
---|
162 | BlockDev->Logical = TRUE;
|
---|
163 | BlockDev->PartitionChecked = FALSE;
|
---|
164 | BlockDev->StartingPos = MultU64x32 (
|
---|
165 | UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),
|
---|
166 | ParentBlockDev->BlockSize
|
---|
167 | );
|
---|
168 | BlockDev->ParentDevNo = ParentBlockDevNo;
|
---|
169 |
|
---|
170 | PrivateData->BlockDeviceCount++;
|
---|
171 | }
|
---|
172 | }
|
---|
173 |
|
---|
174 | Done:
|
---|
175 |
|
---|
176 | ParentBlockDev->PartitionChecked = TRUE;
|
---|
177 | return Found;
|
---|
178 | }
|
---|