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