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