2 A shell application that triggers capsule update process.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/UefiRuntimeServicesTableLib.h>
22 #include <Library/UefiLib.h>
23 #include <Library/PrintLib.h>
24 #include <Protocol/LoadedImage.h>
25 #include <Protocol/SimpleFileSystem.h>
26 #include <Protocol/ShellParameters.h>
27 #include <Guid/FileInfo.h>
30 #define IS_HYPHEN(a) ((a) == L'-')
31 #define IS_NULL(a) ((a) == L'\0')
33 #define MAX_ARG_NUM 11
40 This function parse application ARG.
50 EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
;
52 Status
= gBS
->HandleProtocol (
54 &gEfiShellParametersProtocolGuid
,
55 (VOID
**)&ShellParameters
57 if (EFI_ERROR(Status
)) {
61 Argc
= ShellParameters
->Argc
;
62 Argv
= ShellParameters
->Argv
;
67 Converts a list of string to a specified buffer.
69 @param[out] Buf The output buffer that contains the string.
70 @param[in] BufferLength The length of the buffer
71 @param[in] Str The input string that contains the hex number
73 @retval EFI_SUCCESS The string was successfully converted to the buffer.
79 IN UINTN BufferLength
,
91 // Two hex char make up one byte
93 StrLength
= BufferLength
* sizeof (CHAR16
);
95 for(Index
= 0; Index
< StrLength
; Index
++, Str
++) {
97 if ((*Str
>= L
'a') && (*Str
<= L
'f')) {
98 Digit
= (UINT8
) (*Str
- L
'a' + 0x0A);
99 } else if ((*Str
>= L
'A') && (*Str
<= L
'F')) {
100 Digit
= (UINT8
) (*Str
- L
'A' + 0x0A);
101 } else if ((*Str
>= L
'0') && (*Str
<= L
'9')) {
102 Digit
= (UINT8
) (*Str
- L
'0');
104 return EFI_INVALID_PARAMETER
;
108 // For odd characters, write the upper nibble for each buffer byte,
109 // and for even characters, the lower nibble.
111 if ((Index
& 1) == 0) {
112 Byte
= (UINT8
) (Digit
<< 4);
114 Byte
= Buf
[Index
/ 2];
116 Byte
= (UINT8
) (Byte
| Digit
);
119 Buf
[Index
/ 2] = Byte
;
126 Converts a string to GUID value.
127 Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
129 @param[in] Str The registry format GUID string that contains the GUID value.
130 @param[out] Guid A pointer to the converted GUID value.
132 @retval EFI_SUCCESS The GUID string was successfully converted to the GUID value.
133 @retval EFI_UNSUPPORTED The input string is not in registry format.
134 @return others Some error occurred when converting part of GUID value.
144 // Get the first UINT32 data
146 Guid
->Data1
= (UINT32
) StrHexToUint64 (Str
);
147 while (!IS_HYPHEN (*Str
) && !IS_NULL (*Str
)) {
151 if (IS_HYPHEN (*Str
)) {
154 return EFI_UNSUPPORTED
;
158 // Get the second UINT16 data
160 Guid
->Data2
= (UINT16
) StrHexToUint64 (Str
);
161 while (!IS_HYPHEN (*Str
) && !IS_NULL (*Str
)) {
165 if (IS_HYPHEN (*Str
)) {
168 return EFI_UNSUPPORTED
;
172 // Get the third UINT16 data
174 Guid
->Data3
= (UINT16
) StrHexToUint64 (Str
);
175 while (!IS_HYPHEN (*Str
) && !IS_NULL (*Str
)) {
179 if (IS_HYPHEN (*Str
)) {
182 return EFI_UNSUPPORTED
;
186 // Get the following 8 bytes data
188 InternalStrToBuf (&Guid
->Data4
[0], 2, Str
);
190 // Skip 2 byte hex chars
194 if (IS_HYPHEN (*Str
)) {
197 return EFI_UNSUPPORTED
;
199 InternalStrToBuf (&Guid
->Data4
[2], 6, Str
);
205 Return File System Volume containing this shell application.
207 @return File System Volume containing this shell application.
209 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*
215 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
216 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Vol
;
218 Status
= gBS
->HandleProtocol (
220 &gEfiLoadedImageProtocolGuid
,
221 (VOID
**)&LoadedImage
223 ASSERT_EFI_ERROR (Status
);
225 Status
= gBS
->HandleProtocol (
226 LoadedImage
->DeviceHandle
,
227 &gEfiSimpleFileSystemProtocolGuid
,
230 if (!EFI_ERROR (Status
)) {
238 Read a file from this volume.
240 @param[in] Vol File System Volume
241 @param[in] FileName The file to be read.
242 @param[out] BufferSize The file buffer size
243 @param[out] Buffer The file buffer
245 @retval EFI_SUCCESS Read file successfully
246 @retval EFI_NOT_FOUND File not found
250 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Vol
,
252 OUT UINTN
*BufferSize
,
257 EFI_FILE_HANDLE RootDir
;
258 EFI_FILE_HANDLE Handle
;
260 EFI_FILE_INFO
*FileInfo
;
261 UINTN TempBufferSize
;
265 // Open the root directory
267 Status
= Vol
->OpenVolume (Vol
, &RootDir
);
268 if (EFI_ERROR (Status
)) {
275 Status
= RootDir
->Open (
282 if (EFI_ERROR (Status
)) {
283 RootDir
->Close (RootDir
);
287 RootDir
->Close (RootDir
);
290 // Get the file information
292 FileInfoSize
= sizeof(EFI_FILE_INFO
) + 1024;
294 FileInfo
= AllocateZeroPool (FileInfoSize
);
295 if (FileInfo
== NULL
) {
296 Handle
->Close (Handle
);
300 Status
= Handle
->GetInfo (
306 if (EFI_ERROR (Status
)) {
307 Handle
->Close (Handle
);
308 gBS
->FreePool (FileInfo
);
313 // Allocate buffer for the file data. The last CHAR16 is for L'\0'
315 TempBufferSize
= (UINTN
) FileInfo
->FileSize
+ sizeof(CHAR16
);
316 TempBuffer
= AllocateZeroPool (TempBufferSize
);
317 if (TempBuffer
== NULL
) {
318 Handle
->Close (Handle
);
319 gBS
->FreePool (FileInfo
);
323 gBS
->FreePool (FileInfo
);
326 // Read the file data to the buffer
328 Status
= Handle
->Read (
333 if (EFI_ERROR (Status
)) {
334 Handle
->Close (Handle
);
335 gBS
->FreePool (TempBuffer
);
339 Handle
->Close (Handle
);
341 *BufferSize
= TempBufferSize
;
342 *Buffer
= TempBuffer
;
348 If ScanFs is FLASE, it will use this Vol as default Fs.
349 If ScanFs is TRUE, it will scan all FS and check the file.
350 If there is only one file match the name, it will be read.
351 If there is more than one file match the name, it will return Error.
353 @param[in,out] ThisVol File System Volume
354 @param[in] FileName The file to be read.
355 @param[out] BufferSize The file buffer size
356 @param[out] Buffer The file buffer
357 @param[in] ScanFs Need Scan all FS
359 @retval EFI_SUCCESS Read file successfully
360 @retval EFI_NOT_FOUND File not found
361 @retval EFI_NO_MAPPING There is duplicated files found
365 IN OUT EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
**ThisVol
,
367 OUT UINTN
*BufferSize
,
373 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Vol
;
374 UINTN TempBufferSize
;
377 EFI_HANDLE
*HandleBuffer
;
383 if ((FileName
== NULL
) || (Buffer
== NULL
) || (ThisVol
== NULL
)) {
384 return EFI_INVALID_PARAMETER
;
391 if (*ThisVol
== NULL
) {
392 *ThisVol
= GetMyVol ();
393 if (*ThisVol
== NULL
) {
394 return EFI_INVALID_PARAMETER
;
398 // Read file directly from Vol
400 return ReadFileFromVol (*ThisVol
, FileName
, BufferSize
, Buffer
);
408 // Get all Vol handle
410 Status
= gBS
->LocateHandleBuffer (
412 &gEfiSimpleFileSystemProtocolGuid
,
417 if (EFI_ERROR (Status
) && (NoHandles
== 0)) {
418 return EFI_NOT_FOUND
;
422 // Walk through each Vol
427 for (Index
= 0; Index
< NoHandles
; Index
++) {
428 Status
= gBS
->HandleProtocol (
430 &gEfiSimpleFileSystemProtocolGuid
,
433 if (EFI_ERROR(Status
)) {
437 Status
= ReadFileFromVol (Vol
, FileName
, &TempBufferSize
, &TempBuffer
);
438 if (!EFI_ERROR (Status
)) {
440 // Read file OK, check duplication
442 if (*ThisVol
!= NULL
) {
444 // Find the duplicated file
446 gBS
->FreePool (TempBuffer
);
447 gBS
->FreePool (*Buffer
);
448 Print (L
"Duplicated FileName found!\n");
449 return EFI_NO_MAPPING
;
455 *BufferSize
= TempBufferSize
;
456 *Buffer
= TempBuffer
;
464 if (*ThisVol
== NULL
) {
465 return EFI_NOT_FOUND
;
477 @param[in] FileName The file to be read.
478 @param[out] BufferSize The file buffer size
479 @param[out] Buffer The file buffer
481 @retval EFI_SUCCESS Read file successfully
482 @retval EFI_NOT_FOUND File not found
487 OUT UINTN
*BufferSize
,
491 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Vol
;
493 return ReadFileToBufferEx(&Vol
, FileName
, BufferSize
, Buffer
, FALSE
);
499 @param[in] FileName The file to be written.
500 @param[in] BufferSize The file buffer size
501 @param[in] Buffer The file buffer
503 @retval EFI_SUCCESS Write file successfully
506 WriteFileFromBuffer (
513 EFI_FILE_HANDLE RootDir
;
514 EFI_FILE_HANDLE Handle
;
515 UINTN TempBufferSize
;
516 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Vol
;
520 return EFI_NOT_FOUND
;
524 // Open the root directory
526 Status
= Vol
->OpenVolume (Vol
, &RootDir
);
527 if (EFI_ERROR (Status
)) {
534 Status
= RootDir
->Open (
538 EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
| EFI_FILE_MODE_CREATE
,
541 if (EFI_ERROR (Status
)) {
542 RootDir
->Close (RootDir
);
549 Status
= Handle
->Delete(Handle
);
550 if (EFI_ERROR(Status
)) {
555 // Open the file again
557 Status
= RootDir
->Open (
561 EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
| EFI_FILE_MODE_CREATE
,
564 if (EFI_ERROR (Status
)) {
565 RootDir
->Close (RootDir
);
569 RootDir
->Close (RootDir
);
572 // Write the file data from the buffer
574 TempBufferSize
= BufferSize
;
575 Status
= Handle
->Write (
580 if (EFI_ERROR (Status
)) {
581 Handle
->Close (Handle
);
585 Handle
->Close (Handle
);