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
25 // Include common header file for this module.
27 #include "CommonHeader.h"
29 #include "Partition.h"
32 PartitionInstallElToritoChildHandles (
33 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
35 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
36 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
37 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
42 Install child handles if the Handle supports El Torito format.
45 This - Calling context.
46 Handle - Parent Handle
47 DiskIo - Parent DiskIo interface
48 BlockIo - Parent BlockIo interface
49 DevicePath - Parent Device Path
52 EFI_SUCCESS - some child handle(s) was added
53 EFI_MEDIA_CHANGED - Media changed Detected
54 !EFI_SUCCESS - no child handle was added
59 UINT32 VolDescriptorLba
;
61 EFI_BLOCK_IO_MEDIA
*Media
;
62 CDROM_VOLUME_DESCRIPTOR
*VolDescriptor
;
63 ELTORITO_CATALOG
*Catalog
;
69 CDROM_DEVICE_PATH CdDev
;
75 Found
= EFI_NOT_FOUND
;
76 Media
= BlockIo
->Media
;
80 // CD_ROM has the fixed block size as 2048 bytes
82 if (Media
->BlockSize
!= 2048) {
86 VolDescriptor
= AllocatePool ((UINTN
) Media
->BlockSize
);
88 if (VolDescriptor
== NULL
) {
92 Catalog
= (ELTORITO_CATALOG
*) VolDescriptor
;
95 // the ISO-9660 volume descriptor starts at 32k on the media
96 // and CD_ROM has the fixed block size as 2048 bytes, so...
99 // ((16*2048) / Media->BlockSize) - 1;
101 VolDescriptorLba
= 15;
103 // Loop: handle one volume descriptor per time
107 VolDescriptorLba
+= 1;
108 if (VolDescriptorLba
> Media
->LastBlock
) {
110 // We are pointing past the end of the device so exit
115 Status
= BlockIo
->ReadBlocks (
122 if (EFI_ERROR (Status
)) {
127 // Check for valid volume descriptor signature
129 if (VolDescriptor
->Type
== CDVOL_TYPE_END
||
130 CompareMem (VolDescriptor
->Id
, CDVOL_ID
, sizeof (VolDescriptor
->Id
)) != 0
133 // end of Volume descriptor list
138 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
139 // the 32-bit numerical values is stored in Both-byte orders
141 if (VolDescriptor
->Type
== CDVOL_TYPE_CODED
) {
142 VolSpaceSize
= VolDescriptor
->VolSpaceSize
[0];
145 // Is it an El Torito volume descriptor?
147 if (CompareMem (VolDescriptor
->SystemId
, CDVOL_ELTORITO_ID
, sizeof (CDVOL_ELTORITO_ID
) - 1) != 0) {
151 // Read in the boot El Torito boot catalog
153 Lba
= UNPACK_INT32 (VolDescriptor
->EltCatalog
);
154 if (Lba
> Media
->LastBlock
) {
158 Status
= BlockIo
->ReadBlocks (
165 if (EFI_ERROR (Status
)) {
166 DEBUG ((EFI_D_ERROR
, "EltCheckDevice: error reading catalog %r\n", Status
));
170 // We don't care too much about the Catalog header's contents, but we do want
171 // to make sure it looks like a Catalog header
173 if (Catalog
->Catalog
.Indicator
!= ELTORITO_ID_CATALOG
|| Catalog
->Catalog
.Id55AA
!= 0xAA55) {
174 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
179 CheckBuffer
= (UINT16
*) Catalog
;
180 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
181 Check
+= CheckBuffer
[Index
];
184 if (Check
& 0xFFFF) {
185 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
189 MaxIndex
= Media
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
190 for (Index
= 1, BootEntry
= 1; Index
< MaxIndex
; Index
+= 1) {
199 if (Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
|| Catalog
->Boot
.Lba
== 0) {
204 SectorCount
= Catalog
->Boot
.SectorCount
;
206 switch (Catalog
->Boot
.MediaType
) {
208 case ELTORITO_NO_EMULATION
:
209 SubBlockSize
= Media
->BlockSize
;
212 case ELTORITO_HARD_DISK
:
215 case ELTORITO_12_DISKETTE
:
216 SectorCount
= 0x50 * 0x02 * 0x0F;
219 case ELTORITO_14_DISKETTE
:
220 SectorCount
= 0x50 * 0x02 * 0x12;
223 case ELTORITO_28_DISKETTE
:
224 SectorCount
= 0x50 * 0x02 * 0x24;
228 DEBUG ((EFI_D_INIT
, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog
->Boot
.MediaType
));
230 SubBlockSize
= Media
->BlockSize
;
234 // Create child device handle
236 CdDev
.Header
.Type
= MEDIA_DEVICE_PATH
;
237 CdDev
.Header
.SubType
= MEDIA_CDROM_DP
;
238 SetDevicePathNodeLength (&CdDev
.Header
, sizeof (CdDev
));
242 // This is the initial/default entry
247 CdDev
.BootEntry
= (UINT32
) BootEntry
;
249 CdDev
.PartitionStart
= Catalog
->Boot
.Lba
;
250 if (SectorCount
< 2) {
252 // When the SectorCount < 2, set the Partition as the whole CD.
254 if (VolSpaceSize
> (Media
->LastBlock
+ 1)) {
255 CdDev
.PartitionSize
= (UINT32
)(Media
->LastBlock
- Catalog
->Boot
.Lba
+ 1);
257 CdDev
.PartitionSize
= (UINT32
)(VolSpaceSize
- Catalog
->Boot
.Lba
);
260 CdDev
.PartitionSize
= DivU64x32 (
264 ) + Media
->BlockSize
- 1,
269 Status
= PartitionInstallChildHandle (
275 (EFI_DEVICE_PATH_PROTOCOL
*) &CdDev
,
277 Catalog
->Boot
.Lba
+ CdDev
.PartitionSize
- 1,
281 if (!EFI_ERROR (Status
)) {
287 FreePool (VolDescriptor
);