summaryrefslogtreecommitdiffstats
path: root/FatPkg/FatPei/FatLiteLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'FatPkg/FatPei/FatLiteLib.c')
-rw-r--r--FatPkg/FatPei/FatLiteLib.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/FatPkg/FatPei/FatLiteLib.c b/FatPkg/FatPei/FatLiteLib.c
new file mode 100644
index 0000000000..b5191b6706
--- /dev/null
+++ b/FatPkg/FatPei/FatLiteLib.c
@@ -0,0 +1,364 @@
+/** @file
+ General purpose supporting routines for FAT recovery PEIM
+
+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"
+
+
+#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);
+ //
+ 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) {
+ *String = *Fat;
+ String += 1;
+ Fat += 1;
+ FatSize -= 1;
+ if (*Fat == ' ') {
+ *String = 0;
+ return ;
+ }
+ }
+}
+
+
+/**
+ 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);
+}