]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c
add modules DiskIo, Partition and SecurityStub.
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / Partition / Dxe / ElTorito.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 ElTorito.c
15
16 Abstract:
17
18 Decode an El Torito formatted CD-ROM
19
20 Revision History
21
22 --*/
23
24 //
25 // Include common header file for this module.
26 //
27 #include "CommonHeader.h"
28
29 #include "Partition.h"
30
31 EFI_STATUS
32 PartitionInstallElToritoChildHandles (
33 IN EFI_DRIVER_BINDING_PROTOCOL *This,
34 IN EFI_HANDLE Handle,
35 IN EFI_DISK_IO_PROTOCOL *DiskIo,
36 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
37 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
38 )
39 /*++
40
41 Routine Description:
42 Install child handles if the Handle supports El Torito format.
43
44 Arguments:
45 This - Calling context.
46 Handle - Parent Handle
47 DiskIo - Parent DiskIo interface
48 BlockIo - Parent BlockIo interface
49 DevicePath - Parent Device Path
50
51 Returns:
52 EFI_SUCCESS - some child handle(s) was added
53 EFI_MEDIA_CHANGED - Media changed Detected
54 !EFI_SUCCESS - no child handle was added
55
56 --*/
57 {
58 EFI_STATUS Status;
59 UINT32 VolDescriptorLba;
60 UINT32 Lba;
61 EFI_BLOCK_IO_MEDIA *Media;
62 CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
63 ELTORITO_CATALOG *Catalog;
64 UINTN Check;
65 UINTN Index;
66 UINTN BootEntry;
67 UINTN MaxIndex;
68 UINT16 *CheckBuffer;
69 CDROM_DEVICE_PATH CdDev;
70 UINT32 SubBlockSize;
71 UINT32 SectorCount;
72 EFI_STATUS Found;
73 UINT32 VolSpaceSize;
74
75 Found = EFI_NOT_FOUND;
76 Media = BlockIo->Media;
77 VolSpaceSize = 0;
78
79 //
80 // CD_ROM has the fixed block size as 2048 bytes
81 //
82 if (Media->BlockSize != 2048) {
83 return EFI_NOT_FOUND;
84 }
85
86 VolDescriptor = AllocatePool ((UINTN) Media->BlockSize);
87
88 if (VolDescriptor == NULL) {
89 return EFI_NOT_FOUND;
90 }
91
92 Catalog = (ELTORITO_CATALOG *) VolDescriptor;
93
94 //
95 // the ISO-9660 volume descriptor starts at 32k on the media
96 // and CD_ROM has the fixed block size as 2048 bytes, so...
97 //
98 //
99 // ((16*2048) / Media->BlockSize) - 1;
100 //
101 VolDescriptorLba = 15;
102 //
103 // Loop: handle one volume descriptor per time
104 //
105 while (TRUE) {
106
107 VolDescriptorLba += 1;
108 if (VolDescriptorLba > Media->LastBlock) {
109 //
110 // We are pointing past the end of the device so exit
111 //
112 break;
113 }
114
115 Status = BlockIo->ReadBlocks (
116 BlockIo,
117 Media->MediaId,
118 VolDescriptorLba,
119 Media->BlockSize,
120 VolDescriptor
121 );
122 if (EFI_ERROR (Status)) {
123 Found = Status;
124 break;
125 }
126 //
127 // Check for valid volume descriptor signature
128 //
129 if (VolDescriptor->Type == CDVOL_TYPE_END ||
130 CompareMem (VolDescriptor->Id, CDVOL_ID, sizeof (VolDescriptor->Id)) != 0
131 ) {
132 //
133 // end of Volume descriptor list
134 //
135 break;
136 }
137 //
138 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
139 // the 32-bit numerical values is stored in Both-byte orders
140 //
141 if (VolDescriptor->Type == CDVOL_TYPE_CODED) {
142 VolSpaceSize = VolDescriptor->VolSpaceSize[0];
143 }
144 //
145 // Is it an El Torito volume descriptor?
146 //
147 if (CompareMem (VolDescriptor->SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
148 continue;
149 }
150 //
151 // Read in the boot El Torito boot catalog
152 //
153 Lba = UNPACK_INT32 (VolDescriptor->EltCatalog);
154 if (Lba > Media->LastBlock) {
155 continue;
156 }
157
158 Status = BlockIo->ReadBlocks (
159 BlockIo,
160 Media->MediaId,
161 Lba,
162 Media->BlockSize,
163 Catalog
164 );
165 if (EFI_ERROR (Status)) {
166 DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));
167 continue;
168 }
169 //
170 // We don't care too much about the Catalog header's contents, but we do want
171 // to make sure it looks like a Catalog header
172 //
173 if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
174 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
175 continue;
176 }
177
178 Check = 0;
179 CheckBuffer = (UINT16 *) Catalog;
180 for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
181 Check += CheckBuffer[Index];
182 }
183
184 if (Check & 0xFFFF) {
185 DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
186 continue;
187 }
188
189 MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);
190 for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {
191 //
192 // Next entry
193 //
194 Catalog += 1;
195
196 //
197 // Check this entry
198 //
199 if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
200 continue;
201 }
202
203 SubBlockSize = 512;
204 SectorCount = Catalog->Boot.SectorCount;
205
206 switch (Catalog->Boot.MediaType) {
207
208 case ELTORITO_NO_EMULATION:
209 SubBlockSize = Media->BlockSize;
210 break;
211
212 case ELTORITO_HARD_DISK:
213 break;
214
215 case ELTORITO_12_DISKETTE:
216 SectorCount = 0x50 * 0x02 * 0x0F;
217 break;
218
219 case ELTORITO_14_DISKETTE:
220 SectorCount = 0x50 * 0x02 * 0x12;
221 break;
222
223 case ELTORITO_28_DISKETTE:
224 SectorCount = 0x50 * 0x02 * 0x24;
225 break;
226
227 default:
228 DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
229 SectorCount = 0;
230 SubBlockSize = Media->BlockSize;
231 break;
232 }
233 //
234 // Create child device handle
235 //
236 CdDev.Header.Type = MEDIA_DEVICE_PATH;
237 CdDev.Header.SubType = MEDIA_CDROM_DP;
238 SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
239
240 if (Index == 1) {
241 //
242 // This is the initial/default entry
243 //
244 BootEntry = 0;
245 }
246
247 CdDev.BootEntry = (UINT32) BootEntry;
248 BootEntry++;
249 CdDev.PartitionStart = Catalog->Boot.Lba;
250 if (SectorCount < 2) {
251 //
252 // When the SectorCount < 2, set the Partition as the whole CD.
253 //
254 if (VolSpaceSize > (Media->LastBlock + 1)) {
255 CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1);
256 } else {
257 CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba);
258 }
259 } else {
260 CdDev.PartitionSize = DivU64x32 (
261 MultU64x32 (
262 SectorCount,
263 SubBlockSize
264 ) + Media->BlockSize - 1,
265 Media->BlockSize
266 );
267 }
268
269 Status = PartitionInstallChildHandle (
270 This,
271 Handle,
272 DiskIo,
273 BlockIo,
274 DevicePath,
275 (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
276 Catalog->Boot.Lba,
277 Catalog->Boot.Lba + CdDev.PartitionSize - 1,
278 SubBlockSize,
279 FALSE
280 );
281 if (!EFI_ERROR (Status)) {
282 Found = EFI_SUCCESS;
283 }
284 }
285 }
286
287 FreePool (VolDescriptor);
288
289 return Found;
290 }