123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /** @file
- General purpose supporting routines for FAT recovery PEIM
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "FatLitePeim.h"
- #define CHAR_FAT_VALID 0x01
- /**
- Converts a union code character to upper case.
- This functions converts a unicode character to upper case.
- If the input Letter is not a lower-cased letter,
- the original value is returned.
- @param Letter The input unicode character.
- @return The upper cased letter.
- **/
- CHAR16
- ToUpper (
- IN CHAR16 Letter
- )
- {
- if ('a' <= Letter && Letter <= 'z') {
- Letter = (CHAR16) (Letter - 0x20);
- }
- return Letter;
- }
- /**
- Reads a block of data from the block device by calling
- underlying Block I/O service.
- @param PrivateData Global memory map for accessing global variables
- @param BlockDeviceNo The index for the block device number.
- @param Lba The logic block address to read data from.
- @param BufferSize The size of data in byte to read.
- @param Buffer The buffer of the
- @retval EFI_DEVICE_ERROR The specified block device number exceeds the maximum
- device number.
- @retval EFI_DEVICE_ERROR The maximum address has exceeded the maximum address
- of the block device.
- **/
- EFI_STATUS
- FatReadBlock (
- IN PEI_FAT_PRIVATE_DATA *PrivateData,
- IN UINTN BlockDeviceNo,
- IN EFI_PEI_LBA Lba,
- IN UINTN BufferSize,
- OUT VOID *Buffer
- )
- {
- EFI_STATUS Status;
- PEI_FAT_BLOCK_DEVICE *BlockDev;
- if (BlockDeviceNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
- return EFI_DEVICE_ERROR;
- }
- Status = EFI_SUCCESS;
- BlockDev = &(PrivateData->BlockDevice[BlockDeviceNo]);
- if (BufferSize > MultU64x32 (BlockDev->LastBlock - Lba + 1, BlockDev->BlockSize)) {
- return EFI_DEVICE_ERROR;
- }
- if (!BlockDev->Logical) {
- //
- // Status = BlockDev->ReadFunc
- // (PrivateData->PeiServices, BlockDev->PhysicalDevNo, Lba, BufferSize, Buffer);
- //
- if (BlockDev->BlockIo2 != NULL) {
- Status = BlockDev->BlockIo2->ReadBlocks (
- (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),
- BlockDev->BlockIo2,
- BlockDev->PhysicalDevNo,
- Lba,
- BufferSize,
- Buffer
- );
- } else {
- Status = BlockDev->BlockIo->ReadBlocks (
- (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (),
- BlockDev->BlockIo,
- BlockDev->PhysicalDevNo,
- Lba,
- BufferSize,
- Buffer
- );
- }
- } else {
- Status = FatReadDisk (
- PrivateData,
- BlockDev->ParentDevNo,
- BlockDev->StartingPos + MultU64x32 (Lba, BlockDev->BlockSize),
- BufferSize,
- Buffer
- );
- }
- return Status;
- }
- /**
- 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;
- }
- /**
- 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;
- }
- /**
- This version is different from the version in Unicode collation
- protocol in that this version strips off trailing blanks.
- Converts an 8.3 FAT file name using an OEM character set
- to a Null-terminated Unicode string.
- Here does not expand DBCS FAT chars.
- @param FatSize The size of the string Fat in bytes.
- @param Fat A pointer to a Null-terminated string that contains
- an 8.3 file name using an OEM character set.
- @param Str A pointer to a Null-terminated Unicode string. The
- string must be allocated in advance to hold FatSize
- Unicode characters
- **/
- VOID
- EngFatToStr (
- IN UINTN FatSize,
- IN CHAR8 *Fat,
- OUT CHAR16 *Str
- )
- {
- CHAR16 *String;
- String = Str;
- //
- // No DBCS issues, just expand and add null terminate to end of string
- //
- while (*Fat != 0 && FatSize != 0) {
- if (*Fat == ' ') {
- break;
- }
- *String = *Fat;
- String += 1;
- Fat += 1;
- FatSize -= 1;
- }
- *String = 0;
- }
- /**
- Performs a case-insensitive comparison of two Null-terminated Unicode strings.
- @param PrivateData Global memory map for accessing global variables
- @param Str1 First string to perform case insensitive comparison.
- @param Str2 Second string to perform case insensitive comparison.
- **/
- BOOLEAN
- EngStriColl (
- IN PEI_FAT_PRIVATE_DATA *PrivateData,
- IN CHAR16 *Str1,
- IN CHAR16 *Str2
- )
- {
- CHAR16 UpperS1;
- CHAR16 UpperS2;
- UpperS1 = ToUpper (*Str1);
- UpperS2 = ToUpper (*Str2);
- while (*Str1 != 0) {
- if (UpperS1 != UpperS2) {
- return FALSE;
- }
- Str1++;
- Str2++;
- UpperS1 = ToUpper (*Str1);
- UpperS2 = ToUpper (*Str2);
- }
- return (BOOLEAN) ((*Str2 != 0) ? FALSE : TRUE);
- }
|