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 | }
|
---|