Fix various typos in FatPkg/EnhancedFatDxe comments. Cc: Ray Ni <ray.ni@intel.com> Signed-off-by: Antoine Coeur <coeur@gmx.fr> Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com> Acked-by: Liming Gao <liming.gao@intel.com> Signed-off-by: Philippe Mathieu-Daude <philmd@redhat.com> Message-Id: <20200207010831.9046-8-philmd@redhat.com>
		
			
				
	
	
		
			500 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			500 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Functions for manipulating file names.
 | |
| 
 | |
| Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Fat.h"
 | |
| 
 | |
| /**
 | |
| 
 | |
|   This function checks whether the input FileName is a valid 8.3 short name.
 | |
|   If the input FileName is a valid 8.3, the output is the 8.3 short name;
 | |
|   otherwise, the output is the base tag of 8.3 short name.
 | |
| 
 | |
|   @param  FileName              - The input unicode filename.
 | |
|   @param  File8Dot3Name         - The output ascii 8.3 short name or base tag of 8.3 short name.
 | |
| 
 | |
|   @retval TRUE                  - The input unicode filename is a valid 8.3 short name.
 | |
|   @retval FALSE                 - The input unicode filename is not a valid 8.3 short name.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| FatCheckIs8Dot3Name (
 | |
|   IN  CHAR16    *FileName,
 | |
|   OUT CHAR8     *File8Dot3Name
 | |
|   )
 | |
| {
 | |
|   BOOLEAN PossibleShortName;
 | |
|   CHAR16  *TempName;
 | |
|   CHAR16  *ExtendName;
 | |
|   CHAR16  *SeparateDot;
 | |
|   UINTN   MainNameLen;
 | |
|   UINTN   ExtendNameLen;
 | |
| 
 | |
|   PossibleShortName = TRUE;
 | |
|   SeparateDot       = NULL;
 | |
|   SetMem (File8Dot3Name, FAT_NAME_LEN, ' ');
 | |
|   for (TempName = FileName; *TempName != '\0'; TempName++) {
 | |
|     if (*TempName == L'.') {
 | |
|       SeparateDot = TempName;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (SeparateDot == NULL) {
 | |
|     //
 | |
|     // Extended filename is not detected
 | |
|     //
 | |
|     MainNameLen   = TempName - FileName;
 | |
|     ExtendName    = TempName;
 | |
|     ExtendNameLen = 0;
 | |
|   } else {
 | |
|     //
 | |
|     // Extended filename is detected
 | |
|     //
 | |
|     MainNameLen   = SeparateDot - FileName;
 | |
|     ExtendName    = SeparateDot + 1;
 | |
|     ExtendNameLen = TempName - ExtendName;
 | |
|   }
 | |
|   //
 | |
|   // We scan the filename for the second time
 | |
|   // to check if there exists any extra blanks and dots
 | |
|   //
 | |
|   while (--TempName >= FileName) {
 | |
|     if ((*TempName == L'.' || *TempName == L' ') && (TempName != SeparateDot)) {
 | |
|       //
 | |
|       // There exist extra blanks and dots
 | |
|       //
 | |
|       PossibleShortName = FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (MainNameLen == 0) {
 | |
|     PossibleShortName = FALSE;
 | |
|   }
 | |
| 
 | |
|   if (MainNameLen > FAT_MAIN_NAME_LEN) {
 | |
|     PossibleShortName = FALSE;
 | |
|     MainNameLen       = FAT_MAIN_NAME_LEN;
 | |
|   }
 | |
| 
 | |
|   if (ExtendNameLen > FAT_EXTEND_NAME_LEN) {
 | |
|     PossibleShortName = FALSE;
 | |
|     ExtendNameLen     = FAT_EXTEND_NAME_LEN;
 | |
|   }
 | |
| 
 | |
|   if (FatStrToFat (FileName, MainNameLen, File8Dot3Name)) {
 | |
|     PossibleShortName = FALSE;
 | |
|   }
 | |
| 
 | |
|   if (FatStrToFat (ExtendName, ExtendNameLen, File8Dot3Name + FAT_MAIN_NAME_LEN)) {
 | |
|     PossibleShortName = FALSE;
 | |
|   }
 | |
| 
 | |
|   return PossibleShortName;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Trim the trailing blanks of fat name.
 | |
| 
 | |
|   @param  Name                  - The Char8 string needs to be trimmed.
 | |
|   @param  Len                   - The length of the fat name.
 | |
| 
 | |
|   The real length of the fat name after the trailing blanks are trimmed.
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| UINTN
 | |
| FatTrimAsciiTrailingBlanks (
 | |
|   IN CHAR8        *Name,
 | |
|   IN UINTN        Len
 | |
|   )
 | |
| {
 | |
|   while (Len > 0 && Name[Len - 1] == ' ') {
 | |
|     Len--;
 | |
|   }
 | |
| 
 | |
|   return Len;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Convert the ascii fat name to the unicode string and strip trailing spaces,
 | |
|   and if necessary, convert the unicode string to lower case.
 | |
| 
 | |
|   @param  FatName               - The Char8 string needs to be converted.
 | |
|   @param  Len                   - The length of the fat name.
 | |
|   @param  LowerCase             - Indicate whether to convert the string to lower case.
 | |
|   @param  Str                   - The result of the conversion.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FatNameToStr (
 | |
|   IN  CHAR8            *FatName,
 | |
|   IN  UINTN            Len,
 | |
|   IN  UINTN            LowerCase,
 | |
|   OUT CHAR16           *Str
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // First, trim the trailing blanks
 | |
|   //
 | |
|   Len = FatTrimAsciiTrailingBlanks (FatName, Len);
 | |
|   //
 | |
|   // Convert fat string to unicode string
 | |
|   //
 | |
|   FatFatToStr (Len, FatName, Str);
 | |
| 
 | |
|   //
 | |
|   // If the name is to be lower cased, do it now
 | |
|   //
 | |
|   if (LowerCase != 0) {
 | |
|     FatStrLwr (Str);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   This function generates 8Dot3 name from user specified name for a newly created file.
 | |
| 
 | |
|   @param  Parent                - The parent directory.
 | |
|   @param  DirEnt                - The directory entry whose 8Dot3Name needs to be generated.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FatCreate8Dot3Name (
 | |
|   IN FAT_OFILE    *Parent,
 | |
|   IN FAT_DIRENT   *DirEnt
 | |
|   )
 | |
| {
 | |
|   CHAR8 *ShortName;
 | |
|   CHAR8 *ShortNameChar;
 | |
|   UINTN BaseTagLen;
 | |
|   UINTN Index;
 | |
|   UINTN Retry;
 | |
|   UINT8 Segment;
 | |
|   union {
 | |
|     UINT32  Crc;
 | |
|     struct HEX_DATA {
 | |
|       UINT8 Segment : HASH_VALUE_TAG_LEN;
 | |
|     } Hex[HASH_VALUE_TAG_LEN];
 | |
|   } HashValue;
 | |
|   //
 | |
|   // Make sure the whole directory has been loaded
 | |
|   //
 | |
|   ASSERT (Parent->ODir->EndOfDir);
 | |
|   ShortName = DirEnt->Entry.FileName;
 | |
| 
 | |
|   //
 | |
|   // Trim trailing blanks of 8.3 name
 | |
|   //
 | |
|   BaseTagLen = FatTrimAsciiTrailingBlanks (ShortName, FAT_MAIN_NAME_LEN);
 | |
|   if (BaseTagLen > SPEC_BASE_TAG_LEN) {
 | |
|     BaseTagLen = SPEC_BASE_TAG_LEN;
 | |
|   }
 | |
|   //
 | |
|   // We first use the algorithm described by spec.
 | |
|   //
 | |
|   ShortNameChar     = ShortName + BaseTagLen;
 | |
|   *ShortNameChar++  = '~';
 | |
|   *ShortNameChar    = '1';
 | |
|   Retry = 0;
 | |
|   while (*FatShortNameHashSearch (Parent->ODir, ShortName) != NULL) {
 | |
|     *ShortNameChar = (CHAR8)(*ShortNameChar + 1);
 | |
|     if (++Retry == MAX_SPEC_RETRY) {
 | |
|       //
 | |
|       // We use new algorithm to generate 8.3 name
 | |
|       //
 | |
|       ASSERT (DirEnt->FileString != NULL);
 | |
|       gBS->CalculateCrc32 (DirEnt->FileString, StrSize (DirEnt->FileString), &HashValue.Crc);
 | |
| 
 | |
|       if (BaseTagLen > HASH_BASE_TAG_LEN) {
 | |
|         BaseTagLen = HASH_BASE_TAG_LEN;
 | |
|       }
 | |
| 
 | |
|       ShortNameChar = ShortName + BaseTagLen;
 | |
|       for (Index = 0; Index < HASH_VALUE_TAG_LEN; Index++) {
 | |
|         Segment = HashValue.Hex[Index].Segment;
 | |
|         if (Segment > 9) {
 | |
|           *ShortNameChar++ = (CHAR8)(Segment - 10 + 'A');
 | |
|         } else {
 | |
|           *ShortNameChar++ = (CHAR8)(Segment + '0');
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       *ShortNameChar++  = '~';
 | |
|       *ShortNameChar    = '1';
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Check the string is lower case or upper case
 | |
|   and it is used by fatname to dir entry count
 | |
| 
 | |
|   @param Str                   - The string which needs to be checked.
 | |
|   @param InCaseFlag            - The input case flag which is returned when the string is lower case.
 | |
| 
 | |
|   @retval OutCaseFlag           - The output case flag.
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| UINT8
 | |
| FatCheckNameCase (
 | |
|   IN CHAR16           *Str,
 | |
|   IN UINT8            InCaseFlag
 | |
|   )
 | |
| {
 | |
|   CHAR16  Buffer[FAT_MAIN_NAME_LEN + 1 + FAT_EXTEND_NAME_LEN + 1];
 | |
|   UINT8   OutCaseFlag;
 | |
| 
 | |
|   //
 | |
|   // Assume the case of input string is mixed
 | |
|   //
 | |
|   OutCaseFlag = FAT_CASE_MIXED;
 | |
|   //
 | |
|   // Lower case a copy of the string, if it matches the
 | |
|   // original then the string is lower case
 | |
|   //
 | |
|   StrCpyS (Buffer, ARRAY_SIZE (Buffer), Str);
 | |
|   FatStrLwr (Buffer);
 | |
|   if (StrCmp (Str, Buffer) == 0) {
 | |
|     OutCaseFlag = InCaseFlag;
 | |
|   }
 | |
|   //
 | |
|   // Upper case a copy of the string, if it matches the
 | |
|   // original then the string is upper case
 | |
|   //
 | |
|   StrCpyS (Buffer, ARRAY_SIZE (Buffer), Str);
 | |
|   FatStrUpr (Buffer);
 | |
|   if (StrCmp (Str, Buffer) == 0) {
 | |
|     OutCaseFlag = 0;
 | |
|   }
 | |
| 
 | |
|   return OutCaseFlag;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Set the caseflag value for the directory entry.
 | |
| 
 | |
|   @param DirEnt                - The logical directory entry whose caseflag value is to be set.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FatSetCaseFlag (
 | |
|   IN FAT_DIRENT   *DirEnt
 | |
|   )
 | |
| {
 | |
|   CHAR16  LfnBuffer[FAT_MAIN_NAME_LEN + 1 + FAT_EXTEND_NAME_LEN + 1];
 | |
|   CHAR16  *TempCharPtr;
 | |
|   CHAR16  *ExtendName;
 | |
|   CHAR16  *FileNameCharPtr;
 | |
|   UINT8   CaseFlag;
 | |
| 
 | |
|   ExtendName      = NULL;
 | |
|   TempCharPtr     = LfnBuffer;
 | |
|   FileNameCharPtr = DirEnt->FileString;
 | |
|   ASSERT (StrSize (DirEnt->FileString) <= sizeof (LfnBuffer));
 | |
|   while ((*TempCharPtr = *FileNameCharPtr) != 0) {
 | |
|     if (*TempCharPtr == L'.') {
 | |
|       ExtendName = TempCharPtr;
 | |
|     }
 | |
| 
 | |
|     TempCharPtr++;
 | |
|     FileNameCharPtr++;
 | |
|   }
 | |
| 
 | |
|   CaseFlag = 0;
 | |
|   if (ExtendName != NULL) {
 | |
|     *ExtendName = 0;
 | |
|     ExtendName++;
 | |
|     CaseFlag = (UINT8)(CaseFlag | FatCheckNameCase (ExtendName, FAT_CASE_EXT_LOWER));
 | |
|   }
 | |
| 
 | |
|   CaseFlag = (UINT8)(CaseFlag | FatCheckNameCase (LfnBuffer, FAT_CASE_NAME_LOWER));
 | |
|   if ((CaseFlag & FAT_CASE_MIXED) == 0) {
 | |
|     //
 | |
|     // We just need one directory entry to store this file name entry
 | |
|     //
 | |
|     DirEnt->Entry.CaseFlag = CaseFlag;
 | |
|   } else {
 | |
|     //
 | |
|     // We need one extra directory entry to store the mixed case entry
 | |
|     //
 | |
|     DirEnt->Entry.CaseFlag = 0;
 | |
|     DirEnt->EntryCount++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Convert the 8.3 ASCII fat name to cased Unicode string according to case flag.
 | |
| 
 | |
|   @param  DirEnt                - The corresponding directory entry.
 | |
|   @param  FileString            - The output Unicode file name.
 | |
|   @param  FileStringMax           The max length of FileString.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FatGetFileNameViaCaseFlag (
 | |
|   IN     FAT_DIRENT   *DirEnt,
 | |
|   IN OUT CHAR16       *FileString,
 | |
|   IN     UINTN        FileStringMax
 | |
|   )
 | |
| {
 | |
|   UINT8   CaseFlag;
 | |
|   CHAR8   *File8Dot3Name;
 | |
|   CHAR16  TempExt[1 + FAT_EXTEND_NAME_LEN + 1];
 | |
|   //
 | |
|   // Store file extension like ".txt"
 | |
|   //
 | |
|   CaseFlag      = DirEnt->Entry.CaseFlag;
 | |
|   File8Dot3Name = DirEnt->Entry.FileName;
 | |
| 
 | |
|   FatNameToStr (File8Dot3Name, FAT_MAIN_NAME_LEN, CaseFlag & FAT_CASE_NAME_LOWER, FileString);
 | |
|   FatNameToStr (File8Dot3Name + FAT_MAIN_NAME_LEN, FAT_EXTEND_NAME_LEN, CaseFlag & FAT_CASE_EXT_LOWER, &TempExt[1]);
 | |
|   if (TempExt[1] != 0) {
 | |
|     TempExt[0] = L'.';
 | |
|     StrCatS (FileString, FileStringMax, TempExt);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Get the Check sum for a short name.
 | |
| 
 | |
|   @param  ShortNameString       - The short name for a file.
 | |
| 
 | |
|   @retval Sum                   - UINT8 checksum.
 | |
| 
 | |
| **/
 | |
