Mbr.c 5.2 KB

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