]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Application/CapsuleApp/AppSupport.c
MdePkg/UefiDevicePathLib: Use BaseLib string conversion services
[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
1e09ec09
JY
30#define IS_HYPHEN(a) ((a) == L'-')\r
31#define IS_NULL(a) ((a) == L'\0')\r
32\r
592bad04
JY
33#define MAX_ARG_NUM 11\r
34\r
35UINTN Argc;\r
36CHAR16 **Argv;\r
37\r
38/**\r
39\r
40 This function parse application ARG.\r
41\r
42 @return Status\r
43**/\r
44EFI_STATUS\r
45GetArg (\r
46 VOID\r
47 )\r
48{\r
49 EFI_STATUS Status;\r
50 EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters;\r
51\r
52 Status = gBS->HandleProtocol (\r
53 gImageHandle,\r
54 &gEfiShellParametersProtocolGuid,\r
55 (VOID**)&ShellParameters\r
56 );\r
57 if (EFI_ERROR(Status)) {\r
58 return Status;\r
59 }\r
60\r
61 Argc = ShellParameters->Argc;\r
62 Argv = ShellParameters->Argv;\r
63 return EFI_SUCCESS;\r
64}\r
65\r
1e09ec09
JY
66/**\r
67 Converts a list of string to a specified buffer.\r
68\r
69 @param[out] Buf The output buffer that contains the string.\r
70 @param[in] BufferLength The length of the buffer\r
71 @param[in] Str The input string that contains the hex number\r
72\r
73 @retval EFI_SUCCESS The string was successfully converted to the buffer.\r
74\r
75**/\r
76EFI_STATUS\r
c608cda5 77InternalStrToBuf (\r
1e09ec09
JY
78 OUT UINT8 *Buf,\r
79 IN UINTN BufferLength,\r
80 IN CHAR16 *Str\r
81 )\r
82{\r
83 UINTN Index;\r
84 UINTN StrLength;\r
85 UINT8 Digit;\r
86 UINT8 Byte;\r
87\r
88 Digit = 0;\r
89\r
90 //\r
91 // Two hex char make up one byte\r
92 //\r
93 StrLength = BufferLength * sizeof (CHAR16);\r
94\r
95 for(Index = 0; Index < StrLength; Index++, Str++) {\r
96\r
97 if ((*Str >= L'a') && (*Str <= L'f')) {\r
98 Digit = (UINT8) (*Str - L'a' + 0x0A);\r
99 } else if ((*Str >= L'A') && (*Str <= L'F')) {\r
100 Digit = (UINT8) (*Str - L'A' + 0x0A);\r
101 } else if ((*Str >= L'0') && (*Str <= L'9')) {\r
102 Digit = (UINT8) (*Str - L'0');\r
103 } else {\r
104 return EFI_INVALID_PARAMETER;\r
105 }\r
106\r
107 //\r
108 // For odd characters, write the upper nibble for each buffer byte,\r
109 // and for even characters, the lower nibble.\r
110 //\r
111 if ((Index & 1) == 0) {\r
112 Byte = (UINT8) (Digit << 4);\r
113 } else {\r
114 Byte = Buf[Index / 2];\r
115 Byte &= 0xF0;\r
116 Byte = (UINT8) (Byte | Digit);\r
117 }\r
118\r
119 Buf[Index / 2] = Byte;\r
120 }\r
121\r
122 return EFI_SUCCESS;\r
123}\r
124\r
125/**\r
126 Converts a string to GUID value.\r
127 Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\r
128\r
129 @param[in] Str The registry format GUID string that contains the GUID value.\r
130 @param[out] Guid A pointer to the converted GUID value.\r
131\r
132 @retval EFI_SUCCESS The GUID string was successfully converted to the GUID value.\r
133 @retval EFI_UNSUPPORTED The input string is not in registry format.\r
134 @return others Some error occurred when converting part of GUID value.\r
135\r
136**/\r
137EFI_STATUS\r
c608cda5 138InternalStrToGuid (\r
1e09ec09
JY
139 IN CHAR16 *Str,\r
140 OUT EFI_GUID *Guid\r
141 )\r
142{\r
143 //\r
144 // Get the first UINT32 data\r
145 //\r
146 Guid->Data1 = (UINT32) StrHexToUint64 (Str);\r
147 while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {\r
148 Str ++;\r
149 }\r
150\r
151 if (IS_HYPHEN (*Str)) {\r
152 Str++;\r
153 } else {\r
154 return EFI_UNSUPPORTED;\r
155 }\r
156\r
157 //\r
158 // Get the second UINT16 data\r
159 //\r
160 Guid->Data2 = (UINT16) StrHexToUint64 (Str);\r
161 while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {\r
162 Str ++;\r
163 }\r
164\r
165 if (IS_HYPHEN (*Str)) {\r
166 Str++;\r
167 } else {\r
168 return EFI_UNSUPPORTED;\r
169 }\r
170\r
171 //\r
172 // Get the third UINT16 data\r
173 //\r
174 Guid->Data3 = (UINT16) StrHexToUint64 (Str);\r
175 while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {\r
176 Str ++;\r
177 }\r
178\r
179 if (IS_HYPHEN (*Str)) {\r
180 Str++;\r
181 } else {\r
182 return EFI_UNSUPPORTED;\r
183 }\r
184\r
185 //\r
186 // Get the following 8 bytes data\r
187 //\r
c608cda5 188 InternalStrToBuf (&Guid->Data4[0], 2, Str);\r
1e09ec09
JY
189 //\r
190 // Skip 2 byte hex chars\r
191 //\r
192 Str += 2 * 2;\r
193\r
194 if (IS_HYPHEN (*Str)) {\r
195 Str++;\r
196 } else {\r
197 return EFI_UNSUPPORTED;\r
198 }\r
c608cda5 199 InternalStrToBuf (&Guid->Data4[2], 6, Str);\r
1e09ec09
JY
200\r
201 return EFI_SUCCESS;\r
202}\r
203\r
592bad04
JY
204/**\r
205 Return File System Volume containing this shell application.\r
206\r
207 @return File System Volume containing this shell application.\r
208**/\r
209EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *\r
210GetMyVol (\r
211 VOID\r
212 )\r
213{\r
214 EFI_STATUS Status;\r
215 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
216 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
217\r
218 Status = gBS->HandleProtocol (\r
219 gImageHandle,\r
220 &gEfiLoadedImageProtocolGuid,\r
221 (VOID **)&LoadedImage\r
222 );\r
223 ASSERT_EFI_ERROR (Status);\r
224\r
225 Status = gBS->HandleProtocol (\r
226 LoadedImage->DeviceHandle,\r
227 &gEfiSimpleFileSystemProtocolGuid,\r
228 (VOID **)&Vol\r
229 );\r
230 if (!EFI_ERROR (Status)) {\r
231 return Vol;\r
232 }\r
233\r
234 return NULL;\r
235}\r
236\r
237/**\r
238 Read a file from this volume.\r
239\r
240 @param[in] Vol File System Volume\r
241 @param[in] FileName The file to be read.\r
242 @param[out] BufferSize The file buffer size\r
243 @param[out] Buffer The file buffer\r
244\r
245 @retval EFI_SUCCESS Read file successfully\r
246 @retval EFI_NOT_FOUND File not found\r
247**/\r
248EFI_STATUS\r
249ReadFileFromVol (\r
250 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol,\r
251 IN CHAR16 *FileName,\r
252 OUT UINTN *BufferSize,\r
253 OUT VOID **Buffer\r
254 )\r
255{\r
256 EFI_STATUS Status;\r
257 EFI_FILE_HANDLE RootDir;\r
258 EFI_FILE_HANDLE Handle;\r
259 UINTN FileInfoSize;\r
260 EFI_FILE_INFO *FileInfo;\r
261 UINTN TempBufferSize;\r
262 VOID *TempBuffer;\r
263\r
264 //\r
265 // Open the root directory\r
266 //\r
267 Status = Vol->OpenVolume (Vol, &RootDir);\r
268 if (EFI_ERROR (Status)) {\r
269 return Status;\r
270 }\r
271\r
272 //\r
273 // Open the file\r
274 //\r
275 Status = RootDir->Open (\r
276 RootDir,\r
277 &Handle,\r
278 FileName,\r
279 EFI_FILE_MODE_READ,\r
280 0\r
281 );\r
282 if (EFI_ERROR (Status)) {\r
283 RootDir->Close (RootDir);\r
284 return Status;\r
285 }\r
286\r
287 RootDir->Close (RootDir);\r
288\r
289 //\r
290 // Get the file information\r
291 //\r
292 FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;\r
293\r
294 FileInfo = AllocateZeroPool (FileInfoSize);\r
295 if (FileInfo == NULL) {\r
296 Handle->Close (Handle);\r
297 return Status;\r
298 }\r
299\r
300 Status = Handle->GetInfo (\r
301 Handle,\r
302 &gEfiFileInfoGuid,\r
303 &FileInfoSize,\r
304 FileInfo\r
305 );\r
306 if (EFI_ERROR (Status)) {\r
307 Handle->Close (Handle);\r
308 gBS->FreePool (FileInfo);\r
309 return Status;\r
310 }\r
311\r
312 //\r
313 // Allocate buffer for the file data. The last CHAR16 is for L'\0'\r
314 //\r
315 TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);\r
316 TempBuffer = AllocateZeroPool (TempBufferSize);\r
317 if (TempBuffer == NULL) {\r
318 Handle->Close (Handle);\r
319 gBS->FreePool (FileInfo);\r
320 return Status;\r
321 }\r
322\r
323 gBS->FreePool (FileInfo);\r
324\r
325 //\r
326 // Read the file data to the buffer\r
327 //\r
328 Status = Handle->Read (\r
329 Handle,\r
330 &TempBufferSize,\r
331 TempBuffer\r
332 );\r
333 if (EFI_ERROR (Status)) {\r
334 Handle->Close (Handle);\r
335 gBS->FreePool (TempBuffer);\r
336 return Status;\r
337 }\r
338\r
339 Handle->Close (Handle);\r
340\r
341 *BufferSize = TempBufferSize;\r
342 *Buffer = TempBuffer;\r
343 return EFI_SUCCESS;\r
344}\r
345\r
346/**\r
347 Read a file.\r
348 If ScanFs is FLASE, it will use this Vol as default Fs.\r
349 If ScanFs is TRUE, it will scan all FS and check the file.\r
350 If there is only one file match the name, it will be read.\r
351 If there is more than one file match the name, it will return Error.\r
352\r
11ee1bc9
DB
353 @param[in,out] ThisVol File System Volume\r
354 @param[in] FileName The file to be read.\r
355 @param[out] BufferSize The file buffer size\r
356 @param[out] Buffer The file buffer\r
357 @param[in] ScanFs Need Scan all FS\r
592bad04
JY
358\r
359 @retval EFI_SUCCESS Read file successfully\r
360 @retval EFI_NOT_FOUND File not found\r
361 @retval EFI_NO_MAPPING There is duplicated files found\r
362**/\r
363EFI_STATUS\r
364ReadFileToBufferEx (\r
365 IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL **ThisVol,\r
366 IN CHAR16 *FileName,\r
367 OUT UINTN *BufferSize,\r
368 OUT VOID **Buffer,\r
369 IN BOOLEAN ScanFs\r
370 )\r
371{\r
372 EFI_STATUS Status;\r
373 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
374 UINTN TempBufferSize;\r
375 VOID *TempBuffer;\r
376 UINTN NoHandles;\r
377 EFI_HANDLE *HandleBuffer;\r
378 UINTN Index;\r
379\r
380 //\r
381 // Check parameters\r
382 //\r
383 if ((FileName == NULL) || (Buffer == NULL) || (ThisVol == NULL)) {\r
384 return EFI_INVALID_PARAMETER;\r
385 }\r
386\r
387 //\r
388 // not scan fs\r
389 //\r
390 if (!ScanFs) {\r
391 if (*ThisVol == NULL) {\r
392 *ThisVol = GetMyVol ();\r
393 if (*ThisVol == NULL) {\r
394 return EFI_INVALID_PARAMETER;\r
395 }\r
396 }\r
397 //\r
398 // Read file directly from Vol\r
399 //\r
400 return ReadFileFromVol (*ThisVol, FileName, BufferSize, Buffer);\r
401 }\r
402\r
403 //\r
404 // need scan fs\r
405 //\r
406\r
407 //\r
408 // Get all Vol handle\r
409 //\r
410 Status = gBS->LocateHandleBuffer (\r
411 ByProtocol,\r
412 &gEfiSimpleFileSystemProtocolGuid,\r
413 NULL,\r
414 &NoHandles,\r
415 &HandleBuffer\r
416 );\r
417 if (EFI_ERROR (Status) && (NoHandles == 0)) {\r
418 return EFI_NOT_FOUND;\r
419 }\r
420\r
421 //\r
422 // Walk through each Vol\r
423 //\r
424 *ThisVol = NULL;\r
425 *BufferSize = 0;\r
426 *Buffer = NULL;\r
427 for (Index = 0; Index < NoHandles; Index++) {\r
428 Status = gBS->HandleProtocol (\r
429 HandleBuffer[Index],\r
430 &gEfiSimpleFileSystemProtocolGuid,\r
431 (VOID **)&Vol\r
432 );\r
433 if (EFI_ERROR(Status)) {\r
434 continue;\r
435 }\r
436\r
437 Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);\r
438 if (!EFI_ERROR (Status)) {\r
439 //\r
440 // Read file OK, check duplication\r
441 //\r
442 if (*ThisVol != NULL) {\r
443 //\r
444 // Find the duplicated file\r
445 //\r
446 gBS->FreePool (TempBuffer);\r
447 gBS->FreePool (*Buffer);\r
448 Print (L"Duplicated FileName found!\n");\r
449 return EFI_NO_MAPPING;\r
450 } else {\r
451 //\r
452 // Record value\r
453 //\r
454 *ThisVol = Vol;\r
455 *BufferSize = TempBufferSize;\r
456 *Buffer = TempBuffer;\r
457 }\r
458 }\r
459 }\r
460\r
461 //\r
462 // Scan Fs done\r
463 //\r
464 if (*ThisVol == NULL) {\r
465 return EFI_NOT_FOUND;\r
466 }\r
467\r
468 //\r
469 // Done\r
470 //\r
471 return EFI_SUCCESS;\r
472}\r
473\r
474/**\r
475 Read a file.\r
476\r
477 @param[in] FileName The file to be read.\r
478 @param[out] BufferSize The file buffer size\r
479 @param[out] Buffer The file buffer\r
480\r
481 @retval EFI_SUCCESS Read file successfully\r
482 @retval EFI_NOT_FOUND File not found\r
483**/\r
484EFI_STATUS\r
485ReadFileToBuffer (\r
486 IN CHAR16 *FileName,\r
487 OUT UINTN *BufferSize,\r
488 OUT VOID **Buffer\r
489 )\r
490{\r
491 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
492 Vol = NULL;\r
493 return ReadFileToBufferEx(&Vol, FileName, BufferSize, Buffer, FALSE);\r
494}\r
495\r
496/**\r
497 Write a file.\r
498\r
499 @param[in] FileName The file to be written.\r
500 @param[in] BufferSize The file buffer size\r
501 @param[in] Buffer The file buffer\r
502\r
503 @retval EFI_SUCCESS Write file successfully\r
504**/\r
505EFI_STATUS\r
506WriteFileFromBuffer (\r
507 IN CHAR16 *FileName,\r
508 IN UINTN BufferSize,\r
509 IN VOID *Buffer\r
510 )\r
511{\r
512 EFI_STATUS Status;\r
513 EFI_FILE_HANDLE RootDir;\r
514 EFI_FILE_HANDLE Handle;\r
515 UINTN TempBufferSize;\r
516 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol;\r
517\r
518 Vol = GetMyVol();\r
519 if (Vol == NULL) {\r
520 return EFI_NOT_FOUND;\r
521 }\r
522\r
523 //\r
524 // Open the root directory\r
525 //\r
526 Status = Vol->OpenVolume (Vol, &RootDir);\r
527 if (EFI_ERROR (Status)) {\r
528 return Status;\r
529 }\r
530\r
531 //\r
532 // Open the file\r
533 //\r
534 Status = RootDir->Open (\r
535 RootDir,\r
536 &Handle,\r
537 FileName,\r
538 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
539 0\r
540 );\r
541 if (EFI_ERROR (Status)) {\r
542 RootDir->Close (RootDir);\r
543 return Status;\r
544 }\r
545\r
546 //\r
547 // Delete file\r
548 //\r
549 Status = Handle->Delete(Handle);\r
550 if (EFI_ERROR(Status)) {\r
551 return Status;\r
552 }\r
553\r
554 //\r
555 // Open the file again\r
556 //\r
557 Status = RootDir->Open (\r
558 RootDir,\r
559 &Handle,\r
560 FileName,\r
561 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE,\r
562 0\r
563 );\r
564 if (EFI_ERROR (Status)) {\r
565 RootDir->Close (RootDir);\r
566 return Status;\r
567 }\r
568\r
569 RootDir->Close (RootDir);\r
570\r
571 //\r
572 // Write the file data from the buffer\r
573 //\r
574 TempBufferSize = BufferSize;\r
575 Status = Handle->Write (\r
576 Handle,\r
577 &TempBufferSize,\r
578 Buffer\r
579 );\r
580 if (EFI_ERROR (Status)) {\r
581 Handle->Close (Handle);\r
582 return Status;\r
583 }\r
584\r
585 Handle->Close (Handle);\r
586\r
587 return EFI_SUCCESS;\r
588}\r
589\r