2 Decode an El Torito formatted CD-ROM
4 Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
5 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
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.
16 #include "Partition.h"
20 Install child handles if the Handle supports El Torito format.
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
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
35 PartitionInstallElToritoChildHandles (
36 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
38 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
39 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
40 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
44 UINT32 VolDescriptorLba
;
46 EFI_BLOCK_IO_MEDIA
*Media
;
47 CDROM_VOLUME_DESCRIPTOR
*VolDescriptor
;
48 ELTORITO_CATALOG
*Catalog
;
54 CDROM_DEVICE_PATH CdDev
;
60 Found
= EFI_NOT_FOUND
;
61 Media
= BlockIo
->Media
;
65 // CD_ROM has the fixed block size as 2048 bytes
67 if (Media
->BlockSize
!= 2048) {
71 VolDescriptor
= AllocatePool ((UINTN
) Media
->BlockSize
);
73 if (VolDescriptor
== NULL
) {
77 Catalog
= (ELTORITO_CATALOG
*) VolDescriptor
;
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...
84 // ((16*2048) / Media->BlockSize) - 1;
86 VolDescriptorLba
= 15;
88 // Loop: handle one volume descriptor per time
92 VolDescriptorLba
+= 1;
93 if (VolDescriptorLba
> Media
->LastBlock
) {
95 // We are pointing past the end of the device so exit
100 Status
= DiskIo
->ReadDisk (
103 MultU64x32 (VolDescriptorLba
, Media
->BlockSize
),
107 if (EFI_ERROR (Status
)) {
112 // Check for valid volume descriptor signature
114 if (VolDescriptor
->Unknown
.Type
== CDVOL_TYPE_END
||
115 CompareMem (VolDescriptor
->Unknown
.Id
, CDVOL_ID
, sizeof (VolDescriptor
->Unknown
.Id
)) != 0
118 // end of Volume descriptor list
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
126 if (VolDescriptor
->PrimaryVolume
.Type
== CDVOL_TYPE_CODED
) {
127 VolSpaceSize
= VolDescriptor
->PrimaryVolume
.VolSpaceSize
[0];
130 // Is it an El Torito volume descriptor?
132 if (CompareMem (VolDescriptor
->BootRecordVolume
.SystemId
, CDVOL_ELTORITO_ID
, sizeof (CDVOL_ELTORITO_ID
) - 1) != 0) {
136 // Read in the boot El Torito boot catalog
138 Lba
= UNPACK_INT32 (VolDescriptor
->BootRecordVolume
.EltCatalog
);
139 if (Lba
> Media
->LastBlock
) {
143 Status
= DiskIo
->ReadDisk (
146 MultU64x32 (Lba
, Media
->BlockSize
),
150 if (EFI_ERROR (Status
)) {
151 DEBUG ((EFI_D_ERROR
, "EltCheckDevice: error reading catalog %r\n", Status
));
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
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"));
164 CheckBuffer
= (UINT16
*) Catalog
;
165 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
166 Check
+= CheckBuffer
[Index
];
169 if ((Check
& 0xFFFF) != 0) {
170 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
174 MaxIndex
= Media
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
175 for (Index
= 1, BootEntry
= 1; Index
< MaxIndex
; Index
+= 1) {
184 if (Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
|| Catalog
->Boot
.Lba
== 0) {
189 SectorCount
= Catalog
->Boot
.SectorCount
;
191 switch (Catalog
->Boot
.MediaType
) {
193 case ELTORITO_NO_EMULATION
:
194 SubBlockSize
= Media
->BlockSize
;
197 case ELTORITO_HARD_DISK
:
200 case ELTORITO_12_DISKETTE
:
201 SectorCount
= 0x50 * 0x02 * 0x0F;
204 case ELTORITO_14_DISKETTE
:
205 SectorCount
= 0x50 * 0x02 * 0x12;
208 case ELTORITO_28_DISKETTE
:
209 SectorCount
= 0x50 * 0x02 * 0x24;
213 DEBUG ((EFI_D_INIT
, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog
->Boot
.MediaType
));
215 SubBlockSize
= Media
->BlockSize
;
219 // Create child device handle
221 CdDev
.Header
.Type
= MEDIA_DEVICE_PATH
;
222 CdDev
.Header
.SubType
= MEDIA_CDROM_DP
;
223 SetDevicePathNodeLength (&CdDev
.Header
, sizeof (CdDev
));
227 // This is the initial/default entry
232 CdDev
.BootEntry
= (UINT32
) BootEntry
;
234 CdDev
.PartitionStart
= Catalog
->Boot
.Lba
;
235 if (SectorCount
< 2) {
237 // When the SectorCount < 2, set the Partition as the whole CD.
239 if (VolSpaceSize
> (Media
->LastBlock
+ 1)) {
240 CdDev
.PartitionSize
= (UINT32
)(Media
->LastBlock
- Catalog
->Boot
.Lba
+ 1);
242 CdDev
.PartitionSize
= (UINT32
)(VolSpaceSize
- Catalog
->Boot
.Lba
);
245 CdDev
.PartitionSize
= DivU64x32 (
249 ) + Media
->BlockSize
- 1,
254 Status
= PartitionInstallChildHandle (
260 (EFI_DEVICE_PATH_PROTOCOL
*) &CdDev
,
262 Catalog
->Boot
.Lba
+ CdDev
.PartitionSize
- 1,
266 if (!EFI_ERROR (Status
)) {
272 FreePool (VolDescriptor
);