fixed to build under IPF.
[mirror_edk2.git] / ShellPkg / Library / BaseShellLib / BaseShellLib.c
CommitLineData
94b17fa1 1/** @file\r
2 Provides interface to shell functionality for shell commands and applications.\r
3\r
4Copyright (c) 2006 - 2009, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <Uefi.h>\r
16#include <Library/ShellLib.h>\r
17#include <Library/UefiBootServicesTableLib.h>\r
18#include <Library/BaseLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/DevicePathLib.h>\r
d2b4564b 23#include <Library/PcdLib.h>\r
24#include <Library/FileHandleLib.h>\r
94b17fa1 25#include <Protocol/EfiShellEnvironment2.h>\r
26#include <Protocol/EfiShellInterface.h>\r
27#include <Protocol/EfiShell.h>\r
28#include <Protocol/EfiShellParameters.h>\r
29#include <Protocol/SimpleFileSystem.h>\r
30\r
d2b4564b 31#include "BaseShellLib.h"\r
32\r
94b17fa1 33#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)\r
34#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)\r
35\r
d2b4564b 36//\r
37// This is not static since it's extern in the .h file\r
38//\r
39SHELL_PARAM_ITEM EmptyParamList[] = {\r
40 {NULL, TypeMax}\r
41 };\r
42\r
43//\r
44// Static file globals for the shell library\r
45//\r
46STATIC EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;\r
47STATIC EFI_SHELL_INTERFACE *mEfiShellInterface;\r
48STATIC EFI_SHELL_PROTOCOL *mEfiShellProtocol;\r
49STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;\r
50STATIC EFI_HANDLE mEfiShellEnvironment2Handle;\r
51STATIC FILE_HANDLE_FUNCTION_MAP FileFunctionMap;\r
94b17fa1 52\r
53/**\r
54 helper function to find ShellEnvironment2 for constructor\r
55**/\r
56EFI_STATUS\r
57EFIAPI\r
58ShellFindSE2 (\r
59 IN EFI_HANDLE ImageHandle\r
60 )\r
61{\r
62 EFI_STATUS Status;\r
63 EFI_HANDLE *Buffer;\r
64 UINTN BufferSize;\r
65 UINTN HandleIndex;\r
66\r
67 BufferSize = 0;\r
68 Buffer = NULL;\r
69 Status = gBS->OpenProtocol(ImageHandle, \r
70 &gEfiShellEnvironment2Guid,\r
71 (VOID **)&mEfiShellEnvironment2,\r
72 ImageHandle,\r
73 NULL,\r
74 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
75 );\r
76 //\r
77 // look for the mEfiShellEnvironment2 protocol at a higher level\r
78 //\r
79 if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
80 (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
81 (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER)))) {\r
82 //\r
83 // figure out how big of a buffer we need.\r
84 //\r
85 Status = gBS->LocateHandle (ByProtocol,\r
86 &gEfiShellEnvironment2Guid,\r
87 NULL, // ignored for ByProtocol\r
88 &BufferSize,\r
89 Buffer\r
90 );\r
91 ASSERT(Status == EFI_BUFFER_TOO_SMALL);\r
92 Buffer = (EFI_HANDLE*)AllocatePool(BufferSize);\r
93 ASSERT(Buffer != NULL);\r
94 Status = gBS->LocateHandle (ByProtocol,\r
95 &gEfiShellEnvironment2Guid,\r
96 NULL, // ignored for ByProtocol\r
97 &BufferSize,\r
98 Buffer\r
99 );\r
100 if (!EFI_ERROR (Status)) {\r
101 //\r
102 // now parse the list of returned handles\r
103 //\r
104 Status = EFI_NOT_FOUND;\r
105 for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) {\r
106 Status = gBS->OpenProtocol(Buffer[HandleIndex], \r
107 &gEfiShellEnvironment2Guid,\r
108 (VOID **)&mEfiShellEnvironment2,\r
109 ImageHandle,\r
110 NULL,\r
111 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
112 );\r
113 if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
114 (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
115 (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER))) {\r
116 mEfiShellEnvironment2Handle = Buffer[HandleIndex];\r
117 Status = EFI_SUCCESS;\r
118 break;\r
119 }\r
120 }\r
121 }\r
122 }\r
123 if (Buffer != NULL) {\r
124 FreePool (Buffer);\r
125 }\r
126 return (Status);\r
127}\r
128\r
94b17fa1 129EFI_STATUS\r
130EFIAPI\r
d2b4564b 131ShellLibConstructorWorker (\r
94b17fa1 132 IN EFI_HANDLE ImageHandle,\r
133 IN EFI_SYSTEM_TABLE *SystemTable\r
d2b4564b 134){\r
94b17fa1 135 EFI_STATUS Status;\r
136\r
94b17fa1 137 //\r
138 // UEFI 2.0 shell interfaces (used preferentially)\r
139 //\r
140 Status = gBS->OpenProtocol(ImageHandle, \r
141 &gEfiShellProtocolGuid,\r
142 (VOID **)&mEfiShellProtocol,\r
143 ImageHandle,\r
144 NULL,\r
145 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
146 );\r
147 if (EFI_ERROR(Status)) {\r
148 mEfiShellProtocol = NULL;\r
149 }\r
150 Status = gBS->OpenProtocol(ImageHandle, \r
151 &gEfiShellParametersProtocolGuid,\r
152 (VOID **)&mEfiShellParametersProtocol,\r
153 ImageHandle,\r
154 NULL,\r
155 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
156 );\r
157 if (EFI_ERROR(Status)) {\r
158 mEfiShellParametersProtocol = NULL;\r
159 }\r
160\r
161 if (mEfiShellParametersProtocol == NULL || mEfiShellProtocol == NULL) {\r
162 //\r
163 // Moved to seperate function due to complexity\r
164 //\r
165 Status = ShellFindSE2(ImageHandle);\r
166\r
167 if (EFI_ERROR(Status)) {\r
168 DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status));\r
169 mEfiShellEnvironment2 = NULL;\r
170 }\r
171 Status = gBS->OpenProtocol(ImageHandle, \r
172 &gEfiShellInterfaceGuid,\r
173 (VOID **)&mEfiShellInterface,\r
174 ImageHandle,\r
175 NULL,\r
176 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
177 );\r
178 if (EFI_ERROR(Status)) {\r
179 mEfiShellInterface = NULL;\r
180 }\r
181 }\r
182 //\r
183 // only success getting 2 of either the old or new, but no 1/2 and 1/2\r
184 //\r
185 if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) || \r
186 (mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) {\r
d2b4564b 187 if (mEfiShellProtocol != NULL) {\r
188 FileFunctionMap.GetFileInfo = mEfiShellProtocol->GetFileInfo;\r
189 FileFunctionMap.SetFileInfo = mEfiShellProtocol->SetFileInfo;\r
190 FileFunctionMap.ReadFile = mEfiShellProtocol->ReadFile;\r
191 FileFunctionMap.WriteFile = mEfiShellProtocol->WriteFile;\r
192 FileFunctionMap.CloseFile = mEfiShellProtocol->CloseFile;\r
193 FileFunctionMap.DeleteFile = mEfiShellProtocol->DeleteFile;\r
194 FileFunctionMap.GetFilePosition = mEfiShellProtocol->GetFilePosition;\r
195 FileFunctionMap.SetFilePosition = mEfiShellProtocol->SetFilePosition;\r
196 FileFunctionMap.FlushFile = mEfiShellProtocol->FlushFile;\r
197 FileFunctionMap.GetFileSize = mEfiShellProtocol->GetFileSize;\r
198 } else {\r
199 FileFunctionMap.GetFileInfo = FileHandleGetInfo;\r
200 FileFunctionMap.SetFileInfo = FileHandleSetInfo;\r
201 FileFunctionMap.ReadFile = FileHandleRead;\r
202 FileFunctionMap.WriteFile = FileHandleWrite;\r
203 FileFunctionMap.CloseFile = FileHandleClose;\r
204 FileFunctionMap.DeleteFile = FileHandleDelete;\r
205 FileFunctionMap.GetFilePosition = FileHandleGetPosition;\r
206 FileFunctionMap.SetFilePosition = FileHandleSetPosition;\r
207 FileFunctionMap.FlushFile = FileHandleFlush;\r
208 FileFunctionMap.GetFileSize = FileHandleGetSize;\r
209 }\r
94b17fa1 210 return (EFI_SUCCESS);\r
211 }\r
212 return (EFI_NOT_FOUND);\r
213}\r
d2b4564b 214/**\r
215 Constructor for the Shell library.\r
216\r
217 Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.\r
218\r
219 @param ImageHandle the image handle of the process\r
220 @param SystemTable the EFI System Table pointer\r
221\r
222 @retval EFI_SUCCESS the initialization was complete sucessfully\r
223 @return others an error ocurred during initialization\r
224**/\r
225EFI_STATUS\r
226EFIAPI\r
227ShellLibConstructor (\r
228 IN EFI_HANDLE ImageHandle,\r
229 IN EFI_SYSTEM_TABLE *SystemTable\r
230 )\r
231{\r
232\r
233\r
234 mEfiShellEnvironment2 = NULL;\r
235 mEfiShellProtocol = NULL;\r
236 mEfiShellParametersProtocol = NULL;\r
237 mEfiShellInterface = NULL;\r
238 mEfiShellEnvironment2Handle = NULL;\r
239\r
240 ///@todo make a worker constructor so initialize function works\r
241 //\r
242 // verify that auto initialize is not set false\r
243 // \r
244 if (PcdGetBool(PcdShellLibAutoInitialize) == 0) {\r
245 return (EFI_SUCCESS);\r
246 }\r
247 \r
248 return (ShellLibConstructorWorker(ImageHandle, SystemTable));\r
249}\r
94b17fa1 250\r
251/**\r
252 Destructory for the library. free any resources.\r
253**/\r
254EFI_STATUS\r
255EFIAPI\r
256ShellLibDestructor (\r
257 IN EFI_HANDLE ImageHandle,\r
258 IN EFI_SYSTEM_TABLE *SystemTable\r
259 )\r
260{\r
261 if (mEfiShellEnvironment2 != NULL) {\r
262 gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
263 &gEfiShellEnvironment2Guid,\r
264 ImageHandle,\r
265 NULL);\r
d2b4564b 266 mEfiShellEnvironment2 = NULL;\r
94b17fa1 267 }\r
268 if (mEfiShellInterface != NULL) {\r
269 gBS->CloseProtocol(ImageHandle,\r
270 &gEfiShellInterfaceGuid,\r
271 ImageHandle,\r
272 NULL); \r
d2b4564b 273 mEfiShellInterface = NULL;\r
94b17fa1 274 }\r
275 if (mEfiShellProtocol != NULL) {\r
276 gBS->CloseProtocol(ImageHandle,\r
277 &gEfiShellProtocolGuid,\r
278 ImageHandle,\r
d2b4564b 279 NULL); \r
280 mEfiShellProtocol = NULL;\r
94b17fa1 281 }\r
282 if (mEfiShellParametersProtocol != NULL) {\r
283 gBS->CloseProtocol(ImageHandle,\r
284 &gEfiShellParametersProtocolGuid,\r
285 ImageHandle,\r
286 NULL); \r
d2b4564b 287 mEfiShellParametersProtocol = NULL;\r
94b17fa1 288 }\r
d2b4564b 289 mEfiShellEnvironment2Handle = NULL;\r
94b17fa1 290 return (EFI_SUCCESS);\r
291}\r
d2b4564b 292\r
293/**\r
294 This function causes the shell library to initialize itself. If the shell library\r
295 is already initialized it will de-initialize all the current protocol poitners and\r
296 re-populate them again.\r
297\r
298 When the library is used with PcdShellLibAutoInitialize set to true this function\r
299 will return EFI_SUCCESS and perform no actions.\r
300\r
301 This function is intended for internal access for shell commands only.\r
302\r
303 @retval EFI_SUCCESS the initialization was complete sucessfully\r
304\r
305**/\r
306EFI_STATUS\r
307EFIAPI\r
308ShellInitialize (\r
309 ) {\r
310 //\r
311 // if auto initialize is not false then skip\r
312 //\r
313 if (PcdGetBool(PcdShellLibAutoInitialize) != 0) {\r
314 return (EFI_SUCCESS);\r
315 }\r
316\r
317 //\r
318 // deinit the current stuff\r
319 //\r
320 ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST));\r
321\r
322 //\r
323 // init the new stuff\r
324 //\r
325 return (ShellLibConstructorWorker(gImageHandle, gST));\r
326}\r
327\r
94b17fa1 328/**\r
329 This function will retrieve the information about the file for the handle \r
330 specified and store it in allocated pool memory.\r
331\r
332