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
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.
18 Decode an El Torito formatted CD-ROM
24 #include "Partition.h"
28 PartitionInstallElToritoChildHandles (
29 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
31 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
32 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
33 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
38 Install child handles if the Handle supports El Torito format.
41 This - Calling context.
42 Handle - Parent Handle
43 DiskIo - Parent DiskIo interface
44 BlockIo - Parent BlockIo interface
45 DevicePath - Parent Device Path
48 TRUE - some child handle(s) was added
49 FALSE - no child handle was added
54 UINT32 VolDescriptorLba
;
56 EFI_BLOCK_IO_MEDIA
*Media
;
57 CDROM_VOLUME_DESCRIPTOR
*VolDescriptor
;
58 ELTORITO_CATALOG
*Catalog
;
64 CDROM_DEVICE_PATH CdDev
;
71 Media
= BlockIo
->Media
;
75 // CD_ROM has the fixed block size as 2048 bytes
77 if (Media
->BlockSize
!= 2048) {
81 VolDescriptor
= AllocatePool ((UINTN
) Media
->BlockSize
);
83 if (VolDescriptor
== NULL
) {
87 Catalog
= (ELTORITO_CATALOG
*) VolDescriptor
;
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...
94 // ((16*2048) / Media->BlockSize) - 1;
96 VolDescriptorLba
= 15;
98 // Loop: handle one volume descriptor per time
102 VolDescriptorLba
+= 1;
103 if (VolDescriptorLba
> Media
->LastBlock
) {
105 // We are pointing past the end of the device so exit
110 Status
= BlockIo
->ReadBlocks (
117 if (EFI_ERROR (Status
)) {
121 // Check for valid volume descriptor signature
123 if (VolDescriptor
->Type
== CDVOL_TYPE_END
||
124 CompareMem (VolDescriptor
->Id
, CDVOL_ID
, sizeof (VolDescriptor
->Id
)) != 0
127 // end of Volume descriptor list
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
135 if (VolDescriptor
->Type
== CDVOL_TYPE_CODED
) {
136 VolSpaceSize
= VolDescriptor
->VolSpaceSize
[1];
139 // Is it an El Torito volume descriptor?
141 if (CompareMem (VolDescriptor
->SystemId
, CDVOL_ELTORITO_ID
, sizeof (CDVOL_ELTORITO_ID
) - 1) != 0) {
145 // Read in the boot El Torito boot catalog
147 Lba
= UNPACK_INT32 (VolDescriptor
->EltCatalog
);
148 if (Lba
> Media
->LastBlock
) {
152 Status
= BlockIo
->ReadBlocks (
159 if (EFI_ERROR (Status
)) {
160 DEBUG ((EFI_D_ERROR
, "EltCheckDevice: error reading catalog %r\n", Status
));
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
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"));
173 CheckBuffer
= (UINT16
*) Catalog
;
174 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
175 Check
+= CheckBuffer
[Index
];
178 if (Check
& 0xFFFF) {
179 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
183 MaxIndex
= Media
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
184 for (Index
= 1, BootEntry
= 1; Index
< MaxIndex
; Index
+= 1) {
193 if (Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
|| Catalog
->Boot
.Lba
== 0) {
198 SectorCount
= Catalog
->Boot
.SectorCount
;
200 switch (Catalog
->Boot
.MediaType
) {
202 case ELTORITO_NO_EMULATION
:
203 SubBlockSize
= Media
->BlockSize
;
206 case ELTORITO_HARD_DISK
:
209 case ELTORITO_12_DISKETTE
:
210 SectorCount
= 0x50 * 0x02 * 0x0F;
213 case ELTORITO_14_DISKETTE
:
214 SectorCount
= 0x50 * 0x02 * 0x12;
217 case ELTORITO_28_DISKETTE
:
218 SectorCount
= 0x50 * 0x02 * 0x24;
222 DEBUG ((EFI_D_INIT
, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog
->Boot
.MediaType
));
224 SubBlockSize
= Media
->BlockSize
;
228 // Create child device handle
230 CdDev
.Header
.Type
= MEDIA_DEVICE_PATH
;
231 CdDev
.Header
.SubType
= MEDIA_CDROM_DP
;
232 SetDevicePathNodeLength (&CdDev
.Header
, sizeof (CdDev
));
236 // This is the initial/default entry
241 CdDev
.BootEntry
= (UINT32
) BootEntry
;
243 CdDev
.PartitionStart
= Catalog
->Boot
.Lba
;
244 if (SectorCount
< 2) {
245 CdDev
.PartitionSize
= VolSpaceSize
;
247 CdDev
.PartitionSize
= DivU64x32 (
251 ) + Media
->BlockSize
- 1,
256 Status
= PartitionInstallChildHandle (
262 (EFI_DEVICE_PATH_PROTOCOL
*) &CdDev
,
264 Catalog
->Boot
.Lba
+ CdDev
.PartitionSize
- 1,
268 if (!EFI_ERROR (Status
)) {
274 gBS
->FreePool (VolDescriptor
);