summaryrefslogtreecommitdiffstats
path: root/StdLib/LibC/Uefi/SysCalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'StdLib/LibC/Uefi/SysCalls.c')
-rw-r--r--StdLib/LibC/Uefi/SysCalls.c313
1 files changed, 217 insertions, 96 deletions
diff --git a/StdLib/LibC/Uefi/SysCalls.c b/StdLib/LibC/Uefi/SysCalls.c
index 5576938f8e..c3b210120b 100644
--- a/StdLib/LibC/Uefi/SysCalls.c
+++ b/StdLib/LibC/Uefi/SysCalls.c
@@ -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.
-
- 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.
-
- QUESTION: Should writes to stdout or stderr always succeed?
+ 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.
+
+ 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.
+
+ @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);
}
-