• 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
31 EFIAPI
ConnectAllEfi(VOID)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
LoadDriver(IN CONST CHAR16 * FileName,IN CONST BOOLEAN Connect)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
ShellCommandRunLoad(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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 }
282