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/ElTorito.h>
12 #include "FatLitePeim.h"
15 This function finds Eltorito partitions. Main algorithm
16 is ported from DXE partition driver.
18 @param[in] PrivateData The global memory map
19 @param[in] ParentBlockDevNo The parent block device
21 @retval TRUE New partitions are detected and logical block devices
22 are added to block device array
23 @retval FALSE No new partitions are added
27 FatFindEltoritoPartitions (
28 IN PEI_FAT_PRIVATE_DATA
*PrivateData
,
29 IN UINTN ParentBlockDevNo
34 PEI_FAT_BLOCK_DEVICE
*BlockDev
;
35 PEI_FAT_BLOCK_DEVICE
*ParentBlockDev
;
36 UINT32 VolDescriptorLba
;
38 CDROM_VOLUME_DESCRIPTOR
*VolDescriptor
;
39 ELTORITO_CATALOG
*Catalog
;
48 if (ParentBlockDevNo
> PEI_FAT_MAX_BLOCK_DEVICE
- 1) {
53 ParentBlockDev
= &(PrivateData
->BlockDevice
[ParentBlockDevNo
]);
57 // CD_ROM has the fixed block size as 2048 bytes
59 if (ParentBlockDev
->BlockSize
!= 2048) {
63 VolDescriptor
= (CDROM_VOLUME_DESCRIPTOR
*)PrivateData
->BlockData
;
64 Catalog
= (ELTORITO_CATALOG
*)VolDescriptor
;
67 // the ISO-9660 volume descriptor starts at 32k on the media
68 // and CD_ROM has the fixed block size as 2048 bytes, so...
70 VolDescriptorLba
= 15;
72 // ((16*2048) / Media->BlockSize) - 1;
74 // Loop: handle one volume descriptor per time
77 VolDescriptorLba
+= 1;
78 if (VolDescriptorLba
> ParentBlockDev
->LastBlock
) {
80 // We are pointing past the end of the device so exit
85 Status
= FatReadBlock (
89 ParentBlockDev
->BlockSize
,
92 if (EFI_ERROR (Status
)) {
97 // Check for valid volume descriptor signature
99 if ((VolDescriptor
->Unknown
.Type
== CDVOL_TYPE_END
) ||
100 (CompareMem (VolDescriptor
->Unknown
.Id
, CDVOL_ID
, sizeof (VolDescriptor
->Unknown
.Id
)) != 0)
104 // end of Volume descriptor list
110 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
112 if (VolDescriptor
->Unknown
.Type
== CDVOL_TYPE_CODED
) {
113 VolSpaceSize
= VolDescriptor
->PrimaryVolume
.VolSpaceSize
[1];
117 // Is it an El Torito volume descriptor?
120 VolDescriptor
->BootRecordVolume
.SystemId
,
122 sizeof (CDVOL_ELTORITO_ID
) - 1
129 // Read in the boot El Torito boot catalog
131 Lba
= UNPACK_INT32 (VolDescriptor
->BootRecordVolume
.EltCatalog
);
132 if (Lba
> ParentBlockDev
->LastBlock
) {
136 Status
= FatReadBlock (
140 ParentBlockDev
->BlockSize
,
143 if (EFI_ERROR (Status
)) {
148 // We don't care too much about the Catalog header's contents, but we do want
149 // to make sure it looks like a Catalog header
151 if ((Catalog
->Catalog
.Indicator
!= ELTORITO_ID_CATALOG
) || (Catalog
->Catalog
.Id55AA
!= 0xAA55)) {
156 CheckBuffer
= (UINT16
*)Catalog
;
157 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
158 Check
+= CheckBuffer
[Index
];
161 if ((Check
& 0xFFFF) != 0) {
165 MaxIndex
= ParentBlockDev
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
166 for (Index
= 1; Index
< MaxIndex
; Index
+= 1) {
175 if ((Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
) || (Catalog
->Boot
.Lba
== 0)) {
180 SectorCount
= Catalog
->Boot
.SectorCount
;
182 switch (Catalog
->Boot
.MediaType
) {
183 case ELTORITO_NO_EMULATION
:
184 SubBlockSize
= ParentBlockDev
->BlockSize
;
185 SectorCount
= Catalog
->Boot
.SectorCount
;
188 case ELTORITO_HARD_DISK
:
191 case ELTORITO_12_DISKETTE
:
192 SectorCount
= 0x50 * 0x02 * 0x0F;
195 case ELTORITO_14_DISKETTE
:
196 SectorCount
= 0x50 * 0x02 * 0x12;
199 case ELTORITO_28_DISKETTE
:
200 SectorCount
= 0x50 * 0x02 * 0x24;
205 SubBlockSize
= ParentBlockDev
->BlockSize
;
209 if (SectorCount
< 2) {
210 SectorCount
= (VolSpaceSize
> ParentBlockDev
->LastBlock
+ 1) ? (UINT32
)(ParentBlockDev
->LastBlock
- Catalog
->Boot
.Lba
+ 1) : (UINT32
)(VolSpaceSize
- Catalog
->Boot
.Lba
);
214 // Register this partition
216 if (PrivateData
->BlockDeviceCount
< PEI_FAT_MAX_BLOCK_DEVICE
) {
219 BlockDev
= &(PrivateData
->BlockDevice
[PrivateData
->BlockDeviceCount
]);
221 BlockDev
->BlockSize
= SubBlockSize
;
222 BlockDev
->LastBlock
= SectorCount
- 1;
223 BlockDev
->IoAlign
= ParentBlockDev
->IoAlign
;
224 BlockDev
->Logical
= TRUE
;
225 BlockDev
->PartitionChecked
= FALSE
;
226 BlockDev
->StartingPos
= MultU64x32 (Catalog
->Boot
.Lba
, ParentBlockDev
->BlockSize
);
227 BlockDev
->ParentDevNo
= ParentBlockDevNo
;
229 PrivateData
->BlockDeviceCount
++;
234 ParentBlockDev
->PartitionChecked
= TRUE
;