]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Ebl/Command.c
Remove dead command and clean up some coding style stuff.
[mirror_edk2.git] / EmbeddedPkg / Ebl / Command.c
CommitLineData
2ef2b01e
A
1/** @file\r
2 Basic commands and command processing infrastructure for EBL\r
3\r
4 Copyright (c) 2007, Intel Corporation<BR>\r
5 Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.\r
6\r
7 All rights reserved. This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "Ebl.h"\r
18#include <Protocol/DiskIo.h>\r
19#include <Protocol/BlockIo.h>\r
20\r
21UINTN mCmdTableMaxIndex = EBL_MAX_COMMAND_COUNT;\r
22UINTN mCmdTableNextFreeIndex = 0;\r
23EBL_COMMAND_TABLE *mCmdTable[EBL_MAX_COMMAND_COUNT];\r
24\r
25/**\r
26 Converts a lowercase Ascii character to upper one\r
27\r
28 If Chr is lowercase Ascii character, then converts it to upper one.\r
29\r
30 If Value >= 0xA0, then ASSERT().\r
31 If (Value & 0x0F) >= 0x0A, then ASSERT().\r
32\r
33 @param chr one Ascii character\r
34\r
35 @return The uppercase value of Ascii character \r
36\r
37**/\r
38STATIC\r
39CHAR8\r
40AsciiToUpper (\r
41 IN CHAR8 Chr\r
42 )\r
43{\r
44 return (UINT8) ((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr);\r
45}\r
46\r
47\r
48/**\r
49 Case insensitve comparison of two Null-terminated Unicode strings with maximum\r
50 lengths, and returns the difference between the first mismatched Unicode\r
51 characters.\r
52 This function compares the Null-terminated Unicode string FirstString to the\r
53 Null-terminated Unicode string SecondString. At most, Length Unicode\r
54 characters will be compared. If Length is 0, then 0 is returned. If\r
55 FirstString is identical to SecondString, then 0 is returned. Otherwise, the\r
56 value returned is the first mismatched Unicode character in SecondString\r
57 subtracted from the first mismatched Unicode character in FirstString.\r
58 \r
59 @param FirstString Pointer to a Null-terminated ASCII string. \r
60 @param SecondString Pointer to a Null-terminated ASCII string.\r
61 @param Length Max length to compare.\r
62 \r
63 @retval 0 FirstString is identical to SecondString using case insensitive\r
64 comparisons.\r
65 @retval !=0 FirstString is not identical to SecondString using case\r
66 insensitive comparisons.\r
67\r
68**/\r
69INTN\r
70EFIAPI\r
71AsciiStrniCmp (\r
72 IN CONST CHAR8 *FirstString,\r
73 IN CONST CHAR8 *SecondString,\r
74 IN UINTN Length\r
75 )\r
76{\r
77 if (Length == 0) {\r
78 return 0;\r
79 }\r
80\r
81 while ((AsciiToUpper (*FirstString) != '\0') &&\r
82 (AsciiToUpper (*FirstString) == AsciiToUpper (*SecondString)) &&\r
83 (Length > 1)) {\r
84 FirstString++;\r
85 SecondString++;\r
86 Length--;\r
87 }\r
88 \r
89 return AsciiToUpper (*FirstString) - AsciiToUpper (*SecondString);\r
90}\r
91\r
92\r
93\r
94/**\r
95 Add a command to the mCmdTable. If there is no free space in the command \r
96 table ASSERT. The mCmdTable is maintained in alphabetical order and the \r
97 new entry is inserted into its sorted possition.\r
98\r
99 @param Entry Commnad Entry to add to the CmdTable\r
100\r
101**/\r
102VOID\r
103EFIAPI\r
104EblAddCommand (\r
105 IN const EBL_COMMAND_TABLE *Entry\r
106 )\r
107{\r
108 UINTN Count;\r
109\r
110 if (mCmdTableNextFreeIndex == EBL_MAX_COMMAND_COUNT) {\r
111 //\r
112 // Ran out of space to store commands. Increase EBL_MAX_COMMAND_COUNT\r
113 //\r
114 ASSERT (FALSE);\r
115 return;\r
116 }\r
117\r
118 //\r
119 // Add command and Insertion sort array in the process\r
120 //\r
121 mCmdTable[mCmdTableNextFreeIndex] = (EBL_COMMAND_TABLE *)Entry;\r
122 if (mCmdTableNextFreeIndex != 0) {\r
123 for (Count = mCmdTableNextFreeIndex; Count > 0; Count--) {\r
124 if (AsciiStriCmp (mCmdTable[Count - 1]->Name, Entry->Name) <= 0) {\r
125 break;\r
126 }\r
127 \r
128 mCmdTable[Count] = mCmdTable[Count - 1];\r
129 }\r
130 mCmdTable[Count] = (EBL_COMMAND_TABLE *)Entry;\r
131 }\r
132\r
133 mCmdTableNextFreeIndex++;\r
134}\r
135\r
136\r
137/**\r
138 Add an set of commands to the command table. Most commonly used on static \r
139 array of commands.\r
140\r
141 @param EntryArray Pointer to array of command entries\r
142 @param ArrayCount Number of commnad entries to add\r
143\r
144**/\r
145VOID\r
146EFIAPI\r
147EblAddCommands (\r
148 IN const EBL_COMMAND_TABLE *EntryArray,\r
149 IN UINTN ArrayCount\r
150 )\r
151{\r
152 UINTN Index;\r
153\r
154 for (Index = 0; Index < ArrayCount; Index++) {\r
155 EblAddCommand (&EntryArray[Index]);\r
156 }\r
157}\r
158\r
159\r
160EBL_ADD_COMMAND_PROTOCOL gEblAddCommand = {\r
161 EblAddCommand,\r
162 EblAddCommands,\r
163 EblGetCharKey,\r
164 EblAnyKeyToContinueQtoQuit\r
165};\r
166\r
167\r
168\r
169/**\r
170 Return the best matching command for the passed in command name. The match \r
171 does not have to be exact, it just needs to be unqiue. This enables commands\r
172 to be shortend to the smallest set of starting characters that is unique.\r
173\r
174 @param CommandName Name of command to search for\r
175\r
176 @return NULL CommandName did not match or was not unique\r
177 Other Pointer to EBL_COMMAND_TABLE entry for CommandName\r
178\r
179**/\r
180EBL_COMMAND_TABLE *\r
181EblGetCommand (\r
182 IN CHAR8 *CommandName\r
183 )\r
184{\r
185 UINTN Index;\r
186 UINTN BestMatchCount;\r
187 UINTN Length;\r
188 EBL_COMMAND_TABLE *Match;\r
189\r
190 Length = AsciiStrLen (CommandName);\r
191 for (Index = 0, BestMatchCount = 0, Match = NULL; Index < mCmdTableNextFreeIndex; Index++) {\r
192 if (AsciiStriCmp (mCmdTable[Index]->Name, CommandName) == 0) {\r
193 // match a command exactly\r
194 return mCmdTable[Index];\r
195 }\r
196\r
197 if (AsciiStrniCmp (CommandName, mCmdTable[Index]->Name, Length) == 0) {\r
198 // partial match, so keep looking to make sure there is only one partial match\r
199 BestMatchCount++;\r
200 Match = mCmdTable[Index];\r
201 }\r
202 }\r
203\r
204 if (BestMatchCount == 1) {\r
205 return Match;\r
206 }\r
207\r
208 //\r
209 // We had no matches or too many matches\r
210 //\r
211 return NULL;\r
212}\r
213\r
214\r
215\r
216/**\r
217 List out help information on all the commands or print extended information \r
218 about a specific passed in command.\r
219\r
220 Argv[0] - "help"\r
221 Argv[1] - Command to display help about\r
222\r
223 @param Argc Number of command arguments in Argv\r
224 @param Argv Array of strings that represent the parsed command line. \r
225 Argv[0] is the comamnd name\r
226\r
227 @return EFI_SUCCESS\r
228\r
229**/\r
230EFI_STATUS\r
231EblHelpCmd (\r
232 IN UINTN Argc,\r
233 IN CHAR8 **Argv\r
234 )\r
235{\r
236 UINTN Index;\r
237 CHAR8 *Ptr;\r
238 UINTN CurrentRow;\r
239\r
240 if (Argc == 1) {\r
241 // Print all the commands\r
242 AsciiPrint ("Embedded Boot Loader (EBL) commands (help command for more info):\n");\r
243 for (Index = 0; Index < mCmdTableNextFreeIndex; Index++) {\r
244 EblSetTextColor (EFI_YELLOW);\r
245 AsciiPrint (" %a", mCmdTable[Index]->Name);\r
246 EblSetTextColor (0);\r
247 AsciiPrint ("%a\n", mCmdTable[Index]->HelpSummary);\r
248 }\r
249 } else if (Argv[1] != NULL) {\r
250 // Print specific help \r
251 for (Index = 0, CurrentRow = 0; Index < mCmdTableNextFreeIndex; Index++) {\r
252 if (AsciiStriCmp (Argv[1], mCmdTable[Index]->Name) == 0) {\r
253 Ptr = (mCmdTable[Index]->Help == NULL) ? mCmdTable[Index]->HelpSummary : mCmdTable[Index]->Help;\r
254 AsciiPrint ("%a%a\n", Argv[1], Ptr);\r
255 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
256 break;\r
257 }\r
258 }\r
259 }\r
260 }\r
261\r
262 return EFI_SUCCESS;\r
263}\r
264\r
265\r
266/**\r
267 Exit the EBL. If the commnad processor sees EFI_ABORTED return status it will\r
268 exit the EBL.\r
269\r
270 Argv[0] - "exit"\r
271\r
272 @param Argc Number of command arguments in Argv\r
273 @param Argv Array of strings that represent the parsed command line. \r
274 Argv[0] is the comamnd name\r
275\r
276 @return EFI_ABORTED\r
277\r
278**/\r
279EFI_STATUS\r
280EblExitCmd (\r
281 IN UINTN Argc,\r
282 IN CHAR8 **Argv\r
283 )\r
284{\r
85e385f4 285 EFI_STATUS Status;\r
286 UINTN MemoryMapSize;\r
287 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
288 UINTN MapKey;\r
289 UINTN DescriptorSize;\r
290 UINT32 DescriptorVersion;\r
291 UINTN Pages;\r
2ef2b01e
A
292\r
293 if (Argc > 1) { \r
294 if (AsciiStriCmp (Argv[1], "efi") != 0) {\r
295 return EFI_ABORTED;\r
296 }\r
297 } else if (Argc == 1) {\r
298 return EFI_ABORTED;\r
299 }\r
300 \r
85e385f4 301 MemoryMap = NULL;\r
302 MemoryMapSize = 0;\r
303 do {\r
304 Status = gBS->GetMemoryMap (\r
305 &MemoryMapSize,\r
306 MemoryMap,\r
307 &MapKey,\r
308 &DescriptorSize,\r
309 &DescriptorVersion\r
310 );\r
311 if (Status == EFI_BUFFER_TOO_SMALL) {\r
312\r
313 Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;\r
314 MemoryMap = AllocatePages (Pages);\r
315 \r
316 //\r
317 // Get System MemoryMap\r
318 //\r
319 Status = gBS->GetMemoryMap (\r
320 &MemoryMapSize,\r
321 MemoryMap,\r
322 &MapKey,\r
323 &DescriptorSize,\r
324 &DescriptorVersion\r
325 );\r
326 // Don't do anything between the GetMemoryMap() and ExitBootServices()\r
327 if (!EFI_ERROR (Status)) {\r
328 Status = gBS->ExitBootServices (gImageHandle, MapKey);\r
329 if (EFI_ERROR (Status)) {\r
330 FreePages (MemoryMap, Pages);\r
331 MemoryMap = NULL;\r
332 MemoryMapSize = 0;\r
333 }\r
334 }\r
335 }\r
336 } while (EFI_ERROR (Status));\r
2ef2b01e
A
337\r
338 //\r
339 // At this point it is very dangerous to do things EFI as most of EFI is now gone.\r
340 // This command is useful if you are working with a debugger as it will shutdown\r
341 // DMA and other things that could break a soft resets.\r
342 // \r
343 CpuDeadLoop ();\r
344 \r
345 // Should never get here, but makes the compiler happy\r
346 return EFI_ABORTED;\r
347}\r
348\r
349\r
350/**\r
351 Update the screen by decrementing the timeout value.\r
352 This AsciiPrint has to match the AsciiPrint in \r
353 EblPauseCmd. \r
354\r
355 @param ElaspedTime Current timout value remaining\r
356\r
357**/\r
358VOID\r
359EFIAPI\r
360EblPauseCallback (\r
361 IN UINTN ElapsedTime\r
362 )\r
363{\r
364 AsciiPrint ("\b\b\b\b\b\b\b\b\b\b\b\b \b\b%3d seconds", ElapsedTime);\r
365}\r
366\r
367/**\r
368 Pause until a key is pressed and abort the remaining commands on the command\r
369 line. If no key is pressed continue processing the command line. This command\r
370 allows the user to stop an operation from happening and return control to the\r
371 command prompt.\r
372\r
373 Argv[0] - "pause"\r
374 Argv[1] - timeout value is decimal seconds\r
375\r
376 @param Argc Number of command arguments in Argv\r
377 @param Argv Array of strings that represent the parsed command line. \r
378 Argv[0] is the comamnd name\r
379\r
380 @return EFI_SUCCESS Timeout expired with no input\r
381 @return EFI_TIMEOUT Stop procesing other commands on the same command line\r
382\r
383**/\r
384EFI_STATUS\r
385EblPauseCmd (\r
386 IN UINTN Argc,\r
387 IN CHAR8 **Argv\r
388 )\r
389{\r
390 EFI_STATUS Status;\r
391 UINTN Delay;\r
392 EFI_INPUT_KEY Key;\r
393\r
394 Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]);\r
395\r
396 AsciiPrint ("Hit any key to break. You have %3d seconds", Delay);\r
397 Status = EblGetCharKey (&Key, Delay, EblPauseCallback);\r
398 AsciiPrint ("\n");\r
399\r
400 // If we timeout then the pause succeded thus return success\r
401 // If we get a key return timout to stop other commnad on this cmd line\r
402 return (Status == EFI_SUCCESS) ? EFI_TIMEOUT : EFI_SUCCESS;;\r
403}\r
404\r
405\r
406/**\r
407 On a debug build issue a software breakpoint to enter the debugger\r
408\r
409 Argv[0] - "break"\r
410\r
411 @param Argc Number of command arguments in Argv\r
412 @param Argv Array of strings that represent the parsed command line. \r
413 Argv[0] is the comamnd name\r
414\r
415 @return EFI_SUCCESS\r
416\r
417**/\r
418EFI_STATUS\r
419EblBreakPointCmd (\r
420 IN UINTN Argc,\r
421 IN CHAR8 **Argv\r
422 )\r
423{\r
424 CpuBreakpoint ();\r
425 return EFI_SUCCESS;\r
426}\r
427\r
428\r
429/**\r
430 Reset the system. If no Argument do a Cold reset. If argument use that reset type\r
431 (W)arm = Warm Reset\r
432 (S)hutdown = Shutdown Reset\r
433\r
434 Argv[0] - "reset"\r
435 Argv[1] - warm or shutdown reset type\r
436\r
437 @param Argc Number of command arguments in Argv\r
438 @param Argv Array of strings that represent the parsed command line. \r
439 Argv[0] is the comamnd name\r
440\r
441 @return EFI_SUCCESS\r
442\r
443**/\r
444EFI_STATUS\r
445EblResetCmd (\r
446 IN UINTN Argc,\r
447 IN CHAR8 **Argv\r
448 )\r
449{\r
450 EFI_RESET_TYPE ResetType;\r
451\r
452 ResetType = EfiResetCold;\r
453 if (Argc > 1) {\r
454 switch (*Argv[1]) {\r
455 case 'W':\r
456 case 'w':\r
457 ResetType = EfiResetWarm;\r
458 break;\r
459 case 'S':\r
460 case 's':\r
461 ResetType = EfiResetShutdown;\r
462 }\r
463 } \r
464\r
465 gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);\r
466 return EFI_SUCCESS;\r
467}\r
468\r
469\r
470/**\r
471 Toggle page break global. This turns on and off prompting to Quit or hit any\r
472 key to continue when a command is about to scroll the screen with its output\r
473\r
474 Argv[0] - "page"\r
475 Argv[1] - on or off\r
476\r
477 @param Argc Number of command arguments in Argv\r
478 @param Argv Array of strings that represent the parsed command line. \r
479 Argv[0] is the comamnd name\r
480\r
481 @return EFI_SUCCESS\r
482\r
483**/\r
484EFI_STATUS\r
485EblPageCmd (\r
486 IN UINTN Argc,\r
487 IN CHAR8 **Argv\r
488 )\r
489{\r
490 if (Argc <= 1) {\r
491 // toggle setting \r
492 gPageBreak = (gPageBreak) ? FALSE : TRUE;\r
493 } else {\r
494 // use argv to set the value\r
495 if ((Argv[1][0] == 'o') || (Argv[1][0] == 'O')) {\r
496 if ((Argv[1][1] == 'n') || (Argv[1][1] == 'N')) {\r
497 gPageBreak = TRUE;\r
498 } else if ((Argv[1][1] == 'f') || (Argv[1][1] == 'F')) {\r
499 gPageBreak = FALSE;\r
500 } else {\r
501 return EFI_INVALID_PARAMETER;\r
502 }\r
503 }\r
504 }\r
505 return EFI_SUCCESS;\r
506}\r
507\r
508EFI_STATUS\r
509EblSleepCmd (\r
510 IN UINTN Argc,\r
511 IN CHAR8 **Argv\r
512 )\r
513{\r
514 UINTN Delay;\r
515\r
516 Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]);\r
517\r
518 gBS->Stall (Delay * 1000000);\r
519\r
520 return EFI_SUCCESS;\r
521}\r
522\r
523CHAR8\r
524ConvertToTextLine (\r
525 IN CHAR8 Character\r
526 )\r
527{\r
0534bb8f 528 if (Character < ' ' || Character > '~') {\r
2ef2b01e 529 return '.';\r
0534bb8f 530 } else {\r
2ef2b01e
A
531 return Character;\r
532 }\r
533}\r
534\r
535UINTN\r
536GetBytes (\r
537 IN UINT8 *Address,\r
538 IN UINTN Bytes\r
539 )\r
540{\r
541 UINTN Result = 0;\r
542\r
0534bb8f 543 if (Bytes >= 1) {\r
2ef2b01e 544 Result = *Address++;\r
0534bb8f 545 }\r
546 if (Bytes >= 2) {\r
2ef2b01e 547 Result = (Result << 8) + *Address++;\r
0534bb8f 548 } \r
549 if (Bytes >= 3) {\r
2ef2b01e 550 Result = (Result << 8) + *Address++;\r
0534bb8f 551 }\r
2ef2b01e
A
552 return Result;\r
553}\r
554\r
555CHAR8 mBlanks[] = " ";\r
556\r
557EFI_STATUS\r
558OutputData (\r
559 IN UINT8 *Address,\r
560 IN UINTN Length,\r
561 IN UINTN Width,\r
562 IN UINTN Offset\r
563 )\r
564{\r
565 UINT8 *EndAddress;\r
566 UINTN Line;\r
567 CHAR8 TextLine[0x11];\r
568 UINTN CurrentRow = 0;\r
569 UINTN Bytes;\r
570 UINTN Spaces = 0;\r
571 CHAR8 Blanks[80];\r
572\r
573 AsciiStrCpy (Blanks, mBlanks);\r
0534bb8f 574 for (EndAddress = Address + Length; Address < EndAddress; Offset += Line) {\r
2ef2b01e 575 AsciiPrint ("%08x: ", Offset);\r
0534bb8f 576 for (Line = 0; (Line < 0x10) && (Address < EndAddress);) {\r
2ef2b01e
A
577 Bytes = EndAddress - Address;\r
578 \r
0534bb8f 579 switch (Width) {\r
2ef2b01e 580 case 4:\r
0534bb8f 581 if (Bytes >= 4) {\r
2ef2b01e
A
582 AsciiPrint ("%08x ", *((UINT32 *)Address));\r
583 TextLine[Line++] = ConvertToTextLine(*Address++);\r
584 TextLine[Line++] = ConvertToTextLine(*Address++);\r
585 TextLine[Line++] = ConvertToTextLine(*Address++);\r
586 TextLine[Line++] = ConvertToTextLine(*Address++);\r
0534bb8f 587 } else {\r
2ef2b01e
A
588 AsciiPrint ("%08x ", GetBytes(Address, Bytes));\r
589 Address += Bytes;\r
590 Line += Bytes;\r
591 }\r
592 break;\r
593\r
594 case 2:\r
0534bb8f 595 if (Bytes >= 2) {\r
2ef2b01e
A
596 AsciiPrint ("%04x ", *((UINT16 *)Address));\r
597 TextLine[Line++] = ConvertToTextLine(*Address++);\r
598 TextLine[Line++] = ConvertToTextLine(*Address++);\r
0534bb8f 599 } else {\r
2ef2b01e
A
600 AsciiPrint ("%04x ", GetBytes(Address, Bytes));\r
601 Address += Bytes;\r
602 Line += Bytes;\r
603 }\r
604 break;\r
605\r
606 case 1:\r
607 AsciiPrint ("%02x ", *((UINT8 *)Address));\r
608 TextLine[Line++] = ConvertToTextLine(*Address++);\r
609 break;\r
610\r
611 default:\r
612 AsciiPrint ("Width must be 1, 2, or 4!\n");\r
613 return EFI_INVALID_PARAMETER;\r
614 }\r
615 }\r
616\r
617 // Pad spaces\r
0534bb8f 618 if (Line < 0x10) {\r
619 switch (Width) {\r
2ef2b01e
A
620 case 4:\r
621 Spaces = 9 * ((0x10 - Line)/4);\r
622 break;\r
623 case 2:\r
624 Spaces = 5 * ((0x10 - Line)/2);\r
625 break;\r
626 case 1:\r
627 Spaces = 3 * (0x10 - Line);\r
628 break;\r
629 }\r
630\r
631 Blanks[Spaces] = '\0';\r
632\r
633 AsciiPrint(Blanks);\r
634 \r
635 Blanks[Spaces] = ' ';\r
636 }\r
637\r
638 TextLine[Line] = 0;\r
639 AsciiPrint ("|%a|\n", TextLine);\r
640\r
0534bb8f 641 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
2ef2b01e
A
642 return EFI_END_OF_FILE;\r
643 }\r
644 }\r
645\r
0534bb8f 646 if (Length % Width != 0) {\r
2ef2b01e
A
647 AsciiPrint ("%08x\n", Offset);\r
648 }\r
649 \r
650 return EFI_SUCCESS;\r
651}\r
652\r
653#define HEXDUMP_CHUNK 1024\r
654\r
655EFI_STATUS\r
656EblHexdumpCmd (\r
657 IN UINTN Argc,\r
658 IN CHAR8 **Argv\r
659 )\r
660{\r
661 EFI_OPEN_FILE *File;\r
662 VOID *Location;\r
663 UINTN Size;\r
664 UINTN Width = 1;\r
665 UINTN Offset = 0;\r
666 EFI_STATUS Status;\r
667 UINTN Chunk = HEXDUMP_CHUNK;\r
668\r
0534bb8f 669 if ((Argc < 2) || (Argc > 3)) {\r
2ef2b01e
A
670 return EFI_INVALID_PARAMETER;\r
671 }\r
672 \r
0534bb8f 673 if (Argc == 3) {\r
2ef2b01e
A
674 Width = AsciiStrDecimalToUintn(Argv[2]);\r
675 }\r
676 \r
0534bb8f 677 if ((Width != 1) && (Width != 2) && (Width != 4)) {\r
2ef2b01e
A
678 return EFI_INVALID_PARAMETER;\r
679 }\r
680\r
0534bb8f 681 File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);\r
682 if (File == NULL) {\r
2ef2b01e
A
683 return EFI_NOT_FOUND;\r
684 }\r
685\r
0534bb8f 686 Location = AllocatePool (Chunk);\r
2ef2b01e
A
687 Size = EfiTell(File, NULL);\r
688\r
0534bb8f 689 for (Offset = 0; Offset + HEXDUMP_CHUNK <= Size; Offset += Chunk) {\r
2ef2b01e
A
690 Chunk = HEXDUMP_CHUNK;\r
691 \r
0534bb8f 692 Status = EfiRead (File, Location, &Chunk);\r
2ef2b01e
A
693 if (EFI_ERROR(Status))\r
694 {\r
695 AsciiPrint ("Error reading file content\n");\r
696 goto Exit;\r
697 }\r
698\r
0534bb8f 699 Status = OutputData (Location, Chunk, Width, File->BaseOffset + Offset);\r
700 if (EFI_ERROR(Status)) {\r
2ef2b01e
A
701 if (Status == EFI_END_OF_FILE) {\r
702 Status = EFI_SUCCESS;\r
703 }\r
704 goto Exit;\r
705 }\r
706 }\r
707 \r
708 // Any left over?\r
0534bb8f 709 if (Offset < Size) {\r
2ef2b01e 710 Chunk = Size - Offset;\r
0534bb8f 711 Status = EfiRead (File, Location, &Chunk);\r
712 if (EFI_ERROR(Status)) {\r
2ef2b01e
A
713 AsciiPrint ("Error reading file content\n");\r
714 goto Exit;\r
715 }\r
716\r
0534bb8f 717 Status = OutputData (Location, Chunk, Width, File->BaseOffset + Offset);\r
718 if (EFI_ERROR(Status)) {\r
2ef2b01e
A
719 if (Status == EFI_END_OF_FILE) {\r
720 Status = EFI_SUCCESS;\r
721 }\r
722 goto Exit;\r
723 }\r
724 }\r
725\r
726Exit:\r
0534bb8f 727 EfiClose (File);\r
2ef2b01e 728\r
0534bb8f 729 FreePool (Location);\r
2ef2b01e
A
730\r
731 return EFI_SUCCESS;\r
732}\r
733\r
2ef2b01e
A
734\r
735GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdTemplate[] =\r
736{\r
737 {\r
738 "reset",\r
739 " [type]; Reset system. type = [warm] [shutdown] default is cold reset",\r
740 NULL,\r
741 EblResetCmd\r
742 },\r
743 {\r
744 "exit",\r
745 "; Exit EBL",\r
746 NULL,\r
747 EblExitCmd\r
748 },\r
749 {\r
750 "help",\r
751 " [cmd]; Help on cmd or a list of all commands if cmd is ommited",\r
752 NULL,\r
753 EblHelpCmd\r
754 },\r
755 {\r
756 "break",\r
757 "; Generate debugging breakpoint",\r
758 NULL,\r
759 EblBreakPointCmd\r
760 },\r
761 {\r
762 "page",\r
763 " [on|off]]; toggle promting on command output larger than screen",\r
764 NULL,\r
765 EblPageCmd\r
766 },\r
767 {\r
768 "pause",\r
769 " [sec]; Pause for sec[10] seconds. ",\r
770 NULL,\r
771 EblPauseCmd\r
772 },\r
773 {\r
774 "sleep",\r
775 " [sec]; Sleep for sec[10] seconds. ",\r
776 NULL,\r
777 EblSleepCmd\r
778 },\r
779 {\r
780 "hexdump",\r
781 " filename ; dump a file as hex bytes",\r
782 NULL,\r
783 EblHexdumpCmd\r
0534bb8f 784 }\r
2ef2b01e
A
785};\r
786\r
787\r
788EFI_HANDLE gExternalCmdHandle = NULL;\r
789\r
790/**\r
791 Initialize the commands in this in this file\r
792**/\r
793VOID\r
794EblInitializeCmdTable (\r
795 VOID\r
796 )\r
797{\r
798\r
799 EblAddCommands (mCmdTemplate, sizeof (mCmdTemplate)/sizeof (EBL_COMMAND_TABLE));\r
800 \r
801 gBS->InstallProtocolInterface (\r
802 &gExternalCmdHandle,\r
803 &gEfiEblAddCommandProtocolGuid,\r
804 EFI_NATIVE_INTERFACE,\r
805 &gEblAddCommand\r
806 );\r
807\r
808}\r
809\r
810\r
811VOID\r
812EblShutdownExternalCmdTable (\r
813 VOID\r
814 )\r
815{\r
816 gBS->UninstallProtocolInterface (gExternalCmdHandle, &gEfiEblAddCommandProtocolGuid, &gEblAddCommand);\r
817}\r
818\r
819\r