Indentation has been corrected in all of the files. LibC/Locale/multibyte_Utf8.c LibC/Uefi/SysCalls.c Clarify and improve comments. Include/sys/termios.h Add parameter names to function prototypes as referenced in the comments. StdLibPrivateInternalFiles\Include\kfile.h Add comment for the fo_close fileop. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Daryl McDaniel <edk2-lists@mc2research.org> Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19588 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1449 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1449 lines
		
	
	
		
			48 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  EFI versions of NetBSD system calls.
 | 
						|
 | 
						|
  Copyright (c) 2016, Daryl McDaniel. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
 | 
						|
  This program and the accompanying materials are licensed and made available under
 | 
						|
  the terms and conditions of the BSD License that accompanies this distribution.
 | 
						|
  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
#include  <Uefi.h>
 | 
						|
#include  <Library/UefiLib.h>
 | 
						|
#include  <Library/UefiBootServicesTableLib.h>
 | 
						|
#include  <Library/BaseLib.h>
 | 
						|
#include  <Library/MemoryAllocationLib.h>
 | 
						|
#include  <Library/ShellLib.h>
 | 
						|
 | 
						|
#include  <LibConfig.h>
 | 
						|
#include  <sys/EfiCdefs.h>
 | 
						|
 | 
						|
#include  <sys/ansi.h>
 | 
						|
#include  <errno.h>
 | 
						|
#include  <stdarg.h>
 | 
						|
#include  <stdlib.h>
 | 
						|
#include  <string.h>
 | 
						|
#include  <wchar.h>
 | 
						|
#include  <sys/poll.h>
 | 
						|
#include  <sys/fcntl.h>
 | 
						|
#include  <sys/stat.h>
 | 
						|
#include  <sys/syslimits.h>
 | 
						|
#include  <sys/filio.h>
 | 
						|
#include  <Efi/SysEfi.h>
 | 
						|
#include  <unistd.h>
 | 
						|
#include  <kfile.h>
 | 
						|
#include  <Device/Device.h>
 | 
						|
#include  <Device/IIO.h>
 | 
						|
#include  <MainData.h>
 | 
						|
#include  <extern.h>
 | 
						|
 | 
						|
/* EFI versions of BSD system calls used in stdio */
 | 
						|
 | 
						|
/*  Validate that fd refers to a valid file descriptor.
 | 
						|
    IsOpen is interpreted as follows:
 | 
						|
      - Positive  fd must be OPEN
 | 
						|
      - Zero      fd must be CLOSED
 | 
						|
      - Negative  fd may be OPEN or CLOSED
 | 
						|
 | 
						|
    @retval TRUE  fd is VALID
 | 
						|
    @retval FALSE fd is INVALID
 | 
						|
*/
 | 
						|
BOOLEAN
 | 
						|
