]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/FatPei/Eltorito.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 VolDescriptorLba += 1;
78 if (VolDescriptorLba > ParentBlockDev->LastBlock) {
79 //
80 // We are pointing past the end of the device so exit
81 //
82 break;
83 }
84
85 Status = FatReadBlock (
86 PrivateData,
87 ParentBlockDevNo,
88 VolDescriptorLba,
89 ParentBlockDev->BlockSize,
90 VolDescriptor
91 );
92 if (EFI_ERROR (Status)) {
93 break;
94 }
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 //
104 // end of Volume descriptor list
105 //
106 break;
107 }
108
109 //
110 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
111 //
112 if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {
113 VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];
114 }
115
116 //
117 // Is it an El Torito volume descriptor?
118 //
119 if (CompareMem (
120 VolDescriptor->BootRecordVolume.SystemId,
121 CDVOL_ELTORITO_ID,
122 sizeof (CDVOL_ELTORITO_ID) - 1
123 ) != 0)
124 {
125 continue;
126 }
127
128 //
129 // Read in the boot El Torito boot catalog
130 //
131 Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
132 if (Lba > ParentBlockDev->LastBlock) {
133 continue;
134 }
135
136 Status = FatReadBlock (
137 PrivateData,
138 ParentBlockDevNo,
139 Lba,
140 ParentBlockDev->BlockSize,
141 Catalog
142 );
143 if (EFI_ERROR (Status)) {
144 continue;
145 }
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 case ELTORITO_NO_EMULATION:
184 SubBlockSize = ParentBlockDev->BlockSize;
185 SectorCount = Catalog->Boot.SectorCount;
186 break;
187
188 case ELTORITO_HARD_DISK:
189 break;
190
191 case ELTORITO_12_DISKETTE:
192 SectorCount = 0x50 * 0x02 * 0x0F;
193 break;
194
195 case ELTORITO_14_DISKETTE:
196 SectorCount = 0x50 * 0x02 * 0x12;
197 break;
198
199 case ELTORITO_28_DISKETTE:
200 SectorCount = 0x50 * 0x02 * 0x24;
201 break;
202
203 default:
204 SectorCount = 0;
205 SubBlockSize = ParentBlockDev->BlockSize;
206 break;
207 }
208
209 if (SectorCount < 2) {
210 SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32)(ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32)(VolSpaceSize - Catalog->Boot.Lba);
211 }
212
213 //
214 // Register this partition
215 //
216 if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
217 Found = TRUE;
218
219 BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
220
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;
228
229 PrivateData->BlockDeviceCount++;
230 }
231 }
232 }
233
234 ParentBlockDev->PartitionChecked = TRUE;
235
236 return Found;
237 }