OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
Mbr.c
Go to the documentation of this file.
1
21#include "Partition.h"
22
33BOOLEAN
35 IN MASTER_BOOT_RECORD *Mbr,
36 IN EFI_LBA LastLba
37 )
38{
39 UINT32 StartingLBA;
40 UINT32 EndingLBA;
41 UINT32 NewEndingLBA;
42 INTN Index1;
43 INTN Index2;
44 BOOLEAN MbrValid;
45
46 if (Mbr->Signature != MBR_SIGNATURE) {
47 return FALSE;
48 }
49
50 //
51 // The BPB also has this signature, so it can not be used alone.
52 //
53 MbrValid = FALSE;
54 for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
55 if ((Mbr->Partition[Index1].OSIndicator == 0x00) || (UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0)) {
56 continue;
57 }
58
59 MbrValid = TRUE;
60 StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
61 EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
62 if (EndingLBA > LastLba) {
63 //
64 // Compatibility Errata:
65 // Some systems try to hide drive space with their INT 13h driver
66 // This does not hide space from the OS driver. This means the MBR
67 // that gets created from DOS is smaller than the MBR created from
68 // a real OS (NT & Win98). This leads to BlockIo->LastBlock being
69 // wrong on some systems FDISKed by the OS.
70 //
71 // return FALSE since no block devices on a system are implemented
72 // with INT 13h
73 //
74
75 DEBUG ((EFI_D_INFO, "PartitionValidMbr: Bad MBR partition size EndingLBA(%1x) > LastLBA(%1x)\n", EndingLBA, LastLba));
76
77 return FALSE;
78 }
79
80 for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
81 if ((Mbr->Partition[Index2].OSIndicator == 0x00) || (UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) == 0)) {
82 continue;
83 }
84
85 NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
86 if ((NewEndingLBA >= StartingLBA) && (UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA)) {
87 //
88 // This region overlaps with the Index1'th region
89 //
90 return FALSE;
91 }
92 }
93 }
94
95 //
96 // None of the regions overlapped so MBR is O.K.
97 //
98 return MbrValid;
99}
100
117EFI_STATUS
119 IN EFI_DRIVER_BINDING_PROTOCOL *This,
120 IN EFI_HANDLE Handle,
121 IN EFI_DISK_IO_PROTOCOL *DiskIo,
122 IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
123 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
124 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
125 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
126 )
127{
128 EFI_STATUS Status;
129 MASTER_BOOT_RECORD *Mbr;
130 UINT32 ExtMbrStartingLba;
131 UINT32 Index;
132 HARDDRIVE_DEVICE_PATH HdDev;
133 HARDDRIVE_DEVICE_PATH ParentHdDev;
134 EFI_STATUS Found;
135 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
136 EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
137 UINT32 BlockSize;
138 UINT32 MediaId;
139 EFI_LBA LastSector;
140 EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
141 APPLE_PARTITION_INFO_PROTOCOL ApplePartitionInfo;
142
143 Found = EFI_NOT_FOUND;
144
145 BlockSize = BlockIo->Media->BlockSize;
146 MediaId = BlockIo->Media->MediaId;
147 LastSector = DivU64x32 (
148 MultU64x32 (BlockIo->Media->LastBlock + 1, BlockSize),
149 MBR_SIZE
150 ) - 1;
151
152 //
153 // Ensure the block size can hold the MBR
154 //
155 if (BlockSize < sizeof (MASTER_BOOT_RECORD)) {
156 return EFI_NOT_FOUND;
157 }
158
159 Mbr = AllocatePool (BlockSize);
160 if (Mbr == NULL) {
161 return Found;
162 }
163
164 Status = DiskIo->ReadDisk (
165 DiskIo,
166 MediaId,
167 0,
168 BlockSize,
169 Mbr
170 );
171 if (EFI_ERROR (Status)) {
172 Found = Status;
173 goto Done;
174 }
175
176 if (!PartitionValidMbr (Mbr, LastSector)) {
177 goto Done;
178 }
179
180 //
181 // We have a valid mbr - add each partition
182 //
183 //
184 // Get starting and ending LBA of the parent block device.
185 //
186 LastDevicePathNode = NULL;
187 ZeroMem (&ParentHdDev, sizeof (ParentHdDev));
188 DevicePathNode = DevicePath;
189 while (!IsDevicePathEnd (DevicePathNode)) {
190 LastDevicePathNode = DevicePathNode;
191 DevicePathNode = NextDevicePathNode (DevicePathNode);
192 }
193
194 if (LastDevicePathNode != NULL) {
195 if ((DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH) &&
196 (DevicePathSubType (LastDevicePathNode) == MEDIA_HARDDRIVE_DP)
197 )
198 {
199 CopyMem (&ParentHdDev, LastDevicePathNode, sizeof (ParentHdDev));
200 } else {
201 LastDevicePathNode = NULL;
202 }
203 }
204
205 ZeroMem (&HdDev, sizeof (HdDev));
206 HdDev.Header.Type = MEDIA_DEVICE_PATH;
207 HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;
208 SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));
209 HdDev.MBRType = MBR_TYPE_PCAT;
210 HdDev.SignatureType = SIGNATURE_TYPE_MBR;
211
212 if (LastDevicePathNode == NULL) {
213 //
214 // This is a MBR, add each partition
215 //
216 for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
217 if ((Mbr->Partition[Index].OSIndicator == 0x00) || (UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA) == 0)) {
218 //
219 // Don't use null MBR entries
220 //
221 continue;
222 }
223
224 if (Mbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION) {
225 //
226 // This is the guard MBR for the GPT. If you ever see a GPT disk with zero partitions you can get here.
227 // We can not produce an MBR BlockIo for this device as the MBR spans the GPT headers. So formating
228 // this BlockIo would corrupt the GPT structures and require a recovery that would corrupt the format
229 // that corrupted the GPT partition.
230 //
231 continue;
232 }
233
234 HdDev.PartitionNumber = Index + 1;
235 HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[Index].StartingLBA);
236 HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA);
237 CopyMem (HdDev.Signature, &(Mbr->UniqueMbrSignature[0]), sizeof (Mbr->UniqueMbrSignature));
238
239 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
240 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
241 PartitionInfo.Type = PARTITION_TYPE_MBR;
242 if (Mbr->Partition[Index].OSIndicator == EFI_PARTITION) {
243 PartitionInfo.System = 1;
244 }
245
246 CopyMem (&PartitionInfo.Info.Mbr, &Mbr->Partition[Index], sizeof (MBR_PARTITION_RECORD));
247
248 ZeroMem (&ApplePartitionInfo, sizeof (APPLE_PARTITION_INFO_PROTOCOL));
249 ApplePartitionInfo.Revision = APPLE_PARTITION_INFO_REVISION;
250 ApplePartitionInfo.MBRType = HdDev.MBRType;
251 ApplePartitionInfo.SignatureType = HdDev.SignatureType;
252 ApplePartitionInfo.PartitionNumber = HdDev.PartitionNumber;
253 ApplePartitionInfo.PartitionStart = HdDev.PartitionStart;
254 ApplePartitionInfo.PartitionSize = HdDev.PartitionSize;
255 CopyMem (&ApplePartitionInfo.Signature, &(HdDev.Signature[0]), sizeof (UINT32));
256 CopyMem (&ApplePartitionInfo.PartitionType, &Mbr->Partition[Index].OSIndicator, sizeof (UINT8));
257
259 This,
260 Handle,
261 DiskIo,
262 DiskIo2,
263 BlockIo,
264 BlockIo2,
265 DevicePath,
266 (EFI_DEVICE_PATH_PROTOCOL *)&HdDev,
267 &PartitionInfo,
268 &ApplePartitionInfo,
269 HdDev.PartitionStart,
270 HdDev.PartitionStart + HdDev.PartitionSize - 1,
271 MBR_SIZE,
272 ((Mbr->Partition[Index].OSIndicator == EFI_PARTITION) ? &gEfiPartTypeSystemPartGuid : NULL)
273 );
274
275 if (!EFI_ERROR (Status)) {
276 Found = EFI_SUCCESS;
277 }
278 }
279 } else {
280 //
281 // It's an extended partition. Follow the extended partition
282 // chain to get all the logical drives
283 //
284 Index = 0;
285 ExtMbrStartingLba = 0;
286
287 do {
288 Status = DiskIo->ReadDisk (
289 DiskIo,
290 MediaId,
291 MultU64x32 (ExtMbrStartingLba, BlockSize),
292 BlockSize,
293 Mbr
294 );
295 if (EFI_ERROR (Status)) {
296 Found = Status;
297 goto Done;
298 }
299
300 if (UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA) == 0) {
301 break;
302 }
303
304 if ((Mbr->Partition[0].OSIndicator == EXTENDED_DOS_PARTITION) ||
305 (Mbr->Partition[0].OSIndicator == EXTENDED_WINDOWS_PARTITION))
306 {
307 ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA);
308 continue;
309 }
310
311 HdDev.PartitionNumber = ++Index;
312 HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA) + ExtMbrStartingLba + ParentHdDev.PartitionStart;
313 HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA);
314 if ((HdDev.PartitionStart + HdDev.PartitionSize - 1 >= ParentHdDev.PartitionStart + ParentHdDev.PartitionSize) ||
315 (HdDev.PartitionStart <= ParentHdDev.PartitionStart))
316 {
317 break;
318 }
319
320 //
321 // The signature in EBR(Extended Boot Record) should always be 0.
322 //
323 *((UINT32 *)&HdDev.Signature[0]) = 0;
324
325 ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
326 PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
327 PartitionInfo.Type = PARTITION_TYPE_MBR;
328 if (Mbr->Partition[0].OSIndicator == EFI_PARTITION) {
329 PartitionInfo.System = 1;
330 }
331
332 CopyMem (&PartitionInfo.Info.Mbr, &Mbr->Partition[0], sizeof (MBR_PARTITION_RECORD));
333
334 ZeroMem (&ApplePartitionInfo, sizeof (APPLE_PARTITION_INFO_PROTOCOL));
335 ApplePartitionInfo.Revision = APPLE_PARTITION_INFO_REVISION;
336 ApplePartitionInfo.MBRType = HdDev.MBRType;
337 ApplePartitionInfo.SignatureType = HdDev.SignatureType;
338 ApplePartitionInfo.PartitionNumber = HdDev.PartitionNumber;
339 ApplePartitionInfo.PartitionStart = HdDev.PartitionStart;
340 ApplePartitionInfo.PartitionSize = HdDev.PartitionSize;
341 CopyMem (&ApplePartitionInfo.Signature, &(HdDev.Signature[0]), sizeof (UINT32));
342 CopyMem (&ApplePartitionInfo.PartitionType, &Mbr->Partition[0].OSIndicator, sizeof (UINT8));
343
345 This,
346 Handle,
347 DiskIo,
348 DiskIo2,
349 BlockIo,
350 BlockIo2,
351 DevicePath,
352 (EFI_DEVICE_PATH_PROTOCOL *)&HdDev,
353 &PartitionInfo,
354 &ApplePartitionInfo,
355 HdDev.PartitionStart - ParentHdDev.PartitionStart,
356 HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1,
357 MBR_SIZE,
358 ((Mbr->Partition[0].OSIndicator == EFI_PARTITION) ? &gEfiPartTypeSystemPartGuid : NULL)
359 );
360 if (!EFI_ERROR (Status)) {
361 Found = EFI_SUCCESS;
362 }
363
364 if ((Mbr->Partition[1].OSIndicator != EXTENDED_DOS_PARTITION) &&
365 (Mbr->Partition[1].OSIndicator != EXTENDED_WINDOWS_PARTITION)
366 )
367 {
368 break;
369 }
370
371 ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[1].StartingLBA);
372 //
373 // Don't allow partition to be self referencing
374 //
375 if (ExtMbrStartingLba == 0) {
376 break;
377 }
378 } while (ExtMbrStartingLba < ParentHdDev.PartitionSize);
379 }
380
381Done:
382 FreePool (Mbr);
383
384 return Found;
385}
UINT16 BlockSize
Definition Apm.h:32
#define APPLE_PARTITION_INFO_REVISION
BOOLEAN PartitionValidMbr(IN MASTER_BOOT_RECORD *Mbr, IN EFI_LBA LastLba)
Definition Mbr.c:34
EFI_STATUS PartitionInstallMbrChildHandles(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)
Definition Mbr.c:118
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
EFI_STATUS PartitionInstallChildHandle(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ParentHandle, IN EFI_DISK_IO_PROTOCOL *ParentDiskIo, IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2, IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo, IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, IN EFI_PARTITION_INFO_PROTOCOL *PartitionInfo, IN APPLE_PARTITION_INFO_PROTOCOL *ApplePartitionInfo, IN EFI_LBA Start, IN EFI_LBA End, IN UINT32 BlockSize, IN EFI_GUID *TypeGuid)
Definition Partition.c:1140
#define UNPACK_UINT32(a)
Definition Partition.h:96
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition UserMath.c:96
#define DivU64x32(x, y, z)