• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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