Member functions of EFI_SHELL_PROTOCOL and functions for creation,\r
manipulation, and initialization of EFI_SHELL_PROTOCOL.\r
\r
- Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
)\r
{\r
ShellFileHandleRemove(FileHandle);\r
- return (FileHandleClose(FileHandle));\r
+ return (FileHandleClose(ConvertShellHandleToEfiFileProtocol(FileHandle)));\r
+}\r
+\r
+/**\r
+ Internal worker to determine whether there is a BlockIo somewhere\r
+ upon the device path specified.\r
+\r
+ @param[in] DevicePath The device path to test.\r
+\r
+ @retval TRUE gEfiBlockIoProtocolGuid was installed on a handle with this device path\r
+ @retval FALSE gEfiBlockIoProtocolGuid was not found.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+InternalShellProtocolIsBlockIoPresent(\r
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+\r
+ Handle = NULL;\r
+\r
+ DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)DevicePath;\r
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &DevicePathCopy, &Handle);\r
+\r
+ if ((Handle != NULL) && (!EFI_ERROR(Status))) {\r
+ return (TRUE);\r
+ }\r
+ return (FALSE);\r
}\r
\r
/**\r
// make sure this is a valid to add device path\r
//\r
///@todo add BlockIo to this test...\r
- if (!InternalShellProtocolIsSimpleFileSystemPresent(DevicePath)) {\r
+ if (!InternalShellProtocolIsSimpleFileSystemPresent(DevicePath)\r
+ && !InternalShellProtocolIsBlockIoPresent(DevicePath)) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
\r
EFI_HANDLE MapHandle;\r
EFI_STATUS Status;\r
FILEPATH_DEVICE_PATH *FilePath;\r
+ FILEPATH_DEVICE_PATH *AlignedNode;\r
\r
PathForReturn = NULL;\r
PathSize = 0;\r
//\r
ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L"\\", 1);\r
- PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, FilePath->PathName, 0);\r
+\r
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
+ FreePool(AlignedNode);\r
}\r
} // for loop of remaining nodes\r
}\r
EFI_HANDLE Handle;\r
EFI_STATUS Status;\r
\r
+ if (Path == NULL) {\r
+ return (NULL);\r
+ }\r
+\r
MapName = NULL;\r
- ASSERT(Path != NULL);\r
+ NewPath = NULL;\r
\r
if (StrStr(Path, L":") == NULL) {\r
Cwd = EfiShellGetCurDir(NULL);\r
NewPath = AllocateZeroPool(Size);\r
ASSERT(NewPath != NULL);\r
StrCpy(NewPath, Cwd);\r
- if ((NewPath[0] == (CHAR16)L'\\') &&\r
- (NewPath[StrLen(NewPath)-1] == (CHAR16)L'\\')\r
- ) {\r
- ((CHAR16*)NewPath)[StrLen(NewPath)-1] = CHAR_NULL;\r
+ if (*Path == L'\\') {\r
+ Path++;\r
+ while (PathRemoveLastItem(NewPath)) ;\r
}\r
StrCat(NewPath, Path);\r
DevicePathForReturn = EfiShellGetDevicePathFromFilePath(NewPath);\r
//\r
// build the full device path\r
//\r
- DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName)+1);\r
+ if (*(Path+StrLen(MapName)+1) == CHAR_NULL) {\r
+ DevicePathForReturn = FileDevicePath(Handle, L"\\");\r
+ } else {\r
+ DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName)+1);\r
+ }\r
\r
FreePool(MapName);\r
if (DevicePathCopyForFree != NULL) {\r
CHAR8 *Lang;\r
CHAR8 *TempChar;\r
\r
+ UINTN ParentControllerCount;\r
+ EFI_HANDLE *ParentControllerBuffer;\r
+ UINTN ParentDriverCount;\r
+ EFI_HANDLE *ParentDriverBuffer;\r
+\r
if (BestDeviceName == NULL ||\r
DeviceHandle == NULL\r
){\r
continue;\r
}\r
if (Language == NULL) {\r
- Lang = AllocatePool(AsciiStrSize(CompName2->SupportedLanguages));\r
+ Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages));\r
+ if (Lang == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
AsciiStrCpy(Lang, CompName2->SupportedLanguages);\r
TempChar = AsciiStrStr(Lang, ";");\r
if (TempChar != NULL){\r
*TempChar = CHAR_NULL;\r
}\r
} else {\r
- Lang = AllocatePool(AsciiStrSize(Language));\r
+ Lang = AllocateZeroPool(AsciiStrSize(Language));\r
+ if (Lang == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
AsciiStrCpy(Lang, Language);\r
}\r
Status = CompName2->GetControllerName(CompName2, DeviceHandle, NULL, Lang, &DeviceNameToReturn);\r
if (HandleList != NULL) {\r
FreePool(HandleList);\r
}\r
- if (DeviceNameToReturn != NULL){\r
- ASSERT(BestDeviceName == NULL);\r
- StrnCatGrow(BestDeviceName, NULL, DeviceNameToReturn, 0);\r
- return (EFI_SUCCESS);\r
+\r
+ //\r
+ // Now check the parent controller using this as the child.\r
+ //\r
+ if (DeviceNameToReturn == NULL){\r
+ PARSE_HANDLE_DATABASE_PARENTS(DeviceHandle, &ParentControllerCount, &ParentControllerBuffer);\r
+ for (LoopVar = 0 ; LoopVar < ParentControllerCount ; LoopVar++) {\r
+ PARSE_HANDLE_DATABASE_UEFI_DRIVERS(ParentControllerBuffer[LoopVar], &ParentDriverCount, &ParentDriverBuffer);\r
+ for (HandleCount = 0 ; HandleCount < ParentDriverCount ; HandleCount++) {\r
+ //\r
+ // try using that driver's component name with controller and our driver as the child.\r
+ //\r
+ Status = gBS->OpenProtocol(\r
+ ParentDriverBuffer[HandleCount],\r
+ &gEfiComponentName2ProtocolGuid,\r
+ (VOID**)&CompName2,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ if (EFI_ERROR(Status)) {\r
+ Status = gBS->OpenProtocol(\r
+ ParentDriverBuffer[HandleCount],\r
+ &gEfiComponentNameProtocolGuid,\r
+ (VOID**)&CompName2,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ }\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+ if (Language == NULL) {\r
+ Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages));\r
+ if (Lang == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ AsciiStrCpy(Lang, CompName2->SupportedLanguages);\r
+ TempChar = AsciiStrStr(Lang, ";");\r
+ if (TempChar != NULL){\r
+ *TempChar = CHAR_NULL;\r
+ }\r
+ } else {\r
+ Lang = AllocateZeroPool(AsciiStrSize(Language));\r
+ if (Lang == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ AsciiStrCpy(Lang, Language);\r
+ }\r
+ Status = CompName2->GetControllerName(CompName2, ParentControllerBuffer[LoopVar], DeviceHandle, Lang, &DeviceNameToReturn);\r
+ FreePool(Lang);\r
+ Lang = NULL;\r
+ if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) {\r
+ break;\r
+ }\r
+\r
+\r
+\r
+ }\r
+ SHELL_FREE_NON_NULL(ParentDriverBuffer);\r
+ if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) {\r
+ break;\r
+ }\r
+ }\r
+ SHELL_FREE_NON_NULL(ParentControllerBuffer);\r
}\r
//\r
// dont return on fail since we will try device path if that bit is on\r
//\r
+ if (DeviceNameToReturn != NULL){\r
+ ASSERT(BestDeviceName != NULL);\r
+ StrnCatGrow(BestDeviceName, NULL, DeviceNameToReturn, 0);\r
+ return (EFI_SUCCESS);\r
+ }\r
}\r
if ((Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH) != 0) {\r
Status = gBS->LocateProtocol(\r
could not be opened.\r
@retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.\r
@retval EFI_DEVICE_ERROR The device had an error\r
+ @retval EFI_INVALID_PARAMETER FileHandle is NULL.\r
**/\r
EFI_STATUS\r
EFIAPI\r
EFI_STATUS Status;\r
EFI_HANDLE Handle;\r
\r
+ if (FileHandle == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
//\r
// find the handle of the device with that device handle and the file system\r
//\r
EFI_FILE_PROTOCOL *Handle1;\r
EFI_FILE_PROTOCOL *Handle2;\r
EFI_DEVICE_PATH_PROTOCOL *DpCopy;\r
+ FILEPATH_DEVICE_PATH *AlignedNode;\r
\r
- ASSERT(FileHandle != NULL);\r
- *FileHandle = NULL;\r
- Handle1 = NULL;\r
- DpCopy = DevicePath;\r
+ if (FileHandle == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ *FileHandle = NULL;\r
+ Handle1 = NULL;\r
+ Handle2 = NULL;\r
+ Handle = NULL;\r
+ DpCopy = DevicePath;\r
+ ShellHandle = NULL;\r
+ FilePathNode = NULL;\r
+ AlignedNode = NULL;\r
\r
Status = EfiShellOpenRoot(DevicePath, &ShellHandle);\r
\r
if (!EFI_ERROR(Status)) {\r
Handle1 = ConvertShellHandleToEfiFileProtocol(ShellHandle);\r
- //\r
- // chop off the begining part before the file system part...\r
- //\r
- ///@todo BlockIo?\r
- Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,\r
- &DevicePath,\r
- &Handle);\r
- if (!EFI_ERROR(Status)) {\r
+ if (Handle1 != NULL) {\r
//\r
- // To access as a file system, the file path should only\r
- // contain file path components. Follow the file path nodes\r
- // and find the target file\r
+ // chop off the begining part before the file system part...\r
//\r
- for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath\r
- ; !IsDevicePathEnd (&FilePathNode->Header)\r
- ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)\r
- ){\r
- //\r
- // For file system access each node should be a file path component\r
- //\r
- if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
- DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP\r
- ) {\r
- Status = EFI_UNSUPPORTED;\r
- break;\r
- }\r
-\r
- //\r
- // Open this file path node\r
- //\r
- Handle2 = Handle1;\r
- Handle1 = NULL;\r
-\r
+ ///@todo BlockIo?\r
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,\r
+ &DevicePath,\r
+ &Handle);\r
+ if (!EFI_ERROR(Status)) {\r
//\r
- // if this is the last node in the DevicePath always create (if that was requested).\r
+ // To access as a file system, the file path should only\r
+ // contain file path components. Follow the file path nodes\r
+ // and find the target file\r
//\r
- if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) {\r
- Status = Handle2->Open (\r
- Handle2,\r
- &Handle1,\r
- FilePathNode->PathName,\r
- OpenMode,\r
- Attributes\r
- );\r
- } else {\r
-\r
+ for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath\r
+ ; !IsDevicePathEnd (&FilePathNode->Header)\r
+ ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)\r
+ ){\r
+ SHELL_FREE_NON_NULL(AlignedNode);\r
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePathNode), FilePathNode);\r
//\r
- // This is not the last node and we dont want to 'create' existing\r
- // directory entries...\r
+ // For file system access each node should be a file path component\r
//\r
+ if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
+ DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP\r
+ ) {\r
+ Status = EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
\r
//\r
- // open without letting it create\r
- // prevents error on existing files/directories\r
+ // Open this file path node\r
//\r
- Status = Handle2->Open (\r
- Handle2,\r
- &Handle1,\r
- FilePathNode->PathName,\r
- OpenMode &~EFI_FILE_MODE_CREATE,\r
- Attributes\r
- );\r
+ Handle2 = Handle1;\r
+ Handle1 = NULL;\r
+\r
//\r
- // if above failed now open and create the 'item'\r
- // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)\r
+ // if this is the last node in the DevicePath always create (if that was requested).\r
//\r
- if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {\r
+ if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) {\r
Status = Handle2->Open (\r
Handle2,\r
&Handle1,\r
- FilePathNode->PathName,\r
+ AlignedNode->PathName,\r
OpenMode,\r
Attributes\r
);\r
+ } else {\r
+\r
+ //\r
+ // This is not the last node and we dont want to 'create' existing\r
+ // directory entries...\r
+ //\r
+\r
+ //\r
+ // open without letting it create\r
+ // prevents error on existing files/directories\r
+ //\r
+ Status = Handle2->Open (\r
+ Handle2,\r
+ &Handle1,\r
+ AlignedNode->PathName,\r
+ OpenMode &~EFI_FILE_MODE_CREATE,\r
+ Attributes\r
+ );\r
+ //\r
+ // if above failed now open and create the 'item'\r
+ // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)\r
+ //\r
+ if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {\r
+ Status = Handle2->Open (\r
+ Handle2,\r
+ &Handle1,\r
+ AlignedNode->PathName,\r
+ OpenMode,\r
+ Attributes\r
+ );\r
+ }\r
}\r
- }\r
- //\r
- // Close the last node\r
- //\r
- Handle2->Close (Handle2);\r
+ //\r
+ // Close the last node\r
+ //\r
+ ShellInfoObject.NewEfiShellProtocol->CloseFile (Handle2);\r
\r
- //\r
- // If there's been an error, stop\r
- //\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- } // for loop\r
+ //\r
+ // If there's been an error, stop\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ } // for loop\r
+ }\r
}\r
}\r
+ SHELL_FREE_NON_NULL(AlignedNode);\r
if (EFI_ERROR(Status)) {\r
if (Handle1 != NULL) {\r
- Handle1->Close(Handle1);\r
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(Handle1);\r
}\r
} else {\r
*FileHandle = ConvertEfiFileProtocolToShellHandle(Handle1, ShellFileHandleGetPath(ShellHandle));\r
{\r
EFI_SHELL_FILE_INFO *NewNode;\r
\r
- NewNode = AllocatePool(sizeof(EFI_SHELL_FILE_INFO));\r
+ NewNode = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
if (NewNode == NULL) {\r
return (NULL);\r
}\r
NewNode->FullName = AllocateZeroPool(StrSize(Node->FullName));\r
\r
NewNode->FileName = AllocateZeroPool(StrSize(Node->FileName));\r
- NewNode->Info = AllocatePool((UINTN)Node->Info->Size);\r
+ NewNode->Info = AllocateZeroPool((UINTN)Node->Info->Size);\r
if ( NewNode->FullName == NULL\r
|| NewNode->FileName == NULL\r
|| NewNode->Info == NULL\r
If FileHandle is a file and matches all of the remaining Pattern (which would be\r
on its last node), then add a EFI_SHELL_FILE_INFO object for this file to fileList.\r
\r
- if FileList is NULL, then ASSERT\r
- if FilePattern is NULL, then ASSERT\r
- if UnicodeCollation is NULL, then ASSERT\r
- if FileHandle is NULL, then ASSERT\r
-\r
Upon a EFI_SUCCESS return fromt he function any the caller is responsible to call\r
FreeFileList with FileList.\r
\r
@param[in] FileHandle The FileHandle to start with\r
@param[in,out] FileList pointer to pointer to list of found files.\r
@param[in] ParentNode The node for the parent. Same file as identified by HANDLE.\r
+ @param[in] MapName The file system name this file is on.\r
\r
@retval EFI_SUCCESS all files were found and the FileList contains a list.\r
@retval EFI_NOT_FOUND no files were found\r
IN EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation,\r
IN SHELL_FILE_HANDLE FileHandle,\r
IN OUT EFI_SHELL_FILE_INFO **FileList,\r
- IN CONST EFI_SHELL_FILE_INFO *ParentNode OPTIONAL\r
+ IN CONST EFI_SHELL_FILE_INFO *ParentNode OPTIONAL,\r
+ IN CONST CHAR16 *MapName\r
)\r
{\r
EFI_STATUS Status;\r
EFI_SHELL_FILE_INFO *ShellInfoNode;\r
EFI_SHELL_FILE_INFO *NewShellNode;\r
BOOLEAN Directory;\r
+ CHAR16 *NewFullName;\r
+ UINTN Size;\r
\r
if ( FilePattern == NULL\r
|| UnicodeCollation == NULL\r
} else {\r
NewShellNode->Handle = NULL;\r
if (*FileList == NULL) {\r
- *FileList = AllocatePool(sizeof(EFI_SHELL_FILE_INFO));\r
+ *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
InitializeListHead(&((*FileList)->Link));\r
}\r
\r
; ShellInfoNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ShellInfo->Link, &ShellInfoNode->Link)\r
){\r
if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){\r
- if (Directory){\r
+ if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) {\r
+ Size = StrSize(ShellInfoNode->FullName);\r
+ Size += StrSize(MapName) + sizeof(CHAR16);\r
+ NewFullName = AllocateZeroPool(Size);\r
+ if (NewFullName == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ StrCpy(NewFullName, MapName);\r
+ StrCat(NewFullName, ShellInfoNode->FullName+1);\r
+ FreePool((VOID*)ShellInfoNode->FullName);\r
+ ShellInfoNode->FullName = NewFullName;\r
+ }\r
+ }\r
+ if (Directory && !EFI_ERROR(Status) && ShellInfoNode->FullName != NULL && ShellInfoNode->FileName != NULL){\r
//\r
// should be a directory\r
//\r
//\r
//\r
//\r
- ASSERT_EFI_ERROR(Status);\r
if (EFI_ERROR(Status)) {\r
break;\r
}\r
//\r
// recurse with the next part of the pattern\r
//\r
- Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode);\r
+ Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName);\r
}\r
- } else {\r
+ } else if (!EFI_ERROR(Status)) {\r
//\r
// should be a file\r
//\r
Status = EFI_OUT_OF_RESOURCES;\r
}\r
if (*FileList == NULL) {\r
- *FileList = AllocatePool(sizeof(EFI_SHELL_FILE_INFO));\r
+ *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
InitializeListHead(&((*FileList)->Link));\r
}\r
\r
RootDevicePath = NULL;\r
RootFileHandle = NULL;\r
MapName = NULL;\r
- PatternCopy = AllocatePool(StrSize(FilePattern));\r
+ PatternCopy = AllocateZeroPool(StrSize(FilePattern));\r
if (PatternCopy == NULL) {\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
StrCpy(PatternCopy, FilePattern);\r
\r
- PatternCopy = CleanPath(PatternCopy);\r
+ PatternCopy = PathCleanUpDirectories(PatternCopy);\r
\r
Count = StrStr(PatternCopy, L":") - PatternCopy;\r
Count += 2;\r
; *PatternCurrentLocation != ':'\r
; PatternCurrentLocation++);\r
PatternCurrentLocation++;\r
- Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL);\r
+ Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);\r
}\r
FreePool(RootDevicePath);\r
}\r
}\r
\r
- if (PatternCopy != NULL) {\r
- FreePool(PatternCopy);\r
- }\r
- if (MapName != NULL) {\r
- FreePool(MapName);\r
- }\r
+ SHELL_FREE_NON_NULL(PatternCopy);\r
+ SHELL_FREE_NON_NULL(MapName);\r
\r
return(Status);\r
}\r
CHAR16 *Path2;\r
UINTN Path2Size;\r
CONST CHAR16 *CurDir;\r
+ BOOLEAN Found;\r
\r
- ShellCommandCleanPath(Path);\r
+ PathCleanUpDirectories(Path);\r
\r
Path2Size = 0;\r
Path2 = NULL;\r
\r
- ASSERT(FileList != NULL);\r
- ASSERT(*FileList != NULL);\r
+ if (FileList == NULL || *FileList == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
\r
if (*Path == L'.' && *(Path+1) == L'\\') {\r
- Path++;\r
+ Path+=2;\r
}\r
\r
//\r
StrnCatGrow(&Path2, &Path2Size, CurDir, 0);\r
if (*Path == L'\\') {\r
Path++;\r
+ while (PathRemoveLastItem(Path2)) ;\r
}\r
ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
StrnCatGrow(&Path2, &Path2Size, Path, 0);\r
StrnCatGrow(&Path2, NULL, Path, 0);\r
}\r
\r
- CleanPath (Path2);\r
+ PathCleanUpDirectories (Path2);\r
\r
//\r
// do the search\r
return (Status);\r
}\r
\r
+ Found = FALSE;\r
//\r
// We had no errors so open all the files (that are not already opened...)\r
//\r
){\r
if (ShellFileListItem->Status == 0 && ShellFileListItem->Handle == NULL) {\r
ShellFileListItem->Status = EfiShellOpenFileByName (ShellFileListItem->FullName, &ShellFileListItem->Handle, OpenMode);\r
+ Found = TRUE;\r
}\r
}\r
\r
+ if (!Found) {\r
+ return (EFI_NOT_FOUND);\r
+ }\r
return(EFI_SUCCESS);\r
}\r
\r
Size += 2*sizeof(CHAR16);\r
\r
Buffer = AllocateZeroPool(Size);\r
+ if (Buffer == NULL) {\r
+ if (!IsListEmpty (&List)) {\r
+ FreeEnvironmentVariableList(&List);\r
+ }\r
+ return (NULL);\r
+ }\r
CurrentWriteLocation = (CHAR16*)Buffer;\r
\r
for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)\r
//\r
// Free the list...\r
//\r
- FreeEnvironmentVariableList(&List);\r
+ if (!IsListEmpty (&List)) {\r
+ FreeEnvironmentVariableList(&List);\r
+ }\r
} else {\r
//\r
// We are doing a specific environment variable\r
TempString = NULL;\r
DirectoryName = NULL;\r
\r
- if (FileSystem == NULL && Dir == NULL) {\r
+ if ((FileSystem == NULL && Dir == NULL) || Dir == NULL) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
\r
DirectoryName = StrnCatGrow(&DirectoryName, NULL, Dir, 0);\r
ASSERT(DirectoryName != NULL);\r
\r
- CleanPath(DirectoryName);\r
+ PathCleanUpDirectories(DirectoryName);\r
\r
if (FileSystem == NULL) {\r
//\r
RetSize = 0;\r
RetVal = NULL;\r
\r
+ if (VariableName == NULL) {\r
+ return (NULL);\r
+ }\r
+\r
VariableName[0] = CHAR_NULL;\r
\r
while (TRUE) {\r
UINTN HandleCounter;\r
SHELL_PROTOCOL_HANDLE_LIST *OldProtocolNode;\r
\r
+ if (NewShell == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
BufferSize = 0;\r
Buffer = NULL;\r
OldProtocolNode = NULL;\r
InitializeListHead(&ShellInfoObject.OldShellList.Link);\r
\r
- ASSERT(NewShell != NULL);\r
-\r
//\r
// Initialize EfiShellProtocol object...\r
//\r
- *NewShell = &mShellProtocol;\r
Status = gBS->CreateEvent(0,\r
0,\r
NULL,\r
NULL,\r
&mShellProtocol.ExecutionBreak);\r
- ASSERT_EFI_ERROR(Status);\r
+ if (EFI_ERROR(Status)) {\r
+ return (Status);\r
+ }\r
\r
//\r
// Get the size of the buffer we need.\r
// Allocate and recall with buffer of correct size\r
//\r
Buffer = AllocateZeroPool(BufferSize);\r
- ASSERT(Buffer != NULL);\r
+ if (Buffer == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
Status = gBS->LocateHandle(ByProtocol,\r
&gEfiShellProtocolGuid,\r
NULL,\r
&BufferSize,\r
Buffer);\r
- ASSERT_EFI_ERROR(Status);\r
+ if (EFI_ERROR(Status)) {\r
+ FreePool(Buffer);\r
+ return (Status);\r
+ }\r
//\r
// now overwrite each of them, but save the info to restore when we end.\r
//\r
OldProtocolNode->Handle,\r
&gEfiShellProtocolGuid,\r
OldProtocolNode->Interface,\r
- (VOID*)(*NewShell));\r
+ (VOID*)(&mShellProtocol));\r
if (!EFI_ERROR(Status)) {\r
//\r
// we reinstalled sucessfully. log this so we can reverse it later.\r
&gImageHandle,\r
&gEfiShellProtocolGuid,\r
EFI_NATIVE_INTERFACE,\r
- (VOID*)(*NewShell));\r
+ (VOID*)(&mShellProtocol));\r
}\r
\r
if (PcdGetBool(PcdShellSupportOldProtocols)){\r
///@todo do we need to support ShellEnvironment (not ShellEnvironment2) also?\r
}\r
\r
+ if (!EFI_ERROR(Status)) {\r
+ *NewShell = &mShellProtocol;\r
+ }\r
return (Status);\r
}\r
\r
IN OUT EFI_SHELL_PROTOCOL *NewShell\r
)\r
{\r
- EFI_STATUS Status;\r
- SHELL_PROTOCOL_HANDLE_LIST *Node2;\r
+ EFI_STATUS Status;\r
+ SHELL_PROTOCOL_HANDLE_LIST *Node2;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
\r
//\r
// if we need to restore old protocols...\r
&gEfiShellProtocolGuid,\r
NewShell,\r
Node2->Interface);\r
- ASSERT_EFI_ERROR(Status);\r
FreePool(Node2);\r
}\r
} else {\r
Status = gBS->UninstallProtocolInterface(gImageHandle,\r
&gEfiShellProtocolGuid,\r
NewShell);\r
- ASSERT_EFI_ERROR(Status);\r
}\r
Status = gBS->CloseEvent(NewShell->ExecutionBreak);\r
+ NewShell->ExecutionBreak = NULL;\r
\r
+ Status = gBS->OpenProtocol(\r
+ gST->ConsoleInHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID**)&SimpleEx,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle1);\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle2);\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle3);\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle4);\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle1);\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle2);\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle3);\r
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle4);\r
+ }\r
return (Status);\r
}\r
\r
+/**\r
+ Notification function for keystrokes.\r
+\r
+ @param[in] KeyData The key that was pressed.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotificationFunction(\r
+ IN EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+// ShellPrintEx(-1,-1,L" <Notify> ");\r
+ if ((KeyData->Key.UnicodeChar == L'c' || KeyData->Key.UnicodeChar == 3) &&\r
+ (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))\r
+ ){ \r
+ if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
+ return (EFI_UNSUPPORTED);\r
+ }\r
+ return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));\r
+ } else if ((KeyData->Key.UnicodeChar == L's') &&\r
+ (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))\r
+ ){ \r
+ ShellInfoObject.HaltOutput = TRUE;\r
+ }\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. This \r
+ feature's enabled state was not known when the shell initially launched.\r
\r
+ @retval EFI_SUCCESS The feature is enabled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InernalEfiShellStartMonitor(\r
+ VOID\r
+ )\r
+{\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->OpenProtocol(\r
+ gST->ConsoleInHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID**)&SimpleEx,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ if (EFI_ERROR(Status)) {\r
+ ShellPrintHiiEx(\r
+ -1, \r
+ -1, \r
+ NULL,\r
+ STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
+ ShellInfoObject.HiiHandle);\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
+ return (EFI_UNSUPPORTED);\r
+ }\r
+\r
+ KeyData.KeyState.KeyToggleState = 0;\r
+ KeyData.Key.ScanCode = 0;\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+ KeyData.Key.UnicodeChar = L'c';\r
+\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlCNotifyHandle1);\r
+ \r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlCNotifyHandle2);\r
+ }\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+ KeyData.Key.UnicodeChar = 3;\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlCNotifyHandle3);\r
+ }\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlCNotifyHandle4);\r
+ }\r
+ return (Status);\r
+}\r