Include/ctype.h:             Function declaration and Macro definition of isDirSep
Include/unistd.h:            Declarations added from EfiSysCall.h
Include/utime.h:             New file.  For the Posix utime() function.
Include/sys/_ctype.h:        Update character class bit maps.
Include/sys/EfiSysCall.h:    Move declarations to unistd.h
Include/sys/fcntl.h:         Improve comments.  Add UEFI-specific macros.
Include/sys/filio.h:         Remove declarations for unsupported file ioctls.
Include/sys/stat.h:          Fix flags.  Add macros and declarations.
Include/sys/time.h:          Add declarations for new functions Tm2Efi() and Time2Efi().
Include/sys/types.h:         Use EFI-specific instead of BSD-specific definitions for typedefs.
Include/sys/unistd.h:        Delete inappropriate content.  Guard macro definitions.
LibC/Locale/setlocale.c
LibC/Stdio/{fdopen.c, findfp.c, fopen.c, freopen.c, gettemp.c, makebuf.c, mktemp.c,
            remove.c, stdio.c, tempnam.c, tmpfile.c, tmpnam.c}
LibC/Time/{itimer.c, ZoneProc.c}
LibC/Uefi/SysCalls.c
LibC/Uefi/Devices/Console/daConsole.c
LibC/Uefi/Devices/UefiShell/daShell.c
PosixLib/Gen/readdir.c
                             Include unistd.h instead of EfiSysCall.h
LibC/Ctype/CClass.c:         Character classification function implementation for isDirSep.
LibC/Ctype/iCtype.c:         Update character classification and case conversion tables.
LibC/Time/TimeEfi.c:         Improve comments.  Implement new functions Tm2Efi() and Time2Efi().
LibC/Uefi/StubFunctions.c:   Add missing include.  Cosmetic changes to declarations.
LibC/Uefi/SysCalls.c:        Add support function for utime().
LibC/Uefi/Uefi.inf:          Add LibGen library class dependency.
LibC/Uefi/Xform.c:           Enhance Omode2EFI().
LibC/Uefi/Devices/UefiShell/daShell.c:    Enhance da_ShellMkdir.  Implement da_ShellIoctl to set file times.
PosixLib/Gen/access.c:       New file.  Implement the access() function.
PosixLib/Gen/dirname.c:      Enhance to use isDirSep and differentiate between the device, path, and filename components of UEFI Shell-style paths.
PosixLib/Gen/utime.c:        New file.  Implement the utime() function.
PosixLib/Gen/LibGen.inf:     Change MODULE_TYPE.  Add new files.
Signed-off-by: darylm503
Reviewed-by: geekboy15a
Reviewed-by: jljusten
Reviewed-by: Rahul Khana
Reviewed-by: leegrosenbaum
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12800 6f19259b-4bc3-4df7-8a09-765794883524
		
	
		
			
				
	
	
		
			612 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			612 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Abstract device driver for the UEFI Console.
 | |
| 
 | |
|   Manipulates abstractions for stdin, stdout, stderr.
 | |
| 
 | |
|   Copyright (c) 2010 - 2011, 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.php.
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| #include  <Uefi.h>
 | |
| #include  <Library/BaseLib.h>
 | |
| #include  <Library/MemoryAllocationLib.h>
 | |
| #include  <Library/UefiBootServicesTableLib.h>
 | |
| #include  <Protocol/SimpleTextIn.h>
 | |
| #include  <Protocol/SimpleTextOut.h>
 | |
| 
 | |
| #include  <LibConfig.h>
 | |
| 
 | |
| #include  <errno.h>
 | |
| #include  <wctype.h>
 | |
| #include  <wchar.h>
 | |
| #include  <stdarg.h>
 | |
| #include  <sys/fcntl.h>
 | |
| #include  <unistd.h>
 | |
| #include  <kfile.h>
 | |
| #include  <Device/Device.h>
 | |
| #include  <MainData.h>
 | |
| 
 | |
| static const CHAR16* const
 | |
