2 Routines supporting partition discovery and
5 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials are licensed and made available
8 under the terms and conditions of the BSD License which accompanies this
9 distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <IndustryStandard/ElTorito.h>
18 #include "FatLitePeim.h"
21 This function finds Eltorito partitions. Main algorithm
22 is ported from DXE partition driver.
24 @param[in] PrivateData The global memory map
25 @param[in] ParentBlockDevNo The parent block device
27 @retval TRUE New partitions are detected and logical block devices
28 are added to block device array
29 @retval FALSE No new partitions are added
33 FatFindEltoritoPartitions (
34 IN PEI_FAT_PRIVATE_DATA
*PrivateData
,
35 IN UINTN ParentBlockDevNo
40 PEI_FAT_BLOCK_DEVICE
*BlockDev
;
41 PEI_FAT_BLOCK_DEVICE
*ParentBlockDev
;
42 UINT32 VolDescriptorLba
;
44 CDROM_VOLUME_DESCRIPTOR
*VolDescriptor
;
45 ELTORITO_CATALOG
*Catalog
;
54 if (ParentBlockDevNo
> PEI_FAT_MAX_BLOCK_DEVICE
- 1) {
59 ParentBlockDev
= &(PrivateData
->BlockDevice
[ParentBlockDevNo
]);
63 // CD_ROM has the fixed block size as 2048 bytes
65 if (ParentBlockDev
->BlockSize
!= 2048) {
69 VolDescriptor
= (CDROM_VOLUME_DESCRIPTOR
*) PrivateData
->BlockData
;
70 Catalog
= (ELTORITO_CATALOG
*) VolDescriptor
;
73 // the ISO-9660 volume descriptor starts at 32k on the media
74 // and CD_ROM has the fixed block size as 2048 bytes, so...
76 VolDescriptorLba
= 15;
78 // ((16*2048) / Media->BlockSize) - 1;
80 // Loop: handle one volume descriptor per time
84 VolDescriptorLba
+= 1;
85 if (VolDescriptorLba
> ParentBlockDev
->LastBlock
) {
87 // We are pointing past the end of the device so exit
92 Status
= FatReadBlock (
96 ParentBlockDev
->BlockSize
,
99 if (EFI_ERROR (Status
)) {
103 // Check for valid volume descriptor signature
105 if (VolDescriptor
->Unknown
.Type
== CDVOL_TYPE_END
||
106 CompareMem (VolDescriptor
->Unknown
.Id
, CDVOL_ID
, sizeof (VolDescriptor
->Unknown
.Id
)) != 0
109 // end of Volume descriptor list
114 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
116 if (VolDescriptor
->Unknown
.Type
== CDVOL_TYPE_CODED
) {
117 VolSpaceSize
= VolDescriptor
->PrimaryVolume
.VolSpaceSize
[1];
120 // Is it an El Torito volume descriptor?
123 VolDescriptor
->BootRecordVolume
.SystemId
,
125 sizeof (CDVOL_ELTORITO_ID
) - 1
130 // Read in the boot El Torito boot catalog
132 Lba
= UNPACK_INT32 (VolDescriptor
->BootRecordVolume
.EltCatalog
);
133 if (Lba
> ParentBlockDev
->LastBlock
) {
137 Status
= FatReadBlock (
141 ParentBlockDev
->BlockSize
,
144 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
) {
184 case ELTORITO_NO_EMULATION
:
185 SubBlockSize
= ParentBlockDev
->BlockSize
;
186 SectorCount
= Catalog
->Boot
.SectorCount
;
189 case ELTORITO_HARD_DISK
:
192 case ELTORITO_12_DISKETTE
:
193 SectorCount
= 0x50 * 0x02 * 0x0F;
196 case ELTORITO_14_DISKETTE
:
197 SectorCount
= 0x50 * 0x02 * 0x12;
200 case ELTORITO_28_DISKETTE
:
201 SectorCount
= 0x50 * 0x02 * 0x24;
206 SubBlockSize
= ParentBlockDev
->BlockSize
;
210 if (SectorCount
< 2) {
211 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
) {
220 BlockDev
= &(PrivateData
->BlockDevice
[PrivateData
->BlockDeviceCount
]);
222 BlockDev
->BlockSize
= SubBlockSize
;
223 BlockDev
->LastBlock
= SectorCount
- 1;
224 BlockDev
->IoAlign
= ParentBlockDev
->IoAlign
;
225 BlockDev
->Logical
= TRUE
;
226 BlockDev
->PartitionChecked
= FALSE
;
227 BlockDev
->StartingPos
= MultU64x32 (Catalog
->Boot
.Lba
, ParentBlockDev
->BlockSize
);
228 BlockDev
->ParentDevNo
= ParentBlockDevNo
;
230 PrivateData
->BlockDeviceCount
++;
235 ParentBlockDev
->PartitionChecked
= TRUE
;