]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c
ShellPkg: Fix GCC 4.4 build issues
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / UefiShellDebug1CommandsLib.c
1 /** @file
2 Main file for NULL named library for debug1 profile shell command functions.
3
4 Copyright (c) 2010 - 2011, 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 "UefiShellDebug1CommandsLib.h"
16
17 STATIC CONST CHAR16 mFileName[] = L"Debug1Commands";
18 EFI_HANDLE gShellDebug1HiiHandle = NULL;
19 CONST EFI_GUID gShellDebug1HiiGuid = \
20 { \
21 0x25f200aa, 0xd3cb, 0x470a, { 0xbf, 0x51, 0xe7, 0xd1, 0x62, 0xd2, 0x2e, 0x6f } \
22 };
23
24 /**
25 Gets the debug file name. This will be used if HII is not working.
26
27 @retval NULL No file is available.
28 @return The NULL-terminated filename to get help from.
29 **/
30 CONST CHAR16*
31 EFIAPI
32 ShellCommandGetManFileNameDebug1 (
33 VOID
34 )
35 {
36 return (mFileName);
37 }
38
39 /**
40 Constructor for the Shell Debug1 Commands library.
41
42 @param ImageHandle the image handle of the process
43 @param SystemTable the EFI System Table pointer
44
45 @retval EFI_SUCCESS the shell command handlers were installed sucessfully
46 @retval EFI_UNSUPPORTED the shell level required was not found.
47 **/
48 EFI_STATUS
49 EFIAPI
50 UefiShellDebug1CommandsLibConstructor (
51 IN EFI_HANDLE ImageHandle,
52 IN EFI_SYSTEM_TABLE *SystemTable
53 )
54 {
55 //
56 // check our bit of the profiles mask
57 //
58 if ((PcdGet8(PcdShellProfileMask) & BIT1) == 0) {
59 return (EFI_UNSUPPORTED);
60 }
61
62 //
63 // install the HII stuff.
64 //
65 gShellDebug1HiiHandle = HiiAddPackages (&gShellDebug1HiiGuid, gImageHandle, UefiShellDebug1CommandsLibStrings, NULL);
66 if (gShellDebug1HiiHandle == NULL) {
67 return (EFI_DEVICE_ERROR);
68 }
69
70 //
71 // install our shell command handlers that are always installed
72 //
73 ShellCommandRegisterCommandName(L"setsize", ShellCommandRunSetSize , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETSIZE) );
74 ShellCommandRegisterCommandName(L"comp", ShellCommandRunComp , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_COMP) );
75 ShellCommandRegisterCommandName(L"mode", ShellCommandRunMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MODE) );
76 ShellCommandRegisterCommandName(L"memmap", ShellCommandRunMemMap , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MEMMAP) );
77 ShellCommandRegisterCommandName(L"eficompress", ShellCommandRunEfiCompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFICOMPRESS) );
78 ShellCommandRegisterCommandName(L"efidecompress", ShellCommandRunEfiDecompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFIDCOMPRESS) );
79 ShellCommandRegisterCommandName(L"dmem", ShellCommandRunDmem , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMEM) );
80 ShellCommandRegisterCommandName(L"loadpcirom", ShellCommandRunLoadPciRom , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD_PCI_ROM) );
81 ShellCommandRegisterCommandName(L"mm", ShellCommandRunMm , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MM) );
82 ShellCommandRegisterCommandName(L"setvar", ShellCommandRunSetVar , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETVAR) );
83 ShellCommandRegisterCommandName(L"sermode", ShellCommandRunSerMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SERMODE) );
84 ShellCommandRegisterCommandName(L"pci", ShellCommandRunPci , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_PCI) );
85 ShellCommandRegisterCommandName(L"smbiosview", ShellCommandRunSmbiosView , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SMBIOSVIEW) );
86 ShellCommandRegisterCommandName(L"dmpstore", ShellCommandRunDmpStore , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMPSTORE) );
87 ShellCommandRegisterCommandName(L"dblk", ShellCommandRunDblk , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DBLK) );
88 ShellCommandRegisterCommandName(L"edit", ShellCommandRunEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EDIT) );
89 ShellCommandRegisterCommandName(L"hexedit", ShellCommandRunHexEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_HEXEDIT) );
90
91 //
92 // check install profile bit of the profiles mask is set
93 //
94 if ((PcdGet8(PcdShellProfileMask) & BIT2) == 0) {
95 ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG) );
96 }
97
98
99
100
101 ShellCommandRegisterAlias(L"dmem", L"mem");
102
103 return (EFI_SUCCESS);
104 }
105
106 /**
107 Destructor for the library. free any resources.
108
109 @param ImageHandle The image handle of the process.
110 @param SystemTable The EFI System Table pointer.
111 **/
112 EFI_STATUS
113 EFIAPI
114 UefiShellDebug1CommandsLibDestructor (
115 IN EFI_HANDLE ImageHandle,
116 IN EFI_SYSTEM_TABLE *SystemTable
117 )
118 {
119 if (gShellDebug1HiiHandle != NULL) {
120 HiiRemovePackages(gShellDebug1HiiHandle);
121 }
122 return (EFI_SUCCESS);
123 }
124
125 STATIC CONST CHAR8 Hex[] = {
126 '0',
127 '1',
128 '2',
129 '3',
130 '4',
131 '5',
132 '6',
133 '7',
134 '8',
135 '9',
136 'A',
137 'B',
138 'C',
139 'D',
140 'E',
141 'F'
142 };
143
144 /**
145 Dump some hexadecimal data to the screen.
146
147 @param[in] Indent How many spaces to indent the output.
148 @param[in] Offset The offset of the printing.
149 @param[in] DataSize The size in bytes of UserData.
150 @param[in] UserData The data to print out.
151 **/
152 VOID
153 DumpHex (
154 IN UINTN Indent,
155 IN UINTN Offset,
156 IN UINTN DataSize,
157 IN VOID *UserData
158 )
159 {
160 UINT8 *Data;
161
162 CHAR8 Val[50];
163
164 CHAR8 Str[20];
165
166 UINT8 TempByte;
167 UINTN Size;
168 UINTN Index;
169
170 Data = UserData;
171 while (DataSize != 0) {
172 Size = 16;
173 if (Size > DataSize) {
174 Size = DataSize;
175 }
176
177 for (Index = 0; Index < Size; Index += 1) {
178 TempByte = Data[Index];
179 Val[Index * 3 + 0] = Hex[TempByte >> 4];
180 Val[Index * 3 + 1] = Hex[TempByte & 0xF];
181 Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' ');
182 Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
183 }
184
185 Val[Index * 3] = 0;
186 Str[Index] = 0;
187 ShellPrintEx(-1, -1, L"%*a%02X: %-.48a *%a*\r\n", Indent, "", Offset, Val, Str);
188
189 Data += Size;
190 Offset += Size;
191 DataSize -= Size;
192 }
193 }
194
195 /**
196 Convert a Unicode character to upper case only if
197 it maps to a valid small-case ASCII character.
198
199 This internal function only deal with Unicode character
200 which maps to a valid small-case ASCII character, i.e.
201 L'a' to L'z'. For other Unicode character, the input character
202 is returned directly.
203
204 @param Char The character to convert.
205
206 @retval LowerCharacter If the Char is with range L'a' to L'z'.
207 @retval Unchanged Otherwise.
208
209
210 //Stolen from MdePkg Baselib
211 **/
212 CHAR16
213 EFIAPI
214 CharToUpper (
215 IN CHAR16 Char
216 )
217 {
218 if (Char >= L'a' && Char <= L'z') {
219 return (CHAR16) (Char - (L'a' - L'A'));
220 }
221
222 return Char;
223 }
224
225 /**
226 Function returns a system configuration table that is stored in the
227 EFI System Table based on the provided GUID.
228
229 @param[in] TableGuid A pointer to the table's GUID type.
230 @param[in,out] Table On exit, a pointer to a system configuration table.
231
232 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
233 @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found.
234 **/
235 EFI_STATUS
236 EFIAPI
237 GetSystemConfigurationTable (
238 IN EFI_GUID *TableGuid,
239 IN OUT VOID **Table
240 )
241 {
242 UINTN Index;
243 ASSERT (Table != NULL);
244
245 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
246 if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
247 *Table = gST->ConfigurationTable[Index].VendorTable;
248 return EFI_SUCCESS;
249 }
250 }
251
252 return EFI_NOT_FOUND;
253 }
254
255 /**
256 Convert a Unicode character to numerical value.
257
258 This internal function only deal with Unicode character
259 which maps to a valid hexadecimal ASII character, i.e.
260 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
261 Unicode character, the value returned does not make sense.
262
263 @param Char The character to convert.
264
265 @return The numerical value converted.
266
267 **/
268 UINTN
269 EFIAPI
270 HexCharToUintn (
271 IN CHAR16 Char
272 )
273 {
274 if (Char >= L'0' && Char <= L'9') {
275 return Char - L'0';
276 }
277
278 return (UINTN) (10 + CharToUpper (Char) - L'A');
279 }
280
281 /**
282 Convert a string representation of a guid to a Guid value.
283
284 @param[in] StringGuid The pointer to the string of a guid.
285 @param[in,out] Guid The pointer to the GUID structure to populate.
286
287 @retval EFI_INVALID_PARAMETER A parameter was invalid.
288 @retval EFI_SUCCESS The conversion was successful.
289 **/
290 EFI_STATUS
291 EFIAPI
292 ConvertStringToGuid (
293 IN CONST CHAR16 *StringGuid,
294 IN OUT EFI_GUID *Guid
295 )
296 {
297 CHAR16 *TempCopy;
298 CHAR16 *TempSpot;
299 CHAR16 *Walker;
300 UINT64 TempVal;
301 EFI_STATUS Status;
302
303 if (StringGuid == NULL) {
304 return (EFI_INVALID_PARAMETER);
305 } else if (StrLen(StringGuid) != 36) {
306 return (EFI_INVALID_PARAMETER);
307 }
308 TempCopy = NULL;
309 TempCopy = StrnCatGrow(&TempCopy, NULL, StringGuid, 0);
310 Walker = TempCopy;
311 TempSpot = StrStr(Walker, L"-");
312 if (TempSpot != NULL) {
313 *TempSpot = CHAR_NULL;
314 }
315 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
316 if (EFI_ERROR(Status)) {
317 FreePool(TempCopy);
318 return (Status);
319 }
320 Guid->Data1 = (UINT32)TempVal;
321 Walker += 9;
322 TempSpot = StrStr(Walker, L"-");
323 if (TempSpot != NULL) {
324 *TempSpot = CHAR_NULL;
325 }
326 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
327 if (EFI_ERROR(Status)) {
328 FreePool(TempCopy);
329 return (Status);
330 }
331 Guid->Data2 = (UINT16)TempVal;
332 Walker += 5;
333 TempSpot = StrStr(Walker, L"-");
334 if (TempSpot != NULL) {
335 *TempSpot = CHAR_NULL;
336 }
337 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
338 if (EFI_ERROR(Status)) {
339 FreePool(TempCopy);
340 return (Status);
341 }
342 Guid->Data3 = (UINT16)TempVal;
343 Walker += 5;
344 Guid->Data4[0] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
345 Guid->Data4[0] = (UINT8)(Guid->Data4[0]+ (UINT8)HexCharToUintn(Walker[1]));
346 Walker += 2;
347 Guid->Data4[1] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
348 Guid->Data4[1] = (UINT8)(Guid->Data4[1] + (UINT8)HexCharToUintn(Walker[1]));
349 Walker += 3;
350 Guid->Data4[2] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
351 Guid->Data4[2] = (UINT8)(Guid->Data4[2] + (UINT8)HexCharToUintn(Walker[1]));
352 Walker += 2;
353 Guid->Data4[3] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
354 Guid->Data4[3] = (UINT8)(Guid->Data4[3] + (UINT8)HexCharToUintn(Walker[1]));
355 Walker += 2;
356 Guid->Data4[4] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
357 Guid->Data4[4] = (UINT8)(Guid->Data4[4] + (UINT8)HexCharToUintn(Walker[1]));
358 Walker += 2;
359 Guid->Data4[5] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
360 Guid->Data4[5] = (UINT8)(Guid->Data4[5] + (UINT8)HexCharToUintn(Walker[1]));
361 Walker += 2;
362 Guid->Data4[6] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
363 Guid->Data4[6] = (UINT8)(Guid->Data4[6] + (UINT8)HexCharToUintn(Walker[1]));
364 Walker += 2;
365 Guid->Data4[7] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
366 Guid->Data4[7] = (UINT8)(Guid->Data4[7] + (UINT8)HexCharToUintn(Walker[1]));
367 FreePool(TempCopy);
368 return (EFI_SUCCESS);
369 }
370
371 CHAR16 TempBufferCatSPrint[1000];
372 /**
373 Appends a formatted Unicode string to a Null-terminated Unicode string
374
375 This function appends a formatted Unicode string to the Null-terminated
376 Unicode string specified by String. String is optional and may be NULL.
377 Storage for the formatted Unicode string returned is allocated using
378 AllocateZeroPool(). The pointer to the appended string is returned. The caller
379 is responsible for freeing the returned string.
380
381 If String is not NULL and not aligned on a 16-bit boundary, then ASSERT().
382 If Format is NULL, then ASSERT().
383 If Format is not aligned on a 16-bit boundary, then ASSERT().
384
385 @param String A null-terminated Unicode string.
386 @param FormatString A null-terminated Unicode format string.
387 @param ... The variable argument list whose contents are accessed based
388 on the format string specified by Format.
389
390 @retval NULL There was not enough available memory.
391 @return Null terminated Unicode string is that is the formatted
392 string appended to String.
393 @sa CatVSPrint
394 **/
395 CHAR16*
396 EFIAPI
397 CatSPrint (
398 IN CONST CHAR16 *String OPTIONAL,
399 IN CONST CHAR16 *FormatString,
400 ...
401 )
402 {
403 VA_LIST Marker;
404 UINTN StringLength;
405 if (String != NULL) {
406 StrCpy(TempBufferCatSPrint, String);
407 } else {
408 *TempBufferCatSPrint = CHAR_NULL;
409 }
410 VA_START (Marker, FormatString);
411 StringLength = StrLen(TempBufferCatSPrint);
412
413 UnicodeVSPrint(TempBufferCatSPrint+StrLen(TempBufferCatSPrint), 1000-StringLength, FormatString, Marker);
414 return (AllocateCopyPool(StrSize(TempBufferCatSPrint), TempBufferCatSPrint));
415 }
416
417 /**
418 Clear the line at the specified Row.
419
420 @param[in] Row The row number to be cleared ( start from 1 )
421 @param[in] LastCol The last printable column.
422 @param[in] LastRow The last printable row.
423 **/
424 VOID
425 EFIAPI
426 EditorClearLine (
427 IN UINTN Row,
428 IN UINTN LastCol,
429 IN UINTN LastRow
430 )
431 {
432 CHAR16 Line[200];
433
434 if (Row == 0) {
435 Row = 1;
436 }
437
438 //
439 // prepare a blank line
440 //
441 SetMem16(Line, LastCol*sizeof(CHAR16), L' ');
442
443 if (Row == LastRow) {
444 //
445 // if CHAR_NULL is still at position 80, it will cause first line error
446 //
447 Line[LastCol - 1] = CHAR_NULL;
448 } else {
449 Line[LastCol] = CHAR_NULL;
450 }
451
452 //
453 // print out the blank line
454 //
455 ShellPrintEx (0, ((INT32)Row) - 1, Line);
456 }
457
458 /**
459 Determine if the character is valid for a filename.
460
461 @param[in] Ch The character to test.
462
463 @retval TRUE The character is valid.
464 @retval FALSE The character is not valid.
465 **/
466 BOOLEAN
467 EFIAPI
468 IsValidFileNameChar (
469 IN CONST CHAR16 Ch
470 )
471 {
472 //
473 // See if there are any illegal characters within the name
474 //
475 if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|' || Ch == L' ') {
476 return FALSE;
477 }
478
479 return TRUE;
480 }
481
482 /**
483 Check if file name has illegal characters.
484
485 @param Name The filename to check.
486
487 @retval TRUE The filename is ok.
488 @retval FALSE The filename is not ok.
489 **/
490 BOOLEAN
491 EFIAPI
492 IsValidFileName (
493 IN CONST CHAR16 *Name
494 )
495 {
496
497 UINTN Index;
498 UINTN Len;
499
500 //
501 // check the length of Name
502 //
503 for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) {
504 if (Name[Index] == '\\' || Name[Index] == ':') {
505 break;
506 }
507 }
508
509 if (Len == 0 || Len > 255) {
510 return FALSE;
511 }
512 //
513 // check whether any char in Name not appears in valid file name char
514 //
515 for (Index = 0; Index < StrLen (Name); Index++) {
516 if (!IsValidFileNameChar (Name[Index])) {
517 return FALSE;
518 }
519 }
520
521 return TRUE;
522 }
523
524 /**
525 Find a filename that is valid (not taken) with the given extension.
526
527 @param[in] Extension The file extension.
528
529 @retval NULL Something went wrong.
530 @return the valid filename.
531 **/
532 CHAR16 *
533 EFIAPI
534 EditGetDefaultFileName (
535 IN CONST CHAR16 *Extension
536 )
537 {
538 EFI_STATUS Status;
539 UINTN Suffix;
540 BOOLEAN FoundNewFile;
541 CHAR16 *FileNameTmp;
542
543 Suffix = 0;
544 FoundNewFile = FALSE;
545
546 do {
547 FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension);
548
549 //
550 // after that filename changed to path
551 //
552 Status = ShellFileExists (FileNameTmp);
553
554 if (Status == EFI_NOT_FOUND) {
555 return FileNameTmp;
556 }
557
558 FreePool (FileNameTmp);
559 FileNameTmp = NULL;
560 Suffix++;
561 } while (Suffix != 0);
562
563 FreePool (FileNameTmp);
564 return NULL;
565 }
566
567 /**
568 Read a file into an allocated buffer. The buffer is the responsibility
569 of the caller to free.
570
571 @param[in] FileName The filename of the file to open.
572 @param[out] Buffer Upon successful return, the pointer to the
573 address of the allocated buffer.
574 @param[out] BufferSize If not NULL, then the pointer to the size
575 of the allocated buffer.
576 @param[out] ReadOnly Upon successful return TRUE if the file is
577 read only. FALSE otherwise.
578
579 @retval EFI_NOT_FOUND The filename did not represent a file in the
580 file system.
581 @retval EFI_SUCCESS The file was read into the buffer.
582 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
583 @retval EFI_LOAD_ERROR The file read operation failed.
584 @retval EFI_INVALID_PARAMETER A parameter was invalid.
585 @retval EFI_INVALID_PARAMETER FileName was NULL.
586 @retval EFI_INVALID_PARAMETER FileName was a directory.
587 **/
588 EFI_STATUS
589 EFIAPI
590 ReadFileIntoBuffer (
591 IN CONST CHAR16 *FileName,
592 OUT VOID **Buffer,
593 OUT UINTN *BufferSize OPTIONAL,
594 OUT BOOLEAN *ReadOnly
595 )
596 {
597 VOID *InternalBuffer;
598 UINTN FileSize;
599 SHELL_FILE_HANDLE FileHandle;
600 BOOLEAN CreateFile;
601 EFI_STATUS Status;
602 EFI_FILE_INFO *Info;
603
604 InternalBuffer = NULL;
605 FileSize = 0;
606 FileHandle = NULL;
607 CreateFile = FALSE;
608 Status = EFI_SUCCESS;
609 Info = NULL;
610
611 if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) {
612 return (EFI_INVALID_PARAMETER);
613 }
614
615 //
616 // try to open the file
617 //
618 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
619
620 if (!EFI_ERROR(Status)) {
621 ASSERT(CreateFile == FALSE);
622 if (FileHandle == NULL) {
623 return EFI_LOAD_ERROR;
624 }
625
626 Info = ShellGetFileInfo(FileHandle);
627
628 if (Info->Attribute & EFI_FILE_DIRECTORY) {
629 FreePool (Info);
630 return EFI_INVALID_PARAMETER;
631 }
632
633 if (Info->Attribute & EFI_FILE_READ_ONLY) {
634 *ReadOnly = TRUE;
635 } else {
636 *ReadOnly = FALSE;
637 }
638 //
639 // get file size
640 //
641 FileSize = (UINTN) Info->FileSize;
642
643 FreePool (Info);
644 } else if (Status == EFI_NOT_FOUND) {
645 //
646 // file not exists. add create and try again
647 //
648 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
649 if (EFI_ERROR (Status)) {
650 return Status;
651 } else {
652 //
653 // it worked. now delete it and move on with the name (now validated)
654 //
655 Status = ShellDeleteFile (&FileHandle);
656 if (Status == EFI_WARN_DELETE_FAILURE) {
657 Status = EFI_ACCESS_DENIED;
658 }
659 if (EFI_ERROR (Status)) {
660 return Status;
661 }
662 }
663 //
664 // file doesn't exist, so set CreateFile to TRUE and can't be read-only
665 //
666 CreateFile = TRUE;
667 *ReadOnly = FALSE;
668 }
669
670 //
671 // the file exists
672 //
673 if (!CreateFile) {
674 //
675 // allocate buffer to read file
676 //
677 InternalBuffer = AllocateZeroPool (FileSize);
678 if (InternalBuffer == NULL) {
679 return EFI_OUT_OF_RESOURCES;
680 }
681 //
682 // read file into InternalBuffer
683 //
684 Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer);
685 ShellCloseFile(&FileHandle);
686 FileHandle = NULL;
687 if (EFI_ERROR (Status)) {
688 SHELL_FREE_NON_NULL (InternalBuffer);
689 return EFI_LOAD_ERROR;
690 }
691 }
692 *Buffer = InternalBuffer;
693 if (BufferSize != NULL) {
694 *BufferSize = FileSize;
695 }
696 return (EFI_SUCCESS);
697
698 }