REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3739 Update all use of EFI_D_* defines in DEBUG() macros to DEBUG_* defines. Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael Kubacki <michael.kubacki@microsoft.com> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			490 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			490 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Cache implementation for EFI FAT File system driver.
 | 
						|
 | 
						|
Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Fat.h"
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  This function is used by the Data Cache.
 | 
						|
 | 
						|
  When this function is called by write command, all entries in this range
 | 
						|
  are older than the contents in disk, so they are invalid; just mark them invalid.
 | 
						|
 | 
						|
  When this function is called by read command, if any entry in this range
 | 
						|
  is dirty, it means that the relative info directly read from media is older than
 | 
						|
  than the info in the cache; So need to update the relative info in the Buffer.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  IoMode                - This function is called by read command or write command
 | 
						|
  @param  StartPageNo           - First PageNo to be checked in the cache.
 | 
						|
  @param  EndPageNo             - Last PageNo to be checked in the cache.
 | 
						|
  @param  Buffer                - The user buffer need to update. Only when doing the read command
 | 
						|
                          and there is dirty cache in the cache range, this parameter will be used.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
FatFlushDataCacheRange (
 | 
						|
  IN  FAT_VOLUME         *Volume,
 | 
						|
  IN  IO_MODE            IoMode,
 | 
						|
  IN  UINTN              StartPageNo,
 | 
						|
  IN  UINTN              EndPageNo,
 | 
						|
  OUT UINT8              *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN       PageNo;
 | 
						|
  UINTN       GroupNo;
 | 
						|
  UINTN       GroupMask;
 | 
						|
  UINTN       PageSize;
 | 
						|
  UINT8       PageAlignment;
 | 
						|
  DISK_CACHE  *DiskCache;
 | 
						|
  CACHE_TAG   *CacheTag;
 | 
						|
  UINT8       *BaseAddress;
 | 
						|
 | 
						|
  DiskCache     = &Volume->DiskCache[CacheData];
 | 
						|
  BaseAddress   = DiskCache->CacheBase;
 | 
						|
  GroupMask     = DiskCache->GroupMask;
 | 
						|
  PageAlignment = DiskCache->PageAlignment;
 | 
						|
  PageSize      = (UINTN)1 << PageAlignment;
 | 
						|
 | 
						|
  for (PageNo = StartPageNo; PageNo < EndPageNo; PageNo++) {
 | 
						|
    GroupNo   = PageNo & GroupMask;
 | 
						|
    CacheTag  = &DiskCache->CacheTag[GroupNo];
 | 
						|
    if (CacheTag->RealSize > 0 && CacheTag->PageNo == PageNo) {
 | 
						|
      //
 | 
						|
      // When reading data form disk directly, if some dirty data
 | 
						|
      // in cache is in this rang, this data in the Buffer need to
 | 
						|
      // be updated with the cache's dirty data.
 | 
						|
      //
 | 
						|
      if (IoMode == ReadDisk) {
 | 
						|
        if (CacheTag->Dirty) {
 | 
						|
          CopyMem (
 | 
						|
            Buffer + ((PageNo - StartPageNo) << PageAlignment),
 | 
						|
            BaseAddress + (GroupNo << PageAlignment),
 | 
						|
            PageSize
 | 
						|
            );
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Make all valid entries in this range invalid.
 | 
						|
        //
 | 
						|
        CacheTag->RealSize = 0;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Exchange the cache page with the image on the disk
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  DataType              - Indicate the cache type.
 | 
						|
  @param  IoMode                - Indicate whether to load this page from disk or store this page to disk.
 | 
						|
  @param  CacheTag              - The Cache Tag for the current cache page.
 | 
						|
  @param  Task                    point to task instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - Cache page exchanged successfully.
 | 
						|
  @return Others                - An error occurred when exchanging cache page.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
FatExchangeCachePage (
 | 
						|
  IN FAT_VOLUME         *Volume,
 | 
						|
  IN CACHE_DATA_TYPE    DataType,
 | 
						|
  IN IO_MODE            IoMode,
 | 
						|
  IN CACHE_TAG          *CacheTag,
 | 
						|
  IN FAT_TASK           *Task
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       GroupNo;
 | 
						|
  UINTN       PageNo;
 | 
						|
  UINTN       WriteCount;
 | 
						|
  UINTN       RealSize;
 | 
						|
  UINT64      EntryPos;
 | 
						|
  UINT64      MaxSize;
 | 
						|
  DISK_CACHE  *DiskCache;
 | 
						|
  VOID        *PageAddress;
 | 
						|
  UINT8       PageAlignment;
 | 
						|
 | 
						|
  DiskCache     = &Volume->DiskCache[DataType];
 | 
						|
  PageNo        = CacheTag->PageNo;
 | 
						|
  GroupNo       = PageNo & DiskCache->GroupMask;
 | 
						|
  PageAlignment = DiskCache->PageAlignment;
 | 
						|
  PageAddress   = DiskCache->CacheBase + (GroupNo << PageAlignment);
 | 
						|
  EntryPos      = DiskCache->BaseAddress + LShiftU64 (PageNo, PageAlignment);
 | 
						|
  RealSize      = CacheTag->RealSize;
 | 
						|
  if (IoMode == ReadDisk) {
 | 
						|
    RealSize  = (UINTN)1 << PageAlignment;
 | 
						|
    MaxSize   = DiskCache->LimitAddress - EntryPos;
 | 
						|
    if (MaxSize < RealSize) {
 | 
						|
      DEBUG ((DEBUG_INFO, "FatDiskIo: Cache Page OutBound occurred! \n"));
 | 
						|
      RealSize = (UINTN) MaxSize;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  WriteCount = 1;
 | 
						|
  if (DataType == CacheFat && IoMode == WriteDisk) {
 | 
						|
    WriteCount = Volume->NumFats;
 | 
						|
  }
 | 
						|
 | 
						|
  do {
 | 
						|
    //
 | 
						|
    // Only fat table writing will execute more than once
 | 
						|
    //
 | 
						|
    Status = FatDiskIo (Volume, IoMode, EntryPos, RealSize, PageAddress, Task);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    EntryPos += Volume->FatSize;
 | 
						|
  } while (--WriteCount > 0);
 | 
						|
 | 
						|
  CacheTag->Dirty     = FALSE;
 | 
						|
  CacheTag->RealSize  = RealSize;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Get one cache page by specified PageNo.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  CacheDataType         - The cache type: CACHE_FAT or CACHE_DATA.
 | 
						|
  @param  PageNo                - PageNo to match with the cache.
 | 
						|
  @param  CacheTag              - The Cache Tag for the current cache page.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - Get the cache page successfully.
 | 
						|
  @return other                 - An error occurred when accessing data.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
FatGetCachePage (
 | 
						|
  IN FAT_VOLUME         *Volume,
 | 
						|
  IN CACHE_DATA_TYPE    CacheDataType,
 | 
						|
  IN UINTN              PageNo,
 | 
						|
  IN CACHE_TAG          *CacheTag
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       OldPageNo;
 | 
						|
 | 
						|
  OldPageNo = CacheTag->PageNo;
 | 
						|
  if (CacheTag->RealSize > 0 && OldPageNo == PageNo) {
 | 
						|
    //
 | 
						|
    // Cache Hit occurred
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Write dirty cache page back to disk
 | 
						|
  //
 | 
						|
  if (CacheTag->RealSize > 0 && CacheTag->Dirty) {
 | 
						|
    Status = FatExchangeCachePage (Volume, CacheDataType, WriteDisk, CacheTag, NULL);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Load new data from disk;
 | 
						|
  //
 | 
						|
  CacheTag->PageNo  = PageNo;
 | 
						|
  Status            = FatExchangeCachePage (Volume, CacheDataType, ReadDisk, CacheTag, NULL);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Read Length bytes from the position of Offset into Buffer, or
 | 
						|
  write Length bytes from Buffer into the position of Offset.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  CacheDataType         - The type of cache: CACHE_DATA or CACHE_FAT.
 | 
						|
  @param  IoMode                - Indicate the type of disk access.
 | 
						|
  @param  PageNo                - The number of unaligned cache page.
 | 
						|
  @param  Offset                - The starting byte of cache page.
 | 
						|
  @param  Length                - The number of bytes that is read or written
 | 
						|
  @param  Buffer                - Buffer containing cache data.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - The data was accessed correctly.
 | 
						|
  @return Others                - An error occurred when accessing unaligned cache page.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
FatAccessUnalignedCachePage (
 | 
						|
  IN     FAT_VOLUME        *Volume,
 | 
						|
  IN     CACHE_DATA_TYPE   CacheDataType,
 | 
						|
  IN     IO_MODE           IoMode,
 | 
						|
  IN     UINTN             PageNo,
 | 
						|
  IN     UINTN             Offset,
 | 
						|
  IN     UINTN             Length,
 | 
						|
  IN OUT VOID              *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  VOID        *Source;
 | 
						|
  VOID        *Destination;
 | 
						|
  DISK_CACHE  *DiskCache;
 | 
						|
  CACHE_TAG   *CacheTag;
 | 
						|
  UINTN       GroupNo;
 | 
						|
 | 
						|
  DiskCache = &Volume->DiskCache[CacheDataType];
 | 
						|
  GroupNo   = PageNo & DiskCache->GroupMask;
 | 
						|
  CacheTag  = &DiskCache->CacheTag[GroupNo];
 | 
						|
  Status    = FatGetCachePage (Volume, CacheDataType, PageNo, CacheTag);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Source      = DiskCache->CacheBase + (GroupNo << DiskCache->PageAlignment) + Offset;
 | 
						|
    Destination = Buffer;
 | 
						|
    if (IoMode != ReadDisk) {
 | 
						|
      CacheTag->Dirty   = TRUE;
 | 
						|
      DiskCache->Dirty  = TRUE;
 | 
						|
      Destination       = Source;
 | 
						|
      Source            = Buffer;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (Destination, Source, Length);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Read BufferSize bytes from the position of Offset into Buffer,
 | 
						|
  or write BufferSize bytes from Buffer into the position of Offset.
 | 
						|
 | 
						|
  Base on the parameter of CACHE_DATA_TYPE, the data access will be divided into
 | 
						|
  the access of FAT cache (CACHE_FAT) and the access of Data cache (CACHE_DATA):
 | 
						|
 | 
						|
  1. Access of FAT cache (CACHE_FAT): Access the data in the FAT cache, if there is cache
 | 
						|
     page hit, just return the cache page; else update the related cache page and return
 | 
						|
     the right cache page.
 | 
						|
  2. Access of Data cache (CACHE_DATA):
 | 
						|
     The access data will be divided into UnderRun data, Aligned data and OverRun data;
 | 
						|
     The UnderRun data and OverRun data will be accessed by the Data cache,
 | 
						|
     but the Aligned data will be accessed with disk directly.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  CacheDataType         - The type of cache: CACHE_DATA or CACHE_FAT.
 | 
						|
  @param  IoMode                - Indicate the type of disk access.
 | 
						|
  @param  Offset                - The starting byte offset to read from.
 | 
						|
  @param  BufferSize            - Size of Buffer.
 | 
						|
  @param  Buffer                - Buffer containing cache data.
 | 
						|
  @param  Task                    point to task instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - The data was accessed correctly.
 | 
						|
  @retval EFI_MEDIA_CHANGED     - The MediaId does not match the current device.
 | 
						|
  @return Others                - An error occurred when accessing cache.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FatAccessCache (
 | 
						|
  IN     FAT_VOLUME         *Volume,
 | 
						|
  IN     CACHE_DATA_TYPE    CacheDataType,
 | 
						|
  IN     IO_MODE            IoMode,
 | 
						|
  IN     UINT64             Offset,
 | 
						|
  IN     UINTN              BufferSize,
 | 
						|
  IN OUT UINT8              *Buffer,
 | 
						|
  IN     FAT_TASK           *Task
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       PageSize;
 | 
						|
  UINTN       UnderRun;
 | 
						|
  UINTN       OverRun;
 | 
						|
  UINTN       AlignedSize;
 | 
						|
  UINTN       Length;
 | 
						|
  UINTN       PageNo;
 | 
						|
  UINTN       AlignedPageCount;
 | 
						|
  UINTN       OverRunPageNo;
 | 
						|
  DISK_CACHE  *DiskCache;
 | 
						|
  UINT64      EntryPos;
 | 
						|
  UINT8       PageAlignment;
 | 
						|
 | 
						|
  ASSERT (Volume->CacheBuffer != NULL);
 | 
						|
 | 
						|
  Status        = EFI_SUCCESS;
 | 
						|
  DiskCache     = &Volume->DiskCache[CacheDataType];
 | 
						|
  EntryPos      = Offset - DiskCache->BaseAddress;
 | 
						|
  PageAlignment = DiskCache->PageAlignment;
 | 
						|
  PageSize      = (UINTN)1 << PageAlignment;
 | 
						|
  PageNo        = (UINTN) RShiftU64 (EntryPos, PageAlignment);
 | 
						|
  UnderRun      = ((UINTN) EntryPos) & (PageSize - 1);
 | 
						|
 | 
						|
  if (UnderRun > 0) {
 | 
						|
    Length = PageSize - UnderRun;
 | 
						|
    if (Length > BufferSize) {
 | 
						|
      Length = BufferSize;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = FatAccessUnalignedCachePage (Volume, CacheDataType, IoMode, PageNo, UnderRun, Length, Buffer);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    Buffer     += Length;
 | 
						|
    BufferSize -= Length;
 | 
						|
    PageNo++;
 | 
						|
  }
 | 
						|
 | 
						|
  AlignedPageCount  = BufferSize >> PageAlignment;
 | 
						|
  OverRunPageNo     = PageNo + AlignedPageCount;
 | 
						|
  //
 | 
						|
  // The access of the Aligned data
 | 
						|
  //
 | 
						|
  if (AlignedPageCount > 0) {
 | 
						|
    //
 | 
						|
    // Accessing fat table cannot have alignment data
 | 
						|
    //
 | 
						|
    ASSERT (CacheDataType == CacheData);
 | 
						|
 | 
						|
    EntryPos    = Volume->RootPos + LShiftU64 (PageNo, PageAlignment);
 | 
						|
    AlignedSize = AlignedPageCount << PageAlignment;
 | 
						|
    Status      = FatDiskIo (Volume, IoMode, EntryPos, AlignedSize, Buffer, Task);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If these access data over laps the relative cache range, these cache pages need
 | 
						|
    // to be updated.
 | 
						|
    //
 | 
						|
    FatFlushDataCacheRange (Volume, IoMode, PageNo, OverRunPageNo, Buffer);
 | 
						|
    Buffer      += AlignedSize;
 | 
						|
    BufferSize  -= AlignedSize;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // The access of the OverRun data
 | 
						|
  //
 | 
						|
  OverRun = BufferSize;
 | 
						|
  if (OverRun > 0) {
 | 
						|
    //
 | 
						|
    // Last read is not a complete page
 | 
						|
    //
 | 
						|
    Status = FatAccessUnalignedCachePage (Volume, CacheDataType, IoMode, OverRunPageNo, 0, OverRun, Buffer);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Flush all the dirty cache back, include the FAT cache and the Data cache.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
  @param  Task                    point to task instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - Flush all the dirty cache back successfully
 | 
						|
  @return other                 - An error occurred when writing the data into the disk
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FatVolumeFlushCache (
 | 
						|
  IN FAT_VOLUME         *Volume,
 | 
						|
  IN FAT_TASK           *Task
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  CACHE_DATA_TYPE CacheDataType;
 | 
						|
  UINTN           GroupIndex;
 | 
						|
  UINTN           GroupMask;
 | 
						|
  DISK_CACHE      *DiskCache;
 | 
						|
  CACHE_TAG       *CacheTag;
 | 
						|
 | 
						|
  for (CacheDataType = (CACHE_DATA_TYPE) 0; CacheDataType < CacheMaxType; CacheDataType++) {
 | 
						|
    DiskCache = &Volume->DiskCache[CacheDataType];
 | 
						|
    if (DiskCache->Dirty) {
 | 
						|
      //
 | 
						|
      // Data cache or fat cache is dirty, write the dirty data back
 | 
						|
      //
 | 
						|
      GroupMask = DiskCache->GroupMask;
 | 
						|
      for (GroupIndex = 0; GroupIndex <= GroupMask; GroupIndex++) {
 | 
						|
        CacheTag = &DiskCache->CacheTag[GroupIndex];
 | 
						|
        if (CacheTag->RealSize > 0 && CacheTag->Dirty) {
 | 
						|
          //
 | 
						|
          // Write back all Dirty Data Cache Page to disk
 | 
						|
          //
 | 
						|
          Status = FatExchangeCachePage (Volume, CacheDataType, WriteDisk, CacheTag, Task);
 | 
						|
          if (EFI_ERROR (Status)) {
 | 
						|
            return Status;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      DiskCache->Dirty = FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Flush the block device.
 | 
						|
  //
 | 
						|
  Status = Volume->BlockIo->FlushBlocks (Volume->BlockIo);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Initialize the disk cache according to Volume's FatType.
 | 
						|
 | 
						|
  @param  Volume                - FAT file system volume.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           - The disk cache is successfully initialized.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  - Not enough memory to allocate disk cache.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FatInitializeDiskCache (
 | 
						|
  IN FAT_VOLUME         *Volume
 | 
						|
  )
 | 
						|
{
 | 
						|
  DISK_CACHE  *DiskCache;
 | 
						|
  UINTN       FatCacheGroupCount;
 | 
						|
  UINTN       DataCacheSize;
 | 
						|
  UINTN       FatCacheSize;
 | 
						|
  UINT8       *CacheBuffer;
 | 
						|
 | 
						|
  DiskCache = Volume->DiskCache;
 | 
						|
  //
 | 
						|
  // Configure the parameters of disk cache
 | 
						|
  //
 | 
						|
  if (Volume->FatType == Fat12) {
 | 
						|
    FatCacheGroupCount                  = FAT_FATCACHE_GROUP_MIN_COUNT;
 | 
						|
    DiskCache[CacheFat].PageAlignment  = FAT_FATCACHE_PAGE_MIN_ALIGNMENT;
 | 
						|
    DiskCache[CacheData].PageAlignment = FAT_DATACACHE_PAGE_MIN_ALIGNMENT;
 | 
						|
  } else {
 | 
						|
    FatCacheGroupCount                  = FAT_FATCACHE_GROUP_MAX_COUNT;
 | 
						|
    DiskCache[CacheFat].PageAlignment  = FAT_FATCACHE_PAGE_MAX_ALIGNMENT;
 | 
						|
    DiskCache[CacheData].PageAlignment = FAT_DATACACHE_PAGE_MAX_ALIGNMENT;
 | 
						|
  }
 | 
						|
 | 
						|
  DiskCache[CacheData].GroupMask     = FAT_DATACACHE_GROUP_COUNT - 1;
 | 
						|
  DiskCache[CacheData].BaseAddress   = Volume->RootPos;
 | 
						|
  DiskCache[CacheData].LimitAddress  = Volume->VolumeSize;
 | 
						|
  DiskCache[CacheFat].GroupMask      = FatCacheGroupCount - 1;
 | 
						|
  DiskCache[CacheFat].BaseAddress    = Volume->FatPos;
 | 
						|
  DiskCache[CacheFat].LimitAddress   = Volume->FatPos + Volume->FatSize;
 | 
						|
  FatCacheSize                        = FatCacheGroupCount << DiskCache[CacheFat].PageAlignment;
 | 
						|
  DataCacheSize                       = FAT_DATACACHE_GROUP_COUNT << DiskCache[CacheData].PageAlignment;
 | 
						|
  //
 | 
						|
  // Allocate the Fat Cache buffer
 | 
						|
  //
 | 
						|
  CacheBuffer = AllocateZeroPool (FatCacheSize + DataCacheSize);
 | 
						|
  if (CacheBuffer == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Volume->CacheBuffer             = CacheBuffer;
 | 
						|
  DiskCache[CacheFat].CacheBase  = CacheBuffer;
 | 
						|
  DiskCache[CacheData].CacheBase = CacheBuffer + FatCacheSize;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |