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