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