]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c
ShellPkg: Unload image on EFI_SECURITY_VIOLATION
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Load.c
CommitLineData
a405b86d 1/** @file\r
2 Main file for attrib shell level 2 function.\r
3\r
c011b6c9 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
c671c910 5 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
56ba3746 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a405b86d 7\r
8**/\r
9\r
10#include "UefiShellLevel2CommandsLib.h"\r
11\r
12// This function was from from the BdsLib implementation in\r
13// IntelFrameworkModulePkg\Library\GenericBdsLib\BdsConnect.c\r
14// function name: BdsLibConnectAllEfi\r
15/**\r
16 This function will connect all current system handles recursively. The\r
17 connection will finish until every handle's child handle created if it have.\r
18\r
19 @retval EFI_SUCCESS All handles and it's child handle have been\r
20 connected\r
21 @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().\r
22\r
23**/\r
24EFI_STATUS\r
a405b86d 25ConnectAllEfi (\r
26 VOID\r
27 )\r
28{\r
29 EFI_STATUS Status;\r
30 UINTN HandleCount;\r
31 EFI_HANDLE *HandleBuffer;\r
32 UINTN Index;\r
33\r
34 Status = gBS->LocateHandleBuffer (\r
35 AllHandles,\r
36 NULL,\r
37 NULL,\r
38 &HandleCount,\r
39 &HandleBuffer\r
40 );\r
41 if (EFI_ERROR (Status)) {\r
42 return Status;\r
43 }\r
44\r
45 for (Index = 0; Index < HandleCount; Index++) {\r
46 Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
47 }\r
48\r
49 if (HandleBuffer != NULL) {\r
50 FreePool (HandleBuffer);\r
51 }\r
52\r
53 return EFI_SUCCESS;\r
54}\r
55\r
56/**\r
57 function to load a .EFI driver into memory and possible connect the driver.\r
58\r
59 if FileName is NULL then ASSERT.\r
60\r
61 @param[in] FileName FileName of the driver to load\r
62 @param[in] Connect Whether to connect or not\r
63\r
64 @retval EFI_SUCCESS the driver was loaded and if Connect was\r
65 true then connect was attempted. Connection may\r
66 have failed.\r
67 @retval EFI_OUT_OF_RESOURCES there was insufficient memory\r
68**/\r
69EFI_STATUS\r
a405b86d 70LoadDriver(\r
71 IN CONST CHAR16 *FileName,\r
72 IN CONST BOOLEAN Connect\r
73 )\r
74{\r
75 EFI_HANDLE LoadedDriverHandle;\r
76 EFI_STATUS Status;\r
a405b86d 77 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
78 EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage;\r
79\r
80 LoadedDriverImage = NULL;\r
81 FilePath = NULL;\r
a405b86d 82 LoadedDriverHandle = NULL;\r
83 Status = EFI_SUCCESS;\r
84\r
85 ASSERT (FileName != NULL);\r
86\r
87 //\r
88 // Fix local copies of the protocol pointers\r
89 //\r
90 Status = CommandInit();\r
91 ASSERT_EFI_ERROR(Status);\r
92\r
93 //\r
94 // Convert to DEVICE_PATH\r
95 //\r
96 FilePath = gEfiShellProtocol->GetDevicePathFromFilePath(FileName);\r
97\r
98 if (FilePath == NULL) {\r
99 ASSERT(FALSE);\r
100 return (EFI_INVALID_PARAMETER);\r
101 }\r
102\r
103 //\r
104 // Use LoadImage to get it into memory\r
105 //\r
106 Status = gBS->LoadImage(\r
107 FALSE,\r
108 gImageHandle,\r
109 FilePath,\r
110 NULL,\r
111 0,\r
112 &LoadedDriverHandle);\r
113\r
114 if (EFI_ERROR(Status)) {\r
c671c910
DB
115 //\r
116 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created\r
117 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.\r
118 // If the caller doesn't have the option to defer the execution of an image, we should\r
119 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.\r
120 //\r
121 if (Status == EFI_SECURITY_VIOLATION) {\r
122 gBS->UnloadImage (LoadedDriverHandle);\r
123 }\r
a405b86d 124 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_IMAGE), gShellLevel2HiiHandle, FileName, Status);\r
125 } else {\r
126 //\r
127 // Make sure it is a driver image\r
128 //\r
129 Status = gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage);\r
130\r
131 ASSERT (LoadedDriverImage != NULL);\r
132\r
133 if ( EFI_ERROR(Status)\r
134 || ( LoadedDriverImage->ImageCodeType != EfiBootServicesCode\r
135 && LoadedDriverImage->ImageCodeType != EfiRuntimeServicesCode)\r
136 ){\r
137 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_DRIVER), gShellLevel2HiiHandle, FileName);\r
138\r
139 //\r
140 // Exit and unload the non-driver image\r
141 //\r
142 gBS->Exit(LoadedDriverHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
143 Status = EFI_INVALID_PARAMETER;\r
144 }\r
145 }\r
146\r
147 if (!EFI_ERROR(Status)) {\r
148 //\r
149 // Start the image\r
150 //\r
151 Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL);\r
152 if (EFI_ERROR(Status)) {\r
153 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status);\r
154 } else {\r
155 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status);\r
156 }\r
157 }\r
158\r
159 if (!EFI_ERROR(Status) && Connect) {\r
160 //\r
161 // Connect it...\r
162 //\r
163 Status = ConnectAllEfi();\r
164 }\r
165\r
166 //\r
167 // clean up memory...\r
168 //\r
169 if (FilePath != NULL) {\r
170 FreePool(FilePath);\r
171 }\r
172\r
173 return (Status);\r
174}\r
175\r
176STATIC CONST SHELL_PARAM_ITEM LoadParamList[] = {\r
177 {L"-nc", TypeFlag},\r
178 {NULL, TypeMax}\r
179 };\r
180\r
181/**\r
182 Function for 'load' command.\r
183\r
184 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
185 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
186**/\r
187SHELL_STATUS\r
188EFIAPI\r
189ShellCommandRunLoad (\r
190 IN EFI_HANDLE ImageHandle,\r
191 IN EFI_SYSTEM_TABLE *SystemTable\r
192 )\r
193{\r
194 EFI_STATUS Status;\r
195 LIST_ENTRY *Package;\r
196 CHAR16 *ProblemParam;\r
197 SHELL_STATUS ShellStatus;\r
198 UINTN ParamCount;\r
199 EFI_SHELL_FILE_INFO *ListHead;\r
200 EFI_SHELL_FILE_INFO *Node;\r
201\r
202 ListHead = NULL;\r
203 ProblemParam = NULL;\r
204 ShellStatus = SHELL_SUCCESS;\r
205\r
206 //\r
207 // initialize the shell lib (we must be in non-auto-init...)\r
208 //\r
209 Status = ShellInitialize();\r
210 ASSERT_EFI_ERROR(Status);\r
211\r
212 //\r
213 // parse the command line\r
214 //\r
215 Status = ShellCommandLineParse (LoadParamList, &Package, &ProblemParam, TRUE);\r
216 if (EFI_ERROR(Status)) {\r
217 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
ba0014b9 218 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"load", ProblemParam);\r
a405b86d 219 FreePool(ProblemParam);\r
220 ShellStatus = SHELL_INVALID_PARAMETER;\r
221 } else {\r
222 ASSERT(FALSE);\r
223 }\r
224 } else {\r
225 //\r
226 // check for "-?"\r
227 //\r
228 if (ShellCommandLineGetFlag(Package, L"-?")) {\r
229 ASSERT(FALSE);\r
230 } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {\r
231 //\r
232 // we didnt get a single file to load parameter\r
233 //\r
ba0014b9 234 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"load");\r
a405b86d 235 ShellStatus = SHELL_INVALID_PARAMETER;\r
236 } else {\r
237 for ( ParamCount = 1\r
238 ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL\r
239 ; ParamCount++\r
240 ){\r
241 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount), EFI_FILE_MODE_READ, &ListHead);\r
242 if (!EFI_ERROR(Status)) {\r
243 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)\r
244 ; !IsNull(&ListHead->Link, &Node->Link)\r
245 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)\r
246 ){\r
247 //\r
248 // once we have an error preserve that value, but finish the loop.\r
249 //\r
250 if (EFI_ERROR(Status)) {\r
b54fd049 251 LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));\r
a405b86d 252 } else {\r
b54fd049 253 Status = LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));\r
a405b86d 254 }\r
255 } // for loop for multi-open\r
256 if (EFI_ERROR(Status)) {\r
257 ShellCloseFileMetaArg(&ListHead);\r
258 } else {\r
259 Status = ShellCloseFileMetaArg(&ListHead);;\r
260 }\r
261 } else {\r
262 //\r
263 // no files found.\r
264 //\r
ba0014b9 265 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"load", (CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount));\r
a405b86d 266 ShellStatus = SHELL_NOT_FOUND;\r
267 }\r
268 } // for loop for params\r
269 }\r
270\r
271 //\r
272 // free the command line package\r
273 //\r
274 ShellCommandLineFreeVarList (Package);\r
275 }\r
276\r
277 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {\r
278 ShellStatus = SHELL_DEVICE_ERROR;\r
279 }\r
280\r
281 return (ShellStatus);\r
282}\r