예제 #1
0
/**
  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_CD_EXPRESS_PRIVATE_DATA     *PrivateData;
    EFI_PEI_RECOVERY_BLOCK_IO_PPI   *BlockIoPpi;
    EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *BlockIo2Ppi;
    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_CD_EXPRESS_PRIVATE_DATA_FROM_THIS (This);
    BlockIoPpi  = PrivateData->CapsuleData[CapsuleInstance - 1].BlockIo;
    BlockIo2Ppi = PrivateData->CapsuleData[CapsuleInstance - 1].BlockIo2;

    if (BlockIo2Ppi != NULL) {
        Status = BlockIo2Ppi->ReadBlocks (
                     PeiServices,
                     BlockIo2Ppi,
                     PrivateData->CapsuleData[CapsuleInstance - 1].IndexBlock,
                     PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleStartLBA,
                     PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleSize,
                     Buffer
                 );
    } else {
        Status = BlockIoPpi->ReadBlocks (
                     PeiServices,
                     BlockIoPpi,
                     PrivateData->CapsuleData[CapsuleInstance - 1].IndexBlock,
                     PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleStartLBA,
                     PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleSize,
                     Buffer
                 );
    }
    return Status;
}
예제 #2
0
/**
  Finds out the recovery capsule in the current volume.

  @param PrivateData                    The private data structure that contains recovery module information.

  @retval EFI_SUCCESS                   The recovery capsule is successfully found in the volume.
  @retval EFI_NOT_FOUND                 The recovery capsule is not found in the volume.

**/
EFI_STATUS
EFIAPI
FindRecoveryCapsules (
    IN OUT PEI_CD_EXPRESS_PRIVATE_DATA            *PrivateData
)
{
    EFI_STATUS                      Status;
    UINTN                           Lba;
    EFI_PEI_RECOVERY_BLOCK_IO_PPI   *BlockIoPpi;
    EFI_PEI_RECOVERY_BLOCK_IO2_PPI  *BlockIo2Ppi;
    UINTN                           BufferSize;
    UINT8                           *Buffer;
    UINT8                           Type;
    UINT8                           *StandardID;
    UINT32                          RootDirLBA;
    PEI_CD_EXPRESS_DIR_FILE_RECORD  *RoorDirRecord;
    UINTN                           VolumeSpaceSize;
    BOOLEAN                         StartOfVolume;
    UINTN                           OriginalLBA;
    UINTN                           IndexBlockDevice;

    Buffer      = PrivateData->BlockBuffer;
    BufferSize  = PEI_CD_BLOCK_SIZE;

    Lba         = 16;
    //
    // The volume descriptor starts on Lba 16
    //
    IndexBlockDevice = PrivateData->CapsuleData[PrivateData->CapsuleCount].IndexBlock;
    BlockIoPpi       = PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo;
    BlockIo2Ppi      = PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo2;

    VolumeSpaceSize = 0;
    StartOfVolume   = TRUE;
    OriginalLBA     = 16;

    while (TRUE) {
        SetMem (Buffer, BufferSize, 0);
        if (BlockIo2Ppi != NULL) {
            Status = BlockIo2Ppi->ReadBlocks (
                         (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),
                         BlockIo2Ppi,
                         IndexBlockDevice,
                         Lba,
                         BufferSize,
                         Buffer
                     );
        } else {
            Status = BlockIoPpi->ReadBlocks (
                         (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),
                         BlockIoPpi,
                         IndexBlockDevice,
                         Lba,
                         BufferSize,
                         Buffer
                     );
        }
        if (EFI_ERROR (Status)) {
            return Status;
        }

        StandardID = (UINT8 *) (Buffer + PEI_CD_EXPRESS_STANDARD_ID_OFFSET);
        if (!StringCmp (StandardID, (UINT8 *) PEI_CD_STANDARD_ID, PEI_CD_EXPRESS_STANDARD_ID_SIZE, TRUE)) {
            break;
        }

        if (StartOfVolume) {
            OriginalLBA   = Lba;
            StartOfVolume = FALSE;
        }

        Type = *(UINT8 *) (Buffer + PEI_CD_EXPRESS_VOLUME_TYPE_OFFSET);
        if (Type == PEI_CD_EXPRESS_VOLUME_TYPE_TERMINATOR) {
            if (VolumeSpaceSize == 0) {
                break;
            } else {
                Lba             = (OriginalLBA + VolumeSpaceSize);
                VolumeSpaceSize = 0;
                StartOfVolume   = TRUE;
                continue;
            }
        }

        if (Type != PEI_CD_EXPRESS_VOLUME_TYPE_PRIMARY) {
            Lba++;
            continue;
        }

        VolumeSpaceSize = *(UINT32 *) (Buffer + PEI_CD_EXPRESS_VOLUME_SPACE_OFFSET);

        RoorDirRecord   = (PEI_CD_EXPRESS_DIR_FILE_RECORD *) (Buffer + PEI_CD_EXPRESS_ROOT_DIR_RECORD_OFFSET);
        RootDirLBA      = RoorDirRecord->LocationOfExtent[0];

        Status          = RetrieveCapsuleFileFromRoot (PrivateData, BlockIoPpi, BlockIo2Ppi, IndexBlockDevice, RootDirLBA);
        if (!EFI_ERROR (Status)) {
            //
            // Just look for the first primary descriptor
            //
            return EFI_SUCCESS;
        }

        Lba++;
    }

    return EFI_NOT_FOUND;
}