From 804405e7d10525e41720216137b2551f62a0663f Mon Sep 17 00:00:00 2001 From: eric_tian Date: Mon, 30 Jun 2008 05:08:49 +0000 Subject: Port EdkUnixPkg to UnixPkg. The changes are listed as follows: 1. change *.msa to *.inf, and create platform configuration files .dec&.dsc&.fdf to comply with Edk2 build process 2. using PCD mechanism to replace macro. 3. change Sec code to cowork with PI1.0 Pei Core and produce temparory memory ppi. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5380 6f19259b-4bc3-4df7-8a09-765794883524 --- UnixPkg/UnixSimpleFileSystemDxe/ComponentName.c | 204 ++ UnixPkg/UnixSimpleFileSystemDxe/EntryPoint.c | 51 + .../UnixSimpleFileSystemDxe/UnixSimpleFileSystem.c | 2186 ++++++++++++++++++++ .../UnixSimpleFileSystemDxe/UnixSimpleFileSystem.h | 599 ++++++ .../UnixSimpleFileSystem.inf | 71 + .../UnixSimpleFileSystem.msa | 94 + 6 files changed, 3205 insertions(+) create mode 100644 UnixPkg/UnixSimpleFileSystemDxe/ComponentName.c create mode 100644 UnixPkg/UnixSimpleFileSystemDxe/EntryPoint.c create mode 100644 UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.c create mode 100644 UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.h create mode 100644 UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.inf create mode 100644 UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.msa (limited to 'UnixPkg/UnixSimpleFileSystemDxe') diff --git a/UnixPkg/UnixSimpleFileSystemDxe/ComponentName.c b/UnixPkg/UnixSimpleFileSystemDxe/ComponentName.c new file mode 100644 index 0000000000..347326dcb8 --- /dev/null +++ b/UnixPkg/UnixSimpleFileSystemDxe/ComponentName.c @@ -0,0 +1,204 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "UnixSimpleFileSystem.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UnixSimpleFileSystemComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUnixSimpleFileSystemComponentName = { + UnixSimpleFileSystemComponentNameGetDriverName, + UnixSimpleFileSystemComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mUnixSimpleFileSystemDriverNameTable[] = { + { + "eng", + L"Unix Simple File System Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUnixSimpleFileSystemComponentName.SupportedLanguages, + mUnixSimpleFileSystemDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure this driver is currently managing ControllerHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gUnixSimpleFileSystemDriverBinding.DriverBindingHandle, + &gEfiUnixIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**)&SimpleFileSystem, + gUnixSimpleFileSystemDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem); + + return LookupUnicodeString ( + Language, + gUnixSimpleFileSystemComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/UnixPkg/UnixSimpleFileSystemDxe/EntryPoint.c b/UnixPkg/UnixSimpleFileSystemDxe/EntryPoint.c new file mode 100644 index 0000000000..44e271bc19 --- /dev/null +++ b/UnixPkg/UnixSimpleFileSystemDxe/EntryPoint.c @@ -0,0 +1,51 @@ +/**@file + Entry Point Source file. + + This file contains the user entry point + + Copyright (c) 2006 - 2008, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + + + +#include "UnixSimpleFileSystem.h" + +/** + The user Entry Point for module UnixSimpleFileSystem. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeUnixSimpleFileSystem( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gUnixSimpleFileSystemDriverBinding, + ImageHandle, + &gUnixSimpleFileSystemComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} diff --git a/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.c b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.c new file mode 100644 index 0000000000..84ba962739 --- /dev/null +++ b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.c @@ -0,0 +1,2186 @@ +/*++ + +Copyright (c) 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + UnixSimpleFileSystem.c + +Abstract: + + Produce Simple File System abstractions for directories on your PC using Posix APIs. + The configuration of what devices to mount or emulate comes from UNIX + environment variables. The variables must be visible to the Microsoft* + Developer Studio for them to work. + + * Other names and brands may be claimed as the property of others. + +--*/ + +#include "UnixSimpleFileSystem.h" + +EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding = { + UnixSimpleFileSystemDriverBindingSupported, + UnixSimpleFileSystemDriverBindingStart, + UnixSimpleFileSystemDriverBindingStop, + 0xa, + NULL, + NULL +}; + + +CHAR16 * +EfiStrChr ( + IN CHAR16 *Str, + IN CHAR16 Chr + ) +/*++ + +Routine Description: + + Locate the first occurance of a character in a string. + +Arguments: + + Str - Pointer to NULL terminated unicode string. + Chr - Character to locate. + +Returns: + + If Str is NULL, then NULL is returned. + If Chr is not contained in Str, then NULL is returned. + If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned. + +--*/ +{ + if (Str == NULL) { + return Str; + } + + while (*Str != '\0' && *Str != Chr) { + ++Str; + } + + return (*Str == Chr) ? Str : NULL; +} + +BOOLEAN +IsZero ( + IN VOID *Buffer, + IN UINTN Length + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Buffer - TODO: add argument description + Length - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + if (Buffer == NULL || Length == 0) { + return FALSE; + } + + if (*(UINT8 *) Buffer != 0) { + return FALSE; + } + + if (Length > 1) { + if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) { + return FALSE; + } + } + + return TRUE; +} + +VOID +CutPrefix ( + IN CHAR8 *Str, + IN UINTN Count + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Str - TODO: add argument description + Count - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + CHAR8 *Pointer; + + if (AsciiStrLen (Str) < Count) { + ASSERT (0); + } + + for (Pointer = Str; *(Pointer + Count); Pointer++) { + *Pointer = *(Pointer + Count); + } + + *Pointer = *(Pointer + Count); +} + + + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Check to see if the driver supports a given controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to test. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver + specified by This. + + EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + the driver specified by This. + + EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + a different driver or an application that requires exclusive access. + + EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the + driver specified by This. + +--*/ +{ + EFI_STATUS Status; + EFI_UNIX_IO_PROTOCOL *UnixIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUnixIoProtocolGuid, + (VOID **)&UnixIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure GUID is for a File System handle. + // + Status = EFI_UNSUPPORTED; + if (CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) { + Status = EFI_SUCCESS; + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUnixIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Starts a device controller or a bus controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to start. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device or bus controller has been started. + + EFI_DEVICE_ERROR - The device could not be started due to a device failure. + + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + EFI_UNIX_IO_PROTOCOL *UnixIo; + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + INTN i; + + Private = NULL; + + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUnixIoProtocolGuid, + (VOID **)&UnixIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Validate GUID + // + if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (UNIX_SIMPLE_FILE_SYSTEM_PRIVATE), + (VOID **)&Private + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Private->Signature = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE; + Private->UnixThunk = UnixIo->UnixThunk; + Private->FilePath = NULL; + Private->VolumeLabel = NULL; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrLen (UnixIo->EnvString) + 1, + (VOID **)&Private->FilePath + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + for (i = 0; UnixIo->EnvString[i] != 0; i++) + Private->FilePath[i] = UnixIo->EnvString[i]; + Private->FilePath[i] = 0; + + Private->VolumeLabel = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (L"EFI_EMULATED"), + (VOID **)&Private->VolumeLabel + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (Private->VolumeLabel, L"EFI_EMULATED"); + + Private->SimpleFileSystem.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION; + Private->SimpleFileSystem.OpenVolume = UnixSimpleFileSystemOpenVolume; + + Private->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gUnixSimpleFileSystemComponentName.SupportedLanguages, + &Private->ControllerNameTable, + UnixIo->EnvString + ); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + &Private->SimpleFileSystem, + NULL + ); + +Done: + if (EFI_ERROR (Status)) { + + if (Private != NULL) { + + if (Private->VolumeLabel != NULL) + gBS->FreePool (Private->VolumeLabel); + if (Private->FilePath != NULL) + gBS->FreePool (Private->FilePath); + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUnixIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - A handle to the device to be stopped. + + NumberOfChildren - The number of child device handles in ChildHandleBuffer. + + ChildHandleBuffer - An array of child device handles to be freed. + +Returns: + + EFI_SUCCESS - The device has been stopped. + + EFI_DEVICE_ERROR - The device could not be stopped due to a device failure. + +--*/ +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **)&SimpleFileSystem, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem); + + // + // Uninstall the Simple File System Protocol from ControllerHandle + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + &Private->SimpleFileSystem, + NULL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiUnixIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + if (!EFI_ERROR (Status)) { + // + // Free our instance data + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE **Root + ) +/*++ + +Routine Description: + + Open the root directory on a volume. + +Arguments: + + This - A pointer to the volume to open. + + Root - A pointer to storage for the returned opened file handle of the root directory. + +Returns: + + EFI_SUCCESS - The volume was opened. + + EFI_UNSUPPORTED - The volume does not support the requested file system type. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_TPL OldTpl; + + if (This == NULL || Root == NULL) { + return EFI_INVALID_PARAMETER; + } + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This); + + PrivateFile = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (UNIX_EFI_FILE_PRIVATE), + (VOID **)&PrivateFile + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + PrivateFile->FileName = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + AsciiStrSize (Private->FilePath), + (VOID **)&PrivateFile->FileName + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + AsciiStrCpy (PrivateFile->FileName, Private->FilePath); + PrivateFile->Signature = UNIX_EFI_FILE_PRIVATE_SIGNATURE; + PrivateFile->UnixThunk = Private->UnixThunk; + PrivateFile->SimpleFileSystem = This; + PrivateFile->IsRootDirectory = TRUE; + PrivateFile->IsDirectoryPath = TRUE; + PrivateFile->IsOpenedByRead = TRUE; + PrivateFile->EfiFile.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION; + PrivateFile->EfiFile.Open = UnixSimpleFileSystemOpen; + PrivateFile->EfiFile.Close = UnixSimpleFileSystemClose; + PrivateFile->EfiFile.Delete = UnixSimpleFileSystemDelete; + PrivateFile->EfiFile.Read = UnixSimpleFileSystemRead; + PrivateFile->EfiFile.Write = UnixSimpleFileSystemWrite; + PrivateFile->EfiFile.GetPosition = UnixSimpleFileSystemGetPosition; + PrivateFile->EfiFile.SetPosition = UnixSimpleFileSystemSetPosition; + PrivateFile->EfiFile.GetInfo = UnixSimpleFileSystemGetInfo; + PrivateFile->EfiFile.SetInfo = UnixSimpleFileSystemSetInfo; + PrivateFile->EfiFile.Flush = UnixSimpleFileSystemFlush; + PrivateFile->fd = -1; + PrivateFile->Dir = NULL; + PrivateFile->Dirent = NULL; + + *Root = &PrivateFile->EfiFile; + + PrivateFile->Dir = PrivateFile->UnixThunk->OpenDir(PrivateFile->FileName); + + if (PrivateFile->Dir == NULL) { + Status = EFI_ACCESS_DENIED; + } + else { + Status = EFI_SUCCESS; + } + +Done: + if (EFI_ERROR (Status)) { + if (PrivateFile) { + if (PrivateFile->FileName) { + gBS->FreePool (PrivateFile->FileName); + } + + gBS->FreePool (PrivateFile); + } + } + + gBS->RestoreTPL (OldTpl); + + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemOpen ( + IN EFI_FILE *This, + OUT EFI_FILE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Open a file relative to the source file location. + +Arguments: + + This - A pointer to the source file location. + + NewHandle - Pointer to storage for the new file handle. + + FileName - Pointer to the file name to be opened. + + OpenMode - File open mode information. + + Attributes - File creation attributes. + +Returns: + + EFI_SUCCESS - The file was opened. + + EFI_NOT_FOUND - The file could not be found in the volume. + + EFI_NO_MEDIA - The device has no media. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_WRITE_PROTECTED - The volume or file is write protected. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file. + + EFI_VOLUME_FULL - There is not enough space left to create the new file. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_FILE *Root; + UNIX_EFI_FILE_PRIVATE *PrivateFile; + UNIX_EFI_FILE_PRIVATE *NewPrivateFile; + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + EFI_STATUS Status; + CHAR16 *Src; + char *Dst; + CHAR8 *RealFileName; + char *ParseFileName; + char *GuardPointer; + CHAR8 TempChar; + UINTN Count; + BOOLEAN TrailingDash; + BOOLEAN LoopFinish; + UINTN InfoSize; + EFI_FILE_INFO *Info; + + TrailingDash = FALSE; + + // + // Check for obvious invalid parameters. + // + if (This == NULL || NewHandle == NULL || FileName == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (OpenMode) { + case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: + if (Attributes &~EFI_FILE_VALID_ATTR) { + return EFI_INVALID_PARAMETER; + } + + if (Attributes & EFI_FILE_READ_ONLY) { + return EFI_INVALID_PARAMETER; + } + + // + // fall through + // + case EFI_FILE_MODE_READ: + case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: + break; + + default: + return EFI_INVALID_PARAMETER; + } + + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + NewPrivateFile = NULL; + + // + // BUGBUG: assume an open of root + // if current location, return current data + // + if (StrCmp (FileName, L"\\") == 0 + || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) { + // + // BUGBUG: assume an open root + // +OpenRoot: + Status = UnixSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root); + NewPrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root); + goto Done; + } + + if (FileName[StrLen (FileName) - 1] == L'\\') { + TrailingDash = TRUE; + FileName[StrLen (FileName) - 1] = 0; + } + + // + // Attempt to open the file + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (UNIX_EFI_FILE_PRIVATE), + (VOID **)&NewPrivateFile + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (NewPrivateFile, PrivateFile, sizeof (UNIX_EFI_FILE_PRIVATE)); + + NewPrivateFile->FileName = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + AsciiStrSize (PrivateFile->FileName) + 1 + StrLen (FileName) + 1, + (VOID **)&NewPrivateFile->FileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (*FileName == L'\\') { + AsciiStrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath); + // Skip first '\'. + Src = FileName + 1; + } else { + AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName); + Src = FileName; + } + Dst = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName); + GuardPointer = NewPrivateFile->FileName + AsciiStrLen(PrivateRoot->FilePath); + *Dst++ = '/'; + // Convert unicode to ascii and '\' to '/' + while (*Src) { + if (*Src == '\\') + *Dst++ = '/'; + else + *Dst++ = *Src; + Src++; + } + *Dst = 0; + + + // + // Get rid of . and .., except leading . or .. + // + + // + // GuardPointer protect simplefilesystem root path not be destroyed + // + + LoopFinish = FALSE; + + while (!LoopFinish) { + + LoopFinish = TRUE; + + for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) { + if (*ParseFileName == '.' && + (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == '/') && + *(ParseFileName - 1) == '/' + ) { + + // + // cut /. + // + CutPrefix (ParseFileName - 1, 2); + LoopFinish = FALSE; + break; + } + + if (*ParseFileName == '.' && + *(ParseFileName + 1) == '.' && + (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == '/') && + *(ParseFileName - 1) == '/' + ) { + + ParseFileName--; + Count = 3; + + while (ParseFileName != GuardPointer) { + ParseFileName--; + Count++; + if (*ParseFileName == '/') { + break; + } + } + + // + // cut /.. and its left directory + // + CutPrefix (ParseFileName, Count); + LoopFinish = FALSE; + break; + } + } + } + + if (AsciiStrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) { + NewPrivateFile->IsRootDirectory = TRUE; + gBS->FreePool (NewPrivateFile->FileName); + gBS->FreePool (NewPrivateFile); + goto OpenRoot; + } + + RealFileName = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName) - 1; + while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/') + RealFileName--; + + TempChar = *(RealFileName - 1); + *(RealFileName - 1) = 0; + + *(RealFileName - 1) = TempChar; + + + + // + // Test whether file or directory + // + NewPrivateFile->IsRootDirectory = FALSE; + NewPrivateFile->fd = -1; + NewPrivateFile->Dir = NULL; + if (OpenMode & EFI_FILE_MODE_CREATE) { + if (Attributes & EFI_FILE_DIRECTORY) { + NewPrivateFile->IsDirectoryPath = TRUE; + } else { + NewPrivateFile->IsDirectoryPath = FALSE; + } + } else { + struct stat finfo; + int res = NewPrivateFile->UnixThunk->Stat (NewPrivateFile->FileName, &finfo); + if (res == 0 && S_ISDIR(finfo.st_mode)) + NewPrivateFile->IsDirectoryPath = TRUE; + else + NewPrivateFile->IsDirectoryPath = FALSE; + } + + if (OpenMode & EFI_FILE_MODE_WRITE) { + NewPrivateFile->IsOpenedByRead = FALSE; + } else { + NewPrivateFile->IsOpenedByRead = TRUE; + } + + Status = EFI_SUCCESS; + + // + // deal with directory + // + if (NewPrivateFile->IsDirectoryPath) { + + if ((OpenMode & EFI_FILE_MODE_CREATE)) { + // + // Create a directory + // + if (NewPrivateFile->UnixThunk->MkDir (NewPrivateFile->FileName, 0777) != 0) { + INTN LastError; + + LastError = PrivateFile->UnixThunk->GetErrno (); + if (LastError != EEXIST) { + //gBS->FreePool (TempFileName); + Status = EFI_ACCESS_DENIED; + goto Done; + } + } + } + + NewPrivateFile->Dir = NewPrivateFile->UnixThunk->OpenDir + (NewPrivateFile->FileName); + + if (NewPrivateFile->Dir == NULL) { + if (PrivateFile->UnixThunk->GetErrno () == EACCES) { + Status = EFI_ACCESS_DENIED; + } else { + Status = EFI_NOT_FOUND; + } + + goto Done; + } + + } else { + // + // deal with file + // + NewPrivateFile->fd = NewPrivateFile->UnixThunk->Open + (NewPrivateFile->FileName, + ((OpenMode & EFI_FILE_MODE_CREATE) ? O_CREAT : 0) + | (NewPrivateFile->IsOpenedByRead ? O_RDONLY : O_RDWR), + 0666); + if (NewPrivateFile->fd < 0) { + if (PrivateFile->UnixThunk->GetErrno () == ENOENT) { + Status = EFI_NOT_FOUND; + } else { + Status = EFI_ACCESS_DENIED; + } + } + } + + if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) { + // + // Set the attribute + // + InfoSize = 0; + Info = NULL; + + Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info); + + if (Status != EFI_BUFFER_TOO_SMALL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + InfoSize, + (VOID **)&Info + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Info->Attribute = Attributes; + + UnixSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info); + } + +Done: ; + if (TrailingDash) { + FileName[StrLen (FileName) + 1] = 0; + FileName[StrLen (FileName)] = L'\\'; + } + + if (EFI_ERROR (Status)) { + if (NewPrivateFile) { + if (NewPrivateFile->FileName) { + gBS->FreePool (NewPrivateFile->FileName); + } + + gBS->FreePool (NewPrivateFile); + } + } else { + *NewHandle = &NewPrivateFile->EfiFile; + } + + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemClose ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close the specified file handle. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle has been closed. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_TPL OldTpl; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + if (PrivateFile->fd >= 0) { + PrivateFile->UnixThunk->Close (PrivateFile->fd); + } + if (PrivateFile->Dir != NULL) { + PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir); + } + + PrivateFile->fd = -1; + PrivateFile->Dir = NULL; + + if (PrivateFile->FileName) { + gBS->FreePool (PrivateFile->FileName); + } + + gBS->FreePool (PrivateFile); + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDelete ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close and delete a file. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle was closed and deleted. + + EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_TPL OldTpl; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + Status = EFI_WARN_DELETE_FAILURE; + + if (PrivateFile->IsDirectoryPath) { + if (PrivateFile->Dir != NULL) { + PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir); + PrivateFile->Dir = NULL; + } + + if (PrivateFile->UnixThunk->RmDir (PrivateFile->FileName) == 0) { + Status = EFI_SUCCESS; + } + } else { + PrivateFile->UnixThunk->Close (PrivateFile->fd); + PrivateFile->fd = -1; + + if (!PrivateFile->IsOpenedByRead) { + if (!PrivateFile->UnixThunk->UnLink (PrivateFile->FileName)) { + Status = EFI_SUCCESS; + } + } + } + + gBS->FreePool (PrivateFile->FileName); + gBS->FreePool (PrivateFile); + + gBS->RestoreTPL (OldTpl); + + return Status; +} + +STATIC +VOID +UnixSystemTimeToEfiTime ( + EFI_UNIX_THUNK_PROTOCOL *UnixThunk, + IN time_t SystemTime, + OUT EFI_TIME *Time + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SystemTime - TODO: add argument description + TimeZone - TODO: add argument description + Time - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + struct tm *tm; + tm = UnixThunk->GmTime (&SystemTime); + Time->Year = tm->tm_year; + Time->Month = tm->tm_mon; + Time->Day = tm->tm_mday; + Time->Hour = tm->tm_hour; + Time->Minute = tm->tm_min; + Time->Second = tm->tm_sec; + Time->Nanosecond = 0; + + Time->TimeZone = UnixThunk->GetTimeZone (); + + if (UnixThunk->GetDayLight ()) { + Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT; + } +} + +STATIC +EFI_STATUS +UnixSimpleFileSystemFileInfo ( + UNIX_EFI_FILE_PRIVATE *PrivateFile, + IN CHAR8 *FileName, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PrivateFile - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + UINTN Size; + UINTN NameSize; + UINTN ResultSize; + EFI_FILE_INFO *Info; + CHAR8 *RealFileName; + CHAR8 *TempPointer; + CHAR16 *BufferFileName; + struct stat buf; + + if (FileName != NULL) { + RealFileName = FileName; + } + else if (PrivateFile->IsRootDirectory) { + RealFileName = ""; + } else { + RealFileName = PrivateFile->FileName; + } + + TempPointer = RealFileName; + while (*TempPointer) { + if (*TempPointer == '/') { + RealFileName = TempPointer + 1; + } + + TempPointer++; + } + + Size = SIZE_OF_EFI_FILE_INFO; + NameSize = AsciiStrSize (RealFileName) * 2; + ResultSize = Size + NameSize; + + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + return EFI_BUFFER_TOO_SMALL; + } + if (PrivateFile->UnixThunk->Stat ( + FileName == NULL ? PrivateFile->FileName : FileName, + &buf) < 0) + return EFI_DEVICE_ERROR; + + Status = EFI_SUCCESS; + + Info = Buffer; + ZeroMem (Info, ResultSize); + + Info->Size = ResultSize; + Info->FileSize = buf.st_size; + Info->PhysicalSize = MultU64x32 (buf.st_blocks, buf.st_blksize); + + UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_ctime, &Info->CreateTime); + UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_atime, &Info->LastAccessTime); + UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_mtime, &Info->ModificationTime); + + if (!(buf.st_mode & S_IWUSR)) { + Info->Attribute |= EFI_FILE_READ_ONLY; + } + + if (S_ISDIR(buf.st_mode)) { + Info->Attribute |= EFI_FILE_DIRECTORY; + } + + + BufferFileName = (CHAR16 *)((CHAR8 *) Buffer + Size); + while (*RealFileName) + *BufferFileName++ = *RealFileName++; + *BufferFileName = 0; + + *BufferSize = ResultSize; + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemRead ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read data from a file. + +Arguments: + + This - Pointer to a returned open file handle. + + BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer. + + Buffer - Pointer to the first byte of the read Buffer. + +Returns: + + EFI_SUCCESS - The data was read. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry. + *BufferSize has been updated with the size needed to complete the request. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_STATUS Status; + INTN Res; + UINTN Size; + UINTN NameSize; + UINTN ResultSize; + CHAR8 *FullFileName; + EFI_TPL OldTpl; + + if (This == NULL || BufferSize == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (!PrivateFile->IsDirectoryPath) { + + if (PrivateFile->fd < 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Res = PrivateFile->UnixThunk->Read ( + PrivateFile->fd, + Buffer, + *BufferSize); + if (Res < 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + *BufferSize = Res; + Status = EFI_SUCCESS; + goto Done; + } + + // + // Read on a directory. + // + if (PrivateFile->Dir == NULL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + if (PrivateFile->Dirent == NULL) { + PrivateFile->Dirent = PrivateFile->UnixThunk->ReadDir (PrivateFile->Dir); + if (PrivateFile->Dirent == NULL) { + *BufferSize = 0; + Status = EFI_SUCCESS; + goto Done; + } + } + + Size = SIZE_OF_EFI_FILE_INFO; + NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1; + ResultSize = Size + 2 * NameSize; + + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } + Status = EFI_SUCCESS; + + *BufferSize = ResultSize; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + AsciiStrLen(PrivateFile->FileName) + 1 + NameSize, + (VOID **)&FullFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + AsciiStrCpy(FullFileName, PrivateFile->FileName); + AsciiStrCat(FullFileName, "/"); + AsciiStrCat(FullFileName, PrivateFile->Dirent->d_name); + Status = UnixSimpleFileSystemFileInfo (PrivateFile, + FullFileName, + BufferSize, + Buffer); + gBS->FreePool (FullFileName); + + PrivateFile->Dirent = NULL; + +Done: + gBS->RestoreTPL (OldTpl); + + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemWrite ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Write data to a file. + +Arguments: + + This - Pointer to an opened file handle. + + BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes + of data written to the file. + + Buffer - Pointer to the first by of data in the buffer to write to the file. + +Returns: + + EFI_SUCCESS - The data was written to the file. + + EFI_UNSUPPORTED - Writes to an open directory are not supported. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + UNIX_EFI_FILE_PRIVATE *PrivateFile; + UINTN Res; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (This == NULL || BufferSize == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->fd < 0) { + return EFI_DEVICE_ERROR; + } + + if (PrivateFile->IsDirectoryPath) { + return EFI_UNSUPPORTED; + } + + if (PrivateFile->IsOpenedByRead) { + return EFI_ACCESS_DENIED; + } + + Res = PrivateFile->UnixThunk->Write ( + PrivateFile->fd, + Buffer, + *BufferSize); + if (Res == (UINTN)-1) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + *BufferSize = Res; + Status = EFI_SUCCESS; + +Done: + gBS->RestoreTPL (OldTpl); + return Status; + + // + // bugbug: need to access unix error reporting + // +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemSetPosition ( + IN EFI_FILE *This, + IN UINT64 Position + ) +/*++ + +Routine Description: + + Set a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - The byte position from the start of the file to set. + +Returns: + + EFI_SUCCESS - The file position has been changed. + + EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + UNIX_EFI_FILE_PRIVATE *PrivateFile; + UINT64 Pos; + EFI_TPL OldTpl; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->IsDirectoryPath) { + if (Position != 0) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (PrivateFile->Dir == NULL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + PrivateFile->UnixThunk->RewindDir (PrivateFile->Dir); + Status = EFI_SUCCESS; + goto Done; + } else { + if (Position == (UINT64) -1) { + Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_END); + } else { + Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, Position, SEEK_SET); + } + Status = (Pos == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS; + } + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemGetPosition ( + IN EFI_FILE *This, + OUT UINT64 *Position + ) +/*++ + +Routine Description: + + Get a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - Pointer to storage for the current position. + +Returns: + + EFI_SUCCESS - The file position has been reported. + + EFI_UNSUPPORTED - Not valid for directories. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_TPL OldTpl; + + if (This == NULL || Position == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->IsDirectoryPath) { + Status = EFI_UNSUPPORTED; + } else { + *Position = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_CUR); + Status = (*Position == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS; + } + + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemGetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Return information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID describing the type of information to be returned. + + BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the + information buffer. + + Buffer - Pointer to the first byte of the information buffer. + +Returns: + + EFI_SUCCESS - The requested information has been written into the buffer. + + EFI_UNSUPPORTED - The InformationType is not known. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has + been updated with the size needed to complete the requested operation. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer; + INTN UnixStatus; + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + struct statfs buf; + EFI_TPL OldTpl; + + if (This == NULL || InformationType == NULL || BufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + + Status = EFI_UNSUPPORTED; + + if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { + Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, BufferSize, Buffer); + } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { + if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) { + *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } + + UnixStatus = PrivateFile->UnixThunk->StatFs (PrivateFile->FileName, &buf); + if (UnixStatus < 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer; + FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + FileSystemInfoBuffer->ReadOnly = FALSE; + + // + // Succeeded + // + FileSystemInfoBuffer->VolumeSize = MultU64x32 (buf.f_blocks, buf.f_bsize); + FileSystemInfoBuffer->FreeSpace = MultU64x32 (buf.f_bavail, buf.f_bsize); + FileSystemInfoBuffer->BlockSize = buf.f_bsize; + + + StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel); + *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + Status = EFI_SUCCESS; + } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) { + *BufferSize = StrSize (PrivateRoot->VolumeLabel); + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } + + StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel); + *BufferSize = StrSize (PrivateRoot->VolumeLabel); + Status = EFI_SUCCESS; + } + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemSetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Set information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID identifying the type of information to set. + + BufferSize - Number of bytes of data in the information buffer. + + Buffer - Pointer to the first byte of data in the information buffer. + +Returns: + + EFI_SUCCESS - The file or volume information has been updated. + + EFI_UNSUPPORTED - The information identifier is not recognised. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + + EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_FILE_INFO *OldFileInfo; + EFI_FILE_INFO *NewFileInfo; + EFI_STATUS Status; + UINTN OldInfoSize; + EFI_TPL OldTpl; + mode_t NewAttr; + struct stat OldAttr; + CHAR8 *OldFileName; + CHAR8 *NewFileName; + CHAR8 *CharPointer; + BOOLEAN AttrChangeFlag; + BOOLEAN NameChangeFlag; + BOOLEAN SizeChangeFlag; + BOOLEAN TimeChangeFlag; + struct tm NewLastAccessSystemTime; + struct tm NewLastWriteSystemTime; + EFI_FILE_SYSTEM_INFO *NewFileSystemInfo; + CHAR8 *AsciiFilePtr; + CHAR16 *UnicodeFilePtr; + INTN UnixStatus; + + // + // Check for invalid parameters. + // + if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + // + // Initialise locals. + // + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + + Status = EFI_UNSUPPORTED; + OldFileInfo = NewFileInfo = NULL; + OldFileName = NewFileName = NULL; + AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE; + + // + // Set file system information. + // + if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { + if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer; + + gBS->FreePool (PrivateRoot->VolumeLabel); + + PrivateRoot->VolumeLabel = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (NewFileSystemInfo->VolumeLabel), + (VOID **)&PrivateRoot->VolumeLabel + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel); + + Status = EFI_SUCCESS; + goto Done; + } + + // + // Set volume label information. + // + if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer); + + Status = EFI_SUCCESS; + goto Done; + } + + if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (BufferSize < SIZE_OF_EFI_FILE_INFO) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + // + // Set file/directory information. + // + + // + // Check for invalid set file information parameters. + // + NewFileInfo = (EFI_FILE_INFO *) Buffer; + + if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) || + (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) || + (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF) + ) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // bugbug: - This is not safe. We need something like EfiStrMaxSize() + // that would have an additional parameter that would be the size + // of the string array just in case there are no NULL characters in + // the string array. + // + // + // Get current file information so we can determine what kind + // of change request this is. + // + OldInfoSize = 0; + Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL); + + if (Status != EFI_BUFFER_TOO_SMALL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize, + (VOID **)&OldFileInfo); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + AsciiStrSize (PrivateFile->FileName), + (VOID **)&OldFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + AsciiStrCpy (OldFileName, PrivateFile->FileName); + + // + // Make full pathname from new filename and rootpath. + // + if (NewFileInfo->FileName[0] == '\\') { + Status = gBS->AllocatePool ( + EfiBootServicesData, + AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1, + (VOID **)&NewFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + AsciiStrCpy (NewFileName, PrivateRoot->FilePath); + AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName); + UnicodeFilePtr = NewFileInfo->FileName + 1; + *AsciiFilePtr++ ='/'; + } else { + Status = gBS->AllocatePool ( + EfiBootServicesData, + AsciiStrLen (PrivateFile->FileName) + 1 + StrLen (NewFileInfo->FileName) + 1, + (VOID **)&NewFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + AsciiStrCpy (NewFileName, PrivateRoot->FilePath); + AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName); + while (AsciiFilePtr > NewFileName && AsciiFilePtr[-1] != '/') { + AsciiFilePtr--; + } + UnicodeFilePtr = NewFileInfo->FileName; + } + // Convert to ascii. + while (*UnicodeFilePtr) { + *AsciiFilePtr++ = *UnicodeFilePtr++; + } + *AsciiFilePtr = 0; + + + // + // Is there an attribute change request? + // + if (NewFileInfo->Attribute != OldFileInfo->Attribute) { + if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + AttrChangeFlag = TRUE; + } + + // + // Is there a name change request? + // bugbug: - Need EfiStrCaseCmp() + // + if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) { + NameChangeFlag = TRUE; + } + + // + // Is there a size change request? + // + if (NewFileInfo->FileSize != OldFileInfo->FileSize) { + SizeChangeFlag = TRUE; + } + + // + // Is there a time stamp change request? + // + if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } + + // + // All done if there are no change requests being made. + // + if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) { + Status = EFI_SUCCESS; + goto Done; + } + + // + // Set file or directory information. + // + if (PrivateFile->UnixThunk->Stat (OldFileName, &OldAttr) != 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // Name change. + // + if (NameChangeFlag) { + // + // Close the handles first + // + if (PrivateFile->IsOpenedByRead) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) { + } + + if (*CharPointer != 0) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + UnixStatus = PrivateFile->UnixThunk->Rename (OldFileName, NewFileName); + + if (UnixStatus == 0) { + // + // modify file name + // + gBS->FreePool (PrivateFile->FileName); + + Status = gBS->AllocatePool ( + EfiBootServicesData, + AsciiStrSize (NewFileName), + (VOID **)&PrivateFile->FileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + AsciiStrCpy (PrivateFile->FileName, NewFileName); + } else { + Status = EFI_DEVICE_ERROR; + goto Done; + } + } + + // + // Size change + // + if (SizeChangeFlag) { + if (PrivateFile->IsDirectoryPath) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + if (PrivateFile->UnixThunk->FTruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + } + + // + // Time change + // + if (TimeChangeFlag) { + struct utimbuf utime; + + NewLastAccessSystemTime.tm_year = NewFileInfo->LastAccessTime.Year; + NewLastAccessSystemTime.tm_mon = NewFileInfo->LastAccessTime.Month; + NewLastAccessSystemTime.tm_mday = NewFileInfo->LastAccessTime.Day; + NewLastAccessSystemTime.tm_hour = NewFileInfo->LastAccessTime.Hour; + NewLastAccessSystemTime.tm_min = NewFileInfo->LastAccessTime.Minute; + NewLastAccessSystemTime.tm_sec = NewFileInfo->LastAccessTime.Second; + NewLastAccessSystemTime.tm_isdst = 0; + + utime.actime = PrivateFile->UnixThunk->MkTime (&NewLastAccessSystemTime); + + NewLastWriteSystemTime.tm_year = NewFileInfo->ModificationTime.Year; + NewLastWriteSystemTime.tm_mon = NewFileInfo->ModificationTime.Month; + NewLastWriteSystemTime.tm_mday = NewFileInfo->ModificationTime.Day; + NewLastWriteSystemTime.tm_hour = NewFileInfo->ModificationTime.Hour; + NewLastWriteSystemTime.tm_min = NewFileInfo->ModificationTime.Minute; + NewLastWriteSystemTime.tm_sec = NewFileInfo->ModificationTime.Second; + NewLastWriteSystemTime.tm_isdst = 0; + + utime.modtime = PrivateFile->UnixThunk->MkTime (&NewLastWriteSystemTime); + + if (utime.actime == (time_t)-1 || utime.modtime == (time_t)-1) { + goto Done; + } + + if (PrivateFile->UnixThunk->UTime (PrivateFile->FileName, &utime) == -1) { + goto Done; + } + } + + // + // No matter about AttrChangeFlag, Attribute must be set. + // Because operation before may cause attribute change. + // + NewAttr = OldAttr.st_mode; + + if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) { + NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH); + } else { + NewAttr |= S_IRUSR; + } + + UnixStatus = PrivateFile->UnixThunk->Chmod (NewFileName, NewAttr); + + if (UnixStatus != 0) { + Status = EFI_DEVICE_ERROR; + } + +Done: + if (OldFileInfo != NULL) { + gBS->FreePool (OldFileInfo); + } + + if (OldFileName != NULL) { + gBS->FreePool (OldFileName); + } + + if (NewFileName != NULL) { + gBS->FreePool (NewFileName); + } + + gBS->RestoreTPL (OldTpl); + + return Status; +} + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemFlush ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Flush all modified data to the media. + +Arguments: + + This - Pointer to an opened file handle. + +Returns: + + EFI_SUCCESS - The data has been flushed. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures have been corrupted. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + UNIX_EFI_FILE_PRIVATE *PrivateFile; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + + if (PrivateFile->IsDirectoryPath) { + goto Done; + } + + if (PrivateFile->IsOpenedByRead) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + if (PrivateFile->fd < 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + PrivateFile->UnixThunk->FSync (PrivateFile->fd) == 0 ? EFI_SUCCESS : EFI_DEVICE_ERROR; + +Done: + gBS->RestoreTPL (OldTpl); + + return Status; + + // + // bugbug: - Use Unix error reporting. + // +} + + diff --git a/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.h b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.h new file mode 100644 index 0000000000..51dce83a91 --- /dev/null +++ b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.h @@ -0,0 +1,599 @@ +/*++ + +Copyright (c) 2006 - 2008, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + UnixSimpleFileSystem.h + +Abstract: + + Produce Simple File System abstractions for a directory on your PC using Unix APIs. + The configuration of what devices to mount or emulate comes from + environment variables. + +--*/ + +#ifndef _UNIX_SIMPLE_FILE_SYSTEM_H_ +#define _UNIX_SIMPLE_FILE_SYSTEM_H_ + +#include "PiDxe.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "UnixDxe.h" + +extern EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUnixSimpleFileSystemComponentName; + + +#define UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('L', 'X', 'f', 's') + +typedef struct { + UINTN Signature; + EFI_UNIX_THUNK_PROTOCOL *UnixThunk; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFileSystem; + CHAR8 *FilePath; + CHAR16 *VolumeLabel; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} UNIX_SIMPLE_FILE_SYSTEM_PRIVATE; + +#define UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE, \ + SimpleFileSystem, \ + UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \ + ) + +#define UNIX_EFI_FILE_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('l', 'o', 'f', 's') + +typedef struct { + UINTN Signature; + EFI_UNIX_THUNK_PROTOCOL *UnixThunk; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + EFI_FILE EfiFile; + INTN fd; + DIR *Dir; + BOOLEAN IsRootDirectory; + BOOLEAN IsDirectoryPath; + BOOLEAN IsOpenedByRead; + char *FileName; + struct dirent *Dirent; +} UNIX_EFI_FILE_PRIVATE; + +#define UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + UNIX_EFI_FILE_PRIVATE, \ + EfiFile, \ + UNIX_EFI_FILE_PRIVATE_SIGNATURE \ + ) + +// +// Global Protocol Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUnixSimpleFileSystemComponentName; + +// +// Driver Binding protocol member functions +// +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + +Routine Description: + + Check to see if the driver supports a given controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to test. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver + specified by This. + + EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + the driver specified by This. + + EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + a different driver or an application that requires exclusive access. + + EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the + driver specified by This. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + +Routine Description: + + Starts a device controller or a bus controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to start. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device or bus controller has been started. + + EFI_DEVICE_ERROR - The device could not be started due to a device failure. + + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - A handle to the device to be stopped. + + NumberOfChildren - The number of child device handles in ChildHandleBuffer. + + ChildHandleBuffer - An array of child device handles to be freed. + +Returns: + + EFI_SUCCESS - The device has been stopped. + + EFI_DEVICE_ERROR - The device could not be stopped due to a device failure. + +--*/ +; + +// +// Simple File System protocol member functions +// +EFI_STATUS +EFIAPI +UnixSimpleFileSystemOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE **Root + ) +/*++ + +Routine Description: + + Open the root directory on a volume. + +Arguments: + + This - A pointer to the volume to open. + + Root - A pointer to storage for the returned opened file handle of the root directory. + +Returns: + + EFI_SUCCESS - The volume was opened. + + EFI_UNSUPPORTED - The volume does not support the requested file system type. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemOpen ( + IN EFI_FILE *This, + OUT EFI_FILE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Open a file relative to the source file location. + +Arguments: + + This - A pointer to the source file location. + + NewHandle - Pointer to storage for the new file handle. + + FileName - Pointer to the file name to be opened. + + OpenMode - File open mode information. + + Attributes - File creation attributes. + +Returns: + + EFI_SUCCESS - The file was opened. + + EFI_NOT_FOUND - The file could not be found in the volume. + + EFI_NO_MEDIA - The device has no media. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_WRITE_PROTECTED - The volume or file is write protected. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file. + + EFI_VOLUME_FULL - There is not enough space left to create the new file. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemClose ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close the specified file handle. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle has been closed. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemDelete ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close and delete a file. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle was closed and deleted. + + EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemRead ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read data from a file. + +Arguments: + + This - Pointer to a returned open file handle. + + BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer. + + Buffer - Pointer to the first byte of the read Buffer. + +Returns: + + EFI_SUCCESS - The data was read. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry. + *BufferSize has been updated with the size needed to complete the request. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemWrite ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Write data to a file. + +Arguments: + + This - Pointer to an opened file handle. + + BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes + of data written to the file. + + Buffer - Pointer to the first by of data in the buffer to write to the file. + +Returns: + + EFI_SUCCESS - The data was written to the file. + + EFI_UNSUPPORTED - Writes to an open directory are not supported. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemSetPosition ( + IN EFI_FILE *This, + IN UINT64 Position + ) +/*++ + +Routine Description: + + Set a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - The byte position from the start of the file to set. + +Returns: + + EFI_SUCCESS - The file position has been changed. + + EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemGetPosition ( + IN EFI_FILE *This, + OUT UINT64 *Position + ) +/*++ + +Routine Description: + + Get a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - Pointer to storage for the current position. + +Returns: + + EFI_SUCCESS - The file position has been reported. + + EFI_UNSUPPORTED - Not valid for directories. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemGetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Return information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID describing the type of information to be returned. + + BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the + information buffer. + + Buffer - Pointer to the first byte of the information buffer. + +Returns: + + EFI_SUCCESS - The requested information has been written into the buffer. + + EFI_UNSUPPORTED - The InformationType is not known. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has + been updated with the size needed to complete the requested operation. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemSetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Set information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID identifying the type of information to set. + + BufferSize - Number of bytes of data in the information buffer. + + Buffer - Pointer to the first byte of data in the information buffer. + +Returns: + + EFI_SUCCESS - The file or volume information has been updated. + + EFI_UNSUPPORTED - The information identifier is not recognised. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + + EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType. + +--*/ +; + +EFI_STATUS +EFIAPI +UnixSimpleFileSystemFlush ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Flush all modified data to the media. + +Arguments: + + This - Pointer to an opened file handle. + +Returns: + + EFI_SUCCESS - The data has been flushed. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures have been corrupted. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +; + +#endif /* _UNIX_SIMPLE_FILE_SYSTEM_H_ */ + +/* eof - UnixSimpleFileSystem.h */ diff --git a/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.inf b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.inf new file mode 100644 index 0000000000..f3cce016df --- /dev/null +++ b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.inf @@ -0,0 +1,71 @@ +#/** @file +# Simple filesystem driver +# +# Produce Simple File System abstractions for directories on your PC using Unix APIs. +# The configuration of what devices to mount or emulate comes from +# environment variables. +# Copyright (c) 2006, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UnixSimpleFileSystem + FILE_GUID = f330834e-8985-11db-a295-0040d02b1835 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeUnixSimpleFileSystem + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gUnixSimpleFileSystemDriverBinding +# COMPONENT_NAME = gUnixSimpleFileSystemComponentName +# + +[Sources.common] + ComponentName.c + UnixSimpleFileSystem.c + UnixSimpleFileSystem.h + EntryPoint.c + + +[Packages] + MdePkg/MdePkg.dec + UnixPkg/UnixPkg.dec + + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + BaseLib + DebugLib + + +[Guids] + gEfiFileSystemVolumeLabelInfoIdGuid # SOMETIMES_CONSUMED + gEfiFileInfoGuid # SOMETIMES_CONSUMED + gEfiFileSystemInfoGuid # SOMETIMES_CONSUMED + gEfiUnixFileSystemGuid # ALWAYS_CONSUMED + + +[Protocols] + gEfiSimpleFileSystemProtocolGuid # PROTOCOL BY_START + gEfiUnixIoProtocolGuid # PROTOCOL TO_START + diff --git a/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.msa b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.msa new file mode 100644 index 0000000000..c57aa7165e --- /dev/null +++ b/UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.msa @@ -0,0 +1,94 @@ + + + + UnixSimpleFileSystem + UEFI_DRIVER + f330834e-8985-11db-a295-0040d02b1835 + 1.0 + Simple filesystem driver + + Produce Simple File System abstractions for directories on your PC using Unix APIs. + The configuration of what devices to mount or emulate comes from + environment variables. + + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + UnixSimpleFileSystem + + + + DebugLib + + + BaseLib + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + UefiLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + + UnixSimpleFileSystem.h + UnixSimpleFileSystem.c + ComponentName.c + + + + + + + + + gEfiUnixIoProtocolGuid + + + gEfiSimpleFileSystemProtocolGuid + + + + + gEfiUnixFileSystemGuid + + + gEfiFileSystemInfoGuid + + + gEfiFileInfoGuid + + + gEfiFileSystemVolumeLabelInfoIdGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + gUnixSimpleFileSystemDriverBinding + gUnixSimpleFileSystemComponentName + + + -- cgit v1.2.3