Beispiel #1
0
/**
  This function finds Eltorito partitions. Main algorithm
  is ported from DXE partition driver.

  @param  PrivateData       The global memory map 
  @param  ParentBlockDevNo  The parent block device 

  @retval TRUE              New partitions are detected and logical block devices 
                            are  added to block device array 
  @retval FALSE             No New partitions are added;

**/
BOOLEAN
FatFindEltoritoPartitions (
  IN  PEI_FAT_PRIVATE_DATA *PrivateData,
  IN  UINTN                ParentBlockDevNo
  )
{
  EFI_STATUS              Status;
  BOOLEAN                 Found;
  PEI_FAT_BLOCK_DEVICE    *BlockDev;
  PEI_FAT_BLOCK_DEVICE    *ParentBlockDev;
  UINT32                  VolDescriptorLba;
  UINT32                  Lba;
  CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
  ELTORITO_CATALOG        *Catalog;
  UINTN                   Check;
  UINTN                   Index;
  UINTN                   MaxIndex;
  UINT16                  *CheckBuffer;
  UINT32                  SubBlockSize;
  UINT32                  SectorCount;
  UINT32                  VolSpaceSize;

  if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
    return FALSE;
  }

  Found           = FALSE;
  ParentBlockDev  = &(PrivateData->BlockDevice[ParentBlockDevNo]);
  VolSpaceSize    = 0;

  //
  // CD_ROM has the fixed block size as 2048 bytes
  //
  if (ParentBlockDev->BlockSize != 2048) {
    return FALSE;
  }

  VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;
  Catalog       = (ELTORITO_CATALOG *) VolDescriptor;

  //
  // the ISO-9660 volume descriptor starts at 32k on the media
  // and CD_ROM has the fixed block size as 2048 bytes, so...
  //
  VolDescriptorLba = 15;
  //
  // ((16*2048) / Media->BlockSize) - 1;
  //
  // Loop: handle one volume descriptor per time
  //
  while (TRUE) {

    VolDescriptorLba += 1;
    if (VolDescriptorLba > ParentBlockDev->LastBlock) {
      //
      // We are pointing past the end of the device so exit
      //
      break;
    }

    Status = FatReadBlock (
              PrivateData,
              ParentBlockDevNo,
              VolDescriptorLba,
              ParentBlockDev->BlockSize,
              VolDescriptor
              );
    if (EFI_ERROR (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
    //
    if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {
      VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];
    }
    //
    // 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
    //
    Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
    if (Lba > ParentBlockDev->LastBlock) {
      continue;
    }

    Status = FatReadBlock (
              PrivateData,
              ParentBlockDevNo,
              Lba,
              ParentBlockDev->BlockSize,
              Catalog
              );
    if (EFI_ERROR (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) {
      continue;
    }

    Check       = 0;
    CheckBuffer = (UINT16 *) Catalog;
    for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
      Check += CheckBuffer[Index];
    }

    if ((Check & 0xFFFF) != 0) {
      continue;
    }

    MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);
    for (Index = 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  = ParentBlockDev->BlockSize;
        SectorCount   = Catalog->Boot.SectorCount;
        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:
        SectorCount   = 0;
        SubBlockSize  = ParentBlockDev->BlockSize;
        break;
      }

      if (SectorCount < 2) {
        SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);
      }
      //
      // Register this partition
      //
      if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {

        Found                       = TRUE;

        BlockDev                    = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);

        BlockDev->BlockSize         = SubBlockSize;
        BlockDev->LastBlock         = SectorCount - 1;
        BlockDev->IoAlign           = ParentBlockDev->IoAlign;
        BlockDev->Logical           = TRUE;
        BlockDev->PartitionChecked  = FALSE;
        BlockDev->StartingPos       = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize);
        BlockDev->ParentDevNo       = ParentBlockDevNo;

        PrivateData->BlockDeviceCount++;
      }
    }
  }

  ParentBlockDev->PartitionChecked = TRUE;

  return Found;

}
Beispiel #2
0
/**
  Disk reading.

  @param  PrivateData       the global memory map; 
  @param  BlockDeviceNo     the block device to read; 
  @param  StartingAddress   the starting address. 
  @param  Size              the amount of data to read. 
  @param  Buffer            the buffer holding the data 

  @retval EFI_SUCCESS       The function completed successfully.
  @retval EFI_DEVICE_ERROR  Something error.

**/
EFI_STATUS
FatReadDisk (
  IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
  IN  UINTN                 BlockDeviceNo,
  IN  UINT64                StartingAddress,
  IN  UINTN                 Size,
  OUT VOID                  *Buffer
  )
{
  EFI_STATUS  Status;
  UINT32      BlockSize;
  CHAR8       *BufferPtr;
  CHAR8       *CachePtr;
  UINT32      Offset;
  UINT64      Lba;
  UINT64      OverRunLba;
  UINTN       Amount;

  Status    = EFI_SUCCESS;
  BufferPtr = Buffer;
  BlockSize = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;

  //
  // Read underrun
  //
  Lba     = DivU64x32Remainder (StartingAddress, BlockSize, &Offset);
  Status  = FatGetCacheBlock (PrivateData, BlockDeviceNo, Lba, &CachePtr);
  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  Amount = Size < (BlockSize - Offset) ? Size : (BlockSize - Offset);
  CopyMem (BufferPtr, CachePtr + Offset, Amount);

  if (Size == Amount) {
    return EFI_SUCCESS;
  }

  Size -= Amount;
  BufferPtr += Amount;
  StartingAddress += Amount;
  Lba += 1;

  //
  // Read aligned parts
  //
  OverRunLba = Lba + DivU64x32Remainder (Size, BlockSize, &Offset);

  Size -= Offset;
  Status = FatReadBlock (PrivateData, BlockDeviceNo, Lba, Size, BufferPtr);
  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  BufferPtr += Size;

  //
  // Read overrun
  //
  if (Offset != 0) {
    Status = FatGetCacheBlock (PrivateData, BlockDeviceNo, OverRunLba, &CachePtr);
    if (EFI_ERROR (Status)) {
      return EFI_DEVICE_ERROR;
    }

    CopyMem (BufferPtr, CachePtr, Offset);
  }

  return Status;
}
Beispiel #3
0
/**
  This function finds Mbr partitions. Main algorithm
  is ported from DXE partition driver.

  @param  PrivateData       The global memory map 
  @param  ParentBlockDevNo  The parent block device 

  @retval TRUE              New partitions are detected and logical block devices 
                            are  added to block device array 
  @retval FALSE             No New partitions are added;

**/
BOOLEAN
FatFindMbrPartitions (
  IN  PEI_FAT_PRIVATE_DATA *PrivateData,
  IN  UINTN                ParentBlockDevNo
  )
{
  EFI_STATUS            Status;
  MASTER_BOOT_RECORD    *Mbr;
  UINTN                 Index;
  BOOLEAN               Found;
  PEI_FAT_BLOCK_DEVICE  *ParentBlockDev;
  PEI_FAT_BLOCK_DEVICE  *BlockDev;

  if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
    return FALSE;
  }

  ParentBlockDev  = &(PrivateData->BlockDevice[ParentBlockDevNo]);

  Found           = FALSE;
  Mbr             = (MASTER_BOOT_RECORD *) PrivateData->BlockData;

  Status = FatReadBlock (
            PrivateData,
            ParentBlockDevNo,
            0,
            ParentBlockDev->BlockSize,
            Mbr
            );

  if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {
    goto Done;
  }
  //
  // We have a valid mbr - add each partition
  //
  for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
    if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
      //
      // Don't use null MBR entries
      //
      continue;
    }
    //
    // Register this partition
    //
    if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {

      Found                       = TRUE;

      BlockDev                    = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);

      BlockDev->BlockSize         = MBR_SIZE;
      BlockDev->LastBlock         = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;
      BlockDev->IoAlign           = ParentBlockDev->IoAlign;
      BlockDev->Logical           = TRUE;
      BlockDev->PartitionChecked  = FALSE;
      BlockDev->StartingPos = MultU64x32 (
                                UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),
                                ParentBlockDev->BlockSize
                                );
      BlockDev->ParentDevNo = ParentBlockDevNo;

      PrivateData->BlockDeviceCount++;
    }
  }

