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
		
			
				
	
	
		
			2187 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2187 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
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.
 | 
						|
  //
 | 
						|
}
 | 
						|
 | 
						|
 |