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 TRUE - some child handle(s) was added
48 FALSE - no child handle was added
53 UINT32 VolDescriptorLba
;
55 EFI_BLOCK_IO_MEDIA
*Media
;
56 CDROM_VOLUME_DESCRIPTOR
*VolDescriptor
;
57 ELTORITO_CATALOG
*Catalog
;
63 CDROM_DEVICE_PATH CdDev
;
70 Media
= BlockIo
->Media
;
74 // CD_ROM has the fixed block size as 2048 bytes
76 if (Media
->BlockSize
!= 2048) {
80 VolDescriptor
= AllocatePool ((UINTN
) Media
->BlockSize
);
82 if (VolDescriptor
== NULL
) {
86 Catalog
= (ELTORITO_CATALOG
*) VolDescriptor
;
89 // the ISO-9660 volume descriptor starts at 32k on the media
90 // and CD_ROM has the fixed block size as 2048 bytes, so...
93 // ((16*2048) / Media->BlockSize) - 1;
95 VolDescriptorLba
= 15;
97 // Loop: handle one volume descriptor per time
101 VolDescriptorLba
+= 1;
102 if (VolDescriptorLba
> Media
->LastBlock
) {
104 // We are pointing past the end of the device so exit
109 Status
= BlockIo
->ReadBlocks (
116 if (EFI_ERROR (Status
)) {
120 // Check for valid volume descriptor signature
122 if (VolDescriptor
->Type
== CDVOL_TYPE_END
||
123 CompareMem (VolDescriptor
->Id
, CDVOL_ID
, sizeof (VolDescriptor
->Id
)) != 0
126 // end of Volume descriptor list
131 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
132 // the 32-bit numerical values is stored in Both-byte orders
134 if (VolDescriptor
->Type
== CDVOL_TYPE_CODED
) {
135 VolSpaceSize
= VolDescriptor
->VolSpaceSize
[0];
138 // Is it an El Torito volume descriptor?
140 if (CompareMem (VolDescriptor
->SystemId
, CDVOL_ELTORITO_ID
, sizeof (CDVOL_ELTORITO_ID
) - 1) != 0) {
144 // Read in the boot El Torito boot catalog
146 Lba
= UNPACK_INT32 (VolDescriptor
->EltCatalog
);
147 if (Lba
> Media
->LastBlock
) {
151 Status
= BlockIo
->ReadBlocks (
158 if (EFI_ERROR (Status
)) {
159 DEBUG ((EFI_D_ERROR
, "EltCheckDevice: error reading catalog %r\n", Status
));
163 // We don't care too much about the Catalog header's contents, but we do want
164 // to make sure it looks like a Catalog header
166 if (Catalog
->Catalog
.Indicator
!= ELTORITO_ID_CATALOG
|| Catalog
->Catalog
.Id55AA
!= 0xAA55) {
167 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
172 CheckBuffer
= (UINT16
*) Catalog
;
173 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
174 Check
+= CheckBuffer
[Index
];
177 if (Check
& 0xFFFF) {
178 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
182 MaxIndex
= Media
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
183 for (Index
= 1, BootEntry
= 1; Index
< MaxIndex
; Index
+= 1) {
192 if (Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
|| Catalog
->Boot
.Lba
== 0) {
197 SectorCount
= Catalog
->Boot
.SectorCount
;
199 switch (Catalog
->Boot
.MediaType
) {
201 case ELTORITO_NO_EMULATION
:
202 SubBlockSize
= Media
->BlockSize
;
205 case ELTORITO_HARD_DISK
:
208 case ELTORITO_12_DISKETTE
:
209 SectorCount
= 0x50 * 0x02 * 0x0F;
212 case ELTORITO_14_DISKETTE
:
213 SectorCount
= 0x50 * 0x02 * 0x12;
216 case ELTORITO_28_DISKETTE
:
217 SectorCount
= 0x50 * 0x02 * 0x24;
221 DEBUG ((EFI_D_INIT
, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog
->Boot
.MediaType
));
223 SubBlockSize
= Media
->BlockSize
;
227 // Create child device handle
229 CdDev
.Header
.Type
= MEDIA_DEVICE_PATH
;
230 CdDev
.Header
.SubType
= MEDIA_CDROM_DP
;
231 SetDevicePathNodeLength (&CdDev
.Header
, sizeof (CdDev
));
235 // This is the initial/default entry
240 CdDev
.BootEntry
= (UINT32
) BootEntry
;
242 CdDev
.PartitionStart
= Catalog
->Boot
.Lba
;
243 if (SectorCount
< 2) {
245 // When the SectorCount < 2, set the Partition as the whole CD.
247 if (VolSpaceSize
> (Media
->LastBlock
+ 1)) {
248 CdDev
.PartitionSize
= (UINT32
)(Media
->LastBlock
- Catalog
->Boot
.Lba
+ 1);
250 CdDev
.PartitionSize
= (UINT32
)(VolSpaceSize
- Catalog
->Boot
.Lba
);
253 CdDev
.PartitionSize
= DivU64x32 (
257 ) + Media
->BlockSize
- 1,
262 Status
= PartitionInstallChildHandle (
268 (EFI_DEVICE_PATH_PROTOCOL
*) &CdDev
,
270 Catalog
->Boot
.Lba
+ CdDev
.PartitionSize
- 1,
274 if (!EFI_ERROR (Status
)) {
280 gBS
->FreePool (VolDescriptor
);