+++ /dev/null
-/** @file\r
- Decode an El Torito formatted CD-ROM\r
-\r
- Copyright (c) 2006 - 2007, Intel Corporation \r
- All rights reserved. This program and the accompanying materials \r
- are licensed and made available under the terms and conditions of the BSD License \r
- which accompanies this distribution. The full text of the license may be found at \r
- http://opensource.org/licenses/bsd-license.php \r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-**/\r
-\r
-\r
-#include "Partition.h"\r
-\r
-\r
-/**\r
- Install child handles if the Handle supports El Torito format.\r
-\r
- @param[in] This Calling context.\r
- @param[in] Handle Parent Handle\r
- @param[in] DiskIo Parent DiskIo interface\r
- @param[in] BlockIo Parent BlockIo interface\r
- @param[in] DevicePath Parent Device Path\r
-\r
-\r
- @retval EFI_SUCCESS Child handle(s) was added\r
- @retval EFI_MEDIA_CHANGED Media changed Detected\r
- @retval other no child handle was added\r
-\r
-**/\r
-EFI_STATUS\r
-PartitionInstallElToritoChildHandles (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Handle,\r
- IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
- IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 VolDescriptorLba;\r
- UINT32 Lba;\r
- EFI_BLOCK_IO_MEDIA *Media;\r
- CDROM_VOLUME_DESCRIPTOR *VolDescriptor;\r
- ELTORITO_CATALOG *Catalog;\r
- UINTN Check;\r
- UINTN Index;\r
- UINTN BootEntry;\r
- UINTN MaxIndex;\r
- UINT16 *CheckBuffer;\r
- CDROM_DEVICE_PATH CdDev;\r
- UINT32 SubBlockSize;\r
- UINT32 SectorCount;\r
- EFI_STATUS Found;\r
- UINT32 VolSpaceSize;\r
-\r
- Found = EFI_NOT_FOUND;\r
- Media = BlockIo->Media;\r
- VolSpaceSize = 0;\r
-\r
- //\r
- // CD_ROM has the fixed block size as 2048 bytes\r
- //\r
- if (Media->BlockSize != 2048) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- VolDescriptor = AllocatePool ((UINTN) Media->BlockSize);\r
-\r
- if (VolDescriptor == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- Catalog = (ELTORITO_CATALOG *) VolDescriptor;\r
-\r
- //\r
- // the ISO-9660 volume descriptor starts at 32k on the media\r
- // and CD_ROM has the fixed block size as 2048 bytes, so...\r
- //\r
- //\r
- // ((16*2048) / Media->BlockSize) - 1;\r
- //\r
- VolDescriptorLba = 15;\r
- //\r
- // Loop: handle one volume descriptor per time\r
- //\r
- while (TRUE) {\r
-\r
- VolDescriptorLba += 1;\r
- if (VolDescriptorLba > Media->LastBlock) {\r
- //\r
- // We are pointing past the end of the device so exit\r
- //\r
- break;\r
- }\r
-\r
- Status = BlockIo->ReadBlocks (\r
- BlockIo,\r
- Media->MediaId,\r
- VolDescriptorLba,\r
- Media->BlockSize,\r
- VolDescriptor\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Found = Status;\r
- break;\r
- }\r
- //\r
- // Check for valid volume descriptor signature\r
- //\r
- if (VolDescriptor->Type == CDVOL_TYPE_END ||\r
- CompareMem (VolDescriptor->Id, CDVOL_ID, sizeof (VolDescriptor->Id)) != 0\r
- ) {\r
- //\r
- // end of Volume descriptor list\r
- //\r
- break;\r
- }\r
- //\r
- // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,\r
- // the 32-bit numerical values is stored in Both-byte orders\r
- //\r
- if (VolDescriptor->Type == CDVOL_TYPE_CODED) {\r
- VolSpaceSize = VolDescriptor->VolSpaceSize[0];\r
- }\r
- //\r
- // Is it an El Torito volume descriptor?\r
- //\r
- if (CompareMem (VolDescriptor->SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {\r
- continue;\r
- }\r
- //\r
- // Read in the boot El Torito boot catalog\r
- //\r
- Lba = UNPACK_INT32 (VolDescriptor->EltCatalog);\r
- if (Lba > Media->LastBlock) {\r
- continue;\r
- }\r
-\r
- Status = BlockIo->ReadBlocks (\r
- BlockIo,\r
- Media->MediaId,\r
- Lba,\r
- Media->BlockSize,\r
- Catalog\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));\r
- continue;\r
- }\r
- //\r
- // We don't care too much about the Catalog header's contents, but we do want\r
- // to make sure it looks like a Catalog header\r
- //\r
- if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {\r
- DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));\r
- continue;\r
- }\r
-\r
- Check = 0;\r
- CheckBuffer = (UINT16 *) Catalog;\r
- for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {\r
- Check += CheckBuffer[Index];\r
- }\r
-\r
- if (Check & 0xFFFF) {\r
- DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));\r
- continue;\r
- }\r
-\r
- MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);\r
- for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {\r
- //\r
- // Next entry\r
- //\r
- Catalog += 1;\r
-\r
- //\r
- // Check this entry\r
- //\r
- if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {\r
- continue;\r
- }\r
-\r
- SubBlockSize = 512;\r
- SectorCount = Catalog->Boot.SectorCount;\r
-\r
- switch (Catalog->Boot.MediaType) {\r
-\r
- case ELTORITO_NO_EMULATION:\r
- SubBlockSize = Media->BlockSize;\r
- break;\r
-\r
- case ELTORITO_HARD_DISK:\r
- break;\r
-\r
- case ELTORITO_12_DISKETTE:\r
- SectorCount = 0x50 * 0x02 * 0x0F;\r
- break;\r
-\r
- case ELTORITO_14_DISKETTE:\r
- SectorCount = 0x50 * 0x02 * 0x12;\r
- break;\r
-\r
- case ELTORITO_28_DISKETTE:\r
- SectorCount = 0x50 * 0x02 * 0x24;\r
- break;\r
-\r
- default:\r
- DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));\r
- SectorCount = 0;\r
- SubBlockSize = Media->BlockSize;\r
- break;\r
- }\r
- //\r
- // Create child device handle\r
- //\r
- CdDev.Header.Type = MEDIA_DEVICE_PATH;\r
- CdDev.Header.SubType = MEDIA_CDROM_DP;\r
- SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));\r
-\r
- if (Index == 1) {\r
- //\r
- // This is the initial/default entry\r
- //\r
- BootEntry = 0;\r
- }\r
-\r
- CdDev.BootEntry = (UINT32) BootEntry;\r
- BootEntry++;\r
- CdDev.PartitionStart = Catalog->Boot.Lba;\r
- if (SectorCount < 2) {\r
- //\r
- // When the SectorCount < 2, set the Partition as the whole CD.\r
- //\r
- if (VolSpaceSize > (Media->LastBlock + 1)) {\r
- CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1);\r
- } else {\r
- CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba);\r
- }\r
- } else {\r
- CdDev.PartitionSize = DivU64x32 (\r
- MultU64x32 (\r
- SectorCount,\r
- SubBlockSize\r
- ) + Media->BlockSize - 1,\r
- Media->BlockSize\r
- );\r
- }\r
-\r
- Status = PartitionInstallChildHandle (\r
- This,\r
- Handle,\r
- DiskIo,\r
- BlockIo,\r
- DevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,\r
- Catalog->Boot.Lba,\r
- Catalog->Boot.Lba + CdDev.PartitionSize - 1,\r
- SubBlockSize,\r
- FALSE\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Found = EFI_SUCCESS;\r
- }\r
- }\r
- }\r
-\r
- FreePool (VolDescriptor);\r
-\r
- return Found;\r
-}\r