/** Set the name of a file. This is a helper function for SetFileInfo(). @param[in] Instance A pointer to the description of the volume the file belongs to. @param[in] File A pointer to the description of the file. @param[in] FileName A pointer to the new name of the file. @retval EFI_SUCCESS The name was set. @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file to a file that is already present. **/ STATIC EFI_STATUS SetFileName ( IN BOOTMON_FS_INSTANCE *Instance, IN BOOTMON_FS_FILE *File, IN CONST CHAR16 *FileName ) { CHAR8 AsciiFileName[MAX_NAME_LENGTH]; BOOTMON_FS_FILE *SameFile; // If the file path start with a \ strip it. The EFI Shell may // insert a \ in front of the file name. if (FileName[0] == L'\\') { FileName++; } UnicodeStrToAsciiStrS (FileName, AsciiFileName, MAX_NAME_LENGTH); if (BootMonGetFileFromAsciiFileName ( File->Instance, AsciiFileName, &SameFile ) != EFI_NOT_FOUND) { // A file with that name already exists. return EFI_ACCESS_DENIED; } else { // OK, change the filename. AsciiStrToUnicodeStrS (AsciiFileName, File->Info->FileName, (File->Info->Size - SIZE_OF_EFI_FILE_INFO) / sizeof (CHAR16)); return EFI_SUCCESS; } }
STATIC EFI_STATUS SetFileName ( IN BOOTMON_FS_FILE *File, IN CHAR16 *FileNameUnicode ) { CHAR8 *FileNameAscii; UINT16 SavedChar; UINTN FileNameSize; BOOTMON_FS_FILE *SameFile; EFI_STATUS Status; // EFI Shell inserts '\' in front of the filename that must be stripped if (FileNameUnicode[0] == L'\\') { FileNameUnicode++; } // // Convert Unicode into Ascii // SavedChar = L'\0'; FileNameSize = StrLen (FileNameUnicode) + 1; FileNameAscii = AllocatePool (FileNameSize * sizeof (CHAR8)); if (FileNameAscii == NULL) { return EFI_OUT_OF_RESOURCES; } // If Unicode string is too long then truncate it. if (FileNameSize > MAX_NAME_LENGTH) { SavedChar = FileNameUnicode[MAX_NAME_LENGTH - 1]; FileNameUnicode[MAX_NAME_LENGTH - 1] = L'\0'; } UnicodeStrToAsciiStr (FileNameUnicode, FileNameAscii); // If the unicode string was truncated then restore its original content. if (SavedChar != L'\0') { FileNameUnicode[MAX_NAME_LENGTH - 1] = SavedChar; } // If we're changing the file name if (AsciiStrCmp (FileNameAscii, File->HwDescription.Footer.Filename) == 0) { // No change to filename. Status = EFI_SUCCESS; } else if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) { // You can only change the filename if you open the file for write. Status = EFI_ACCESS_DENIED; } else if (BootMonGetFileFromAsciiFileName ( File->Instance, File->HwDescription.Footer.Filename, &SameFile) != EFI_NOT_FOUND) { // A file with that name already exists. Status = EFI_ACCESS_DENIED; } else { // OK, change the filename. AsciiStrCpy (FileNameAscii, File->HwDescription.Footer.Filename); Status = EFI_SUCCESS; } FreePool (FileNameAscii); return Status; }
/** Opens a file on the Nor Flash FS volume Calls BootMonFsGetFileFromAsciiFilename to search the list of tracked files. @param This The EFI_FILE_PROTOCOL parent handle. @param NewHandle Double-pointer to the newly created protocol. @param FileName The name of the image/metadata on flash @param OpenMode Read,write,append etc @param Attributes ? @return EFI_STATUS OUT_OF_RESOURCES Run out of space to keep track of the allocated structures DEVICE_ERROR Unable to locate the volume associated with the parent file handle NOT_FOUND Filename wasn't found on flash SUCCESS **/ EFIAPI EFI_STATUS BootMonFsOpenFile ( IN EFI_FILE_PROTOCOL *This, OUT EFI_FILE_PROTOCOL **NewHandle, IN CHAR16 *FileName, IN UINT64 OpenMode, IN UINT64 Attributes ) { BOOTMON_FS_FILE *Directory; BOOTMON_FS_FILE *File; BOOTMON_FS_INSTANCE *Instance; CHAR8* AsciiFileName; EFI_STATUS Status; if ((FileName == NULL) || (NewHandle == NULL)) { return EFI_INVALID_PARAMETER; } // The only valid modes are read, read/write, and read/write/create if (!(OpenMode & EFI_FILE_MODE_READ) || ((OpenMode & EFI_FILE_MODE_CREATE) && !(OpenMode & EFI_FILE_MODE_WRITE))) { return EFI_INVALID_PARAMETER; } Directory = BOOTMON_FS_FILE_FROM_FILE_THIS (This); if (Directory == NULL) { return EFI_DEVICE_ERROR; } Instance = Directory->Instance; // If the instance has not been initialized it yet then do it ... if (!Instance->Initialized) { Status = BootMonFsInitialize (Instance); if (EFI_ERROR (Status)) { return Status; } } // BootMonFs interface requires ASCII filenames AsciiFileName = AllocatePool ((StrLen (FileName) + 1) * sizeof (CHAR8)); if (AsciiFileName == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStr (FileName, AsciiFileName); if ((AsciiStrCmp (AsciiFileName, "\\") == 0) || (AsciiStrCmp (AsciiFileName, "/") == 0) || (AsciiStrCmp (AsciiFileName, "") == 0) || (AsciiStrCmp (AsciiFileName, ".") == 0)) { // // Opening '/', '\', '.', or the NULL pathname is trying to open the root directory // *NewHandle = &Instance->RootFile->File; Instance->RootFile->Position = 0; Status = EFI_SUCCESS; } else { // // Open or Create a regular file // // Check if the file already exists Status = BootMonGetFileFromAsciiFileName (Instance, AsciiFileName, &File); if (Status == EFI_NOT_FOUND) { // The file doesn't exist. if (OpenMode & EFI_FILE_MODE_CREATE) { // If the file does not exist but is required then create it. if (Attributes & EFI_FILE_DIRECTORY) { // BootMonFS doesn't support subdirectories Status = EFI_UNSUPPORTED; } else { // Create a new file Status = CreateNewFile (Instance, AsciiFileName, &File); if (!EFI_ERROR (Status)) { File->OpenMode = OpenMode; *NewHandle = &File->File; File->Position = 0; } } } } else if (Status == EFI_SUCCESS) { // The file exists File->OpenMode = OpenMode; *NewHandle = &File->File; File->Position = 0; } } FreePool (AsciiFileName); return Status; }