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 - 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
ConnectAllEfi(VOID)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
LoadDriver(IN CONST CHAR16 * FileName,IN CONST BOOLEAN Connect)76 LoadDriver(
77 IN CONST CHAR16 *FileName,
78 IN CONST BOOLEAN Connect
79 )
80 {
81 EFI_HANDLE LoadedDriverHandle;
82 EFI_STATUS Status;
83 EFI_DEVICE_PATH_PROTOCOL *FilePath;
84 EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage;
85
86 LoadedDriverImage = NULL;
87 FilePath = NULL;
88 LoadedDriverHandle = NULL;
89 Status = EFI_SUCCESS;
90
91 ASSERT (FileName != NULL);
92
93 //
94 // Fix local copies of the protocol pointers
95 //
96 Status = CommandInit();
97 ASSERT_EFI_ERROR(Status);
98
99 //
100 // Convert to DEVICE_PATH
101 //
102 FilePath = gEfiShellProtocol->GetDevicePathFromFilePath(FileName);
103
104 if (FilePath == NULL) {
105 ASSERT(FALSE);
106 return (EFI_INVALID_PARAMETER);
107 }
108
109 //
110 // Use LoadImage to get it into memory
111 //
112 Status = gBS->LoadImage(
113 FALSE,
114 gImageHandle,
115 FilePath,
116 NULL,
117 0,
118 &LoadedDriverHandle);
119
120 if (EFI_ERROR(Status)) {
121 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_IMAGE), gShellLevel2HiiHandle, FileName, Status);
122 } else {
123 //
124 // Make sure it is a driver image
125 //
126 Status = gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage);
127
128 ASSERT (LoadedDriverImage != NULL);
129
130 if ( EFI_ERROR(Status)
131 || ( LoadedDriverImage->ImageCodeType != EfiBootServicesCode
132 && LoadedDriverImage->ImageCodeType != EfiRuntimeServicesCode)
133 ){
134 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_DRIVER), gShellLevel2HiiHandle, FileName);
135
136 //
137 // Exit and unload the non-driver image
138 //
139 gBS->Exit(LoadedDriverHandle, EFI_INVALID_PARAMETER, 0, NULL);
140 Status = EFI_INVALID_PARAMETER;
141 }
142 }
143
144 if (!EFI_ERROR(Status)) {
145 //
146 // Start the image
147 //
148 Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL);
149 if (EFI_ERROR(Status)) {
150 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status);
151 } else {
152 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status);
153 }
154 }
155
156 if (!EFI_ERROR(Status) && Connect) {
157 //
158 // Connect it...
159 //
160 Status = ConnectAllEfi();
161 }
162
163 //
164 // clean up memory...
165 //
166 if (FilePath != NULL) {
167 FreePool(FilePath);
168 }
169
170 return (Status);
171 }
172
173 STATIC CONST SHELL_PARAM_ITEM LoadParamList[] = {
174 {L"-nc", TypeFlag},
175 {NULL, TypeMax}
176 };
177
178 /**
179 Function for 'load' command.
180
181 @param[in] ImageHandle Handle to the Image (NULL if Internal).
182 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
183 **/
184 SHELL_STATUS
185 EFIAPI
ShellCommandRunLoad(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)186 ShellCommandRunLoad (
187 IN EFI_HANDLE ImageHandle,
188 IN EFI_SYSTEM_TABLE *SystemTable
189 )
190 {
191 EFI_STATUS Status;
192 LIST_ENTRY *Package;
193 CHAR16 *ProblemParam;
194 SHELL_STATUS ShellStatus;
195 UINTN ParamCount;
196 EFI_SHELL_FILE_INFO *ListHead;
197 EFI_SHELL_FILE_INFO *Node;
198
199 ListHead = NULL;
200 ProblemParam = NULL;
201 ShellStatus = SHELL_SUCCESS;
202
203 //
204 // initialize the shell lib (we must be in non-auto-init...)
205 //
206 Status = ShellInitialize();
207 ASSERT_EFI_ERROR(Status);
208
209 //
210 // parse the command line
211 //
212 Status = ShellCommandLineParse (LoadParamList, &Package, &ProblemParam, TRUE);
213 if (EFI_ERROR(Status)) {
214 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
215 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"load", ProblemParam);
216 FreePool(ProblemParam);
217 ShellStatus = SHELL_INVALID_PARAMETER;
218 } else {
219 ASSERT(FALSE);
220 }
221 } else {
222 //
223 // check for "-?"
224 //
225 if (ShellCommandLineGetFlag(Package, L"-?")) {
226 ASSERT(FALSE);
227 } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
228 //
229 // we didnt get a single file to load parameter
230 //
231 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"load");
232 ShellStatus = SHELL_INVALID_PARAMETER;
233 } else {
234 for ( ParamCount = 1
235 ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL
236 ; ParamCount++
237 ){
238 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount), EFI_FILE_MODE_READ, &ListHead);
239 if (!EFI_ERROR(Status)) {
240 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
241 ; !IsNull(&ListHead->Link, &Node->Link)
242 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
243 ){
244 //
245 // once we have an error preserve that value, but finish the loop.
246 //
247 if (EFI_ERROR(Status)) {
248 LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));
249 } else {
250 Status = LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));
251 }
252 } // for loop for multi-open
253 if (EFI_ERROR(Status)) {
254 ShellCloseFileMetaArg(&ListHead);
255 } else {
256 Status = ShellCloseFileMetaArg(&ListHead);;
257 }
258 } else {
259 //
260 // no files found.
261 //
262 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"load", (CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount));
263 ShellStatus = SHELL_NOT_FOUND;
264 }
265 } // for loop for params
266 }
267
268 //
269 // free the command line package
270 //
271 ShellCommandLineFreeVarList (Package);
272 }
273
274 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
275 ShellStatus = SHELL_DEVICE_ERROR;
276 }
277
278 return (ShellStatus);
279 }
280