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