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"
27 PartitionInstallElToritoChildHandles (
28 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
30 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
31 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
32 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
37 Install child handles if the Handle supports El Torito format.
40 This - Calling context.
41 Handle - Parent Handle
42 DiskIo - Parent DiskIo interface
43 BlockIo - Parent BlockIo interface
44 DevicePath - Parent Device Path
47 EFI_SUCCESS - some child handle(s) was added
48 EFI_MEDIA_CHANGED - Media changed Detected
49 !EFI_SUCCESS - 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
;
70 Found
= EFI_NOT_FOUND
;
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
)) {
122 // Check for valid volume descriptor signature
124 if (VolDescriptor
->Type
== CDVOL_TYPE_END
||
125 CompareMem (VolDescriptor
->Id
, CDVOL_ID
, sizeof (VolDescriptor
->Id
)) != 0
128 // end of Volume descriptor list
133 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
134 // the 32-bit numerical values is stored in Both-byte orders
136 if (VolDescriptor
->Type
== CDVOL_TYPE_CODED
) {
137 VolSpaceSize
= VolDescriptor
->VolSpaceSize
[0];
140 // Is it an El Torito volume descriptor?
142 if (CompareMem (VolDescriptor
->SystemId
, CDVOL_ELTORITO_ID
, sizeof (CDVOL_ELTORITO_ID
) - 1) != 0) {
146 // Read in the boot El Torito boot catalog
148 Lba
= UNPACK_INT32 (VolDescriptor
->EltCatalog
);
149 if (Lba
> Media
->LastBlock
) {
153 Status
= BlockIo
->ReadBlocks (
160 if (EFI_ERROR (Status
)) {
161 DEBUG ((EFI_D_ERROR
, "EltCheckDevice: error reading catalog %r\n", Status
));
165 // We don't care too much about the Catalog header's contents, but we do want
166 // to make sure it looks like a Catalog header
168 if (Catalog
->Catalog
.Indicator
!= ELTORITO_ID_CATALOG
|| Catalog
->Catalog
.Id55AA
!= 0xAA55) {
169 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
174 CheckBuffer
= (UINT16
*) Catalog
;
175 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
176 Check
+= CheckBuffer
[Index
];
179 if (Check
& 0xFFFF) {
180 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
184 MaxIndex
= Media
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
185 for (Index
= 1, BootEntry
= 1; Index
< MaxIndex
; Index
+= 1) {
194 if (Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
|| Catalog
->Boot
.Lba
== 0) {
199 SectorCount
= Catalog
->Boot
.SectorCount
;
201 switch (Catalog
->Boot
.MediaType
) {
203 case ELTORITO_NO_EMULATION
:
204 SubBlockSize
= Media
->BlockSize
;
207 case ELTORITO_HARD_DISK
:
210 case ELTORITO_12_DISKETTE
:
211 SectorCount
= 0x50 * 0x02 * 0x0F;
214 case ELTORITO_14_DISKETTE
:
215 SectorCount
= 0x50 * 0x02 * 0x12;
218 case ELTORITO_28_DISKETTE
:
219 SectorCount
= 0x50 * 0x02 * 0x24;
223 DEBUG ((EFI_D_INIT
, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog
->Boot
.MediaType
));
225 SubBlockSize
= Media
->BlockSize
;
229 // Create child device handle
231 CdDev
.Header
.Type
= MEDIA_DEVICE_PATH
;
232 CdDev
.Header
.SubType
= MEDIA_CDROM_DP
;
233 SetDevicePathNodeLength (&CdDev
.Header
, sizeof (CdDev
));
237 // This is the initial/default entry
242 CdDev
.BootEntry
= (UINT32
) BootEntry
;
244 CdDev
.PartitionStart
= Catalog
->Boot
.Lba
;
245 if (SectorCount
< 2) {
247 // When the SectorCount < 2, set the Partition as the whole CD.
249 if (VolSpaceSize
> (Media
->LastBlock
+ 1)) {
250 CdDev
.PartitionSize
= (UINT32
)(Media
->LastBlock
- Catalog
->Boot
.Lba
+ 1);
252 CdDev
.PartitionSize
= (UINT32
)(VolSpaceSize
- Catalog
->Boot
.Lba
);
255 CdDev
.PartitionSize
= DivU64x32 (
259 ) + Media
->BlockSize
- 1,
264 Status
= PartitionInstallChildHandle (
270 (EFI_DEVICE_PATH_PROTOCOL
*) &CdDev
,
272 Catalog
->Boot
.Lba
+ CdDev
.PartitionSize
- 1,
276 if (!EFI_ERROR (Status
)) {
282 gBS
->FreePool (VolDescriptor
);