| stdioNames[NUM_SPECIAL]   = {
 | |
|   L"stdin:", L"stdout:", L"stderr:"
 | |
| };
 | |
| 
 | |
| static const int stdioFlags[NUM_SPECIAL] = {
 | |
|   O_RDONLY,             // stdin
 | |
|   O_WRONLY,             // stdout
 | |
|   O_WRONLY              // stderr
 | |
| };
 | |
| 
 | |
| static DeviceNode    *ConNode[NUM_SPECIAL];
 | |
| static ConInstance   *ConInstanceList;
 | |
| 
 | |
| static wchar_t       *ConReadBuf;
 | |
| 
 | |
| /* Flags settable by Ioctl */
 | |
| static BOOLEAN        TtyCooked;
 | |
| static BOOLEAN        TtyEcho;
 | |
| 
 | |
| ssize_t
 | |
| WideTtyCvt( CHAR16 *dest, const char *buf, size_t n)
 | |
| {
 | |
|   UINTN   i;
 | |
|   wint_t  wc;
 | |
| 
 | |
|   for(i = 0; i < n; ++i) {
 | |
|     wc = btowc(*buf++);
 | |
|     if( wc == 0) {
 | |
|       break;
 | |
|     };
 | |
|     if(wc < 0) {
 | |
|       wc = BLOCKELEMENT_LIGHT_SHADE;
 | |
|     }
 | |
|     if(wc == L'\n') {
 | |
|       *dest++ = L'\r';
 | |
|     }
 | |
|     *dest++ = (CHAR16)wc;
 | |
|   }
 | |
|   *dest = 0;
 | |
|   return (ssize_t)i;
 | |
| }
 | |
| 
 | |
| static
 | |
| int
 | |
| EFIAPI
 | |
| da_ConClose(
 | |
|   IN      struct __filedes   *filp
 | |
| )
 | |
| {
 | |
|   ConInstance    *Stream;
 | |
| 
 | |
|   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
 | |
|   // Quick check to see if Stream looks reasonable
 | |
|   if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     return -1;    // Looks like a bad File Descriptor pointer
 | |
|   }
 | |
|   gMD->StdIo[Stream->InstanceNum] = NULL;   // Mark the stream as closed
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| static
 | |
| off_t
 | |
| EFIAPI
 | |
| da_ConSeek(
 | |
|   struct __filedes   *filp,
 | |
|   off_t               Position,
 | |
|   int                 whence      ///< Ignored by Console
 | |
| )
 | |
| {
 | |
|   ConInstance                       *Stream;
 | |
|   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *Proto;
 | |
|   XYoffset                           CursorPos;
 | |
| 
 | |
|   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
 | |
|   // Quick check to see if Stream looks reasonable
 | |
|   if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     return -1;    // Looks like a bad This pointer
 | |
|   }
 | |
|   if(Stream->InstanceNum == STDIN_FILENO) {
 | |
|     // Seek is not valid for stdin
 | |
|     EFIerrno = RETURN_UNSUPPORTED;
 | |
|     return -1;
 | |
|   }
 | |
|   // Everything is OK to do the final verification and "seek".
 | |
|   Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;
 | |
|   CursorPos.Offset = Position;
 | |
| 
 | |
|   EFIerrno = Proto->SetCursorPosition(Proto,
 | |
|                                       (INTN)CursorPos.XYpos.Column,
 | |
|                                       (INTN)CursorPos.XYpos.Row);
 | |
| 
 | |
|   if(RETURN_ERROR(EFIerrno)) {
 | |
|     return -1;
 | |
|   }
 | |