| UINT8
 | |
| FatCheckSum (
 | |
|   IN CHAR8  *ShortNameString
 | |
|   )
 | |
| {
 | |
|   UINTN ShortNameLen;
 | |
|   UINT8 Sum;
 | |
|   Sum = 0;
 | |
|   for (ShortNameLen = FAT_NAME_LEN; ShortNameLen != 0; ShortNameLen--) {
 | |
|     Sum = (UINT8)((((Sum & 1) != 0) ? 0x80 : 0) + (Sum >> 1) + *ShortNameString++);
 | |
|   }
 | |
| 
 | |
|   return Sum;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Takes Path as input, returns the next name component
 | |
|   in Name, and returns the position after Name (e.g., the
 | |
|   start of the next name component)
 | |
| 
 | |
|   @param  Path                  - The path of one file.
 | |
|   @param  Name                  - The next name component in Path.
 | |
| 
 | |
|   The position after Name in the Path
 | |
| 
 | |
| **/
 | |
| CHAR16 *
 | |
| FatGetNextNameComponent (
 | |
|   IN  CHAR16      *Path,
 | |
|   OUT CHAR16      *Name
 | |
|   )
 | |
| {
 | |
|   while (*Path != 0 && *Path != PATH_NAME_SEPARATOR) {
 | |
|     *Name++ = *Path++;
 | |
|   }
 | |
|   *Name = 0;
 | |
|   //
 | |
|   // Get off of trailing path name separator
 | |
|   //
 | |
|   while (*Path == PATH_NAME_SEPARATOR) {
 | |
|     Path++;
 | |
|   }
 | |
| 
 | |
|   return Path;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Check whether the IFileName is valid long file name. If the IFileName is a valid
 | |
|   long file name, then we trim the possible leading blanks and leading/trailing dots.
 | |
|   the trimmed filename is stored in OutputFileName
 | |
| 
 | |
|   @param  InputFileName         - The input file name.
 | |
|   @param  OutputFileName        - The output file name.
 | |
| 
 | |
|   @retval TRUE                  - The InputFileName is a valid long file name.
 | |
|   @retval FALSE                 - The InputFileName is not a valid long file name.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| FatFileNameIsValid (
 | |
|   IN  CHAR16  *InputFileName,
 | |
|   OUT CHAR16  *OutputFileName
 | |
|   )
 | |
| {
 | |
|   CHAR16  *TempNamePointer;
 | |
|   CHAR16  TempChar;
 | |
|   //
 | |
|   // Trim Leading blanks
 | |
|   //
 | |
|   while (*InputFileName == L' ') {
 | |
|     InputFileName++;
 | |
|   }
 | |
| 
 | |
|   TempNamePointer = OutputFileName;
 | |
|   while (*InputFileName != 0) {
 | |
|     *TempNamePointer++ = *InputFileName++;
 | |
|   }
 | |
|   //
 | |
|   // Trim Trailing blanks and dots
 | |
|   //
 | |
|   while (TempNamePointer > OutputFileName) {
 | |
|     TempChar = *(TempNamePointer - 1);
 | |
|     if (TempChar != L' ' && TempChar != L'.') {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     TempNamePointer--;
 | |
|   }
 | |
| 
 | |
|   *TempNamePointer = 0;
 | |
| 
 | |
|   //
 | |
|   // Per FAT Spec the file name should meet the following criteria:
 | |
|   //   C1. Length (FileLongName) <= 255
 | |
|   //   C2. Length (X:FileFullPath<NUL>) <= 260
 | |
|   // Here we check C1.
 | |
|   //
 | |
|   if (TempNamePointer - OutputFileName > EFI_FILE_STRING_LENGTH) {
 | |
|     return FALSE;
 | |
|   }
 | |
|   //
 | |
|   // See if there is any illegal characters within the name
 | |
|   //
 | |
|   do {
 | |
|     if (*OutputFileName < 0x20 ||
 | |
|         *OutputFileName == '\"' ||
 | |
|         *OutputFileName == '*' ||
 | |
|         *OutputFileName == '/' ||
 | |
|         *OutputFileName == ':' ||
 | |
|         *OutputFileName == '<' ||
 | |
|         *OutputFileName == '>' ||
 | |
|         *OutputFileName == '?' ||
 | |
|         *OutputFileName == '\\' ||
 | |
|         *OutputFileName == '|'
 | |
|         ) {
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|     OutputFileName++;
 | |
|   } while (*OutputFileName != 0);
 | |
|   return TRUE;
 | |
| }
 |