]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/FatPei/Eltorito.c
MdeModulePkg/SdMmcPciHcDxe: Use 16/32-bit IO widths
[mirror_edk2.git] / FatPkg / FatPei / Eltorito.c
1 /** @file
2 Routines supporting partition discovery and
3 logical device reading
4
5 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
6
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
11
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.
14
15 **/
16
17 #include <IndustryStandard/ElTorito.h>
18 #include "FatLitePeim.h"
19
20 /**
21 This function finds Eltorito partitions. Main algorithm
22 is ported from DXE partition driver.
23
24 @param[in] PrivateData The global memory map
25 @param[in] ParentBlockDevNo The parent block device
26
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
30
31 **/
32 BOOLEAN
33 FatFindEltoritoPartitions (
34 IN PEI_FAT_PRIVATE_DATA *PrivateData,
35 IN UINTN ParentBlockDevNo
36 )
37 {
38 EFI_STATUS Status;
39 BOOLEAN Found;
40 PEI_FAT_BLOCK_DEVICE *BlockDev;
41 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;
42 UINT32 VolDescriptorLba;
43 UINT32 Lba;
44 CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
45 ELTORITO_CATALOG *Catalog;
46 UINTN Check;
47 UINTN Index;
48 UINTN MaxIndex;
49 UINT16 *CheckBuffer;
50 UINT32 SubBlockSize;
51 UINT32 SectorCount;
52 UINT32 VolSpaceSize;
53
54 if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
55 return FALSE;
56 }
57
58 Found = FALSE;
59 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);
60 VolSpaceSize = 0;
61
62 //
63 // CD_ROM has the fixed block size as 2048 bytes
64 //
65 if (ParentBlockDev->BlockSize != 2048) {
66 return FALSE;
67 }
68
69 VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;
70 Catalog = (ELTORITO_CATALOG *) VolDescriptor;
71
72 //
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...
75 //
76 VolDescriptorLba = 15;
77 //
78 // ((16*2048) / Media->BlockSize) - 1;
79 //
80 // Loop: handle one volume descriptor per time
81 //
82 while (TRUE) {
83
84 VolDescriptorLba += 1;
85 if (VolDescriptorLba > ParentBlockDev->LastBlock) {
86 //
87 // We are pointing past the end of the device so exit
88 //
89 break;
90 }
91
92 Status = FatReadBlock (
93 PrivateData,
94 ParentBlockDevNo,
95 VolDescriptorLba,
96 ParentBlockDev->BlockSize,
97 VolDescriptor
98 );
99 if (EFI_ERROR (Status)) {
100 break;
101 }
102 //
103 // Check for valid volume descriptor signature
104 //
105 if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
106 CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
107 ) {
108 //
109 // end of Volume descriptor list
110 //
111 break;
112 }
113 //
114 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
115 //
116 if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {
117 VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];
118 }
119 //
120 // Is it an El Torito volume descriptor?
121 //
122 if (CompareMem (
123 VolDescriptor->BootRecordVolume.SystemId,
124 CDVOL_ELTORITO_ID,
125 sizeof (CDVOL_ELTORITO_ID) - 1
126 ) != 0) {
127 continue;
128 }
129 //
130 // Read in the boot El Torito boot catalog
131 //
132 Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
133 if (Lba > ParentBlockDev->LastBlock) {
134 continue;
135 }
136
137 Status = FatReadBlock (
138 PrivateData,
139 ParentBlockDevNo,
140 Lba,
141 ParentBlockDev->BlockSize,
142 Catalog
143 );
144 if (EFI_ERROR (Status)) {
145 continue;
146 }
147 //
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
150 //
151 if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
152 continue;
153 }
154
155 Check = 0;
156 CheckBuffer = (UINT16 *) Catalog;
157 for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
158 Check += CheckBuffer[Index];
159 }
160
161 if ((Check & 0xFFFF) != 0) {
162 continue;
163 }
164
165 MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);
166 for (Index = 1; Index < MaxIndex; Index += 1) {
167 //
168 // Next entry
169 //
170 Catalog += 1;
171
172 //
173 // Check this entry
174 //
175 if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
176 continue;
177 }
178
179 SubBlockSize = 512;
180 SectorCount = Catalog->Boot.SectorCount;
181
182 switch (Catalog->Boot.MediaType) {
183
184 case ELTORITO_NO_EMULATION:
185 SubBlockSize = ParentBlockDev->BlockSize;
186 SectorCount = Catalog->Boot.SectorCount;
187 break;
188
189 case ELTORITO_HARD_DISK:
190 break;
191
192 case ELTORITO_12_DISKETTE:
193 SectorCount = 0x50 * 0x02 * 0x0F;
194 break;
195
196 case ELTORITO_14_DISKETTE:
197 SectorCount = 0x50 * 0x02 * 0x12;
198 break;
199
200 case ELTORITO_28_DISKETTE:
201 SectorCount = 0x50 * 0x02 * 0x24;
202 break;
203
204 default:
205 SectorCount = 0;
206 SubBlockSize = ParentBlockDev->BlockSize;
207 break;
208 }
209
210 if (SectorCount < 2) {
211 SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);
212 }
213 //
214 // Register this partition
215 //
216 if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
217
218 Found = TRUE;
219
220 BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
221
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;
229
230 PrivateData->BlockDeviceCount++;
231 }
232 }
233 }
234
235 ParentBlockDev->PartitionChecked = TRUE;
236
237 return Found;
238
239 }