|   else {
 | |
|     return Position;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* Write a NULL terminated WCS to the EFI console.
 | |
| 
 | |
|   @param[in,out]  BufferSize  Number of bytes in Buffer.  Set to zero if
 | |
|                               the string couldn't be displayed.
 | |
|   @param[in]      Buffer      The WCS string to be displayed
 | |
| 
 | |
|   @return   The number of characters written.
 | |
| */
 | |
| static
 | |
| ssize_t
 | |
| EFIAPI
 | |
| da_ConWrite(
 | |
|   IN  struct __filedes     *filp,
 | |
|   IN  off_t                *Position,
 | |
|   IN  size_t                BufferSize,
 | |
|   IN  const void           *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                          Status;
 | |
|   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *Proto;
 | |
|   ConInstance                        *Stream;
 | |
|   ssize_t                             NumChar;
 | |
|   //XYoffset                            CursorPos;
 | |
| 
 | |
|   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
 | |
|   // Quick check to see if Stream looks reasonable
 | |
|   if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     return -1;    // Looks like a bad This pointer
 | |
|   }
 | |
|   if(Stream->InstanceNum == STDIN_FILENO) {
 | |
|     // Write is not valid for stdin
 | |
|     EFIerrno = RETURN_UNSUPPORTED;
 | |
|     return -1;
 | |
|   }
 | |
|   // Everything is OK to do the write.
 | |
|   Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;
 | |
| 
 | |
|   // Convert string from MBCS to WCS and translate \n to \r\n.
 | |
|   NumChar = WideTtyCvt(gMD->UString, (const char *)Buffer, BufferSize);
 | |
|   //if(NumChar > 0) {
 | |
|   //  BufferSize = (size_t)(NumChar * sizeof(CHAR16));
 | |
|   //}
 | |
|   BufferSize = NumChar;
 | |
| 
 | |
|   //if( Position != NULL) {
 | |
|   //  CursorPos.Offset = (UINT64)*Position;
 | |
| 
 | |
|   //  Status = Proto->SetCursorPosition(Proto,
 | |
|   //                                    (INTN)CursorPos.XYpos.Column,
 | |
|   //                                    (INTN)CursorPos.XYpos.Row);
 | |
|   //  if(RETURN_ERROR(Status)) {
 | |
|   //    return -1;
 | |
|   //  }
 | |
|   //}
 | |
| 
 | |
|   // Send the Unicode buffer to the console
 | |
|   Status = Proto->OutputString( Proto, gMD->UString);
 | |
|   // Depending on status, update BufferSize and return
 | |
|   if(RETURN_ERROR(Status)) {
 | |
|     BufferSize = 0;    // We don't really know how many characters made it out
 | |
|   }
 | |
|   else {
 | |
|     //BufferSize = NumChar;
 | |
|     Stream->NumWritten += NumChar;
 | |
|   }
 | |
|   EFIerrno = Status;
 | |
|   return BufferSize;
 | |
| }
 | |
| 
 | |
| /** Read characters from the console input device.
 | |
| 
 | |
|     @param[in,out]  filp          Pointer to file descriptor for this file.
 | |
|     @param[in,out]  offset        Ignored.
 | |
|     @param[in]      BufferSize    Buffer size, in bytes.
 | |
|     @param[out]     Buffer        Buffer in which to place the read characters.
 | |
| 
 | |
|     @return     Number of bytes actually placed into Buffer.
 | |
| 
 | |
|     @todo       Handle encodings other than ASCII-7 and UEFI.
 | |
| **/
 | |
| static
 | |
| ssize_t
 | |
| EFIAPI
 | |
| da_ConRead(
 | |
|   IN OUT  struct __filedes   *filp,
 | |
|   IN OUT  off_t              *offset,         // Console ignores this
 | |
|   IN      size_t              BufferSize,
 | |
|      OUT  VOID               *Buffer
 | |
| )
 | |
| {
 | |
|   EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *Proto;
 | |
|   ConInstance                      *Stream;
 | |
|   wchar_t                          *OutPtr;
 | |
|   EFI_INPUT_KEY                     Key;
 | |
|   UINTN                             NumChar;
 | |
|   UINTN                             Edex;
 | |
|   EFI_STATUS                        Status = RETURN_SUCCESS;
 | |
|   UINTN                             i;
 | |
|   char                              EchoBuff[MB_CUR_MAX + 1];
 | |
|   int                               NumEcho;
 | |
| 
 | |
|   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
 | |
|   // Quick check to see if Stream looks reasonable
 | |
|   if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     return -1;    // Looks like a bad This pointer
 | |
|   }
 | |
