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