+++ /dev/null
-/** @file\r
- Abstract device driver for the UEFI Shell-hosted environment.\r
-\r
- In a Shell-hosted environment, this is the driver that is called\r
- when no other driver matches.\r
-\r
- Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials are licensed and made available under\r
- the terms and conditions of the BSD License that accompanies this distribution.\r
- The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-#include <Uefi.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/ShellLib.h>\r
-\r
-#include <LibConfig.h>\r
-\r
-#include <errno.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <stdarg.h>\r
-#include <wctype.h>\r
-#include <wchar.h>\r
-#include <sys/fcntl.h>\r
-#include <sys/filio.h>\r
-#include <sys/syslimits.h>\r
-#include <unistd.h>\r
-#include <kfile.h>\r
-#include <Device/Device.h>\r
-#include <MainData.h>\r
-#include <Efi/SysEfi.h>\r
-\r
-/** EFI Shell specific operations for close().\r
-\r
- @param[in] Fp Pointer to a file descriptor structure.\r
-\r
- @retval 0 Successful completion.\r
- @retval -1 Operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-int\r
-EFIAPI\r
-da_ShellClose(\r
- IN struct __filedes *Fp\r
-)\r
-{\r
- EFIerrno = ShellCloseFile( (SHELL_FILE_HANDLE *)&Fp->devdata);\r
- if(RETURN_ERROR(EFIerrno)) {\r
- return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-/** EFI Shell specific operations for deleting a file or directory.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
-\r
- @retval 0 Successful completion.\r
- @retval -1 Operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-int\r
-EFIAPI\r
-da_ShellDelete(\r
- struct __filedes *filp\r
- )\r
-{\r
- RETURN_STATUS Status;\r
-\r
- Status = ShellDeleteFile( (SHELL_FILE_HANDLE *)&filp->devdata);\r
- if(Status != RETURN_SUCCESS) {\r
- errno = EFI2errno(Status);\r
- EFIerrno = Status;\r
- return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-/** EFI Shell specific operations for setting the position within a file.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
- @param[in] offset Relative position to move to.\r
- @param[in] whence Specifies the location offset is relative to: Beginning, Current, End.\r
-\r
- @return Returns the new file position or EOF if the seek failed.\r
-**/\r
-static\r
-off_t\r
-EFIAPI\r
-da_ShellSeek(\r
- struct __filedes *filp,\r
- off_t offset,\r
- int whence\r
-)\r
-{\r
- __off_t CurPos = -1;\r
- RETURN_STATUS Status = RETURN_SUCCESS;\r
- SHELL_FILE_HANDLE FileHandle;\r
-\r
- FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
-\r
- if(whence != SEEK_SET) {\r
- // We are doing a relative seek\r
- if(whence == SEEK_END) {\r
- // seeking relative to EOF, so position there first.\r
- Status = ShellSetFilePosition( FileHandle, 0xFFFFFFFFFFFFFFFFULL);\r
- }\r
- if(Status == RETURN_SUCCESS) {\r
- // Now, determine our current position.\r
- Status = ShellGetFilePosition( FileHandle, (UINT64 *)&CurPos);\r
- }\r
- }\r
- else {\r
- CurPos = 0; // offset is an absolute position for SEEK_SET\r
- if(offset < 0) {\r
- Status = RETURN_INVALID_PARAMETER;\r
- }\r
- }\r
- if(Status == RETURN_SUCCESS) {\r
- /* CurPos now indicates the point we are seeking from, so seek... */\r
- Status = ShellSetFilePosition( FileHandle, (UINT64)(CurPos + offset));\r
- if(Status == RETURN_SUCCESS) {\r
- // Now, determine our final position.\r
- Status = ShellGetFilePosition( FileHandle, (UINT64 *)&CurPos);\r
- }\r
- }\r
- if(Status != RETURN_SUCCESS) {\r
- if(Status == EFI_UNSUPPORTED) {\r
- errno = EISDIR;\r
- }\r
- else {\r
- errno = EFI2errno(Status);\r
- }\r
- EFIerrno = Status;\r
- CurPos = EOF;\r
- }\r
- return CurPos;\r
-}\r
-\r
-/** The directory path is created with the access permissions specified by\r
- perms.\r
-\r
- The directory is closed after it is created.\r
-\r
- @param[in] path The directory to be created.\r
- @param[in] perms Access permissions for the new directory.\r
-\r
- @retval 0 The directory was created successfully.\r
- @retval -1 An error occurred and an error code is stored in errno.\r
-**/\r
-static\r
-int\r
-EFIAPI\r
-da_ShellMkdir(\r
- const char *path,\r
- __mode_t perms\r
- )\r
-{\r
- UINT64 TempAttr;\r
- SHELL_FILE_HANDLE FileHandle;\r
- RETURN_STATUS Status;\r
- EFI_FILE_INFO *FileInfo;\r
- wchar_t *NewPath;\r
- int retval = -1;\r
-\r
- // Convert name from MBCS to WCS and change '/' to '\\'\r
- NewPath = NormalizePath( path);\r
-\r
- if(NewPath != NULL) {\r
- Status = ShellCreateDirectory( NewPath, &FileHandle);\r
- if(Status == RETURN_SUCCESS) {\r
- FileInfo = ShellGetFileInfo( FileHandle);\r
- Status = RETURN_ABORTED; // In case ShellGetFileInfo() failed\r
- if(FileInfo != NULL) {\r
- TempAttr = FileInfo->Attribute & (EFI_FILE_RESERVED | EFI_FILE_DIRECTORY);\r
- FileInfo->Attribute = TempAttr | Omode2EFI(perms);\r
- Status = ShellSetFileInfo( FileHandle, FileInfo);\r
- FreePool(FileInfo);\r
- if(Status == RETURN_SUCCESS) {\r
- (void)ShellCloseFile(&FileHandle);\r
- retval = 0;\r
- }\r
- }\r
- }\r
- errno = EFI2errno(Status);\r
- EFIerrno = Status;\r
- free(NewPath);\r
- }\r
- return retval;\r
-}\r
-\r
-/** EFI Shell specific operations for reading from a file.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
- @param[in] offset Offset into the file to begin reading at, or NULL.\r
- @param[in] BufferSize Number of bytes in Buffer. Max number of bytes to read.\r
- @param[in] Buffer Pointer to a buffer to receive the read data.\r
-\r
- @return Returns the number of bytes successfully read,\r
- or -1 if the operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-ssize_t\r
-EFIAPI\r
-da_ShellRead(\r
- IN OUT struct __filedes *filp,\r
- IN OUT off_t *offset,\r
- IN size_t BufferSize,\r
- OUT VOID *Buffer\r
-)\r
-{\r
- ssize_t BufSize;\r
- SHELL_FILE_HANDLE FileHandle;\r
- RETURN_STATUS Status;\r
-\r
- if(offset != NULL) {\r
- BufSize = (ssize_t)da_ShellSeek(filp, *offset, SEEK_SET);\r
- if(BufSize >= 0) {\r
- filp->f_offset = BufSize;\r
- }\r
- }\r
-\r
- BufSize = (ssize_t)BufferSize;\r
- FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
-\r
- Status = ShellReadFile( FileHandle, (UINTN *)&BufSize, Buffer);\r
- if(Status != RETURN_SUCCESS) {\r
- EFIerrno = Status;\r
- errno = EFI2errno(Status);\r
- if(Status == RETURN_BUFFER_TOO_SMALL) {\r
- BufSize = -BufSize;\r
- }\r
- else {\r
- BufSize = -1;\r
- }\r
- }\r
- else {\r
- filp->f_offset += BufSize; // Advance to where we want to read next.\r
- }\r
- return BufSize;\r
-}\r
-\r
-/** EFI Shell specific operations for writing to a file.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
- @param[in] offset Offset into the file to begin writing at, or NULL.\r
- @param[in] BufferSize Number of bytes in Buffer. Max number of bytes to write.\r
- @param[in] Buffer Pointer to a buffer containing the data to be written.\r
-\r
- @return Returns the number of bytes successfully written,\r
- or -1 if the operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-ssize_t\r
-EFIAPI\r
-da_ShellWrite(\r
- IN struct __filedes *filp,\r
- IN off_t *offset,\r
- IN size_t BufferSize,\r
- IN const void *Buffer\r
- )\r
-{\r
- ssize_t BufSize;\r
- SHELL_FILE_HANDLE FileHandle;\r
- RETURN_STATUS Status;\r
- off_t Position = 0;\r
- int How = SEEK_SET;\r
-\r
-\r
- if((offset != NULL) || (filp->Oflags & O_APPEND)) {\r
- if(filp->Oflags & O_APPEND) {\r
- Position = 0;\r
- How = SEEK_END;\r
- }\r
- else {\r
- Position = *offset;\r
- How = SEEK_SET;\r
- }\r
- BufSize = (ssize_t)da_ShellSeek(filp, Position, How);\r
- if(BufSize >= 0) {\r
- filp->f_offset = BufSize;\r
- }\r
- }\r
-\r
- BufSize = (ssize_t)BufferSize;\r
- FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
-\r
- Status = ShellWriteFile( FileHandle, (UINTN *)&BufSize, (void *)Buffer);\r
-\r
- if(Status != RETURN_SUCCESS) {\r
- EFIerrno = Status;\r
- errno = EFI2errno(Status);\r
- if(Status == EFI_UNSUPPORTED) {\r
- errno = EISDIR;\r
- }\r
- BufSize = -1;\r
- }\r
- else {\r
- filp->f_offset += BufSize; // Advance to where we want to write next.\r
- }\r
-\r
- return BufSize;\r
-}\r
-\r
-/** EFI Shell specific operations for getting information about an open file.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
- @param[out] statbuf Buffer in which to store the file status.\r
- @param[in] Something This parameter is not used by this device.\r
-\r
- @retval 0 Successful completion.\r
- @retval -1 Operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-int\r
-EFIAPI\r
-da_ShellStat(\r
- struct __filedes *filp,\r
- struct stat *statbuf,\r
- void *Something\r
- )\r
-{\r
- SHELL_FILE_HANDLE FileHandle;\r
- EFI_FILE_INFO *FileInfo = NULL;\r
- UINT64 Attributes;\r
- RETURN_STATUS Status;\r
- mode_t newmode;\r
-\r
- FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
-\r
- FileInfo = ShellGetFileInfo( FileHandle);\r
-\r
- if(FileInfo != NULL) {\r
- // Got the info, now populate statbuf with it\r
- statbuf->st_blksize = S_BLKSIZE;\r
- statbuf->st_size = FileInfo->FileSize;\r
- statbuf->st_physsize = FileInfo->PhysicalSize;\r
- statbuf->st_birthtime = Efi2Time( &FileInfo->CreateTime);\r
- statbuf->st_atime = Efi2Time( &FileInfo->LastAccessTime);\r
- statbuf->st_mtime = Efi2Time( &FileInfo->ModificationTime);\r
- Attributes = FileInfo->Attribute;\r
- newmode = (mode_t)(Attributes << S_EFISHIFT) | S_ACC_READ;\r
- if((Attributes & EFI_FILE_DIRECTORY) == 0) {\r
- newmode |= _S_IFREG;\r
- if((Attributes & EFI_FILE_READ_ONLY) == 0) {\r
- newmode |= S_ACC_WRITE;\r
- }\r
- }\r
- else {\r
- newmode |= _S_IFDIR;\r
- }\r
- statbuf->st_mode = newmode;\r
- Status = RETURN_SUCCESS;\r
- }\r
- else {\r
- Status = RETURN_DEVICE_ERROR;\r
- errno = EIO;\r
- }\r
- EFIerrno = Status;\r
-\r
- if(FileInfo != NULL) {\r
- FreePool(FileInfo); // Release the buffer allocated by the GetInfo function\r
- }\r
- return (Status == RETURN_SUCCESS)? 0 : -1;\r
-}\r
-\r
-/** EFI Shell specific operations for low-level control of a file or device.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
- @param[in] cmd The command this ioctl is to perform.\r
- @param[in,out] argp Zero or more arguments as needed by the command.\r
-\r
- @retval 0 Successful completion.\r
- @retval -1 Operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-int\r
-EFIAPI\r
-da_ShellIoctl(\r
- struct __filedes *filp,\r
- ULONGN cmd,\r
- va_list argp\r
- )\r
-{\r
- EFI_FILE_INFO *FileInfo = NULL;\r
- SHELL_FILE_HANDLE FileHandle;\r
- RETURN_STATUS Status = RETURN_SUCCESS;\r
- int retval = 0;\r
-\r
- FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
-\r
- FileInfo = ShellGetFileInfo( FileHandle);\r
-\r
- if(FileInfo != NULL) {\r
- if( cmd == (ULONGN)FIOSETIME) {\r
- struct timeval *TV;\r
- EFI_TIME *ET;\r
- int mod = 0;\r
-\r
- TV = va_arg(argp, struct timeval*);\r
- if(TV[0].tv_sec != 0) {\r
- ET = Time2Efi(TV[0].tv_sec);\r
- if(ET != NULL) {\r
- (void) memcpy(&FileInfo->LastAccessTime, ET, sizeof(EFI_TIME));\r
- FileInfo->LastAccessTime.Nanosecond = TV[0].tv_usec * 1000;\r
- free(ET);\r
- ++mod;\r
- }\r
- }\r
- if(TV[1].tv_sec != 0) {\r
- ET = Time2Efi(TV[1].tv_sec);\r
- if(ET != NULL) {\r
- (void) memcpy(&FileInfo->ModificationTime, ET, sizeof(EFI_TIME));\r
- FileInfo->ModificationTime.Nanosecond = TV[1].tv_usec * 1000;\r
- free(ET);\r
- ++mod;\r
- }\r
- }\r
- /* Set access and modification times */\r
- Status = ShellSetFileInfo(FileHandle, FileInfo);\r
- errno = EFI2errno(Status);\r
- }\r
- }\r
- else {\r
- Status = RETURN_DEVICE_ERROR;\r
- errno = EIO;\r
- }\r
- if(RETURN_ERROR(Status)) {\r
- retval = -1;\r
- }\r
- EFIerrno = Status;\r
-\r
- if(FileInfo != NULL) {\r
- FreePool(FileInfo); // Release the buffer allocated by the GetInfo function\r
- }\r
- return retval;\r
-}\r
-\r
-/** EFI Shell specific operations for opening a file or directory.\r
-\r
- @param[in] DevNode Pointer to a device descriptor\r
- @param[in] filp Pointer to a file descriptor structure.\r
- @param[in] DevInstance Not used by this device.\r
- @param[in] Path File-system path to the file or directory.\r
- @param[in] MPath Device or Map name on which Path resides.\r
-\r
- @return Returns a file descriptor for the newly opened file,\r
- or -1 if the Operation failed. Further information is specified by errno.\r
-**/\r
-int\r
-EFIAPI\r
-da_ShellOpen(\r
- DeviceNode *DevNode,\r
- struct __filedes *filp,\r
- int DevInstance, /* Not used by Shell */\r
- wchar_t *Path,\r
- wchar_t *MPath\r
- )\r
-{\r
- UINT64 OpenMode;\r
- UINT64 Attributes;\r
- SHELL_FILE_HANDLE FileHandle;\r
- GenericInstance *Gip;\r
- char *NPath;\r
- wchar_t *WPath;\r
- RETURN_STATUS Status;\r
- int oflags;\r
- int retval;\r
-\r
- EFIerrno = RETURN_SUCCESS;\r
-\r
- //Attributes = Omode2EFI(mode);\r
- Attributes = 0;\r
-\r
- // Convert oflags to Attributes\r
- oflags = filp->Oflags;\r
- OpenMode = Oflags2EFI(oflags);\r
- if(OpenMode == 0) {\r
- errno = EINVAL;\r
- return -1;\r
- }\r
-\r
- /* Re-create the full mapped path for the shell. */\r
- if(MPath != NULL) {\r
- WPath = AllocateZeroPool(PATH_MAX * sizeof(wchar_t) + 1);\r
- if(WPath == NULL) {\r
- errno = ENOMEM;\r
- EFIerrno = RETURN_OUT_OF_RESOURCES;\r
- return -1;\r
- }\r
- wcsncpy(WPath, MPath, NAME_MAX); /* Get the Map Name */\r
- wcsncat(WPath, Path, (PATH_MAX - NAME_MAX)); /* Append the path */\r
- }\r
- else {\r
- WPath = Path;\r
- }\r
-\r
- retval = -1; /* Initially assume failure. */\r
-\r
- /* Do we care if the file already exists?\r
- If O_TRUNC, then delete the file. It will be created anew subsequently.\r
- If O_EXCL, then error if the file exists and O_CREAT is set.\r
-\r
- !!!!!!!!! Change this to use ShellSetFileInfo() to actually truncate the file\r
- !!!!!!!!! instead of deleting and re-creating it.\r
- */\r
- do { /* Do fake exception handling */\r
- if((oflags & O_TRUNC) || ((oflags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {\r
- Status = ShellIsFile( WPath );\r
- if(Status == RETURN_SUCCESS) {\r
- // The file exists\r
- if(oflags & O_TRUNC) {\r
- NPath = AllocateZeroPool(PATH_MAX);\r
- if(NPath == NULL) {\r
- errno = ENOMEM;\r
- EFIerrno = RETURN_OUT_OF_RESOURCES;\r
- break;\r
- }\r
- wcstombs(NPath, WPath, PATH_MAX);\r
- // We do a truncate by deleting the existing file and creating a new one.\r
- if(unlink(NPath) != 0) {\r
- filp->f_iflags = 0; // Release our reservation on this FD\r
- FreePool(NPath);\r
- break;\r
- }\r
- FreePool(NPath);\r
- }\r
- else if((oflags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT)) {\r
- errno = EEXIST;\r
- EFIerrno = RETURN_ACCESS_DENIED;\r
- filp->f_iflags = 0; // Release our reservation on this FD\r
- break;\r
- }\r
- }\r
- }\r
-\r
- // Call the EFI Shell's Open function\r
- Status = ShellOpenFileByName( WPath, &FileHandle, OpenMode, Attributes);\r
- if(RETURN_ERROR(Status)) {\r
- filp->f_iflags = 0; // Release our reservation on this FD\r
- // Set errno based upon Status\r
- errno = EFI2errno(Status);\r
- EFIerrno = Status;\r
- break;\r
- }\r
- retval = 0;\r
- // Successfully got a regular File\r
- filp->f_iflags |= S_IFREG;\r
-\r
- // Update the info in the fd\r
- filp->devdata = (void *)FileHandle;\r
-\r
- Gip = (GenericInstance *)DevNode->InstanceList;\r
- filp->f_offset = 0;\r
- filp->f_ops = &Gip->Abstraction;\r
- // filp->devdata = FileHandle;\r
- } while(FALSE);\r
-\r
- /* If we get this far, WPath is not NULL.\r
- If MPath is not NULL, then WPath was allocated so we need to free it.\r
- */\r
- if(MPath != NULL) {\r
- FreePool(WPath);\r
- }\r
- return retval;\r
-}\r
-\r
-#include <sys/poll.h>\r
-/** Returns a bit mask describing which operations could be completed immediately.\r
-\r
- For now, assume the file system, via the shell, is always ready.\r
-\r
- (POLLIN | POLLRDNORM) The file system is ready to be read.\r
- (POLLOUT) The file system is ready for output.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
- @param[in] events Bit mask describing which operations to check.\r
-\r
- @return The returned value is a bit mask describing which operations\r
- could be completed immediately, without blocking.\r
-**/\r
-static\r
-short\r
-EFIAPI\r
-da_ShellPoll(\r
- struct __filedes *filp,\r
- short events\r
- )\r
-{\r
- UINT32 RdyMask;\r
- short retval = 0;\r
-\r
- RdyMask = (UINT32)filp->Oflags;\r
-\r
- switch(RdyMask & O_ACCMODE) {\r
- case O_RDONLY:\r
- retval = (POLLIN | POLLRDNORM);\r
- break;\r
-\r
- case O_WRONLY:\r
- retval = POLLOUT;\r
- break;\r
-\r
- case O_RDWR:\r
- retval = (POLLIN | POLLRDNORM | POLLOUT);\r
- break;\r
-\r
- default:\r
- retval = POLLERR;\r
- break;\r
- }\r
- return (retval & (events | POLL_RETONLY));\r
-}\r
-\r
-/** EFI Shell specific operations for renaming a file.\r
-\r
- @param[in] from Name of the file to be renamed.\r
- @param[in] to New name for the file.\r
-\r
- @retval 0 Successful completion.\r
- @retval -1 Operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-int\r
-EFIAPI\r
-da_ShellRename(\r
- const char *from,\r
- const char *to\r
- )\r
-{\r
- RETURN_STATUS Status;\r
- EFI_FILE_INFO *NewFileInfo;\r
- EFI_FILE_INFO *OldFileInfo;\r
- wchar_t *NewFn;\r
- int OldFd;\r
- SHELL_FILE_HANDLE FileHandle;\r
- wchar_t *NormalizedPath;\r
-\r
- // Open old file\r
- OldFd = open(from, O_RDWR, 0);\r
- if(OldFd >= 0) {\r
- FileHandle = (SHELL_FILE_HANDLE)gMD->fdarray[OldFd].devdata;\r
-\r
- NewFileInfo = malloc(sizeof(EFI_FILE_INFO) + PATH_MAX);\r
- if(NewFileInfo != NULL) {\r
- OldFileInfo = ShellGetFileInfo( FileHandle);\r
- if(OldFileInfo != NULL) {\r
- // Copy the Old file info into our new buffer, and free the old.\r
- memcpy(NewFileInfo, OldFileInfo, sizeof(EFI_FILE_INFO));\r
- FreePool(OldFileInfo);\r
- // Normalize path and convert to WCS.\r
- NormalizedPath = NormalizePath(to);\r
- if (NormalizedPath != NULL) {\r
- // Strip off all but the file name portion of new\r
- NewFn = GetFileNameFromPath(NormalizedPath);\r
- // Copy the new file name into our new file info buffer\r
- wcsncpy(NewFileInfo->FileName, NewFn, wcslen(NewFn) + 1);\r
- // Update the size of the structure.\r
- NewFileInfo->Size = sizeof(EFI_FILE_INFO) + StrSize(NewFn);\r
- // Apply the new file name\r
- Status = ShellSetFileInfo(FileHandle, NewFileInfo);\r
- free(NormalizedPath);\r
- free(NewFileInfo);\r
- if(Status == EFI_SUCCESS) {\r
- // File has been successfully renamed. We are DONE!\r
- return 0;\r
- }\r
- errno = EFI2errno( Status );\r
- EFIerrno = Status;\r
- }\r
- else {\r
- free(NewFileInfo);\r
- errno = ENOMEM;\r
- }\r
- }\r
- else {\r
- free(NewFileInfo);\r
- errno = EIO;\r
- }\r
- }\r
- else {\r
- errno = ENOMEM;\r
- }\r
- }\r
- return -1;\r
-}\r
-\r
-/** EFI Shell specific operations for deleting directories.\r
-\r
- @param[in] filp Pointer to a file descriptor structure.\r
-\r
- @retval 0 Successful completion.\r
- @retval -1 Operation failed. Further information is specified by errno.\r
-**/\r
-static\r
-int\r
-EFIAPI\r
-da_ShellRmdir(\r
- struct __filedes *filp\r
- )\r
-{\r
- SHELL_FILE_HANDLE FileHandle;\r
- RETURN_STATUS Status = RETURN_SUCCESS;\r
- EFI_FILE_INFO *FileInfo;\r
- int OldErrno;\r
- int Count = 0;\r
- BOOLEAN NoFile = FALSE;\r
-\r
- OldErrno = errno; // Save the original value\r
- errno = 0; // Make it easier to see if we have an error later\r
-\r
- FileHandle = (SHELL_FILE_HANDLE)filp->devdata;\r
-\r
- FileInfo = ShellGetFileInfo(FileHandle);\r
- if(FileInfo != NULL) {\r
- if((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r
- errno = ENOTDIR;\r
- }\r
- else {\r
- FreePool(FileInfo); // Free up the buffer from ShellGetFileInfo()\r
- // See if the directory has any entries other than ".." and ".".\r
- Status = ShellFindFirstFile( FileHandle, &FileInfo);\r
- if(Status == RETURN_SUCCESS) {\r
- ++Count;\r
- while(Count < 3) {\r
- Status = ShellFindNextFile( FileHandle, FileInfo, &NoFile);\r
- if(Status == RETURN_SUCCESS) {\r
- if(NoFile) {\r
- break;\r
- }\r
- ++Count;\r
- }\r
- else {\r
- Count = 99;\r
- }\r
- }\r
- /* Count == 99 and FileInfo is allocated if ShellFindNextFile failed.\r
- ShellFindNextFile has freed FileInfo itself if it sets NoFile TRUE.\r
- */\r
- if((! NoFile) || (Count == 99)) {\r
- free(FileInfo); // Free buffer from ShellFindFirstFile()\r
- }\r
- if(Count < 3) {\r
- // Directory is empty\r
- Status = ShellDeleteFile( &FileHandle);\r
- if(Status == RETURN_SUCCESS) {\r
- EFIerrno = RETURN_SUCCESS;\r
- errno = OldErrno; // Restore the original value\r
- return 0;\r
- /* ######## SUCCESSFUL RETURN ######## */\r
- }\r
- /* FileInfo is freed and FileHandle closed. */\r
- }\r
- else {\r
- if(Count == 99) {\r
- errno = EIO;\r
- }\r
- else {\r
- errno = ENOTEMPTY;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- else {\r
- errno = EIO;\r
- }\r
- ShellCloseFile( &FileHandle);\r
- EFIerrno = Status;\r
- if(errno == 0) {\r
- errno = EFI2errno( Status );\r
- }\r
- return -1;\r
-}\r
-\r
-/** Construct an instance of the abstract Shell device.\r
-\r
- Allocate the instance structure and populate it with the information for\r
- the device.\r
-\r
- @param[in] ImageHandle This application's image handle.\r
- @param[in] SystemTable Pointer to the UEFI System Table.\r
-\r
- @retval RETURN_SUCCESS Successful completion.\r
- @retval RETURN_OUT_OF_RESOURCES Failed to allocate memory for new device.\r
- @retval RETURN_INVALID_PARAMETER A default device has already been created.\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-__ctor_DevShell(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
-)\r
-{\r
- GenericInstance *Stream;\r
- DeviceNode *Node;\r
- RETURN_STATUS Status;\r
-\r
- Stream = (GenericInstance *)AllocateZeroPool(sizeof(GenericInstance));\r
- if(Stream == NULL) {\r
- return RETURN_OUT_OF_RESOURCES;\r
- }\r
-\r
- Stream->Cookie = CON_COOKIE;\r
- Stream->InstanceNum = 1;\r
- Stream->Dev = NULL;\r
- Stream->Abstraction.fo_close = &da_ShellClose;\r
- Stream->Abstraction.fo_read = &da_ShellRead;\r
- Stream->Abstraction.fo_write = &da_ShellWrite;\r
- Stream->Abstraction.fo_fcntl = &fnullop_fcntl;\r
- Stream->Abstraction.fo_poll = &da_ShellPoll;\r
- Stream->Abstraction.fo_flush = &fnullop_flush;\r
- Stream->Abstraction.fo_stat = &da_ShellStat;\r
- Stream->Abstraction.fo_ioctl = &da_ShellIoctl;\r
- Stream->Abstraction.fo_delete = &da_ShellDelete;\r
- Stream->Abstraction.fo_rmdir = &da_ShellRmdir;\r
- Stream->Abstraction.fo_mkdir = &da_ShellMkdir;\r
- Stream->Abstraction.fo_rename = &da_ShellRename;\r
- Stream->Abstraction.fo_lseek = &da_ShellSeek;\r
-\r
- Node = __DevRegister(NULL, NULL, &da_ShellOpen, Stream, 1, sizeof(GenericInstance), O_RDWR);\r
- Status = EFIerrno;\r
- Stream->Parent = Node;\r
-\r
- return Status;\r
-}\r
-\r
-/** Destructor for previously constructed EFI Shell device instances.\r
-\r
- @param[in] ImageHandle This application's image handle.\r
- @param[in] SystemTable Pointer to the UEFI System Table.\r
-\r
- @retval 0 Successful completion is always returned.\r
-**/\r
-RETURN_STATUS\r
-EFIAPI\r
-__dtor_DevShell(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
-)\r
-{\r
- if(daDefaultDevice != NULL) {\r
- if(daDefaultDevice->InstanceList != NULL) {\r
- FreePool(daDefaultDevice->InstanceList);\r
- }\r
- FreePool(daDefaultDevice);\r
- }\r
- return RETURN_SUCCESS;\r
-}\r