|   if(Stream->InstanceNum != STDIN_FILENO) {
 | |
|     // Read only valid for stdin
 | |
|     EFIerrno = RETURN_UNSUPPORTED;
 | |
|     return -1;
 | |
|   }
 | |
|   // It looks like things are OK for trying to read
 | |
|   // We will accumulate *BufferSize characters or until we encounter
 | |
|   // an "activation" character.  Currently any control character.
 | |
|   Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
 | |
|   OutPtr = ConReadBuf;
 | |
|   NumChar = (BufferSize > MAX_INPUT)? MAX_INPUT : BufferSize;
 | |
|   i = 0;
 | |
|   do {
 | |
|     if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
 | |
|       Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
 | |
|       if(Status != RETURN_SUCCESS) {
 | |
|         break;
 | |
|       }
 | |
|       Status = Proto->ReadKeyStroke(Proto, &Key);
 | |
|       if(Status != RETURN_SUCCESS) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     else {
 | |
|       Key.ScanCode          = Stream->UnGetKey.ScanCode;
 | |
|       Key.UnicodeChar       = Stream->UnGetKey.UnicodeChar;
 | |
|       Stream->UnGetKey.ScanCode     = SCAN_NULL;
 | |
|       Stream->UnGetKey.UnicodeChar  = CHAR_NULL;
 | |
|     }
 | |
|     if(Key.ScanCode == SCAN_NULL) {
 | |
|       NumEcho = 0;
 | |
|       if(TtyCooked && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
 | |
|         *OutPtr++ = CHAR_LINEFEED;
 | |
|         NumEcho = wctomb(EchoBuff, CHAR_LINEFEED);
 | |
|       }
 | |
|       else {
 | |
|         *OutPtr++ = Key.UnicodeChar;
 | |
|         NumEcho = wctomb(EchoBuff, Key.UnicodeChar);
 | |
|       }
 | |
|       ++i;
 | |
|       EchoBuff[NumEcho] = 0;  /* Terminate the Echo buffer */
 | |
|       if(TtyEcho) {
 | |
|         /* Echo the character just input */
 | |
|         da_ConWrite(&gMD->fdarray[STDOUT_FILENO], NULL, 2, EchoBuff);
 | |
|       }
 | |
|     }
 | |
|     if(iswcntrl(Key.UnicodeChar)) {    // If a control character, or a scan code
 | |
|       break;
 | |
|     }
 | |
|   } while(i < NumChar);
 | |
| 
 | |
|   *OutPtr = L'\0';    // Terminate the input buffer
 | |
| 
 | |
|   /*  Convert the input buffer and place in Buffer.
 | |
|       If the fully converted input buffer won't fit, write what will and
 | |
|       leave the rest in ConReadBuf with ConReadLeft indicating how many
 | |
|       unconverted characters remain in ConReadBuf.
 | |
|   */
 | |
|   NumEcho = (int)wcstombs(Buffer, ConReadBuf, BufferSize);   /* Re-use NumEcho to hold number of bytes in Buffer */
 | |
|   /* More work needs to be done before locales other than C can be supported. */
 | |
| 
 | |
|   EFIerrno = Status;
 | |
|   return (ssize_t)NumEcho;  // Will be 0 if we didn't get a key
 | |
| }
 | |
| 
 | |
| /** Console-specific helper function for the fstat() function.
 | |
| 
 | |
|     st_size       Set to number of characters read for stdin and number written for stdout and stderr.
 | |
|     st_physsize   1 for stdin, 0 if QueryMode error, else max X and Y coordinates for the current mode.
 | |
|     st_curpos     0 for stdin, current X & Y coordinates for stdout and stderr
 | |
|     st_blksize    Set to 1 since this is a character device
 | |
| 
 | |
|     All other members of the stat structure are left unchanged.
 | |
| **/
 | |
| static
 | |
| int
 | |
| EFIAPI
 | |
