StdLib: Add terminal type line editing (Interactive IO) for console devices.

Adds a subset of the terminal I/O capabilities described in the Single Unix Specification, V4.
Supports:
    Erase previous character.  Default is Backspace or ^H
    Erase line.  Default is ^U
TAB characters are supported and, by default, are rendered as 8 spaces.  They will still be read as a single TAB character.
Both Canonical and Non-Canonical modes are supported.
If a terminal device is opened with O_TTY_INIT in the mode, the device will be initialized to "sane" values for interactive use.  It will be in Canonical mode, Enter will be translated to NewLine and on output, a NewLine is translated to CRLF.  Echoing will be on, control characters are output as ^X, and TABs are expanded.
See the new <sys/termios.h> file for more information.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by:  daryl.mcdaniel@intel.com
Reviewed-by:    erik.c.bjorge@intel.com
Reviewed-by:    leroy.p.leahy@intel.com
Reviewed-by:    lee.g.rosenbaum@intel.com
Reviewed-by:    jaben.carsey@intel.com





git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13989 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
darylm503 2012-12-11 21:19:14 +00:00
parent e575c101d8
commit 6c6c850ad6
23 changed files with 3404 additions and 218 deletions

View File

@ -0,0 +1,206 @@
/** @file
Class for arbitrary sized FIFO queues.
Copyright (c) 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 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.
**/
#ifndef _FIFO_CLASS_H
#define _FIFO_CLASS_H
#include <Uefi.h>
#include <wchar.h>
#include <Containers/ModuloUtil.h>
#include <sys/types.h>
__BEGIN_DECLS
typedef struct _FIFO_CLASS cFIFO;
/// Constants to select what is counted by the FIFO_NumInQueue function.
typedef enum {
AsElements, ///< Count the number of readable elements in the queue.
AsBytes ///< Count the number of readable bytes in the queue.
} FIFO_ElemBytes;
/** Construct a new instance of a FIFO Queue.
@param[in] NumElements Number of elements to be contained in the new FIFO.
@param[in] ElementSize Size, in bytes, of an element
@retval NULL Unable to create the instance.
@retval NonNULL Pointer to the new FIFO instance.
**/
cFIFO * EFIAPI New_cFIFO(UINT32 NumElements, size_t ElementSize);
/** Add one or more elements to the FIFO.
This function allows one to add one or more elements, as specified by Count,
to the FIFO. Each element is of the size specified when the FIFO object
was instantiated (FIFO.ElementSize).
pElement points to the first byte of the first element to be added.
If multiple elements are to be added, the elements are expected to be
organized as a packed array.
@param[in] Self Pointer to the FIFO instance.
@param[in] pElement Pointer to the element(s) to enqueue (add).
@param[in] Count Number of elements to add.
@retval 0 The FIFO is full.
@retval >=0 The number of elements added to the FIFO.
**/
typedef size_t (EFIAPI *cFIFO_Enqueue) (cFIFO *Self, const void *ElementPointer, size_t Count);
/** Read or copy elements from the FIFO.
This function allows one to read one or more elements, as specified by Count,
from the FIFO. Each element is of the size specified when the FIFO object
was instantiated (FIFO.ElementSize).
pElement points to the destination of the first byte of the first element
to be read. If multiple elements are to be read, the elements are expected
to be organized as a packed array.
@param[in] Self Pointer to the FIFO instance.
@param[out] pElement Pointer to where to store the element(s) read from the FIFO.
@param[in] Count Number of elements to dequeue.
@param[in] Consume If TRUE, consume read elements. Otherwise, preserve.
@retval 0 The FIFO is empty.
@retval >=0 The number of elements read from the FIFO.
**/
typedef size_t (EFIAPI *cFIFO_Dequeue) (cFIFO *Self, void *ElementPointer, size_t Count);
/** Make a copy of the FIFO's data.
The contents of the FIFO is copied out and linearized without affecting the
FIFO contents.
@param[in] Self Pointer to the FIFO instance.
@param[out] ElementPointer Pointer to where to store the elements copied from the FIFO.
@param[in] Count Number of elements to copy.
@retval 0 The FIFO is empty.
@retval >=0 The number of elements copied from the FIFO.
**/
typedef size_t (EFIAPI *cFIFO_Copy) (cFIFO *Self, void *ElementPointer, size_t Count);
/** Test whether the FIFO is empty.
@param[in] Self Pointer to the FIFO instance.
@retval TRUE The FIFO is empty.
@retval FALSE The FIFO is NOT empty.
**/
typedef BOOLEAN (EFIAPI *cFIFO_IsEmpty) (cFIFO *Self);
/** Test whether the FIFO is full.
@param[in] Self Pointer to the FIFO instance.
@retval TRUE The FIFO is full.
@retval FALSE The FIFO is NOT full.
**/
typedef BOOLEAN (EFIAPI *cFIFO_IsFull) (cFIFO *Self);
/** Determine number of items available to read from the FIFO.
The number of items are either the number of bytes, or the number of elements
depending upon the value of the As enumerator.
@param[in] Self Pointer to the FIFO instance.
@param[in] As An enumeration variable whose value determines whether the
returned value is the number of bytes or the number of elements
currently contained by the FIFO.
@retval 0 The FIFO is empty.
@retval >=0 The number of items contained in the FIFO.
**/
typedef size_t (EFIAPI *cFIFO_NumInQueue) (cFIFO *Self, FIFO_ElemBytes As);
/** Determine amount of free space in the FIFO that can be written into.
The number of items are either the number of bytes, or the number of elements
depending upon the value of the As enumerator.
@param[in] Self Pointer to the FIFO instance.
@param[in] As An enumeration variable whose value determines whether the
returned value is the number of bytes or the number of elements
currently available in the FIFO.
@retval 0 The FIFO is full.
@retval >=0 The number of items which can be accepted by the FIFO.
**/
typedef size_t (EFIAPI *cFIFO_FreeSpace) (cFIFO *Self, FIFO_ElemBytes As);
/** Empty the FIFO, discarding up to NumToFlush elements.
@param[in] Self Pointer to the FIFO instance.
@param[in] NumToFlush Number of elements to flush from the FIFO.
If larger than the number of elements in the
FIFO, the FIFO is emptied.
@return Returns the number of elements remaining in the FIFO after the flush.
**/
typedef size_t (EFIAPI *cFIFO_Flush) (cFIFO *Self, size_t NumToFlush);
/** Remove the most recent element from the FIFO.
@param[in] Self Pointer to the FIFO instance.
**/
typedef void (EFIAPI *cFIFO_Truncate) (cFIFO *Self);
/** Cleanly delete a FIFO instance.
@param[in] Self Pointer to the FIFO instance.
**/
typedef void (EFIAPI *cFIFO_Delete) (cFIFO *Self);
/** Get the FIFO's current Read Index.
@param[in] Self Pointer to the FIFO instance.
@return The current value of the FIFO's ReadIndex member is returned.
**/
typedef UINT32 (EFIAPI *cFIFO_GetRDex) (cFIFO *Self);
/** Get the FIFO's current Write Index.
@param[in] Self Pointer to the FIFO instance.
@return The current value of the FIFO's WriteIndex member is returned.
**/
typedef UINT32 (EFIAPI *cFIFO_GetWDex) (cFIFO *Self);
/// Structure declaration for FIFO objects.
struct _FIFO_CLASS {
/* ######## Public Functions ######## */
cFIFO_Enqueue Write; ///< Write an element into the FIFO.
cFIFO_Dequeue Read; ///< Read an element from the FIFO.
cFIFO_Copy Copy; ///< Non-destructive copy from FIFO.
cFIFO_IsEmpty IsEmpty; ///< Test whether the FIFO is empty.
cFIFO_IsFull IsFull; ///< Test whether the FIFO is full.
cFIFO_NumInQueue Count; ///< Return the number of elements contained in the FIFO.
cFIFO_FreeSpace FreeSpace; ///< Return the number of available elements in the FIFO.
cFIFO_Flush Flush; ///< Remove the N earliest elements from the FIFO.
cFIFO_Truncate Truncate; ///< Remove the most recent element from the FIFO.
cFIFO_Delete Delete; ///< Delete the FIFO object.
/* ######## Protected Functions ######## */
cFIFO_GetRDex GetRDex; ///< Get a copy of the current Read Index.
cFIFO_GetWDex GetWDex; ///< Get a copy of the current Write Index.
/* ######## PRIVATE Data ######## */
void *Queue; ///< The FIFO's data storage.
UINT32 ElementSize; ///< Number of bytes in an element.
UINT32 NumElements; ///< Number of elements the FIFO can store.
UINT32 ReadIndex; ///< Index of next element to Read.
UINT32 WriteIndex; ///< Index of where next element will be Written.
};
__END_DECLS
#endif /* _FIFO_CLASS_H */

View File

@ -0,0 +1,105 @@
/** @file
Utility functions for performing basic math operations constrained within a
modulus.
These functions are intended to simplify small changes to a value which much
remain within a specified modulus. Changes must be less than or equal to
the modulus specified by MaxVal.
Copyright (c) 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 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.
**/
#ifndef _MODULO_UTIL_H
#define _MODULO_UTIL_H
#include <Uefi.h>
#include <sys/EfiCdefs.h>
__BEGIN_DECLS
/** Counter = (Counter + 1) % MaxVal;
Counter is always expected to be LESS THAN MaxVal.
0 <= Counter < MaxVal
@param[in] Counter The value to be incremented.
@param[in] MaxVal Modulus of the operation.
@return Returns the result of incrementing Counter, modulus MaxVal.
If Counter >= MaxVal, returns -1.
**/
INT32
EFIAPI
ModuloIncrement(
UINT32 Counter,
UINT32 MaxVal
);
/** Counter = (Counter - 1) % MaxVal;
Counter is always expected to be LESS THAN MaxVal.
0 <= Counter < MaxVal
@param[in] Counter The value to be decremented.
@param[in] MaxVal Modulus of the operation.
@return Returns the result of decrementing Counter, modulus MaxVal.
If Counter >= MaxVal, returns -1.
**/
INT32
EFIAPI
ModuloDecrement(
UINT32 Counter,
UINT32 MaxVal
);
/** Counter = (Counter + Increment) % MaxVal;
@param[in] Counter The value to be incremented.
@param[in] Increment The value to add to Counter.
@param[in] MaxVal Modulus of the operation.
@return Returns the result of adding Increment to Counter, modulus MaxVal,
or -1 if Increment is larger than MaxVal.
**/
INT32
EFIAPI
ModuloAdd (
UINT32 Counter,
UINT32 Increment,
UINT32 MaxVal
);
/** Increment Counter but don't increment past MaxVal.
@param[in] Counter The value to be decremented.
@param[in] MaxVal The upper bound for Counter. Counter < MaxVal.
@return Returns the result of incrementing Counter.
**/
UINT32
EFIAPI
BoundIncrement(
UINT32 Counter,
UINT32 MaxVal
);
/** Decrement Counter but don't decrement past zero.
@param[in] Counter The value to be decremented.
@return Returns the result of decrementing Counter.
**/
UINT32
EFIAPI
BoundDecrement(
UINT32 Counter
);
__END_DECLS
#endif /* _MODULO_UTIL_H */

View File

