mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 10:40:34 +00:00 
			
		
		
		
	 7492c63d42
			
		
	
	
		7492c63d42
		
	
	
	
	
		
			
			git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@6301 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1290 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1290 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2004 - 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:
 | |
| 
 | |
|   UnixBlockIo.c
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
|   Produce block IO abstractions for real devices 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.
 | |
| 
 | |
|   <F>ixed       - Fixed disk like a hard drive.
 | |
|   <R>emovable   - Removable media like a floppy or CD-ROM.
 | |
|   Read <O>nly   - Write protected device.
 | |
|   Read <W>rite  - Read write device.
 | |
|   <block count> - Decimal number of blocks a device supports.
 | |
|   <block size>  - Decimal number of bytes per block.
 | |
| 
 | |
|   UNIX envirnonment variable contents. '<' and '>' are not part of the variable, 
 | |
|   they are just used to make this help more readable. There should be no 
 | |
|   spaces between the ';'. Extra spaces will break the variable. A '!' is 
 | |
|   used to seperate multiple devices in a variable.
 | |
| 
 | |
|   EFI_UNIX_VIRTUAL_DISKS = 
 | |
|     <F | R><O | W>;<block count>;<block size>[!...]
 | |
| 
 | |
|   EFI_UNIX_PHYSICAL_DISKS =
 | |
|     <drive letter>:<F | R><O | W>;<block count>;<block size>[!...]
 | |
| 
 | |
|   Virtual Disks: These devices use a file to emulate a hard disk or removable
 | |
|                  media device. 
 | |
|                  
 | |
|     Thus a 20 MB emulated hard drive would look like:
 | |
|     EFI_UNIX_VIRTUAL_DISKS=FW;40960;512
 | |
| 
 | |
|     A 1.44MB emulated floppy with a block size of 1024 would look like:
 | |
|     EFI_UNIX_VIRTUAL_DISKS=RW;1440;1024
 | |
| 
 | |
|   Physical Disks: These devices use UNIX to open a real device in your system
 | |
| 
 | |
|     Thus a 120 MB floppy would look like:
 | |
|     EFI_UNIX_PHYSICAL_DISKS=B:RW;245760;512
 | |
| 
 | |
|     Thus a standard CD-ROM floppy would look like:
 | |
|     EFI_UNIX_PHYSICAL_DISKS=Z:RO;307200;2048
 | |
| 
 | |
| 
 | |
|   * Other names and brands may be claimed as the property of others.
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include <fcntl.h>
 | |
| #include <unistd.h>
 | |
| #include "UnixBlockIo.h"
 | |
| 
 | |
| //
 | |
| // Block IO protocol member functions
 | |
| //
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoReadBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This,
 | |
|   IN UINT32                 MediaId,
 | |
|   IN EFI_LBA                Lba,
 | |
|   IN UINTN                  BufferSize,
 | |
|   OUT VOID                  *Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This        - TODO: add argument description
 | |
|   MediaId     - TODO: add argument description
 | |
|   Lba         - TODO: add argument description
 | |
|   BufferSize  - TODO: add argument description
 | |
|   Buffer      - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoWriteBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This,
 | |
|   IN UINT32                 MediaId,
 | |
|   IN EFI_LBA                Lba,
 | |
|   IN UINTN                  BufferSize,
 | |
|   IN VOID                   *Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This        - TODO: add argument description
 | |
|   MediaId     - TODO: add argument description
 | |
|   Lba         - TODO: add argument description
 | |
|   BufferSize  - TODO: add argument description
 | |
