]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c
pointer verification (not NULL) and buffer overrun fixes.
[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 EFIAPI
154 DumpHex (
155 IN UINTN Indent,
156 IN UINTN Offset,
157 IN UINTN DataSize,
158 IN VOID *UserData
159 )
160 {
161 UINT8 *Data;
162
163 CHAR8 Val[50];
164
165 CHAR8 Str[20];
166
167 UINT8 TempByte;
168 UINTN Size;
169 UINTN Index;
170
171 Data = UserData;
172 while (DataSize != 0) {
173 Size = 16;
174 if (Size > DataSize) {
175 Size = DataSize;
176 }
177
178 for (Index = 0; Index < Size; Index += 1) {
179 TempByte = Data[Index];
180 Val[Index * 3 + 0] = Hex[TempByte >> 4];
181 Val[Index * 3 + 1] = Hex[TempByte & 0xF];
182 Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' ');
183 Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
184 }
185
186 Val[Index * 3] = 0;
187 Str[Index] = 0;
188 ShellPrintEx(-1, -1, L"%*a%02X: %-.48a *%a*\r\n", Indent, "", Offset, Val, Str);
189
190 Data += Size;
191 Offset += Size;
192 DataSize -= Size;
193 }
194 }
195
196 /**
197 Convert a Unicode character to upper case only if
198 it maps to a valid small-case ASCII character.
199
200 This internal function only deal with Unicode character
201 which maps to a valid small-case ASCII character, i.e.
202 L'a' to L'z'. For other Unicode character, the input character
203 is returned directly.
204
205 @param Char The character to convert.
206
207 @retval LowerCharacter If the Char is with range L'a' to L'z'.
208 @retval Unchanged Otherwise.
209
210
211 //Stolen from MdePkg Baselib
212 **/
213 CHAR16
214 EFIAPI
215 CharToUpper (
216 IN CHAR16 Char
217 )
218 {
219 if (Char >= L'a' && Char <= L'z') {
220 return (CHAR16) (Char - (L'a' - L'A'));
221 }
222
223 return Char;
224 }
225
226 /**
227 Function returns a system configuration table that is stored in the
228 EFI System Table based on the provided GUID.
229
230 @param[in] TableGuid A pointer to the table's GUID type.
231 @param[in,out] Table On exit, a pointer to a system configuration table.
232
233 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
234 @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found.
235 **/
236 EFI_STATUS
237 EFIAPI
238 GetSystemConfigurationTable (
239 IN EFI_GUID *TableGuid,
240 IN OUT VOID **Table
241 )
242 {
243 UINTN Index;
244 ASSERT (Table != NULL);
245
246 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
247 if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
248 *Table = gST->ConfigurationTable[Index].VendorTable;
249 return EFI_SUCCESS;
250 }
251 }
252
253 return EFI_NOT_FOUND;
254 }
255
256 /**
257 Convert a Unicode character to numerical value.
258
259 This internal function only deal with Unicode character
260 which maps to a valid hexadecimal ASII character, i.e.
261 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
262 Unicode character, the value returned does not make sense.
263
264 @param Char The character to convert.
265
266 @return The numerical value converted.
267
268 **/
269 UINTN
270 EFIAPI
271 HexCharToUintn (
272 IN CHAR16 Char
273 )
274 {
275 if (Char >= L'0' && Char <= L'9') {
276 return Char - L'0';
277 }
278
279 return (UINTN) (10 + CharToUpper (Char) - L'A');
280 }
281
282 /**
283 Convert a string representation of a guid to a Guid value.
284
285 @param[in] StringGuid The pointer to the string of a guid.
286 @param[in,out] Guid The pointer to the GUID structure to populate.
287
288 @retval EFI_INVALID_PARAMETER A parameter was invalid.
289 @retval EFI_SUCCESS The conversion was successful.
290 **/
291 EFI_STATUS
292 EFIAPI
293 ConvertStringToGuid (
294 IN CONST CHAR16 *StringGuid,
295 IN OUT EFI_GUID *Guid
296 )
297 {
298 CHAR16 *TempCopy;
299 CHAR16 *TempSpot;
300 CHAR16 *Walker;
301 UINT64 TempVal;
302 EFI_STATUS Status;
303
304 if (StringGuid == NULL) {
305 return (EFI_INVALID_PARAMETER);
306 } else if (StrLen(StringGuid) != 36) {
307 return (EFI_INVALID_PARAMETER);
308 }
309 TempCopy = NULL;
310 TempCopy = StrnCatGrow(&TempCopy, NULL, StringGuid, 0);
311 Walker = TempCopy;
312 TempSpot = StrStr(Walker, L"-");
313 if (TempSpot != NULL) {
314 *TempSpot = CHAR_NULL;
315 }
316 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
317 if (EFI_ERROR(Status)) {
318 FreePool(TempCopy);
319 return (Status);
320 }
321 Guid->Data1 = (UINT32)TempVal;
322 Walker += 9;
323 TempSpot = StrStr(Walker, L"-");
324 if (TempSpot != NULL) {
325 *TempSpot = CHAR_NULL;
326 }
327 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
328 if (EFI_ERROR(Status)) {
329 FreePool(TempCopy);
330 return (Status);
331 }
332 Guid->Data2 = (UINT16)TempVal;
333 Walker += 5;
334 TempSpot = StrStr(Walker, L"-");
335 if (TempSpot != NULL) {
336 *TempSpot = CHAR_NULL;
337 }
338 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
339 if (EFI_ERROR(Status)) {
340 FreePool(TempCopy);
341 return (Status);
342 }
343 Guid->Data3 = (UINT16)TempVal;
344 Walker += 5;
345 Guid->Data4[0] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
346 Guid->Data4[0] = (UINT8)(Guid->Data4[0]+ (UINT8)HexCharToUintn(Walker[1]));
347 Walker += 2;
348 Guid->Data4[1] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
349 Guid->Data4[1] = (UINT8)(Guid->Data4[1] + (UINT8)HexCharToUintn(Walker[1]));
350 Walker += 3;
351 Guid->Data4[2] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
352 Guid->Data4[2] = (UINT8)(Guid->Data4[2] + (UINT8)HexCharToUintn(Walker[1]));
353 Walker += 2;
354 Guid->Data4[3] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
355 Guid->Data4[3] = (UINT8)(Guid->Data4[3] + (UINT8)HexCharToUintn(Walker[1]));
356 Walker += 2;
357 Guid->Data4[4] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
358 Guid->Data4[4] = (UINT8)(Guid->Data4[4] + (UINT8)HexCharToUintn(Walker[1]));
359 Walker += 2;
360 Guid->Data4[5] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
361 Guid->Data4[5] = (UINT8)(Guid->Data4[5] + (UINT8)HexCharToUintn(Walker[1]));
362 Walker += 2;
363 Guid->Data4[6] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
364 Guid->Data4[6] = (UINT8)(Guid->Data4[6] + (UINT8)HexCharToUintn(Walker[1]));
365 Walker += 2;
366 Guid->Data4[7] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
367 Guid->Data4[7] = (UINT8)(Guid->Data4[7] + (UINT8)HexCharToUintn(Walker[1]));
368 FreePool(TempCopy);
369 return (EFI_SUCCESS);
370 }
371
372 CHAR16 TempBufferCatSPrint[1000];
373 /**
374 Appends a formatted Unicode string to a Null-terminated Unicode string
375
376 This function appends a formatted Unicode string to the Null-terminated
377 Unicode string specified by String. String is optional and may be NULL.
378 Storage for the formatted Unicode string returned is allocated using
379 AllocateZeroPool(). The pointer to the appended string is returned. The caller
380 is responsible for freeing the returned string.
381
382 If String is not NULL and not aligned on a 16-bit boundary, then ASSERT().
383 If Format is NULL, then ASSERT().
384 If Format is not aligned on a 16-bit boundary, then ASSERT().
385
386 @param String A null-terminated Unicode string.
387 @param FormatString A null-terminated Unicode format string.
388 @param ... The variable argument list whose contents are accessed based
389 on the format string specified by Format.
390
391 @retval NULL There was not enough available memory.
392 @return Null terminated Unicode string is that is the formatted
393 string appended to String.
394 @sa CatVSPrint
395 **/
396 CHAR16*
397 EFIAPI
398 CatSPrint (
399 IN CONST CHAR16 *String OPTIONAL,
400 IN CONST CHAR16 *FormatString,
401 ...
402 )
403 {
404 VA_LIST Marker;
405 UINTN StringLength;
406 if (String != NULL) {
407 StrCpy(TempBufferCatSPrint, String);
408 } else {
409 *TempBufferCatSPrint = CHAR_NULL;
410 }
411 VA_START (Marker, FormatString);
412 StringLength = StrLen(TempBufferCatSPrint);
413
414 UnicodeVSPrint(TempBufferCatSPrint+StrLen(TempBufferCatSPrint), 1000-StringLength, FormatString, Marker);
415 return (AllocateCopyPool(StrSize(TempBufferCatSPrint), TempBufferCatSPrint));
416 }
417
418 /**
419 Clear the line at the specified Row.
420
421 @param[in] Row The row number to be cleared ( start from 1 )
422 @param[in] LastCol The last printable column.
423 @param[in] LastRow The last printable row.
424 **/
425 VOID
426 EFIAPI
427 EditorClearLine (
428 IN UINTN Row,
429 IN UINTN LastCol,
430 IN UINTN LastRow
431 )
432 {
433 CHAR16 Line[200];
434
435 if (Row == 0) {
436 Row = 1;
437 }
438
439 //
440 // prepare a blank line
441 //
442 SetMem16(Line, LastCol*sizeof(CHAR16), L' ');
443
444 if (Row == LastRow) {
445 //
446 // if CHAR_NULL is still at position 80, it will cause first line error
447 //
448 Line[LastCol - 1] = CHAR_NULL;
449 } else {
450 Line[LastCol] = CHAR_NULL;
451 }
452
453 //
454 // print out the blank line
455 //
456 ShellPrintEx (0, ((INT32)Row) - 1, Line);
457 }
458
459 /**
460 Determine if the character is valid for a filename.
461
462 @param[in] Ch The character to test.
463
464 @retval TRUE The character is valid.
465 @retval FALSE The character is not valid.
466 **/
467 BOOLEAN
468 EFIAPI
469 IsValidFileNameChar (
470 IN CONST CHAR16 Ch
471 )
472 {
473 //
474 // See if there are any illegal characters within the name
475 //
476 if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|' || Ch == L' ') {
477 return FALSE;
478 }
479
480 return TRUE;
481 }
482
483 /**
484 Check if file name has illegal characters.
485
486 @param Name The filename to check.
487
488 @retval TRUE The filename is ok.
489 @retval FALSE The filename is not ok.
490 **/
491 BOOLEAN
492 EFIAPI
493 IsValidFileName (
494 IN CONST CHAR16 *Name
495 )
496 {
497
498 UINTN Index;
499 UINTN Len;
500
501 //
502 // check the length of Name
503 //
504 for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) {
505 if (Name[Index] == '\\' || Name[Index] == ':') {
506 break;
507 }
508 }
509
510 if (Len == 0 || Len > 255) {
511 return FALSE;
512 }
513 //
514 // check whether any char in Name not appears in valid file name char
515 //
516 for (Index = 0; Index < StrLen (Name); Index++) {
517 if (!IsValidFileNameChar (Name[Index])) {
518 return FALSE;
519 }
520 }
521
522 return TRUE;
523 }
524
525 /**
526 Find a filename that is valid (not taken) with the given extension.
527
528 @param[in] Extension The file extension.
529
530 @retval NULL Something went wrong.
531 @return the valid filename.
532 **/
533 CHAR16 *
534 EFIAPI
535 EditGetDefaultFileName (
536 IN CONST CHAR16 *Extension
537 )
538 {
539 EFI_STATUS Status;
540 UINTN Suffix;
541 BOOLEAN FoundNewFile;
542 CHAR16 *FileNameTmp;
543
544 Suffix = 0;
545 FoundNewFile = FALSE;
546
547 do {
548 FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension);
549
550 //
551 // after that filename changed to path
552 //
553 Status = ShellFileExists (FileNameTmp);
554
555 if (Status == EFI_NOT_FOUND) {
556 return FileNameTmp;
557 }
558
559 FreePool (FileNameTmp);
560 FileNameTmp = NULL;
561 Suffix++;
562 } while (Suffix != 0);
563
564 FreePool (FileNameTmp);
565 return NULL;
566 }
567
568 /**
569 Read a file into an allocated buffer. The buffer is the responsibility
570 of the caller to free.
571
572 @param[in] FileName The filename of the file to open.
573 @param[out] Buffer Upon successful return, the pointer to the
574 address of the allocated buffer.
575 @param[out] BufferSize If not NULL, then the pointer to the size
576 of the allocated buffer.
577 @param[out] ReadOnly Upon successful return TRUE if the file is
578 read only. FALSE otherwise.
579
580 @retval EFI_NOT_FOUND The filename did not represent a file in the
581 file system.
582 @retval EFI_SUCCESS The file was read into the buffer.
583 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
584 @retval EFI_LOAD_ERROR The file read operation failed.
585 @retval EFI_INVALID_PARAMETER A parameter was invalid.
586 @retval EFI_INVALID_PARAMETER FileName was NULL.
587 @retval EFI_INVALID_PARAMETER FileName was a directory.
588 **/
589 EFI_STATUS
590 EFIAPI
591 ReadFileIntoBuffer (
592 IN CONST CHAR16 *FileName,
593 OUT VOID **Buffer,
594 OUT UINTN *BufferSize OPTIONAL,
595 OUT BOOLEAN *ReadOnly
596 )
597 {
598 VOID *InternalBuffer;
599 UINTN FileSize;
600 SHELL_FILE_HANDLE FileHandle;
601 BOOLEAN CreateFile;
602 EFI_STATUS Status;
603 EFI_FILE_INFO *Info;
604
605 InternalBuffer = NULL;
606 FileSize = 0;
607 FileHandle = NULL;
608 CreateFile = FALSE;
609 Status = EFI_SUCCESS;
610 Info = NULL;
611
612 if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) {
613 return (EFI_INVALID_PARAMETER);
614 }
615
616 //
617 // try to open the file
618 //
619 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
620
621 if (!EFI_ERROR(Status)) {
622 ASSERT(CreateFile == FALSE);
623 if (FileHandle == NULL) {
624 return EFI_LOAD_ERROR;
625 }
626
627 Info = ShellGetFileInfo(FileHandle);
628
629 if (Info->Attribute & EFI_FILE_DIRECTORY) {
630 FreePool (Info);
631 return EFI_INVALID_PARAMETER;
632 }
633
634 if (Info->Attribute & EFI_FILE_READ_ONLY) {
635 *ReadOnly = TRUE;
636 } else {
637 *ReadOnly = FALSE;
638 }
639 //
640 // get file size
641 //
642 FileSize = (UINTN) Info->FileSize;
643
644 FreePool (Info);
645 } else if (Status == EFI_NOT_FOUND) {
646 //
647 // file not exists. add create and try again
648 //
649 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
650 if (EFI_ERROR (Status)) {
651 return Status;
652 } else {
653 //
654 // it worked. now delete it and move on with the name (now validated)
655 //
656 Status = ShellDeleteFile (&FileHandle);
657 if (Status == EFI_WARN_DELETE_FAILURE) {
658 Status = EFI_ACCESS_DENIED;
659 }
660 if (EFI_ERROR (Status)) {
661 return Status;
662 }
663 }
664 //
665 // file doesn't exist, so set CreateFile to TRUE and can't be read-only
666 //
667 CreateFile = TRUE;
668 *ReadOnly = FALSE;
669 }
670
671 //
672 // the file exists
673 //
674 if (!CreateFile) {
675 //
676 // allocate buffer to read file
677 //
678 InternalBuffer = AllocateZeroPool (FileSize);
679 if (InternalBuffer == NULL) {
680 return EFI_OUT_OF_RESOURCES;
681 }
682 //
683 // read file into InternalBuffer
684 //
685 Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer);
686 ShellCloseFile(&FileHandle);
687 FileHandle = NULL;
688 if (EFI_ERROR (Status)) {
689 SHELL_FREE_NON_NULL (InternalBuffer);
690 return EFI_LOAD_ERROR;
691 }
692 }
693 *Buffer = InternalBuffer;
694 if (BufferSize != NULL) {
695 *BufferSize = FileSize;
696 }
697 return (EFI_SUCCESS);
698
699 }