/** 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; }
/** 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; }