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