From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- roms/edk2/FatPkg/FatPei/FatLiteLib.c | 370 +++++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 roms/edk2/FatPkg/FatPei/FatLiteLib.c (limited to 'roms/edk2/FatPkg/FatPei/FatLiteLib.c') diff --git a/roms/edk2/FatPkg/FatPei/FatLiteLib.c b/roms/edk2/FatPkg/FatPei/FatLiteLib.c new file mode 100644 index 000000000..3d43e0b87 --- /dev/null +++ b/roms/edk2/FatPkg/FatPei/FatLiteLib.c @@ -0,0 +1,370 @@ +/** @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); +} -- cgit