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