Exemplo n.º 1
0
// Clear a file's image description on storage media:
// UEFI allows you to seek past the end of a file, a subsequent write will grow
// the file. It does not specify how space between the former end of the file
// and the beginning of the write should be filled. It's therefore possible that
// BootMonFs metadata, that comes after the end of a file, could be left there
// and wrongly detected by BootMonFsImageInBlock.
STATIC
EFI_STATUS
InvalidateImageDescription (
  IN  BOOTMON_FS_FILE  *File
  )
{
  EFI_DISK_IO_PROTOCOL   *DiskIo;
  EFI_BLOCK_IO_PROTOCOL  *BlockIo;
  UINT32                  MediaId;
  UINT32                  BlockSize;
  VOID                   *Buffer;
  EFI_STATUS              Status;
  UINT64                  DescriptionAddress;

  DiskIo = File->Instance->DiskIo;
  BlockIo = File->Instance->BlockIo;
  MediaId = BlockIo->Media->MediaId;
  BlockSize = BlockIo->Media->BlockSize;

  DescriptionAddress = (File->HwDescription.BlockEnd * BlockSize)
                       - sizeof (HW_IMAGE_DESCRIPTION);

  Buffer = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION));

  Status = DiskIo->WriteDisk (DiskIo,
                    MediaId,
                    DescriptionAddress,
                    sizeof (HW_IMAGE_DESCRIPTION),
                    Buffer
                    );

  FreePool(Buffer);

  return Status;
}
Exemplo n.º 2
0
static bool ntfs_device_uefi_io_writesectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer)
{
    // Get the device driver descriptor
    struct _uefi_fd *fd = DEV_FD(dev);
	UINT64	_sectorStart;
	UINT64	_bufferSize;

	EFI_DISK_IO_PROTOCOL *DiskIo = fd->interface->DiskIo;

	ntfs_log_trace("ntfs_device_uefi_io_writesectors\n\r");

    if (!fd) {
        errno = EBADF;
        return false;
    }

    // Write the sectors to disc (or cache, if enabled)
	if (fd->cache) {
        //return _NTFS_cache_writeSectors(fd->cache, sector, numSectors, buffer);
		ntfs_log_perror("ntfs_device_uefi_io_writesectors cache enabled?!?!");
	}
    else
	{
		while(numSectors > 0)
		{
			//AsciiPrint("DiskIo.ReadDisk sectors %x\n\r", (UINTN) numSectors );
			_sectorStart = sector * fd->sectorSize;
			_bufferSize = fd->sectorSize;

			if (DiskIo->WriteDisk(DiskIo, fd->interface->MediaId, _sectorStart, _bufferSize, buffer) != EFI_SUCCESS)
			{
				//AsciiPrint("DiskIo %x\n\r", DiskIo);
				//AsciiPrint("MediaId %x\n\r", fd->interface->MediaId);
				//AsciiPrint("sector %x%x\n\r", (UINTN) sector * fd->sectorSize);
				//AsciiPrint("numSectors %x%x\n\r", (UINTN)  fd->sectorSize);
				//AsciiPrint("buffer %x\n\r", buffer);
				//AsciiPrint("ntfs_device_uefi_io_writesectors [DISKIO!WRITEDISK] FAILED!!!\n\r");
				return false;
			}

			numSectors--;	// decrease sector count
			sector++;		// increase sector start
			buffer = CALC_OFFSET(void *, buffer, fd->sectorSize);	// move ptr!
		}
	}

        //return fd->interface->writeSectors(sector, numSectors, buffer);

    return true;
}
Exemplo n.º 3
0
static bool ntfs_device_uefi_io_readsectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer)
{
    // Get the device driver descriptor
    struct _uefi_fd *fd = DEV_FD(dev);
	EFI_DISK_IO_PROTOCOL *DiskIo = fd->interface->DiskIo;
	UINT64 _sectorStart, _bufferSize;

	//AsciiPrint("ntfs_device_uefi_io_readsectors(sector %x, numSectors %x)\n\r", (UINTN) sector, (UINTN) numSectors);

	ntfs_log_trace("ntfs_device_uefi_io_readsectors {%x,%d,%d}", dev, sector, numSectors);
    if (!fd) {
        errno = EBADF;
        return false;
    }
    // Read the sectors from disc (or cache, if enabled)
	if (fd->cache) {
		//return _NTFS_cache_readSectors(fd->cache, sector, numSectors, buffer);
		ntfs_log_trace("ntfs_device_uefi_io_readsectors cache enabled?!?!");
	}
    else
	{
		while(numSectors > 0)
		{
			//AsciiPrint("DiskIo.ReadDisk sectors %x\n\r", (UINTN) numSectors );
			_sectorStart = sector * fd->sectorSize;
			_bufferSize = fd->sectorSize;

			if (DiskIo->ReadDisk(DiskIo, fd->interface->MediaId, _sectorStart, _bufferSize, buffer) != EFI_SUCCESS)
			{
				/*AsciiPrint("DiskIo %x\n\r", DiskIo);
				AsciiPrint("MediaId %x\n\r", fd->interface->MediaId);
				AsciiPrint("sector %x%x\n\r", (UINTN) sector * fd->sectorSize);
				AsciiPrint("numSectors %x%x\n\r", (UINTN)  fd->sectorSize);
				AsciiPrint("buffer %x\n\r", buffer);
				AsciiPrint("ntfs_device_uefi_io_readsectors [DISKIO!READDISK] FAILED!!!\n\r");*/
				ntfs_log_trace("failed I/O!");
				return false;
			}

			numSectors--;	// decrease sector count
			sector++;		// increase sector start
			buffer = CALC_OFFSET(void *, buffer, fd->sectorSize);	// move ptr!
		}


		//ReadDisk(DiskIo, fd->Volume->MediaId, fd->startSector * fd->sectorSize, sizeof(NTFS_BOOT_SECTOR), boot) 
	}

    return true;
}
Exemplo n.º 4
0
/**
 * ntfs_device_uefi_io_pread - Perform a positioned read from the device
 * @dev:
 * @buf:
 * @count:
 * @offset:
 *
 * Description...
 *
 * Returns:
 */
