diff options
Diffstat (limited to 'FatPkg/FatPei/FatLiteApi.c')
-rw-r--r-- | FatPkg/FatPei/FatLiteApi.c | 611 |
1 files changed, 611 insertions, 0 deletions
diff --git a/FatPkg/FatPei/FatLiteApi.c b/FatPkg/FatPei/FatLiteApi.c new file mode 100644 index 0000000000..bf8158d94f --- /dev/null +++ b/FatPkg/FatPei/FatLiteApi.c @@ -0,0 +1,611 @@ +/** @file
+ FAT recovery PEIM entry point, Ppi Functions and FAT Api functions.
+
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials are licensed and made available
+under the terms and conditions of the BSD License which accompanies this
+distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "FatLitePeim.h"
+
+PEI_FAT_PRIVATE_DATA *mPrivateData = NULL;
+
+/**
+ BlockIo installation nofication function. Find out all the current BlockIO
+ PPIs in the system and add them into private data. Assume there is
+
+ @param PeiServices General purpose services available to every
+ PEIM.
+ @param NotifyDescriptor The typedef structure of the notification
+ descriptor. Not used in this function.
+ @param Ppi The typedef structure of the PPI descriptor.
+ Not used in this function.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoNotifyEntry (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+
+/**
+ Discover all the block I/O devices to find the FAT volume.
+
+ @param PrivateData Global memory map for accessing global
+ variables.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+UpdateBlocksAndVolumes (
+ IN OUT PEI_FAT_PRIVATE_DATA *PrivateData
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;
+ UINTN BlockIoPpiInstance;
+ EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;
+ UINTN NumberBlockDevices;
+ UINTN Index;
+ EFI_PEI_BLOCK_IO_MEDIA Media;
+ PEI_FAT_VOLUME Volume;
+ EFI_PEI_SERVICES **PeiServices;
+
+ PeiServices = (EFI_PEI_SERVICES **) GetPeiServicesTablePointer ();
+
+ //
+ // Clean up caches
+ //
+ for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {
+ PrivateData->CacheBuffer[Index].Valid = FALSE;
+ }
+
+ PrivateData->BlockDeviceCount = 0;
+
+ //
+ // Find out all Block Io Ppi instances within the system
+ // Assuming all device Block Io Peims are dispatched already
+ //
+ for (BlockIoPpiInstance = 0; BlockIoPpiInstance < PEI_FAT_MAX_BLOCK_IO_PPI; BlockIoPpiInstance++) {
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiVirtualBlockIoPpiGuid,
+ BlockIoPpiInstance,
+ &TempPpiDescriptor,
+ (VOID **) &BlockIoPpi
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Done with all Block Io Ppis
+ //
+ break;
+ }
+
+ Status = BlockIoPpi->GetNumberOfBlockDevices (
+ PeiServices,
+ BlockIoPpi,
+ &NumberBlockDevices
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (Index = 1; Index <= NumberBlockDevices && PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE; Index++) {
+
+ Status = BlockIoPpi->GetBlockDeviceMediaInfo (
+ PeiServices,
+ BlockIoPpi,
+ Index,
+ &Media
+ );
+ if (EFI_ERROR (Status) || !Media.MediaPresent) {
+ continue;
+ }
+
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockSize = (UINT32) Media.BlockSize;
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].LastBlock = Media.LastBlock;
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].IoAlign = 0;
+ //
+ // Not used here
+ //
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].Logical = FALSE;
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].PartitionChecked = FALSE;
+
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockIo = BlockIoPpi;
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].PhysicalDevNo = (UINT8) Index;
+ PrivateData->BlockDevice[PrivateData->BlockDeviceCount].DevType = Media.DeviceType;
+
+ PrivateData->BlockDeviceCount++;
+ }
+ }
+ //
+ // Find out all logical devices
+ //
+ FatFindPartitions (PrivateData);
+
+ //
+ // Build up file system volume array
+ //
+ PrivateData->VolumeCount = 0;
+ for (Index = 0; Index < PrivateData->BlockDeviceCount; Index++) {
+ Volume.BlockDeviceNo = Index;
+ Status = FatGetBpbInfo (PrivateData, &Volume);
+ if (Status == EFI_SUCCESS) {
+ //
+ // Add the detected volume to the volume array
+ //
+ CopyMem (
+ (UINT8 *) &(PrivateData->Volume[PrivateData->VolumeCount]),
+ (UINT8 *) &Volume,
+ sizeof (PEI_FAT_VOLUME)
+ );
+ PrivateData->VolumeCount += 1;
+ if (PrivateData->VolumeCount >= PEI_FAT_MAX_VOLUME) {
+ break;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ BlockIo installation notification function. Find out all the current BlockIO
+ PPIs in the system and add them into private data. Assume there is
+
+ @param PeiServices General purpose services available to every
+ PEIM.
+ @param NotifyDescriptor The typedef structure of the notification
+ descriptor. Not used in this function.
+ @param Ppi The typedef structure of the PPI descriptor.
+ Not used in this function.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+BlockIoNotifyEntry (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ UpdateBlocksAndVolumes (mPrivateData);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Installs the Device Recovery Module PPI, Initialize BlockIo Ppi
+ installation notification
+
+ @param FileHandle Handle of the file being invoked. Type
+ EFI_PEI_FILE_HANDLE is defined in
+ FfsFindNextFile().
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_SUCCESS The entry point was executed successfully.
+ @retval EFI_OUT_OF_RESOURCES There is no enough memory to complete the
+ operations.
+
+**/
+EFI_STATUS
+EFIAPI
+FatPeimEntry (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Address;
+ PEI_FAT_PRIVATE_DATA *PrivateData;
+
+ Status = PeiServicesRegisterForShadow (FileHandle);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ (sizeof (PEI_FAT_PRIVATE_DATA) - 1) / PEI_FAT_MEMMORY_PAGE_SIZE + 1,
+ &Address
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PrivateData = (PEI_FAT_PRIVATE_DATA *) (UINTN) Address;
+
+ //
+ // Initialize Private Data (to zero, as is required by subsequent operations)
+ //
+ ZeroMem ((UINT8 *) PrivateData, sizeof (PEI_FAT_PRIVATE_DATA));
+
+ PrivateData->Signature = PEI_FAT_PRIVATE_DATA_SIGNATURE;
+
+ //
+ // Installs Ppi
+ //
+ PrivateData->DeviceRecoveryPpi.GetNumberRecoveryCapsules = GetNumberRecoveryCapsules;
+ PrivateData->DeviceRecoveryPpi.GetRecoveryCapsuleInfo = GetRecoveryCapsuleInfo;
+ PrivateData->DeviceRecoveryPpi.LoadRecoveryCapsule = LoadRecoveryCapsule;
+
+ PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ PrivateData->PpiDescriptor.Guid = &gEfiPeiDeviceRecoveryModulePpiGuid;
+ PrivateData->PpiDescriptor.Ppi = &PrivateData->DeviceRecoveryPpi;
+
+ Status = PeiServicesInstallPpi (&PrivateData->PpiDescriptor);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Other initializations
+ //
+ PrivateData->BlockDeviceCount = 0;
+
+ UpdateBlocksAndVolumes (PrivateData);
+
+ //
+ // PrivateData is allocated now, set it to the module variable
+ //
+ mPrivateData = PrivateData;
+
+ //
+ // Installs Block Io Ppi notification function
+ //
+ PrivateData->NotifyDescriptor.Flags =
+ (
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
+ );
+ PrivateData->NotifyDescriptor.Guid = &gEfiPeiVirtualBlockIoPpiGuid;
+ PrivateData->NotifyDescriptor.Notify = BlockIoNotifyEntry;
+ return PeiServicesNotifyPpi (&PrivateData->NotifyDescriptor);
+}
+
+
+/**
+ Returns the number of DXE capsules residing on the device.
+
+ This function searches for DXE capsules from the associated device and returns
+ the number and maximum size in bytes of the capsules discovered. Entry 1 is
+ assumed to be the highest load priority and entry N is assumed to be the lowest
+ priority.
+
+ @param[in] PeiServices General-purpose services that are available
+ to every PEIM
+ @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
+ instance.
+ @param[out] NumberRecoveryCapsules Pointer to a caller-allocated UINTN. On
+ output, *NumberRecoveryCapsules contains
+ the number of recovery capsule images
+ available for retrieval from this PEIM
+ instance.
+
+ @retval EFI_SUCCESS One or more capsules were discovered.
+ @retval EFI_DEVICE_ERROR A device error occurred.
+ @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberRecoveryCapsules (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ OUT UINTN *NumberRecoveryCapsules
+ )
+{
+ EFI_STATUS Status;
+ PEI_FAT_PRIVATE_DATA *PrivateData;
+ UINTN Index;
+ UINTN RecoveryCapsuleCount;
+ PEI_FILE_HANDLE Handle;
+
+ PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Search each volume in the root directory for the Recovery capsule
+ //
+ RecoveryCapsuleCount = 0;
+ for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
+ Status = FindRecoveryFile (PrivateData, Index, PEI_FAT_RECOVERY_CAPSULE_WITHOUT_NT_EMULATOR, &Handle);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ RecoveryCapsuleCount++;
+ }
+
+ *NumberRecoveryCapsules = RecoveryCapsuleCount;
+
+ if (*NumberRecoveryCapsules == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns the size and type of the requested recovery capsule.
+
+ This function gets the size and type of the capsule specified by CapsuleInstance.
+
+ @param[in] PeiServices General-purpose services that are available to every PEIM
+ @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
+ instance.
+ @param[in] CapsuleInstance Specifies for which capsule instance to retrieve
+ the information. This parameter must be between
+ one and the value returned by GetNumberRecoveryCapsules()
+ in NumberRecoveryCapsules.
+ @param[out] Size A pointer to a caller-allocated UINTN in which
+ the size of the requested recovery module is
+ returned.
+ @param[out] CapsuleType A pointer to a caller-allocated EFI_GUID in which
+ the type of the requested recovery capsule is
+ returned. The semantic meaning of the value
+ returned is defined by the implementation.
+
+ @retval EFI_SUCCESS One or more capsules were discovered.
+ @retval EFI_DEVICE_ERROR A device error occurred.
+ @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
+
+**/
+EFI_STATUS
+EFIAPI
+GetRecoveryCapsuleInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT UINTN *Size,
+ OUT EFI_GUID *CapsuleType
+ )
+{
+ EFI_STATUS Status;
+ PEI_FAT_PRIVATE_DATA *PrivateData;
+ UINTN Index;
+ UINTN BlockDeviceNo;
+ UINTN RecoveryCapsuleCount;
+ PEI_FILE_HANDLE Handle;
+ UINTN NumberRecoveryCapsules;
+
+ Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ CapsuleInstance = CapsuleInstance + 1;
+ }
+
+ if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Search each volume in the root directory for the Recovery capsule
+ //
+ RecoveryCapsuleCount = 0;
+ for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
+ Status = FindRecoveryFile (PrivateData, Index, PEI_FAT_RECOVERY_CAPSULE_WITHOUT_NT_EMULATOR, &Handle);
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (CapsuleInstance - 1 == RecoveryCapsuleCount) {
+ //
+ // Get file size
+ //
+ *Size = (UINTN) (((PEI_FAT_FILE *) Handle)->FileSize);
+
+ //
+ // Find corresponding physical block device
+ //
+ BlockDeviceNo = PrivateData->Volume[Index].BlockDeviceNo;
+ while (PrivateData->BlockDevice[BlockDeviceNo].Logical && BlockDeviceNo < PrivateData->BlockDeviceCount) {
+ BlockDeviceNo = PrivateData->BlockDevice[BlockDeviceNo].ParentDevNo;
+ }
+ //
+ // Fill in the Capsule Type GUID according to the block device type
+ //
+ if (BlockDeviceNo < PrivateData->BlockDeviceCount) {
+ switch (PrivateData->BlockDevice[BlockDeviceNo].DevType) {
+ case LegacyFloppy:
+ CopyGuid (CapsuleType, &gRecoveryOnFatFloppyDiskGuid);
+ break;
+
+ case IdeCDROM:
+ case IdeLS120:
+ CopyGuid (CapsuleType, &gRecoveryOnFatIdeDiskGuid);
+ break;
+
+ case UsbMassStorage:
+ CopyGuid (CapsuleType, &gRecoveryOnFatUsbDiskGuid);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ RecoveryCapsuleCount++;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Loads a DXE capsule from some media into memory.
+
+ This function, by whatever mechanism, retrieves a DXE capsule from some device
+ and loads it into memory. Note that the published interface is device neutral.
+
+ @param[in] PeiServices General-purpose services that are available
+ to every PEIM
+ @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
+ instance.
+ @param[in] CapsuleInstance Specifies which capsule instance to retrieve.
+ @param[out] Buffer Specifies a caller-allocated buffer in which
+ the requested recovery capsule will be returned.
+
+ @retval EFI_SUCCESS The capsule was loaded correctly.
+ @retval EFI_DEVICE_ERROR A device error occurred.
+ @retval EFI_NOT_FOUND A requested recovery DXE capsule cannot be found.
+
+**/
+EFI_STATUS
+EFIAPI
+LoadRecoveryCapsule (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
+ IN UINTN CapsuleInstance,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ PEI_FAT_PRIVATE_DATA *PrivateData;
+ UINTN Index;
+ UINTN RecoveryCapsuleCount;
+ PEI_FILE_HANDLE Handle;
+ UINTN NumberRecoveryCapsules;
+
+ Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
+ CapsuleInstance = CapsuleInstance + 1;
+ }
+
+ if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
+
+ //
+ // Search each volume in the root directory for the Recovery capsule
+ //
+ RecoveryCapsuleCount = 0;
+ for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
+ Status = FindRecoveryFile (PrivateData, Index, PEI_FAT_RECOVERY_CAPSULE_WITHOUT_NT_EMULATOR, &Handle);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (CapsuleInstance - 1 == RecoveryCapsuleCount) {
+
+ Status = FatReadFile (
+ PrivateData,
+ Handle,
+ (UINTN) (((PEI_FAT_FILE *) Handle)->FileSize),
+ Buffer
+ );
+ return Status;
+ }
+
+ RecoveryCapsuleCount++;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Finds the recovery file on a FAT volume.
+ This function finds the the recovery file named FileName on a specified FAT volume and returns
+ its FileHandle pointer.
+
+ @param PrivateData Global memory map for accessing global
+ variables.
+ @param VolumeIndex The index of the volume.
+ @param FileName The recovery file name to find.
+ @param Handle The output file handle.
+
+ @retval EFI_DEVICE_ERROR Some error occured when operating the FAT
+ volume.
+ @retval EFI_NOT_FOUND The recovery file was not found.
+ @retval EFI_SUCCESS The recovery file was successfully found on the
+ FAT volume.
+
+**/
+EFI_STATUS
+FindRecoveryFile (
+ IN PEI_FAT_PRIVATE_DATA *PrivateData,
+ IN UINTN VolumeIndex,
+ IN CHAR16 *FileName,
+ OUT PEI_FILE_HANDLE *Handle
+ )
+{
+ EFI_STATUS Status;
+ PEI_FAT_FILE Parent;
+ PEI_FAT_FILE *File;
+
+ File = &PrivateData->File;
+
+ //
+ // VolumeIndex must be less than PEI_FAT_MAX_VOLUME because PrivateData->VolumeCount
+ // cannot be larger than PEI_FAT_MAX_VOLUME when detecting recovery volume.
+ //
+ ASSERT (VolumeIndex < PEI_FAT_MAX_VOLUME);
+
+ //
+ // Construct root directory file
+ //
+ Parent.IsFixedRootDir = (BOOLEAN) ((PrivateData->Volume[VolumeIndex].FatType == Fat32) ? FALSE : TRUE);
+ Parent.Attributes = FAT_ATTR_DIRECTORY;
+ Parent.CurrentPos = 0;
+ Parent.CurrentCluster = Parent.IsFixedRootDir ? 0 : PrivateData->Volume[VolumeIndex].RootDirCluster;
+ Parent.StartingCluster = Parent.CurrentCluster;
+ Parent.Volume = &PrivateData->Volume[VolumeIndex];
+
+ Status = FatSetFilePos (PrivateData, &Parent, 0);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Search for recovery capsule in root directory
+ //
+ Status = FatReadNextDirectoryEntry (PrivateData, &Parent, File);
+ while (Status == EFI_SUCCESS) {
+ if (EngStriColl (PrivateData, FileName, File->FileName)) {
+ break;
+ }
+
+ Status = FatReadNextDirectoryEntry (PrivateData, &Parent, File);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Handle = File;
+
+ return EFI_SUCCESS;
+
+}
|