ValidateFD( int fd, int IsOpen)
 | 
						|
{
 | 
						|
  struct __filedes    *filp;
 | 
						|
  BOOLEAN   retval = FALSE;
 | 
						|
 | 
						|
  if((fd >= 0) && (fd < OPEN_MAX)) {
 | 
						|
    filp = &gMD->fdarray[fd];
 | 
						|
    retval = TRUE;
 | 
						|
    if(IsOpen >= 0) {
 | 
						|
      retval = (BOOLEAN)((filp->f_iflags != 0)  &&    // TRUE if OPEN
 | 
						|
                         FILE_IS_USABLE(filp));         // and Usable (not Larval or Closing)
 | 
						|
      if(IsOpen == VALID_CLOSED) {
 | 
						|
        retval = (BOOLEAN)!retval;                      // We want TRUE if CLOSED
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/* Find and reserve a free File Descriptor.
 | 
						|
 | 
						|
  Returns the first free File Descriptor greater than or equal to the,
 | 
						|
  already validated, fd specified by Minfd.
 | 
						|
 | 
						|
  @return   Returns -1 if there are no free FDs.  Otherwise returns the
 | 
						|
            found fd.
 | 
						|
*/
 | 
						|
int
 | 
						|
FindFreeFD( int MinFd )
 | 
						|
{
 | 
						|
  struct __filedes    *Mfd;
 | 
						|
  int i;
 | 
						|
  int fd = -1;
 | 
						|
 | 
						|
  Mfd = gMD->fdarray;
 | 
						|
 | 
						|
  // Get an available fd
 | 
						|
  for(i=MinFd; i < OPEN_MAX; ++i) {
 | 
						|
    if(Mfd[i].f_iflags == 0) {
 | 
						|
      Mfd[i].f_iflags = FIF_LARVAL; // Temporarily mark this fd as reserved
 | 
						|
      fd = i;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return fd;
 | 
						|
}
 | 
						|
 | 
						|
/* Mark that an open file is to be deleted when closed. */
 | 
						|
int
 | 
						|
DeleteOnClose(int fd)
 | 
						|
{
 | 
						|
  int   retval = 0;
 | 
						|
 | 
						|
  if(ValidateFD( fd, VALID_OPEN)) {
 | 
						|
    gMD->fdarray[fd].f_iflags |= FIF_DELCLOSE;
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    errno = EBADF;
 | 
						|
    retval = -1;
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** The isatty() function tests whether fd, an open file descriptor,
 | 
						|
    is associated with a terminal device.
 | 
						|
 | 
						|
    @param[in]  fd  File Descriptor for the file to be examined.
 | 
						|
 | 
						|
    @retval   1   fd is associated with a terminal.
 | 
						|
    @retval   0   fd is not associated with a terminal.  errno is set to
 | 
						|
                  EBADF if fd is not a valid open FD.
 | 
						|
**/
 | 
						|
int
 | 
						|
isatty  (int fd)
 | 
						|
{
 | 
						|
  int   retval = 0;
 | 
						|
  struct __filedes *Fp;
 | 
						|
 | 
						|
  if(ValidateFD( fd, VALID_OPEN)) {
 | 
						|
    Fp = &gMD->fdarray[fd];
 | 
						|
    retval =  (Fp->f_iflags & _S_ITTY) ? 1 : 0;
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    errno = EBADF;
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** Determine if file descriptor fd is a duplicate of some other fd.
 | 
						|
 | 
						|
    @param[in]    fd    The file descriptor to check.
 | 
						|
 | 
						|
    @retval   TRUE    fd is a duplicate of another fd.
 | 
						|
    @retval   FALSE   fd is unique.
 | 
						|
**/
 | 
						|
static BOOLEAN
 | 
						|
IsDupFd( int fd)
 | 
						|
{
 | 
						|
  void * DevData;
 | 
						|
  const struct fileops   *FileOps;
 | 
						|
  int                   i;
 | 
						|
  BOOLEAN               Ret = FALSE;
 | 
						|
 | 
						|
  if(ValidateFD( fd, VALID_OPEN )) {
 | 
						|
    FileOps = gMD->fdarray[fd].f_ops;
 | 
						|
    DevData = gMD->fdarray[fd].devdata;
 | 
						|
    for(i=0; i < OPEN_MAX; ++i) {
 | 
						|
      if(i == fd)   continue;
 | 
						|
      if(ValidateFD( i, VALID_OPEN )) {   // TRUE if fd is valid and OPEN
 | 
						|
        if((gMD->fdarray[i].f_ops == FileOps)
 | 
						|
          &&(gMD->fdarray[i].devdata == DevData )) {
 | 
						|
          Ret = TRUE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return Ret;
 | 
						|
}
 | 
						|
 | 
						|
/** Worker function to Close a file and set its fd to the specified state.
 | 
						|
 | 
						|
    @param[in]    fd          The file descriptor to close.
 | 
						|
    @param[in]    NewState    State to set the fd to after the file is closed.
 | 
						|
 | 
						|
    @retval    0    The operation completed successfully.
 | 
						|
    @retval   -1    The operation failed.  Further information is in errno.
 | 
						|
                      * EBADF   fd is not a valid or open file descriptor.
 | 
						|
**/
 | 
						|
static int
 | 
						|
_closeX  (int fd, int NewState)
 | 
						|
{
 | 
						|
  struct __filedes     *Fp;
 | 
						|
  int                   retval = 0;
 | 
						|
 | 
						|
  // Verify my pointers and get my FD.
 | 
						|
  if(ValidateFD( fd, VALID_OPEN )) {
 | 
						|
    Fp = &gMD->fdarray[fd];
 | 
						|
    // Check if there are other users of this FileHandle
 | 
						|
    if(Fp->RefCount == 1) { // There should be no other users
 | 
						|
      if(! IsDupFd(fd)) {
 | 
						|
        // Only do the close if no one else is using the FileHandle
 | 
						|
        if(Fp->f_iflags & FIF_DELCLOSE) {
 | 
						|
          /* Handle files marked "Delete on Close". */
 | 
						|
          if(Fp->f_ops->fo_delete != NULL) {
 | 
						|
            retval = Fp->f_ops->fo_delete(Fp);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        else {
 | 
						|
          retval = Fp->f_ops->fo_close( Fp);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      Fp->f_iflags = NewState;    // Close this FD or reserve it
 | 
						|
      Fp->RefCount = 0;           // No one using this FD
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      --Fp->RefCount;   /* One less user of this FD */
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    // Bad FD
 | 
						|
    retval = -1;
 | 
						|
    errno = EBADF;
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** The close() function deallocates the file descriptor indicated by fd.
 | 
						|
    To deallocate means to make the file descriptor available for return by
 | 
						|
    subsequent calls to open() or other functions that allocate file
 | 
						|
    descriptors. All outstanding record locks owned by the process on the file
 | 
						|
    associated with the file descriptor are removed (that is, unlocked).
 | 
						|
 | 
						|
    @param[in]    fd          Descriptor for the File to close.
 | 
						|
 | 
						|
    @retval   0     Successful completion.
 | 
						|
    @retval   -1    An error occurred and errno is set to identify the error.
 | 
						|
**/
 | 
						|
int
 | 
						|
close  (int fd)
 | 
						|
{
 | 
						|
  return _closeX(fd, 0);
 | 
						|
}
 | 
						|
 | 
						|
/** Delete the file specified by path.
 | 
						|
 | 
						|
    @param[in]    path  The MBCS path of the file to delete.
 | 
						|
 | 
						|
    @retval   -1  Unable to open the file specified by path.
 | 
						|
    @retval   -1  If (errno == EPERM), unlink is not permited for this file.
 | 
						|
    @retval   -1  Low-level delete filed.  Reason is in errno.
 | 
						|
    @retval   0   The file was successfully deleted.
 | 
						|
**/
 | 
						|
int
 | 
						|
unlink (const char *path)
 | 
						|
{
 | 
						|
  struct __filedes     *Fp;
 | 
						|
  int                   fd;
 | 
						|
  int                   retval = -1;
 | 
						|
 | 
						|
  EFIerrno = RETURN_SUCCESS;
 | 
						|
 | 
						|
  fd = open(path, O_WRONLY, 0);
 | 
						|
  if(fd >= 0) {
 | 
						|
    Fp = &gMD->fdarray[fd];
 | 
						|
 | 
						|
    if(Fp->f_ops->fo_delete != NULL) {
 | 
						|
      retval = Fp->f_ops->fo_delete(Fp);
 | 
						|
  }
 | 
						|
    Fp->f_iflags = 0;    // Close this FD
 | 
						|
    Fp->RefCount = 0;    // No one using this FD
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** The fcntl() function shall perform the operations described below on open
 | 
						|
    files. The fildes argument is a file descriptor.
 | 
						|
 | 
						|
    The available values for cmd are defined in <fcntl.h> and are as follows:
 | 
						|
      - F_DUPFD - Return a new file descriptor which shall be the lowest
 | 
						|
                  numbered available (that is, not already open) file
 | 
						|
                  descriptor greater than or equal to the third argument, arg,
 | 
						|
                  taken as an integer of type int. The new file descriptor
 | 
						|
                  shall refer to the same open file description as the original
 | 
						|
                  file descriptor, and shall share any locks. The FD_CLOEXEC
 | 
						|
                  flag associated with the new file descriptor shall be cleared
 | 
						|
                  to keep the file open across calls to one of the exec functions.
 | 
						|
      - F_GETFD - Get the file descriptor flags defined in <fcntl.h> that are
 | 
						|
                  associated with the file descriptor fildes. File descriptor
 | 
						|
                  flags are associated with a single file descriptor and do not
 | 
						|
                  affect other file descriptors that refer to the same file.
 | 
						|
      - F_SETFD - Set the file descriptor flags defined in <fcntl.h>, that are
 | 
						|
                  associated with fildes, to the third argument, arg, taken
 | 
						|
                  as type int. If the FD_CLOEXEC flag in the third argument
 | 
						|
                  is 0, the file shall remain open across the exec
 | 
						|
                  functions; otherwise, the file shall be closed upon
 | 
						|
                  successful execution of one of the exec functions.
 | 
						|
      - F_GETFL - Get the file status flags and file access modes, defined in
 | 
						|
                  <fcntl.h>, for the file description associated with fildes.
 | 
						|
                  The file access modes can be extracted from the return
 | 
						|
                  value using the mask O_ACCMODE, which is defined in
 | 
						|
                  <fcntl.h>. File status flags and file access modes are
 | 
						|
                  associated with the file description and do not affect
 | 
						|
                  other file descriptors that refer to the same file with
 | 
						|
                  different open file descriptions.
 | 
						|
      - F_SETFL - Set the file status flags, defined in <fcntl.h>, for the file
 | 
						|
                  description associated with fildes from the corresponding
 | 
						|
                  bits in the third argument, arg, taken as type int. Bits
 | 
						|
                  corresponding to the file access mode and the file creation
 | 
						|
                  flags, as defined in <fcntl.h>, that are set in arg shall
 | 
						|
                  be ignored. If any bits in arg other than those mentioned
 | 
						|
                  here are changed by the application, the result is unspecified.
 | 
						|
      - F_GETOWN -  If fildes refers to a socket, get the process or process group
 | 
						|
                  ID specified to receive SIGURG signals when out-of-band
 | 
						|
                  data is available. Positive values indicate a process ID;
 | 
						|
                  negative values, other than -1, indicate a process group
 | 
						|
                  ID. If fildes does not refer to a socket, the results are
 | 
						|
                  unspecified.
 | 
						|
      - F_SETOWN -  If fildes refers to a socket, set the process or process
 | 
						|
                  group ID specified to receive SIGURG signals when
 | 
						|
                  out-of-band data is available, using the value of the third
 | 
						|
                  argument, arg, taken as type int. Positive values indicate
 | 
						|
                  a process ID; negative values, other than -1, indicate a
 | 
						|
                  process group ID. If fildes does not refer to a socket, the
 | 
						|
                  results are unspecified.
 | 
						|
 | 
						|
    The fcntl() function shall fail if:
 | 
						|
 | 
						|
    [EBADF]       The fildes argument is not a valid open file descriptor.
 | 
						|
    [EINVAL]      The cmd argument is invalid, or the cmd argument is F_DUPFD
 | 
						|
                  and arg is negative or greater than or equal to {OPEN_MAX}.
 | 
						|
    [EMFILE]      The argument cmd is F_DUPFD and {OPEN_MAX} file descriptors
 | 
						|
                  are currently open in the calling process, or no file
 | 
						|
                  descriptors greater than or equal to arg are available.
 | 
						|
    [EOVERFLOW]   One of the values to be returned cannot be represented correctly.
 | 
						|
 | 
						|
    @param[in]      fildes    Descriptor for the file to be controlled.
 | 
						|
    @param[in]      cmd       Command to be acted upon.
 | 
						|
    @param[in,out]  ...       Optional additional parameters as required by cmd.
 | 
						|
 | 
						|
    @return   Upon successful completion, the value returned shall depend on
 | 
						|
              cmd as follows:
 | 
						|
                - F_DUPFD - A new file descriptor.
 | 
						|
                - F_GETFD - Value of flags defined in <fcntl.h>. The return value
 | 
						|
                            shall not be negative.
 | 
						|
                - F_SETFD - Value other than -1.
 | 
						|
                - F_GETFL - Value of file status flags and access modes. The return
 | 
						|
                            value is not negative.
 | 
						|
                - F_SETFL - Value other than -1.
 | 
						|
                - F_GETOWN  - Value of the socket owner process or process group;
 | 
						|
                            this will not be -1.
 | 
						|
                - F_SETOWN - Value other than -1.
 | 
						|
              Otherwise, -1 shall be returned and errno set to indicate the error.
 | 
						|
 | 
						|
**/
 | 
						|
int
 | 
						|
fcntl     (int fildes, int cmd, ...)
 | 
						|
{
 | 
						|
  va_list             p3;
 | 
						|
  struct __filedes   *MyFd;
 | 
						|
  int                 retval = -1;
 | 
						|
  int                 temp;
 | 
						|
 | 
						|
//Print(L"%a( %d, %d, ...)\n", __func__, fildes, cmd);
 | 
						|
  va_start(p3, cmd);
 | 
						|
 | 
						|
  if(ValidateFD( fildes, VALID_OPEN )) {
 | 
						|
    MyFd = &gMD->fdarray[fildes];
 | 
						|
 | 
						|
    switch(cmd) {
 | 
						|
      case F_DUPFD:
 | 
						|
        temp = va_arg(p3, int);
 | 
						|
        if(ValidateFD( temp, VALID_DONT_CARE )) {
 | 
						|
          temp = FindFreeFD( temp );
 | 
						|
          if(temp < 0) {
 | 
						|
            errno = EMFILE;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
          /* temp is now a valid fd reserved for further use
 | 
						|
             so copy fd into temp.
 | 
						|
          */
 | 
						|
          (void)memcpy(&gMD->fdarray[temp], MyFd, sizeof(struct __filedes));
 | 
						|
          retval = temp;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
          errno = EINVAL;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case F_SETFL:
 | 
						|
        retval = MyFd->Oflags;        // Get original value
 | 
						|
        temp = va_arg(p3, int);
 | 
						|
        temp &= O_SETMASK;            // Only certain bits can be set
 | 
						|
        temp |= retval & O_SETMASK;
 | 
						|
        MyFd->Oflags = temp;          // Set new value
 | 
						|
        break;
 | 
						|
 | 
						|
      case F_SETFD:
 | 
						|
        retval = MyFd->f_iflags;
 | 
						|
        break;
 | 
						|
      //case F_SETOWN:
 | 
						|
      //  retval = MyFd->SocProc;
 | 
						|
      //  MyFd->SocProc = va_arg(p3, int);
 | 
						|
      //  break;
 | 
						|
      case F_GETFD:
 | 
						|
        retval = MyFd->f_iflags;
 | 
						|
        break;
 | 
						|
      case F_GETFL:
 | 
						|
        retval = MyFd->Oflags;
 | 
						|
        break;
 | 
						|
      //case F_GETOWN:
 | 
						|
      //  retval = MyFd->SocProc;
 | 
						|
      //  break;
 | 
						|
      default:
 | 
						|
        errno  = EINVAL;
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    // Bad FD
 | 
						|
    errno = EBADF;
 | 
						|
  }
 | 
						|
  va_end(p3);
 | 
						|
  return retval;;
 | 
						|
}
 | 
						|
 | 
						|
/** The dup() function provides an alternative interface to the
 | 
						|
    service provided by fcntl() using the F_DUPFD command. The call:
 | 
						|
      - fid = dup(fildes);
 | 
						|
    shall be equivalent to:
 | 
						|
      - fid = fcntl(fildes, F_DUPFD, 0);
 | 
						|
 | 
						|
    @param[in]    fildes    Descriptor for the file to be examined.
 | 
						|
 | 
						|
    @return   Upon successful completion a non-negative integer, namely the
 | 
						|
              file descriptor, shall be returned; otherwise, -1 shall be
 | 
						|
              returned and errno set to indicate the error.
 | 
						|
**/
 | 
						|
int
 | 
						|
dup   (int fildes)
 | 
						|
{
 | 
						|
  return fcntl(fildes, F_DUPFD, 0);
 | 
						|
}
 | 
						|
 | 
						|
/** Make fildes2 refer to a duplicate of fildes.
 | 
						|
 | 
						|
    The dup2() function provides an alternative interface to the
 | 
						|
    service provided by fcntl() using the F_DUPFD command. The call:
 | 
						|
      - fid = dup2(fildes, fildes2);
 | 
						|
    shall be equivalent to:
 | 
						|
      - close(fildes2);
 | 
						|
      - fid = fcntl(fildes, F_DUPFD, fildes2);
 | 
						|
    except for the following:
 | 
						|
      - If fildes2 is less than 0 or greater than or equal to {OPEN_MAX},
 | 
						|
        dup2() shall return -1 with errno set to [EBADF].
 | 
						|
      - If fildes is a valid file descriptor and is equal to fildes2, dup2()
 | 
						|
        shall return fildes2 without closing it.
 | 
						|
      - If fildes is not a valid file descriptor, dup2() shall return -1 and
 | 
						|
        shall not close fildes2.
 | 
						|
      - The value returned shall be equal to the value of fildes2 upon
 | 
						|
        successful completion, or -1 upon failure.
 | 
						|
 | 
						|
    @param[in]  fildes    File Descriptor to be duplicated.
 | 
						|
    @param[in]  fildes2   File Descriptor to be made a duplicate of fildes.
 | 
						|
 | 
						|
    @return   Upon successful completion a non-negative integer, namely
 | 
						|
              fildes2, shall be returned; otherwise, -1 shall be
 | 
						|
              returned and errno set to EBADF indicate the error.
 | 
						|
**/
 | 
						|
int
 | 
						|
dup2    (int fildes, int fildes2)
 | 
						|
{
 | 
						|
  int retval = -1;
 | 
						|
 | 
						|
  if(ValidateFD( fildes, VALID_OPEN)) {
 | 
						|
    retval = fildes2;
 | 
						|
    if( fildes != fildes2) {
 | 
						|
      if(ValidateFD( fildes2, VALID_DONT_CARE)) {
 | 
						|
        gMD->fdarray[fildes2].f_iflags = FIF_LARVAL;  // Mark the file closed, but reserved
 | 
						|
        (void)memcpy(&gMD->fdarray[fildes2],      // Duplicate fildes into fildes2
 | 
						|
                     &gMD->fdarray[fildes], sizeof(struct __filedes));
 | 
						|
        gMD->fdarray[fildes2].MyFD = (UINT16)fildes2;
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        errno = EBADF;
 | 
						|
        retval = -1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    errno = EBADF;
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** Reposition a file's read/write offset.
 | 
						|
 | 
						|
    The lseek() function repositions the offset of the file descriptor fildes
 | 
						|
    to the argument offset according to the directive how.  The argument
 | 
						|
    fildes must be an open file descriptor.  lseek() repositions the file
 | 
						|
    pointer fildes as follows:
 | 
						|
 | 
						|
      - If how is SEEK_SET, the offset is set to offset bytes.
 | 
						|
 | 
						|
      - If how is SEEK_CUR, the offset is set to its current location
 | 
						|
        plus offset bytes.
 | 
						|
 | 
						|
      - If how is SEEK_END, the offset is set to the size of the file
 | 
						|
        plus offset bytes.
 | 
						|
 | 
						|
    The lseek() function allows the file offset to be set beyond the end of
 | 
						|
    the existing end-of-file of the file.  If data is later written at this
 | 
						|
    point, subsequent reads of the data in the gap return bytes of zeros
 | 
						|
    (until data is actually written into the gap).
 | 
						|
 | 
						|
    Some devices are incapable of seeking.  The value of the pointer associ-
 | 
						|
    ated with such a device is undefined.
 | 
						|
 | 
						|
    @param[in]  fd        Descriptor for the File to be affected.
 | 
						|
    @param[in]  offset    Value to adjust the file position by.
 | 
						|
    @param[in]  how       How the file position is to be adjusted.
 | 
						|
 | 
						|
    @return   Upon successful completion, lseek() returns the resulting offset
 | 
						|
              location as measured in bytes from the beginning of the file.
 | 
						|
              Otherwise, a value of -1 is returned and errno is set to
 | 
						|
              indicate the error.
 | 
						|
**/
 | 
						|
__off_t
 | 
						|
lseek (int fd, __off_t offset, int how)
 | 
						|
{
 | 
						|
  __off_t             CurPos = -1;
 | 
						|
//  RETURN_STATUS       Status = RETURN_SUCCESS;
 | 
						|
  struct __filedes   *filp;
 | 
						|
 | 
						|
  EFIerrno = RETURN_SUCCESS;    // In case of error without an EFI call
 | 
						|
 | 
						|
  if( how == SEEK_SET || how == SEEK_CUR  || how == SEEK_END) {
 | 
						|
    if(ValidateFD( fd, VALID_OPEN)) {
 | 
						|
      filp = &gMD->fdarray[fd];
 | 
						|
      // Both of our parameters have been verified as valid
 | 
						|
      CurPos = filp->f_ops->fo_lseek( filp, offset, how);
 | 
						|
      if(CurPos >= 0) {
 | 
						|
        filp->f_offset = CurPos;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      errno = EBADF;  // Bad File Descriptor
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    errno = EINVAL;   // Invalid how argument
 | 
						|
  }
 | 
						|
  return CurPos;
 | 
						|
}
 | 
						|
 | 
						|
/** The directory path is created with the access permissions specified by
 | 
						|
    perms.
 | 
						|
 | 
						|
    The directory is closed after it is created.
 | 
						|
 | 
						|
    @param[in]  path    The path to a directory to create.
 | 
						|
    @param[in]  perms   Permissions as defined in <sys/stat.h>
 | 
						|
 | 
						|
    @retval   0   The directory was created successfully.
 | 
						|
    @retval  -1   An error occurred and error codes are stored in errno and EFIerrno.
 | 
						|
**/
 | 
						|
int
 | 
						|
mkdir (const char *path, __mode_t perms)
 | 
						|
{
 | 
						|
  wchar_t            *NewPath;
 | 
						|
  DeviceNode         *Node;
 | 
						|
  char               *GenI;
 | 
						|
  RETURN_STATUS       Status;
 | 
						|
  int                 Instance  = 0;
 | 
						|
  int                 retval = 0;
 | 
						|
 | 
						|
  Status = ParsePath(path, &NewPath, &Node, &Instance, NULL);
 | 
						|
  if(Status == RETURN_SUCCESS) {
 | 
						|
    GenI = Node->InstanceList;
 | 
						|
    if(GenI == NULL) {
 | 
						|
      errno   = EPERM;
 | 
						|
      retval  = -1;
 | 
						|
      }
 | 
						|
    else {
 | 
						|
      //GenI += (Instance * Node->InstanceSize);
 | 
						|
      retval = ((GenericInstance *)GenI)->Abstraction.fo_mkdir( path, perms);
 | 
						|
      }
 | 
						|
    free(NewPath);
 | 
						|
    }
 | 
						|
  else {
 | 
						|
    retval = -1;
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** Open a file.
 | 
						|
    The open() function establishes the connection between a file and a file
 | 
						|
    descriptor.  It creates an open file description that refers to a file
 | 
						|
    and a file descriptor that refers to that open file description. The file
 | 
						|
    descriptor is used by other I/O functions to refer to that file.
 | 
						|
 | 
						|
    The open() function returns a file descriptor for the named file that is
 | 
						|
    the lowest file descriptor not currently open for that process. The open
 | 
						|
    file description is new, and therefore the file descriptor shall not
 | 
						|
    share it with any other process in the system.
 | 
						|
 | 
						|
    The file offset used to mark the current position within the file is set
 | 
						|
    to the beginning of the file.
 | 
						|
 | 
						|
    The EFI ShellOpenFileByName() function is used to perform the low-level
 | 
						|
    file open operation.  The primary task of open() is to translate from the
 | 
						|
    flags used in the <stdio.h> environment to those used by the EFI function.
 | 
						|
 | 
						|
    The file status flags and file access modes of the open file description
 | 
						|
    are set according to the value of oflags.
 | 
						|
 | 
						|
    Values for oflags are constructed by a bitwise-inclusive OR of flags from
 | 
						|
    the following list, defined in <fcntl.h>. Applications shall specify
 | 
						|
    exactly one of { O_RDONLY, O_RDWR, O_WRONLY } in the value of oflags.
 | 
						|
    Any combination of { O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL } may
 | 
						|
    also be specified in oflags.
 | 
						|
 | 
						|
    The only valid flag combinations for ShellOpenFileByName() are:
 | 
						|
      - Read
 | 
						|
      - Read/Write
 | 
						|
      - Create/Read/Write
 | 
						|
 | 
						|
    Values for mode specify the access permissions for newly created files.
 | 
						|
    The mode value is saved in the FD to indicate permissions for further operations.
 | 
						|
 | 
						|
    O_RDONLY      -- flags = EFI_FILE_MODE_READ -- this is always done
 | 
						|
    O_WRONLY      -- flags |= EFI_FILE_MODE_WRITE
 | 
						|
    O_RDWR        -- flags |= EFI_FILE_MODE_WRITE -- READ is already set
 | 
						|
 | 
						|
    O_NONBLOCK    -- ignored
 | 
						|
    O_APPEND      -- Seek to EOF before every write
 | 
						|
    O_CREAT       -- flags |= EFI_FILE_MODE_CREATE
 | 
						|
    O_TRUNC       -- delete first then create new
 | 
						|
    O_EXCL        -- if O_CREAT is also set, open will fail if the file already exists.
 | 
						|
 | 
						|
    @param[in]    Path      The path argument points to a pathname naming the
 | 
						|
                            object to be opened.
 | 
						|
    @param[in]    oflags    File status flags and file access modes of the
 | 
						|
                            open file description.
 | 
						|
    @param[in]    mode      File access permission bits as defined in
 | 
						|
                            <sys/stat.h>.  Only used if a file is created
 | 
						|
                            as a result of the open.
 | 
						|
 | 
						|
    @return     Upon successful completion, open() opens the file and returns
 | 
						|
                a non-negative integer representing the lowest numbered
 | 
						|
                unused file descriptor. Otherwise, open returns -1 and sets
 | 
						|
                errno to indicate the error. If a negative value is
 | 
						|
                returned, no files are created or modified.
 | 
						|
                  - EMFILE - No file descriptors available -- Max number already open.
 | 
						|
                  - EINVAL - Bad value specified for oflags or mode.
 | 
						|
                  - ENOMEM - Failure allocating memory for internal buffers.
 | 
						|
                  - EEXIST - File exists and open attempted with (O_EXCL | O_CREAT) set.
 | 
						|
                  - EIO - UEFI failure.  Check value in EFIerrno.
 | 
						|
**/
 | 
						|
int
 | 
						|
open(
 | 
						|
  const char *path,
 | 
						|
  int oflags,
 | 
						|
  int mode
 | 
						|
  )
 | 
						|
{
 | 
						|
  wchar_t              *NewPath;
 | 
						|
  wchar_t              *MPath;
 | 
						|
  DeviceNode           *Node;
 | 
						|
  struct __filedes     *filp;
 | 
						|
  struct termios       *Termio;
 | 
						|
  int                   Instance  = 0;
 | 
						|
  RETURN_STATUS         Status;
 | 
						|
  UINT32                OpenMode;
 | 
						|
  int                   fd = -1;
 | 
						|
  int                   doresult;
 | 
						|
 | 
						|
  Status = ParsePath(path, &NewPath, &Node, &Instance, &MPath);
 | 
						|
  if(Status == RETURN_SUCCESS) {
 | 
						|
    if ((Node == NULL)               ||
 | 
						|
        (Node->InstanceList == NULL))
 | 
						|
    {
 | 
						|
      errno   = EPERM;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      // Could add a test to see if the file name begins with a period.
 | 
						|
      // If it does, then add the HIDDEN flag to Attributes.
 | 
						|
 | 
						|
      // Get an available fd
 | 
						|
      fd = FindFreeFD( VALID_CLOSED );
 | 
						|
 | 
						|
      if( fd < 0 ) {
 | 
						|
        // All available FDs are in use
 | 
						|
        errno = EMFILE;
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        filp = &gMD->fdarray[fd];
 | 
						|
        // Save the flags and mode in the File Descriptor
 | 
						|
        filp->Oflags = oflags;
 | 
						|
        filp->Omode = mode;
 | 
						|
 | 
						|
        doresult = Node->OpenFunc(Node, filp, Instance, NewPath, MPath);
 | 
						|
        if(doresult < 0) {
 | 
						|
          filp->f_iflags = 0;   // Release this FD
 | 
						|
          fd = -1;              // Indicate an error
 | 
						|
        }
 | 
						|
        else {
 | 
						|
          // Build our final f_iflags value
 | 
						|
          OpenMode  = ( mode & S_ACC_READ )  ? S_ACC_READ : 0;
 | 
						|
          OpenMode |= ( mode & S_ACC_WRITE ) ? S_ACC_WRITE : 0;
 | 
						|
 | 
						|
          filp->f_iflags |= OpenMode;
 | 
						|
 | 
						|
          if((oflags & O_TTY_INIT) && (filp->f_iflags & _S_ITTY) && (filp->devdata != NULL)) {
 | 
						|
            // Initialize the device's termios flags to a "sane" value
 | 
						|
            Termio = &((cIIO *)filp->devdata)->Termio;
 | 
						|
            Termio->c_iflag = ICRNL | IGNSPEC;
 | 
						|
            Termio->c_oflag = OPOST | ONLCR | OXTABS | ONOEOT | ONOCR | ONLRET | OCTRL;
 | 
						|
            Termio->c_lflag = ECHO | ECHOE | ECHONL | ICANON;
 | 
						|
            Termio->c_cc[VERASE]  = 0x08;   // ^H Backspace
 | 
						|
            Termio->c_cc[VKILL]   = 0x15;   // ^U
 | 
						|
            Termio->c_cc[VINTR]   = 0x03;   // ^C Interrupt character
 | 
						|
          }
 | 
						|
          ++filp->RefCount;
 | 
						|
          FILE_SET_MATURE(filp);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    free(NewPath);
 | 
						|
  }
 | 
						|
  free(MPath);    // We don't need this any more.
 | 
						|
 | 
						|
  // return the fd of our now open file
 | 
						|
  return fd;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Poll a list of file descriptors.
 | 
						|
 | 
						|
  The ::poll routine waits for up to timeout milliseconds for an event
 | 
						|
  to occur on one or more of the file descriptors listed.  The event
 | 
						|
  types of interested are specified for each file descriptor in the events
 | 
						|
  field.  The actual event detected is returned in the revents field of
 | 
						|
  the array.  The
 | 
						|
  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">POSIX</a>
 | 
						|
  documentation is available online.
 | 
						|
 | 
						|
  @param[in]  pfd       Address of an array of pollfd structures.
 | 
						|
 | 
						|
  @param[in]  nfds      Number of elements in the array of pollfd structures.
 | 
						|
 | 
						|
  @param[in]  timeout   Length of time in milliseconds to wait for the event
 | 
						|
 | 
						|
  @return     The number of file descriptors with detected events.  Zero
 | 
						|
              indicates that the call timed out and -1 indicates an error.
 | 
						|
 | 
						|
 **/
 | 
						|
int
 | 
						|
poll (
 | 
						|
  struct pollfd * pfd,
 | 
						|
  nfds_t nfds,
 | 
						|
  int timeout
 | 
						|
  )
 | 
						|
{
 | 
						|
  struct __filedes * pDescriptor;
 | 
						|
  struct pollfd * pEnd;
 | 
						|
  struct pollfd * pPollFD;
 | 
						|
  int SelectedFDs;
 | 
						|
  EFI_STATUS Status;
 | 
						|
  EFI_EVENT Timer;
 | 
						|
  UINT64 TimerTicks;
 | 
						|
 | 
						|
  //
 | 
						|
  //  Create the timer for the timeout
 | 
						|
  //
 | 
						|
  Timer = NULL;
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  if ( INFTIM != timeout ) {
 | 
						|
    Status = gBS->CreateEvent ( EVT_TIMER,
 | 
						|
                                TPL_NOTIFY,
 | 
						|
                                NULL,
 | 
						|
                                NULL,
 | 
						|
                                &Timer );
 | 
						|
    if ( !EFI_ERROR ( Status )) {
 | 
						|
      //
 | 
						|
      //  Start the timeout timer
 | 
						|
      //
 | 
						|
      TimerTicks = timeout;
 | 
						|
      TimerTicks *= 1000 * 10;
 | 
						|
      Status = gBS->SetTimer ( Timer,
 | 
						|
                               TimerRelative,
 | 
						|
                               TimerTicks );
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      SelectedFDs = -1;
 | 
						|
      errno = ENOMEM;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if ( !EFI_ERROR ( Status )) {
 | 
						|
    //
 | 
						|
    //  Poll until an event is detected or the timer fires
 | 
						|
    //
 | 
						|
    SelectedFDs = 0;
 | 
						|
    errno = 0;
 | 
						|
    do {
 | 
						|
      //
 | 
						|
      //  Poll the list of file descriptors
 | 
						|
      //
 | 
						|
      pPollFD = pfd;
 | 
						|
      pEnd = &pPollFD [ nfds ];
 | 
						|
      while ( pEnd > pPollFD ) {
 | 
						|
        //
 | 
						|
        //  Validate the file descriptor
 | 
						|
        //
 | 
						|
        if ( !ValidateFD ( pPollFD->fd, VALID_OPEN )) {
 | 
						|
          errno = EINVAL;
 | 
						|
          return -1;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        //  Poll the device or file
 | 
						|
        //
 | 
						|
        pDescriptor = &gMD->fdarray [ pPollFD->fd ];
 | 
						|
        pPollFD->revents = pDescriptor->f_ops->fo_poll ( pDescriptor,
 | 
						|
                                                         pPollFD->events );
 | 
						|
 | 
						|
        //
 | 
						|
        //  Determine if this file descriptor detected an event
 | 
						|
        //
 | 
						|
        if ( 0 != pPollFD->revents ) {
 | 
						|
          //
 | 
						|
          //  Select this descriptor
 | 
						|
          //
 | 
						|
          SelectedFDs += 1;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        //  Set the next file descriptor
 | 
						|
        //
 | 
						|
        pPollFD += 1;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      //  Check for timeout
 | 
						|
      //
 | 
						|
      if ( NULL != Timer ) {
 | 
						|
        Status = gBS->CheckEvent ( Timer );
 | 
						|
        if ( EFI_SUCCESS == Status ) {
 | 
						|
          //
 | 
						|
          //  Timeout
 | 
						|
          //
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        else if ( EFI_NOT_READY == Status ) {
 | 
						|
          Status = EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    }
 | 
						|
    } while (( 0 == SelectedFDs )
 | 
						|
        && ( EFI_SUCCESS == Status ));
 | 
						|
 | 
						|
    //
 | 
						|
    //  Stop the timer
 | 
						|
    //
 | 
						|
    if ( NULL != Timer ) {
 | 
						|
      gBS->SetTimer ( Timer,
 | 
						|
                      TimerCancel,
 | 
						|
                      0 );
 | 
						|
  }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    SelectedFDs = -1;
 | 
						|
    errno = EAGAIN;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  //  Release the timer
 | 
						|
  //
 | 
						|
  if ( NULL != Timer ) {
 | 
						|
    gBS->CloseEvent ( Timer );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  //  Return the number of selected file system descriptors
 | 
						|
  //
 | 
						|
  return SelectedFDs;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/** The rename() function changes the name of a file.
 | 
						|
    The From argument points to the pathname of the file to be renamed. The To
 | 
						|
    argument points to the new pathname of the file.
 | 
						|
 | 
						|
    If the From argument points to the pathname of a file that is not a
 | 
						|
    directory, the To argument shall not point to the pathname of a
 | 
						|
    directory. If the file named by the To argument exists, it shall be
 | 
						|
    removed and From renamed to To. Write access permission is required for
 | 
						|
    both the directory containing old and the directory containing To.
 | 
						|
 | 
						|
    If the From argument points to the pathname of a directory, the To
 | 
						|
    argument shall not point to the pathname of a file that is not a
 | 
						|
    directory. If the directory named by the To argument exists, it shall be
 | 
						|
    removed and From renamed to To.
 | 
						|
 | 
						|
    The To pathname shall not contain a path prefix that names From. Write
 | 
						|
    access permission is required for the directory containing From and the
 | 
						|
    directory containing To. If the From argument points to the pathname of a
 | 
						|
    directory, write access permission may be required for the directory named
 | 
						|
    by From, and, if it exists, the directory named by To.
 | 
						|
 | 
						|
    If the rename() function fails for any reason other than [EIO], any file
 | 
						|
    named by To shall be unaffected.
 | 
						|
 | 
						|
    @param[in]  From    Path to the file to be renamed.
 | 
						|
    @param[in]  To      The new name of From.
 | 
						|
 | 
						|
    @retval   0     Successful completion.
 | 
						|
    @retval   -1    An error has occured and errno has been set to further specify the error.
 | 
						|
                    Neither the file named by From nor the file named by To are
 | 
						|
                    changed or created.
 | 
						|
                      - ENXIO: Path specified is not supported by any loaded driver.
 | 
						|
                      - ENOMEM: Insufficient memory to calloc a MapName buffer.
 | 
						|
                      - EINVAL: The path parameter is not valid.
 | 
						|
**/
 | 
						|
int
 | 
						|
rename(
 | 
						|
  const char *From,
 | 
						|
  const char *To
 | 
						|
  )
 | 
						|
{
 | 
						|
  wchar_t            *FromPath;
 | 
						|
  DeviceNode         *FromNode;
 | 
						|
  char               *GenI;
 | 
						|
  int                 Instance    = 0;
 | 
						|
  RETURN_STATUS       Status;
 | 
						|
  int                 retval      = -1;
 | 
						|
 | 
						|
  Status = ParsePath(From, &FromPath, &FromNode, &Instance, NULL);
 | 
						|
  if(Status == RETURN_SUCCESS) {
 | 
						|
    GenI = FromNode->InstanceList;
 | 
						|
    if(GenI == NULL) {
 | 
						|
      errno   = EPERM;
 | 
						|
      retval  = -1;
 | 
						|
      }
 | 
						|
      else {
 | 
						|
      //GenI += (Instance * FromNode->InstanceSize);
 | 
						|
      retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( From, To);
 | 
						|
              }
 | 
						|
    free(FromPath);
 | 
						|
            }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** Delete a specified directory.
 | 
						|
 | 
						|
    @param[in]  path    Path to the directory to delete.
 | 
						|
 | 
						|
    @retval   -1    The directory couldn't be opened (doesn't exist).
 | 
						|
    @retval   -1    The directory wasn't empty or an IO error occured.
 | 
						|
**/
 | 
						|
int
 | 
						|
rmdir(
 | 
						|
  const char *path
 | 
						|
  )
 | 
						|
{
 | 
						|
  struct __filedes   *filp;
 | 
						|
  int                 fd;
 | 
						|
  int                 retval = -1;
 | 
						|
 | 
						|
  fd = open(path, O_RDWR, 0);
 | 
						|
  if(fd >= 0) {
 | 
						|
    filp = &gMD->fdarray[fd];
 | 
						|
 | 
						|
    retval = filp->f_ops->fo_rmdir(filp);
 | 
						|
    filp->f_iflags = 0;           // Close this FD
 | 
						|
    filp->RefCount = 0;           // No one using this FD
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** The fstat() function obtains information about an open file associated
 | 
						|
    with the file descriptor fd, and writes it to the area pointed to
 | 
						|
    by statbuf.
 | 
						|
 | 
						|
    The statbuf argument is a pointer to a stat structure, as defined
 | 
						|
    in <sys/stat.h>, into which information is placed concerning the file.
 | 
						|
 | 
						|
    The structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atime,
 | 
						|
    st_ctime, and st_mtime shall have meaningful values. The value of the
 | 
						|
    member st_nlink shall be set to the number of links to the file.
 | 
						|
 | 
						|
    The fstat() function shall update any time-related fields before writing
 | 
						|
    into the stat structure.
 | 
						|
 | 
						|
    The fstat() function is implemented using the ShellGetFileInfo()
 | 
						|
    function.
 | 
						|
 | 
						|
    The stat structure members which don't have direct analogs to EFI file
 | 
						|
    information are filled in as follows:
 | 
						|
      - st_mode     Populated with information from fd
 | 
						|
      - st_ino      Set to zero.  (inode)
 | 
						|
      - st_dev      Set to zero.
 | 
						|
      - st_uid      Set to zero.
 | 
						|
      - st_gid      Set to zero.
 | 
						|
      - st_nlink    Set to one.
 | 
						|
 | 
						|
    @param[in]    fd        File descriptor as returned from open().
 | 
						|
    @param[out]   statbuf   Buffer in which the file status is put.
 | 
						|
 | 
						|
    @retval    0  Successful Completion.
 | 
						|
    @retval   -1  An error has occurred and errno has been set to
 | 
						|
                  identify the error.
 | 
						|
**/
 | 
						|
int
 | 
						|
fstat (int fd, struct stat *statbuf)
 | 
						|
{
 | 
						|
  int                 retval = -1;
 | 
						|
  struct __filedes   *filp;
 | 
						|
 | 
						|
  if(ValidateFD( fd, VALID_OPEN)) {
 | 
						|
    filp = &gMD->fdarray[fd];
 | 
						|
    retval = filp->f_ops->fo_stat(filp, statbuf, NULL);
 | 
						|
      }
 | 
						|
      else {
 | 
						|
    errno   =  EBADF;
 | 
						|
      }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** Obtains information about the file pointed to by path.
 | 
						|
 | 
						|
    Opens the file pointed to by path, calls _EFI_FileInfo with the file's handle,
 | 
						|
    then closes the file.
 | 
						|
 | 
						|
    @param[in]    path      Path to the file to obtain information about.
 | 
						|
    @param[out]   statbuf   Buffer in which the file status is put.
 | 
						|
 | 
						|
    @retval    0  Successful Completion.
 | 
						|
    @retval   -1  An error has occurred and errno has been set to
 | 
						|
                  identify the error.
 | 
						|
**/
 | 
						|
int
 | 
						|
stat   (const char *path, struct stat *statbuf)
 | 
						|
{
 | 
						|
  int                 fd;
 | 
						|
  int                 retval  = -1;
 | 
						|
  struct __filedes   *filp;
 | 
						|
 | 
						|
  fd = open(path, O_RDONLY, 0);
 | 
						|
  if(fd >= 0) {
 | 
						|
    filp = &gMD->fdarray[fd];
 | 
						|
    retval = filp->f_ops->fo_stat( filp, statbuf, NULL);
 | 
						|
    close(fd);
 | 
						|
  }
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/**  Same as stat since EFI doesn't have symbolic links.
 | 
						|
 | 
						|
    @param[in]    path      Path to the file to obtain information about.
 | 
						|
    @param[out]   statbuf   Buffer in which the file status is put.
 | 
						|
 | 
						|
    @retval    0  Successful Completion.
 | 
						|
    @retval   -1  An error has occurred and errno has been set to
 | 
						|
                  identify the error.
 | 
						|
**/
 | 
						|
int
 | 
						|
lstat (const char *path, struct stat *statbuf)
 | 
						|
{
 | 
						|
  return stat(path, statbuf);
 | 
						|
}
 | 
						|
 | 
						|
/** Control a device.
 | 
						|
 | 
						|
    @param[in]        fd        Descriptor for the file to be acted upon.
 | 
						|
    @param[in]        request   Specifies the operation to perform.
 | 
						|
    @param[in,out]    ...       Zero or more parameters as required for request.
 | 
						|
 | 
						|
    @retval   >=0   The operation completed successfully.
 | 
						|
    @retval   -1    An error occured.  More information is in errno.
 | 
						|
**/
 | 
						|
int
 | 
						|
ioctl(
 | 
						|
  int             fd,
 | 
						|
  unsigned long   request,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  int                 retval = -1;
 | 
						|
  struct __filedes   *filp;
 | 
						|
  va_list             argp;
 | 
						|
 | 
						|
  va_start(argp, request);
 | 
						|
 | 
						|
  if(ValidateFD( fd, VALID_OPEN)) {
 | 
						|
    filp = &gMD->fdarray[fd];
 | 
						|
 | 
						|
    if(request == FIODLEX) {
 | 
						|
      /* set Delete-on-Close */
 | 
						|
      filp->f_iflags |= FIF_DELCLOSE;
 | 
						|
      retval = 0;
 | 
						|
    }
 | 
						|
    else if(request == FIONDLEX) {
 | 
						|
      /* clear Delete-on-Close */
 | 
						|
      filp->f_iflags &= ~FIF_DELCLOSE;
 | 
						|
      retval = 0;
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      /* All other requests. */
 | 
						|
      retval = filp->f_ops->fo_ioctl(filp, request, argp);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    errno   =  EBADF;
 | 
						|
  }
 | 
						|
  va_end(argp);
 | 
						|
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** Read from a file.
 | 
						|
 | 
						|
    The read() function shall attempt to read nbyte bytes from the file
 | 
						|
    associated with the open file descriptor, fildes, into the buffer pointed
 | 
						|
    to by buf.
 | 
						|
 | 
						|
    Before any action described below is taken, and if nbyte is zero, the
 | 
						|
    read() function may detect and return errors as described below. In the
 | 
						|
    absence of errors, or if error detection is not performed, the read()
 | 
						|
    function shall return zero and have no other results.
 | 
						|
 | 
						|
    On files that support seeking (for example, a regular file), the read()
 | 
						|
    shall start at a position in the file given by the file offset associated
 | 
						|
    with fildes. The file offset shall be incremented by the number of bytes
 | 
						|
    actually read.
 | 
						|
 | 
						|
    Files that do not support seeking - for example, terminals - always read
 | 
						|
    from the current position. The value of a file offset associated with
 | 
						|
    such a file is undefined.
 | 
						|
 | 
						|
    No data transfer shall occur past the current end-of-file. If the
 | 
						|
    starting position is at or after the end-of-file, 0 shall be returned.
 | 
						|
 | 
						|
    The read() function reads data previously written to a file. If any
 | 
						|
    portion of a regular file prior to the end-of-file has not been written,
 | 
						|
    read() shall return bytes with value 0. For example, lseek() allows the
 | 
						|
    file offset to be set beyond the end of existing data in the file. If data
 | 
						|
    is later written at this point, subsequent reads in the gap between the
 | 
						|
    previous end of data and the newly written data shall return bytes with
 | 
						|
    value 0 until data is written into the gap.
 | 
						|
 | 
						|
    Upon successful completion, where nbyte is greater than 0, read() shall
 | 
						|
    mark for update the st_atime field of the file, and shall return the
 | 
						|
    number of bytes read. This number shall never be greater than nbyte. The
 | 
						|
    value returned may be less than nbyte if the number of bytes left in the
 | 
						|
    file is less than nbyte, if the read() request was interrupted by a
 | 
						|
    signal, or if the file is a pipe or FIFO or special file and has fewer
 | 
						|
    than nbyte bytes immediately available for reading. For example, a read()
 | 
						|
    from a file associated with a terminal may return one typed line of data.
 | 
						|
 | 
						|
    If fildes does not refer to a directory, the function reads the requested
 | 
						|
    number of bytes from the file at the file's current position and returns
 | 
						|
    them in buf. If the read goes beyond the end of the file, the read
 | 
						|
    length is truncated to the end of the file. The file's current position is
 | 
						|
    increased by the number of bytes returned.
 | 
						|
 | 
						|
    If fildes refers to a directory, the function reads the directory entry at
 | 
						|
    the file's current position and returns the entry in buf. If buf
 | 
						|
    is not large enough to hold the current directory entry, then
 | 
						|
    errno is set to EBUFSIZE, EFIerrno is set to EFI_BUFFER_TOO_SMALL, and the
 | 
						|
    current file position is not updated. The size of the buffer needed to read
 | 
						|
    the entry will be returned as a negative number. On success, the current
 | 
						|
    position is updated to the next directory entry. If there are no more
 | 
						|
    directory entries, the read returns a zero-length buffer.
 | 
						|
    EFI_FILE_INFO is the structure returned as the directory entry.
 | 
						|
 | 
						|
    @param[in]    fildes  Descriptor of the file to be read.
 | 
						|
    @param[out]   buf     Pointer to location in which to store the read data.
 | 
						|
    @param[in]    nbyte   Maximum number of bytes to be read.
 | 
						|
 | 
						|
    @return   Upon successful completion, read() returns a non-negative integer
 | 
						|
              indicating the number of bytes actually read. Otherwise, the
 | 
						|
              functions return a negative value and sets errno to indicate the
 | 
						|
              error.  If errno is EBUFSIZE, the absolute value of the
 | 
						|
              return value indicates the size of the buffer needed to read
 | 
						|
              the directory entry.
 | 
						|
**/
 | 
						|
ssize_t
 | 
						|
read   (int fildes, void *buf, size_t nbyte)
 | 
						|
{
 | 
						|
  struct __filedes *filp;
 | 
						|
  cIIO             *IIO;
 | 
						|
  ssize_t           BufSize;
 | 
						|
 | 
						|
  BufSize = (ssize_t)nbyte;
 | 
						|
  if(BufSize > 0) {
 | 
						|
    if(ValidateFD( fildes, VALID_OPEN)) {
 | 
						|
      filp = &gMD->fdarray[fildes];
 | 
						|
 | 
						|
      IIO = filp->devdata;
 | 
						|
      if(isatty(fildes) && (IIO != NULL)) {
 | 
						|
        BufSize = IIO->Read(filp, nbyte, buf);
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        BufSize = filp->f_ops->fo_read(filp, &filp->f_offset, nbyte, buf);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      errno = EBADF;
 | 
						|
      BufSize = -1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return BufSize;
 | 
						|
}
 | 
						|
 | 
						|
/** Write data to a file.
 | 
						|
 | 
						|
    This function writes the specified number of bytes to the file at the current
 | 
						|
    file position. The current file position is advanced the actual number of bytes
 | 
						|
    written. Partial writes only occur when there has been a data error during
 | 
						|
    the write attempt (such as "volume space full").  The file is automatically
 | 
						|
    grown to hold the data if required.
 | 
						|
 | 
						|
    Direct writes to opened directories are not supported.
 | 
						|
 | 
						|
    If fildes refers to a terminal device, isatty() returns TRUE, a partial write
 | 
						|
    will occur if a NULL or EOF character is encountered before n characters have
 | 
						|
    been written.  Characters inserted due to line-end translations or TAB
 | 
						|
    expansion will not be counted.  Unconvertable characters are translated into
 | 
						|
    the UEFI character BLOCKELEMENT_LIGHT_SHADE.
 | 
						|
 | 
						|
    Since the UEFI console device works on wide characters, the buffer is assumed
 | 
						|
    to contain a byte-oriented multi-byte character stream which is then
 | 
						|
    translated to wide characters using the mbtowc() functions.  The resulting
 | 
						|
    wide character stream is what is actually sent to the UEFI console.
 | 
						|
 | 
						|
    Although both text and binary wide-oriented streams are conceptually
 | 
						|
    sequences of wide characters, the external file associated with a
 | 
						|
    wide-oriented stream is a sequence of multibyte characters,
 | 
						|
    generalized as follows:
 | 
						|
      - Multibyte encodings within files may contain embedded null bytes
 | 
						|
        (unlike multibyte encodings valid for use internal to the program).
 | 
						|
      - A file need not begin nor end in the initial shift state.
 | 
						|
 | 
						|
    @param[in]  fd      Descriptor of file to be written to.
 | 
						|
    @param[in]  buf     Pointer to data to write to the file.
 | 
						|
    @param[in]  nbyte   Number of bytes to be written to the file.
 | 
						|
 | 
						|
    @retval   >=0   Number of bytes actually written to the file.
 | 
						|
    @retval   <0    An error occurred.  More data is provided by errno.
 | 
						|
**/
 | 
						|
ssize_t
 | 
						|
write  (int fd, const void *buf, size_t nbyte)
 | 
						|
{
 | 
						|
  struct __filedes *filp;
 | 
						|
  cIIO             *IIO;
 | 
						|
  ssize_t           BufSize;
 | 
						|
 | 
						|
  BufSize = (ssize_t)nbyte;
 | 
						|
 | 
						|
  if(ValidateFD( fd, VALID_OPEN)) {
 | 
						|
    filp = &gMD->fdarray[fd];
 | 
						|
    if ((filp->Oflags & O_ACCMODE) != 0) {
 | 
						|
      // File is open for writing
 | 
						|
      IIO = filp->devdata;
 | 
						|
      if(isatty(fd) && (IIO != NULL)) {
 | 
						|
        // Output to an Interactive I/O device
 | 
						|
        // (Terminal device or the slave side of a pseudo-tty)
 | 
						|
        BufSize = IIO->Write(filp, buf, nbyte);
 | 
						|
      }
 | 
						|
      else {
 | 
						|
        // Output to a regular file, socket, pipe, etc.
 | 
						|
        BufSize = filp->f_ops->fo_write(filp, &filp->f_offset, nbyte, buf);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else {
 | 
						|
      // File is NOT open for writing
 | 
						|
      errno = EINVAL;
 | 
						|
      BufSize = -1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    // fd is not for a valid open file
 | 
						|
    errno = EBADF;
 | 
						|
    BufSize = -1;
 | 
						|
  }
 | 
						|
  return BufSize;
 | 
						|
}
 | 
						|
 | 
						|
/** Gets the current working directory.
 | 
						|
 | 
						|
  The getcwd() function shall place an absolute pathname of the current
 | 
						|
  working directory in the array pointed to by buf, and return buf.The
 | 
						|
  size argument is the size in bytes of the character array pointed to
 | 
						|
  by the buf argument.
 | 
						|
 | 
						|
  @param[in,out] buf    The buffer to fill.
 | 
						|
  @param[in]     size   The number of bytes in buffer.
 | 
						|
 | 
						|
  @retval NULL          The function failed.  The value in errno provides
 | 
						|
                        further information about the cause of the failure.
 | 
						|
                        Values for errno are:
 | 
						|
                          - EINVAL: buf is NULL or size is zero.
 | 
						|
                          - ENOENT: directory does not exist.
 | 
						|
                          - ERANGE: buf size is too small to hold CWD
 | 
						|
 | 
						|
  @retval buf           The function completed successfully.
 | 
						|
**/
 | 
						|
char
 | 
						|
*getcwd (char *buf, size_t size)
 | 
						|
{
 | 
						|
  CONST CHAR16 *Cwd;
 | 
						|
 | 
						|
  if (size == 0 || buf == NULL) {
 | 
						|
    errno = EINVAL;
 | 
						|
    return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
  Cwd = ShellGetCurrentDir(NULL);
 | 
						|
  if (Cwd == NULL) {
 | 
						|
    errno = ENOENT;
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
  if (size < ((StrLen (Cwd) + 1) * sizeof (CHAR8))) {
 | 
						|
    errno = ERANGE;
 | 
						|
    return (NULL);
 | 
						|
  }
 | 
						|
  return (UnicodeStrToAsciiStr(Cwd, buf));
 | 
						|
}
 | 
						|
 | 
						|
/** Change the current working directory.
 | 
						|
 | 
						|
  The chdir() function shall cause the directory named by the pathname
 | 
						|
  pointed to by the path argument to become the current working directory;
 | 
						|
  that is, the starting point for path searches for pathnames not beginning
 | 
						|
  with '/'.
 | 
						|
 | 
						|
  @param[in] path   The new path to set.
 | 
						|
 | 
						|
  @retval   0   Operation completed successfully.
 | 
						|
  @retval  -1   Function failed.  The value in errno provides more
 | 
						|
                information on the cause of failure:
 | 
						|
                  - EPERM: Operation not supported with this Shell version.
 | 
						|
                  - ENOMEM: Unable to allocate memory.
 | 
						|
                  - ENOENT: Target directory does not exist.
 | 
						|
 | 
						|
  @todo Add non-NEW-shell CWD changing.
 | 
						|
**/
 | 
						|
int
 | 
						|
chdir (const char *path)
 | 
						|
{
 | 
						|
  CONST CHAR16 *Cwd;
 | 
						|
  EFI_STATUS   Status;
 | 
						|
  CHAR16       *UnicodePath;
 | 
						|
 | 
						|
  /* Old Shell does not support Set Current Dir. */
 | 
						|
  if(gEfiShellProtocol != NULL) {
 | 
						|
    Cwd = ShellGetCurrentDir(NULL);
 | 
						|
    if (Cwd != NULL) {
 | 
						|
      /* We have shell support */
 | 
						|
      UnicodePath = AllocatePool(((AsciiStrLen (path) + 1) * sizeof (CHAR16)));
 | 
						|
      if (UnicodePath == NULL) {
 | 
						|
        errno = ENOMEM;
 | 
						|
        return -1;
 | 
						|
      }
 | 
						|
      AsciiStrToUnicodeStr(path, UnicodePath);
 | 
						|
      Status = gEfiShellProtocol->SetCurDir(NULL, UnicodePath);
 | 
						|
      FreePool(UnicodePath);
 | 
						|
      if (EFI_ERROR(Status)) {
 | 
						|
        errno = ENOENT;
 | 
						|
        return -1;
 | 
						|
      } else {
 | 
						|
        return 0;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  /* Add here for non-shell */
 | 
						|
  errno = EPERM;
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
 | 
						|
/** Get the foreground process group ID associated with a terminal.
 | 
						|
 | 
						|
    Just returns the Image Handle for the requestor since UEFI does not have
 | 
						|
    a concept of processes or groups.
 | 
						|
 | 
						|
    @param[in]    x   Ignored.
 | 
						|
 | 
						|
    @return   Returns the Image Handle of the application or driver which
 | 
						|
              called this function.
 | 
						|
**/
 | 
						|
pid_t tcgetpgrp (int x)
 | 
						|
{
 | 
						|
  return ((pid_t)(UINTN)(gImageHandle));
 | 
						|
}
 | 
						|
 | 
						|
/** Get the process group ID of the calling process.
 | 
						|
 | 
						|
    Just returns the Image Handle for the requestor since UEFI does not have
 | 
						|
    a concept of processes or groups.
 | 
						|
 | 
						|
    @return   Returns the Image Handle of the application or driver which
 | 
						|
              called this function.
 | 
						|
**/
 | 
						|
pid_t getpgrp(void)
 | 
						|
{
 | 
						|
  return ((pid_t)(UINTN)(gImageHandle));
 | 
						|
}
 | 
						|
 | 
						|
/* Internal worker function for utimes.
 | 
						|
    This works around an error produced by GCC when the va_* macros
 | 
						|
    are used within a function with a fixed number of arguments.
 | 
						|
*/
 | 
						|
static
 | 
						|
int
 | 
						|
EFIAPI
 | 
						|
va_Utimes(
 | 
						|
  const char   *path,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  struct __filedes   *filp;
 | 
						|
  va_list             ap;
 | 
						|
  int                 fd;
 | 
						|
  int                 retval  = -1;
 | 
						|
 | 
						|
  va_start(ap, path);
 | 
						|
  fd = open(path, O_RDWR, 0);
 | 
						|
  if(fd >= 0) {
 | 
						|
    filp = &gMD->fdarray[fd];
 | 
						|
    retval = filp->f_ops->fo_ioctl( filp, FIOSETIME, ap);
 | 
						|
    close(fd);
 | 
						|
  }
 | 
						|
  va_end(ap);
 | 
						|
  return retval;
 | 
						|
}
 | 
						|
 | 
						|
/** Set file access and modification times.
 | 
						|
 | 
						|
    @param[in]  path    Path to the file to be modified.
 | 
						|
    @param[in]  times   Pointer to an array of two timeval structures
 | 
						|
 | 
						|
    @retval   0     File times successfully set.
 | 
						|
    @retval   -1    An error occured.  Error type in errno.
 | 
						|
**/
 | 
						|
int
 | 
						|
utimes(
 | 
						|
  const char *path,
 | 
						|
  const struct timeval *times
 | 
						|
  )
 | 
						|
{
 | 
						|
  return va_Utimes(path, times);
 | 
						|
}
 |