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