| da_ConStat(
 | |
|   struct __filedes   *filp,
 | |
|   struct stat        *Buffer,
 | |
|   void               *Something
 | |
|   )
 | |
| {
 | |
|   ConInstance                        *Stream;
 | |
|   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *Proto;
 | |
|   XYoffset                            CursorPos;
 | |
|   INT32                               OutMode;
 | |
|   UINTN                               ModeCol;
 | |
|   UINTN                               ModeRow;
 | |
| 
 | |
| // ConGetInfo
 | |
|   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
 | |
|   // Quick check to see if Stream looks reasonable
 | |
|   if ((Stream->Cookie != CON_COOKIE) ||    // Cookie == 'IoAb'
 | |
|       (Buffer == NULL))
 | |
|   {
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     return -1;
 | |
|   }
 | |
|   // All of our parameters are correct, so fill in the information.
 | |
|   Buffer->st_blksize = 1;
 | |
| 
 | |
| // ConGetPosition
 | |
|   if(Stream->InstanceNum == STDIN_FILENO) {
 | |
|     // This is stdin
 | |
|     Buffer->st_curpos    = 0;
 | |
|     Buffer->st_size      = (off_t)Stream->NumRead;
 | |
|     Buffer->st_physsize  = 1;
 | |
|   }
 | |
|   else {
 | |
|     Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)Stream->Dev;
 | |
|     CursorPos.XYpos.Column  = (UINT32)Proto->Mode->CursorColumn;
 | |
|     CursorPos.XYpos.Row     = (UINT32)Proto->Mode->CursorRow;
 | |
|     Buffer->st_curpos       = (off_t)CursorPos.Offset;
 | |
|     Buffer->st_size         = (off_t)Stream->NumWritten;
 | |
| 
 | |
|     OutMode  = Proto->Mode->Mode;
 | |
|     EFIerrno = Proto->QueryMode(Proto, (UINTN)OutMode, &ModeCol, &ModeRow);
 | |
|     if(RETURN_ERROR(EFIerrno)) {
 | |
|       Buffer->st_physsize = 0;
 | |
|     }
 | |
|     else {
 | |
|       CursorPos.XYpos.Column  = (UINT32)ModeCol;
 | |
|       CursorPos.XYpos.Row     = (UINT32)ModeRow;
 | |
|       Buffer->st_physsize     = (off_t)CursorPos.Offset;
 | |
|     }
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| static
 | |
| int
 | |
| EFIAPI
 | |
| da_ConIoctl(
 | |
|   struct __filedes   *filp,
 | |
|   ULONGN              cmd,
 | |
|   va_list             argp
 | |
|   )
 | |
| {
 | |
|   return -EPERM;
 | |
| }
 | |
| 
 | |
| /** Open an abstract Console Device.
 | |
| **/
 | |
| int
 | |
| EFIAPI
 | |
| da_ConOpen(
 | |
|   DeviceNode         *DevNode,
 | |
|   struct __filedes   *filp,
 | |
|   int                 DevInstance,    // Not used for console devices
 | |
|   wchar_t            *Path,           // Not used for console devices
 | |
|   wchar_t            *MPath           // Not used for console devices
 | |
|   )
 | |
| {
 | |
|   ConInstance                      *Stream;
 | |
| 
 | |
|   if((filp == NULL)           ||
 | |
|      (DevNode  == NULL))
 | |
|   {
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     errno = EINVAL;
 | |
|     return -1;
 | |
|   }
 | |
|   Stream = (ConInstance *)DevNode->InstanceList;
 | |
|   // Quick check to see if Stream looks reasonable
 | |
|   if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     errno = EINVAL;
 | |
|     return -1;    // Looks like a bad This pointer
 | |
|   }
 | |
|   gMD->StdIo[Stream->InstanceNum] = Stream;
 | |
|   filp->f_iflags |= (S_IFREG | _S_IFCHR | _S_ICONSOLE);
 | |
|   filp->f_offset = 0;
 | |
|   filp->f_ops = &Stream->Abstraction;
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| #include  <sys/poll.h>
 | |
| /*  Returns a bit mask describing which operations could be completed immediately.
 | |
| 
 | |
|     (POLLIN | POLLRDNORM)   A Unicode character is available to read
 | |
|     (POLLIN)                A ScanCode is ready.
 | |
|     (POLLOUT)               The device is ready for output - always set on stdout and stderr.
 | |
| 
 | |
| */
 | |
| static
 | |
| short
 | |
| EFIAPI
 | |
| da_ConPoll(
 | |
|   struct __filedes   *filp,
 | |
|   short              events
 | |
|   )
 | |
| {
 | |
|   EFI_SIMPLE_TEXT_INPUT_PROTOCOL   *Proto;
 | |
|   ConInstance                      *Stream;
 | |
|   EFI_STATUS                        Status = RETURN_SUCCESS;
 | |
|   short                             RdyMask = 0;
 | |
| 
 | |
|   Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
 | |
|   // Quick check to see if Stream looks reasonable
 | |
|   if(Stream->Cookie != CON_COOKIE) {    // Cookie == 'IoAb'
 | |
|     EFIerrno = RETURN_INVALID_PARAMETER;
 | |
|     return POLLNVAL;    // Looks like a bad filp pointer
 | |
|   }
 | |
|   if(Stream->InstanceNum == 0) {
 | |
|     // Only input is supported for this device
 | |
|     Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
 | |
|     if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
 | |
|       Status = Proto->ReadKeyStroke(Proto, &Stream->UnGetKey);
 | |
|       if(Status == RETURN_SUCCESS) {
 | |
|         RdyMask = POLLIN;
 | |
|         if(Stream->UnGetKey.UnicodeChar != CHAR_NULL) {
 | |
|           RdyMask |= POLLRDNORM;
 | |
|         }
 | |
|       }
 | |
|       else {
 | |
|         Stream->UnGetKey.ScanCode     = SCAN_NULL;
 | |
|         Stream->UnGetKey.UnicodeChar  = CHAR_NULL;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   else if(Stream->InstanceNum < NUM_SPECIAL) {  // Not 0, is it 1 or 2?
 | |
|     // Only output is supported for this device
 | |
|     RdyMask = POLLOUT;
 | |
|   }
 | |
|   else {
 | |
|     RdyMask = POLLERR;    // Not one of the standard streams
 | |
|   }
 | |
|   EFIerrno = Status;
 | |
| 
 | |
|   return (RdyMask & (events | POLL_RETONLY));
 | |
| }
 | |
| 
 | |
| /** Construct the Console stream devices: stdin, stdout, stderr.
 | |
| 
 | |
|     Allocate the instance structure and populate it with the information for
 | |
|     each stream device.
 | |
| **/
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| __Cons_construct(
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
| )
 | |
| {
 | |
|   ConInstance    *Stream;
 | |
|   RETURN_STATUS   Status = RETURN_SUCCESS;
 | |
|   int             i;
 | |
| 
 | |
|   ConInstanceList = (ConInstance *)AllocateZeroPool(NUM_SPECIAL * sizeof(ConInstance));
 | |
|   ConReadBuf      = (wchar_t *)AllocateZeroPool((MAX_INPUT + 1) * sizeof(wchar_t));
 | |
|   if((ConInstanceList == NULL) || (ConReadBuf == NULL))  {
 | |
|     return RETURN_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   for( i = 0; i < NUM_SPECIAL; ++i) {
 | |
|     // Get pointer to instance.
 | |
|     Stream = &ConInstanceList[i];
 | |
| 
 | |
|     Stream->Cookie      = CON_COOKIE;
 | |
|     Stream->InstanceNum = i;
 | |
| 
 | |
|     switch(i) {
 | |
|       case STDIN_FILENO:
 | |
|         Stream->Dev = SystemTable->ConIn;
 | |
|         break;
 | |
|       case STDOUT_FILENO:
 | |
|         Stream->Dev = SystemTable->ConOut;
 | |
|         break;
 | |
|       case STDERR_FILENO:
 | |
|         if(SystemTable->StdErr == NULL) {
 | |
|           Stream->Dev = SystemTable->ConOut;
 | |
|         }
 | |
|         else {
 | |
|           Stream->Dev = SystemTable->StdErr;
 | |
|         }
 | |
|         break;
 | |
|       default:
 | |
|         return RETURN_VOLUME_CORRUPTED;     // This is a "should never happen" case.
 | |
|     }
 | |
| 
 | |
|     Stream->Abstraction.fo_close    = &da_ConClose;
 | |
|     Stream->Abstraction.fo_read     = &da_ConRead;
 | |
|     Stream->Abstraction.fo_write    = &da_ConWrite;
 | |
|     Stream->Abstraction.fo_stat     = &da_ConStat;
 | |
|     Stream->Abstraction.fo_lseek    = &da_ConSeek;
 | |
|     Stream->Abstraction.fo_fcntl    = &fnullop_fcntl;
 | |
|     Stream->Abstraction.fo_ioctl    = &da_ConIoctl;
 | |
|     Stream->Abstraction.fo_poll     = &da_ConPoll;
 | |
|     Stream->Abstraction.fo_flush    = &fnullop_flush;
 | |
|     Stream->Abstraction.fo_delete   = &fbadop_delete;
 | |
|     Stream->Abstraction.fo_mkdir    = &fbadop_mkdir;
 | |
|     Stream->Abstraction.fo_rmdir    = &fbadop_rmdir;
 | |
|     Stream->Abstraction.fo_rename   = &fbadop_rename;
 | |
| 
 | |
|     Stream->NumRead     = 0;
 | |
|     Stream->NumWritten  = 0;
 | |
|     Stream->UnGetKey.ScanCode     = SCAN_NULL;
 | |
|     Stream->UnGetKey.UnicodeChar  = CHAR_NULL;
 | |
| 
 | |
|     if(Stream->Dev == NULL) {
 | |
|       continue;                 // No device for this stream.
 | |
|     }
 | |
|     ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream, 1, sizeof(ConInstance), stdioFlags[i]);
 | |
|     if(ConNode[i] == NULL) {
 | |
|       Status = EFIerrno;
 | |
|       break;
 | |
|     }
 | |
|     Stream->Parent = ConNode[i];
 | |
|   }
 | |
|   /* Initialize Ioctl flags until Ioctl is really implemented. */
 | |
|   TtyCooked = TRUE;
 | |
|   TtyEcho   = TRUE;
 | |
| 
 | |
|   return  Status;
 | |
| }
 | |
| 
 | |
| RETURN_STATUS
 | |
| EFIAPI
 | |
| __Cons_deconstruct(
 | |
|   IN EFI_HANDLE        ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE  *SystemTable
 | |
| )
 | |
| {
 | |
|   int   i;
 | |
| 
 | |
|   for(i = 0; i < NUM_SPECIAL; ++i) {
 | |
|     if(ConNode[i] != NULL) {
 | |
|       FreePool(ConNode[i]);
 | |
|     }
 | |
|   }
 | |
|   if(ConInstanceList != NULL) {
 | |
|     FreePool(ConInstanceList);
 | |
|   }
 | |
|   if(ConReadBuf != NULL) {
 | |
|     FreePool(ConReadBuf);
 | |
|   }
 | |
| 
 | |
|   return RETURN_SUCCESS;
 | |
| }
 | |
| 
 | |
| /* ######################################################################### */
 | |
| #if 0 /* Not implemented for Console */
 | |
| 
 | |
| static
 | |
| int
 | |
| EFIAPI
 | |
| da_ConCntl(
 | |
|   struct __filedes *filp,
 | |
|   UINT32,
 | |
|   void *,
 | |
|   void *
 | |
|   )
 | |
| {
 | |
| }
 | |
| 
 | |
| static
 | |
| int
 | |
| EFIAPI
 | |
| da_ConFlush(
 | |
|   struct __filedes *filp
 | |
|   )
 | |
| {
 | |
|   return 0;
 | |
| }
 | |
| #endif  /* Not implemented for Console */
 |