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