REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the FatPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			494 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			494 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;
 | |
| }
 |