VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/PartitionDxe/ElTorito.c@ 48730

Last change on this file since 48730 was 48730, checked in by vboxsync, 11 years ago

EFI: Use VBox prefix for our stuff so that it's obvious what's our stuff and what isn't. Also, I do NOT like anyone but iprt/log.h defining LogXXX macros!

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette