mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
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:
parent
e575c101d8
commit
6c6c850ad6
206
StdLib/Include/Containers/Fifo.h
Normal file
206
StdLib/Include/Containers/Fifo.h
Normal 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 */
|
105
StdLib/Include/Containers/ModuloUtil.h
Normal file
105
StdLib/Include/Containers/ModuloUtil.h
Normal 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 */
|
@ -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
|
||||
|
149
StdLib/LibC/Containers/Common/ModuloUtil.c
Normal file
149
StdLib/LibC/Containers/Common/ModuloUtil.c
Normal 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;
|
||||
}
|
46
StdLib/LibC/Containers/ContainerLib.inf
Normal file
46
StdLib/LibC/Containers/ContainerLib.inf
Normal 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
|
526
StdLib/LibC/Containers/Queues/Fifo.c
Normal file
526
StdLib/LibC/Containers/Queues/Fifo.c
Normal 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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
161
StdLib/LibC/Uefi/InteractiveIO/CanonRead.c
Normal file
161
StdLib/LibC/Uefi/InteractiveIO/CanonRead.c
Normal 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;
|
||||
}
|
373
StdLib/LibC/Uefi/InteractiveIO/IIO.c
Normal file
373
StdLib/LibC/Uefi/InteractiveIO/IIO.c
Normal 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;
|
||||
}
|
51
StdLib/LibC/Uefi/InteractiveIO/IIO.inf
Normal file
51
StdLib/LibC/Uefi/InteractiveIO/IIO.inf
Normal 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
|
141
StdLib/LibC/Uefi/InteractiveIO/IIOecho.c
Normal file
141
StdLib/LibC/Uefi/InteractiveIO/IIOecho.c
Normal 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;
|
||||
}
|
33
StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h
Normal file
33
StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h
Normal 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 */
|
288
StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c
Normal file
288
StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c
Normal 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;
|
||||
}
|
129
StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h
Normal file
129
StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h
Normal 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 */
|
210
StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c
Normal file
210
StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c
Normal 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;
|
||||
}
|
89
StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c
Normal file
89
StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c
Normal 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;
|
||||
}
|
285
StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c
Normal file
285
StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c
Normal 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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user