2 Decode an El Torito formatted CD-ROM
4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. 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.
17 // Include common header file for this module.
19 #include "CommonHeader.h"
21 #include "Partition.h"
25 Install child handles if the Handle supports El Torito format.
27 @param[in] This Calling context.
28 @param[in] Handle Parent Handle
29 @param[in] DiskIo Parent DiskIo interface
30 @param[in] BlockIo Parent BlockIo interface
31 @param[in] DevicePath Parent Device Path
34 @retval EFI_SUCCESS Child handle(s) was added
35 @retval EFI_MEDIA_CHANGED Media changed Detected
36 @retval other no child handle was added
40 PartitionInstallElToritoChildHandles (
41 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
43 IN EFI_DISK_IO_PROTOCOL
*DiskIo
,
44 IN EFI_BLOCK_IO_PROTOCOL
*BlockIo
,
45 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
49 UINT32 VolDescriptorLba
;
51 EFI_BLOCK_IO_MEDIA
*Media
;
52 CDROM_VOLUME_DESCRIPTOR
*VolDescriptor
;
53 ELTORITO_CATALOG
*Catalog
;
59 CDROM_DEVICE_PATH CdDev
;
65 Found
= EFI_NOT_FOUND
;
66 Media
= BlockIo
->Media
;
70 // CD_ROM has the fixed block size as 2048 bytes
72 if (Media
->BlockSize
!= 2048) {
76 VolDescriptor
= AllocatePool ((UINTN
) Media
->BlockSize
);
78 if (VolDescriptor
== NULL
) {
82 Catalog
= (ELTORITO_CATALOG
*) VolDescriptor
;
85 // the ISO-9660 volume descriptor starts at 32k on the media
86 // and CD_ROM has the fixed block size as 2048 bytes, so...
89 // ((16*2048) / Media->BlockSize) - 1;
91 VolDescriptorLba
= 15;
93 // Loop: handle one volume descriptor per time
97 VolDescriptorLba
+= 1;
98 if (VolDescriptorLba
> Media
->LastBlock
) {
100 // We are pointing past the end of the device so exit
105 Status
= BlockIo
->ReadBlocks (
112 if (EFI_ERROR (Status
)) {
117 // Check for valid volume descriptor signature
119 if (VolDescriptor
->Type
== CDVOL_TYPE_END
||
120 CompareMem (VolDescriptor
->Id
, CDVOL_ID
, sizeof (VolDescriptor
->Id
)) != 0
123 // end of Volume descriptor list
128 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
129 // the 32-bit numerical values is stored in Both-byte orders
131 if (VolDescriptor
->Type
== CDVOL_TYPE_CODED
) {
132 VolSpaceSize
= VolDescriptor
->VolSpaceSize
[0];
135 // Is it an El Torito volume descriptor?
137 if (CompareMem (VolDescriptor
->SystemId
, CDVOL_ELTORITO_ID
, sizeof (CDVOL_ELTORITO_ID
) - 1) != 0) {
141 // Read in the boot El Torito boot catalog
143 Lba
= UNPACK_INT32 (VolDescriptor
->EltCatalog
);
144 if (Lba
> Media
->LastBlock
) {
148 Status
= BlockIo
->ReadBlocks (
155 if (EFI_ERROR (Status
)) {
156 DEBUG ((EFI_D_ERROR
, "EltCheckDevice: error reading catalog %r\n", Status
));
160 // We don't care too much about the Catalog header's contents, but we do want
161 // to make sure it looks like a Catalog header
163 if (Catalog
->Catalog
.Indicator
!= ELTORITO_ID_CATALOG
|| Catalog
->Catalog
.Id55AA
!= 0xAA55) {
164 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
169 CheckBuffer
= (UINT16
*) Catalog
;
170 for (Index
= 0; Index
< sizeof (ELTORITO_CATALOG
) / sizeof (UINT16
); Index
+= 1) {
171 Check
+= CheckBuffer
[Index
];
174 if (Check
& 0xFFFF) {
175 DEBUG ((EFI_D_ERROR
, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
179 MaxIndex
= Media
->BlockSize
/ sizeof (ELTORITO_CATALOG
);
180 for (Index
= 1, BootEntry
= 1; Index
< MaxIndex
; Index
+= 1) {
189 if (Catalog
->Boot
.Indicator
!= ELTORITO_ID_SECTION_BOOTABLE
|| Catalog
->Boot
.Lba
== 0) {
194 SectorCount
= Catalog
->Boot
.SectorCount
;
196 switch (Catalog
->Boot
.MediaType
) {
198 case ELTORITO_NO_EMULATION
:
199 SubBlockSize
= Media
->BlockSize
;
202 case ELTORITO_HARD_DISK
:
205 case ELTORITO_12_DISKETTE
:
206 SectorCount
= 0x50 * 0x02 * 0x0F;
209 case ELTORITO_14_DISKETTE
:
210 SectorCount
= 0x50 * 0x02 * 0x12;
213 case ELTORITO_28_DISKETTE
:
214 SectorCount
= 0x50 * 0x02 * 0x24;
218 DEBUG ((EFI_D_INIT
, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog
->Boot
.MediaType
));
220 SubBlockSize
= Media
->BlockSize
;
224 // Create child device handle
226 CdDev
.Header
.Type
= MEDIA_DEVICE_PATH
;
227 CdDev
.Header
.SubType
= MEDIA_CDROM_DP
;
228 SetDevicePathNodeLength (&CdDev
.Header
, sizeof (CdDev
));
232 // This is the initial/default entry
237 CdDev
.BootEntry
= (UINT32
) BootEntry
;
239 CdDev
.PartitionStart
= Catalog
->Boot
.Lba
;
240 if (SectorCount
< 2) {
242 // When the SectorCount < 2, set the Partition as the whole CD.
244 if (VolSpaceSize
> (Media
->LastBlock
+ 1)) {
245 CdDev
.PartitionSize
= (UINT32
)(Media
->LastBlock
- Catalog
->Boot
.Lba
+ 1);
247 CdDev
.PartitionSize
= (UINT32
)(VolSpaceSize
- Catalog
->Boot
.Lba
);
250 CdDev
.PartitionSize
= DivU64x32 (
254 ) + Media
->BlockSize
- 1,
259 Status
= PartitionInstallChildHandle (
265 (EFI_DEVICE_PATH_PROTOCOL
*) &CdDev
,
267 Catalog
->Boot
.Lba
+ CdDev
.PartitionSize
- 1,
271 if (!EFI_ERROR (Status
)) {
277 FreePool (VolDescriptor
);