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
78 VolDescriptorLba
+= 1;
79 if (VolDescriptorLba
> ParentBlockDev
->LastBlock
) {
81 // We are pointing past the end of the device so exit
86 Status
= FatReadBlock (
90 ParentBlockDev
->BlockSize
,
93 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
103 // end of Volume descriptor list
108 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
110 if (VolDescriptor
->Unknown
.Type
== CDVOL_TYPE_CODED
) {
111 VolSpaceSize
= VolDescriptor
->PrimaryVolume
.VolSpaceSize
[1];
114 // Is it an El Torito volume descriptor?
117 VolDescriptor
->BootRecordVolume
.SystemId
,
119 sizeof (CDVOL_ELTORITO_ID
) - 1
124 // Read in the boot El Torito boot catalog
126 Lba
= UNPACK_INT32 (VolDescriptor
->BootRecordVolume
.EltCatalog
);
127 if (Lba
> ParentBlockDev
->LastBlock
) {
131 Status
= FatReadBlock (
135 ParentBlockDev
->BlockSize
,
138 if (EFI_ERROR (Status
)) {
142 // We don't care too much about the Catalog header's contents, but we do want
143 // to make sure it looks like a Catalog header
145 if (Catalog
->Catalog
.Indicator
!= ELTORITO_ID_CATALOG
|| Catalog
->Catalog
.Id55AA
!= 0xAA55) {
150 CheckBuffer
= (UINT16
*) Catalog
;
151 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
152 Check
+= CheckBuffer
[Index
];
155 if ((Check
& 0xFFFF) != 0) {
159 MaxIndex
= ParentBlockDev
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
160 for (Index
= 1; Index
< MaxIndex
; Index
+= 1) {
169 if (Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
|| Catalog
->Boot
.Lba
== 0) {
174 SectorCount
= Catalog
->Boot
.SectorCount
;
176 switch (Catalog
->Boot
.MediaType
) {
178 case ELTORITO_NO_EMULATION
:
179 SubBlockSize
= ParentBlockDev
->BlockSize
;
180 SectorCount
= Catalog
->Boot
.SectorCount
;
183 case ELTORITO_HARD_DISK
:
186 case ELTORITO_12_DISKETTE
:
187 SectorCount
= 0x50 * 0x02 * 0x0F;
190 case ELTORITO_14_DISKETTE
:
191 SectorCount
= 0x50 * 0x02 * 0x12;
194 case ELTORITO_28_DISKETTE
:
195 SectorCount
= 0x50 * 0x02 * 0x24;
200 SubBlockSize
= ParentBlockDev
->BlockSize
;
204 if (SectorCount
< 2) {
205 SectorCount
= (VolSpaceSize
> ParentBlockDev
->LastBlock
+ 1) ? (UINT32
) (ParentBlockDev
->LastBlock
- Catalog
->Boot
.Lba
+ 1) : (UINT32
) (VolSpaceSize
- Catalog
->Boot
.Lba
);
208 // Register this partition
210 if (PrivateData
->BlockDeviceCount
< PEI_FAT_MAX_BLOCK_DEVICE
) {
214 BlockDev
= &(PrivateData
->BlockDevice
[PrivateData
->BlockDeviceCount
]);
216 BlockDev
->BlockSize
= SubBlockSize
;
217 BlockDev
->LastBlock
= SectorCount
- 1;
218 BlockDev
->IoAlign
= ParentBlockDev
->IoAlign
;
219 BlockDev
->Logical
= TRUE
;
220 BlockDev
->PartitionChecked
= FALSE
;
221 BlockDev
->StartingPos
= MultU64x32 (Catalog
->Boot
.Lba
, ParentBlockDev
->BlockSize
);
222 BlockDev
->ParentDevNo
= ParentBlockDevNo
;
224 PrivateData
->BlockDeviceCount
++;
229 ParentBlockDev
->PartitionChecked
= TRUE
;