]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/CapsuleApp/AppSupport.c
MdeModulePkg/CapsuleApp: Add CapsuleApp application.
[mirror_edk2.git] / MdeModulePkg / Application / CapsuleApp / AppSupport.c
CommitLineData
592bad04
JY
1/** @file\r
2 A shell application that triggers capsule update process.\r
3\r
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT 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/BaseLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Library/UefiRuntimeServicesTableLib.h>\r
22#include <Library/UefiLib.h>\r
23#include <Library/PrintLib.h>\r
24#include <Protocol/LoadedImage.h>\r
25#include <Protocol/SimpleFileSystem.h>\r
26#include <Protocol/ShellParameters.h>\r
27#include <Guid/FileInfo.h>\r
28#include <Guid/Gpt.h>\r
29\r
30#define MAX_ARG_NUM 11\r
31\r
32UINTN Argc;\r
33CHAR16 **Argv;\r
34\r
35/**\r
36\r
37 This function parse application ARG.\r
38\r
39 @return Status\r
40**/\r
41EFI_STATUS\r
42GetArg (\r
43 VOID\r
44 )\r
45{\r
46 EFI_STATUS Status;\r
47 EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;\r
48\r
49 Status = gBS->HandleProtocol (\r
50 gImageHandle,\r
51 &gEfiShellParametersProtocolGuid,\r
52 (VOID**)&ShellParameters\r
53 );\r
54 if (EFI_ERROR(Status)) {\r
55 return Status;\r
56 }\r
57\r
58 Argc = ShellParameters->Argc;\r
59 Argv = ShellParameters->Argv;\r
60 return EFI_SUCCESS;\r
61}\r
62\r
63/**\r
64 Return File System Volume containing this shell application.\r
65\r
66 @return File System Volume containing this shell application.\r
67**/\r
68EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *\r
69GetMyVol (\r
70 VOID\r
71 )\r
72{\r
73 EFI_STATUS Status;\r
74 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
75 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
76\r
77 Status = gBS->HandleProtocol (\r
78 gImageHandle,\r
79 &gEfiLoadedImageProtocolGuid,\r
80 (VOID **)&LoadedImage\r
81 );\r
82 ASSERT_EFI_ERROR (Status);\r
83\r
84 Status = gBS->HandleProtocol (\r
85 LoadedImage->DeviceHandle,\r
86 &gEfiSimpleFileSystemProtocolGuid,\r
87 (VOID **)&Vol\r
88 );\r
89 if (!EFI_ERROR (Status)) {\r
90 return Vol;\r
91 }\r
92\r
93 return NULL;\r
94}\r
95\r
96/**\r
97 Read a file from this volume.\r
98\r
99 @param[in] Vol File System Volume\r
100 @param[in] FileName The file to be read.\r
101 @param[out] BufferSize The file buffer size\r
102 @param[out] Buffer The file buffer\r
103\r
104 @retval EFI_SUCCESS Read file successfully\r
105 @retval EFI_NOT_FOUND File not found\r
106**/\r
107EFI_STATUS\r
108ReadFileFromVol (\r
109 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol,\r
110 IN CHAR16 *FileName,\r
111 OUT UINTN *BufferSize,\r
112 OUT VOID **Buffer\r
113 )\r
114{\r
115 EFI_STATUS Status;\r
116 EFI_FILE_HANDLE RootDir;\r
117 EFI_FILE_HANDLE Handle;\r
118 UINTN FileInfoSize;\r
119 EFI_FILE_INFO *FileInfo;\r
120 UINTN TempBufferSize;\r
121 VOID *TempBuffer;\r
122\r
123 //\r
124 // Open the root directory\r
125 //\r
126 Status = Vol->OpenVolume (Vol, &RootDir);\r
127 if (EFI_ERROR (Status)) {\r
128 return Status;\r
129 }\r
130\r
131 //\r
132 // Open the file\r
133 //\r
134 Status = RootDir->Open (\r
135 RootDir,\r
136 &Handle,\r
137 FileName,\r
138 EFI_FILE_MODE_READ,\r
139 0\r
140 );\r
141 if (EFI_ERROR (Status)) {\r
142 RootDir->Close (RootDir);\r
143 return Status;\r
144 }\r
145\r
146 RootDir->Close (RootDir);\r
147\r
148 //\r
149 // Get the file information\r
150 //\r
151 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;\r
152\r
153 FileInfo = AllocateZeroPool (FileInfoSize);\r
154 if (FileInfo == NULL) {\r
155 Handle->Close (Handle);\r
156 return Status;\r
157 }\r
158\r
159 Status = Handle->GetInfo (\r
160 Handle,\r
161 &gEfiFileInfoGuid,\r
162 &FileInfoSize,\r
163 FileInfo\r
164 );\r
165 if (EFI_ERROR (Status)) {\r
166 Handle->Close (Handle);\r
167 gBS->FreePool (FileInfo);\r
168 return Status;\r
169 }\r
170\r
171 //\r
172 // Allocate buffer for the file data. The last CHAR16 is for L'\0'\r
173 //\r
174 TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);\r
175 TempBuffer = AllocateZeroPool (TempBufferSize);\r
176 if (TempBuffer == NULL) {\r
177 Handle->Close (Handle);\r
178 gBS->FreePool (FileInfo);\r
179 return Status;\r
180 }\r
181\r
182 gBS->FreePool (FileInfo);\r
183\r
184 //\r
185 // Read the file data to the buffer\r
186 //\r
187 Status = Handle->Read (\r
188 Handle,\r
189 &TempBufferSize,\r
190 TempBuffer\r
191 );\r
192 if (EFI_ERROR (Status)) {\r
193 Handle->Close (Handle);\r
194 gBS->FreePool (TempBuffer);\r
195 return Status;\r
196 }\r
197\r
198 Handle->Close (Handle);\r
199\r
200 *BufferSize = TempBufferSize;\r
201 *Buffer = TempBuffer;\r
202 return EFI_SUCCESS;\r
203}\r
204\r
205/**\r
206 Read a file.\r
207 If ScanFs is FLASE, it will use this Vol as default Fs.\r
208 If ScanFs is TRUE, it will scan all FS and check the file.\r
209 If there is only one file match the name, it will be read.\r
210 If there is more than one file match the name, it will return Error.\r
211\r
212 @param[in] ThisVol File System Volume\r
213 @param[in] FileName The file to be read.\r
214 @param[out] BufferSize The file buffer size\r
215 @param[out] Buffer The file buffer\r
216 @param[in] ScanFs Need Scan all FS\r
217\r
218 @retval EFI_SUCCESS Read file successfully\r
219 @retval EFI_NOT_FOUND File not found\r
220 @retval EFI_NO_MAPPING There is duplicated files found\r
221**/\r
222EFI_STATUS\r
223ReadFileToBufferEx (\r
224 IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **ThisVol,\r
225 IN CHAR16 *FileName,\r
226 OUT UINTN *BufferSize,\r
227 OUT VOID **Buffer,\r
228 IN BOOLEAN ScanFs\r
229 )\r
230{\r
231 EFI_STATUS Status;\r
232 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
233 UINTN TempBufferSize;\r
234 VOID *TempBuffer;\r
235 UINTN NoHandles;\r
236 EFI_HANDLE *HandleBuffer;\r
237 UINTN Index;\r
238\r
239 //\r
240 // Check parameters\r
241 //\r
242 if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {\r
243 return EFI_INVALID_PARAMETER;\r
244 }\r
245\r
246 //\r
247 // not scan fs\r
248 //\r
249 if (!ScanFs) {\r
250 if (*ThisVol == NULL) {\r
251 *ThisVol = GetMyVol ();\r
252 if (*ThisVol == NULL) {\r
253 return EFI_INVALID_PARAMETER;\r
254 }\r
255 }\r
256 //\r
257 // Read file directly from Vol\r
258 //\r
259 return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);\r
260 }\r
261\r
262 //\r
263 // need scan fs\r
264 //\r
265\r
266 //\r
267 // Get all Vol handle\r
268 //\r
269 Status = gBS->LocateHandleBuffer (\r
270 ByProtocol,\r
271 &gEfiSimpleFileSystemProtocolGuid,\r
272 NULL,\r
273 &NoHandles,\r
274 &HandleBuffer\r
275 );\r
276 if (EFI_ERROR (Status) && (NoHandles == 0)) {\r
277 return EFI_NOT_FOUND;\r
278 }\r
279\r
280 //\r
281 // Walk through each Vol\r
282 //\r
283 *ThisVol = NULL;\r
284 *BufferSize = 0;\r
285 *Buffer = NULL;\r
286 for (Index = 0; Index < NoHandles; Index++) {\r
287 Status = gBS->HandleProtocol (\r
288 HandleBuffer[Index],\r
289 &gEfiSimpleFileSystemProtocolGuid,\r
290 (VOID **)&Vol\r
291 );\r
292 if (EFI_ERROR(Status)) {\r
293 continue;\r
294 }\r
295\r
296 Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);\r
297 if (!EFI_ERROR (Status)) {\r
298 //\r
299 // Read file OK, check duplication\r
300 //\r
301 if (*ThisVol != NULL) {\r
302 //\r
303 // Find the duplicated file\r
304 //\r
305 gBS->FreePool (TempBuffer);\r
306 gBS->FreePool (*Buffer);\r
307 Print (L"Duplicated FileName found!\n");\r
308 return EFI_NO_MAPPING;\r
309 } else {\r
310 //\r
311 // Record value\r
312 //\r
313 *ThisVol = Vol;\r
314 *BufferSize = TempBufferSize;\r
315 *Buffer = TempBuffer;\r
316 }\r
317 }\r
318 }\r
319\r
320 //\r
321 // Scan Fs done\r
322 //\r
323 if (*ThisVol == NULL) {\r
324 return EFI_NOT_FOUND;\r
325 }\r
326\r
327 //\r
328 // Done\r
329 //\r
330 return EFI_SUCCESS;\r
331}\r
332\r
333/**\r
334 Read a file.\r
335\r
336 @param[in] FileName The file to be read.\r
337 @param[out] BufferSize The file buffer size\r
338 @param[out] Buffer The file buffer\r
339\r
340 @retval EFI_SUCCESS Read file successfully\r
341 @retval EFI_NOT_FOUND File not found\r
342**/\r
343EFI_STATUS\r
344ReadFileToBuffer (\r
345 IN CHAR16 *FileName,\r
346 OUT UINTN *BufferSize,\r
347 OUT VOID **Buffer\r
348 )\r
349{\r
350 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
351 Vol = NULL;\r
352 return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);\r
353}\r
354\r
355/**\r
356 Write a file.\r
357\r
358 @param[in] FileName The file to be written.\r
359 @param[in] BufferSize The file buffer size\r
360 @param[in] Buffer The file buffer\r
361\r
362 @retval EFI_SUCCESS Write file successfully\r
363**/\r
364EFI_STATUS\r
365WriteFileFromBuffer (\r
366 IN CHAR16 *FileName,\r
367 IN UINTN BufferSize,\r
368 IN VOID *Buffer\r
369 )\r
370{\r
371 EFI_STATUS Status;\r
372 EFI_FILE_HANDLE RootDir;\r
373 EFI_FILE_HANDLE Handle;\r
374 UINTN TempBufferSize;\r
375 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
376\r
377 Vol = GetMyVol();\r
378 if (Vol == NULL) {\r
379 return EFI_NOT_FOUND;\r
380 }\r
381\r
382 //\r
383 // Open the root directory\r
384 //\r
385 Status = Vol->OpenVolume (Vol, &RootDir);\r
386 if (EFI_ERROR (Status)) {\r
387 return Status;\r
388 }\r
389\r
390 //\r
391 // Open the file\r
392 //\r
393 Status = RootDir->Open (\r
394 RootDir,\r
395 &Handle,\r
396 FileName,\r
397 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
398 0\r
399 );\r
400 if (EFI_ERROR (Status)) {\r
401 RootDir->Close (RootDir);\r
402 return Status;\r
403 }\r
404\r
405 //\r
406 // Delete file\r
407 //\r
408 Status = Handle->Delete(Handle);\r
409 if (EFI_ERROR(Status)) {\r
410 return Status;\r
411 }\r
412\r
413 //\r
414 // Open the file again\r
415 //\r
416 Status = RootDir->Open (\r
417 RootDir,\r
418 &Handle,\r
419 FileName,\r
420 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
421 0\r
422 );\r
423 if (EFI_ERROR (Status)) {\r
424 RootDir->Close (RootDir);\r
425 return Status;\r
426 }\r
427\r
428 RootDir->Close (RootDir);\r
429\r
430 //\r
431 // Write the file data from the buffer\r
432 //\r
433 TempBufferSize = BufferSize;\r
434 Status = Handle->Write (\r
435 Handle,\r
436 &TempBufferSize,\r
437 Buffer\r
438 );\r
439 if (EFI_ERROR (Status)) {\r
440 Handle->Close (Handle);\r
441 return Status;\r
442 }\r
443\r
444 Handle->Close (Handle);\r
445\r
446 return EFI_SUCCESS;\r
447}\r
448\r