@ -215,19 +215,171 @@ struct termios {
#include <sys/EfiCdefs.h>
__BEGIN_DECLS
/** Get input baud rate.
Extracts the input baud rate from the termios structure pointed to by the
pTermios argument.
@param[in] pTermios A pointer to the termios structure from which to extract
the input baud rate.
@return The value of the input speed is returned exactly as it is contained
in the termios structure, without interpretation.
**/
speed_t cfgetispeed (const struct termios *);
/** Get output baud rate.
Extracts the output baud rate from the termios structure pointed to by the
pTermios argument.
@param[in] pTermios A pointer to the termios structure from which to extract
the output baud rate.
@return The value of the output speed is returned exactly as it is contained
in the termios structure, without interpretation.
**/
speed_t cfgetospeed (const struct termios *);
/** Set input baud rate.
Replaces the input baud rate, in the termios structure pointed to by the
pTermios argument, with the value of NewSpeed.
@param[out] pTermios A pointer to the termios structure into which to set
the input baud rate.
@param[in] NewSpeed The new input baud rate.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EINVAL - The value of NewSpeed is outside the range of
possible speed values as specified in <sys/termios.h>.
**/
int cfsetispeed (struct termios *, speed_t);
/** Set output baud rate.
Replaces the output baud rate, in the termios structure pointed to by the
pTermios argument, with the value of NewSpeed.
@param[out] pTermios A pointer to the termios structure into which to set
the output baud rate.
@param[in] NewSpeed The new output baud rate.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EINVAL - The value of NewSpeed is outside the range of
possible speed values as specified in <sys/termios.h>.
**/
int cfsetospeed (struct termios *, speed_t);
/** Get the parameters associated with an interactive IO device.
Get the parameters associated with the device referred to by
fd and store them into the termios structure referenced by pTermios.
@param[in] fd The file descriptor for an open interactive IO device.
@param[out] pTermios A pointer to a termios structure into which to store
attributes of the interactive IO device.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EBADF - The fd argument is not a valid file descriptor.
* ENOTTY - The file associated with fd is not an interactive IO device.
**/
int tcgetattr (int, struct termios *);
/** Set the parameters associated with an interactive IO device.
Set the parameters associated with the device referred to by
fd to the values in the termios structure referenced by pTermios.
Behavior is modified by the value of the OptAct parameter:
* TCSANOW: The change shall occur immediately.
* TCSADRAIN: The change shall occur after all output written to fd is
transmitted. This action should be used when changing parameters which
affect output.
* TCSAFLUSH: The change shall occur after all output written to fd is
transmitted, and all input so far received but not read shall be
discarded before the change is made.
@param[in] fd The file descriptor for an open interactive IO device.
@param[in] OptAct Currently has no effect.
@param[in] pTermios A pointer to a termios structure into which to retrieve
attributes to set in the interactive IO device.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EBADF - The fd argument is not a valid file descriptor.
* ENOTTY - The file associated with fd is not an interactive IO device.
**/
int tcsetattr (int, int, const struct termios *);
/** Transmit pending output.
@param[in] fd The file descriptor for an open interactive IO device.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EBADF - The fd argument is not a valid file descriptor.
* ENOTTY - The file associated with fd is not an interactive IO device.
* EINTR - A signal interrupted tcdrain().
* ENOTSUP - This function is not supported.
**/
int tcdrain (int);
/** Suspend or restart the transmission or reception of data.
This function will suspend or resume transmission or reception of data on
the file referred to by fd, depending on the value of Action.
@param[in] fd The file descriptor of an open interactive IO device (terminal).
@param[in] Action The action to be performed:
* TCOOFF - Suspend output.
* TCOON - Resume suspended output.
* TCIOFF - If fd refers to an IIO device, transmit a
STOP character, which is intended to cause the
terminal device to stop transmitting data.
* TCION - If fd refers to an IIO device, transmit a
START character, which is intended to cause the
terminal device to start transmitting data.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EBADF - The fd argument is not a valid file descriptor.
* ENOTTY - The file associated with fd is not an interactive IO device.
* EINVAL - The Action argument is not a supported value.
* ENOTSUP - This function is not supported.
**/
int tcflow (int, int);
/** Discard non-transmitted output data, non-read input data, or both.
@param[in] fd The file descriptor for an open interactive IO device.
@param[in] QueueSelector The IO queue to be affected:
* TCIFLUSH - If fd refers to a device open for input, flush
pending input. Otherwise error EINVAL.
* TCOFLUSH - If fd refers to a device open for output,
flush pending output. Otherwise error EINVAL.
* TCIOFLUSH - If fd refers to a device open for both
input and output, flush pending input and output.
Otherwise error EINVAL.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EBADF - The fd argument is not a valid file descriptor.
* ENOTTY - The file associated with fd is not an interactive IO device.
* EINVAL - The QueueSelector argument is not a supported value.
* ENOTSUP - This function is not supported.
**/
int tcflush (int, int);
//int tcsendbreak (int, int);
//pid_t tcgetsid (int);
//void cfmakeraw (struct termios *);
//int cfsetspeed (struct termios *, speed_t);
__END_DECLS

View File

@ -0,0 +1,149 @@
/** @file
Utility functions for performing basic math operations constrained within a
modulus.
These functions are intended to simplify small changes to a value which much
remain within a specified modulus.
NOTE: Changes must be less than or equal to the modulus specified by MaxVal.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <LibConfig.h>
#include <assert.h>
/** Counter = (Counter + 1) % MaxVal;
Counter is always expected to be LESS THAN MaxVal.
0 <= Counter < MaxVal
@param[in] Counter The value to be incremented.
@param[in] MaxVal Modulus of the operation.
@return Returns the result of incrementing Counter, modulus MaxVal.
If Counter >= MaxVal, returns -1.
**/
INT32
EFIAPI
ModuloIncrement(
UINT32 Counter,
UINT32 MaxVal
)
{
INT32 Temp;
if(Counter < MaxVal) {
Temp = (INT32)(Counter + 1);
if(Temp >= (INT32)MaxVal) {
Temp = 0;
}
}
else {
Temp = -1;
}
return Temp;
}
/** Counter = (Counter - 1) % MaxVal;
Counter is always expected to be LESS THAN MaxVal.
0 <= Counter < MaxVal
@param[in] Counter The value to be decremented.
@param[in] MaxVal Modulus of the operation.
@return Returns the result of decrementing Counter, modulus MaxVal.
If Counter >= MaxVal, returns -1.
**/
INT32
EFIAPI
ModuloDecrement(
UINT32 Counter,
UINT32 MaxVal
)
{
INT32 Temp;
if(Counter < MaxVal) {
Temp = (INT32)Counter - 1;
// If Counter is zero, Temp will become -1.
if(Temp < 0) {
Temp = (INT32)MaxVal - 1;
}
}
else {
Temp = -1;
}
return Temp;
}
/** Decrement Counter but don't decrement past zero.
@param[in] Counter The value to be decremented.
@return Returns the result of decrementing Counter.
**/
UINT32
EFIAPI
BoundDecrement(
UINT32 Counter
)
{
return ((Counter > 0) ? (Counter - 1) : 0);
}
/** Increment Counter but don't increment past MaxVal.
Counter should be maintained in the range (0 <= Counter < MaxVal).
@param[in] Counter The value to be decremented.
@param[in] MaxVal The upper bound for Counter.
@return Returns the result of incrementing Counter.
**/
UINT32
EFIAPI
BoundIncrement(
UINT32 Counter,
UINT32 MaxVal
)
{
return ((Counter < (MaxVal - 1)) ? (Counter + 1) : (MaxVal - 1));
}
/** Counter = (Counter + Increment) % MaxVal;
@param[in] Counter The value to be incremented.
@param[in] Increment The value to add to Counter.
@param[in] MaxVal Modulus of the operation.
@return Returns the result of adding Increment to Counter, modulus MaxVal,
or -1 if Increment is larger than MaxVal.
**/
INT32
EFIAPI
ModuloAdd (
UINT32 Counter,
UINT32 Increment,
UINT32 MaxVal
)
{
UINT32 Temp;
if(Increment > MaxVal) {
return -1;
}
Temp = (Counter + Increment);
while(Temp >= MaxVal) {
Temp -= MaxVal;
}
return Temp;
}

View File

@ -0,0 +1,46 @@
## @file
# INF file for building the Container library.
#
# Various types of containers are implemented within this library.
# Types of containers may be Queues (FIFO, LIFO, etc.), hash tables, etc.
#
# Copyright (c) 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 which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THIS PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = LibContainer
FILE_GUID = 92f7436e-7395-4da1-a7be-f352f0bcd79c
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = LibContainer
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
Queues/Fifo.c
Common/ModuloUtil.c
[LibraryClasses]
BaseLib
BaseMemoryLib
MemoryAllocationLib
LibC
LibWchar
[Packages]
MdePkg/MdePkg.dec
StdLib/StdLib.dec
StdLibPrivateInternalFiles/DoNotUse.dec

View File

@ -0,0 +1,526 @@
/** @file
Class for arbitrary sized FIFO queues.
The FIFO is empty if both the Read and Write indexes are equal.
The FIFO is full if the next write would make the Read and Write indexes equal.
Member variable NumElements is the maximum number of elements that can be
contained in the FIFO.
If NumElements is ZERO, there is an error.
NumElements should be in the range 1:N.
Members WriteIndex and ReadIndex are indexes into the array implementing the
FIFO. They should be in the range 0:(NumElements - 1).
One element of the FIFO is always reserved as the "terminator" element. Thus,
the capacity of a FIFO is actually NumElements-1.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <LibConfig.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <wchar.h>
#include <Containers/Fifo.h>
/** Determine number of items available to read from the FIFO.
The number of items are either the number of bytes, or the number of elements
depending upon the value of the As enumerator.
@param[in] Self Pointer to the FIFO instance.
@param[in] As An enumeration variable whose value determines whether the
returned value is the number of bytes or the number of elements
currently contained by the FIFO.
@retval 0 The FIFO is empty.
@retval >=0 The number of items contained by the FIFO.
**/
static
size_t
EFIAPI
FIFO_NumInQueue (
cFIFO *Self,
FIFO_ElemBytes As
)
{
size_t Count;
if(Self->ReadIndex <= Self->WriteIndex) {
Count = Self->WriteIndex - Self->ReadIndex;
}
else {
Count = Self->NumElements - (Self->ReadIndex - Self->WriteIndex);
}
if(As == AsBytes) {
Count *= Self->ElementSize;
}
return Count;
}
/** Determine amount of free space in the FIFO that can be written into.
The number of items are either the number of bytes, or the number of elements
depending upon the value of the As enumerator.
@param[in] Self Pointer to the FIFO instance.
@param[in] As An enumeration variable whose value determines whether the
returned value is the number of bytes or the number of elements
currently available in the FIFO.
@retval 0 The FIFO is full.
@retval >=0 The number of items which can be accepted by the FIFO.
**/
static
size_t
EFIAPI
FIFO_FreeSpace (
cFIFO *Self,
FIFO_ElemBytes As
)
{
size_t Count;
UINT32 RDex;
UINT32 WDex;
RDex = Self->ReadIndex;
WDex = Self->WriteIndex;
if(RDex <= WDex) {
Count = Self->NumElements - ((WDex - RDex) - 1);
}
else {
Count = (RDex - WDex);
}
if(As == AsBytes) {
Count *= Self->ElementSize;
}
return Count;
}
/** Reduce the FIFO contents by NumElem elements.
@param[in] Self Pointer to the FIFO instance.
@param[in] NumElem Number of elements to delete from the FIFO.
@retval 0 FIFO is now empty.
@retval N>0 There are still N elements in the FIFO.
@retval -1 There are fewer than NumElem elements in the FIFO.
**/
static
ssize_t
FIFO_Reduce (
cFIFO *Self,
size_t NumElem
)
{
size_t QCount;
ssize_t RetVal;
assert(Self != NULL);
QCount = FIFO_NumInQueue(Self, AsElements);
if(NumElem > QCount) {
RetVal = -1;
errno = EINVAL;
}
else {
RetVal = (ssize_t)ModuloAdd(Self->ReadIndex, (UINT32)NumElem, Self->NumElements);
Self->ReadIndex = (UINT32)RetVal;
RetVal = (ssize_t)(QCount - NumElem);
}
return RetVal;
}
/** Test whether the FIFO is empty.
@param[in] Self Pointer to the FIFO instance.
@retval TRUE The FIFO is empty.
@retval FALSE There is data in the FIFO.
**/
static
BOOLEAN
EFIAPI
FIFO_IsEmpty (
cFIFO *Self
)
{
assert(Self != NULL);
return (BOOLEAN)(Self->WriteIndex == Self->ReadIndex);
}
/** Test whether the FIFO is full.
@param[in] Self Pointer to the FIFO instance.
@retval TRUE The FIFO is full.
@retval FALSE There is free space in the FIFO.
**/
static
BOOLEAN
EFIAPI
FIFO_IsFull (
cFIFO *Self
)
{
assert(Self != NULL);
return (BOOLEAN)(ModuloIncrement(Self->WriteIndex, Self->NumElements) == (INT32)Self->ReadIndex);
}
/** Add one or more elements to the FIFO.
This function allows one to add one or more elements, as specified by Count,
to the FIFO. Each element is of the size specified when the FIFO object
was instantiated (FIFO.ElementSize).
pElement points to the first byte of the first element to be added.
If multiple elements are to be added, the elements are expected to be
organized as a packed array.
@param[in] Self Pointer to the FIFO instance.
@param[in] pElement Pointer to the element(s) to enqueue (add).
@param[in] Count Number of elements to add.
@retval 0 The FIFO is full.
@retval >=0 The number of elements added to the FIFO.
**/
static
size_t
EFIAPI
FIFO_Enqueue (
cFIFO *Self,
const void *pElement,
size_t Count
)
{
uintptr_t ElemPtr;
uintptr_t QPtr;
size_t i;
UINT32 SizeOfElement;
UINT32 Windex;
assert(Self != NULL);
assert(pElement != NULL);
assert(Count >= 0);
if(FIFO_IsFull(Self)) {
Count = 0;
}
else {
Count = MIN(Count, Self->FreeSpace(Self, AsElements));
SizeOfElement = Self->ElementSize;
Windex = Self->WriteIndex;
ElemPtr = (uintptr_t)pElement;
QPtr = (uintptr_t)Self->Queue + (SizeOfElement * Windex);
for(i = 0; i < Count; ++i) {
(void)CopyMem((void *)QPtr, (const void *)ElemPtr, SizeOfElement);
Windex = (UINT32)ModuloIncrement(Windex, Self->NumElements);
if(Windex == 0) { // If the index wrapped
QPtr = (uintptr_t)Self->Queue;
}
else {
QPtr += SizeOfElement;
}
ElemPtr += SizeOfElement;
}
(void)ZeroMem((void*)QPtr, SizeOfElement);
Self->WriteIndex = Windex;
}
return Count;
}
/** Read or copy elements from the FIFO.
This function allows one to read one or more elements, as specified by Count,
from the FIFO. Each element is of the size specified when the FIFO object
was instantiated (FIFO.ElementSize).
pElement points to the destination of the first byte of the first element
to be read. If multiple elements are to be read, the elements are expected
to be organized as a packed array.
@param[in] Self Pointer to the FIFO instance.
@param[out] pElement Pointer to where to store the element(s) read from the FIFO.
@param[in] Count Number of elements to dequeue.
@param[in] Consume If TRUE, consume read elements. Otherwise, preserve.
@retval 0 The FIFO is empty.
@retval >=0 The number of elements read from the FIFO.
**/
static
size_t
EFIAPI
FIFO_Dequeue (
cFIFO *Self,
void *pElement,
size_t Count,
BOOLEAN Consume
)
{
UINTN ElemPtr;
UINTN QPtr;
UINT32 RDex;
UINT32 SizeOfElement;
UINT32 i;
assert(Self != NULL);
assert(pElement != NULL);
assert(Count != 0);
if(FIFO_IsEmpty(Self)) {
Count = 0;
}
else {
RDex = Self->ReadIndex;
SizeOfElement = Self->ElementSize;
ElemPtr = (UINTN)pElement;
Count = MIN(Count, Self->Count(Self, AsElements));
QPtr = (UINTN)Self->Queue + (RDex * Self->ElementSize);
for(i = 0; i < Count; ++i) {
(void)CopyMem((void *)ElemPtr, (const void *)QPtr, Self->ElementSize);
RDex = (UINT32)ModuloIncrement(RDex, Self->NumElements);
if(RDex == 0) { // If the index wrapped
QPtr = (UINTN)Self->Queue;
}
else {
QPtr += Self->ElementSize;
}
ElemPtr += Self->ElementSize;
}
if(Consume) {
Self->ReadIndex = RDex;
}
}
return Count;
}
/** Read elements from the FIFO.
@param[in] Self Pointer to the FIFO instance.
@param[out] pElement Pointer to where to store the element read from the FIFO.
@param[in] Count Number of elements to dequeue.
@retval 0 The FIFO is empty.
@retval >=0 The number of elements read from the FIFO.
**/
static
size_t
EFIAPI
FIFO_Read (
cFIFO *Self,
void *pElement,
size_t Count
)
{
return FIFO_Dequeue(Self, pElement, Count, TRUE);
}
/** Make a copy of the FIFO's data.
The contents of the FIFO is copied out and linearized without affecting the
FIFO contents.
@param[in] Self Pointer to the FIFO instance.
@param[out] pElement Pointer to where to store the elements copied from the FIFO.
@param[in] Count Number of elements to copy.
@retval 0 The FIFO is empty.
@retval >=0 The number of elements copied from the FIFO.
**/
static
size_t
EFIAPI
FIFO_Copy (
cFIFO *Self,
void *pElement,
size_t Count
)
{
return FIFO_Dequeue(Self, pElement, Count, FALSE);
}
/** Get the FIFO's current Read Index.
@param[in] Self Pointer to the FIFO instance.
**/
static
UINT32
EFIAPI
FIFO_GetRDex (
cFIFO *Self
)
{
assert(Self != NULL);
return Self->ReadIndex;
}
/** Get the FIFO's current Write Index.
@param[in] Self Pointer to the FIFO instance.
@return The current value of the FIFO's WriteIndex member is returned.
**/
static
UINT32
EFIAPI
FIFO_GetWDex (
cFIFO *Self
)
{
assert(Self != NULL);
return Self->WriteIndex;
}
/** Cleanly delete a FIFO instance.
@param[in] Self Pointer to the FIFO instance.
**/
static
void
EFIAPI
FIFO_Delete (
cFIFO *Self
)
{
assert(Self != NULL);
if(Self->Queue != NULL) {
FreePool(Self->Queue);
Self->Queue = NULL; // Zombie catcher
}
FreePool(Self);
}
/** Empty the FIFO, discarding up to NumToFlush elements.
@param[in] Self Pointer to the FIFO instance.
@param[in] NumToFlush Number of elements to flush from the FIFO.
If larger than the number of elements in the
FIFO, the FIFO is emptied.
@return Returns the number of elements remaining in the FIFO after the flush.
**/
static
size_t
EFIAPI
FIFO_Flush (
cFIFO *Self,
size_t NumToFlush
)
{
size_t NumInQ;
size_t Remainder;
assert(Self != NULL);
NumInQ = FIFO_FreeSpace(Self, AsElements);
if(NumToFlush >= NumInQ) {
Self->ReadIndex = 0;
Self->WriteIndex = 0;
Remainder = 0;
}
else {
Remainder = FIFO_Reduce(Self, NumToFlush);
}
return Remainder;
}
/** Remove the most recently added element from the FIFO.
@param[in] Self Pointer to the FIFO instance.
@return Returns the number of elements remaining in the FIFO.
**/
static
size_t
EFIAPI
FIFO_Truncate (
cFIFO *Self
)
{
size_t Remainder;
assert(Self != NULL);
Remainder = Self->Count(Self, AsElements);
if(Remainder > 0) {
Self->WriteIndex = (UINT32)ModuloDecrement(Self->WriteIndex, Self->NumElements);
--Remainder;
}
return Remainder;
}
/** Construct a new instance of a FIFO Queue.
@param[in] NumElements Number of elements to be contained in the new FIFO.
@param[in] ElementSize Size, in bytes, of an element.
@retval NULL Unable to create the instance.
@retval NonNULL Pointer to the new FIFO instance.
**/
cFIFO *
EFIAPI
New_cFIFO(
UINT32 NumElements,
size_t ElementSize
)
{
cFIFO *FIFO;
UINT8 *Queue;
FIFO = NULL;
if((NumElements > 2) && (ElementSize > 0)) {
FIFO = (cFIFO *)AllocatePool(sizeof(cFIFO));
if(FIFO != NULL) {
Queue = (UINT8 *)AllocateZeroPool(NumElements * ElementSize);
if(Queue != NULL) {
FIFO->Write = FIFO_Enqueue;
FIFO->Read = FIFO_Read;
FIFO->Copy = FIFO_Copy;
FIFO->IsEmpty = FIFO_IsEmpty;
FIFO->IsFull = FIFO_IsFull;
FIFO->Count = FIFO_NumInQueue;
FIFO->FreeSpace = FIFO_FreeSpace;
FIFO->Flush = FIFO_Flush;
FIFO->Truncate = FIFO_Truncate;
FIFO->Delete = FIFO_Delete;
FIFO->GetRDex = FIFO_GetRDex;
FIFO->GetWDex = FIFO_GetWDex;
FIFO->Queue = Queue;
FIFO->ElementSize = (UINT32)ElementSize;
FIFO->NumElements = (UINT32)NumElements;
FIFO->ReadIndex = 0;
FIFO->WriteIndex = 0;
}
else {
FreePool(FIFO);
FIFO = NULL;
}
}
}
return FIFO;
}

View File

@ -158,9 +158,9 @@ ShellAppMain (
mfd[i].MyFD = (UINT16)i;
}
i = open("stdin:", O_RDONLY, 0444);
i = open("stdin:", (O_RDONLY | O_TTY_INIT), 0444);
if(i == 0) {
i = open("stdout:", O_WRONLY, 0222);
i = open("stdout:", (O_WRONLY | O_TTY_INIT), 0222);
if(i == 1) {
i = open("stderr:", O_WRONLY, 0222);
}

View File

@ -3,6 +3,13 @@
Manipulates abstractions for stdin, stdout, stderr.
This device is a WIDE device and this driver returns WIDE
characters. It this the responsibility of the caller to convert between
narrow and wide characters in order to perform the desired operations.
The devices status as a wide device is indicatd by _S_IWTTY being set in
f_iflags.
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.
@ -30,6 +37,7 @@
#include <unistd.h>
#include <kfile.h>
#include <Device/Device.h>
#include <Device/IIO.h>
#include <MainData.h>
static const CHAR16* const
@ -46,7 +54,7 @@ static const int stdioFlags[NUM_SPECIAL] = {
static DeviceNode *ConNode[NUM_SPECIAL];
static ConInstance *ConInstanceList;
static wchar_t *ConReadBuf;
static cIIO *IIO;
/* Flags settable by Ioctl */
static BOOLEAN TtyCooked;
@ -58,10 +66,10 @@ static BOOLEAN TtyEcho;
large enough to hold the converted results. It is guaranteed
that there will be fewer than n characters placed in dest.
@param dest WCS buffer to receive the converted string.
@param buf MBCS string to convert to WCS.
@param n Number of BYTES contained in buf.
@param Cs Pointer to the character state object for this stream
@param[out] dest WCS buffer to receive the converted string.
@param[in] buf MBCS string to convert to WCS.
@param[in] n Number of BYTES contained in buf.
@param[in,out] Cs Pointer to the character state object for this stream
@return The number of BYTES consumed from buf.
**/
@ -94,6 +102,13 @@ WideTtyCvt( CHAR16 *dest, const char *buf, ssize_t n, mbstate_t *Cs)
return i;
}
/** Close an open file.
@param[in] filp Pointer to the file descriptor structure for this file.
@retval 0 The file has been successfully closed.
@retval -1 filp does not point to a valid console descriptor.
**/
static
int
EFIAPI
@ -106,13 +121,25 @@ da_ConClose(
Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
errno = EINVAL;
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;
return 0;
}
/** Position the console cursor to the coordinates specified by Position.
@param[in] filp Pointer to the file descriptor structure for this file.
@param[in] Position A value containing the target X and Y coordinates.
@param[in] whence Ignored by the Console device.
@retval Position Success. Returns a copy of the Position argument.
@retval -1 filp is not associated with a valid console stream.
@retval -1 This console stream is attached to stdin.
@retval -1 The SetCursorPosition operation failed.
**/
static
off_t
EFIAPI
@ -155,11 +182,14 @@ da_ConSeek(
/* 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.
NOTE: The UEFI Console is a wide device, _S_IWTTY, so characters received
by da_ConWrite are WIDE characters. It is the responsibility of the
higher-level function(s) to perform any necessary conversions.
@param[in,out] BufferSize Number of characters in Buffer.
@param[in] Buffer The WCS string to be displayed
@return The number of BYTES written. Because of MBCS, this may be more than number of characters.
@return The number of Characters written.
*/
static
ssize_t
@ -174,8 +204,10 @@ da_ConWrite(
EFI_STATUS Status;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
ConInstance *Stream;
ssize_t NumBytes;
ssize_t NumChar;
XY_OFFSET CursorPos;
NumChar = -1;
Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
@ -190,35 +222,45 @@ da_ConWrite(
// 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.
NumBytes = WideTtyCvt(gMD->UString, (const char *)Buffer, (ssize_t)BufferSize, &Stream->CharState);
BufferSize = NumBytes;
Status = EFI_SUCCESS;
if(Position != NULL) {
CursorPos.Offset = *Position;
Status = Proto->SetCursorPosition(Proto,
(INTN)CursorPos.XYpos.Column,
(INTN)CursorPos.XYpos.Row);
// 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 = NumBytes;
Stream->NumWritten += NumBytes;
if(!RETURN_ERROR(Status)) {
// Send the Unicode buffer to the console
Status = Proto->OutputString( Proto, (CHAR16 *)Buffer);
}
// Depending on status, update BufferSize and return
if(!RETURN_ERROR(Status)) {
//BufferSize = NumChar;
NumChar = BufferSize;
Stream->NumWritten += NumChar;
}
EFIerrno = Status; // Make error reason available to caller
return BufferSize;
return NumChar;
}
/** Read characters from the console input device.
/** Read a wide character from the console input device.
@param[in,out] filp Pointer to file descriptor for this file.
@param[in,out] offset Ignored.
NOTE: The UEFI Console is a wide device, _S_IWTTY, so characters returned
by da_ConRead are WIDE characters. It is the responsibility of the
higher-level function(s) to perform any necessary conversions.
@param[in,out] BufferSize Number of characters in Buffer.
@param[in] filp Pointer to file descriptor for this file.
@param[in] 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.
@retval -1 An error has occurred. Reason in errno and EFIerrno.
@retval -1 No data is available. errno is set to EAGAIN
@retval 1 One wide character has been placed in Buffer
**/
static
ssize_t
@ -232,84 +274,80 @@ da_ConRead(
{
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
ConInstance *Stream;
wchar_t *OutPtr;
EFI_INPUT_KEY Key;
UINTN NumChar;
UINTN Edex;
cIIO *Self;
EFI_INPUT_KEY Key = {0,0};
EFI_STATUS Status = RETURN_SUCCESS;
UINTN i;
char EchoBuff[MB_CUR_MAX + 1];
int NumEcho;
UINTN Edex;
ssize_t NumRead;
int Flags;
wchar_t RetChar; // Default to No Data
NumRead = -1;
if(BufferSize < sizeof(wchar_t)) {
errno = EINVAL; // Buffer is too small to hold one character
}
else {
Self = (cIIO *)filp->devdata;
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 {
Flags = filp->Oflags;
if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
// No data pending in the Un-get buffer. Get a char from the hardware.
if((Flags & O_NONBLOCK) == 0) {
// Read a byte in Blocking mode
Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
if(Status != RETURN_SUCCESS) {
break;
EFIerrno = Status;
if(Status != EFI_SUCCESS) {
errno = EINVAL;
}
else {
Status = Proto->ReadKeyStroke(Proto, &Key);
if(Status != RETURN_SUCCESS) {
break;
if(Status == EFI_SUCCESS) {
NumRead = 1; // Indicate that Key holds the data
}
else {
errno = EIO;
}
}
}
else {
// Read a byte in Non-Blocking mode
Status = Proto->ReadKeyStroke(Proto, &Key);
EFIerrno = Status;
if(Status == EFI_SUCCESS) {
// Got a keystroke.
NumRead = 1; // Indicate that Key holds the data
}
else if(Status == EFI_NOT_READY) {
// Keystroke data is not available
errno = EAGAIN;
}
else {
// Hardware error
errno = EIO;
}
}
}
else {
// Use the data in the Un-get buffer
Key.ScanCode = Stream->UnGetKey.ScanCode;
Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
Stream->UnGetKey.ScanCode = SCAN_NULL;
Stream->UnGetKey.UnicodeChar = CHAR_NULL;
NumRead = 1; // Indicate that Key holds the data
}
if(Key.ScanCode == SCAN_NULL) {
NumEcho = 0;
if(TtyCooked && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
*OutPtr++ = CHAR_LINEFEED;
NumEcho = wctomb(EchoBuff, CHAR_LINEFEED);
// If we have data, prepare it for return.
if(NumRead == 1) {
RetChar = Key.UnicodeChar;
if((RetChar == 0) && ((Self->Termio.c_iflag & IGNSPEC) == 0)) {
// Must be a control, function, or other non-printable key.
// Map it into the Platform portion of the Unicode private use area
RetChar = (Key.ScanCode == 0) ? 0 : 0xF900U - Key.ScanCode;
}
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);
*((wchar_t *)Buffer) = RetChar;
}
}
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
return NumRead;
}
/** Console-specific helper function for the fstat() function.
@ -320,6 +358,14 @@ da_ConRead(
st_blksize Set to 1 since this is a character device
All other members of the stat structure are left unchanged.
@param[in] filp Pointer to file descriptor for this file.
@param[out] Buffer Pointer to a stat structure to receive the information.
@param[in,out] Something Ignored.
@retval 0 Successful completion.
@retval -1 Either filp is not associated with a console stream, or
Buffer is NULL. errno is set to EINVAL.
**/
static
int
@ -343,6 +389,7 @@ da_ConStat(
if ((Stream->Cookie != CON_COOKIE) || // Cookie == 'IoAb'
(Buffer == NULL))
{
errno = EINVAL;
EFIerrno = RETURN_INVALID_PARAMETER;
return -1;
}
@ -378,6 +425,14 @@ da_ConStat(
return 0;
}
/** Console-specific helper for the ioctl system call.
The console device does not directly participate in ioctl operations.
This function completes the device abstraction and returns an error value
to indicate that the function is not supported for this device.
@retval -1 Function is not supported for this device.
**/
static
int
EFIAPI
@ -387,10 +442,21 @@ da_ConIoctl(
va_list argp
)
{
return -EPERM;
errno = ENODEV;
return -1;
}
/** Open an abstract Console Device.
@param[in] DevNode Pointer to the Device control structure for this stream.
@param[in] filp Pointer to the new file control structure for this stream.
@param[in] DevInstance Not used for the console device.
@param[in] Path Not used for the console device.
@param[in] MPath Not used for the console device.
@retval 0 This console stream has been successfully opened.
@retval -1 The DevNode or filp pointer is NULL.
@retval -1 DevNode does not point to a valid console stream device.
**/
int
EFIAPI
@ -403,36 +469,57 @@ da_ConOpen(
)
{
ConInstance *Stream;
UINT32 Instance;
int RetVal = -1;
if((filp == NULL) ||
(DevNode == NULL))
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'
if(Stream->Cookie == CON_COOKIE)
{
Instance = Stream->InstanceNum;
if(Instance < NUM_SPECIAL) {
gMD->StdIo[Instance] = Stream;
filp->f_iflags |= (_S_IFCHR | _S_ITTY | _S_IWTTY | _S_ICONSOLE);
filp->f_offset = 0;
filp->f_ops = &Stream->Abstraction;
filp->devdata = (void *)IIO;
RetVal = 0;
}
}
}
if (RetVal < 0) {
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 RetVal;
return 0;
}
#include <sys/poll.h>
/* Returns a bit mask describing which operations could be completed immediately.
Testable Events for this device are:
(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.
Non-testable Events which are only valid in return values are:
POLLERR The specified device is not one of stdin, stdout, or stderr.
POLLHUP The specified stream has been disconnected
POLLNVAL da_ConPoll was called with an invalid parameter.
NOTE: The "Events" handled by this function are not UEFI events.
@param[in] filp Pointer to the file control structure for this stream.
@param[in] events A bit mask identifying the events to be examined
for this device.
@return Returns a bit mask comprised of both testable and non-testable
event codes indicating both the state of the operation and the
status of the device.
*/
static
short
@ -450,6 +537,7 @@ da_ConPoll(
Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
errno = EINVAL;
EFIerrno = RETURN_INVALID_PARAMETER;
return POLLNVAL; // Looks like a bad filp pointer
}
@ -495,15 +583,18 @@ __Cons_construct(
)
{
ConInstance *Stream;
RETURN_STATUS Status = RETURN_SUCCESS;
RETURN_STATUS Status;
int i;
Status = RETURN_OUT_OF_RESOURCES;
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;
if(ConInstanceList != NULL) {
IIO = New_cIIO();
if(IIO == NULL) {
FreePool(ConInstanceList);
}
else {
Status = RETURN_SUCCESS;
for( i = 0; i < NUM_SPECIAL; ++i) {
// Get pointer to instance.
Stream = &ConInstanceList[i];
@ -553,9 +644,10 @@ __Cons_construct(
if(Stream->Dev == NULL) {
continue; // No device for this stream.
}
ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream, 1, sizeof(ConInstance), stdioFlags[i]);
ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream,
1, sizeof(ConInstance), stdioFlags[i]);
if(ConNode[i] == NULL) {
Status = EFIerrno;
Status = EFIerrno; // Grab error code that DevRegister produced.
break;
}
Stream->Parent = ConNode[i];
@ -563,7 +655,8 @@ __Cons_construct(
/* Initialize Ioctl flags until Ioctl is really implemented. */
TtyCooked = TRUE;
TtyEcho = TRUE;
}
}
return Status;
}
@ -584,15 +677,16 @@ __Cons_deconstruct(
if(ConInstanceList != NULL) {
FreePool(ConInstanceList);
}
if(ConReadBuf != NULL) {
FreePool(ConReadBuf);
if(IIO != NULL) {
IIO->Delete(IIO);
IIO = NULL;
}
return RETURN_SUCCESS;
}
/* ######################################################################### */
#if 0 /* Not implemented for Console */
#if 0 /* Not implemented (yet?) for Console */
static
int

View File

@ -1,7 +1,7 @@
/** @file
Device Abstraction: device creation utility functions.
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2011 - 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
@ -44,22 +44,40 @@ int EFIAPI fnullop_flush (struct __filedes *filp)
{ return 0; }
int EFIAPI fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
{ return -EPERM; }
{
errno = EPERM;
return -1;
}
int EFIAPI fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, va_list argp)
{ return -EPERM; }
{
errno = EPERM;
return -1;
}
int EFIAPI fbadop_delete (struct __filedes *filp)
{ return -EPERM; }
{
errno = EPERM;
return -1;
}
int EFIAPI fbadop_mkdir (const char *path, __mode_t perms)
{ return -EPERM; }
{
errno = EPERM;
return -1;
}
int EFIAPI fbadop_rename (const char *from, const char *to)
{ return -EPERM; }
{
errno = EPERM;
return -1;
}
int EFIAPI fbadop_rmdir (struct __filedes *filp)
{ return -EPERM; }
{
errno = EPERM;
return -1;
}
/** Add a new device to the device list.
If both DevName and DevProto are NULL, register this as the Default device.

View File

@ -1,7 +1,7 @@
## @file
# Standard C library: Console Device Abstraction.
#
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2011 - 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 which accompanies this
# distribution. The full text of the license may be found at
@ -44,8 +44,9 @@
LibC
LibWchar
LibUefi
LibIIO
DevUtility
[Protocols]
gEfiSimpleTextInProtocolGuid
gEfiSimpleTextOutProtocolGuid
gEfiSimpleTextInProtocolGuid ## CONSUMED
gEfiSimpleTextOutProtocolGuid ## CONSUMED

View File

@ -0,0 +1,161 @@
/** @file
Canonical Interactive Input Function.
The functions assume that isatty() is TRUE at the time they are called.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <LibConfig.h>
#include <errno.h>
#include <sys/syslimits.h>
#include <sys/termios.h>
#include <Device/IIO.h>
#include <MainData.h>
#include "IIOutilities.h"
#include "IIOechoCtrl.h"
/** Read a line from the input file in canonical mode.
Perform echoing and input processing as directed by the termios flags.
@param[in] filp A pointer to a file descriptor structure.
@return The number of characters in the input buffer, or -1 if there
was an error.
**/
ssize_t
IIO_CanonRead (
struct __filedes *filp
)
{
cIIO *This;
cFIFO *InBuf;
struct termios *Termio;
struct __filedes *fpOut;
size_t NumRead;
wint_t InChar;
tcflag_t IFlag;
tcflag_t LFlag;
BOOLEAN EchoIsOK;
BOOLEAN Activate;
BOOLEAN FirstRead;
int OutMode;
UINTN MaxColumn;
UINTN MaxRow;
NumRead = MAX_INPUT; // Workaround "potentially uninitialized" warning
EchoIsOK = FALSE;
FirstRead = TRUE;
This = filp->devdata;
Termio = &This->Termio;
InBuf = This->InBuf;
// Get a copy of the flags we are going to use
IFlag = Termio->c_iflag;
LFlag = Termio->c_lflag;
/* Determine what the current screen size is. Also validates the output device. */
OutMode = IIO_GetOutputSize(STDOUT_FILENO, &MaxColumn, &MaxRow);
if(OutMode >= 0) {
/* Set the maximum screen dimensions. */
This->MaxColumn = MaxColumn;
This->MaxRow = MaxRow;
/* Record where the cursor is at the beginning of this Input operation.
The currently set stdout device is used to determine this. If there is
no stdout, or stdout is not an interactive device, nothing is recorded.
*/
if (IIO_GetCursorPosition(STDOUT_FILENO, &This->InitialXY.Column, &This->InitialXY.Row) >= 0) {
This->CurrentXY.Column = This->InitialXY.Column;
This->CurrentXY.Row = This->InitialXY.Row;
EchoIsOK = TRUE; // Can only echo to stdout
}
}
// For now, we only echo to stdout.
fpOut = &gMD->fdarray[STDOUT_FILENO];
// Input and process characters until BufferSize is exhausted.
do {
InChar = IIO_GetInChar(filp, FirstRead);
FirstRead = FALSE;
Activate = TRUE;
if(InChar == CHAR_CARRIAGE_RETURN) {
if((IFlag & IGNCR) != 0) {
continue; // Restart the do loop, discarding the CR
}
else if((IFlag & ICRNL) != 0) {
InChar = L'\n';
}
}
else if(InChar == CHAR_LINEFEED) {
if((IFlag & INLCR) != 0) {
InChar = L'\r';
}
}
else if(CCEQ(Termio->c_cc[VINTR], InChar)) {
if((LFlag & ISIG) != 0) {
// Raise Signal
// Flush Input Buffer
// Return to caller
InChar = IIO_ECHO_DISCARD;
errno = EINTR;
}
else {
Activate = FALSE;
}
}
else if(CCEQ(Termio->c_cc[VQUIT], InChar)) {
if((LFlag & ISIG) != 0) {
// Raise Signal
// Flush Input Buffer
// Return to caller
InChar = IIO_ECHO_DISCARD;
errno = EINTR;
}
else {
Activate = FALSE;
}
}
else if(CCEQ(Termio->c_cc[VEOF], InChar)) {
InChar = WEOF;
}
else if(CCEQ(Termio->c_cc[VEOL], InChar)) {
EchoIsOK = FALSE; // Buffer, but don't echo this character
}
else if(CCEQ(Termio->c_cc[VERASE], InChar)) {
InChar = IIO_ECHO_ERASE;
Activate = FALSE;
}
else if(CCEQ(Termio->c_cc[VKILL], InChar)) {
InChar = IIO_ECHO_KILL;
Activate = FALSE;
}
else {
if((InChar < TtySpecKeyMin) || (InChar >= TtyFunKeyMax)) {
Activate = FALSE;
}
}
/** The Echo function is responsible for:
* Adding the character to the input buffer, if appropriate.
* Removing characters from the input buffer for ERASE and KILL processing.
* Visually removing characters from the screen if ECHOE is set.
* Ensuring one can not backspace beyond the beginning of the input text.
* Sending final echo strings to output.
**/
(void)This->Echo(fpOut, (wchar_t)InChar, EchoIsOK);
NumRead = InBuf->Count(InBuf, AsElements);
} while((NumRead < MAX_INPUT) &&
(Activate == FALSE));
return (ssize_t)NumRead;
}

View File

@ -0,0 +1,373 @@
/** @file
Definitions for the Interactive IO library.
The functions assume that isatty() is TRUE at the time they are called.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/MemoryAllocationLib.h>
#include <LibConfig.h>
#include <assert.h>
#include <errno.h>
#include <sys/syslimits.h>
#include <sys/termios.h>
#include <Device/IIO.h>
#include <MainData.h>
#include "IIOutilities.h"
#include "IIOechoCtrl.h"
/** Read from an Interactive IO device.
NOTE: If _S_IWTTY is set, the internal buffer contains WIDE characters.
They will need to be converted to MBCS when returned.
Input is line buffered if ICANON is set,
otherwise MIN determines how many characters to input.
Currently MIN is always zero, meaning 0 or 1 character is input in
noncanonical mode.
@param[in] filp Pointer to the descriptor of the device (file) to be read.
@param[in] BufferSize Maximum number of bytes to be returned to the caller.
@param[out] Buffer Pointer to the buffer where the input is to be stored.
@retval -1 An error occurred. No data is available.
@retval 0 No data was available. Try again later.
@retval >0 The number of bytes consumed by the returned data.
**/
static
ssize_t
EFIAPI
IIO_Read(
struct __filedes *filp,
size_t BufferSize,
VOID *Buffer
)
{
cIIO *This;
ssize_t NumRead;
tcflag_t Flags;
size_t XlateSz;
size_t Needed;
NumRead = -1;
This = filp->devdata;
if(This != NULL) {
Flags = This->Termio.c_lflag;
if(Flags & ICANON) {
NumRead = IIO_CanonRead(filp);
}
else {
NumRead = IIO_NonCanonRead(filp);
}
// At this point, the input has been accumulated in the input buffer.
if(filp->f_iflags & _S_IWTTY) {
// Data in InBuf is wide characters. Convert to MBCS
// First, convert into a linear buffer
NumRead = This->InBuf->Copy(This->InBuf, gMD->UString2, (INT32)UNICODE_STRING_MAX-1);
gMD->UString2[NumRead] = 0; // Ensure that the buffer is terminated
// Determine the needed space
XlateSz = EstimateWtoM((const wchar_t *)gMD->UString2, BufferSize, &Needed);
// Now translate this into MBCS in Buffer
NumRead = wcstombs((char *)Buffer, (const wchar_t *)gMD->UString2, XlateSz);
// Consume the translated characters
(void)This->InBuf->Flush(This->InBuf, Needed);
}
else {
// Data in InBuf is narrow characters. Use verbatim.
NumRead = This->InBuf->Read(This->InBuf, Buffer, (INT32)BufferSize);
}
}
return NumRead;
}
/** Process characters from buffer buf and write them to the output device
specified by filp.
@param[in] filp Pointer to a file descriptor structure.
@param[in] buf Pointer to the MBCS string to be output.
@param[in] N Number of bytes in buf.
@retval >=0 Number of bytes sent to the output device.
**/
static
ssize_t
EFIAPI
IIO_Write(
struct __filedes *filp,
const char *buf,
ssize_t N
)
{
cIIO *This;
cFIFO *OutBuf;
mbstate_t *OutState;
char *MbcsPtr;
ssize_t NumWritten;
ssize_t NumProc;
size_t CharLen;
UINTN MaxColumn;
UINTN MaxRow;
wchar_t OutChar[2]; // Just in case we run into 4-byte MBCS character
int OutMode;
errno = 0; // indicate no error as default
NumWritten = -1;
/* Determine what the current screen size is. Also validates the output device. */
OutMode = IIO_GetOutputSize(filp->MyFD, &MaxColumn, &MaxRow);
This = filp->devdata;
if((This != NULL) && (OutMode >= 0)) {
if(filp->MyFD == STDERR_FILENO) {
OutBuf = This->ErrBuf;
OutState = &This->ErrState;
}
else {
OutBuf = This->OutBuf;
OutState = &This->OutState;
}
/* Set the maximum screen dimensions. */
This->MaxColumn = MaxColumn;
This->MaxRow = MaxRow;
/* Record where the cursor is at the beginning of the Output operation. */
(void)IIO_GetCursorPosition(filp->MyFD, &This->InitialXY.Column, &This->InitialXY.Row);
This->CurrentXY.Column = This->InitialXY.Column;
This->CurrentXY.Row = This->InitialXY.Row;
NumWritten = 0;
OutChar[0] = (wchar_t)buf[0];
while((OutChar[0] != 0) && (NumWritten < N)) {
CharLen = mbrtowc(OutChar, (const char *)&buf[NumWritten], MB_CUR_MAX, OutState);
NumProc = IIO_WriteOne(filp, OutBuf, OutChar[0]);
if(NumProc > 0) {
// Successfully processed and buffered one character
NumWritten += CharLen; // Index of start of next character
}
else if(NumProc == -1) {
// Encoding Error
(void)mbrtowc(NULL, NULL, 1, OutState); // Re-Initialize the conversion state
errno = EILSEQ;
break;
}
else {
// Last character was incomplete
break;
}
}
// At this point, the characters to write are in OutBuf
// First, linearize the buffer
NumWritten = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);
gMD->UString[NumWritten] = 0; // Ensure that the buffer is terminated
if(filp->f_iflags & _S_IWTTY) {
// Output device expects wide characters, Output what we have
NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, gMD->UString);
}
else {
// Output device expects narrow characters, convert to MBCS
MbcsPtr = (char *)gMD->UString2;
// Determine the needed space
NumProc = (ssize_t)EstimateWtoM((const wchar_t *)gMD->UString, UNICODE_STRING_MAX * sizeof(wchar_t), &CharLen);
// Now translate this into MBCS in Buffer
NumWritten = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);
MbcsPtr[NumWritten] = 0; // Ensure the buffer is terminated
// Send the MBCS buffer to Output
NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, MbcsPtr);
}
// Consume the translated characters
(void)OutBuf->Flush(OutBuf, NumWritten);
}
else {
if(This == NULL) {
errno = EINVAL;
}
// Otherwise, errno is already set.
}
return NumWritten;
}
/** Echo a character to an output device.
Performs translation and edit processing depending upon termios flags.
@param[in] filp A pointer to a file descriptor structure.
@param[in] EChar The character to echo.
@param[in] EchoIsOK TRUE if the caller has determined that characters
should be echoed. Otherwise, just buffer.
@return Returns the number of characters actually output.
**/
static
ssize_t
EFIAPI
IIO_Echo(
struct __filedes *filp,
wchar_t EChar,
BOOLEAN EchoIsOK
)
{
cIIO *This;
ssize_t NumWritten;
cFIFO *OutBuf;
char *MbcsPtr;
ssize_t NumProc;
tcflag_t LFlags;
NumWritten = -1;
This = filp->devdata;
if(This != NULL) {
OutBuf = This->OutBuf;
LFlags = This->Termio.c_lflag & (ECHOK | ECHOE);
if((EChar >= TtyFunKeyMin) && (EChar < TtyFunKeyMax)) {
// A special function key was pressed, buffer it, don't echo, and activate.
// Process and buffer the character. May produce multiple characters.
NumProc = IIO_EchoOne(filp, EChar, FALSE); // Don't echo this character
EChar = CHAR_LINEFEED; // Every line must end with '\n' (legacy)
}
// Process and buffer the character. May produce multiple characters.
NumProc = IIO_EchoOne(filp, EChar, EchoIsOK);
// At this point, the character(s) to write are in OutBuf
// First, linearize the buffer
NumWritten = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);
gMD->UString[NumWritten] = 0; // Ensure that the buffer is terminated
if((EChar == IIO_ECHO_KILL) && (LFlags & ECHOE) && EchoIsOK) {
// Position the cursor to the start of input.
(void)IIO_SetCursorPosition(filp, &This->InitialXY);
}
// Output the buffer
if(filp->f_iflags & _S_IWTTY) {
// Output device expects wide characters, Output what we have
NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, gMD->UString);
}
else {
// Output device expects narrow characters, convert to MBCS
MbcsPtr = (char *)gMD->UString2;
// Determine the needed space
NumProc = (ssize_t)EstimateWtoM((const wchar_t *)gMD->UString, UNICODE_STRING_MAX * sizeof(wchar_t), NULL);
// Now translate this into MBCS in Buffer
NumWritten = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);
MbcsPtr[NumWritten] = 0; // Ensure the buffer is terminated
// Send the MBCS buffer to Output
NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, MbcsPtr);
}
// Consume the echoed characters
(void)OutBuf->Flush(OutBuf, NumWritten);
if(EChar == IIO_ECHO_KILL) {
if(LFlags == ECHOK) {
NumWritten = IIO_WriteOne(filp, OutBuf, CHAR_LINEFEED);
}
else if((LFlags & ECHOE) && EchoIsOK) {
// Position the cursor to the start of input.
(void)IIO_SetCursorPosition(filp, &This->InitialXY);
}
NumWritten = 0;
}
}
else {
errno = EINVAL;
}
return NumWritten;
}
static
void
FifoDelete(cFIFO *Member)
{
if(Member != NULL) {
Member->Delete(Member);
}
}
/** Destructor for an IIO instance.
Releases all resources used by a particular IIO instance.
**/
static
void
EFIAPI
IIO_Delete(
cIIO *Self
)
{
if(Self != NULL) {
FifoDelete(Self->ErrBuf);
FifoDelete(Self->OutBuf);
FifoDelete(Self->InBuf);
if(Self->AttrBuf != NULL) {
FreePool(Self->AttrBuf);
}
FreePool(Self);
}
}
/** Constructor for new IIO instances.
@return Returns NULL or a pointer to a new IIO instance.
**/
cIIO *
EFIAPI
New_cIIO(void)
{
cIIO *IIO;
cc_t *TempBuf;
int i;
IIO = (cIIO *)AllocateZeroPool(sizeof(cIIO));
if(IIO != NULL) {
IIO->InBuf = New_cFIFO(MAX_INPUT, sizeof(wchar_t));
IIO->OutBuf = New_cFIFO(MAX_OUTPUT, sizeof(wchar_t));
IIO->ErrBuf = New_cFIFO(MAX_OUTPUT, sizeof(wchar_t));
IIO->AttrBuf = (UINT8 *)AllocateZeroPool(MAX_OUTPUT);
if((IIO->InBuf == NULL) || (IIO->OutBuf == NULL) ||
(IIO->ErrBuf == NULL) || (IIO->AttrBuf == NULL))
{
IIO_Delete(IIO);
IIO = NULL;
}
else {
IIO->Delete = IIO_Delete;
IIO->Read = IIO_Read;
IIO->Write = IIO_Write;
IIO->Echo = IIO_Echo;
}
// Initialize Termio member
TempBuf = &IIO->Termio.c_cc[0];
TempBuf[0] = 8; // Default length for TABs
for(i=1; i < NCCS; ++i) {
TempBuf[i] = _POSIX_VDISABLE;
}
TempBuf[VMIN] = 0;
TempBuf[VTIME] = 0;
IIO->Termio.c_ispeed = B115200;
IIO->Termio.c_ospeed = B115200;
IIO->Termio.c_iflag = ICRNL;
IIO->Termio.c_oflag = OPOST | ONLCR | ONOCR | ONLRET;
IIO->Termio.c_cflag = 0;
IIO->Termio.c_lflag = ECHO | ECHONL;
}
return IIO;
}

View File

@ -0,0 +1,51 @@
## @file
# Interactive I/O Library.
#
# Copyright (c) 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 which accompanies this
# distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php.
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = LibIIO
FILE_GUID = c1e9fffb-5557-4cb5-a5f5-1fbd902a74ed
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = LibIIO
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
IIO.c
NonCanonRead.c
CanonRead.c
TerminalFunctions.c
IIOutilities.c
IIOwrite.c
IIOecho.c
[Packages]
MdePkg/MdePkg.dec
StdLib/StdLib.dec
StdLibPrivateInternalFiles/DoNotUse.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
MemoryAllocationLib
LibC
LibWchar
LibContainer
[Protocols]
gEfiSimpleTextInProtocolGuid ## CONSUMES
gEfiSimpleTextOutProtocolGuid ## CONSUMES

View File

@ -0,0 +1,141 @@
/** @file
Echo characters to an Interactive I/O Output device.
The functions assume that isatty() is TRUE at the time they are called.
Since the UEFI console is a WIDE character device, these functions do all
processing using wide characters.
It is the responsibility of the caller, or higher level function, to perform
any necessary translation between wide and narrow characters.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <LibConfig.h>
#include <assert.h>
#include <errno.h>
#include <sys/termios.h>
#include <Device/IIO.h>
#include "IIOutilities.h"
#include "IIOechoCtrl.h"
/** Echo one character to an IIO file.
If character InCh is a special "echo control" character, process it and output
the resultant character(s), if any. Otherwise pass the character on to the
IIO_WriteOne() function which performs generic output processing, if needed.
@param[in] filp Pointer to an open IIO file's file descriptor structure.
@param[in] InCh The wide character to be echoed.
@param[in] EchoIsOK A flag indicating whether echoing is appropriate for this
device or not.
@retval -1 The filp argument does not refer to an IIO device.
Global value errno is set to EINVAL.
@retval >=0 The number of characters actually output.
@sa IIO_WriteOne
**/
ssize_t
IIO_EchoOne (
struct __filedes *filp,
wchar_t InCh,
BOOLEAN EchoIsOK
)
{
cIIO *This;
cFIFO *OutBuf;
cFIFO *InBuf;
UINT8 *AttrBuf;
ssize_t NumEcho;
tcflag_t LFlags;
UINT32 AttrDex;
int i;
NumEcho = -1;
This = filp->devdata;
if(This != NULL) {
LFlags = This->Termio.c_lflag;
OutBuf = This->OutBuf;
InBuf = This->InBuf;
AttrBuf = This->AttrBuf;
AttrDex = InBuf->GetWDex(InBuf);
switch(InCh) {
case IIO_ECHO_DISCARD:
// Do not buffer or otherwise process
NumEcho = 0;
break;
case IIO_ECHO_ERASE:
// Delete last character from InBuf
if(!InBuf->IsEmpty(InBuf)) {
(void)InBuf->Truncate(InBuf);
// Erase screen character(s) based on Attrib value
if(LFlags & ECHO) {
AttrDex = (UINT32)ModuloDecrement(AttrDex, InBuf->NumElements);
NumEcho = AttrBuf[AttrDex];
for(i = 0; i < NumEcho; ++i) {
(void)IIO_WriteOne(filp, OutBuf, CHAR_BACKSPACE);
}
if(LFlags & ECHOE) {
for(i = 0; i < NumEcho; ++i) {
(void)IIO_WriteOne(filp, OutBuf, L' ');
}
for(i = 0; i < NumEcho; ++i) {
(void)IIO_WriteOne(filp, OutBuf, CHAR_BACKSPACE);
}
}
}
else {
NumEcho = 0;
}
}
break;
case IIO_ECHO_KILL:
// Flush contents of InBuf and OutBuf
InBuf->Flush(InBuf, (size_t)-1);
OutBuf->Flush(OutBuf, (size_t)-1);
// Erase characters from screen.
if(LFlags & ECHOE) {
NumEcho = IIO_CursorDelta(This, &This->InitialXY, &This->CurrentXY);
for(i = 0; i < NumEcho; ++i) {
(void)IIO_WriteOne(filp, OutBuf, L' ');
}
}
break;
default:
// Add character to input buffer
(void)InBuf->Write(InBuf, &InCh, 1);
NumEcho = 0; // In case echoing is not enabled or OK
// If echoing is OK and enabled, "echo" character using IIO_WriteOne
if( EchoIsOK &&
( (LFlags & ECHO) ||
((LFlags & ECHONL) && (InCh == CHAR_LINEFEED))))
{
NumEcho = IIO_WriteOne(filp, OutBuf, InCh);
}
AttrBuf[AttrDex] = (UINT8)NumEcho;
break;
}
}
else {
errno = EINVAL;
}
return NumEcho;
}

View File

@ -0,0 +1,33 @@
/** @file
Constants and declarations for the Echo function.
Copyright (c) 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 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.
**/
#ifndef _IIO_ECHO_CTRL_H
#define _IIO_ECHO_CTRL_H
#include <sys/termios.h>
__BEGIN_DECLS
/* These constants are assigned values within the Unicode Private Use range.
The value of IIO_ECHO_MIN must be adjusted to ensure that IIO_ECHO_MAX
never exceeds the value of 0xF900.
*/
typedef enum {
IIO_ECHO_MIN = (TtyFunKeyMin - 3),
IIO_ECHO_DISCARD = IIO_ECHO_MIN, // Ignore this character completely
IIO_ECHO_ERASE, // Erase previous character
IIO_ECHO_KILL, // Kill the entire line
IIO_ECHO_MAX
} IioEchoCtrl;
__END_DECLS
#endif /* _IIO_ECHO_CTRL_H */

View File

@ -0,0 +1,288 @@
/** @file
Utilities for Interactive I/O Functions.
The functions assume that isatty() is TRUE at the time they are called.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Protocol/SimpleTextOut.h>
#include <LibConfig.h>
#include <assert.h>
#include <errno.h>
#include <sys/syslimits.h>
#include <sys/termios.h>
#include <Device/IIO.h>
#include <MainData.h>
#include "IIOutilities.h"
/** Get the low-level UEFI protocol associated with an open file.
@param[in] fd File descriptor for an open file.
@param[out] filp NULL, or a pointer to where a pointer to the file's
file descriptor structure is to be stored.
@return Returns NULL if fd is not a valid file descriptor, otherwise
a pointer to the file's associated UEFI protocol is returned.
**/
void *
EFIAPI
IIO_GetDeviceProto (
int fd,
struct __filedes **filp
)
{
void *Proto;
ConInstance *Stream;
struct __filedes *pfil;
Proto = NULL;
if(ValidateFD( fd, VALID_OPEN)) {
pfil = &gMD->fdarray[fd];
Stream = BASE_CR(pfil->f_ops, ConInstance, Abstraction);
Proto = (void *)Stream->Dev;
if(filp != NULL) {
*filp = pfil;
}
}
return Proto;
}
/** Get a character either from the input buffer or from hardware.
@param[in] filp Pointer to a file descriptor structure.
@param[in] First Set to TRUE to identify the initial read.
@return Returns a character read from either the input buffer
or from the open file (device) identified by filp.
A return value of WEOF indicates an error has occurred.
**/
wint_t
EFIAPI
IIO_GetInChar (
struct __filedes *filp,
BOOLEAN First
)
{
cIIO *This;
cFIFO *InBuf;
EFI_STATUS Status;
ssize_t NumRead;
wint_t RetVal;
wchar_t InChar;
static size_t BufCnt;
This = filp->devdata;
InBuf = This->InBuf;
NumRead = -1;
InChar = 0;
if(First) {
BufCnt = InBuf->Count(InBuf, AsElements);
}
if(BufCnt > 0) {
Status = InBuf->Read(InBuf, &InChar, 1);
--BufCnt;
NumRead = 1;
}
else {
NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar);
}
if(NumRead <= 0) {
RetVal = WEOF;
}
else {
RetVal = (wint_t)InChar;
}
return InChar;
}
/** Get the current cursor position.
@param[in] fd File descriptor for an open file.
@param[out] Column Pointer to where the current cursor column is to be stored.
@param[out] Row Pointer to where the current cursor row is to be stored.
@retval -1 fd is not an IIO output device.
@retval 0 Cursor position retrieved, Cursor is Not Visible.
@retval 1 Cursor position retrieved, Cursor is Visible.
**/
int
EFIAPI
IIO_GetCursorPosition (
int fd,
UINT32 *Column,
UINT32 *Row
)
{
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
struct __filedes *pStdOut;
int RetVal;
RetVal = -1;
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
if(Proto != NULL) {
if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY
((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output
{
// fd is for a TTY or "Interactive IO" device
*Column = Proto->Mode->CursorColumn;
*Row = Proto->Mode->CursorRow;
if(Proto->Mode->CursorVisible) {
RetVal = 1;
}
else {
RetVal = 0;
}
}
}
return RetVal;
}
/** Set the cursor position.
@param[in] filp Pointer to the output device's file descriptor structure.
@param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating
the desired coordinate to move the cursor to.
@retval -1 fd is not an IIO output device
@retval 0 Cursor position set successfully.
**/
int
EFIAPI
IIO_SetCursorPosition (
struct __filedes *filp,
CURSOR_XY *CursorXY
)
{
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
cIIO *This;
EFI_STATUS Status;
int RetVal;
RetVal = -1;
This = filp->devdata;
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(filp->MyFD, NULL);
if(Proto != NULL) {
if(((filp->f_iflags & _S_ITTY) != 0) && // file is a TTY
((filp->Oflags & O_ACCMODE) != 0)) // and it is open for output
{
// fd is for a TTY or "Interactive IO" device
Status = Proto->SetCursorPosition(Proto, CursorXY->Column, CursorXY->Row);
if(Status == EFI_SUCCESS) {
This->CurrentXY.Column = CursorXY->Column;
This->CurrentXY.Row = CursorXY->Row;
RetVal = 0;
}
}
}
return RetVal;
}
/** Get Output screen size and mode.
@param[in] fd File descriptor of the output device.
@param[out] Col Pointer to where to store the MAX Column, or NULL.
@param[out] Row Pointer to where to store the MAX Row, or NULL.
@retval <0 An error occurred. The reason is in errno and EFIerrno.
* EIO UEFI QueryMode failed
* ENOTTY fd does not refer to an interactive output device
@retval >=0 Current output mode
**/
int
EFIAPI
IIO_GetOutputSize (
int fd,
UINTN *Col,
UINTN *Row
)
{
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
struct __filedes *pStdOut;
EFI_STATUS Status;
UINTN TempCol;
UINTN TempRow;
UINTN TempMode;
int RetVal;
RetVal = -1;
Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
if(Proto != NULL) {
if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY
((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output
{
// fd is for a TTY or "Interactive IO" device
TempMode = Proto->Mode->Mode;
Status = Proto->QueryMode(Proto, TempMode, &TempCol, &TempRow);
if(EFI_ERROR(Status)) {
EFIerrno = Status;
errno = EIO;
}
else {
*Col = TempCol;
*Row = TempRow;
RetVal = (int)TempMode;
}
}
else {
errno = ENOTTY;
}
}
return RetVal;
}
/** Calculate the number of character positions between two X/Y coordinate pairs.
Using the current output device characteristics, calculate the number of
characters between two coordinates. It is assumed that EndXY points to
an output location that occurs after StartXY.
RowDelta is the computed difference between the ending and starting rows.
If RowDelta < 0, then EndXY is NOT after StartXY, so assert.
ColumnDelta is the computed number of character positions (columns) between
the starting position and the ending position. If ColumnDelta is < 0,
then EndXY is NOT after StartXY, so assert.
@param[in] This Pointer to the IIO instance to be examined.
@param[in] StartXY Pointer to the starting coordinate pair.
@param[in] EndXY Pointer to the ending coordinate pair.
@return Returns the difference between the starting and ending coordinates.
**/
UINT32
EFIAPI
IIO_CursorDelta (
cIIO *This,
CURSOR_XY *StartXY,
CURSOR_XY *EndXY
)
{
INT32 ColumnDelta;
INT32 RowDelta;
RowDelta = (int)EndXY->Row - (int)StartXY->Row;
assert(RowDelta >= 0); // assert if EndXY is NOT after StartXY
ColumnDelta = (INT32)((This->MaxColumn * RowDelta) + EndXY->Column);
ColumnDelta -= (INT32)StartXY->Column;
assert(ColumnDelta >= 0); // assert if EndXY is NOT after StartXY
return (UINT32)ColumnDelta;
}

View File

@ -0,0 +1,129 @@
/** @file
Utilities for Interactive I/O Functions.
The functions assume that isatty() is TRUE at the time they are called.
Copyright (c) 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 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.
**/
#ifndef _IIO_UTILITIES_H
#define _IIO_UTILITIES_H
#include <sys/EfiSysCall.h>
__BEGIN_DECLS
/** Get the low-level UEFI protocol associated with an open file.
@param[in] fd File descriptor for an open file.
@param[out] filp NULL, or a pointer to where a pointer to the file's
file descriptor structure is to be stored.
@return Returns NULL if fd is not a valid file descriptor, otherwise
a pointer to the file's associated UEFI protocol is returned.
**/
void *
EFIAPI
IIO_GetDeviceProto (
int fd,
struct __filedes **filp // Optional - filp == NULL if unused
);
/** Get a character either from the input buffer or from hardware.
@param[in] filp Pointer to a file descriptor structure.
@param[in] First Set to TRUE to identify the initial read.
@return Returns a character read from either the input buffer
or from the open file (device) identified by filp.
A return value of WEOF indicates an error has occurred.
**/
wint_t
EFIAPI
IIO_GetInChar (
struct __filedes *filp,
BOOLEAN First
);
/** Get the current cursor position.
@param[in] fd File descriptor for an open file.
@param[out] Column Pointer to where the current cursor column is to be stored.
@param[out] Row Pointer to where the current cursor row is to be stored.
@retval -1 fd is not an IIO output device.
@retval 0 Cursor position retrieved, Cursor is Not Visible.
@retval 1 Cursor position retrieved, Cursor is Visible.
**/
int
EFIAPI
IIO_GetCursorPosition (
int fd,
UINT32 *Column,
UINT32 *Row
);
/** Set the cursor position.
@param[in] filp Pointer to the output device's file descriptor structure.
@param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating
the desired coordinate to move the cursor to.
@retval -1 fd is not an IIO output device
@retval 0 Cursor position set successfully.
**/
int
EFIAPI
IIO_SetCursorPosition (
struct __filedes *filp,
CURSOR_XY *StartXY
);
/** Get Output screen size and mode.
@param[in] fd File descriptor of the output device.
@param[out] Col Pointer to where to store the MAX Column, or NULL.
@param[out] Row Pointer to where to store the MAX Row, or NULL.
@retval <0 An error occurred. The reason is in errno and EFIerrno.
* EIO UEFI QueryMode failed
* ENOTTY fd does not refer to an interactive output device
@retval >=0 Current output mode
**/
int
EFIAPI
IIO_GetOutputSize (
int fd,
UINTN *Col,
UINTN *Row
);
/** Calculate the number of character positions between two X/Y coordinate pairs.
Using the current output device characteristics, calculate the number of
characters between two coordinates.
@param[in] This Pointer to the IIO instance to be examined.
@param[in] StartXY Pointer to the starting coordinate pair.
@param[in] EndXY Pointer to the ending coordinate pair.
@return Returns the difference between the starting and ending coordinates.
The return value is positive if the coordinates contained in EndXY
are larger than StartXY, otherwise the return value is negative.
**/
int
EFIAPI
IIO_CursorDelta (
cIIO *This,
CURSOR_XY *StartXY,
CURSOR_XY *EndXY
);
__END_DECLS
#endif /* _IIO_UTILITIES_H */

View File

@ -0,0 +1,210 @@
/** @file
Write to an Interactive I/O Output device.
The functions assume that isatty() is TRUE at the time they are called.
Since the UEFI console is a WIDE character device, these functions do all
processing using wide characters.
It is the responsibility of the caller, or higher level function, to perform
any necessary translation between wide and narrow characters.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <LibConfig.h>
#include <assert.h>
#include <errno.h>
#include <sys/termios.h>
#include <Device/IIO.h>
static wchar_t Spaces[] = L" "; // Spaces for expanding TABs
#define MAX_TAB_WIDTH ((int)(sizeof(Spaces) / sizeof(wchar_t)) - 1)
#define MAX_EXPANSION 3
/** Process and buffer one character for output.
@param[in] filp Pointer to a file descriptor structure.
@param[out] OBuf Pointer to the Output Buffer FIFO.
@param[in] InCh The wide character to process.
@retval <0 An error occurred. Reason is in errno.
* EINVAL The pointer to the IIO object is NULL.
* ENOSPC The OBuf FIFO is full.
@retval 0 A character was input but not placed in the output buffer.
@retval >0 The number of characters buffered. Normally 1, or 2.
If a character is discarded because of flag settings, a
1 will be returned.
**/
ssize_t
IIO_WriteOne(struct __filedes *filp, cFIFO *OBuf, wchar_t InCh)
{
cIIO *This;
struct termios *Termio;
tcflag_t OFlag;
ssize_t RetVal;
wchar_t wc[MAX_EXPANSION]; // Sub-buffer for conversions
wchar_t *wcb; // Pointer to either wc or spaces
int numW = 0; // Wide characters placed in OBuf
INT32 TabWidth; // Each TAB expands into this number of spaces
UINT32 CurColumn; // Current cursor column on the screen
UINT32 CurRow; // Current cursor row on the screen
UINT32 PrevColumn; // Previous column. Used to detect wrapping.
UINT32 AdjColumn; // Current cursor column on the screen
UINT32 AdjRow; // Current cursor row on the screen
RetVal = -1;
wcb = wc;
This = filp->devdata;
if((This != NULL) && (OBuf->FreeSpace(OBuf, AsElements) >= MAX_EXPANSION)) {
Termio = &This->Termio;
OFlag = Termio->c_oflag;
TabWidth = (INT32)This->Termio.c_cc[VTABLEN];
if(TabWidth > MAX_TAB_WIDTH) {
TabWidth = MAX_TAB_WIDTH;
}
CurColumn = This->CurrentXY.Column;
CurRow = This->CurrentXY.Row;
numW = 1; // The majority of characters buffer one character
AdjRow = 0; // Most characters just cause horizontal movement
AdjColumn = 0;
if(OFlag & OPOST) {
/* Perform output processing */
switch(InCh) {
case CHAR_TAB: //{{
if(OFlag & OXTABS) {
if(TabWidth > 0) {
int SpaceIndex;
SpaceIndex = CurColumn % TabWidth; // Number of spaces after a Tab Stop
numW = TabWidth - SpaceIndex; // Number of spaces to the next Tab Stop
SpaceIndex = MAX_TAB_WIDTH - numW; // Index into the Spaces array
wcb = &Spaces[SpaceIndex]; // Point to the appropriate number of spaces
}
else {
wc[0] = L' ';
}
AdjColumn = numW;
}
else {
wc[0] = InCh; // Send the TAB itself - assumes that it does not move cursor.
}
break; //}}
case CHAR_CARRIAGE_RETURN: //{{
if((OFlag & OCRNL) == 0) {
if((OFlag & ONLRET) == 0) {
numW = 0; /* Discard the CR */
// Cursor doesn't move
}
else {
wc[0] = CHAR_CARRIAGE_RETURN;
CurColumn = 0;
}
break;
}
else {
InCh = CHAR_LINEFEED;
} //}}
// Fall through to the NL case
case CHAR_LINEFEED: //{{
if(OFlag & ONLCR) {
wc[0] = CHAR_CARRIAGE_RETURN;
wc[1] = CHAR_LINEFEED;
numW = 2;
CurColumn = 0;
}
AdjRow = 1;
break; //}}
case CHAR_BACKSPACE: //{{
if(CurColumn > 0) {
wc[0] = CHAR_BACKSPACE;
CurColumn = (UINT32)ModuloDecrement(CurColumn, (UINT32)This->MaxColumn);
}
else {
numW = 0; // Discard the backspace if in column 0
}
break; //}}
case CHAR_EOT: //{{
if(OFlag & ONOEOT) {
numW = 0; // Discard the EOT character
// Cursor doesn't move
break;
} //}}
// Fall through to default in order to potentially output "^D"
default: //{{
if((InCh >= 0) && (InCh < L' ')) {
// InCh contains a control character
if(OFlag & OCTRL) {
wc[1] = InCh + L'@';
wc[0] = L'^';
numW = 2;
AdjColumn = 2;
}
else {
numW = 0; // Discard. Not a UEFI supported control character.
}
}
else {
// Regular printing character
wc[0] = InCh;
AdjColumn = 1;
}
break; //}}
}
if(numW < MAX_EXPANSION) {
wc[numW] = 0; // Terminate the sub-buffer
}
if(AdjColumn != 0) {
// Adjust the cursor position
PrevColumn = CurColumn;
CurColumn = ModuloAdd(PrevColumn, AdjColumn, (UINT32)This->MaxColumn);
if(CurColumn < PrevColumn) {
// We must have wrapped, so we are on the next Row
++CurRow;
if(CurRow >= This->MaxRow) {
// The screen has scrolled so need to adjust Initial location.
--This->InitialXY.Row; // Initial row has moved up one
CurRow = (UINT32)(This->MaxRow - 1); // We stay on the bottom row
}
}
}
This->CurrentXY.Column = CurColumn;
This->CurrentXY.Row = CurRow;
}
else {
// Output processing disabled -- RAW output mode
wc[0] = InCh;
wc[1] = 0;
}
// Put the character(s) into the output buffer
if(numW > 0) {
(void)OBuf->Write(OBuf, (const void *)wcb, (size_t)numW);
}
RetVal = numW;
}
else {
if(This == NULL) {
errno = EINVAL;
}
else {
errno = ENOSPC;
}
}
return RetVal;
}

View File

@ -0,0 +1,89 @@
/** @file
NonCanonical Interactive Input Function.
The functions assume that isatty() is TRUE at the time they are called.
If _S_IWTTY is set, the device returns WIDE characters.
Copyright (c) 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 which accompanies this
distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <LibConfig.h>
#include <sys/syslimits.h>
#include <sys/termios.h>
#include <Device/IIO.h>
#include <Containers/Fifo.h>
/** Perform a noncanonical read of input.
@param[in] filp Pointer to a file descriptor structure.
@param[in] BufferSize Maximum number of bytes to return.
@retval -1 An error has occurred. Reason in errno.
@retval -1 No data returned. None was ready.
@retval >0 The number of elements returned
**/
ssize_t
IIO_NonCanonRead (
struct __filedes *filp
)
{
cIIO *This;
cFIFO *InBuf;
struct termios *Termio;
EFI_STATUS Status;
ssize_t NumRead;
cc_t tioMin;
cc_t tioTime;
UINT32 InputType;
wchar_t InChar; // Intermediate character buffer
NumRead = -1;
InChar = 0; // Initialize so compilers don't complain.
This = filp->devdata;
Termio = &This->Termio;
InBuf = This->InBuf;
tioMin = Termio->c_cc[VMIN];
tioTime = Termio->c_cc[VTIME];
if(tioMin >= MAX_INPUT) {
tioMin = MAX_INPUT;
}
/* There are four types of processing that may be done, based on
the values of tioMin and tioTime.
Min Time Type
--- ---- ----
0 0 0 Return buffer contents or 1 new char
0 >0 1 Return 0 or 1 character depending on timeout
>0 0 2 Buffer Min chars. Return BufferSize chars.
>0 >0 3 Return up to Min chars. Unless the inter-byte timer expires.
Currently, only type 0 is implemented.
*/
InputType = 0;
if(tioMin != 0) InputType = 2;
if(tioTime != 0) ++InputType;
//switch(InputType) {
// case 0:
if(InBuf->IsEmpty(InBuf)) {
NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar);
if(NumRead > 0) {
Status = InBuf->Write(InBuf, &InChar, 1); // Buffer the character
}
}
// break;
// case 1:
// break;
// case 2:
// break;
// case 3:
// break;
//}
return NumRead;
}

View File

@ -0,0 +1,285 @@
/** @file
"Terminal" Control functions for Interactive IO.
Copyright (c) 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/BaseMemoryLib.h>
#include <LibConfig.h>
#include <errno.h>
#include <sys/termios.h>
#include <Device/IIO.h>
#include <MainData.h>
/** Get input baud rate.
Extracts the input baud rate from the termios structure pointed to by the
pTermios argument.
@param[in] pTermios A pointer to the termios structure from which to extract
the input baud rate.
@return The value of the input speed is returned exactly as it is contained
in the termios structure, without interpretation.
**/
speed_t
cfgetispeed (
const struct termios *pTermios
)
{
return pTermios->c_ispeed;
}
/** Get output baud rate.
Extracts the output baud rate from the termios structure pointed to by the
pTermios argument.
@param[in] pTermios A pointer to the termios structure from which to extract
the output baud rate.
@return The value of the output speed is returned exactly as it is contained
in the termios structure, without interpretation.
**/
speed_t
cfgetospeed (
const struct termios *pTermios
)
{
return pTermios->c_ospeed;
}
/** Set input baud rate.
Replaces the input baud rate, in the termios structure pointed to by the
pTermios argument, with the value of NewSpeed.
@param[out] pTermios A pointer to the termios structure into which to set
the input baud rate.
@param[in] NewSpeed The new input baud rate.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EINVAL - The value of NewSpeed is outside the range of
possible speed values as specified in <sys/termios.h>.
**/
int
cfsetispeed (
struct termios *pTermios,
speed_t NewSpeed
)
{
int RetVal;
if(NewSpeed < B921600) {
pTermios->c_ispeed = NewSpeed;
RetVal = 0;
}
else {
RetVal = -1;
errno = EINVAL;
}
return RetVal;
}
/** Set output baud rate.
Replaces the output baud rate, in the termios structure pointed to by the
pTermios argument, with the value of NewSpeed.
@param[out] pTermios A pointer to the termios structure into which to set
the output baud rate.
@param[in] NewSpeed The new output baud rate.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EINVAL - The value of NewSpeed is outside the range of
possible speed values as specified in <sys/termios.h>.
**/
int
cfsetospeed (
struct termios *pTermios,
speed_t NewSpeed
)
{
int RetVal;
if(NewSpeed < B921600) {
pTermios->c_ospeed = NewSpeed;
RetVal = 0;
}
else {
RetVal = -1;
errno = EINVAL;
}
return RetVal;
}
/** Get the parameters associated with an interactive IO device.
Get the parameters associated with the device referred to by
fd and store them into the termios structure referenced by pTermios.
@param[in] fd The file descriptor for an open interactive IO device.
@param[out] pTermios A pointer to a termios structure into which to store
attributes of the interactive IO device.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EBADF - The fd argument is not a valid file descriptor.
* ENOTTY - The file associated with fd is not an interactive IO device.
**/
int
tcgetattr (
int fd,
struct termios *pTermios
)
{
cIIO *IIO;
int RetVal;
struct __filedes *filp;
struct termios *Termio;
RetVal = 0;
if(ValidateFD( fd, VALID_OPEN)) {
filp = &gMD->fdarray[fd];
if((filp->f_iflags & _S_ITTY) != 0) {
// fd is for a TTY or "Interactive IO" device
IIO = (cIIO *)filp->devdata;
Termio = &IIO->Termio;
(void)CopyMem((void *)pTermios, (const void *)Termio, sizeof(struct termios));
}
else {
errno = ENOTTY;
RetVal = -1;
}
}
else {
errno = EBADF;
RetVal = -1;
}
return RetVal;
}
/** Set the parameters associated with an interactive IO device.
Set the parameters associated with the device referred to by
fd to the values in the termios structure referenced by pTermios.
Behavior is modified by the value of the OptAct parameter:
* TCSANOW: The change shall occur immediately.
* TCSADRAIN: The change shall occur after all output written to fd is
transmitted. This action should be used when changing parameters which
affect output.
* TCSAFLUSH: The change shall occur after all output written to fd is
transmitted, and all input so far received but not read shall be
discarded before the change is made.
@param[in] fd The file descriptor for an open interactive IO device.
@param[in] OptAct Currently has no effect.
@param[in] pTermios A pointer to a termios structure into which to retrieve
attributes to set in the interactive IO device.
@retval 0 The operation completed successfully.
@retval -1 An error occured and errno is set to indicate the error.
* EBADF - The fd argument is not a valid file descriptor.
* ENOTTY - The file associated with fd is not an interactive IO device.
**/
int
tcsetattr (
int fd,
int OptAct, // Currently ignored
const struct termios *pTermios
)
{
cIIO *IIO;
int RetVal;
struct __filedes *filp;
struct termios *Termio;
RetVal = 0;
if(ValidateFD( fd, VALID_OPEN)) {
filp = &gMD->fdarray[fd];
if((filp->f_iflags & _S_ITTY) != 0) {
// fd is for a TTY or "Interactive IO" device
IIO = (cIIO *)filp->devdata;
Termio = &IIO->Termio;
(void)CopyMem((void *)Termio, (const void *)pTermios, sizeof(struct termios));
}
else {
errno = ENOTTY;
RetVal = -1;
}
}
else {
errno = EBADF;
RetVal = -1;
}
return RetVal;
}
/** Transmit pending output.
Function is not yet implemented for UEFI.
@param[in] fd Ignored
@retval -1 This function is not yet supported. errno is set to ENOTSUP.
**/
int
tcdrain (int fd)
{
errno = ENOTSUP;
return -1;
}
/** Suspend or restart the transmission or reception of data.
This function will suspend or resume transmission or reception of data on
the file referred to by fd, depending on the value of Action.
Function is not yet implemented for UEFI.
@param[in] fd Ignored
@param[in] Action Ignored
@retval -1 This function is not yet supported. errno is set to ENOTSUP.
**/
int
tcflow (
int fd,
int Action)
{
errno = ENOTSUP;
return -1;
}
/** Discard non-transmitted output data, non-read input data, or both.
Function is not yet implemented for UEFI.
@param[in] fd Ignored
@param[in] QueueSelector Ignored
@retval -1 This function is not yet supported. errno is set to ENOTSUP.
**/
int
tcflush (
int fd,
int QueueSelector)
{
errno = ENOTSUP;
return -1;
}

View File

@ -36,6 +36,7 @@
#include <unistd.h>
#include <kfile.h>
#include <Device/Device.h>
#include <Device/IIO.h>
#include <MainData.h>
#include <extern.h>
@ -114,12 +115,14 @@ DeleteOnClose(int fd)
return retval;
}
/** The isatty() function tests whether fildes, an open file descriptor,
/** The isatty() function tests whether fd, an open file descriptor,
is associated with a terminal device.
@retval 1 fildes is associated with a terminal.
@retval 0 fildes is not associated with a terminal. errno is set to
EBADF if fildes is not a valid open FD.
@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)
@ -129,7 +132,7 @@ isatty (int fd)
if(ValidateFD( fd, VALID_OPEN)) {
Fp = &gMD->fdarray[fd];
retval = Fp->f_iflags & _S_ITTY;
retval = (Fp->f_iflags & _S_ITTY) ? 1 : 0;
}
else {
errno = EBADF;
@ -169,13 +172,14 @@ IsDupFd( int fd)
return Ret;
}
/** Close a file and set its fd to the specified state.
/** 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)
@ -221,6 +225,8 @@ _closeX (int fd, int NewState)
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.
**/
@ -230,7 +236,14 @@ 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)
@ -315,6 +328,10 @@ unlink (const char *path)
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.
@ -407,6 +424,8 @@ fcntl (int fildes, int cmd, ...)
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.
@ -417,7 +436,9 @@ dup (int fildes)
return fcntl(fildes, F_DUPFD, 0);
}
/** The dup2() function provides an alternative interface to the
/** 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:
@ -433,6 +454,9 @@ dup (int fildes)
- 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.
@ -470,13 +494,13 @@ dup2 (int fildes, int fildes2)
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_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_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.
- 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
@ -486,6 +510,10 @@ dup2 (int fildes, int fildes2)
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
@ -524,6 +552,9 @@ lseek (int fd, __off_t offset, int how)
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.
**/
@ -606,19 +637,19 @@ mkdir (const char *path, __mode_t perms)
@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>.
<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.
@retval EMFILE No file descriptors available -- Max number already open.
@retval EINVAL Bad value specified for oflags or mode.
@retval ENOMEM Failure allocating memory for internal buffers.
@retval EEXIST File exists and open attempted with (O_EXCL | O_CREAT) set.
@retval EIO UEFI failure. Check value in EFIerrno.
- 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(
@ -631,18 +662,20 @@ open(
wchar_t *MPath;
DeviceNode *Node;
struct __filedes *filp;
struct termios *Termio;
int Instance = 0;
RETURN_STATUS Status;
UINT64 OpenMode;
UINT32 OpenMode;
int fd = -1;
int doresult;
Status = ParsePath(path, &NewPath, &Node, &Instance, &MPath);
if(Status == RETURN_SUCCESS) {
if((Node == NULL) ||
(Node->InstanceList == 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.
@ -666,23 +699,31 @@ open(
fd = -1; // Indicate an error
}
else {
// Re-use OpenMode in order to build our final f_iflags value
// 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 |= (UINT32)OpenMode;
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;
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);
}
}
}
if(NewPath != NULL) {
free(NewPath);
}
}
if(MPath != NULL) {
free(MPath); // We don't need this any more.
}
// return the fd of our now open file
return fd;
}
@ -699,11 +740,11 @@ open(
<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] pfd Address of an array of pollfd structures.
@param [in] nfds Number of elements in the 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
@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.
@ -841,38 +882,44 @@ poll (
/** The rename() function changes the name of a file.
The old argument points to the pathname of the file to be renamed. The new
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 old argument points to the pathname of a file that is not a
directory, the new argument shall not point to the pathname of a
directory. If the file named by the new argument exists, it shall be
removed and old renamed to new. Write access permission is required for
both the directory containing old and the directory containing new.
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 old argument points to the pathname of a directory, the new
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 new argument exists, it shall be
removed and old renamed to new.
directory. If the directory named by the To argument exists, it shall be
removed and From renamed to To.
The new pathname shall not contain a path prefix that names old. Write
access permission is required for the directory containing old and the
directory containing new. If the old argument points to the pathname of a
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 old, and, if it exists, the directory named by new.
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 new shall be unaffected.
named by To shall be unaffected.
@return Upon successful completion, rename() shall return 0; otherwise,
-1 shall be returned, errno shall be set to indicate the error,
and neither the file named by old nor the file named by new
shall be changed or created.
@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
const char *From,
const char *To
)
{
wchar_t *FromPath;
@ -882,7 +929,7 @@ rename(
RETURN_STATUS Status;
int retval = -1;
Status = ParsePath(from, &FromPath, &FromNode, &Instance, NULL);
Status = ParsePath(From, &FromPath, &FromNode, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = FromNode->InstanceList;
if(GenI == NULL) {
@ -891,14 +938,19 @@ rename(
}
else {
//GenI += (Instance * FromNode->InstanceSize);
retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( from, to);
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(
@ -921,10 +973,10 @@ rmdir(
}
/** The fstat() function obtains information about an open file associated
with the file descriptor fildes, and shall write it to the area pointed to
by buf.
with the file descriptor fd, and writes it to the area pointed to
by statbuf.
The buf argument is a pointer to a stat structure, as defined
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,
@ -939,7 +991,7 @@ rmdir(
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 fildes
- st_mode Populated with information from fd
- st_ino Set to zero. (inode)
- st_dev Set to zero.
- st_uid Set to zero.
@ -974,6 +1026,9 @@ fstat (int fd, struct stat *statbuf)
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.
@ -994,7 +1049,15 @@ stat (const char *path, struct stat *statbuf)
return retval;
}
/** Same as stat since EFI doesn't have symbolic links. **/
/** 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)
{
@ -1002,6 +1065,13 @@ lstat (const char *path, struct stat *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(
@ -1098,6 +1168,10 @@ ioctl(
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
@ -1109,62 +1183,91 @@ ssize_t
read (int fildes, void *buf, size_t nbyte)
{
struct __filedes *filp;
cIIO *IIO;
ssize_t BufSize;
BufSize = (ssize_t)nbyte;
if(ValidateFD( fildes, VALID_OPEN)) {
filp = &gMD->fdarray[fildes];
if(BufSize > 0) {
if(ValidateFD( fildes, VALID_OPEN)) {
filp = &gMD->fdarray[fildes];
BufSize = filp->f_ops->fo_read(filp, &filp->f_offset, nbyte, buf);
}
else {
errno = EBADF;
BufSize = -EBADF;
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, which is returned in BufferSize. 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.
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, which is returned in BufferSize. 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 will not be
counted. Unconvertable characters are translated into the UEFI character
BLOCKELEMENT_LIGHT_SHADE.
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 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 single-byte character stream which is then translated to wide
characters using the btowc() functions. The resulting wide character stream
is what is actually sent to the UEFI console.
Since the UEFI console device works on wide characters, the buffer is assumed
to contain a single-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.
QUESTION: Should writes to stdout or stderr always succeed?
@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;
// EFI_FILE_HANDLE FileHandle;
// RETURN_STATUS Status = RETURN_SUCCESS;
BufSize = (ssize_t)nbyte;
if(ValidateFD( fd, VALID_OPEN)) {
filp = &gMD->fdarray[fd];
BufSize = filp->f_ops->fo_write(filp, &filp->f_offset, nbyte, buf);
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
BufSize = IIO->Write(filp, buf, nbyte);
}
else {
// Output to a 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 = -EBADF;
}
BufSize = -1;
}
return BufSize;
}
@ -1260,11 +1363,29 @@ chdir (const char *path)
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));
@ -1300,10 +1421,11 @@ va_Utimes(
/** Set file access and modification times.
@param[in] path
@param[in] times
@param[in] path Path to the file to be modified.
@param[in] times Pointer to an array of two timeval structures
@return
@retval 0 File times successfully set.
@retval -1 An error occured. Error type in errno.
**/
int
utimes(
@ -1313,4 +1435,3 @@ utimes(
{
return va_Utimes(path, times);
}

View File

@ -113,11 +113,15 @@
StdLib/LibC/Uefi/Devices/daConsole.inf
StdLib/LibC/Uefi/Devices/daShell.inf
# Additional, non-standard, libraries
StdLib/LibC/Containers/ContainerLib.inf
# Additional libraries for POSIX functionality.
StdLib/PosixLib/Err/LibErr.inf
StdLib/PosixLib/Gen/LibGen.inf
StdLib/PosixLib/Glob/LibGlob.inf
StdLib/PosixLib/Stringlist/LibStringlist.inf
StdLib/LibC/Uefi/InteractiveIO/IIO.inf
# Socket Libraries - LibC based
StdLib/BsdSocketLib/BsdSocketLib.inf

View File

@ -54,6 +54,10 @@
LibGen|StdLib/PosixLib/Gen/LibGen.inf
LibGlob|StdLib/PosixLib/Glob/LibGlob.inf
LibStringlist|StdLib/PosixLib/Stringlist/LibStringlist.inf
LibIIO|StdLib/LibC/Uefi/InteractiveIO/IIO.inf
# Additional, non-standard, libraries
LibContainer|StdLib/LibC/Containers/ContainerLib.inf
# Libraries for device abstractions within the Standard C Library
# Applications should not directly access any functions defined in these libraries.