]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Ebl/Main.c
EmbeddedPkg: Fix mispellings
[mirror_edk2.git] / EmbeddedPkg / Ebl / Main.c
CommitLineData
2ef2b01e
A
1/** @file\r
2 Basic command line parser for EBL (Embedded Boot Loader)\r
3\r
60274cca
HT
4 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
2ef2b01e 6\r
60274cca 7 This program and the accompanying materials\r
2ef2b01e
A
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\r
18#include "Ebl.h"\r
19\r
20// Globals for command history processing\r
21INTN mCmdHistoryEnd = -1;\r
22INTN mCmdHistoryStart = -1;\r
23INTN mCmdHistoryCurrent = -1;\r
24CHAR8 mCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LINE];\r
25CHAR8 *mCmdBlank = "";\r
26\r
27// Globals to remember current screen geometry\r
28UINTN gScreenColumns;\r
29UINTN gScreenRows;\r
30\r
31// Global to turn on/off breaking commands with prompts before they scroll the screen\r
32BOOLEAN gPageBreak = TRUE;\r
33\r
34VOID \r
35RingBufferIncrement (\r
36 IN INTN *Value\r
37 )\r
38{\r
39 *Value = *Value + 1;\r
40 \r
41 if (*Value >= MAX_CMD_HISTORY) {\r
42 *Value = 0;\r
43 }\r
44}\r
45\r
46VOID\r
47RingBufferDecrement (\r
48 IN INTN *Value\r
49 )\r
50{\r
51 *Value = *Value - 1;\r
52 \r
53 if (*Value < 0) {\r
54 *Value = MAX_CMD_HISTORY - 1;\r
55 }\r
56}\r
57\r
58/**\r
59 Save this command in the circular history buffer. Older commands are \r
60 overwritten with newer commands.\r
61\r
62 @param Cmd Command line to archive the history of.\r
63\r
64 @return None\r
65\r
66**/\r
67VOID\r
68SetCmdHistory (\r
69 IN CHAR8 *Cmd\r
70 )\r
71{\r
72 // Don't bother adding empty commands to the list\r
73 if (AsciiStrLen(Cmd) != 0) {\r
74 \r
75 // First entry\r
76 if (mCmdHistoryStart == -1) {\r
77 mCmdHistoryStart = 0;\r
78 mCmdHistoryEnd = 0;\r
79 } else {\r
80 // Record the new command at the next index\r
81 RingBufferIncrement(&mCmdHistoryStart);\r
82 \r
83 // If the next index runs into the end index, shuffle end back by one\r
84 if (mCmdHistoryStart == mCmdHistoryEnd) {\r
85 RingBufferIncrement(&mCmdHistoryEnd);\r
86 }\r
87 }\r
88 \r
89 // Copy the new command line into the ring buffer\r
90 AsciiStrnCpy(&mCmdHistory[mCmdHistoryStart][0], Cmd, MAX_CMD_LINE);\r
91 }\r
92 \r
93 // Reset the command history for the next up arrow press\r
94 mCmdHistoryCurrent = mCmdHistoryStart; \r
95}\r
96\r
97\r
98/**\r
99 Retreave data from the Command History buffer. Direction maps into up arrow\r
100 an down arrow on the command line\r
101\r
102 @param Direction Command forward or back\r
103\r
104 @return The Command history based on the Direction\r
105\r
106**/\r
107CHAR8 *\r
108GetCmdHistory (\r
109 IN UINT16 Direction\r
110 )\r
111{\r
112 CHAR8 *HistoricalCommand = NULL;\r
113 \r
114 // No history yet?\r
115 if (mCmdHistoryCurrent == -1) {\r
116 HistoricalCommand = mCmdBlank;\r
117 goto Exit;\r
118 }\r
119 \r
120 if (Direction == SCAN_UP) {\r
121 HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0];\r
122 \r
123 // if we just echoed the last command, hang out there, don't wrap around\r
124 if (mCmdHistoryCurrent == mCmdHistoryEnd) {\r
125 goto Exit;\r
126 }\r
127 \r
128 // otherwise, back up by one\r
129 RingBufferDecrement(&mCmdHistoryCurrent);\r
130 \r
131 } else if (Direction == SCAN_DOWN) {\r
132 \r
133 // if we last echoed the start command, put a blank prompt out\r
134 if (mCmdHistoryCurrent == mCmdHistoryStart) {\r
135 HistoricalCommand = mCmdBlank;\r
136 goto Exit;\r
137 }\r
138 \r
139 // otherwise increment the current pointer and return that command\r
140 RingBufferIncrement(&mCmdHistoryCurrent);\r
141 RingBufferIncrement(&mCmdHistoryCurrent);\r
142 \r
143 HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0];\r
144 RingBufferDecrement(&mCmdHistoryCurrent);\r
145 }\r
146\r
147Exit: \r
148 return HistoricalCommand;\r
149}\r
150\r
151\r
152/**\r
153 Parse the CmdLine and break it up into Argc (arg count) and Argv (array of\r
7ca9e5a4 154 pointers to each argument). The Cmd buffer is altered and separators are\r
2ef2b01e
A
155 converted to string terminators. This allows Argv to point into CmdLine.\r
156 A CmdLine can support multiple commands. The next command in the command line\r
157 is returned if it exists.\r
158\r
159 @param CmdLine String to parse for a set of commands\r
160 @param Argc Returns the number of arguments in the CmdLine current command\r
161 @param Argv Argc pointers to each string in CmdLine\r
162\r
163 @return Next Command in the command line or NULL if non exists\r
164**/\r
165CHAR8 *\r
166ParseArguments (\r
167 IN CHAR8 *CmdLine,\r
168 OUT UINTN *Argc,\r
169 OUT CHAR8 **Argv\r
170 )\r
171{\r
172 UINTN Arg;\r
173 CHAR8 *Char;\r
174 BOOLEAN LookingForArg;\r
175 BOOLEAN InQuote;\r
176\r
177 *Argc = 0;\r
178 if (AsciiStrLen (CmdLine) == 0) {\r
179 return NULL;\r
180 }\r
181\r
7ca9e5a4 182 // Walk a single command line. A CMD_SEPARATOR allows multiple commands on a single line\r
2ef2b01e
A
183 InQuote = FALSE;\r
184 LookingForArg = TRUE;\r
185 for (Char = CmdLine, Arg = 0; *Char != '\0'; Char++) {\r
7ca9e5a4 186 if (!InQuote && *Char == CMD_SEPARATOR) {\r
2ef2b01e
A
187 break;\r
188 }\r
189\r
fb334ef6 190 // Perform any text conversion here\r
2ef2b01e
A
191 if (*Char == '\t') {\r
192 // TAB to space\r
193 *Char = ' ';\r
194 }\r
195\r
196 if (LookingForArg) {\r
7ca9e5a4 197 // Look for the beginning of an Argv[] entry\r
2ef2b01e
A
198 if (*Char == '"') {\r
199 Argv[Arg++] = ++Char;\r
200 LookingForArg = FALSE;\r
201 InQuote = TRUE;\r
202 } else if (*Char != ' ') {\r
203 Argv[Arg++] = Char;\r
204 LookingForArg = FALSE;\r
205 } \r
206 } else {\r
207 // Looking for the terminator of an Argv[] entry\r
fb334ef6 208 if (!InQuote && (*Char == ' ')) {\r
2ef2b01e
A
209 *Char = '\0';\r
210 LookingForArg = TRUE;\r
fb334ef6 211 } else if (!InQuote && (*Char == '"') && (*(Char-1) != '\\')) {\r
212 InQuote = TRUE;\r
213 } else if (InQuote && (*Char == '"') && (*(Char-1) != '\\')) {\r
214 *Char = '\0';\r
215 InQuote = FALSE;\r
2ef2b01e
A
216 }\r
217 } \r
218 }\r
219\r
220 *Argc = Arg;\r
221\r
7ca9e5a4 222 if (*Char == CMD_SEPARATOR) {\r
223 // Replace the command delimiter with null and return pointer to next command line\r
2ef2b01e
A
224 *Char = '\0';\r
225 return ++Char;\r
226 }\r
227\r
228 return NULL;\r
229}\r
230\r
231\r
232/**\r
233 Return a keypress or optionally timeout if a timeout value was passed in.\r
7ca9e5a4 234 An optional callback function is called every second when waiting for a\r
2ef2b01e
A
235 timeout.\r
236\r
237 @param Key EFI Key information returned\r
238 @param TimeoutInSec Number of seconds to wait to timeout\r
239 @param CallBack Callback called every second during the timeout wait \r
240\r
241 @return EFI_SUCCESS Key was returned\r
242 @return EFI_TIMEOUT If the TimoutInSec expired\r
243\r
244**/\r
245EFI_STATUS\r
246EblGetCharKey (\r
247 IN OUT EFI_INPUT_KEY *Key,\r
248 IN UINTN TimeoutInSec,\r
249 IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL\r
250 )\r
251{\r
252 EFI_STATUS Status;\r
253 UINTN WaitCount;\r
254 UINTN WaitIndex;\r
255 EFI_EVENT WaitList[2];\r
256\r
257 WaitCount = 1;\r
258 WaitList[0] = gST->ConIn->WaitForKey;\r
259 if (TimeoutInSec != 0) {\r
260 // Create a time event for 1 sec duration if we have a timeout\r
261 gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &WaitList[1]);\r
262 gBS->SetTimer (WaitList[1], TimerPeriodic, EFI_SET_TIMER_TO_SECOND);\r
263 WaitCount++;\r
264 }\r
265\r
266 for (;;) {\r
267 Status = gBS->WaitForEvent (WaitCount, WaitList, &WaitIndex);\r
268 ASSERT_EFI_ERROR (Status);\r
269\r
270 switch (WaitIndex) {\r
271 case 0:\r
272 // Key event signaled\r
273 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
274 if (!EFI_ERROR (Status)) {\r
275 if (WaitCount == 2) {\r
276 gBS->CloseEvent (WaitList[1]);\r
277 }\r
278 return EFI_SUCCESS; \r
279 }\r
280 break;\r
281\r
282 case 1:\r
283 // Periodic 1 sec timer signaled \r
284 TimeoutInSec--;\r
285 if (CallBack != NULL) {\r
286 // Call the users callback function if registered \r
287 CallBack (TimeoutInSec);\r
288 }\r
289 if (TimeoutInSec == 0) {\r
290 gBS->CloseEvent (WaitList[1]);\r
291 return EFI_TIMEOUT;\r
292 }\r
293 break;\r
294 default:\r
295 ASSERT (FALSE);\r
296 }\r
297 } \r
298}\r
299\r
300\r
301/**\r
302 This routine is used prevent command output data from scrolling off the end\r
303 of the screen. The global gPageBreak is used to turn on or off this feature.\r
304 If the CurrentRow is near the end of the screen pause and print out a prompt\r
305 If the use hits Q to quit return TRUE else for any other key return FALSE.\r
306 PrefixNewline is used to figure out if a newline is needed before the prompt\r
307 string. This depends on the last print done before calling this function.\r
308 CurrentRow is updated by one on a call or set back to zero if a prompt is \r
309 needed.\r
310\r
311 @param CurrentRow Used to figure out if its the end of the page and updated\r
312 @param PrefixNewline Did previous print issue a newline\r
313\r
314 @return TRUE if Q was hit to quit, FALSE in all other cases.\r
315\r
316**/\r
317BOOLEAN\r
318EblAnyKeyToContinueQtoQuit (\r
319 IN UINTN *CurrentRow,\r
320 IN BOOLEAN PrefixNewline\r
321 )\r
322{\r
323 EFI_INPUT_KEY InputKey;\r
324\r
325 if (!gPageBreak) {\r
326 // global disable for this feature\r
327 return FALSE;\r
328 }\r
329\r
330 if (*CurrentRow >= (gScreenRows - 2)) {\r
331 if (PrefixNewline) {\r
332 AsciiPrint ("\n");\r
333 }\r
334 AsciiPrint ("Any key to continue (Q to quit): ");\r
335 EblGetCharKey (&InputKey, 0, NULL);\r
336 AsciiPrint ("\n");\r
337\r
338 // Time to promt to stop the screen. We have to leave space for the prompt string\r
339 *CurrentRow = 0;\r
340 if (InputKey.UnicodeChar == 'Q' || InputKey.UnicodeChar == 'q') {\r
341 return TRUE;\r
342 }\r
343 } else {\r
344 *CurrentRow += 1;\r
345 }\r
346\r
347 return FALSE;\r
348}\r
349\r
350\r
351/**\r
352 Set the text color of the EFI Console. If a zero is passed in reset to \r
353 default text/background color.\r
354\r
355 @param Attribute For text and background color\r
356\r
357**/\r
358VOID\r
359EblSetTextColor (\r
360 UINTN Attribute\r
361 )\r
362{\r
363 if (Attribute == 0) {\r
364 // Set the text color back to default\r
365 Attribute = (UINTN)PcdGet32 (PcdEmbeddedDefaultTextColor);\r
366 }\r
367\r
368 gST->ConOut->SetAttribute (gST->ConOut, Attribute);\r
369}\r
370\r
371\r
372/**\r
7ca9e5a4 373 Collect the keyboard input for a cmd line. Carriage Return, New Line, or ESC\r
2ef2b01e
A
374 terminates the command line. You can edit the command line via left arrow,\r
375 delete and backspace and they all back up and erase the command line. \r
7ca9e5a4 376 No edit of command line is possible without deletion at this time!\r
2ef2b01e
A
377 The up arrow and down arrow fill Cmd with information from the history \r
378 buffer.\r
379\r
380 @param Cmd Command line to return \r
381 @param CmdMaxSize Maximum size of Cmd\r
382\r
383 @return The Status of EblGetCharKey()\r
384\r
385**/\r
386EFI_STATUS\r
387GetCmd (\r
388 IN OUT CHAR8 *Cmd,\r
389 IN UINTN CmdMaxSize\r
390 )\r
391{\r
392 EFI_STATUS Status;\r
393 UINTN Index;\r
394 UINTN Index2;\r
395 CHAR8 Char;\r
396 CHAR8 *History;\r
397 EFI_INPUT_KEY Key;\r
398\r
399 for (Index = 0; Index < CmdMaxSize - 1;) {\r
400 Status = EblGetCharKey (&Key, 0, NULL);\r
401 if (EFI_ERROR (Status)) {\r
402 Cmd[Index] = '\0';\r
403 AsciiPrint ("\n");\r
404 return Status;\r
405 }\r
406\r
407 Char = (CHAR8)Key.UnicodeChar;\r
408 if ((Char == '\n') || (Char == '\r') || (Char == 0x7f)) {\r
409 Cmd[Index] = '\0';\r
410 if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) {\r
411 AsciiPrint ("\n\r");\r
412 }\r
413 return EFI_SUCCESS;\r
414 } else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){\r
415 if (Index != 0) {\r
416 Index--;\r
417 //\r
418 // Update the display\r
419 //\r
420 AsciiPrint ("\b \b");\r
421 }\r
422 } else if ((Key.ScanCode == SCAN_UP) || Key.ScanCode == SCAN_DOWN) {\r
423 History = GetCmdHistory (Key.ScanCode);\r
424 //\r
425 // Clear display line\r
426 //\r
427 for (Index2 = 0; Index2 < Index; Index2++) {\r
428 AsciiPrint ("\b \b");\r
429 }\r
430 AsciiPrint (History);\r
431 Index = AsciiStrLen (History);\r
432 AsciiStrnCpy (Cmd, History, CmdMaxSize);\r
433 } else {\r
434 Cmd[Index++] = Char;\r
435 if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) {\r
436 AsciiPrint ("%c", Char);\r
437 }\r
438 }\r
439 }\r
440\r
441 return EFI_SUCCESS;\r
442}\r
443\r
444\r
445/**\r
446 Print the boot up banner for the EBL.\r
447**/\r
448VOID\r
449EblPrintStartupBanner (\r
450 VOID\r
451 )\r
452{\r
453 AsciiPrint ("Embedded Boot Loader (");\r
454 EblSetTextColor (EFI_YELLOW);\r
455 AsciiPrint ("EBL");\r
456 EblSetTextColor (0);\r
457 AsciiPrint (") prototype. Built at %a on %a\n",__TIME__, __DATE__);\r
458 AsciiPrint ("THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN 'AS IS' BASIS,\nWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\n");\r
fc35d135 459 AsciiPrint ("Please send feedback to edk2-devel@lists.sourceforge.net\n");\r
2ef2b01e
A
460}\r
461\r
462\r
884366cf 463/**\r
464 Send null requests to all removable media block IO devices so the a media add/remove/change\r
465 can be detected in real before we execute a command. \r
466\r
467 This is mainly due to the fact that the FAT driver does not do this today so you can get stale \r
468 dir commands after an SD Card has been removed.\r
469**/\r
470VOID\r
471EblProbeRemovableMedia (\r
472 VOID\r
473 )\r
474{\r
475 UINTN Index;\r
476 UINTN Max;\r
477 EFI_OPEN_FILE *File;\r
478\r
479 //\r
480 // Probe for media insertion/removal in removable media devices\r
481 //\r
482 Max = EfiGetDeviceCounts (EfiOpenBlockIo);\r
483 if (Max != 0) {\r
484 for (Index = 0; Index < Max; Index++) {\r
485 File = EfiDeviceOpenByType (EfiOpenBlockIo, Index);\r
486 if (File != NULL) {\r
487 if (File->FsBlockIoMedia->RemovableMedia) {\r
488 // Probe to see if media is present (or not) or media changed\r
489 // this causes the ReinstallProtocolInterface() to fire in the\r
490 // block io driver to update the system about media change events\r
491 File->FsBlockIo->ReadBlocks (File->FsBlockIo, File->FsBlockIo->Media->MediaId, (EFI_LBA)0, 0, NULL);\r
492 }\r
493 EfiClose (File);\r
494 }\r
495 }\r
496 }\r
497}\r
498\r
499\r
500\r
501\r
2ef2b01e
A
502/**\r
503 Print the prompt for the EBL.\r
504**/\r
505VOID\r
506EblPrompt (\r
507 VOID\r
508 )\r
509{\r
510 EblSetTextColor (EFI_YELLOW);\r
e6b3b508 511 AsciiPrint ("%a %a",(CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt), EfiGetCwd ());\r
2ef2b01e
A
512 EblSetTextColor (0);\r
513 AsciiPrint ("%a", ">");\r
514}\r
515\r
516\r
517\r
518/**\r
7ca9e5a4 519 Parse a command line and execute the commands. The ; separator allows\r
2ef2b01e
A
520 multiple commands for each command line. Stop processing if one of the\r
521 commands returns an error.\r
522\r
523 @param CmdLine Command Line to process.\r
524 @param MaxCmdLineSize MaxSize of the Command line \r
525\r
526 @return EFI status of the Command\r
527\r
528**/\r
529EFI_STATUS\r
530ProcessCmdLine (\r
531 IN CHAR8 *CmdLine,\r
532 IN UINTN MaxCmdLineSize\r
533 )\r
534{\r
535 EFI_STATUS Status;\r
536 EBL_COMMAND_TABLE *Cmd;\r
537 CHAR8 *Ptr;\r
538 UINTN Argc;\r
539 CHAR8 *Argv[MAX_ARGS];\r
540\r
7ca9e5a4 541 // Parse the command line. The loop processes commands separated by ;\r
2ef2b01e
A
542 for (Ptr = CmdLine, Status = EFI_SUCCESS; Ptr != NULL;) {\r
543 Ptr = ParseArguments (Ptr, &Argc, Argv);\r
544 if (Argc != 0) {\r
545 Cmd = EblGetCommand (Argv[0]);\r
546 if (Cmd != NULL) {\r
547 // Execute the Command!\r
548 Status = Cmd->Command (Argc, Argv);\r
549 if (Status == EFI_ABORTED) {\r
550 // exit command so lets exit\r
551 break;\r
552 } else if (Status == EFI_TIMEOUT) {\r
7ca9e5a4 553 // pause command got input so don't process any more cmd on this cmd line\r
2ef2b01e
A
554 break;\r
555 } else if (EFI_ERROR (Status)) {\r
556 AsciiPrint ("%a returned %r error\n", Cmd->Name, Status);\r
557 // if any command fails stop processing CmdLine\r
558 break;\r
559 }\r
560 } \r
561 } \r
562 }\r
563\r
564 return Status;\r
565}\r
566 \r
567\r
568\r
569/**\r
570 Embedded Boot Loader (EBL) - A simple EFI command line application for embedded \r
7ca9e5a4 571 devices. PcdEmbeddedAutomaticBootCommand is a complied in command line that\r
572 gets executed automatically. The ; separator allows multiple commands\r
2ef2b01e
A
573 for each command line.\r
574\r
575 @param ImageHandle EFI ImageHandle for this application.\r
576 @param SystemTable EFI system table\r
577\r
7ca9e5a4 578 @return EFI status of the application\r
2ef2b01e
A
579\r
580**/\r
581EFI_STATUS\r
582EFIAPI\r
583EdkBootLoaderEntry (\r
584 IN EFI_HANDLE ImageHandle,\r
585 IN EFI_SYSTEM_TABLE *SystemTable\r
586 ) \r
587{\r
588 EFI_STATUS Status;\r
589 CHAR8 CmdLine[MAX_CMD_LINE];\r
590 CHAR16 *CommandLineVariable = NULL;\r
591 CHAR16 *CommandLineVariableName = L"default-cmdline";\r
592 UINTN CommandLineVariableSize = 0;\r
593 EFI_GUID VendorGuid;\r
594\r
7ca9e5a4 595 // Initialize tables of commands\r
2ef2b01e
A
596 EblInitializeCmdTable ();\r
597 EblInitializeDeviceCmd ();\r
598 EblInitializemdHwDebugCmds ();\r
599 EblInitializemdHwIoDebugCmds ();\r
600 EblInitializeDirCmd ();\r
601 EblInitializeHobCmd ();\r
602 EblInitializeScriptCmd ();\r
603 EblInitializeExternalCmd ();\r
604 EblInitializeNetworkCmd();\r
fb334ef6 605 EblInitializeVariableCmds ();\r
2ef2b01e 606 \r
d60b4c43 607 if (gST->ConOut == NULL) {\r
7ca9e5a4 608 DEBUG((EFI_D_ERROR,"Error: No Console Output\n"));\r
d60b4c43 609 return EFI_NOT_READY;\r
610 }\r
611\r
16ccac42 612 // Disable the 5 minute EFI watchdog time so we don't get automatically reset\r
613 gBS->SetWatchdogTimer (0, 0, 0, NULL);\r
614\r
2ef2b01e
A
615 if (FeaturePcdGet (PcdEmbeddedMacBoot)) {\r
616 // A MAC will boot in graphics mode, so turn it back to text here\r
617 // This protocol was removed from edk2. It is only an edk thing. We need to make our own copy.\r
618 // DisableQuietBoot ();\r
619\r
620 // Enable the biggest output screen size possible\r
621 gST->ConOut->SetMode (gST->ConOut, (UINTN)gST->ConOut->Mode->MaxMode - 1);\r
622\r
2ef2b01e
A
623 }\r
624\r
625 // Save current screen mode\r
626 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &gScreenColumns, &gScreenRows);\r
627\r
628 EblPrintStartupBanner ();\r
629 \r
7ca9e5a4 630 // Parse command line and handle commands separated by ;\r
2ef2b01e
A
631 // The loop prints the prompt gets user input and saves history\r
632 \r
633 // Look for a variable with a default command line, otherwise use the Pcd\r
634 ZeroMem(&VendorGuid, sizeof(EFI_GUID));\r
635\r
636 Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable);\r
637 if (Status == EFI_BUFFER_TOO_SMALL) {\r
638 CommandLineVariable = AllocatePool(CommandLineVariableSize);\r
639 \r
640 Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable);\r
641 if (!EFI_ERROR(Status)) {\r
642 UnicodeStrToAsciiStr(CommandLineVariable, CmdLine);\r
643 }\r
644 \r
645 FreePool(CommandLineVariable);\r
646 }\r
647 \r
648 if (EFI_ERROR(Status)) {\r
649 AsciiStrCpy (CmdLine, (CHAR8 *)PcdGetPtr (PcdEmbeddedAutomaticBootCommand));\r
650 }\r
651 \r
652 for (;;) {\r
653 Status = ProcessCmdLine (CmdLine, MAX_CMD_LINE);\r
654 if (Status == EFI_ABORTED) {\r
655 // if a command returns EFI_ABORTED then exit the EBL\r
656 EblShutdownExternalCmdTable ();\r
657 return EFI_SUCCESS;\r
658 }\r
659\r
660 // get the command line from the user\r
661 EblPrompt ();\r
662 GetCmd (CmdLine, MAX_CMD_LINE);\r
663 SetCmdHistory (CmdLine);\r
884366cf 664\r
665 if (FeaturePcdGet (PcdEmbeddedProbeRemovable)) {\r
666 // Probe removable media devices to see if media has been inserted or removed.\r
667 EblProbeRemovableMedia ();\r
668 }\r
2ef2b01e
A
669 }\r
670}\r
671\r
672\r