REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3739 Update all use of EFI_D_* defines in DEBUG() macros to DEBUG_* defines. Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael Kubacki <michael.kubacki@microsoft.com> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			276 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Decode an El Torito formatted CD-ROM
 | 
						|
 | 
						|
Copyright (c) 2018 Qualcomm Datacenter Technologies, Inc.
 | 
						|
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
 | 
						|
#include "Partition.h"
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Install child handles if the Handle supports El Torito format.
 | 
						|
 | 
						|
  @param[in]  This        Calling context.
 | 
						|
  @param[in]  Handle      Parent Handle.
 | 
						|
  @param[in]  DiskIo      Parent DiskIo interface.
 | 
						|
  @param[in]  DiskIo2     Parent DiskIo2 interface.
 | 
						|
  @param[in]  BlockIo     Parent BlockIo interface.
 | 
						|
  @param[in]  BlockIo2    Parent BlockIo2 interface.
 | 
						|
  @param[in]  DevicePath  Parent Device Path
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         Child handle(s) was added.
 | 
						|
  @retval EFI_MEDIA_CHANGED   Media changed Detected.
 | 
						|
  @retval other               no child handle was added.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PartitionInstallElToritoChildHandles (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN  EFI_HANDLE                   Handle,
 | 
						|
  IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
 | 
						|
  IN  EFI_DISK_IO2_PROTOCOL        *DiskIo2,
 | 
						|
  IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
 | 
						|
  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
 | 
						|
  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
  UINT64                       VolDescriptorOffset;
 | 
						|
  UINT32                       Lba2KB;
 | 
						|
  EFI_BLOCK_IO_MEDIA           *Media;
 | 
						|
  CDROM_VOLUME_DESCRIPTOR      *VolDescriptor;
 | 
						|
  ELTORITO_CATALOG             *Catalog;
 | 
						|
  UINTN                        Check;
 | 
						|
  UINTN                        Index;
 | 
						|
  UINTN                        BootEntry;
 | 
						|
  UINTN                        MaxIndex;
 | 
						|
  UINT16                       *CheckBuffer;
 | 
						|
  CDROM_DEVICE_PATH            CdDev;
 | 
						|
  UINT32                       SubBlockSize;
 | 
						|
  UINT32                       SectorCount;
 | 
						|
  EFI_STATUS                   Found;
 | 
						|
  UINT32                       VolSpaceSize;
 | 
						|
  EFI_PARTITION_INFO_PROTOCOL  PartitionInfo;
 | 
						|
 | 
						|
  Found         = EFI_NOT_FOUND;
 | 
						|
  Media         = BlockIo->Media;
 | 
						|
 | 
						|
  VolSpaceSize  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // CD_ROM has the fixed block size as 2048 bytes (SIZE_2KB)
 | 
						|
  //
 | 
						|
 | 
						|
  // If the ISO image has been copied onto a different storage media
 | 
						|
  // then the block size might be different (eg: USB).
 | 
						|
  // Ensure 2048 (SIZE_2KB) is a multiple of block size
 | 
						|
  if (((SIZE_2KB % Media->BlockSize) != 0) || (Media->BlockSize > SIZE_2KB)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  VolDescriptor = AllocatePool ((UINTN)SIZE_2KB);
 | 
						|
 | 
						|
  if (VolDescriptor == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  Catalog = (ELTORITO_CATALOG *) VolDescriptor;
 | 
						|
 | 
						|
  //
 | 
						|
  // Loop: handle one volume descriptor per time
 | 
						|
  //       The ISO-9660 volume descriptor starts at 32k on the media
 | 
						|
  //
 | 
						|
  for (VolDescriptorOffset = SIZE_32KB;
 | 
						|
       VolDescriptorOffset <= MultU64x32 (Media->LastBlock, Media->BlockSize);
 | 
						|
       VolDescriptorOffset += SIZE_2KB) {
 | 
						|
    Status = DiskIo->ReadDisk (
 | 
						|
                       DiskIo,
 | 
						|
                       Media->MediaId,
 | 
						|
                       VolDescriptorOffset,
 | 
						|
                       SIZE_2KB,
 | 
						|
                       VolDescriptor
 | 
						|
                       );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Found = Status;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Check for valid volume descriptor signature
 | 
						|
    //
 | 
						|
    if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
 | 
						|
        CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
 | 
						|
        ) {
 | 
						|
      //
 | 
						|
      // end of Volume descriptor list
 | 
						|
      //
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte,
 | 
						|
    // the 32-bit numerical values is stored in Both-byte orders
 | 
						|
    //
 | 
						|
    if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) {
 | 
						|
      VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0];
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Is it an El Torito volume descriptor?
 | 
						|
    //
 | 
						|
    if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Read in the boot El Torito boot catalog
 | 
						|
    // The LBA unit used by El Torito boot catalog is 2KB unit
 | 
						|
    //
 | 
						|
    Lba2KB = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
 | 
						|
    // Ensure the LBA (in 2KB unit) fits into our media
 | 
						|
    if (Lba2KB * (SIZE_2KB / Media->BlockSize) > Media->LastBlock) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = DiskIo->ReadDisk (
 | 
						|
                       DiskIo,
 | 
						|
                       Media->MediaId,
 | 
						|
                       MultU64x32 (Lba2KB, SIZE_2KB),
 | 
						|
                       SIZE_2KB,
 | 
						|
                       Catalog
 | 
						|
                       );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "EltCheckDevice: error reading catalog %r\n", Status));
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // We don't care too much about the Catalog header's contents, but we do want
 | 
						|
    // to make sure it looks like a Catalog header
 | 
						|
    //
 | 
						|
    if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n"));
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Check       = 0;
 | 
						|
    CheckBuffer = (UINT16 *) Catalog;
 | 
						|
    for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
 | 
						|
      Check += CheckBuffer[Index];
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Check & 0xFFFF) != 0) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"));
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG);
 | 
						|
    for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) {
 | 
						|
      //
 | 
						|
      // Next entry
 | 
						|
      //
 | 
						|
      Catalog += 1;
 | 
						|
 | 
						|
      //
 | 
						|
      // Check this entry
 | 
						|
      //
 | 
						|
      if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      SubBlockSize  = 512;
 | 
						|
      SectorCount   = Catalog->Boot.SectorCount;
 | 
						|
 | 
						|
      switch (Catalog->Boot.MediaType) {
 | 
						|
 | 
						|
      case ELTORITO_NO_EMULATION:
 | 
						|
        SubBlockSize = Media->BlockSize;
 | 
						|
        break;
 | 
						|
 | 
						|
      case ELTORITO_HARD_DISK:
 | 
						|
        break;
 | 
						|
 | 
						|
      case ELTORITO_12_DISKETTE:
 | 
						|
        SectorCount = 0x50 * 0x02 * 0x0F;
 | 
						|
        break;
 | 
						|
 | 
						|
      case ELTORITO_14_DISKETTE:
 | 
						|
        SectorCount = 0x50 * 0x02 * 0x12;
 | 
						|
        break;
 | 
						|
 | 
						|
      case ELTORITO_28_DISKETTE:
 | 
						|
        SectorCount = 0x50 * 0x02 * 0x24;
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        DEBUG ((DEBUG_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
 | 
						|
        SectorCount   = 0;
 | 
						|
        SubBlockSize  = Media->BlockSize;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Create child device handle
 | 
						|
      //
 | 
						|
      CdDev.Header.Type     = MEDIA_DEVICE_PATH;
 | 
						|
      CdDev.Header.SubType  = MEDIA_CDROM_DP;
 | 
						|
      SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
 | 
						|
 | 
						|
      if (Index == 1) {
 | 
						|
        //
 | 
						|
        // This is the initial/default entry
 | 
						|
        //
 | 
						|
        BootEntry = 0;
 | 
						|
      }
 | 
						|
 | 
						|
      CdDev.BootEntry = (UINT32) BootEntry;
 | 
						|
      BootEntry++;
 | 
						|
      CdDev.PartitionStart = Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize);
 | 
						|
      if (SectorCount < 2) {
 | 
						|
        //
 | 
						|
        // When the SectorCount < 2, set the Partition as the whole CD.
 | 
						|
        //
 | 
						|
        if (VolSpaceSize * (SIZE_2KB / Media->BlockSize) > (Media->LastBlock + 1)) {
 | 
						|
          CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize) + 1);
 | 
						|
        } else {
 | 
						|
          CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba) * (SIZE_2KB / Media->BlockSize);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        CdDev.PartitionSize = DivU64x32 (
 | 
						|
                                MultU64x32 (
 | 
						|
                                  SectorCount * (SIZE_2KB / Media->BlockSize),
 | 
						|
                                  SubBlockSize
 | 
						|
                                  ) + Media->BlockSize - 1,
 | 
						|
                                Media->BlockSize
 | 
						|
                                );
 | 
						|
      }
 | 
						|
 | 
						|
      ZeroMem (&PartitionInfo, sizeof (EFI_PARTITION_INFO_PROTOCOL));
 | 
						|
      PartitionInfo.Revision = EFI_PARTITION_INFO_PROTOCOL_REVISION;
 | 
						|
      PartitionInfo.Type     = PARTITION_TYPE_OTHER;
 | 
						|
 | 
						|
      Status = PartitionInstallChildHandle (
 | 
						|
                This,
 | 
						|
                Handle,
 | 
						|
                DiskIo,
 | 
						|
                DiskIo2,
 | 
						|
                BlockIo,
 | 
						|
                BlockIo2,
 | 
						|
                DevicePath,
 | 
						|
                (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
 | 
						|
                &PartitionInfo,
 | 
						|
                Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize),
 | 
						|
                Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize) + CdDev.PartitionSize - 1,
 | 
						|
                SubBlockSize,
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Found = EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (VolDescriptor);
 | 
						|
 | 
						|
  return Found;
 | 
						|
}
 |