|   Buffer      - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoFlushBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoResetBlock (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This,
 | |
|   IN BOOLEAN                ExtendedVerification
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This                  - TODO: add argument description
 | |
|   ExtendedVerification  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| //
 | |
| // Private Worker functions
 | |
| //
 | |
| EFI_STATUS
 | |
| UnixBlockIoCreateMapping (
 | |
|   IN EFI_UNIX_IO_PROTOCOL             *UnixIo,
 | |
|   IN EFI_HANDLE                         EfiDeviceHandle,
 | |
|   IN CHAR16                             *Filename,
 | |
|   IN BOOLEAN                            ReadOnly,
 | |
|   IN BOOLEAN                            RemovableMedia,
 | |
|   IN UINTN                              NumberOfBlocks,
 | |
|   IN UINTN                              BlockSize
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   UnixIo         - TODO: add argument description
 | |
|   EfiDeviceHandle - TODO: add argument description
 | |
|   Filename        - TODO: add argument description
 | |
|   ReadOnly        - TODO: add argument description
 | |
|   RemovableMedia  - TODO: add argument description
 | |
|   NumberOfBlocks  - TODO: add argument description
 | |
|   BlockSize       - TODO: add argument description
 | |
|   DeviceType      - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| EFI_STATUS
 | |
| UnixBlockIoReadWriteCommon (
 | |
|   IN  UNIX_BLOCK_IO_PRIVATE *Private,
 | |
|   IN UINT32                   MediaId,
 | |
|   IN EFI_LBA                  Lba,
 | |
|   IN UINTN                    BufferSize,
 | |
|   IN VOID                     *Buffer,
 | |
|   IN CHAR8                    *CallerName
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Private     - TODO: add argument description
 | |
|   MediaId     - TODO: add argument description
 | |
|   Lba         - TODO: add argument description
 | |
|   BufferSize  - TODO: add argument description
 | |
|   Buffer      - TODO: add argument description
 | |
|   CallerName  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| EFI_STATUS
 | |
| UnixBlockIoError (
 | |
|   IN UNIX_BLOCK_IO_PRIVATE      *Private
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Private - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| EFI_STATUS
 | |
| UnixBlockIoOpenDevice (
 | |
|   UNIX_BLOCK_IO_PRIVATE         *Private
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Private - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| 
 | |
| CHAR16                                    *
 | |
| GetNextElementPastTerminator (
 | |
|   IN  CHAR16  *EnvironmentVariable,
 | |
|   IN  CHAR16  Terminator
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   EnvironmentVariable - TODO: add argument description
 | |
|   Terminator          - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| ;
 | |
| EFI_DRIVER_BINDING_PROTOCOL gUnixBlockIoDriverBinding = {
 | |
|   UnixBlockIoDriverBindingSupported,
 | |
|   UnixBlockIoDriverBindingStart,
 | |
|   UnixBlockIoDriverBindingStop,
 | |
|   0xa,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoDriverBindingSupported (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN  EFI_HANDLE                   Handle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| // TODO:    This - add argument and description to function comment
 | |
| // TODO:    Handle - add argument and description to function comment
 | |
| // TODO:    RemainingDevicePath - add argument and description to function comment
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_UNIX_IO_PROTOCOL  *UnixIo;
 | |
| 
 | |
|   //
 | |
|   // Open the IO Abstraction(s) needed to perform the supported test
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Handle,
 | |
|                   &gEfiUnixIoProtocolGuid,
 | |
|                   (VOID **)&UnixIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Handle,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Make sure the UnixThunkProtocol is valid
 | |
|   //
 | |
|   Status = EFI_UNSUPPORTED;
 | |
|   if (UnixIo->UnixThunk->Signature == EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) {
 | |
| 
 | |
|     //
 | |
|     // Check the GUID to see if this is a handle type the driver supports
 | |
|     //
 | |
|     if (CompareGuid (UnixIo->TypeGuid, &gEfiUnixVirtualDisksGuid) ) {
 | |
|       Status = EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Close the I/O Abstraction(s) used to perform the supported test
 | |
|   //
 | |
|   gBS->CloseProtocol (
 | |
|         Handle,
 | |
|         &gEfiUnixIoProtocolGuid,
 | |
|         This->DriverBindingHandle,
 | |
|         Handle
 | |
|         );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoDriverBindingStart (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
 | |
|   IN  EFI_HANDLE                    Handle,
 | |
|   IN  EFI_DEVICE_PATH_PROTOCOL      *RemainingDevicePath
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| // TODO:    This - add argument and description to function comment
 | |
| // TODO:    Handle - add argument and description to function comment
 | |
| // TODO:    RemainingDevicePath - add argument and description to function comment
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_UNIX_IO_PROTOCOL       *UnixIo;
 | |
|   CHAR16                      Buffer[FILENAME_BUFFER_SIZE];
 | |
|   CHAR16                      *Str;
 | |
|   BOOLEAN                     RemovableMedia;
 | |
|   BOOLEAN                     WriteProtected;
 | |
|   UINTN                       NumberOfBlocks;
 | |
|   UINTN                       BlockSize;
 | |
|   INTN	                      i;
 | |
| 
 | |
|   //
 | |
|   // Grab the protocols we need
 | |
|   //
 | |
|   
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Handle,
 | |
|                   &gEfiUnixIoProtocolGuid,
 | |
|                   (void *)&UnixIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Handle,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Set DiskType
 | |
|   //
 | |
|   if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixVirtualDisksGuid)) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status  = EFI_NOT_FOUND;
 | |
|   //  Extract filename.
 | |
|   Str     = UnixIo->EnvString;
 | |
|   i = 0;
 | |
|   while (*Str && *Str != ':')
 | |
|     Buffer[i++] = *Str++;
 | |
|   Buffer[i] = 0;
 | |
|   if (*Str != ':') {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Str++;
 | |
| 
 | |
|   RemovableMedia = FALSE;
 | |
|   WriteProtected = TRUE;
 | |
|   NumberOfBlocks = 0;
 | |
|   BlockSize = 512;
 | |
|   do {
 | |
|     if (*Str == 'R' || *Str == 'F') {
 | |
|       RemovableMedia = (BOOLEAN) (*Str == 'R');
 | |
|       Str++;
 | |
|     }
 | |
|     if (*Str == 'O' || *Str == 'W') {
 | |
|       WriteProtected  = (BOOLEAN) (*Str == 'O');
 | |
|       Str++;
 | |
|     }
 | |
|     if (*Str == 0)
 | |
|       break;
 | |
|     if (*Str != ';')
 | |
|       goto Done;
 | |
|     Str++;
 | |
| 
 | |
|     NumberOfBlocks  = Atoi (Str);
 | |
|     Str       = GetNextElementPastTerminator (Str, ';');
 | |
|     if (NumberOfBlocks == 0)
 | |
|       break;
 | |
| 
 | |
|     BlockSize = Atoi (Str);
 | |
|     if (BlockSize != 0)
 | |
|       Str       = GetNextElementPastTerminator (Str, ';');
 | |
|   } while (0);
 | |
| 
 | |
|   //
 | |
|   // If we get here the variable is valid so do the work.
 | |
|   //
 | |
|   Status = UnixBlockIoCreateMapping (
 | |
|               UnixIo,
 | |
|               Handle,
 | |
|               Buffer,
 | |
|               WriteProtected,
 | |
|               RemovableMedia,
 | |
|               NumberOfBlocks,
 | |
|               BlockSize
 | |
|               );
 | |
| 
 | |
| Done:
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->CloseProtocol (
 | |
|           Handle,
 | |
|           &gEfiUnixIoProtocolGuid,
 | |
|           This->DriverBindingHandle,
 | |
|           Handle
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoDriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
 | |
|   IN  EFI_HANDLE                   Handle,
 | |
|   IN  UINTN                        NumberOfChildren,
 | |
|   IN  EFI_HANDLE                   *ChildHandleBuffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This              - TODO: add argument description
 | |
|   Handle            - TODO: add argument description
 | |
|   NumberOfChildren  - TODO: add argument description
 | |
|   ChildHandleBuffer - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_UNSUPPORTED - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_BLOCK_IO_PROTOCOL   *BlockIo;
 | |
|   EFI_STATUS              Status;
 | |
|   UNIX_BLOCK_IO_PRIVATE *Private;
 | |
| 
 | |
|   //
 | |
|   // Get our context back
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Handle,
 | |
|                   &gEfiBlockIoProtocolGuid,
 | |
|                   (void *)&BlockIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Handle,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo);
 | |
| 
 | |
|   //
 | |
|   // BugBug: If we need to kick people off, we need to make Uninstall Close the handles.
 | |
|   //         We could pass in our image handle or FLAG our open to be closed via
 | |
|   //         Unistall (== to saying any CloseProtocol will close our open)
 | |
|   //
 | |
|   Status = gBS->UninstallMultipleProtocolInterfaces (
 | |
|                   Private->EfiHandle,
 | |
|                   &gEfiBlockIoProtocolGuid,
 | |
|                   &Private->BlockIo,
 | |
|                   NULL
 | |
|                   );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
| 
 | |
|     Status = gBS->CloseProtocol (
 | |
|                     Handle,
 | |
|                     &gEfiUnixIoProtocolGuid,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Handle
 | |
|                     );
 | |
| 
 | |
|     //
 | |
|     // Shut down our device
 | |
|     //
 | |
|     Private->UnixThunk->Close (Private->fd);
 | |
| 
 | |
|     //
 | |
|     // Free our instance data
 | |
|     //
 | |
|     FreeUnicodeStringTable (Private->ControllerNameTable);
 | |
| 
 | |
|     gBS->FreePool (Private);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| CHAR16 *
 | |
| GetNextElementPastTerminator (
 | |
|   IN  CHAR16  *EnvironmentVariable,
 | |
|   IN  CHAR16  Terminator
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Worker function to parse environment variables.
 | |
| 
 | |
| Arguments:
 | |
|   EnvironmentVariable - Envirnment variable to parse.
 | |
| 
 | |
|   Terminator          - Terminator to parse for.
 | |
| 
 | |
| Returns: 
 | |
| 
 | |
|   Pointer to next eliment past the first occurence of Terminator or the '\0'
 | |
|   at the end of the string.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   CHAR16  *Ptr;
 | |
| 
 | |
|   for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) {
 | |
|     if (*Ptr == Terminator) {
 | |
|       Ptr++;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Ptr;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UnixBlockIoCreateMapping (
 | |
|   IN EFI_UNIX_IO_PROTOCOL             *UnixIo,
 | |
|   IN EFI_HANDLE                         EfiDeviceHandle,
 | |
|   IN CHAR16                             *Filename,
 | |
|   IN BOOLEAN                            ReadOnly,
 | |
|   IN BOOLEAN                            RemovableMedia,
 | |
|   IN UINTN                              NumberOfBlocks,
 | |
|   IN UINTN                              BlockSize
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   UnixIo         - TODO: add argument description
 | |
|   EfiDeviceHandle - TODO: add argument description
 | |
|   Filename        - TODO: add argument description
 | |
|   ReadOnly        - TODO: add argument description
 | |
|   RemovableMedia  - TODO: add argument description
 | |
|   NumberOfBlocks  - TODO: add argument description
 | |
|   BlockSize       - TODO: add argument description
 | |
|   DeviceType      - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_BLOCK_IO_PROTOCOL   *BlockIo;
 | |
|   UNIX_BLOCK_IO_PRIVATE *Private;
 | |
|   UINTN                   Index;
 | |
| 
 | |
|   Status = gBS->AllocatePool (
 | |
|                   EfiBootServicesData,
 | |
|                   sizeof (UNIX_BLOCK_IO_PRIVATE),
 | |
|                   (void *)&Private
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   EfiInitializeLock (&Private->Lock, TPL_NOTIFY);
 | |
| 
 | |
|   Private->UnixThunk = UnixIo->UnixThunk;
 | |
| 
 | |
|   Private->Signature  = UNIX_BLOCK_IO_PRIVATE_SIGNATURE;
 | |
|   Private->LastBlock  = NumberOfBlocks - 1;
 | |
|   Private->BlockSize  = BlockSize;
 | |
| 
 | |
|   for (Index = 0; Filename[Index] != 0; Index++) {
 | |
|     Private->Filename[Index] = Filename[Index];
 | |
|   }
 | |
| 
 | |
|   Private->Filename[Index]      = 0;
 | |
| 
 | |
|   Private->Mode                 = (ReadOnly ? O_RDONLY : O_RDWR);
 | |
| 
 | |
|   Private->NumberOfBlocks       = NumberOfBlocks;
 | |
|   Private->fd                   = -1;
 | |
| 
 | |
|   Private->ControllerNameTable  = NULL;
 | |
| 
 | |
|   AddUnicodeString (
 | |
|     "eng",
 | |
|     gUnixBlockIoComponentName.SupportedLanguages,
 | |
|     &Private->ControllerNameTable,
 | |
|     Filename
 | |
|     );
 | |
| 
 | |
|   BlockIo = &Private->BlockIo;
 | |
|   BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
 | |
|   BlockIo->Media = &Private->Media;
 | |
|   BlockIo->Media->BlockSize = Private->BlockSize;
 | |
|   BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1;
 | |
|   BlockIo->Media->MediaId = 0;;
 | |
| 
 | |
|   BlockIo->Reset = UnixBlockIoResetBlock;
 | |
|   BlockIo->ReadBlocks = UnixBlockIoReadBlocks;
 | |
|   BlockIo->WriteBlocks = UnixBlockIoWriteBlocks;
 | |
|   BlockIo->FlushBlocks = UnixBlockIoFlushBlocks;
 | |
| 
 | |
|   BlockIo->Media->ReadOnly = ReadOnly;
 | |
|   BlockIo->Media->RemovableMedia = RemovableMedia;
 | |
|   BlockIo->Media->LogicalPartition = FALSE;
 | |
|   BlockIo->Media->MediaPresent = TRUE;
 | |
|   BlockIo->Media->WriteCaching = FALSE;
 | |
| 
 | |
|   BlockIo->Media->IoAlign = 1;
 | |
| 
 | |
|   Private->EfiHandle  = EfiDeviceHandle;
 | |
|   Status              = UnixBlockIoOpenDevice (Private);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
| 
 | |
|     Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                     &Private->EfiHandle,
 | |
|                     &gEfiBlockIoProtocolGuid,
 | |
|                     &Private->BlockIo,
 | |
|                     NULL
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreeUnicodeStringTable (Private->ControllerNameTable);
 | |
|       gBS->FreePool (Private);
 | |
|     }
 | |
| 
 | |
|     DEBUG ((EFI_D_ERROR, "BlockDevice added: %s\n", Filename));
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UnixBlockIoOpenDevice (
 | |
|   UNIX_BLOCK_IO_PRIVATE                 *Private
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Private - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS            Status;
 | |
|   UINT64                FileSize;
 | |
|   UINT64                EndOfFile;
 | |
|   EFI_BLOCK_IO_PROTOCOL *BlockIo;
 | |
| 
 | |
|   BlockIo = &Private->BlockIo;
 | |
|   EfiAcquireLock (&Private->Lock);
 | |
| 
 | |
|   //
 | |
|   // If the device is already opened, close it
 | |
|   //
 | |
|   if (Private->fd >= 0) {
 | |
|     BlockIo->Reset (BlockIo, FALSE);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Open the device
 | |
|   //
 | |
|   Private->fd = Private->UnixThunk->Open
 | |
|     (Private->Filename, Private->Mode, 0644);
 | |
| 
 | |
|   if (Private->fd < 0) {
 | |
|     DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %s\n",
 | |
| 	    Private->Filename));
 | |
|     BlockIo->Media->MediaPresent  = FALSE;
 | |
|     Status                        = EFI_NO_MEDIA;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (!BlockIo->Media->MediaPresent) {
 | |
|     //
 | |
|     // BugBug: try to emulate if a CD appears - notify drivers to check it out
 | |
|     //
 | |
|     BlockIo->Media->MediaPresent = TRUE;
 | |
|     EfiReleaseLock (&Private->Lock);
 | |
|     EfiAcquireLock (&Private->Lock);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // get the size of the file
 | |
|   //
 | |
|   Status = SetFilePointer64 (Private, 0, &FileSize, SEEK_END);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
 | |
|     DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %s\n", Private->Filename));
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (Private->NumberOfBlocks == 0) {
 | |
|     Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize);
 | |
|   }
 | |
| 
 | |
|   EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize);
 | |
| 
 | |
|   if (FileSize != EndOfFile) {
 | |
|     //
 | |
|     // file is not the proper size, change it
 | |
|     //
 | |
|     DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %a\n", Private->Filename));
 | |
| 
 | |
|     //
 | |
|     // first set it to 0
 | |
|     //
 | |
|     Private->UnixThunk->FTruncate (Private->fd, 0);
 | |
| 
 | |
|     //
 | |
|     // then set it to the needed file size (OS will zero fill it)
 | |
|     //
 | |
|     Private->UnixThunk->FTruncate (Private->fd, EndOfFile);
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %s%N\n", Private->Filename));
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
| Done:
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (Private->fd >= 0) {
 | |
|       BlockIo->Reset (BlockIo, FALSE);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   EfiReleaseLock (&Private->Lock);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UnixBlockIoError (
 | |
|   IN UNIX_BLOCK_IO_PRIVATE      *Private
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Private - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return EFI_DEVICE_ERROR;
 | |
| 
 | |
| #if 0
 | |
|   EFI_BLOCK_IO_PROTOCOL *BlockIo;
 | |
|   EFI_STATUS            Status;
 | |
|   BOOLEAN               ReinstallBlockIoFlag;
 | |
| 
 | |
| 
 | |
|   BlockIo = &Private->BlockIo;
 | |
| 
 | |
|   switch (Private->UnixThunk->GetLastError ()) {
 | |
| 
 | |
|   case ERROR_NOT_READY:
 | |
|     Status                        = EFI_NO_MEDIA;
 | |
|     BlockIo->Media->ReadOnly      = FALSE;
 | |
|     BlockIo->Media->MediaPresent  = FALSE;
 | |
|     ReinstallBlockIoFlag          = FALSE;
 | |
|     break;
 | |
| 
 | |
|   case ERROR_WRONG_DISK:
 | |
|     BlockIo->Media->ReadOnly      = FALSE;
 | |
|     BlockIo->Media->MediaPresent  = TRUE;
 | |
|     BlockIo->Media->MediaId += 1;
 | |
|     ReinstallBlockIoFlag  = TRUE;
 | |
|     Status                = EFI_MEDIA_CHANGED;
 | |
|     break;
 | |
| 
 | |
|   case ERROR_WRITE_PROTECT:
 | |
|     BlockIo->Media->ReadOnly  = TRUE;
 | |
|     ReinstallBlockIoFlag      = FALSE;
 | |
|     Status                    = EFI_WRITE_PROTECTED;
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     ReinstallBlockIoFlag  = FALSE;
 | |
|     Status                = EFI_DEVICE_ERROR;
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   if (ReinstallBlockIoFlag) {
 | |
|     BlockIo->Reset (BlockIo, FALSE);
 | |
| 
 | |
|     gBS->ReinstallProtocolInterface (
 | |
|           Private->EfiHandle,
 | |
|           &gEfiBlockIoProtocolGuid,
 | |
|           BlockIo,
 | |
|           BlockIo
 | |
|           );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UnixBlockIoReadWriteCommon (
 | |
|   IN  UNIX_BLOCK_IO_PRIVATE     *Private,
 | |
|   IN UINT32                       MediaId,
 | |
|   IN EFI_LBA                      Lba,
 | |
|   IN UINTN                        BufferSize,
 | |
|   IN VOID                         *Buffer,
 | |
|   IN CHAR8                        *CallerName
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Private     - TODO: add argument description
 | |
|   MediaId     - TODO: add argument description
 | |
|   Lba         - TODO: add argument description
 | |
|   BufferSize  - TODO: add argument description
 | |
|   Buffer      - TODO: add argument description
 | |
|   CallerName  - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_NO_MEDIA - TODO: Add description for return value
 | |
|   EFI_MEDIA_CHANGED - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
|   EFI_BAD_BUFFER_SIZE - TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - TODO: Add description for return value
 | |
|   EFI_SUCCESS - TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       BlockSize;
 | |
|   UINT64      LastBlock;
 | |
|   INT64       DistanceToMove;
 | |
|   UINT64      DistanceMoved;
 | |
| 
 | |
|   if (Private->fd < 0) {
 | |
|     Status = UnixBlockIoOpenDevice (Private);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!Private->Media.MediaPresent) {
 | |
|     DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName));
 | |
|     return EFI_NO_MEDIA;
 | |
|   }
 | |
| 
 | |
|   if (Private->Media.MediaId != MediaId) {
 | |
|     return EFI_MEDIA_CHANGED;
 | |
|   }
 | |
| 
 | |
|   if ((UINT32) Buffer % Private->Media.IoAlign != 0) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Verify buffer size
 | |
|   //
 | |
|   BlockSize = Private->BlockSize;
 | |
|   if (BufferSize == 0) {
 | |
|     DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName));
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if ((BufferSize % BlockSize) != 0) {
 | |
|     DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName));
 | |
|     return EFI_BAD_BUFFER_SIZE;
 | |
|   }
 | |
| 
 | |
|   LastBlock = Lba + (BufferSize / BlockSize) - 1;
 | |
|   if (LastBlock > Private->LastBlock) {
 | |
|     DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n"));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   // Seek to End of File
 | |
|   //
 | |
|   DistanceToMove = MultU64x32 (Lba, BlockSize);
 | |
|   Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, SEEK_SET);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n"));
 | |
|     return UnixBlockIoError (Private);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoReadBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This,
 | |
|   IN UINT32                 MediaId,
 | |
|   IN EFI_LBA                Lba,
 | |
|   IN UINTN                  BufferSize,
 | |
|   OUT VOID                  *Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Read BufferSize bytes from Lba into Buffer.
 | |
| 
 | |
|   Arguments:
 | |
|     This       - Protocol instance pointer.
 | |
|     MediaId    - Id of the media, changes every time the media is replaced.
 | |
|     Lba        - The starting Logical Block Address to read from
 | |
|     BufferSize - Size of Buffer, must be a multiple of device block size.
 | |
|     Buffer     - Buffer containing read data
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS           - The data was read correctly from the device.
 | |
|     EFI_DEVICE_ERROR      - The device reported an error while performing the read.
 | |
|     EFI_NO_MEDIA          - There is no media in the device.
 | |
|     EFI_MEDIA_CHANGED     - The MediaId does not matched the current device.
 | |
|     EFI_BAD_BUFFER_SIZE   - The Buffer was not a multiple of the block size of the 
 | |
|                             device.
 | |
|     EFI_INVALID_PARAMETER - The read request contains device addresses that are not 
 | |
|                             valid for the device.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UNIX_BLOCK_IO_PRIVATE *Private;
 | |
|   ssize_t                 len;
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_TPL                 OldTpl;
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   Status  = UnixBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "UnixReadBlocks");
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   len = Private->UnixThunk->Read (Private->fd, Buffer, BufferSize);
 | |
|   if (len != BufferSize) {
 | |
|     DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed.\n"));
 | |
|     Status = UnixBlockIoError (Private);
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If we wrote then media is present.
 | |
|   //
 | |
|   This->Media->MediaPresent = TRUE;
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
| Done:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoWriteBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This,
 | |
|   IN UINT32                 MediaId,
 | |
|   IN EFI_LBA                Lba,
 | |
|   IN UINTN                  BufferSize,
 | |
|   IN VOID                   *Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Write BufferSize bytes from Lba into Buffer.
 | |
| 
 | |
|   Arguments:
 | |
|     This       - Protocol instance pointer.
 | |
|     MediaId    - Id of the media, changes every time the media is replaced.
 | |
|     Lba        - The starting Logical Block Address to read from
 | |
|     BufferSize - Size of Buffer, must be a multiple of device block size.
 | |
|     Buffer     - Buffer containing read data
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS           - The data was written correctly to the device.
 | |
|     EFI_WRITE_PROTECTED   - The device can not be written to.
 | |
|     EFI_DEVICE_ERROR      - The device reported an error while performing the write.
 | |
|     EFI_NO_MEDIA          - There is no media in the device.
 | |
|     EFI_MEDIA_CHNAGED     - The MediaId does not matched the current device.
 | |
|     EFI_BAD_BUFFER_SIZE   - The Buffer was not a multiple of the block size of the 
 | |
|                             device.
 | |
|     EFI_INVALID_PARAMETER - The write request contains a LBA that is not 
 | |
|                             valid for the device.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UNIX_BLOCK_IO_PRIVATE *Private;
 | |
|   ssize_t                 len;
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_TPL                 OldTpl;
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   Status  = UnixBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "UnixWriteBlocks");
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   len = Private->UnixThunk->Write (Private->fd, Buffer, BufferSize);
 | |
|   if (len != BufferSize) {
 | |
|     DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed.\n"));
 | |
|     Status = UnixBlockIoError (Private);
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If the write succeeded, we are not write protected and media is present.
 | |
|   //
 | |
|   This->Media->MediaPresent = TRUE;
 | |
|   This->Media->ReadOnly     = FALSE;
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
| Done:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoFlushBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Flush the Block Device.
 | |
| 
 | |
|   Arguments:
 | |
|     This             - Protocol instance pointer.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS      - All outstanding data was written to the device
 | |
|     EFI_DEVICE_ERROR - The device reported an error while writting back the data
 | |
|     EFI_NO_MEDIA     - There is no media in the device.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UnixBlockIoResetBlock (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This,
 | |
|   IN BOOLEAN                ExtendedVerification
 | |
|   )
 | |
| /*++
 | |
| 
 | |
|   Routine Description:
 | |
|     Reset the Block Device.
 | |
| 
 | |
|   Arguments:
 | |
|     This                 - Protocol instance pointer.
 | |
|     ExtendedVerification - Driver may perform diagnostics on reset.
 | |
| 
 | |
|   Returns:
 | |
|     EFI_SUCCESS           - The device was reset.
 | |
|     EFI_DEVICE_ERROR      - The device is not functioning properly and could 
 | |
|                             not be reset.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UNIX_BLOCK_IO_PRIVATE *Private;
 | |
|   EFI_TPL               OldTpl;
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
|   
 | |
|   Private = UNIX_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (Private->fd >= 0) {
 | |
|     Private->UnixThunk->Close (Private->fd);
 | |
|     Private->fd = -1;
 | |
|   }
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| UINTN
 | |
| Atoi (
 | |
|   CHAR16  *String
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Convert a unicode string to a UINTN
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   String - Unicode string.
 | |
| 
 | |
| Returns: 
 | |
| 
 | |
|   UINTN of the number represented by String.  
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN   Number;
 | |
|   CHAR16  *Str;
 | |
| 
 | |
|   //
 | |
|   // skip preceeding white space
 | |
|   //
 | |
|   Str = String;
 | |
|   while ((*Str) && (*Str == ' ')) {
 | |
|     Str++;
 | |
|   }
 | |
|   //
 | |
|   // Convert ot a Number
 | |
|   //
 | |
|   Number = 0;
 | |
|   while (*Str != '\0') {
 | |
|     if ((*Str >= '0') && (*Str <= '9')) {
 | |
|       Number = (Number * 10) +*Str - '0';
 | |
|     } else {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Str++;
 | |
|   }
 | |
| 
 | |
|   return Number;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetFilePointer64 (
 | |
|   IN  UNIX_BLOCK_IO_PRIVATE    *Private,
 | |
|   IN  INT64                      DistanceToMove,
 | |
|   OUT UINT64                     *NewFilePointer,
 | |
|   IN  INTN                      MoveMethod
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| This function extends the capability of SetFilePointer to accept 64 bit parameters
 | |
| 
 | |
| --*/
 | |
| // TODO: function comment is missing 'Routine Description:'
 | |
| // TODO: function comment is missing 'Arguments:'
 | |
| // TODO: function comment is missing 'Returns:'
 | |
| // TODO:    Private - add argument and description to function comment
 | |
| // TODO:    DistanceToMove - add argument and description to function comment
 | |
| // TODO:    NewFilePointer - add argument and description to function comment
 | |
| // TODO:    MoveMethod - add argument and description to function comment
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
|   off_t         res;
 | |
| 
 | |
|   res = Private->UnixThunk->Lseek(Private->fd, DistanceToMove, MoveMethod);
 | |
|   if (res == -1) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (NewFilePointer != NULL) {
 | |
|     *NewFilePointer = res;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 |