static s64 ntfs_device_uefi_io_pread(struct ntfs_device *dev, void *buf,
                                     s64 count, s64 offset)
{
    EFI_DISK_IO_PROTOCOL *DiskIo;
    NTFS_VOLUME *Volume;

    Volume = (NTFS_VOLUME *) dev->d_private;

    if (NDevReadOnly(dev)) {
        errno = EROFS;
        return -1;
    }

    NDevSetDirty(dev);

    DiskIo = Volume->DiskIo;
    DiskIo->ReadDisk (DiskIo, Volume->MediaId, offset, count, buf);

    return 0;
}
Exemplo n.º 5
0
/**
 * ntfs_device_uefi_io_write - Write to the device, at the current location
 * @dev:
 * @buf:
 * @count:
 *
 * Description...
 *
 * Returns:
 */
static s64 ntfs_device_uefi_io_write(struct ntfs_device *dev, const void *buf,
                                     s64 count)
{
    EFI_DISK_IO_PROTOCOL *DiskIo;
    NTFS_VOLUME *Volume;

    Volume = (NTFS_VOLUME *) dev->d_private;

    if (NDevReadOnly(dev)) {
        errno = EROFS;
        return -1;
    }

    NDevSetDirty(dev);

    DiskIo = Volume->DiskIo;
    DiskIo->WriteDisk (DiskIo, Volume->MediaId, 0, count, buf);

    return 0; //write(DEV_FD(dev), buf, count);
}
Exemplo n.º 6
0
static int ntfs_device_uefi_io_open(struct ntfs_device *dev, int flags)
{
	NTFS_BOOT_SECTOR *boot;
	EFI_DISK_IO_PROTOCOL *DiskIo;
	NTFS_VOLUME *Volume;

	struct _uefi_fd *fd = DEV_FD(dev);
	Volume = fd->interface;

	ntfs_log_trace("dev %p, flags %i\n", dev, flags);

	
    // Get the device driver descriptor
    if (!fd) {
        errno = EBADF;
        return -1;
    }

    // Get the device interface
	DiskIo = Volume->DiskIo;

    if (!DiskIo) {
        errno = ENODEV;
        return -1;
    }

    // Start the device interface and ensure that it is inserted
    //if (!interface->startup()) {
     //   ntfs_log_perror("device failed to start\n");
      //  errno = EIO;
      //  return -1;
   // }
    //if (!interface->isInserted()) {
     //   ntfs_log_perror("device media is not inserted\n");
      //  errno = EIO;
       // return -1;
    //}

    // Check that the device isn't already open (used by another volume?)
    if (NDevOpen(dev)) {
		//AsciiPrint("ntfs_device_uefi_io_open...BUSY\n\r");
        ntfs_log_perror("device is busy (already open)\n");
        errno = EBUSY;
        return -1;
    }

    // Check that there is a valid NTFS boot sector at the start of the device
    boot = (NTFS_BOOT_SECTOR *) ntfs_alloc(MAX_SECTOR_SIZE);
    if(boot == NULL) {
		//AsciiPrint("ntfs_device_uefi_io_open...ENOMEM\n\r");
        errno = ENOMEM;
        return -1;
    }

	 
	
	 if (DiskIo->ReadDisk(DiskIo, Volume->MediaId, 0, sizeof(NTFS_BOOT_SECTOR), boot) != EFI_SUCCESS) {
		//AsciiPrint("DiskIo ptr %x\n\r", DiskIo);
		//AsciiPrint("interface ptr %x\n\r", fd->interface);
		//AsciiPrint("DiskIo->ReadDisk(%x,%x,%x)\n\r", fd->interface->MediaId, fd->startSector * fd->sectorSize, sizeof(NTFS_BOOT_SECTOR));
		//AsciiPrint("Sector size: %x\n\r", fd->sectorSize);
		//AsciiPrint("ntfs_device_uefi_io_open...read failure boot sector\n\r");
		ntfs_log_perror("read failure @ sector %x\n", fd->startSector);
        errno = EIO;
        ntfs_free(boot);
        return -1;
	}

    if (!ntfs_boot_sector_is_ntfs(boot)) {
		//AsciiPrint("ntfs_device_uefi_io_open...EINVALIDPART\n\r");
        errno = EINVALPART;
        ntfs_free(boot);
        return -1;
    }

    // Parse the boot sector
    fd->hiddenSectors = le32_to_cpu(boot->bpb.hidden_sectors);
    fd->sectorSize = le16_to_cpu(boot->bpb.bytes_per_sector);
    fd->sectorCount = sle64_to_cpu(boot->number_of_sectors);
    fd->pos = 0;
    fd->len = (fd->sectorCount * fd->sectorSize);
    fd->ino = le64_to_cpu(boot->volume_serial_number);

    // Free memory for boot sector
    ntfs_free(boot);

    // Mark the device as read-only (if required)
    if (flags & O_RDONLY) {
        NDevSetReadOnly(dev);
    }

    // cache disabled!
    fd->cache = NULL;
		//_NTFS_cache_constructor(fd->cachePageCount, fd->cachePageSize, interface, fd->startSector + fd->sectorCount, fd->sectorSize);

    // Mark the device as open
    NDevSetBlock(dev);
    NDevSetOpen(dev);

	//AsciiPrint("ntfs_device_uefi_io_open...success\n\r");
    return 0;
}
Exemplo n.º 7
0
EFI_STATUS
ArmFastbootPlatformFlashPartition (
  IN CHAR8  *PartitionName,
  IN UINTN   Size,
  IN VOID   *Image
  )
{
  EFI_STATUS               Status;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;
  EFI_DISK_IO_PROTOCOL    *DiskIo;
  UINT32                   MediaId;
  UINTN                    PartitionSize;
  FASTBOOT_PARTITION_LIST *Entry;
  CHAR16                   PartitionNameUnicode[60];
  BOOLEAN                  PartitionFound;

  AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode);

  PartitionFound = FALSE;
  Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead));
  while (!IsNull (&mPartitionListHead, &Entry->Link)) {
    // Search the partition list for the partition named by PartitionName
    if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) {
      PartitionFound = TRUE;
      break;
    }

   Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link);
  }
  if (!PartitionFound) {
    return EFI_NOT_FOUND;
  }

  Status = gBS->OpenProtocol (
                  Entry->PartitionHandle,
                  &gEfiBlockIoProtocolGuid,
                  (VOID **) &BlockIo,
                  gImageHandle,
                  NULL,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status));
    return EFI_NOT_FOUND;
  }

  // Check image will fit on device
  PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize;
  if (PartitionSize < Size) {
    DEBUG ((EFI_D_ERROR, "Partition not big enough.\n"));
    DEBUG ((EFI_D_ERROR, "Partition Size:\t%d\nImage Size:\t%d\n", PartitionSize, Size));

    return EFI_VOLUME_FULL;
  }

  MediaId = BlockIo->Media->MediaId;

  Status = gBS->OpenProtocol (
                  Entry->PartitionHandle,
                  &gEfiDiskIoProtocolGuid,
                  (VOID **) &DiskIo,
                  gImageHandle,
                  NULL,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  ASSERT_EFI_ERROR (Status);

  Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  BlockIo->FlushBlocks(BlockIo);

  return Status;
}
Exemplo n.º 8
0
/**

  Detects FAT file system on Disk and set relevant fields of Volume.

  @param Volume                - The volume structure.

  @retval EFI_SUCCESS           - The Fat File System is detected successfully
  @retval EFI_UNSUPPORTED       - The volume is not FAT file system.
  @retval EFI_VOLUME_CORRUPTED  - The volume is corrupted.

**/
EFI_STATUS
FatOpenDevice (
  IN OUT FAT_VOLUME           *Volume
  )
{
  EFI_STATUS            Status;
  UINT32                BlockSize;
  UINT32                DirtyMask;
  EFI_DISK_IO_PROTOCOL  *DiskIo;
  FAT_BOOT_SECTOR       FatBs;
  FAT_VOLUME_TYPE       FatType;
  UINTN                 RootDirSectors;
  UINTN                 FatLba;
  UINTN                 RootLba;
  UINTN                 FirstClusterLba;
  UINTN                 Sectors;
  UINTN                 SectorsPerFat;
  UINT8                 SectorsPerClusterAlignment;
  UINT8                 BlockAlignment;

  //
  // Read the FAT_BOOT_SECTOR BPB info
  // This is the only part of FAT code that uses parent DiskIo,
  // Others use FatDiskIo which utilizes a Cache.
  //
  DiskIo  = Volume->DiskIo;
  Status  = DiskIo->ReadDisk (DiskIo, Volume->MediaId, 0, sizeof (FatBs), &FatBs);

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_INIT, "FatOpenDevice: read of part_lba failed %r\n", Status));
    return Status;
  }

  FatType = FatUndefined;

  //
  // Use LargeSectors if Sectors is 0
  //
  Sectors = FatBs.FatBsb.Sectors;
  if (Sectors == 0) {
    Sectors = FatBs.FatBsb.LargeSectors;
  }

  SectorsPerFat = FatBs.FatBsb.SectorsPerFat;
  if (SectorsPerFat == 0) {
    SectorsPerFat = FatBs.FatBse.Fat32Bse.LargeSectorsPerFat;
    FatType       = Fat32;
  }
  //
  // Is boot sector a fat sector?
  // (Note that so far we only know if the sector is FAT32 or not, we don't
  // know if the sector is Fat16 or Fat12 until later when we can compute
  // the volume size)
  //
  if (FatBs.FatBsb.ReservedSectors == 0 || FatBs.FatBsb.NumFats == 0 || Sectors == 0) {
    return EFI_UNSUPPORTED;
  }

  if ((FatBs.FatBsb.SectorSize & (FatBs.FatBsb.SectorSize - 1)) != 0) {
    return EFI_UNSUPPORTED;
  }

  BlockAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorSize);
  if (BlockAlignment > MAX_BLOCK_ALIGNMENT || BlockAlignment < MIN_BLOCK_ALIGNMENT) {
    return EFI_UNSUPPORTED;
  }

  if ((FatBs.FatBsb.SectorsPerCluster & (FatBs.FatBsb.SectorsPerCluster - 1)) != 0) {
    return EFI_UNSUPPORTED;
  }

  SectorsPerClusterAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorsPerCluster);
  if (SectorsPerClusterAlignment > MAX_SECTORS_PER_CLUSTER_ALIGNMENT) {
    return EFI_UNSUPPORTED;
  }

  if (FatBs.FatBsb.Media <= 0xf7 &&
      FatBs.FatBsb.Media != 0xf0 &&
      FatBs.FatBsb.Media != 0x00 &&
      FatBs.FatBsb.Media != 0x01
      ) {
    return EFI_UNSUPPORTED;
  }
  //
  // Initialize fields the volume information for this FatType
  //
  if (FatType != Fat32) {
    if (FatBs.FatBsb.RootEntries == 0) {
      return EFI_UNSUPPORTED;
    }
    //
    // Unpack fat12, fat16 info
    //
    Volume->RootEntries = FatBs.FatBsb.RootEntries;
  } else {
    //
    // If this is fat32, refuse to mount mirror-disabled volumes
    //
    if ((SectorsPerFat == 0 || FatBs.FatBse.Fat32Bse.FsVersion != 0) || (FatBs.FatBse.Fat32Bse.ExtendedFlags & 0x80)) {
      return EFI_UNSUPPORTED;
    }
    //
    // Unpack fat32 info
    //
    Volume->RootCluster = FatBs.FatBse.Fat32Bse.RootDirFirstCluster;
  }

  Volume->NumFats           = FatBs.FatBsb.NumFats;
  //
  // Compute some fat locations
  //
  BlockSize                 = FatBs.FatBsb.SectorSize;
  RootDirSectors            = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (BlockSize - 1)) / BlockSize;

  FatLba                    = FatBs.FatBsb.ReservedSectors;
  RootLba                   = FatBs.FatBsb.NumFats * SectorsPerFat + FatLba;
  FirstClusterLba           = RootLba + RootDirSectors;

  Volume->FatPos            = FatLba * BlockSize;
  Volume->FatSize           = SectorsPerFat * BlockSize;

  Volume->VolumeSize        = LShiftU64 (Sectors, BlockAlignment);
  Volume->RootPos           = LShiftU64 (RootLba, BlockAlignment);
  Volume->FirstClusterPos   = LShiftU64 (FirstClusterLba, BlockAlignment);
  Volume->MaxCluster        = (Sectors - FirstClusterLba) >> SectorsPerClusterAlignment;
  Volume->ClusterAlignment  = (UINT8)(BlockAlignment + SectorsPerClusterAlignment);
  Volume->ClusterSize       = (UINTN)1 << (Volume->ClusterAlignment);

  //
  // If this is not a fat32, determine if it's a fat16 or fat12
  //
  if (FatType != Fat32) {
    if (Volume->MaxCluster >= FAT_MAX_FAT16_CLUSTER) {
      return EFI_VOLUME_CORRUPTED;
    }

    FatType = Volume->MaxCluster < FAT_MAX_FAT12_CLUSTER ? Fat12 : Fat16;
    //
    // fat12 & fat16 fat-entries are 2 bytes
    //
    Volume->FatEntrySize = sizeof (UINT16);
    DirtyMask            = FAT16_DIRTY_MASK;
  } else {
    if (Volume->MaxCluster < FAT_MAX_FAT16_CLUSTER) {
      return EFI_VOLUME_CORRUPTED;
    }
    //
    // fat32 fat-entries are 4 bytes
    //
    Volume->FatEntrySize = sizeof (UINT32);
    DirtyMask            = FAT32_DIRTY_MASK;
  }
  //
  // Get the DirtyValue and NotDirtyValue
  // We should keep the initial value as the NotDirtyValue
  // in case the volume is dirty already
  //
  if (FatType != Fat12) {
    Status = FatAccessVolumeDirty (Volume, ReadDisk, &Volume->NotDirtyValue);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Volume->DirtyValue = Volume->NotDirtyValue & DirtyMask;
  }
  //
  // If present, read the fat hint info
  //
  if (FatType == Fat32) {
    Volume->FreeInfoPos = FatBs.FatBse.Fat32Bse.FsInfoSector * BlockSize;
    if (FatBs.FatBse.Fat32Bse.FsInfoSector != 0) {
      FatDiskIo (Volume, ReadDisk, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector, NULL);
      if (Volume->FatInfoSector.Signature == FAT_INFO_SIGNATURE &&
          Volume->FatInfoSector.InfoBeginSignature == FAT_INFO_BEGIN_SIGNATURE &&
          Volume->FatInfoSector.InfoEndSignature == FAT_INFO_END_SIGNATURE &&
          Volume->FatInfoSector.FreeInfo.ClusterCount <= Volume->MaxCluster
          ) {
        Volume->FreeInfoValid = TRUE;
      }
    }
  }
  //
  // Just make up a FreeInfo.NextCluster for use by allocate cluster
  //
  if (FAT_MIN_CLUSTER > Volume->FatInfoSector.FreeInfo.NextCluster ||
     Volume->FatInfoSector.FreeInfo.NextCluster > Volume->MaxCluster + 1
     ) {
    Volume->FatInfoSector.FreeInfo.NextCluster = FAT_MIN_CLUSTER;
  }
  //
  // We are now defining FAT Type
  //
  Volume->FatType = FatType;
  ASSERT (FatType != FatUndefined);

  return EFI_SUCCESS;
}
Exemplo n.º 9
0
/**
  Measure GPT table data into TPM log.

  Caution: This function may receive untrusted input.
  The GPT partition table is external input, so this function should parse partition data carefully.

  @param TcgProtocol             Pointer to the located TCG protocol instance.
  @param GptHandle               Handle that GPT partition was installed.

  @retval EFI_SUCCESS            Successfully measure GPT table.
  @retval EFI_UNSUPPORTED        Not support GPT table on the given handle.
  @retval EFI_DEVICE_ERROR       Can't get GPT table because device error.
  @retval EFI_OUT_OF_RESOURCES   No enough resource to measure GPT table.
  @retval other error value
**/
EFI_STATUS
EFIAPI
TcgMeasureGptTable (
  IN  EFI_TCG_PROTOCOL   *TcgProtocol,
  IN  EFI_HANDLE         GptHandle
  )
{
  EFI_STATUS                        Status;
  EFI_BLOCK_IO_PROTOCOL             *BlockIo;
  EFI_DISK_IO_PROTOCOL              *DiskIo;
  EFI_PARTITION_TABLE_HEADER        *PrimaryHeader;
  EFI_PARTITION_ENTRY               *PartitionEntry;
  UINT8                             *EntryPtr;
  UINTN                             NumberOfPartition;
  UINT32                            Index;
  TCG_PCR_EVENT                     *TcgEvent;
  EFI_GPT_DATA                      *GptData;
  UINT32                            EventSize;
  UINT32                            EventNumber;
  EFI_PHYSICAL_ADDRESS              EventLogLastEntry;

  if (mMeasureGptCount > 0) {
    return EFI_SUCCESS;
  }

  Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo);
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }
  Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo);
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }
  //
  // Read the EFI Partition Table Header
  //  
  PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *) AllocatePool (BlockIo->Media->BlockSize);
  if (PrimaryHeader == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }  
  Status = DiskIo->ReadDisk (
                     DiskIo,
                     BlockIo->Media->MediaId,
                     1 * BlockIo->Media->BlockSize,
                     BlockIo->Media->BlockSize,
                     (UINT8 *)PrimaryHeader
                     );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n"));
    FreePool (PrimaryHeader);
    return EFI_DEVICE_ERROR;
  }  
  //
  // Read the partition entry.
  //
  EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry);
  if (EntryPtr == NULL) {
    FreePool (PrimaryHeader);
    return EFI_OUT_OF_RESOURCES;
  }
  Status = DiskIo->ReadDisk (
                     DiskIo,
                     BlockIo->Media->MediaId,
                     MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
                     PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry,
                     EntryPtr
                     );
  if (EFI_ERROR (Status)) {
    FreePool (PrimaryHeader);
    FreePool (EntryPtr);
    return EFI_DEVICE_ERROR;
  }
  
  //
  // Count the valid partition
  //
  PartitionEntry    = (EFI_PARTITION_ENTRY *)EntryPtr;
  NumberOfPartition = 0;
  for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
    if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {
      NumberOfPartition++;  
    }
    PartitionEntry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
  }

  //
  // Prepare Data for Measurement
  // 
  EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) 
                        + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry);
  TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT_HDR));
  if (TcgEvent == NULL) {
    FreePool (PrimaryHeader);
    FreePool (EntryPtr);
    return EFI_OUT_OF_RESOURCES;
  }

  TcgEvent->PCRIndex   = 5;
  TcgEvent->EventType  = EV_EFI_GPT_EVENT;
  TcgEvent->EventSize  = EventSize;
  GptData = (EFI_GPT_DATA *) TcgEvent->Event;  

  //
  // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition
  //  
  CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
  GptData->NumberOfPartitions = NumberOfPartition;
  //
  // Copy the valid partition entry
  //
  PartitionEntry    = (EFI_PARTITION_ENTRY*)EntryPtr;
  NumberOfPartition = 0;
  for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {
    if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) {
      CopyMem (
        (UINT8 *)&GptData->Partitions + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry,
        (UINT8 *)PartitionEntry,
        PrimaryHeader->SizeOfPartitionEntry
        );
      NumberOfPartition++;
    }
    PartitionEntry =(EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntry + PrimaryHeader->SizeOfPartitionEntry);
  }

  //
  // Measure the GPT data
  //
  EventNumber = 1;
  Status = TcgProtocol->HashLogExtendEvent (
             TcgProtocol,
             (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData,
             (UINT64) TcgEvent->EventSize,
             TPM_ALG_SHA,
             TcgEvent,
             &EventNumber,
             &EventLogLastEntry
             );
  if (!EFI_ERROR (Status)) {
    mMeasureGptCount++;
  }

  FreePool (PrimaryHeader);
  FreePool (EntryPtr);
  FreePool (TcgEvent);

  return Status;
}
Exemplo n.º 10
0
// Flush file data that will extend the file's length. Update and, if necessary,
// move the image description.
// We need to pass the file's starting position on media (FileStart), because
// if the file hasn't been flushed before its Description->BlockStart won't
// have been initialised.
// FileStart must be aligned to the media's block size.
// Note that this function uses DiskIo to flush, so call BlockIo->FlushBlocks()
// after calling it.
STATIC
EFI_STATUS
FlushAppendRegion (
  IN BOOTMON_FS_FILE         *File,
  IN BOOTMON_FS_FILE_REGION  *Region,
  IN UINT64                   NewFileSize,
  IN UINT64                   FileStart
  )
{
  EFI_STATUS               Status;
  EFI_DISK_IO_PROTOCOL    *DiskIo;
  UINTN                    BlockSize;
  HW_IMAGE_DESCRIPTION    *Description;

  DiskIo = File->Instance->DiskIo;

  BlockSize = File->Instance->BlockIo->Media->BlockSize;

  ASSERT (FileStart % BlockSize == 0);

  // Only invalidate the Image Description of files that have already been
  // written in Flash
  if (File->HwDescription.RegionCount > 0) {
    Status = InvalidateImageDescription (File);
    ASSERT_EFI_ERROR (Status);
  }

  //
  // Update File Description
  //
  Description = &File->HwDescription;
  Description->Attributes = 1;
  Description->BlockStart = FileStart / BlockSize;
  Description->BlockEnd = Description->BlockStart + (NewFileSize / BlockSize);
  Description->Footer.FooterSignature1 = HW_IMAGE_FOOTER_SIGNATURE_1;
  Description->Footer.FooterSignature2 = HW_IMAGE_FOOTER_SIGNATURE_2;
  Description->Footer.Version = HW_IMAGE_FOOTER_VERSION;
  Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET;
  Description->RegionCount = 1;
  Description->Region[0].Checksum = 0;
  Description->Region[0].Offset = Description->BlockStart * BlockSize;
  Description->Region[0].Size = NewFileSize - sizeof (HW_IMAGE_DESCRIPTION);

  Status = BootMonFsComputeFooterChecksum (Description);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  // Write the new file data
  Status = DiskIo->WriteDisk (
                    DiskIo,
                    File->Instance->Media->MediaId,
                    FileStart + Region->Offset,
                    Region->Size,
                    Region->Buffer
                    );
  ASSERT_EFI_ERROR (Status);

  // Round the file size up to the nearest block size
  if ((NewFileSize % BlockSize) > 0) {
    NewFileSize += BlockSize - (NewFileSize % BlockSize);
  }
  // Update the file description on the media
  Status = DiskIo->WriteDisk (
                    DiskIo,
                    File->Instance->Media->MediaId,
                    (FileStart + NewFileSize) - sizeof (HW_IMAGE_DESCRIPTION),
                    sizeof (HW_IMAGE_DESCRIPTION),
                    Description
                    );
  ASSERT_EFI_ERROR (Status);

  return Status;
}
Exemplo n.º 11
0
EFIAPI
EFI_STATUS
BootMonFsFlushFile (
  IN EFI_FILE_PROTOCOL  *This
  )
{
  EFI_STATUS               Status;
  BOOTMON_FS_INSTANCE     *Instance;
  LIST_ENTRY              *RegionToFlushLink;
  BOOTMON_FS_FILE         *File;
  BOOTMON_FS_FILE         *NextFile;
  BOOTMON_FS_FILE_REGION  *Region;
  LIST_ENTRY              *FileLink;
  UINTN                    CurrentPhysicalSize;
  UINTN                    BlockSize;
  UINT64                   FileStart;
  UINT64                   FileEnd;
  UINT64                   RegionStart;
  UINT64                   RegionEnd;
  UINT64                   NewFileSize;
  UINT64                   EndOfAppendSpace;
  BOOLEAN                  HasSpace;
  EFI_DISK_IO_PROTOCOL    *DiskIo;
  EFI_BLOCK_IO_PROTOCOL   *BlockIo;

  Status      = EFI_SUCCESS;
  FileStart   = 0;

  File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
  if (File == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  // Check if the file needs to be flushed
  if (!BootMonFsFileNeedFlush (File)) {
    return Status;
  }

  Instance = File->Instance;
  BlockIo = Instance->BlockIo;
  DiskIo = Instance->DiskIo;
  BlockSize = BlockIo->Media->BlockSize;

  // If the file doesn't exist then find a space for it
  if (File->HwDescription.RegionCount == 0) {
    Status = BootMonFsFindSpaceForNewFile (File, &FileStart);
    // FileStart has changed so we need to recompute RegionEnd
    if (EFI_ERROR (Status)) {
      return Status;
    }
  } else {
    FileStart = File->HwDescription.BlockStart * BlockSize;
  }

  // FileEnd is the NOR address of the end of the file's data
  FileEnd = FileStart + BootMonFsGetImageLength (File);

  for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
       !IsNull (&File->RegionToFlushLink, RegionToFlushLink);
       RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink)
       )
  {
    Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;

    // RegionStart and RegionEnd are the the intended NOR address of the
    // start and end of the region
    RegionStart = FileStart + Region->Offset;
    RegionEnd = RegionStart + Region->Size;

    if (RegionEnd < FileEnd) {
      // Handle regions representing edits to existing portions of the file
      // Write the region data straight into the file
      Status = DiskIo->WriteDisk (DiskIo,
                        BlockIo->Media->MediaId,
                        RegionStart,
                        Region->Size,
                        Region->Buffer
                        );
      if (EFI_ERROR (Status)) {
        return Status;
      }
    } else {
      // Handle regions representing appends to the file
      //
      // Note: Since seeking past the end of the file with SetPosition() is
      //  valid, it's possible there will be a gap between the current end of
      //  the file and the beginning of the new region. Since the UEFI spec
      //  says nothing about this case (except "a subsequent write would grow
      //  the file"), we just leave garbage in the gap.

      // Check if there is space to append the new region
      HasSpace = FALSE;
      NewFileSize = (RegionEnd - FileStart) + sizeof (HW_IMAGE_DESCRIPTION);
      CurrentPhysicalSize = BootMonFsGetPhysicalSize (File);
      if (NewFileSize <= CurrentPhysicalSize) {
        HasSpace = TRUE;
      } else {
        // Get the File Description for the next file
        FileLink = GetNextNode (&Instance->RootFile->Link, &File->Link);
        if (!IsNull (&Instance->RootFile->Link, FileLink)) {
          NextFile = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink);

          // If there is space between the beginning of the current file and the
          // beginning of the next file then use it
          EndOfAppendSpace = NextFile->HwDescription.BlockStart * BlockSize;
        } else {
          // We are flushing the last file.
          EndOfAppendSpace = (BlockIo->Media->LastBlock + 1) * BlockSize;
        }
        if (EndOfAppendSpace - FileStart >= NewFileSize) {
          HasSpace = TRUE;
        }
      }

      if (HasSpace == TRUE) {
        Status = FlushAppendRegion (File, Region, NewFileSize, FileStart);
        if (EFI_ERROR (Status)) {
          return Status;
        }
      } else {
        // There isn't a space for the file.
        // Options here are to move the file or fragment it. However as files
        // may represent boot images at fixed positions, these options will
        // break booting if the bootloader doesn't use BootMonFs to find the
        // image.

        return EFI_VOLUME_FULL;
      }
    }
  }

  FreeFileRegions (File);

  // Flush DiskIo Buffers (see UEFI Spec 12.7 - DiskIo buffers are flushed by
  // calling FlushBlocks on the same device's BlockIo).
  BlockIo->FlushBlocks (BlockIo);

  return Status;
}