+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- UnixSimpleFileSystem.c\r
-\r
-Abstract:\r
-\r
- Produce Simple File System abstractions for directories on your PC using Posix APIs.\r
- The configuration of what devices to mount or emulate comes from UNIX \r
- environment variables. The variables must be visible to the Microsoft* \r
- Developer Studio for them to work.\r
-\r
- * Other names and brands may be claimed as the property of others.\r
-\r
---*/\r
-\r
-#include "UnixSimpleFileSystem.h"\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding = {\r
- UnixSimpleFileSystemDriverBindingSupported,\r
- UnixSimpleFileSystemDriverBindingStart,\r
- UnixSimpleFileSystemDriverBindingStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-\r
-CHAR16 *\r
-EfiStrChr (\r
- IN CHAR16 *Str,\r
- IN CHAR16 Chr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Locate the first occurance of a character in a string.\r
-\r
-Arguments:\r
-\r
- Str - Pointer to NULL terminated unicode string.\r
- Chr - Character to locate.\r
-\r
-Returns:\r
-\r
- If Str is NULL, then NULL is returned.\r
- If Chr is not contained in Str, then NULL is returned.\r
- If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.\r
-\r
---*/\r
-{\r
- if (Str == NULL) {\r
- return Str;\r
- }\r
-\r
- while (*Str != '\0' && *Str != Chr) {\r
- ++Str;\r
- }\r
-\r
- return (*Str == Chr) ? Str : NULL;\r
-}\r
-\r
-BOOLEAN\r
-IsZero (\r
- IN VOID *Buffer,\r
- IN UINTN Length\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Buffer - TODO: add argument description\r
- Length - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- if (Buffer == NULL || Length == 0) {\r
- return FALSE;\r
- }\r
-\r
- if (*(UINT8 *) Buffer != 0) {\r
- return FALSE;\r
- }\r
-\r
- if (Length > 1) {\r
- if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) {\r
- return FALSE;\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-VOID\r
-CutPrefix (\r
- IN CHAR8 *Str,\r
- IN UINTN Count\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Str - TODO: add argument description\r
- Count - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- CHAR8 *Pointer;\r
-\r
- if (AsciiStrLen (Str) < Count) {\r
- ASSERT (0);\r
- }\r
-\r
- for (Pointer = Str; *(Pointer + Count); Pointer++) {\r
- *Pointer = *(Pointer + Count);\r
- }\r
-\r
- *Pointer = *(Pointer + Count);\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Check to see if the driver supports a given controller.\r
-\r
-Arguments:\r
-\r
- This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
-\r
- ControllerHandle - EFI handle of the controller to test.\r
-\r
- RemainingDevicePath - Pointer to remaining portion of a device path.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver\r
- specified by This.\r
-\r
- EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by\r
- the driver specified by This.\r
-\r
- EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by\r
- a different driver or an application that requires exclusive access.\r
-\r
- EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the\r
- driver specified by This.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_UNIX_IO_PROTOCOL *UnixIo;\r
-\r
- //\r
- // Open the IO Abstraction(s) needed to perform the supported test\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiUnixIoProtocolGuid,\r
- (VOID **)&UnixIo,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Make sure GUID is for a File System handle.\r
- //\r
- Status = EFI_UNSUPPORTED;\r
- if (CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) {\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Close the I/O Abstraction(s) used to perform the supported test\r
- //\r
- gBS->CloseProtocol (\r
- ControllerHandle,\r
- &gEfiUnixIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- ControllerHandle\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Starts a device controller or a bus controller.\r
-\r
-Arguments:\r
-\r
- This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
-\r
- ControllerHandle - EFI handle of the controller to start.\r
-\r
- RemainingDevicePath - Pointer to remaining portion of a device path.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The device or bus controller has been started.\r
-\r
- EFI_DEVICE_ERROR - The device could not be started due to a device failure.\r
-\r
- EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_UNIX_IO_PROTOCOL *UnixIo;\r
- UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
- INTN i;\r
-\r
- Private = NULL;\r
-\r
- //\r
- // Open the IO Abstraction(s) needed\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiUnixIoProtocolGuid,\r
- (VOID **)&UnixIo,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Validate GUID\r
- //\r
- if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (UNIX_SIMPLE_FILE_SYSTEM_PRIVATE),\r
- (VOID **)&Private\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Private->Signature = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;\r
- Private->UnixThunk = UnixIo->UnixThunk;\r
- Private->FilePath = NULL;\r
- Private->VolumeLabel = NULL;\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- StrLen (UnixIo->EnvString) + 1,\r
- (VOID **)&Private->FilePath\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- for (i = 0; UnixIo->EnvString[i] != 0; i++)\r
- Private->FilePath[i] = UnixIo->EnvString[i];\r
- Private->FilePath[i] = 0;\r
-\r
- Private->VolumeLabel = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- StrSize (L"EFI_EMULATED"),\r
- (VOID **)&Private->VolumeLabel\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- StrCpy (Private->VolumeLabel, L"EFI_EMULATED");\r
-\r
- Private->SimpleFileSystem.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;\r
- Private->SimpleFileSystem.OpenVolume = UnixSimpleFileSystemOpenVolume;\r
-\r
- Private->ControllerNameTable = NULL;\r
-\r
- AddUnicodeString (\r
- "eng",\r
- gUnixSimpleFileSystemComponentName.SupportedLanguages,\r
- &Private->ControllerNameTable,\r
- UnixIo->EnvString\r
- );\r
-\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ControllerHandle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- &Private->SimpleFileSystem,\r
- NULL\r
- );\r
-\r
-Done:\r
- if (EFI_ERROR (Status)) {\r
-\r
- if (Private != NULL) {\r
-\r
- if (Private->VolumeLabel != NULL)\r
- gBS->FreePool (Private->VolumeLabel);\r
- if (Private->FilePath != NULL)\r
- gBS->FreePool (Private->FilePath);\r
- FreeUnicodeStringTable (Private->ControllerNameTable);\r
-\r
- gBS->FreePool (Private);\r
- }\r
-\r
- gBS->CloseProtocol (\r
- ControllerHandle,\r
- &gEfiUnixIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- ControllerHandle\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE ControllerHandle,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
-\r
- ControllerHandle - A handle to the device to be stopped.\r
-\r
- NumberOfChildren - The number of child device handles in ChildHandleBuffer.\r
-\r
- ChildHandleBuffer - An array of child device handles to be freed.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The device has been stopped.\r
-\r
- EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.\r
-\r
---*/\r
-// TODO: EFI_UNSUPPORTED - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;\r
- UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
-\r
- //\r
- // Get our context back\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- (VOID **)&SimpleFileSystem,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem);\r
-\r
- //\r
- // Uninstall the Simple File System Protocol from ControllerHandle\r
- //\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- ControllerHandle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- &Private->SimpleFileSystem,\r
- NULL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = gBS->CloseProtocol (\r
- ControllerHandle,\r
- &gEfiUnixIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- ControllerHandle\r
- );\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Free our instance data\r
- //\r
- FreeUnicodeStringTable (Private->ControllerNameTable);\r
-\r
- gBS->FreePool (Private);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemOpenVolume (\r
- IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
- OUT EFI_FILE_PROTOCOL **Root\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Open the root directory on a volume.\r
-\r
-Arguments:\r
-\r
- This - A pointer to the volume to open.\r
-\r
- Root - A pointer to storage for the returned opened file handle of the root directory.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The volume was opened.\r
-\r
- EFI_UNSUPPORTED - The volume does not support the requested file system type.\r
-\r
- EFI_NO_MEDIA - The device has no media.\r
-\r
- EFI_DEVICE_ERROR - The device reported an error.\r
-\r
- EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
-\r
- EFI_ACCESS_DENIED - The service denied access to the file.\r
-\r
- EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.\r
-\r
- EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL || Root == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- PrivateFile = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (UNIX_EFI_FILE_PRIVATE),\r
- (VOID **)&PrivateFile\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- PrivateFile->FileName = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- AsciiStrSize (Private->FilePath),\r
- (VOID **)&PrivateFile->FileName\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- AsciiStrCpy (PrivateFile->FileName, Private->FilePath);\r
- PrivateFile->Signature = UNIX_EFI_FILE_PRIVATE_SIGNATURE;\r
- PrivateFile->UnixThunk = Private->UnixThunk;\r
- PrivateFile->SimpleFileSystem = This;\r
- PrivateFile->IsRootDirectory = TRUE;\r
- PrivateFile->IsDirectoryPath = TRUE;\r
- PrivateFile->IsOpenedByRead = TRUE;\r
- PrivateFile->EfiFile.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;\r
- PrivateFile->EfiFile.Open = UnixSimpleFileSystemOpen;\r
- PrivateFile->EfiFile.Close = UnixSimpleFileSystemClose;\r
- PrivateFile->EfiFile.Delete = UnixSimpleFileSystemDelete;\r
- PrivateFile->EfiFile.Read = UnixSimpleFileSystemRead;\r
- PrivateFile->EfiFile.Write = UnixSimpleFileSystemWrite;\r
- PrivateFile->EfiFile.GetPosition = UnixSimpleFileSystemGetPosition;\r
- PrivateFile->EfiFile.SetPosition = UnixSimpleFileSystemSetPosition;\r
- PrivateFile->EfiFile.GetInfo = UnixSimpleFileSystemGetInfo;\r
- PrivateFile->EfiFile.SetInfo = UnixSimpleFileSystemSetInfo;\r
- PrivateFile->EfiFile.Flush = UnixSimpleFileSystemFlush;\r
- PrivateFile->fd = -1;\r
- PrivateFile->Dir = NULL;\r
- PrivateFile->Dirent = NULL;\r
- \r
- *Root = &PrivateFile->EfiFile;\r
-\r
- PrivateFile->Dir = PrivateFile->UnixThunk->OpenDir(PrivateFile->FileName);\r
-\r
- if (PrivateFile->Dir == NULL) {\r
- Status = EFI_ACCESS_DENIED;\r
- }\r
- else {\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
-Done:\r
- if (EFI_ERROR (Status)) {\r
- if (PrivateFile) {\r
- if (PrivateFile->FileName) {\r
- gBS->FreePool (PrivateFile->FileName);\r
- }\r
-\r
- gBS->FreePool (PrivateFile);\r
- }\r
- \r
- *Root = NULL;\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemOpen (\r
- IN EFI_FILE_PROTOCOL *This,\r
- OUT EFI_FILE_PROTOCOL **NewHandle,\r
- IN CHAR16 *FileName,\r
- IN UINT64 OpenMode,\r
- IN UINT64 Attributes\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Open a file relative to the source file location.\r
-\r
-Arguments:\r
-\r
- This - A pointer to the source file location.\r
-\r
- NewHandle - Pointer to storage for the new file handle.\r
-\r
- FileName - Pointer to the file name to be opened.\r
-\r
- OpenMode - File open mode information.\r
-\r
- Attributes - File creation attributes.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The file was opened.\r
-\r
- EFI_NOT_FOUND - The file could not be found in the volume.\r
-\r
- EFI_NO_MEDIA - The device has no media.\r
-\r
- EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.\r
-\r
- EFI_DEVICE_ERROR - The device reported an error.\r
-\r
- EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
-\r
- EFI_WRITE_PROTECTED - The volume or file is write protected.\r
-\r
- EFI_ACCESS_DENIED - The service denied access to the file.\r
-\r
- EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.\r
-\r
- EFI_VOLUME_FULL - There is not enough space left to create the new file.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- EFI_FILE_PROTOCOL *Root;\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- UNIX_EFI_FILE_PRIVATE *NewPrivateFile;\r
- UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
- EFI_STATUS Status;\r
- CHAR16 *Src;\r
- char *Dst;\r
- CHAR8 *RealFileName;\r
- char *ParseFileName;\r
- char *GuardPointer;\r
- CHAR8 TempChar;\r
- UINTN Count;\r
- BOOLEAN TrailingDash;\r
- BOOLEAN LoopFinish;\r
- UINTN InfoSize;\r
- EFI_FILE_INFO *Info;\r
-\r
- TrailingDash = FALSE;\r
-\r
- //\r
- // Check for obvious invalid parameters.\r
- //\r
- if (This == NULL || NewHandle == NULL || FileName == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- switch (OpenMode) {\r
- case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
- if (Attributes &~EFI_FILE_VALID_ATTR) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (Attributes & EFI_FILE_READ_ONLY) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // fall through\r
- //\r
- case EFI_FILE_MODE_READ:\r
- case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
- break;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
-\r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
- PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
- NewPrivateFile = NULL;\r
-\r
- //\r
- // BUGBUG: assume an open of root\r
- // if current location, return current data\r
- //\r
- if (StrCmp (FileName, L"\\") == 0\r
- || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) {\r
- //\r
- // BUGBUG: assume an open root\r
- //\r
-OpenRoot:\r
- Status = UnixSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root);\r
- NewPrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root);\r
- goto Done;\r
- }\r
-\r
- if (FileName[StrLen (FileName) - 1] == L'\\') {\r
- TrailingDash = TRUE;\r
- FileName[StrLen (FileName) - 1] = 0;\r
- }\r
-\r
- //\r
- // Attempt to open the file\r
- //\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- sizeof (UNIX_EFI_FILE_PRIVATE),\r
- (VOID **)&NewPrivateFile\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- CopyMem (NewPrivateFile, PrivateFile, sizeof (UNIX_EFI_FILE_PRIVATE));\r
-\r
- NewPrivateFile->FileName = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- AsciiStrSize (PrivateFile->FileName) + 1 + StrLen (FileName) + 1,\r
- (VOID **)&NewPrivateFile->FileName\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- if (*FileName == L'\\') {\r
- AsciiStrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);\r
- // Skip first '\'.\r
- Src = FileName + 1;\r
- } else {\r
- AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName);\r
- Src = FileName;\r
- }\r
- Dst = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName);\r
- GuardPointer = NewPrivateFile->FileName + AsciiStrLen(PrivateRoot->FilePath);\r
- *Dst++ = '/';\r
- // Convert unicode to ascii and '\' to '/'\r
- while (*Src) {\r
- if (*Src == '\\')\r
- *Dst++ = '/';\r
- else\r
- *Dst++ = *Src;\r
- Src++;\r
- }\r
- *Dst = 0;\r
- \r
-\r
- //\r
- // Get rid of . and .., except leading . or ..\r
- //\r
-\r
- //\r
- // GuardPointer protect simplefilesystem root path not be destroyed\r
- //\r
-\r
- LoopFinish = FALSE;\r
-\r
- while (!LoopFinish) {\r
-\r
- LoopFinish = TRUE;\r
-\r
- for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {\r
- if (*ParseFileName == '.' &&\r
- (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == '/') &&\r
- *(ParseFileName - 1) == '/'\r
- ) {\r
-\r
- //\r
- // cut /.\r
- //\r
- CutPrefix (ParseFileName - 1, 2);\r
- LoopFinish = FALSE;\r
- break;\r
- }\r
-\r
- if (*ParseFileName == '.' &&\r
- *(ParseFileName + 1) == '.' &&\r
- (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == '/') &&\r
- *(ParseFileName - 1) == '/'\r
- ) {\r
-\r
- ParseFileName--;\r
- Count = 3;\r
-\r
- while (ParseFileName != GuardPointer) {\r
- ParseFileName--;\r
- Count++;\r
- if (*ParseFileName == '/') {\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // cut /.. and its left directory\r
- //\r
- CutPrefix (ParseFileName, Count);\r
- LoopFinish = FALSE;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (AsciiStrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {\r
- NewPrivateFile->IsRootDirectory = TRUE;\r
- gBS->FreePool (NewPrivateFile->FileName);\r
- gBS->FreePool (NewPrivateFile);\r
- goto OpenRoot;\r
- }\r
-\r
- RealFileName = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName) - 1;\r
- while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/')\r
- RealFileName--;\r
-\r
- TempChar = *(RealFileName - 1);\r
- *(RealFileName - 1) = 0;\r
-\r
- *(RealFileName - 1) = TempChar;\r
-\r
-\r
-\r
- //\r
- // Test whether file or directory\r
- //\r
- NewPrivateFile->IsRootDirectory = FALSE;\r
- NewPrivateFile->fd = -1;\r
- NewPrivateFile->Dir = NULL;\r
- if (OpenMode & EFI_FILE_MODE_CREATE) {\r
- if (Attributes & EFI_FILE_DIRECTORY) {\r
- NewPrivateFile->IsDirectoryPath = TRUE;\r
- } else {\r
- NewPrivateFile->IsDirectoryPath = FALSE;\r
- }\r
- } else {\r
- STAT_FIX finfo;\r
- int res = NewPrivateFile->UnixThunk->Stat (NewPrivateFile->FileName, &finfo);\r
- if (res == 0 && S_ISDIR(finfo.st_mode))\r
- NewPrivateFile->IsDirectoryPath = TRUE;\r
- else\r
- NewPrivateFile->IsDirectoryPath = FALSE;\r
- }\r
-\r
- if (OpenMode & EFI_FILE_MODE_WRITE) {\r
- NewPrivateFile->IsOpenedByRead = FALSE;\r
- } else {\r
- NewPrivateFile->IsOpenedByRead = TRUE;\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- //\r
- // deal with directory\r
- //\r
- if (NewPrivateFile->IsDirectoryPath) {\r
-\r
- if ((OpenMode & EFI_FILE_MODE_CREATE)) {\r
- //\r
- // Create a directory\r
- //\r
- if (NewPrivateFile->UnixThunk->MkDir (NewPrivateFile->FileName, 0777) != 0) {\r
- INTN LastError;\r
-\r
- LastError = PrivateFile->UnixThunk->GetErrno ();\r
- if (LastError != EEXIST) {\r
- //gBS->FreePool (TempFileName);\r
- Status = EFI_ACCESS_DENIED;\r
- goto Done;\r
- }\r
- }\r
- }\r
-\r
- NewPrivateFile->Dir = NewPrivateFile->UnixThunk->OpenDir\r
- (NewPrivateFile->FileName);\r
-\r
- if (NewPrivateFile->Dir == NULL) {\r
- if (PrivateFile->UnixThunk->GetErrno () == EACCES) {\r
- Status = EFI_ACCESS_DENIED;\r
- } else {\r
- Status = EFI_NOT_FOUND;\r
- }\r
-\r
- goto Done;\r
- }\r
-\r
- } else {\r
- //\r
- // deal with file\r
- //\r
- NewPrivateFile->fd = NewPrivateFile->UnixThunk->Open\r
- (NewPrivateFile->FileName,\r
- ((OpenMode & EFI_FILE_MODE_CREATE) ? O_CREAT : 0)\r
- | (NewPrivateFile->IsOpenedByRead ? O_RDONLY : O_RDWR),\r
- 0666);\r
- if (NewPrivateFile->fd < 0) {\r
- if (PrivateFile->UnixThunk->GetErrno () == ENOENT) {\r
- Status = EFI_NOT_FOUND;\r
- } else {\r
- Status = EFI_ACCESS_DENIED;\r
- }\r
- }\r
- }\r
-\r
- if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {\r
- //\r
- // Set the attribute\r
- //\r
- InfoSize = 0;\r
- Info = NULL;\r
-\r
- Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
-\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- InfoSize,\r
- (VOID **)&Info\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Info->Attribute = Attributes;\r
-\r
- UnixSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);\r
- }\r
-\r
-Done: ;\r
- if (TrailingDash) {\r
- FileName[StrLen (FileName) + 1] = 0;\r
- FileName[StrLen (FileName)] = L'\\';\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- if (NewPrivateFile) {\r
- if (NewPrivateFile->FileName) {\r
- gBS->FreePool (NewPrivateFile->FileName);\r
- }\r
-\r
- gBS->FreePool (NewPrivateFile);\r
- }\r
- } else {\r
- *NewHandle = &NewPrivateFile->EfiFile;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemClose (\r
- IN EFI_FILE_PROTOCOL *This\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Close the specified file handle.\r
-\r
-Arguments:\r
-\r
- This - Pointer to a returned opened file handle.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The file handle has been closed.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- if (PrivateFile->fd >= 0) {\r
- PrivateFile->UnixThunk->Close (PrivateFile->fd);\r
- }\r
- if (PrivateFile->Dir != NULL) {\r
- PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);\r
- }\r
-\r
- PrivateFile->fd = -1;\r
- PrivateFile->Dir = NULL;\r
-\r
- if (PrivateFile->FileName) {\r
- gBS->FreePool (PrivateFile->FileName);\r
- }\r
-\r
- gBS->FreePool (PrivateFile);\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- \r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemDelete (\r
- IN EFI_FILE_PROTOCOL *This\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Close and delete a file.\r
-\r
-Arguments:\r
-\r
- This - Pointer to a returned opened file handle.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The file handle was closed and deleted.\r
-\r
- EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- \r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- Status = EFI_WARN_DELETE_FAILURE;\r
-\r
- if (PrivateFile->IsDirectoryPath) {\r
- if (PrivateFile->Dir != NULL) {\r
- PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);\r
- PrivateFile->Dir = NULL;\r
- }\r
-\r
- if (PrivateFile->UnixThunk->RmDir (PrivateFile->FileName) == 0) {\r
- Status = EFI_SUCCESS;\r
- }\r
- } else {\r
- PrivateFile->UnixThunk->Close (PrivateFile->fd);\r
- PrivateFile->fd = -1;\r
-\r
- if (!PrivateFile->IsOpenedByRead) {\r
- if (!PrivateFile->UnixThunk->UnLink (PrivateFile->FileName)) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
- }\r
-\r
- gBS->FreePool (PrivateFile->FileName);\r
- gBS->FreePool (PrivateFile);\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return Status;\r
-}\r
-\r
-VOID\r
-UnixSystemTimeToEfiTime (\r
- EFI_UNIX_THUNK_PROTOCOL *UnixThunk,\r
- IN time_t SystemTime,\r
- OUT EFI_TIME *Time\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- SystemTime - TODO: add argument description\r
- TimeZone - TODO: add argument description\r
- Time - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- struct tm *tm;\r
- tm = UnixThunk->GmTime (&SystemTime);\r
- Time->Year = tm->tm_year;\r
- Time->Month = tm->tm_mon + 1;\r
- Time->Day = tm->tm_mday;\r
- Time->Hour = tm->tm_hour;\r
- Time->Minute = tm->tm_min;\r
- Time->Second = tm->tm_sec;\r
- Time->Nanosecond = 0;\r
-\r
- Time->TimeZone = UnixThunk->GetTimeZone ();\r
-\r
- if (UnixThunk->GetDayLight ()) {\r
- Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-UnixSimpleFileSystemFileInfo (\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile,\r
- IN CHAR8 *FileName,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- TODO: Add function description\r
-\r
-Arguments:\r
-\r
- PrivateFile - TODO: add argument description\r
- BufferSize - TODO: add argument description\r
- Buffer - TODO: add argument description\r
-\r
-Returns:\r
-\r
- TODO: add return values\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINTN Size;\r
- UINTN NameSize;\r
- UINTN ResultSize;\r
- EFI_FILE_INFO *Info;\r
- CHAR8 *RealFileName;\r
- CHAR8 *TempPointer;\r
- CHAR16 *BufferFileName;\r
- STAT_FIX buf;\r
-\r
- if (FileName != NULL) {\r
- RealFileName = FileName;\r
- }\r
- else if (PrivateFile->IsRootDirectory) {\r
- RealFileName = "";\r
- } else {\r
- RealFileName = PrivateFile->FileName;\r
- }\r
-\r
- TempPointer = RealFileName;\r
- while (*TempPointer) {\r
- if (*TempPointer == '/') {\r
- RealFileName = TempPointer + 1;\r
- }\r
-\r
- TempPointer++;\r
- }\r
-\r
- Size = SIZE_OF_EFI_FILE_INFO;\r
- NameSize = AsciiStrSize (RealFileName) * 2;\r
- ResultSize = Size + NameSize;\r
-\r
- if (*BufferSize < ResultSize) {\r
- *BufferSize = ResultSize;\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
- if (PrivateFile->UnixThunk->Stat (\r
- FileName == NULL ? PrivateFile->FileName : FileName,\r
- &buf) < 0)\r
- return EFI_DEVICE_ERROR;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- Info = Buffer;\r
- ZeroMem (Info, ResultSize);\r
-\r
- Info->Size = ResultSize;\r
- Info->FileSize = buf.st_size;\r
- Info->PhysicalSize = MultU64x32 (buf.st_blocks, buf.st_blksize);\r
-\r
- UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_ctime, &Info->CreateTime);\r
- UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_atime, &Info->LastAccessTime);\r
- UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_mtime, &Info->ModificationTime);\r
-\r
- if (!(buf.st_mode & S_IWUSR)) {\r
- Info->Attribute |= EFI_FILE_READ_ONLY;\r
- }\r
-\r
- if (S_ISDIR(buf.st_mode)) {\r
- Info->Attribute |= EFI_FILE_DIRECTORY;\r
- }\r
-\r
-\r
- BufferFileName = (CHAR16 *)((CHAR8 *) Buffer + Size);\r
- while (*RealFileName)\r
- *BufferFileName++ = *RealFileName++;\r
- *BufferFileName = 0;\r
-\r
- *BufferSize = ResultSize;\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemRead (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read data from a file.\r
-\r
-Arguments:\r
-\r
- This - Pointer to a returned open file handle.\r
-\r
- BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.\r
-\r
- Buffer - Pointer to the first byte of the read Buffer.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The data was read.\r
-\r
- EFI_NO_MEDIA - The device has no media.\r
-\r
- EFI_DEVICE_ERROR - The device reported an error.\r
-\r
- EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
-\r
- EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.\r
- *BufferSize has been updated with the size needed to complete the request.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_STATUS Status;\r
- INTN Res;\r
- UINTN Size;\r
- UINTN NameSize;\r
- UINTN ResultSize;\r
- CHAR8 *FullFileName;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL || BufferSize == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if ((*BufferSize != 0) && (Buffer == NULL)) {\r
- // Buffer can be NULL if *BufferSize is zero\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- \r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (!PrivateFile->IsDirectoryPath) {\r
-\r
- if (PrivateFile->fd < 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- Res = PrivateFile->UnixThunk->Read (\r
- PrivateFile->fd,\r
- Buffer,\r
- *BufferSize);\r
- if (Res < 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
- *BufferSize = Res;\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Read on a directory.\r
- //\r
- if (PrivateFile->Dir == NULL) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- if (PrivateFile->Dirent == NULL) {\r
- PrivateFile->Dirent = PrivateFile->UnixThunk->ReadDir (PrivateFile->Dir);\r
- if (PrivateFile->Dirent == NULL) {\r
- *BufferSize = 0;\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
- }\r
-\r
- Size = SIZE_OF_EFI_FILE_INFO;\r
- NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1;\r
- ResultSize = Size + 2 * NameSize;\r
-\r
- if (*BufferSize < ResultSize) {\r
- *BufferSize = ResultSize;\r
- Status = EFI_BUFFER_TOO_SMALL;\r
- goto Done;\r
- }\r
- Status = EFI_SUCCESS;\r
-\r
- *BufferSize = ResultSize;\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- AsciiStrLen(PrivateFile->FileName) + 1 + NameSize,\r
- (VOID **)&FullFileName\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- \r
- AsciiStrCpy(FullFileName, PrivateFile->FileName);\r
- AsciiStrCat(FullFileName, "/");\r
- AsciiStrCat(FullFileName, PrivateFile->Dirent->d_name);\r
- Status = UnixSimpleFileSystemFileInfo (PrivateFile,\r
- FullFileName,\r
- BufferSize,\r
- Buffer);\r
- gBS->FreePool (FullFileName);\r
-\r
- PrivateFile->Dirent = NULL;\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemWrite (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN OUT UINTN *BufferSize,\r
- IN VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Write data to a file.\r
-\r
-Arguments:\r
-\r
- This - Pointer to an opened file handle.\r
-\r
- BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes\r
- of data written to the file.\r
-\r
- Buffer - Pointer to the first by of data in the buffer to write to the file.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The data was written to the file.\r
-\r
- EFI_UNSUPPORTED - Writes to an open directory are not supported.\r
-\r
- EFI_NO_MEDIA - The device has no media.\r
-\r
- EFI_DEVICE_ERROR - The device reported an error.\r
-\r
- EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
-\r
- EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
-\r
- EFI_ACCESS_DENIED - The file was opened read-only.\r
-\r
- EFI_VOLUME_FULL - The volume is full.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- UINTN Res;\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (PrivateFile->fd < 0) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (PrivateFile->IsDirectoryPath) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (PrivateFile->IsOpenedByRead) {\r
- return EFI_ACCESS_DENIED;\r
- }\r
-\r
- Res = PrivateFile->UnixThunk->Write (\r
- PrivateFile->fd,\r
- Buffer,\r
- *BufferSize);\r
- if (Res == (UINTN)-1) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
- *BufferSize = Res;\r
- Status = EFI_SUCCESS;\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-\r
- //\r
- // bugbug: need to access unix error reporting\r
- //\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemSetPosition (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN UINT64 Position\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set a file's current position.\r
-\r
-Arguments:\r
-\r
- This - Pointer to an opened file handle.\r
-\r
- Position - The byte position from the start of the file to set.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The file position has been changed.\r
-\r
- EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- UINT64 Pos;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- \r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (PrivateFile->IsDirectoryPath) {\r
- if (Position != 0) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
-\r
- if (PrivateFile->Dir == NULL) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
- PrivateFile->UnixThunk->RewindDir (PrivateFile->Dir);\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- } else {\r
- if (Position == (UINT64) -1) {\r
- Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_END);\r
- } else {\r
- Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, Position, SEEK_SET);\r
- }\r
- Status = (Pos == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
- }\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemGetPosition (\r
- IN EFI_FILE_PROTOCOL *This,\r
- OUT UINT64 *Position\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Get a file's current position.\r
-\r
-Arguments:\r
-\r
- This - Pointer to an opened file handle.\r
-\r
- Position - Pointer to storage for the current position.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The file position has been reported.\r
-\r
- EFI_UNSUPPORTED - Not valid for directories.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL || Position == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- \r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (PrivateFile->IsDirectoryPath) {\r
- Status = EFI_UNSUPPORTED;\r
- } else {\r
- *Position = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_CUR);\r
- Status = (*Position == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemGetInfo (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN EFI_GUID *InformationType,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Return information about a file or volume.\r
-\r
-Arguments:\r
-\r
- This - Pointer to an opened file handle.\r
-\r
- InformationType - GUID describing the type of information to be returned.\r
-\r
- BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the\r
- information buffer.\r
-\r
- Buffer - Pointer to the first byte of the information buffer.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The requested information has been written into the buffer.\r
-\r
- EFI_UNSUPPORTED - The InformationType is not known.\r
-\r
- EFI_NO_MEDIA - The device has no media.\r
-\r
- EFI_DEVICE_ERROR - The device reported an error.\r
-\r
- EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
-\r
- EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has\r
- been updated with the size needed to complete the requested operation.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- EFI_STATUS Status;\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;\r
- INTN UnixStatus;\r
- UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
- struct statfs buf;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL || InformationType == NULL || BufferSize == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- \r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
- PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
-\r
- Status = EFI_UNSUPPORTED;\r
-\r
- if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
- Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, BufferSize, Buffer);\r
- } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
- if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
- *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
- Status = EFI_BUFFER_TOO_SMALL;\r
- goto Done;\r
- }\r
-\r
- UnixStatus = PrivateFile->UnixThunk->StatFs (PrivateFile->FileName, &buf);\r
- if (UnixStatus < 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
- FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
- FileSystemInfoBuffer->ReadOnly = FALSE;\r
-\r
- //\r
- // Succeeded\r
- //\r
- FileSystemInfoBuffer->VolumeSize = MultU64x32 (buf.f_blocks, buf.f_bsize);\r
- FileSystemInfoBuffer->FreeSpace = MultU64x32 (buf.f_bavail, buf.f_bsize);\r
- FileSystemInfoBuffer->BlockSize = buf.f_bsize;\r
-\r
-\r
- StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);\r
- *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
- Status = EFI_SUCCESS;\r
- } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
- if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
- *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
- Status = EFI_BUFFER_TOO_SMALL;\r
- goto Done;\r
- }\r
-\r
- StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);\r
- *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemSetInfo (\r
- IN EFI_FILE_PROTOCOL*This,\r
- IN EFI_GUID *InformationType,\r
- IN UINTN BufferSize,\r
- IN VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Set information about a file or volume.\r
-\r
-Arguments:\r
-\r
- This - Pointer to an opened file handle.\r
-\r
- InformationType - GUID identifying the type of information to set.\r
-\r
- BufferSize - Number of bytes of data in the information buffer.\r
-\r
- Buffer - Pointer to the first byte of data in the information buffer.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The file or volume information has been updated.\r
-\r
- EFI_UNSUPPORTED - The information identifier is not recognised.\r
-\r
- EFI_NO_MEDIA - The device has no media.\r
-\r
- EFI_DEVICE_ERROR - The device reported an error.\r
-\r
- EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
-\r
- EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
-\r
- EFI_ACCESS_DENIED - The file was opened read-only.\r
-\r
- EFI_VOLUME_FULL - The volume is full.\r
-\r
- EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_FILE_INFO *OldFileInfo;\r
- EFI_FILE_INFO *NewFileInfo;\r
- EFI_STATUS Status;\r
- UINTN OldInfoSize;\r
- EFI_TPL OldTpl;\r
- mode_t NewAttr;\r
- STAT_FIX OldAttr;\r
- CHAR8 *OldFileName;\r
- CHAR8 *NewFileName;\r
- CHAR8 *CharPointer;\r
- BOOLEAN AttrChangeFlag;\r
- BOOLEAN NameChangeFlag;\r
- BOOLEAN SizeChangeFlag;\r
- BOOLEAN TimeChangeFlag;\r
- struct tm NewLastAccessSystemTime;\r
- struct tm NewLastWriteSystemTime;\r
- EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;\r
- CHAR8 *AsciiFilePtr;\r
- CHAR16 *UnicodeFilePtr;\r
- INTN UnixStatus;\r
-\r
- //\r
- // Check for invalid parameters.\r
- //\r
- if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- \r
- //\r
- // Initialise locals.\r
- //\r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
- PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
-\r
- Status = EFI_UNSUPPORTED;\r
- OldFileInfo = NewFileInfo = NULL;\r
- OldFileName = NewFileName = NULL;\r
- AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;\r
-\r
- //\r
- // Set file system information.\r
- //\r
- if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
- if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- goto Done;\r
- }\r
-\r
- NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
-\r
- gBS->FreePool (PrivateRoot->VolumeLabel);\r
-\r
- PrivateRoot->VolumeLabel = NULL;\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- StrSize (NewFileSystemInfo->VolumeLabel),\r
- (VOID **)&PrivateRoot->VolumeLabel\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);\r
-\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Set volume label information.\r
- //\r
- if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
- if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- goto Done;\r
- }\r
-\r
- StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);\r
-\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
-\r
- if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
-\r
- if (BufferSize < SIZE_OF_EFI_FILE_INFO) {\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Set file/directory information.\r
- //\r
-\r
- //\r
- // Check for invalid set file information parameters.\r
- //\r
- NewFileInfo = (EFI_FILE_INFO *) Buffer;\r
-\r
- if ((NewFileInfo->Size <= SIZE_OF_EFI_FILE_INFO) ||\r
- (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||\r
- (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)\r
- ) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- //\r
- // bugbug: - This is not safe. We need something like EfiStrMaxSize()\r
- // that would have an additional parameter that would be the size\r
- // of the string array just in case there are no NULL characters in\r
- // the string array.\r
- //\r
- //\r
- // Get current file information so we can determine what kind\r
- // of change request this is.\r
- //\r
- OldInfoSize = 0;\r
- Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL);\r
-\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize,\r
- (VOID **)&OldFileInfo);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo);\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- AsciiStrSize (PrivateFile->FileName),\r
- (VOID **)&OldFileName\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- AsciiStrCpy (OldFileName, PrivateFile->FileName);\r
-\r
- //\r
- // Make full pathname from new filename and rootpath.\r
- //\r
- if (NewFileInfo->FileName[0] == '\\') {\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1,\r
- (VOID **)&NewFileName\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
- AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);\r
- UnicodeFilePtr = NewFileInfo->FileName + 1;\r
- *AsciiFilePtr++ ='/';\r
- } else {\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- AsciiStrLen (PrivateFile->FileName) + 2 + StrLen (NewFileInfo->FileName) + 1,\r
- (VOID **)&NewFileName\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
- AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);\r
- if ((AsciiFilePtr[-1] != '/') && (NewFileInfo->FileName[0] != '/')) {\r
- // make sure there is a / between Root FilePath and NewFileInfo Filename\r
- AsciiFilePtr[0] = '/'; \r
- AsciiFilePtr[1] = '\0';\r
- AsciiFilePtr++;\r
- }\r
- UnicodeFilePtr = NewFileInfo->FileName;\r
- }\r
- // Convert to ascii.\r
- while (*UnicodeFilePtr) {\r
- *AsciiFilePtr++ = *UnicodeFilePtr++;\r
- }\r
- *AsciiFilePtr = 0;\r
-\r
-\r
- //\r
- // Is there an attribute change request?\r
- //\r
- if (NewFileInfo->Attribute != OldFileInfo->Attribute) {\r
- if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
-\r
- AttrChangeFlag = TRUE;\r
- }\r
-\r
- //\r
- // Is there a name change request?\r
- // bugbug: - Need EfiStrCaseCmp()\r
- //\r
- if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {\r
- NameChangeFlag = TRUE;\r
- }\r
-\r
- //\r
- // Is there a size change request?\r
- //\r
- if (NewFileInfo->FileSize != OldFileInfo->FileSize) {\r
- SizeChangeFlag = TRUE;\r
- }\r
-\r
- //\r
- // Is there a time stamp change request?\r
- //\r
- if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&\r
- CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))\r
- ) {\r
- TimeChangeFlag = TRUE;\r
- } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&\r
- CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))\r
- ) {\r
- TimeChangeFlag = TRUE;\r
- } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&\r
- CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))\r
- ) {\r
- TimeChangeFlag = TRUE;\r
- }\r
-\r
- //\r
- // All done if there are no change requests being made.\r
- //\r
- if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Set file or directory information.\r
- //\r
- if (PrivateFile->UnixThunk->Stat (OldFileName, &OldAttr) != 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- //\r
- // Name change.\r
- //\r
- if (NameChangeFlag) {\r
- //\r
- // Close the handles first\r
- //\r
- if (PrivateFile->IsOpenedByRead) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Done;\r
- }\r
-\r
- for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {\r
- }\r
-\r
- if (*CharPointer != 0) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Done;\r
- }\r
-\r
- UnixStatus = PrivateFile->UnixThunk->Rename (OldFileName, NewFileName);\r
-\r
- if (UnixStatus == 0) {\r
- //\r
- // modify file name\r
- //\r
- gBS->FreePool (PrivateFile->FileName);\r
-\r
- Status = gBS->AllocatePool (\r
- EfiBootServicesData,\r
- AsciiStrSize (NewFileName),\r
- (VOID **)&PrivateFile->FileName\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
-\r
- AsciiStrCpy (PrivateFile->FileName, NewFileName);\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
- }\r
-\r
- //\r
- // Size change\r
- //\r
- if (SizeChangeFlag) {\r
- if (PrivateFile->IsDirectoryPath) {\r
- Status = EFI_UNSUPPORTED;\r
- goto Done;\r
- }\r
-\r
- if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Done;\r
- }\r
-\r
- if (PrivateFile->UnixThunk->FTruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- }\r
-\r
- //\r
- // Time change\r
- //\r
- if (TimeChangeFlag) {\r
- struct utimbuf utime;\r
-\r
- NewLastAccessSystemTime.tm_year = NewFileInfo->LastAccessTime.Year;\r
- NewLastAccessSystemTime.tm_mon = NewFileInfo->LastAccessTime.Month;\r
- NewLastAccessSystemTime.tm_mday = NewFileInfo->LastAccessTime.Day;\r
- NewLastAccessSystemTime.tm_hour = NewFileInfo->LastAccessTime.Hour;\r
- NewLastAccessSystemTime.tm_min = NewFileInfo->LastAccessTime.Minute;\r
- NewLastAccessSystemTime.tm_sec = NewFileInfo->LastAccessTime.Second;\r
- NewLastAccessSystemTime.tm_isdst = 0;\r
-\r
- utime.actime = PrivateFile->UnixThunk->MkTime (&NewLastAccessSystemTime);\r
-\r
- NewLastWriteSystemTime.tm_year = NewFileInfo->ModificationTime.Year;\r
- NewLastWriteSystemTime.tm_mon = NewFileInfo->ModificationTime.Month;\r
- NewLastWriteSystemTime.tm_mday = NewFileInfo->ModificationTime.Day;\r
- NewLastWriteSystemTime.tm_hour = NewFileInfo->ModificationTime.Hour;\r
- NewLastWriteSystemTime.tm_min = NewFileInfo->ModificationTime.Minute;\r
- NewLastWriteSystemTime.tm_sec = NewFileInfo->ModificationTime.Second;\r
- NewLastWriteSystemTime.tm_isdst = 0;\r
-\r
- utime.modtime = PrivateFile->UnixThunk->MkTime (&NewLastWriteSystemTime);\r
-\r
- if (utime.actime == (time_t)-1 || utime.modtime == (time_t)-1) {\r
- goto Done;\r
- }\r
-\r
- if (PrivateFile->UnixThunk->UTime (PrivateFile->FileName, &utime) == -1) {\r
- goto Done;\r
- }\r
- }\r
-\r
- //\r
- // No matter about AttrChangeFlag, Attribute must be set.\r
- // Because operation before may cause attribute change.\r
- //\r
- NewAttr = OldAttr.st_mode;\r
-\r
- if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
- NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH);\r
- } else {\r
- NewAttr |= S_IRUSR;\r
- }\r
-\r
- UnixStatus = PrivateFile->UnixThunk->Chmod (NewFileName, NewAttr);\r
- if (UnixStatus != 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
-\r
-Done:\r
- if (OldFileInfo != NULL) {\r
- gBS->FreePool (OldFileInfo);\r
- }\r
-\r
- if (OldFileName != NULL) {\r
- gBS->FreePool (OldFileName);\r
- }\r
-\r
- if (NewFileName != NULL) {\r
- gBS->FreePool (NewFileName);\r
- }\r
-\r
- gBS->RestoreTPL (OldTpl);\r
- \r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-UnixSimpleFileSystemFlush (\r
- IN EFI_FILE_PROTOCOL *This\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Flush all modified data to the media.\r
-\r
-Arguments:\r
-\r
- This - Pointer to an opened file handle.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - The data has been flushed.\r
-\r
- EFI_NO_MEDIA - The device has no media.\r
-\r
- EFI_DEVICE_ERROR - The device reported an error.\r
-\r
- EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.\r
-\r
- EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
-\r
- EFI_ACCESS_DENIED - The file was opened read-only.\r
-\r
- EFI_VOLUME_FULL - The volume is full.\r
-\r
---*/\r
-// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-{\r
- UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
- \r
- PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
-\r
-\r
- if (PrivateFile->IsDirectoryPath) {\r
- goto Done;\r
- }\r
-\r
- if (PrivateFile->IsOpenedByRead) {\r
- Status = EFI_ACCESS_DENIED;\r
- goto Done;\r
- }\r
-\r
- if (PrivateFile->fd < 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Done;\r
- }\r
-\r
- PrivateFile->UnixThunk->FSync (PrivateFile->fd) == 0 ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
-\r
-Done:\r
- gBS->RestoreTPL (OldTpl);\r
-\r
- return Status;\r
-\r
- //\r
- // bugbug: - Use Unix error reporting.\r
- //\r
-}\r
-\r
-\r