Done:

  ParentBlockDev->PartitionChecked = TRUE;
  return Found;
}
Beispiel #4
0
/**
  Find a cache block designated to specific Block device and Lba.
  If not found, invalidate an oldest one and use it. (LRU cache)

  @param  PrivateData       the global memory map. 
  @param  BlockDeviceNo     the Block device. 
  @param  Lba               the Logical Block Address 
  @param  CachePtr          Ptr to the starting address of the memory holding the 
                            data; 

  @retval EFI_SUCCESS       The function completed successfully.
  @retval EFI_DEVICE_ERROR  Something error while accessing media.

**/
EFI_STATUS
FatGetCacheBlock (
  IN  PEI_FAT_PRIVATE_DATA  *PrivateData,
  IN  UINTN                 BlockDeviceNo,
  IN  UINT64                Lba,
  OUT CHAR8                 **CachePtr
  )
{
  EFI_STATUS            Status;
  PEI_FAT_CACHE_BUFFER  *CacheBuffer;
  INTN                  Index;
  STATIC UINT8          Seed;

  Status      = EFI_SUCCESS;
  CacheBuffer = NULL;

  //
  // go through existing cache buffers
  //
  for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {
    CacheBuffer = &(PrivateData->CacheBuffer[Index]);
    if (CacheBuffer->Valid && CacheBuffer->BlockDeviceNo == BlockDeviceNo && CacheBuffer->Lba == Lba) {
      break;
    }
  }

  if (Index < PEI_FAT_CACHE_SIZE) {
    *CachePtr = (CHAR8 *) CacheBuffer->Buffer;
    return EFI_SUCCESS;
  }
  //
  // We have to find an invalid cache buffer
  //
  for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {
    if (!PrivateData->CacheBuffer[Index].Valid) {
      break;
    }
  }
  //
  // Use the cache buffer
  //
  if (Index == PEI_FAT_CACHE_SIZE) {
    Index = (Seed++) % PEI_FAT_CACHE_SIZE;
  }
  
  //
  // Current device ID should be less than maximum device ID. 
  //
  if (BlockDeviceNo >= PEI_FAT_MAX_BLOCK_DEVICE) {
    return EFI_DEVICE_ERROR;
  }

  CacheBuffer                 = &(PrivateData->CacheBuffer[Index]);

  CacheBuffer->BlockDeviceNo  = BlockDeviceNo;
  CacheBuffer->Lba            = Lba;
  CacheBuffer->Size           = PrivateData->BlockDevice[BlockDeviceNo].BlockSize;

  //
  // Read in the data
  //
  Status = FatReadBlock (
            PrivateData,
            BlockDeviceNo,
            Lba,
            CacheBuffer->Size,
            CacheBuffer->Buffer
            );
  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  CacheBuffer->Valid  = TRUE;
  *CachePtr           = (CHAR8 *) CacheBuffer->Buffer;

  return Status;
}