]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/LibC/Uefi/SysCalls.c
2 EFI versions of NetBSD system calls.
4 Copyright (c) 2016, Daryl McDaniel. All rights reserved.<BR>
5 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/UefiLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/ShellLib.h>
22 #include <LibConfig.h>
23 #include <sys/EfiCdefs.h>
32 #include <sys/fcntl.h>
34 #include <sys/syslimits.h>
35 #include <sys/filio.h>
36 #include <Efi/SysEfi.h>
39 #include <Device/Device.h>
40 #include <Device/IIO.h>
44 /* EFI versions of BSD system calls used in stdio */
46 /* Validate that fd refers to a valid file descriptor.
47 IsOpen is interpreted as follows:
48 - Positive fd must be OPEN
49 - Zero fd must be CLOSED
50 - Negative fd may be OPEN or CLOSED
52 @retval TRUE fd is VALID
53 @retval FALSE fd is INVALID
56 ValidateFD( int fd
, int IsOpen
)
58 struct __filedes
*filp
;
59 BOOLEAN retval
= FALSE
;
61 if((fd
>= 0) && (fd
< OPEN_MAX
)) {
62 filp
= &gMD
->fdarray
[fd
];
65 retval
= (BOOLEAN
)((filp
->f_iflags
!= 0) && // TRUE if OPEN
66 FILE_IS_USABLE(filp
)); // and Usable (not Larval or Closing)
67 if(IsOpen
== VALID_CLOSED
) {
68 retval
= (BOOLEAN
)!retval
; // We want TRUE if CLOSED
75 /* Find and reserve a free File Descriptor.
77 Returns the first free File Descriptor greater than or equal to the,
78 already validated, fd specified by Minfd.
80 @return Returns -1 if there are no free FDs. Otherwise returns the
84 FindFreeFD( int MinFd
)
86 struct __filedes
*Mfd
;
92 // Get an available fd
93 for(i
=MinFd
; i
< OPEN_MAX
; ++i
) {
94 if(Mfd
[i
].f_iflags
== 0) {
95 Mfd
[i
].f_iflags
= FIF_LARVAL
; // Temporarily mark this fd as reserved
103 /* Mark that an open file is to be deleted when closed. */
105 DeleteOnClose(int fd
)
109 if(ValidateFD( fd
, VALID_OPEN
)) {
110 gMD
->fdarray
[fd
].f_iflags
|= FIF_DELCLOSE
;
119 /** The isatty() function tests whether fd, an open file descriptor,
120 is associated with a terminal device.
122 @param[in] fd File Descriptor for the file to be examined.
124 @retval 1 fd is associated with a terminal.
125 @retval 0 fd is not associated with a terminal. errno is set to
126 EBADF if fd is not a valid open FD.
132 struct __filedes
*Fp
;
134 if(ValidateFD( fd
, VALID_OPEN
)) {
135 Fp
= &gMD
->fdarray
[fd
];
136 retval
= (Fp
->f_iflags
& _S_ITTY
) ? 1 : 0;
144 /** Determine if file descriptor fd is a duplicate of some other fd.
146 @param[in] fd The file descriptor to check.
148 @retval TRUE fd is a duplicate of another fd.
149 @retval FALSE fd is unique.
155 const struct fileops
*FileOps
;
159 if(ValidateFD( fd
, VALID_OPEN
)) {
160 FileOps
= gMD
->fdarray
[fd
].f_ops
;
161 DevData
= gMD
->fdarray
[fd
].devdata
;
162 for(i
=0; i
< OPEN_MAX
; ++i
) {
163 if(i
== fd
) continue;
164 if(ValidateFD( i
, VALID_OPEN
)) { // TRUE if fd is valid and OPEN
165 if((gMD
->fdarray
[i
].f_ops
== FileOps
)
166 &&(gMD
->fdarray
[i
].devdata
== DevData
)) {
176 /** Worker function to Close a file and set its fd to the specified state.
178 @param[in] fd The file descriptor to close.
179 @param[in] NewState State to set the fd to after the file is closed.
181 @retval 0 The operation completed successfully.
182 @retval -1 The operation failed. Further information is in errno.
183 * EBADF fd is not a valid or open file descriptor.
186 _closeX (int fd
, int NewState
)
188 struct __filedes
*Fp
;
191 // Verify my pointers and get my FD.
192 if(ValidateFD( fd
, VALID_OPEN
)) {
193 Fp
= &gMD
->fdarray
[fd
];
194 // Check if there are other users of this FileHandle
195 if(Fp
->RefCount
== 1) { // There should be no other users
197 // Only do the close if no one else is using the FileHandle
198 if(Fp
->f_iflags
& FIF_DELCLOSE
) {
199 /* Handle files marked "Delete on Close". */
200 if(Fp
->f_ops
->fo_delete
!= NULL
) {
201 retval
= Fp
->f_ops
->fo_delete(Fp
);
205 retval
= Fp
->f_ops
->fo_close( Fp
);
208 Fp
->f_iflags
= NewState
; // Close this FD or reserve it
209 Fp
->RefCount
= 0; // No one using this FD
212 --Fp
->RefCount
; /* One less user of this FD */
223 /** The close() function deallocates the file descriptor indicated by fd.
224 To deallocate means to make the file descriptor available for return by
225 subsequent calls to open() or other functions that allocate file
226 descriptors. All outstanding record locks owned by the process on the file
227 associated with the file descriptor are removed (that is, unlocked).
229 @param[in] fd Descriptor for the File to close.
231 @retval 0 Successful completion.
232 @retval -1 An error occurred and errno is set to identify the error.
237 return _closeX(fd
, 0);
240 /** Delete the file specified by path.
242 @param[in] path The MBCS path of the file to delete.
244 @retval -1 Unable to open the file specified by path.
245 @retval -1 If (errno == EPERM), unlink is not permited for this file.
246 @retval -1 Low-level delete filed. Reason is in errno.
247 @retval 0 The file was successfully deleted.
250 unlink (const char *path
)
252 struct __filedes
*Fp
;
256 EFIerrno
= RETURN_SUCCESS
;
258 fd
= open(path
, O_WRONLY
, 0);
260 Fp
= &gMD
->fdarray
[fd
];
262 if(Fp
->f_ops
->fo_delete
!= NULL
) {
263 retval
= Fp
->f_ops
->fo_delete(Fp
);
265 Fp
->f_iflags
= 0; // Close this FD
266 Fp
->RefCount
= 0; // No one using this FD
271 /** The fcntl() function shall perform the operations described below on open
272 files. The fildes argument is a file descriptor.
274 The available values for cmd are defined in <fcntl.h> and are as follows:
275 - F_DUPFD - Return a new file descriptor which shall be the lowest
276 numbered available (that is, not already open) file
277 descriptor greater than or equal to the third argument, arg,
278 taken as an integer of type int. The new file descriptor
279 shall refer to the same open file description as the original
280 file descriptor, and shall share any locks. The FD_CLOEXEC
281 flag associated with the new file descriptor shall be cleared
282 to keep the file open across calls to one of the exec functions.
283 - F_GETFD - Get the file descriptor flags defined in <fcntl.h> that are
284 associated with the file descriptor fildes. File descriptor
285 flags are associated with a single file descriptor and do not
286 affect other file descriptors that refer to the same file.
287 - F_SETFD - Set the file descriptor flags defined in <fcntl.h>, that are
288 associated with fildes, to the third argument, arg, taken
289 as type int. If the FD_CLOEXEC flag in the third argument
290 is 0, the file shall remain open across the exec
291 functions; otherwise, the file shall be closed upon
292 successful execution of one of the exec functions.
293 - F_GETFL - Get the file status flags and file access modes, defined in
294 <fcntl.h>, for the file description associated with fildes.
295 The file access modes can be extracted from the return
296 value using the mask O_ACCMODE, which is defined in
297 <fcntl.h>. File status flags and file access modes are
298 associated with the file description and do not affect
299 other file descriptors that refer to the same file with
300 different open file descriptions.
301 - F_SETFL - Set the file status flags, defined in <fcntl.h>, for the file
302 description associated with fildes from the corresponding
303 bits in the third argument, arg, taken as type int. Bits
304 corresponding to the file access mode and the file creation
305 flags, as defined in <fcntl.h>, that are set in arg shall
306 be ignored. If any bits in arg other than those mentioned
307 here are changed by the application, the result is unspecified.
308 - F_GETOWN - If fildes refers to a socket, get the process or process group
309 ID specified to receive SIGURG signals when out-of-band
310 data is available. Positive values indicate a process ID;
311 negative values, other than -1, indicate a process group
312 ID. If fildes does not refer to a socket, the results are
314 - F_SETOWN - If fildes refers to a socket, set the process or process
315 group ID specified to receive SIGURG signals when
316 out-of-band data is available, using the value of the third
317 argument, arg, taken as type int. Positive values indicate
318 a process ID; negative values, other than -1, indicate a
319 process group ID. If fildes does not refer to a socket, the
320 results are unspecified.
322 The fcntl() function shall fail if:
324 [EBADF] The fildes argument is not a valid open file descriptor.
325 [EINVAL] The cmd argument is invalid, or the cmd argument is F_DUPFD
326 and arg is negative or greater than or equal to {OPEN_MAX}.
327 [EMFILE] The argument cmd is F_DUPFD and {OPEN_MAX} file descriptors
328 are currently open in the calling process, or no file
329 descriptors greater than or equal to arg are available.
330 [EOVERFLOW] One of the values to be returned cannot be represented correctly.
332 @param[in] fildes Descriptor for the file to be controlled.
333 @param[in] cmd Command to be acted upon.
334 @param[in,out] ... Optional additional parameters as required by cmd.
336 @return Upon successful completion, the value returned shall depend on
338 - F_DUPFD - A new file descriptor.
339 - F_GETFD - Value of flags defined in <fcntl.h>. The return value
340 shall not be negative.
341 - F_SETFD - Value other than -1.
342 - F_GETFL - Value of file status flags and access modes. The return
343 value is not negative.
344 - F_SETFL - Value other than -1.
345 - F_GETOWN - Value of the socket owner process or process group;
347 - F_SETOWN - Value other than -1.
348 Otherwise, -1 shall be returned and errno set to indicate the error.
352 fcntl (int fildes
, int cmd
, ...)
355 struct __filedes
*MyFd
;
359 //Print(L"%a( %d, %d, ...)\n", __func__, fildes, cmd);
362 if(ValidateFD( fildes
, VALID_OPEN
)) {
363 MyFd
= &gMD
->fdarray
[fildes
];
367 temp
= va_arg(p3
, int);
368 if(ValidateFD( temp
, VALID_DONT_CARE
)) {
369 temp
= FindFreeFD( temp
);
374 /* temp is now a valid fd reserved for further use
375 so copy fd into temp.
377 (void)memcpy(&gMD
->fdarray
[temp
], MyFd
, sizeof(struct __filedes
));
386 retval
= MyFd
->Oflags
; // Get original value
387 temp
= va_arg(p3
, int);
388 temp
&= O_SETMASK
; // Only certain bits can be set
389 temp
|= retval
& O_SETMASK
;
390 MyFd
->Oflags
= temp
; // Set new value
394 retval
= MyFd
->f_iflags
;
397 // retval = MyFd->SocProc;
398 // MyFd->SocProc = va_arg(p3, int);
401 retval
= MyFd
->f_iflags
;
404 retval
= MyFd
->Oflags
;
407 // retval = MyFd->SocProc;
422 /** The dup() function provides an alternative interface to the
423 service provided by fcntl() using the F_DUPFD command. The call:
425 shall be equivalent to:
426 - fid = fcntl(fildes, F_DUPFD, 0);
428 @param[in] fildes Descriptor for the file to be examined.
430 @return Upon successful completion a non-negative integer, namely the
431 file descriptor, shall be returned; otherwise, -1 shall be
432 returned and errno set to indicate the error.
437 return fcntl(fildes
, F_DUPFD
, 0);
440 /** Make fildes2 refer to a duplicate of fildes.
442 The dup2() function provides an alternative interface to the
443 service provided by fcntl() using the F_DUPFD command. The call:
444 - fid = dup2(fildes, fildes2);
445 shall be equivalent to:
447 - fid = fcntl(fildes, F_DUPFD, fildes2);
448 except for the following:
449 - If fildes2 is less than 0 or greater than or equal to {OPEN_MAX},
450 dup2() shall return -1 with errno set to [EBADF].
451 - If fildes is a valid file descriptor and is equal to fildes2, dup2()
452 shall return fildes2 without closing it.
453 - If fildes is not a valid file descriptor, dup2() shall return -1 and
454 shall not close fildes2.
455 - The value returned shall be equal to the value of fildes2 upon
456 successful completion, or -1 upon failure.
458 @param[in] fildes File Descriptor to be duplicated.
459 @param[in] fildes2 File Descriptor to be made a duplicate of fildes.
461 @return Upon successful completion a non-negative integer, namely
462 fildes2, shall be returned; otherwise, -1 shall be
463 returned and errno set to EBADF indicate the error.
466 dup2 (int fildes
, int fildes2
)
470 if(ValidateFD( fildes
, VALID_OPEN
)) {
472 if( fildes
!= fildes2
) {
473 if(ValidateFD( fildes2
, VALID_DONT_CARE
)) {
474 gMD
->fdarray
[fildes2
].f_iflags
= FIF_LARVAL
; // Mark the file closed, but reserved
475 (void)memcpy(&gMD
->fdarray
[fildes2
], // Duplicate fildes into fildes2
476 &gMD
->fdarray
[fildes
], sizeof(struct __filedes
));
477 gMD
->fdarray
[fildes2
].MyFD
= (UINT16
)fildes2
;
491 /** Reposition a file's read/write offset.
493 The lseek() function repositions the offset of the file descriptor fildes
494 to the argument offset according to the directive how. The argument
495 fildes must be an open file descriptor. lseek() repositions the file
496 pointer fildes as follows:
498 - If how is SEEK_SET, the offset is set to offset bytes.
500 - If how is SEEK_CUR, the offset is set to its current location
503 - If how is SEEK_END, the offset is set to the size of the file
506 The lseek() function allows the file offset to be set beyond the end of
507 the existing end-of-file of the file. If data is later written at this
508 point, subsequent reads of the data in the gap return bytes of zeros
509 (until data is actually written into the gap).
511 Some devices are incapable of seeking. The value of the pointer associ-
512 ated with such a device is undefined.
514 @param[in] fd Descriptor for the File to be affected.
515 @param[in] offset Value to adjust the file position by.
516 @param[in] how How the file position is to be adjusted.
518 @return Upon successful completion, lseek() returns the resulting offset
519 location as measured in bytes from the beginning of the file.
520 Otherwise, a value of -1 is returned and errno is set to
524 lseek (int fd
, __off_t offset
, int how
)
527 // RETURN_STATUS Status = RETURN_SUCCESS;
528 struct __filedes
*filp
;
530 EFIerrno
= RETURN_SUCCESS
; // In case of error without an EFI call
532 if( how
== SEEK_SET
|| how
== SEEK_CUR
|| how
== SEEK_END
) {
533 if(ValidateFD( fd
, VALID_OPEN
)) {
534 filp
= &gMD
->fdarray
[fd
];
535 // Both of our parameters have been verified as valid
536 CurPos
= filp
->f_ops
->fo_lseek( filp
, offset
, how
);
538 filp
->f_offset
= CurPos
;
542 errno
= EBADF
; // Bad File Descriptor
546 errno
= EINVAL
; // Invalid how argument
551 /** The directory path is created with the access permissions specified by
554 The directory is closed after it is created.
556 @param[in] path The path to a directory to create.
557 @param[in] perms Permissions as defined in <sys/stat.h>
559 @retval 0 The directory was created successfully.
560 @retval -1 An error occurred and error codes are stored in errno and EFIerrno.
563 mkdir (const char *path
, __mode_t perms
)
568 RETURN_STATUS Status
;
572 Status
= ParsePath(path
, &NewPath
, &Node
, &Instance
, NULL
);
573 if(Status
== RETURN_SUCCESS
) {
574 GenI
= Node
->InstanceList
;
580 //GenI += (Instance * Node->InstanceSize);
581 retval
= ((GenericInstance
*)GenI
)->Abstraction
.fo_mkdir( path
, perms
);
592 The open() function establishes the connection between a file and a file
593 descriptor. It creates an open file description that refers to a file
594 and a file descriptor that refers to that open file description. The file
595 descriptor is used by other I/O functions to refer to that file.
597 The open() function returns a file descriptor for the named file that is
598 the lowest file descriptor not currently open for that process. The open
599 file description is new, and therefore the file descriptor shall not
600 share it with any other process in the system.
602 The file offset used to mark the current position within the file is set
603 to the beginning of the file.
605 The EFI ShellOpenFileByName() function is used to perform the low-level
606 file open operation. The primary task of open() is to translate from the
607 flags used in the <stdio.h> environment to those used by the EFI function.
609 The file status flags and file access modes of the open file description
610 are set according to the value of oflags.
612 Values for oflags are constructed by a bitwise-inclusive OR of flags from
613 the following list, defined in <fcntl.h>. Applications shall specify
614 exactly one of { O_RDONLY, O_RDWR, O_WRONLY } in the value of oflags.
615 Any combination of { O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL } may
616 also be specified in oflags.
618 The only valid flag combinations for ShellOpenFileByName() are:
623 Values for mode specify the access permissions for newly created files.
624 The mode value is saved in the FD to indicate permissions for further operations.
626 O_RDONLY -- flags = EFI_FILE_MODE_READ -- this is always done
627 O_WRONLY -- flags |= EFI_FILE_MODE_WRITE
628 O_RDWR -- flags |= EFI_FILE_MODE_WRITE -- READ is already set
630 O_NONBLOCK -- ignored
631 O_APPEND -- Seek to EOF before every write
632 O_CREAT -- flags |= EFI_FILE_MODE_CREATE
633 O_TRUNC -- delete first then create new
634 O_EXCL -- if O_CREAT is also set, open will fail if the file already exists.
636 @param[in] Path The path argument points to a pathname naming the
638 @param[in] oflags File status flags and file access modes of the
639 open file description.
640 @param[in] mode File access permission bits as defined in
641 <sys/stat.h>. Only used if a file is created
642 as a result of the open.
644 @return Upon successful completion, open() opens the file and returns
645 a non-negative integer representing the lowest numbered
646 unused file descriptor. Otherwise, open returns -1 and sets
647 errno to indicate the error. If a negative value is
648 returned, no files are created or modified.
649 - EMFILE - No file descriptors available -- Max number already open.
650 - EINVAL - Bad value specified for oflags or mode.
651 - ENOMEM - Failure allocating memory for internal buffers.
652 - EEXIST - File exists and open attempted with (O_EXCL | O_CREAT) set.
653 - EIO - UEFI failure. Check value in EFIerrno.
665 struct __filedes
*filp
;
666 struct termios
*Termio
;
668 RETURN_STATUS Status
;
673 Status
= ParsePath(path
, &NewPath
, &Node
, &Instance
, &MPath
);
674 if(Status
== RETURN_SUCCESS
) {
675 if ((Node
== NULL
) ||
676 (Node
->InstanceList
== NULL
))
681 // Could add a test to see if the file name begins with a period.
682 // If it does, then add the HIDDEN flag to Attributes.
684 // Get an available fd
685 fd
= FindFreeFD( VALID_CLOSED
);
688 // All available FDs are in use
692 filp
= &gMD
->fdarray
[fd
];
693 // Save the flags and mode in the File Descriptor
694 filp
->Oflags
= oflags
;
697 doresult
= Node
->OpenFunc(Node
, filp
, Instance
, NewPath
, MPath
);
699 filp
->f_iflags
= 0; // Release this FD
700 fd
= -1; // Indicate an error
703 // Build our final f_iflags value
704 OpenMode
= ( mode
& S_ACC_READ
) ? S_ACC_READ
: 0;
705 OpenMode
|= ( mode
& S_ACC_WRITE
) ? S_ACC_WRITE
: 0;
707 filp
->f_iflags
|= OpenMode
;
709 if((oflags
& O_TTY_INIT
) && (filp
->f_iflags
& _S_ITTY
) && (filp
->devdata
!= NULL
)) {
710 // Initialize the device's termios flags to a "sane" value
711 Termio
= &((cIIO
*)filp
->devdata
)->Termio
;
712 Termio
->c_iflag
= ICRNL
| IGNSPEC
;
713 Termio
->c_oflag
= OPOST
| ONLCR
| OXTABS
| ONOEOT
| ONOCR
| ONLRET
| OCTRL
;
714 Termio
->c_lflag
= ECHO
| ECHOE
| ECHONL
| ICANON
;
715 Termio
->c_cc
[VERASE
] = 0x08; // ^H Backspace
716 Termio
->c_cc
[VKILL
] = 0x15; // ^U
717 Termio
->c_cc
[VINTR
] = 0x03; // ^C Interrupt character
720 FILE_SET_MATURE(filp
);
726 free(MPath
); // We don't need this any more.
728 // return the fd of our now open file
734 Poll a list of file descriptors.
736 The ::poll routine waits for up to timeout milliseconds for an event
737 to occur on one or more of the file descriptors listed. The event
738 types of interested are specified for each file descriptor in the events
739 field. The actual event detected is returned in the revents field of
741 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">POSIX</a>
742 documentation is available online.
744 @param[in] pfd Address of an array of pollfd structures.
746 @param[in] nfds Number of elements in the array of pollfd structures.
748 @param[in] timeout Length of time in milliseconds to wait for the event
750 @return The number of file descriptors with detected events. Zero
751 indicates that the call timed out and -1 indicates an error.
761 struct __filedes
* pDescriptor
;
762 struct pollfd
* pEnd
;
763 struct pollfd
* pPollFD
;
770 // Create the timer for the timeout
773 Status
= EFI_SUCCESS
;
774 if ( INFTIM
!= timeout
) {
775 Status
= gBS
->CreateEvent ( EVT_TIMER
,
780 if ( !EFI_ERROR ( Status
)) {
782 // Start the timeout timer
784 TimerTicks
= timeout
;
785 TimerTicks
*= 1000 * 10;
786 Status
= gBS
->SetTimer ( Timer
,
795 if ( !EFI_ERROR ( Status
)) {
797 // Poll until an event is detected or the timer fires
803 // Poll the list of file descriptors
806 pEnd
= &pPollFD
[ nfds
];
807 while ( pEnd
> pPollFD
) {
809 // Validate the file descriptor
811 if ( !ValidateFD ( pPollFD
->fd
, VALID_OPEN
)) {
817 // Poll the device or file
819 pDescriptor
= &gMD
->fdarray
[ pPollFD
->fd
];
820 pPollFD
->revents
= pDescriptor
->f_ops
->fo_poll ( pDescriptor
,
824 // Determine if this file descriptor detected an event
826 if ( 0 != pPollFD
->revents
) {
828 // Select this descriptor
834 // Set the next file descriptor
842 if ( NULL
!= Timer
) {
843 Status
= gBS
->CheckEvent ( Timer
);
844 if ( EFI_SUCCESS
== Status
) {
850 else if ( EFI_NOT_READY
== Status
) {
851 Status
= EFI_SUCCESS
;
854 } while (( 0 == SelectedFDs
)
855 && ( EFI_SUCCESS
== Status
));
860 if ( NULL
!= Timer
) {
861 gBS
->SetTimer ( Timer
,
874 if ( NULL
!= Timer
) {
875 gBS
->CloseEvent ( Timer
);
879 // Return the number of selected file system descriptors
885 /** The rename() function changes the name of a file.
886 The From argument points to the pathname of the file to be renamed. The To
887 argument points to the new pathname of the file.
889 If the From argument points to the pathname of a file that is not a
890 directory, the To argument shall not point to the pathname of a
891 directory. If the file named by the To argument exists, it shall be
892 removed and From renamed to To. Write access permission is required for
893 both the directory containing old and the directory containing To.
895 If the From argument points to the pathname of a directory, the To
896 argument shall not point to the pathname of a file that is not a
897 directory. If the directory named by the To argument exists, it shall be
898 removed and From renamed to To.
900 The To pathname shall not contain a path prefix that names From. Write
901 access permission is required for the directory containing From and the
902 directory containing To. If the From argument points to the pathname of a
903 directory, write access permission may be required for the directory named
904 by From, and, if it exists, the directory named by To.
906 If the rename() function fails for any reason other than [EIO], any file
907 named by To shall be unaffected.
909 @param[in] From Path to the file to be renamed.
910 @param[in] To The new name of From.
912 @retval 0 Successful completion.
913 @retval -1 An error has occured and errno has been set to further specify the error.
914 Neither the file named by From nor the file named by To are
916 - ENXIO: Path specified is not supported by any loaded driver.
917 - ENOMEM: Insufficient memory to calloc a MapName buffer.
918 - EINVAL: The path parameter is not valid.
927 DeviceNode
*FromNode
;
930 RETURN_STATUS Status
;
933 Status
= ParsePath(From
, &FromPath
, &FromNode
, &Instance
, NULL
);
934 if(Status
== RETURN_SUCCESS
) {
935 GenI
= FromNode
->InstanceList
;
941 //GenI += (Instance * FromNode->InstanceSize);
942 retval
= ((GenericInstance
*)GenI
)->Abstraction
.fo_rename( From
, To
);
949 /** Delete a specified directory.
951 @param[in] path Path to the directory to delete.
953 @retval -1 The directory couldn't be opened (doesn't exist).
954 @retval -1 The directory wasn't empty or an IO error occured.
961 struct __filedes
*filp
;
965 fd
= open(path
, O_RDWR
, 0);
967 filp
= &gMD
->fdarray
[fd
];
969 retval
= filp
->f_ops
->fo_rmdir(filp
);
970 filp
->f_iflags
= 0; // Close this FD
971 filp
->RefCount
= 0; // No one using this FD
976 /** The fstat() function obtains information about an open file associated
977 with the file descriptor fd, and writes it to the area pointed to
980 The statbuf argument is a pointer to a stat structure, as defined
981 in <sys/stat.h>, into which information is placed concerning the file.
983 The structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atime,
984 st_ctime, and st_mtime shall have meaningful values. The value of the
985 member st_nlink shall be set to the number of links to the file.
987 The fstat() function shall update any time-related fields before writing
988 into the stat structure.
990 The fstat() function is implemented using the ShellGetFileInfo()
993 The stat structure members which don't have direct analogs to EFI file
994 information are filled in as follows:
995 - st_mode Populated with information from fd
996 - st_ino Set to zero. (inode)
997 - st_dev Set to zero.
998 - st_uid Set to zero.
999 - st_gid Set to zero.
1000 - st_nlink Set to one.
1002 @param[in] fd File descriptor as returned from open().
1003 @param[out] statbuf Buffer in which the file status is put.
1005 @retval 0 Successful Completion.
1006 @retval -1 An error has occurred and errno has been set to
1010 fstat (int fd
, struct stat
*statbuf
)
1013 struct __filedes
*filp
;
1015 if(ValidateFD( fd
, VALID_OPEN
)) {
1016 filp
= &gMD
->fdarray
[fd
];
1017 retval
= filp
->f_ops
->fo_stat(filp
, statbuf
, NULL
);
1025 /** Obtains information about the file pointed to by path.
1027 Opens the file pointed to by path, calls _EFI_FileInfo with the file's handle,
1028 then closes the file.
1030 @param[in] path Path to the file to obtain information about.
1031 @param[out] statbuf Buffer in which the file status is put.
1033 @retval 0 Successful Completion.
1034 @retval -1 An error has occurred and errno has been set to
1038 stat (const char *path
, struct stat
*statbuf
)
1042 struct __filedes
*filp
;
1044 fd
= open(path
, O_RDONLY
, 0);
1046 filp
= &gMD
->fdarray
[fd
];
1047 retval
= filp
->f_ops
->fo_stat( filp
, statbuf
, NULL
);
1053 /** Same as stat since EFI doesn't have symbolic links.
1055 @param[in] path Path to the file to obtain information about.
1056 @param[out] statbuf Buffer in which the file status is put.
1058 @retval 0 Successful Completion.
1059 @retval -1 An error has occurred and errno has been set to
1063 lstat (const char *path
, struct stat
*statbuf
)
1065 return stat(path
, statbuf
);
1068 /** Control a device.
1070 @param[in] fd Descriptor for the file to be acted upon.
1071 @param[in] request Specifies the operation to perform.
1072 @param[in,out] ... Zero or more parameters as required for request.
1074 @retval >=0 The operation completed successfully.
1075 @retval -1 An error occured. More information is in errno.
1080 unsigned long request
,
1085 struct __filedes
*filp
;
1088 va_start(argp
, request
);
1090 if(ValidateFD( fd
, VALID_OPEN
)) {
1091 filp
= &gMD
->fdarray
[fd
];
1093 if(request
== FIODLEX
) {
1094 /* set Delete-on-Close */
1095 filp
->f_iflags
|= FIF_DELCLOSE
;
1098 else if(request
== FIONDLEX
) {
1099 /* clear Delete-on-Close */
1100 filp
->f_iflags
&= ~FIF_DELCLOSE
;
1104 /* All other requests. */
1105 retval
= filp
->f_ops
->fo_ioctl(filp
, request
, argp
);
1116 /** Read from a file.
1118 The read() function shall attempt to read nbyte bytes from the file
1119 associated with the open file descriptor, fildes, into the buffer pointed
1122 Before any action described below is taken, and if nbyte is zero, the
1123 read() function may detect and return errors as described below. In the
1124 absence of errors, or if error detection is not performed, the read()
1125 function shall return zero and have no other results.
1127 On files that support seeking (for example, a regular file), the read()
1128 shall start at a position in the file given by the file offset associated
1129 with fildes. The file offset shall be incremented by the number of bytes
1132 Files that do not support seeking - for example, terminals - always read
1133 from the current position. The value of a file offset associated with
1134 such a file is undefined.
1136 No data transfer shall occur past the current end-of-file. If the
1137 starting position is at or after the end-of-file, 0 shall be returned.
1139 The read() function reads data previously written to a file. If any
1140 portion of a regular file prior to the end-of-file has not been written,
1141 read() shall return bytes with value 0. For example, lseek() allows the
1142 file offset to be set beyond the end of existing data in the file. If data
1143 is later written at this point, subsequent reads in the gap between the
1144 previous end of data and the newly written data shall return bytes with
1145 value 0 until data is written into the gap.
1147 Upon successful completion, where nbyte is greater than 0, read() shall
1148 mark for update the st_atime field of the file, and shall return the
1149 number of bytes read. This number shall never be greater than nbyte. The
1150 value returned may be less than nbyte if the number of bytes left in the
1151 file is less than nbyte, if the read() request was interrupted by a
1152 signal, or if the file is a pipe or FIFO or special file and has fewer
1153 than nbyte bytes immediately available for reading. For example, a read()
1154 from a file associated with a terminal may return one typed line of data.
1156 If fildes does not refer to a directory, the function reads the requested
1157 number of bytes from the file at the file's current position and returns
1158 them in buf. If the read goes beyond the end of the file, the read
1159 length is truncated to the end of the file. The file's current position is
1160 increased by the number of bytes returned.
1162 If fildes refers to a directory, the function reads the directory entry at
1163 the file's current position and returns the entry in buf. If buf
1164 is not large enough to hold the current directory entry, then
1165 errno is set to EBUFSIZE, EFIerrno is set to EFI_BUFFER_TOO_SMALL, and the
1166 current file position is not updated. The size of the buffer needed to read
1167 the entry will be returned as a negative number. On success, the current
1168 position is updated to the next directory entry. If there are no more
1169 directory entries, the read returns a zero-length buffer.
1170 EFI_FILE_INFO is the structure returned as the directory entry.
1172 @param[in] fildes Descriptor of the file to be read.
1173 @param[out] buf Pointer to location in which to store the read data.
1174 @param[in] nbyte Maximum number of bytes to be read.
1176 @return Upon successful completion, read() returns a non-negative integer
1177 indicating the number of bytes actually read. Otherwise, the
1178 functions return a negative value and sets errno to indicate the
1179 error. If errno is EBUFSIZE, the absolute value of the
1180 return value indicates the size of the buffer needed to read
1181 the directory entry.
1184 read (int fildes
, void *buf
, size_t nbyte
)
1186 struct __filedes
*filp
;
1190 BufSize
= (ssize_t
)nbyte
;
1192 if(ValidateFD( fildes
, VALID_OPEN
)) {
1193 filp
= &gMD
->fdarray
[fildes
];
1195 IIO
= filp
->devdata
;
1196 if(isatty(fildes
) && (IIO
!= NULL
)) {
1197 BufSize
= IIO
->Read(filp
, nbyte
, buf
);
1200 BufSize
= filp
->f_ops
->fo_read(filp
, &filp
->f_offset
, nbyte
, buf
);
1211 /** Write data to a file.
1213 This function writes the specified number of bytes to the file at the current
1214 file position. The current file position is advanced the actual number of bytes
1215 written. Partial writes only occur when there has been a data error during
1216 the write attempt (such as "volume space full"). The file is automatically
1217 grown to hold the data if required.
1219 Direct writes to opened directories are not supported.
1221 If fildes refers to a terminal device, isatty() returns TRUE, a partial write
1222 will occur if a NULL or EOF character is encountered before n characters have
1223 been written. Characters inserted due to line-end translations or TAB
1224 expansion will not be counted. Unconvertable characters are translated into
1225 the UEFI character BLOCKELEMENT_LIGHT_SHADE.
1227 Since the UEFI console device works on wide characters, the buffer is assumed
1228 to contain a byte-oriented multi-byte character stream which is then
1229 translated to wide characters using the mbtowc() functions. The resulting
1230 wide character stream is what is actually sent to the UEFI console.
1232 Although both text and binary wide-oriented streams are conceptually
1233 sequences of wide characters, the external file associated with a
1234 wide-oriented stream is a sequence of multibyte characters,
1235 generalized as follows:
1236 - Multibyte encodings within files may contain embedded null bytes
1237 (unlike multibyte encodings valid for use internal to the program).
1238 - A file need not begin nor end in the initial shift state.
1240 @param[in] fd Descriptor of file to be written to.
1241 @param[in] buf Pointer to data to write to the file.
1242 @param[in] nbyte Number of bytes to be written to the file.
1244 @retval >=0 Number of bytes actually written to the file.
1245 @retval <0 An error occurred. More data is provided by errno.
1248 write (int fd
, const void *buf
, size_t nbyte
)
1250 struct __filedes
*filp
;
1254 BufSize
= (ssize_t
)nbyte
;
1256 if(ValidateFD( fd
, VALID_OPEN
)) {
1257 filp
= &gMD
->fdarray
[fd
];
1258 if ((filp
->Oflags
& O_ACCMODE
) != 0) {
1259 // File is open for writing
1260 IIO
= filp
->devdata
;
1261 if(isatty(fd
) && (IIO
!= NULL
)) {
1262 // Output to an Interactive I/O device
1263 // (Terminal device or the slave side of a pseudo-tty)
1264 BufSize
= IIO
->Write(filp
, buf
, nbyte
);
1267 // Output to a regular file, socket, pipe, etc.
1268 BufSize
= filp
->f_ops
->fo_write(filp
, &filp
->f_offset
, nbyte
, buf
);
1272 // File is NOT open for writing
1278 // fd is not for a valid open file
1285 /** Gets the current working directory.
1287 The getcwd() function shall place an absolute pathname of the current
1288 working directory in the array pointed to by buf, and return buf.The
1289 size argument is the size in bytes of the character array pointed to
1290 by the buf argument.
1292 @param[in,out] buf The buffer to fill.
1293 @param[in] size The number of bytes in buffer.
1295 @retval NULL The function failed. The value in errno provides
1296 further information about the cause of the failure.
1297 Values for errno are:
1298 - EINVAL: buf is NULL or size is zero.
1299 - ENOENT: directory does not exist.
1300 - ERANGE: buf size is too small to hold CWD
1302 @retval buf The function completed successfully.
1305 *getcwd (char *buf
, size_t size
)
1309 if (size
== 0 || buf
== NULL
) {
1314 Cwd
= ShellGetCurrentDir(NULL
);
1319 if (size
< ((StrLen (Cwd
) + 1) * sizeof (CHAR8
))) {
1323 return (UnicodeStrToAsciiStr(Cwd
, buf
));
1326 /** Change the current working directory.
1328 The chdir() function shall cause the directory named by the pathname
1329 pointed to by the path argument to become the current working directory;
1330 that is, the starting point for path searches for pathnames not beginning
1333 @param[in] path The new path to set.
1335 @retval 0 Operation completed successfully.
1336 @retval -1 Function failed. The value in errno provides more
1337 information on the cause of failure:
1338 - EPERM: Operation not supported with this Shell version.
1339 - ENOMEM: Unable to allocate memory.
1340 - ENOENT: Target directory does not exist.
1342 @todo Add non-NEW-shell CWD changing.
1345 chdir (const char *path
)
1349 CHAR16
*UnicodePath
;
1351 /* Old Shell does not support Set Current Dir. */
1352 if(gEfiShellProtocol
!= NULL
) {
1353 Cwd
= ShellGetCurrentDir(NULL
);
1355 /* We have shell support */
1356 UnicodePath
= AllocatePool(((AsciiStrLen (path
) + 1) * sizeof (CHAR16
)));
1357 if (UnicodePath
== NULL
) {
1361 AsciiStrToUnicodeStr(path
, UnicodePath
);
1362 Status
= gEfiShellProtocol
->SetCurDir(NULL
, UnicodePath
);
1363 FreePool(UnicodePath
);
1364 if (EFI_ERROR(Status
)) {
1372 /* Add here for non-shell */
1377 /** Get the foreground process group ID associated with a terminal.
1379 Just returns the Image Handle for the requestor since UEFI does not have
1380 a concept of processes or groups.
1382 @param[in] x Ignored.
1384 @return Returns the Image Handle of the application or driver which
1385 called this function.
1387 pid_t
tcgetpgrp (int x
)
1389 return ((pid_t
)(UINTN
)(gImageHandle
));
1392 /** Get the process group ID of the calling process.
1394 Just returns the Image Handle for the requestor since UEFI does not have
1395 a concept of processes or groups.
1397 @return Returns the Image Handle of the application or driver which
1398 called this function.
1402 return ((pid_t
)(UINTN
)(gImageHandle
));
1405 /* Internal worker function for utimes.
1406 This works around an error produced by GCC when the va_* macros
1407 are used within a function with a fixed number of arguments.
1417 struct __filedes
*filp
;
1423 fd
= open(path
, O_RDWR
, 0);
1425 filp
= &gMD
->fdarray
[fd
];
1426 retval
= filp
->f_ops
->fo_ioctl( filp
, FIOSETIME
, ap
);
1433 /** Set file access and modification times.
1435 @param[in] path Path to the file to be modified.
1436 @param[in] times Pointer to an array of two timeval structures
1438 @retval 0 File times successfully set.
1439 @retval -1 An error occured. Error type in errno.
1444 const struct timeval
*times
1447 return va_Utimes(path
, times
);