]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
Treat ASCII 0x7F as backspace for TtyTerm terminals
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / Terminal.c
CommitLineData
fb0b259e 1/** @file\r
11baadb6 2 Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and\r
fb0b259e 3 Simple Text Output Protocol upon Serial IO Protocol.\r
95276127 4\r
4529d723 5Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 6This program and the accompanying materials\r
95276127 7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
fb0b259e 14**/\r
95276127 15\r
16\r
95276127 17#include "Terminal.h"\r
18\r
95276127 19//\r
20// Globals\r
21//\r
22EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {\r
23 TerminalDriverBindingSupported,\r
24 TerminalDriverBindingStart,\r
25 TerminalDriverBindingStop,\r
26 0xa,\r
27 NULL,\r
28 NULL\r
29};\r
30\r
31\r
6b88ceec
A
32EFI_GUID *gTerminalType[] = {\r
33 &gEfiPcAnsiGuid,\r
34 &gEfiVT100Guid,\r
35 &gEfiVT100PlusGuid,\r
6e3227c8
RF
36 &gEfiVTUTF8Guid,\r
37 &gEfiTtyTermGuid\r
6b88ceec
A
38};\r
39\r
40\r
204ba917 41TERMINAL_DEV mTerminalDevTemplate = {\r
6b88ceec
A
42 TERMINAL_DEV_SIGNATURE,\r
43 NULL,\r
44 0,\r
45 NULL,\r
46 NULL,\r
47 { // SimpleTextInput\r
48 TerminalConInReset,\r
49 TerminalConInReadKeyStroke,\r
50 NULL\r
51 },\r
52 { // SimpleTextOutput\r
53 TerminalConOutReset,\r
54 TerminalConOutOutputString,\r
55 TerminalConOutTestString,\r
56 TerminalConOutQueryMode,\r
57 TerminalConOutSetMode,\r
58 TerminalConOutSetAttribute,\r
59 TerminalConOutClearScreen,\r
60 TerminalConOutSetCursorPosition,\r
61 TerminalConOutEnableCursor,\r
62 NULL\r
63 },\r
64 { // SimpleTextOutputMode\r
65 1, // MaxMode\r
11baadb6 66 0, // Mode\r
6b88ceec
A
67 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
68 0, // CursorColumn\r
69 0, // CursorRow\r
70 TRUE // CursorVisible\r
71 },\r
79d07c66 72 NULL, // TerminalConsoleModeData\r
11baadb6 73 0, // SerialInTimeOut\r
5c998646 74\r
75 NULL, // RawFifo\r
76 NULL, // UnicodeFiFo\r
77 NULL, // EfiKeyFiFo\r
78\r
6b88ceec 79 NULL, // ControllerNameTable\r
f0368006 80 NULL, // TimerEvent\r
11baadb6 81 NULL, // TwoSecondTimeOut\r
6b88ceec
A
82 INPUT_STATE_DEFAULT,\r
83 RESET_STATE_DEFAULT,\r
66aa04e4 84 FALSE,\r
85 { // SimpleTextInputEx\r
86 TerminalConInResetEx,\r
87 TerminalConInReadKeyStrokeEx,\r
88 NULL,\r
89 TerminalConInSetState,\r
90 TerminalConInRegisterKeyNotify,\r
91 TerminalConInUnregisterKeyNotify,\r
92 },\r
11baadb6 93 { // NotifyList\r
66aa04e4 94 NULL,\r
95 NULL,\r
96 }\r
6b88ceec
A
97};\r
98\r
79d07c66 99TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
100 {100, 31},\r
101 //\r
102 // New modes can be added here.\r
79d07c66 103 //\r
79d07c66 104};\r
105\r
8fd98315 106/**\r
677fdb90 107 Test to see if this driver supports Controller.\r
8fd98315 108\r
109 @param This Protocol instance pointer.\r
ab76200c 110 @param Controller Handle of device to test\r
8fd98315 111 @param RemainingDevicePath Optional parameter use to pick a specific child\r
112 device to start.\r
113\r
ab76200c 114 @retval EFI_SUCCESS This driver supports this device.\r
115 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
116 @retval other This driver does not support this device.\r
6b88ceec 117\r
8fd98315 118**/\r
95276127 119EFI_STATUS\r
120EFIAPI\r
121TerminalDriverBindingSupported (\r
122 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
123 IN EFI_HANDLE Controller,\r
124 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
125 )\r
126{\r
127 EFI_STATUS Status;\r
128 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
129 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
130 VENDOR_DEVICE_PATH *Node;\r
131\r
132 //\r
133 // If remaining device path is not NULL, then make sure it is a\r
134 // device path that describes a terminal communications protocol.\r
135 //\r
136 if (RemainingDevicePath != NULL) {\r
95276127 137 //\r
e3dcffcc 138 // Check if RemainingDevicePath is the End of Device Path Node,\r
af4a6385 139 // if yes, go on checking other conditions\r
95276127 140 //\r
af4a6385 141 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
142 //\r
143 // If RemainingDevicePath isn't the End of Device Path Node,\r
144 // check its validation\r
145 //\r
146 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
e3dcffcc 147\r
af4a6385 148 if (Node->Header.Type != MESSAGING_DEVICE_PATH ||\r
149 Node->Header.SubType != MSG_VENDOR_DP ||\r
150 DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {\r
e3dcffcc 151\r
af4a6385 152 return EFI_UNSUPPORTED;\r
e3dcffcc 153\r
af4a6385 154 }\r
155 //\r
6e3227c8 156 // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types\r
af4a6385 157 //\r
158 if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
159 !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
160 !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
6e3227c8
RF
161 !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid) &&\r
162 !CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
e3dcffcc 163\r
af4a6385 164 return EFI_UNSUPPORTED;\r
165 }\r
95276127 166 }\r
167 }\r
168 //\r
169 // Open the IO Abstraction(s) needed to perform the supported test\r
af4a6385 170 // The Controller must support the Serial I/O Protocol.\r
171 // This driver is a bus driver with at most 1 child device, so it is\r
172 // ok for it to be already started.\r
95276127 173 //\r
174 Status = gBS->OpenProtocol (\r
175 Controller,\r
af4a6385 176 &gEfiSerialIoProtocolGuid,\r
177 (VOID **) &SerialIo,\r
95276127 178 This->DriverBindingHandle,\r
179 Controller,\r
180 EFI_OPEN_PROTOCOL_BY_DRIVER\r
181 );\r
182 if (Status == EFI_ALREADY_STARTED) {\r
183 return EFI_SUCCESS;\r
184 }\r
185\r
186 if (EFI_ERROR (Status)) {\r
187 return Status;\r
188 }\r
189\r
af4a6385 190 //\r
191 // Close the I/O Abstraction(s) used to perform the supported test\r
192 //\r
95276127 193 gBS->CloseProtocol (\r
194 Controller,\r
af4a6385 195 &gEfiSerialIoProtocolGuid,\r
95276127 196 This->DriverBindingHandle,\r
197 Controller\r
198 );\r
199\r
200 //\r
af4a6385 201 // Open the EFI Device Path protocol needed to perform the supported test\r
95276127 202 //\r
203 Status = gBS->OpenProtocol (\r
204 Controller,\r
af4a6385 205 &gEfiDevicePathProtocolGuid,\r
206 (VOID **) &ParentDevicePath,\r
95276127 207 This->DriverBindingHandle,\r
208 Controller,\r
209 EFI_OPEN_PROTOCOL_BY_DRIVER\r
210 );\r
211 if (Status == EFI_ALREADY_STARTED) {\r
212 return EFI_SUCCESS;\r
213 }\r
214\r
215 if (EFI_ERROR (Status)) {\r
216 return Status;\r
217 }\r
af4a6385 218\r
95276127 219 //\r
af4a6385 220 // Close protocol, don't use device path protocol in the Support() function\r
95276127 221 //\r
222 gBS->CloseProtocol (\r
223 Controller,\r
af4a6385 224 &gEfiDevicePathProtocolGuid,\r
95276127 225 This->DriverBindingHandle,\r
226 Controller\r
227 );\r
228\r
229 return Status;\r
230}\r
231\r
e3dcffcc 232/**\r
233 Build the terminal device path for the child device according to the\r
234 terminal type.\r
235\r
236 @param ParentDevicePath Parent device path.\r
237 @param RemainingDevicePath A specific child device.\r
238\r
239 @return The child device path built.\r
240\r
241**/\r
242EFI_DEVICE_PATH_PROTOCOL*\r
243EFIAPI\r
244BuildTerminalDevpath (\r
245 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
246 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
247 )\r
248{\r
249 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
250 UINT8 TerminalType;\r
251 VENDOR_DEVICE_PATH *Node;\r
252 EFI_STATUS Status;\r
253\r
254 TerminalDevicePath = NULL;\r
255 TerminalType = PCANSITYPE;\r
256\r
257 //\r
258 // Use the RemainingDevicePath to determine the terminal type\r
259 //\r
260 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
261 if (Node == NULL) {\r
262 TerminalType = PCANSITYPE;\r
263\r
264 } else if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
265\r
266 TerminalType = PCANSITYPE;\r
267\r
268 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
269\r
270 TerminalType = VT100TYPE;\r
271\r
272 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
273\r
274 TerminalType = VT100PLUSTYPE;\r
275\r
276 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
277\r
278 TerminalType = VTUTF8TYPE;\r
279\r
6e3227c8
RF
280 } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
281\r
282 TerminalType = TTYTERMTYPE;\r
283\r
e3dcffcc 284 } else {\r
285 return NULL;\r
286 }\r
287\r
288 //\r
289 // Build the device path for the child device\r
290 //\r
291 Status = SetTerminalDevicePath (\r
292 TerminalType,\r
293 ParentDevicePath,\r
294 &TerminalDevicePath\r
295 );\r
296 if (EFI_ERROR (Status)) {\r
297 return NULL;\r
298 }\r
299 return TerminalDevicePath;\r
300}\r
301\r
302/**\r
303 Compare a device path data structure to that of all the nodes of a\r
304 second device path instance.\r
305\r
306 @param Multi A pointer to a multi-instance device path data structure.\r
307 @param Single A pointer to a single-instance device path data structure.\r
308\r
309 @retval TRUE If the Single is contained within Multi.\r
310 @retval FALSE The Single is not match within Multi.\r
311\r
312**/\r
313BOOLEAN\r
314MatchDevicePaths (\r
315 IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
316 IN EFI_DEVICE_PATH_PROTOCOL *Single\r
317 )\r
318{\r
319 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
320 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
321 UINTN Size;\r
322\r
323 DevicePath = Multi;\r
324 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
325 //\r
326 // Search for the match of 'Single' in 'Multi'\r
327 //\r
328 while (DevicePathInst != NULL) {\r
329 //\r
330 // If the single device path is found in multiple device paths,\r
331 // return success\r
332 //\r
333 if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
334 FreePool (DevicePathInst);\r
335 return TRUE;\r
336 }\r
337\r
338 FreePool (DevicePathInst);\r
339 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
340 }\r
341\r
342 return FALSE;\r
343}\r
344\r
345/**\r
346 Check whether the terminal device path is in the global variable.\r
347\r
348 @param VariableName Pointer to one global variable.\r
349 @param TerminalDevicePath Pointer to the terminal device's device path.\r
350\r
351 @retval TRUE The devcie is in the global variable.\r
352 @retval FALSE The devcie is not in the global variable.\r
353\r
354**/\r
355BOOLEAN\r
356IsTerminalInConsoleVariable (\r
357 IN CHAR16 *VariableName,\r
358 IN EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath\r
359 )\r
360{\r
361 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
362 BOOLEAN ReturnFlag;\r
363\r
364 //\r
365 // Get global variable and its size according to the name given.\r
366 //\r
f01b91ae 367 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
e3dcffcc 368 if (Variable == NULL) {\r
369 return FALSE;\r
370 }\r
371\r
372 //\r
373 // Check whether the terminal device path is one of the variable instances.\r
374 //\r
375 ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
376\r
377 FreePool (Variable);\r
378\r
379 return ReturnFlag;\r
380}\r
381\r
382/**\r
383 Free notify functions list.\r
384\r
385 @param ListHead The list head\r
386\r
387 @retval EFI_SUCCESS Free the notify list successfully.\r
388 @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
389\r
390**/\r
391EFI_STATUS\r
392TerminalFreeNotifyList (\r
393 IN OUT LIST_ENTRY *ListHead\r
394 )\r
395{\r
396 TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
397\r
398 if (ListHead == NULL) {\r
399 return EFI_INVALID_PARAMETER;\r
400 }\r
401 while (!IsListEmpty (ListHead)) {\r
402 NotifyNode = CR (\r
403 ListHead->ForwardLink,\r
404 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
405 NotifyEntry,\r
406 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
407 );\r
408 RemoveEntryList (ListHead->ForwardLink);\r
409 FreePool (NotifyNode);\r
410 }\r
411\r
412 return EFI_SUCCESS;\r
413}\r
414\r
79d07c66 415/**\r
416 Initialize all the text modes which the terminal console supports.\r
417\r
418 It returns information for available text modes that the terminal can support.\r
419\r
420 @param[out] TextModeCount The total number of text modes that terminal console supports.\r
421 @param[out] TextModeData The buffer to the text modes column and row information.\r
422 Caller is responsible to free it when it's non-NULL.\r
423\r
424 @retval EFI_SUCCESS The supporting mode information is returned.\r
425 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
426\r
427**/\r
428EFI_STATUS\r
429InitializeTerminalConsoleTextMode (\r
430 OUT UINTN *TextModeCount,\r
431 OUT TERMINAL_CONSOLE_MODE_DATA **TextModeData\r
432 )\r
433{\r
434 UINTN Index;\r
435 UINTN Count;\r
436 TERMINAL_CONSOLE_MODE_DATA *ModeBuffer;\r
437 TERMINAL_CONSOLE_MODE_DATA *NewModeBuffer;\r
438 UINTN ValidCount;\r
439 UINTN ValidIndex;\r
440 \r
441 if ((TextModeCount == NULL) || (TextModeData == NULL)) {\r
442 return EFI_INVALID_PARAMETER;\r
443 }\r
444 \r
79d07c66 445 Count = sizeof (mTerminalConsoleModeData) / sizeof (TERMINAL_CONSOLE_MODE_DATA);\r
79d07c66 446 \r
447 //\r
448 // Get defined mode buffer pointer.\r
449 //\r
450 ModeBuffer = mTerminalConsoleModeData;\r
451 \r
452 //\r
453 // Here we make sure that the final mode exposed does not include the duplicated modes,\r
454 // and does not include the invalid modes which exceed the max column and row.\r
455 // Reserve 2 modes for 80x25, 80x50 of terminal console.\r
456 //\r
457 NewModeBuffer = AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA) * (Count + 2));\r
458 ASSERT (NewModeBuffer != NULL);\r
459\r
460 //\r
461 // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
462 //\r
463 ValidCount = 0; \r
464\r
465 NewModeBuffer[ValidCount].Columns = 80;\r
466 NewModeBuffer[ValidCount].Rows = 25;\r
467 ValidCount++;\r
468\r
469 NewModeBuffer[ValidCount].Columns = 80;\r
470 NewModeBuffer[ValidCount].Rows = 50;\r
471 ValidCount++;\r
472 \r
473 //\r
474 // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.\r
475 //\r
476 for (Index = 0; Index < Count; Index++) {\r
477 if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0)) {\r
478 //\r
479 // Skip the pre-defined mode which is invalid.\r
480 //\r
481 continue;\r
482 }\r
483 for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {\r
484 if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&\r
485 (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {\r
486 //\r
487 // Skip the duplicated mode.\r
488 //\r
489 break;\r
490 }\r
491 }\r
492 if (ValidIndex == ValidCount) {\r
493 NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;\r
494 NewModeBuffer[ValidCount].Rows = ModeBuffer[Index].Rows;\r
495 ValidCount++;\r
496 }\r
497 }\r
498 \r
499 DEBUG_CODE (\r
500 for (Index = 0; Index < ValidCount; Index++) {\r
501 DEBUG ((EFI_D_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n", \r
502 Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows)); \r
503 }\r
504 );\r
505 \r
506 //\r
507 // Return valid mode count and mode information buffer.\r
508 //\r
509 *TextModeCount = ValidCount;\r
510 *TextModeData = NewModeBuffer;\r
511 return EFI_SUCCESS;\r
512}\r
e3dcffcc 513\r
e49ef433 514/**\r
ab76200c 515 Start this driver on Controller by opening a Serial IO protocol,\r
8fd98315 516 reading Device Path, and creating a child handle with a Simple Text In,\r
517 Simple Text In Ex and Simple Text Out protocol, and device path protocol.\r
518 And store Console Device Environment Variables.\r
e49ef433 519\r
8fd98315 520 @param This Protocol instance pointer.\r
ab76200c 521 @param Controller Handle of device to bind driver to\r
8fd98315 522 @param RemainingDevicePath Optional parameter use to pick a specific child\r
523 device to start.\r
e49ef433 524\r
ab76200c 525 @retval EFI_SUCCESS This driver is added to Controller.\r
526 @retval EFI_ALREADY_STARTED This driver is already running on Controller.\r
527 @retval other This driver does not support this device.\r
e49ef433 528\r
529**/\r
95276127 530EFI_STATUS\r
531EFIAPI\r
532TerminalDriverBindingStart (\r
533 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
534 IN EFI_HANDLE Controller,\r
535 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
536 )\r
95276127 537{\r
538 EFI_STATUS Status;\r
539 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
540 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
541 VENDOR_DEVICE_PATH *Node;\r
542 VENDOR_DEVICE_PATH *DefaultNode;\r
543 EFI_SERIAL_IO_MODE *Mode;\r
544 UINTN SerialInTimeOut;\r
545 TERMINAL_DEV *TerminalDevice;\r
546 UINT8 TerminalType;\r
547 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
548 UINTN EntryCount;\r
549 UINTN Index;\r
550 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
c4f9201e 551 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
e3dcffcc 552 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextInput;\r
553 BOOLEAN ConInSelected;\r
554 BOOLEAN ConOutSelected;\r
555 BOOLEAN NullRemaining;\r
556 BOOLEAN SimTxtInInstalled;\r
557 BOOLEAN SimTxtOutInstalled;\r
558 BOOLEAN FirstEnter;\r
79d07c66 559 UINTN ModeCount;\r
e3dcffcc 560\r
561 TerminalDevice = NULL;\r
562 DefaultNode = NULL;\r
563 ConInSelected = FALSE;\r
564 ConOutSelected = FALSE;\r
565 NullRemaining = TRUE;\r
566 SimTxtInInstalled = FALSE;\r
567 SimTxtOutInstalled = FALSE;\r
568 FirstEnter = FALSE;\r
95276127 569 //\r
570 // Get the Device Path Protocol to build the device path of the child device\r
571 //\r
572 Status = gBS->OpenProtocol (\r
573 Controller,\r
574 &gEfiDevicePathProtocolGuid,\r
575 (VOID **) &ParentDevicePath,\r
576 This->DriverBindingHandle,\r
577 Controller,\r
578 EFI_OPEN_PROTOCOL_BY_DRIVER\r
579 );\r
580 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
581 return Status;\r
582 }\r
95276127 583\r
584 //\r
585 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.\r
586 //\r
587 Status = gBS->OpenProtocol (\r
588 Controller,\r
589 &gEfiSerialIoProtocolGuid,\r
590 (VOID **) &SerialIo,\r
591 This->DriverBindingHandle,\r
592 Controller,\r
593 EFI_OPEN_PROTOCOL_BY_DRIVER\r
594 );\r
595 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
596 return Status;\r
597 }\r
598\r
599 if (Status != EFI_ALREADY_STARTED) {\r
600 //\r
e3dcffcc 601 // the serial I/O protocol never be opened before, it is the first\r
602 // time to start the serial Io controller\r
95276127 603 //\r
e3dcffcc 604 FirstEnter = TRUE;\r
95276127 605 }\r
e3dcffcc 606\r
95276127 607 //\r
e3dcffcc 608 // Serial I/O is not already open by this driver, then tag the handle\r
609 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
610 // StdErrDev variables with the list of possible terminal types on this\r
611 // serial port.\r
95276127 612 //\r
e3dcffcc 613 Status = gBS->OpenProtocol (\r
95276127 614 Controller,\r
e3dcffcc 615 &gEfiCallerIdGuid,\r
616 NULL,\r
617 This->DriverBindingHandle,\r
618 Controller,\r
619 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
95276127 620 );\r
e3dcffcc 621 if (EFI_ERROR (Status)) {\r
622 Status = gBS->InstallMultipleProtocolInterfaces (\r
623 &Controller,\r
624 &gEfiCallerIdGuid,\r
625 DuplicateDevicePath (ParentDevicePath),\r
626 NULL\r
627 );\r
628 if (EFI_ERROR (Status)) {\r
629 goto Error;\r
95276127 630 }\r
631\r
e3dcffcc 632 if (!IsHotPlugDevice (ParentDevicePath)) {\r
633 //\r
634 // if the serial device is a hot plug device, do not update the\r
635 // ConInDev, ConOutDev, and StdErrDev variables.\r
636 //\r
637 TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
638 TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
639 TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 640 }\r
641 }\r
e3dcffcc 642\r
643 //\r
644 // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols\r
95276127 645 //\r
e3dcffcc 646 // Simple In/Out Protocol will not be installed onto the handle if the\r
647 // device path to the handle is not present in the ConIn/ConOut\r
648 // environment variable. But If RemainingDevicePath is NULL, then always\r
649 // produce both Simple In and Simple Text Output Protocols. This is required\r
650 // for the connect all sequences to make sure all possible consoles are\r
651 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 652 //\r
653 if (RemainingDevicePath == NULL) {\r
e3dcffcc 654 NullRemaining = TRUE;\r
655 }\r
656\r
657 DevicePath = BuildTerminalDevpath (ParentDevicePath, RemainingDevicePath);\r
658 if (DevicePath != NULL) {\r
659 ConInSelected = IsTerminalInConsoleVariable (L"ConIn", DevicePath);\r
660 ConOutSelected = IsTerminalInConsoleVariable (L"ConOut", DevicePath);\r
661 FreePool (DevicePath);\r
662 } else {\r
663 goto Error;\r
664 }\r
665 //\r
666 // Not create the child terminal handle if both Simple In/In Ex and\r
667 // Simple text Out protocols are not required to be published\r
668 //\r
669 if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
670 goto Error;\r
671 }\r
672\r
673 //\r
674 // create the child terminal handle during first entry\r
675 //\r
676 if (FirstEnter) {\r
677 //\r
678 // First enther the start funciton\r
679 //\r
680 FirstEnter = FALSE;\r
681 //\r
682 // Make sure a child handle does not already exist. This driver can only\r
683 // produce one child per serial port.\r
684 //\r
685 Status = gBS->OpenProtocolInformation (\r
686 Controller,\r
687 &gEfiSerialIoProtocolGuid,\r
688 &OpenInfoBuffer,\r
689 &EntryCount\r
690 );\r
691 if (!EFI_ERROR (Status)) {\r
692 Status = EFI_SUCCESS;\r
693 for (Index = 0; Index < EntryCount; Index++) {\r
694 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
695 Status = EFI_ALREADY_STARTED;\r
696 }\r
697 }\r
698\r
699 FreePool (OpenInfoBuffer);\r
700 if (EFI_ERROR (Status)) {\r
701 goto Error;\r
702 }\r
703 }\r
704\r
705 //\r
706 // If RemainingDevicePath is NULL, then create default device path node\r
707 //\r
708 if (RemainingDevicePath == NULL) {\r
709 DefaultNode = AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH));\r
710 if (DefaultNode == NULL) {\r
711 Status = EFI_OUT_OF_RESOURCES;\r
712 goto Error;\r
713 }\r
714\r
188e4e84 715 TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
e3dcffcc 716 //\r
6e3227c8 717 // Must be between PCANSITYPE (0) and TTYTERMTYPE (4)\r
e3dcffcc 718 //\r
6e3227c8 719 ASSERT (TerminalType <= TTYTERMTYPE);\r
e3dcffcc 720\r
721 CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
722 RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DefaultNode;\r
723 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
724 //\r
725 // If RemainingDevicePath isn't the End of Device Path Node,\r
726 // Use the RemainingDevicePath to determine the terminal type\r
727 //\r
728 Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
729 if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
730 TerminalType = PCANSITYPE;\r
731 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
732 TerminalType = VT100TYPE;\r
733 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
734 TerminalType = VT100PLUSTYPE;\r
735 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
736 TerminalType = VTUTF8TYPE;\r
6e3227c8
RF
737 } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
738 TerminalType = TTYTERMTYPE;\r
e3dcffcc 739 } else {\r
740 goto Error;\r
741 }\r
742 } else {\r
743 //\r
744 // If RemainingDevicePath is the End of Device Path Node,\r
745 // skip enumerate any device and return EFI_SUCESSS\r
746 //\r
747 return EFI_SUCCESS;\r
748 }\r
749\r
750 //\r
751 // Initialize the Terminal Dev\r
752 //\r
753 TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
754 if (TerminalDevice == NULL) {\r
95276127 755 Status = EFI_OUT_OF_RESOURCES;\r
756 goto Error;\r
757 }\r
758\r
e3dcffcc 759 TerminalDevice->TerminalType = TerminalType;\r
760 TerminalDevice->SerialIo = SerialIo;\r
761\r
762 InitializeListHead (&TerminalDevice->NotifyList);\r
763 Status = gBS->CreateEvent (\r
764 EVT_NOTIFY_WAIT,\r
765 TPL_NOTIFY,\r
766 TerminalConInWaitForKeyEx,\r
f0368006 767 TerminalDevice,\r
e3dcffcc 768 &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
769 );\r
770 if (EFI_ERROR (Status)) {\r
771 goto Error;\r
772 }\r
773\r
774 Status = gBS->CreateEvent (\r
775 EVT_NOTIFY_WAIT,\r
776 TPL_NOTIFY,\r
777 TerminalConInWaitForKey,\r
f0368006 778 TerminalDevice,\r
e3dcffcc 779 &TerminalDevice->SimpleInput.WaitForKey\r
780 );\r
781 if (EFI_ERROR (Status)) {\r
782 goto Error;\r
783 }\r
8fd98315 784 //\r
e3dcffcc 785 // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
786 // the pre-read pending characters.\r
8fd98315 787 //\r
e3dcffcc 788 TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
789 if (TerminalDevice->RawFiFo == NULL) {\r
790 goto Error;\r
791 }\r
792 TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
793 if (TerminalDevice->UnicodeFiFo == NULL) {\r
794 goto Error;\r
795 }\r
796 TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
797 if (TerminalDevice->EfiKeyFiFo == NULL) {\r
798 goto Error;\r
799 }\r
95276127 800\r
6b88ceec 801 //\r
e3dcffcc 802 // Set the timeout value of serial buffer for\r
803 // keystroke response performance issue\r
6b88ceec 804 //\r
e3dcffcc 805 Mode = TerminalDevice->SerialIo->Mode;\r
806\r
807 SerialInTimeOut = 0;\r
808 if (Mode->BaudRate != 0) {\r
809 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
810 }\r
811\r
812 Status = TerminalDevice->SerialIo->SetAttributes (\r
813 TerminalDevice->SerialIo,\r
814 Mode->BaudRate,\r
815 Mode->ReceiveFifoDepth,\r
816 (UINT32) SerialInTimeOut,\r
817 (EFI_PARITY_TYPE) (Mode->Parity),\r
818 (UINT8) Mode->DataBits,\r
819 (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
820 );\r
821 if (EFI_ERROR (Status)) {\r
822 //\r
823 // if set attributes operation fails, invalidate\r
824 // the value of SerialInTimeOut,thus make it\r
825 // inconsistent with the default timeout value\r
826 // of serial buffer. This will invoke the recalculation\r
827 // in the readkeystroke routine.\r
828 //\r
829 TerminalDevice->SerialInTimeOut = 0;\r
6b88ceec 830 } else {\r
e3dcffcc 831 TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
6b88ceec 832 }\r
af4a6385 833 //\r
e3dcffcc 834 // Set Simple Text Output Protocol from template.\r
835 //\r
836 SimpleTextOutput = CopyMem (\r
837 &TerminalDevice->SimpleTextOutput,\r
838 &mTerminalDevTemplate.SimpleTextOutput,\r
839 sizeof (mTerminalDevTemplate.SimpleTextOutput)\r
840 );\r
841 SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
79d07c66 842 \r
843 Status = InitializeTerminalConsoleTextMode (&ModeCount, &TerminalDevice->TerminalConsoleModeData);\r
844 if (EFI_ERROR (Status)) {\r
845 goto ReportError;\r
846 }\r
847 TerminalDevice->SimpleTextOutputMode.MaxMode = (INT32) ModeCount;\r
848 \r
e3dcffcc 849 //\r
850 // For terminal devices, cursor is always visible\r
851 //\r
852 TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
853 Status = TerminalConOutSetAttribute (\r
854 SimpleTextOutput,\r
855 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
856 );\r
857 if (EFI_ERROR (Status)) {\r
858 goto ReportError;\r
859 }\r
6b88ceec 860\r
e3dcffcc 861 //\r
862 // Build the component name for the child device\r
863 //\r
864 TerminalDevice->ControllerNameTable = NULL;\r
865 switch (TerminalDevice->TerminalType) {\r
866 case PCANSITYPE:\r
867 AddUnicodeString2 (\r
868 "eng",\r
869 gTerminalComponentName.SupportedLanguages,\r
870 &TerminalDevice->ControllerNameTable,\r
871 (CHAR16 *)L"PC-ANSI Serial Console",\r
872 TRUE\r
873 );\r
874 AddUnicodeString2 (\r
875 "en",\r
876 gTerminalComponentName2.SupportedLanguages,\r
877 &TerminalDevice->ControllerNameTable,\r
878 (CHAR16 *)L"PC-ANSI Serial Console",\r
879 FALSE\r
880 );\r
95276127 881\r
e3dcffcc 882 break;\r
66aa04e4 883\r
e3dcffcc 884 case VT100TYPE:\r
885 AddUnicodeString2 (\r
886 "eng",\r
887 gTerminalComponentName.SupportedLanguages,\r
888 &TerminalDevice->ControllerNameTable,\r
889 (CHAR16 *)L"VT-100 Serial Console",\r
890 TRUE\r
891 );\r
892 AddUnicodeString2 (\r
893 "en",\r
894 gTerminalComponentName2.SupportedLanguages,\r
895 &TerminalDevice->ControllerNameTable,\r
896 (CHAR16 *)L"VT-100 Serial Console",\r
897 FALSE\r
898 );\r
899\r
900 break;\r
901\r
902 case VT100PLUSTYPE:\r
903 AddUnicodeString2 (\r
904 "eng",\r
905 gTerminalComponentName.SupportedLanguages,\r
906 &TerminalDevice->ControllerNameTable,\r
907 (CHAR16 *)L"VT-100+ Serial Console",\r
908 TRUE\r
909 );\r
910 AddUnicodeString2 (\r
911 "en",\r
912 gTerminalComponentName2.SupportedLanguages,\r
913 &TerminalDevice->ControllerNameTable,\r
914 (CHAR16 *)L"VT-100+ Serial Console",\r
915 FALSE\r
916 );\r
917\r
918 break;\r
919\r
920 case VTUTF8TYPE:\r
921 AddUnicodeString2 (\r
922 "eng",\r
923 gTerminalComponentName.SupportedLanguages,\r
924 &TerminalDevice->ControllerNameTable,\r
925 (CHAR16 *)L"VT-UTF8 Serial Console",\r
926 TRUE\r
927 );\r
928 AddUnicodeString2 (\r
929 "en",\r
930 gTerminalComponentName2.SupportedLanguages,\r
931 &TerminalDevice->ControllerNameTable,\r
932 (CHAR16 *)L"VT-UTF8 Serial Console",\r
933 FALSE\r
934 );\r
935\r
936 break;\r
6e3227c8
RF
937\r
938 case TTYTERMTYPE:\r
939 AddUnicodeString2 (\r
940 "eng",\r
941 gTerminalComponentName.SupportedLanguages,\r
942 &TerminalDevice->ControllerNameTable,\r
943 (CHAR16 *)L"Tty Terminal Serial Console",\r
944 TRUE\r
945 );\r
946 AddUnicodeString2 (\r
947 "en",\r
948 gTerminalComponentName2.SupportedLanguages,\r
949 &TerminalDevice->ControllerNameTable,\r
950 (CHAR16 *)L"Tty Terminal Serial Console",\r
951 FALSE\r
952 );\r
953\r
954 break;\r
e3dcffcc 955 }\r
95276127 956\r
95276127 957 //\r
e3dcffcc 958 // Build the device path for the child device\r
95276127 959 //\r
e3dcffcc 960 Status = SetTerminalDevicePath (\r
961 TerminalDevice->TerminalType,\r
962 ParentDevicePath,\r
963 &TerminalDevice->DevicePath\r
964 );\r
965 if (EFI_ERROR (Status)) {\r
966 goto Error;\r
967 }\r
95276127 968\r
abef1c7a 969 Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
970 if (EFI_ERROR (Status)) {\r
971 goto ReportError;\r
972 }\r
973\r
974 Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
975 if (EFI_ERROR (Status)) {\r
976 goto ReportError;\r
977 }\r
978\r
979 Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
980 if (EFI_ERROR (Status)) {\r
981 goto ReportError;\r
982 }\r
983\r
f0368006
RN
984 Status = gBS->CreateEvent (\r
985 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
986 TPL_NOTIFY,\r
987 TerminalConInTimerHandler,\r
988 TerminalDevice,\r
989 &TerminalDevice->TimerEvent\r
990 );\r
991 ASSERT_EFI_ERROR (Status);\r
992\r
993 Status = gBS->SetTimer (\r
994 TerminalDevice->TimerEvent,\r
995 TimerPeriodic,\r
996 KEYBOARD_TIMER_INTERVAL\r
997 );\r
998 ASSERT_EFI_ERROR (Status);\r
999\r
abef1c7a 1000 Status = gBS->CreateEvent (\r
1001 EVT_TIMER,\r
1002 TPL_CALLBACK,\r
1003 NULL,\r
1004 NULL,\r
1005 &TerminalDevice->TwoSecondTimeOut\r
1006 );\r
f0368006 1007 ASSERT_EFI_ERROR (Status);\r
abef1c7a 1008\r
e3dcffcc 1009 Status = gBS->InstallProtocolInterface (\r
1010 &TerminalDevice->Handle,\r
1011 &gEfiDevicePathProtocolGuid,\r
1012 EFI_NATIVE_INTERFACE,\r
1013 TerminalDevice->DevicePath\r
1014 );\r
1015 if (EFI_ERROR (Status)) {\r
1016 goto Error;\r
1017 }\r
95276127 1018\r
95276127 1019 //\r
e3dcffcc 1020 // Register the Parent-Child relationship via\r
1021 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
95276127 1022 //\r
e3dcffcc 1023 Status = gBS->OpenProtocol (\r
1024 Controller,\r
1025 &gEfiSerialIoProtocolGuid,\r
1026 (VOID **) &TerminalDevice->SerialIo,\r
1027 This->DriverBindingHandle,\r
1028 TerminalDevice->Handle,\r
1029 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1030 );\r
1031 if (EFI_ERROR (Status)) {\r
1032 goto Error;\r
1033 }\r
95276127 1034 }\r
95276127 1035\r
3012ce5c 1036 //\r
e3dcffcc 1037 // Find the child handle, and get its TerminalDevice private data\r
3012ce5c 1038 //\r
e3dcffcc 1039 Status = gBS->OpenProtocolInformation (\r
1040 Controller,\r
1041 &gEfiSerialIoProtocolGuid,\r
1042 &OpenInfoBuffer,\r
1043 &EntryCount\r
1044 );\r
1045 if (!EFI_ERROR (Status)) {\r
1046 Status = EFI_NOT_FOUND;\r
1047 ASSERT (OpenInfoBuffer != NULL);\r
1048 for (Index = 0; Index < EntryCount; Index++) {\r
1049 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
1050 //\r
1051 // Find the child terminal handle.\r
1052 // Test whether the SimpleTxtIn and SimpleTxtOut have been published\r
1053 //\r
1054 Status = gBS->OpenProtocol (\r
1055 OpenInfoBuffer[Index].ControllerHandle,\r
1056 &gEfiSimpleTextInProtocolGuid,\r
1057 (VOID **) &SimpleTextInput,\r
1058 This->DriverBindingHandle,\r
1059 OpenInfoBuffer[Index].ControllerHandle,\r
1060 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1061 );\r
1062 if (!EFI_ERROR (Status)) {\r
1063 SimTxtInInstalled = TRUE;\r
1064 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
1065 }\r
3012ce5c 1066\r
e3dcffcc 1067 Status = gBS->OpenProtocol (\r
1068 OpenInfoBuffer[Index].ControllerHandle,\r
1069 &gEfiSimpleTextOutProtocolGuid,\r
1070 (VOID **) &SimpleTextOutput,\r
1071 This->DriverBindingHandle,\r
1072 OpenInfoBuffer[Index].ControllerHandle,\r
1073 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1074 );\r
1075 if (!EFI_ERROR (Status)) {\r
1076 SimTxtOutInstalled = TRUE;\r
1077 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1078 }\r
1079 Status = EFI_SUCCESS;\r
1080 break;\r
1081 }\r
1082 }\r
95276127 1083\r
e3dcffcc 1084 FreePool (OpenInfoBuffer);\r
1085 if (EFI_ERROR (Status)) {\r
1086 goto ReportError;\r
1087 }\r
1088 } else {\r
95276127 1089 goto ReportError;\r
1090 }\r
1091\r
e3dcffcc 1092 ASSERT (TerminalDevice != NULL);\r
1093 //\r
1094 // Only do the reset if the device path is in the Conout variable\r
1095 //\r
1096 if (ConInSelected && !SimTxtInInstalled) {\r
1097 Status = TerminalDevice->SimpleInput.Reset (\r
1098 &TerminalDevice->SimpleInput,\r
1099 FALSE\r
1100 );\r
1101 if (EFI_ERROR (Status)) {\r
1102 //\r
1103 // Need to report Error Code first\r
1104 //\r
1105 goto ReportError;\r
1106 }\r
95276127 1107 }\r
95276127 1108\r
95276127 1109 //\r
e3dcffcc 1110 // Only output the configure string to remote terminal if the device path\r
1111 // is in the Conout variable\r
95276127 1112 //\r
e3dcffcc 1113 if (ConOutSelected && !SimTxtOutInstalled) {\r
1114 Status = TerminalDevice->SimpleTextOutput.SetAttribute (\r
1115 &TerminalDevice->SimpleTextOutput,\r
1116 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
1117 );\r
1118 if (EFI_ERROR (Status)) {\r
1119 goto ReportError;\r
1120 }\r
5bca971e 1121\r
e3dcffcc 1122 Status = TerminalDevice->SimpleTextOutput.Reset (\r
1123 &TerminalDevice->SimpleTextOutput,\r
1124 FALSE\r
1125 );\r
1126 if (EFI_ERROR (Status)) {\r
1127 goto ReportError;\r
1128 }\r
95276127 1129\r
e3dcffcc 1130 Status = TerminalDevice->SimpleTextOutput.SetMode (\r
1131 &TerminalDevice->SimpleTextOutput,\r
1132 0\r
1133 );\r
1134 if (EFI_ERROR (Status)) {\r
1135 goto ReportError;\r
1136 }\r
5bca971e 1137\r
e3dcffcc 1138 Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
1139 &TerminalDevice->SimpleTextOutput,\r
1140 TRUE\r
1141 );\r
1142 if (EFI_ERROR (Status)) {\r
1143 goto ReportError;\r
1144 }\r
95276127 1145 }\r
f1aec6cc 1146\r
95276127 1147 //\r
e3dcffcc 1148 // Simple In/Out Protocol will not be installed onto the handle if the\r
1149 // device path to the handle is not present in the ConIn/ConOut\r
1150 // environment variable. But If RemainingDevicePath is NULL, then always\r
1151 // produce both Simple In and Simple Text Output Protocols. This is required\r
1152 // for the connect all sequences to make sure all possible consoles are\r
1153 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 1154 //\r
e3dcffcc 1155 if (!SimTxtInInstalled && (ConInSelected || NullRemaining)) {\r
1156 Status = gBS->InstallMultipleProtocolInterfaces (\r
1157 &TerminalDevice->Handle,\r
1158 &gEfiSimpleTextInProtocolGuid,\r
1159 &TerminalDevice->SimpleInput,\r
1160 &gEfiSimpleTextInputExProtocolGuid,\r
1161 &TerminalDevice->SimpleInputEx,\r
1162 NULL\r
1163 );\r
1164 if (EFI_ERROR (Status)) {\r
1165 goto Error;\r
1166 }\r
95276127 1167 }\r
1168\r
e3dcffcc 1169 if (!SimTxtOutInstalled && (ConOutSelected || NullRemaining)) {\r
1170 Status = gBS->InstallProtocolInterface (\r
1171 &TerminalDevice->Handle,\r
1172 &gEfiSimpleTextOutProtocolGuid,\r
1173 EFI_NATIVE_INTERFACE,\r
1174 &TerminalDevice->SimpleTextOutput\r
1175 );\r
1176 if (EFI_ERROR (Status)) {\r
1177 goto Error;\r
1178 }\r
1179 }\r
95276127 1180 if (DefaultNode != NULL) {\r
1181 FreePool (DefaultNode);\r
1182 }\r
1183\r
1184 return EFI_SUCCESS;\r
1185\r
1186ReportError:\r
1187 //\r
1188 // Report error code before exiting\r
1189 //\r
e3dcffcc 1190 DevicePath = ParentDevicePath;\r
95276127 1191 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1192 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
f9876ecf 1193 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\r
95276127 1194 DevicePath\r
1195 );\r
1196\r
1197Error:\r
1198 //\r
1199 // Use the Stop() function to free all resources allocated in Start()\r
1200 //\r
1201 if (TerminalDevice != NULL) {\r
1202\r
1203 if (TerminalDevice->Handle != NULL) {\r
1204 This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
1205 } else {\r
1206\r
1207 if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
1208 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
1209 }\r
1210\r
f0368006
RN
1211 if (TerminalDevice->TimerEvent != NULL) {\r
1212 gBS->CloseEvent (TerminalDevice->TimerEvent);\r
1213 }\r
1214\r
95276127 1215 if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
1216 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
1217 }\r
1218\r
66aa04e4 1219 if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
1220 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
1221 }\r
1222\r
1223 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
1224\r
5c998646 1225 if (TerminalDevice->RawFiFo != NULL) {\r
1226 FreePool (TerminalDevice->RawFiFo);\r
1227 }\r
1228 if (TerminalDevice->UnicodeFiFo != NULL) {\r
1229 FreePool (TerminalDevice->UnicodeFiFo);\r
1230 }\r
1231 if (TerminalDevice->EfiKeyFiFo != NULL) {\r
1232 FreePool (TerminalDevice->EfiKeyFiFo);\r
1233 }\r
1234\r
95276127 1235 if (TerminalDevice->ControllerNameTable != NULL) {\r
1236 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1237 }\r
1238\r
1239 if (TerminalDevice->DevicePath != NULL) {\r
1240 FreePool (TerminalDevice->DevicePath);\r
1241 }\r
1242\r
79d07c66 1243 if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
1244 FreePool (TerminalDevice->TerminalConsoleModeData);\r
1245 }\r
1246\r
95276127 1247 FreePool (TerminalDevice);\r
1248 }\r
1249 }\r
1250\r
1251 if (DefaultNode != NULL) {\r
1252 FreePool (DefaultNode);\r
1253 }\r
1254\r
1255 This->Stop (This, Controller, 0, NULL);\r
1256\r
1257 return Status;\r
1258}\r
1259\r
e49ef433 1260/**\r
ab76200c 1261 Stop this driver on Controller by closing Simple Text In, Simple Text\r
8fd98315 1262 In Ex, Simple Text Out protocol, and removing parent device path from\r
677fdb90 1263 Console Device Environment Variables.\r
e49ef433 1264\r
8fd98315 1265 @param This Protocol instance pointer.\r
ab76200c 1266 @param Controller Handle of device to stop driver on\r
8fd98315 1267 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
1268 children is zero stop the entire bus driver.\r
1269 @param ChildHandleBuffer List of Child Handles to Stop.\r
e49ef433 1270\r
ab76200c 1271 @retval EFI_SUCCESS This driver is removed Controller.\r
8fd98315 1272 @retval other This driver could not be removed from this device.\r
e49ef433 1273\r
1274**/\r
95276127 1275EFI_STATUS\r
1276EFIAPI\r
1277TerminalDriverBindingStop (\r
1278 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1279 IN EFI_HANDLE Controller,\r
1280 IN UINTN NumberOfChildren,\r
1281 IN EFI_HANDLE *ChildHandleBuffer\r
1282 )\r
95276127 1283{\r
1284 EFI_STATUS Status;\r
1285 UINTN Index;\r
1286 BOOLEAN AllChildrenStopped;\r
1287 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
1288 TERMINAL_DEV *TerminalDevice;\r
1289 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1290 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
1291 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1292\r
1293 Status = gBS->HandleProtocol (\r
1294 Controller,\r
1295 &gEfiDevicePathProtocolGuid,\r
1296 (VOID **) &DevicePath\r
1297 );\r
1298 if (EFI_ERROR (Status)) {\r
1299 return Status;\r
1300 }\r
95276127 1301\r
1302 //\r
1303 // Complete all outstanding transactions to Controller.\r
1304 // Don't allow any new transaction to Controller to be started.\r
1305 //\r
1306 if (NumberOfChildren == 0) {\r
1307 //\r
1308 // Close the bus driver\r
1309 //\r
1310 Status = gBS->OpenProtocol (\r
1311 Controller,\r
1312 &gEfiCallerIdGuid,\r
1313 (VOID **) &ParentDevicePath,\r
1314 This->DriverBindingHandle,\r
1315 Controller,\r
1316 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1317 );\r
1318 if (!EFI_ERROR (Status)) {\r
1319 //\r
1320 // Remove Parent Device Path from\r
1321 // the Console Device Environment Variables\r
1322 //\r
ff37790d
A
1323 TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
1324 TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
1325 TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 1326\r
1327 //\r
1328 // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
1329 //\r
1330 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1331 Controller,\r
1332 &gEfiCallerIdGuid,\r
1333 ParentDevicePath,\r
1334 NULL\r
1335 );\r
1336\r
1337 //\r
1338 // Free the ParentDevicePath that was duplicated in Start()\r
1339 //\r
1340 if (!EFI_ERROR (Status)) {\r
1341 FreePool (ParentDevicePath);\r
1342 }\r
1343 }\r
1344\r
1345 gBS->CloseProtocol (\r
1346 Controller,\r
1347 &gEfiSerialIoProtocolGuid,\r
1348 This->DriverBindingHandle,\r
1349 Controller\r
1350 );\r
1351\r
1352 gBS->CloseProtocol (\r
1353 Controller,\r
1354 &gEfiDevicePathProtocolGuid,\r
1355 This->DriverBindingHandle,\r
1356 Controller\r
1357 );\r
1358\r
1359 return EFI_SUCCESS;\r
1360 }\r
1361\r
1362 AllChildrenStopped = TRUE;\r
1363\r
1364 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1365\r
1366 Status = gBS->OpenProtocol (\r
1367 ChildHandleBuffer[Index],\r
1368 &gEfiSimpleTextOutProtocolGuid,\r
1369 (VOID **) &SimpleTextOutput,\r
1370 This->DriverBindingHandle,\r
1371 ChildHandleBuffer[Index],\r
1372 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1373 );\r
1374 if (!EFI_ERROR (Status)) {\r
1375\r
1376 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1377\r
1378 gBS->CloseProtocol (\r
1379 Controller,\r
1380 &gEfiSerialIoProtocolGuid,\r
1381 This->DriverBindingHandle,\r
1382 ChildHandleBuffer[Index]\r
1383 );\r
1384\r
1385 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1386 ChildHandleBuffer[Index],\r
1387 &gEfiSimpleTextInProtocolGuid,\r
1388 &TerminalDevice->SimpleInput,\r
66aa04e4 1389 &gEfiSimpleTextInputExProtocolGuid,\r
1390 &TerminalDevice->SimpleInputEx,\r
95276127 1391 &gEfiSimpleTextOutProtocolGuid,\r
1392 &TerminalDevice->SimpleTextOutput,\r
1393 &gEfiDevicePathProtocolGuid,\r
1394 TerminalDevice->DevicePath,\r
1395 NULL\r
1396 );\r
1397 if (EFI_ERROR (Status)) {\r
1398 gBS->OpenProtocol (\r
1399 Controller,\r
1400 &gEfiSerialIoProtocolGuid,\r
1401 (VOID **) &SerialIo,\r
1402 This->DriverBindingHandle,\r
1403 ChildHandleBuffer[Index],\r
1404 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1405 );\r
1406 } else {\r
1407\r
1408 if (TerminalDevice->ControllerNameTable != NULL) {\r
1409 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1410 }\r
1411\r
f0368006 1412 gBS->CloseEvent (TerminalDevice->TimerEvent);\r
95276127 1413 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
1414 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
66aa04e4 1415 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
1416 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
95276127 1417 FreePool (TerminalDevice->DevicePath);\r
79d07c66 1418 if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
1419 FreePool (TerminalDevice->TerminalConsoleModeData);\r
1420 }\r
95276127 1421 FreePool (TerminalDevice);\r
1422 }\r
1423 }\r
1424\r
1425 if (EFI_ERROR (Status)) {\r
1426 AllChildrenStopped = FALSE;\r
1427 }\r
1428 }\r
1429\r
1430 if (!AllChildrenStopped) {\r
1431 return EFI_DEVICE_ERROR;\r
1432 }\r
1433\r
1434 return EFI_SUCCESS;\r
1435}\r
1436\r
8fd98315 1437/**\r
1438 Update terminal device path in Console Device Environment Variables.\r
1439\r
1440 @param VariableName The Console Device Environment Variable.\r
11baadb6 1441 @param ParentDevicePath The terminal device path to be updated.\r
8fd98315 1442\r
8fd98315 1443**/\r
95276127 1444VOID\r
1445TerminalUpdateConsoleDevVariable (\r
1446 IN CHAR16 *VariableName,\r
1447 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
1448 )\r
1449{\r
1450 EFI_STATUS Status;\r
5070befc 1451 UINTN NameSize;\r
95276127 1452 UINTN VariableSize;\r
1453 UINT8 TerminalType;\r
1454 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1455 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1456 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
5070befc 1457 EDKII_SET_VARIABLE_STATUS *SetVariableStatus;\r
95276127 1458\r
95276127 1459 //\r
1460 // Get global variable and its size according to the name given.\r
1461 //\r
f01b91ae 1462 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
e3dcffcc 1463 if (Variable == NULL) {\r
1464 return;\r
1465 }\r
1466\r
95276127 1467 //\r
1468 // Append terminal device path onto the variable.\r
1469 //\r
6e3227c8 1470 for (TerminalType = PCANSITYPE; TerminalType <= TTYTERMTYPE; TerminalType++) {\r
95276127 1471 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1472 NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
4b0786b4 1473 ASSERT (NewVariable != NULL);\r
95276127 1474 if (Variable != NULL) {\r
1475 FreePool (Variable);\r
1476 }\r
1477\r
1478 if (TempDevicePath != NULL) {\r
1479 FreePool (TempDevicePath);\r
1480 }\r
1481\r
1482 Variable = NewVariable;\r
1483 }\r
1484\r
1485 VariableSize = GetDevicePathSize (Variable);\r
1486\r
1487 Status = gRT->SetVariable (\r
1488 VariableName,\r
1489 &gEfiGlobalVariableGuid,\r
1490 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1491 VariableSize,\r
1492 Variable\r
1493 );\r
5070befc
RN
1494\r
1495 if (EFI_ERROR (Status)) {\r
1496 NameSize = StrSize (VariableName);\r
1497 SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize);\r
1498 if (SetVariableStatus != NULL) {\r
1499 CopyGuid (&SetVariableStatus->Guid, &gEfiGlobalVariableGuid);\r
1500 SetVariableStatus->NameSize = NameSize;\r
1501 SetVariableStatus->DataSize = VariableSize;\r
1502 SetVariableStatus->SetStatus = Status;\r
1503 SetVariableStatus->Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
1504 CopyMem (SetVariableStatus + 1, VariableName, NameSize);\r
1505 CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Variable, VariableSize);\r
1506\r
1507 REPORT_STATUS_CODE_EX (\r
1508 EFI_ERROR_CODE,\r
1509 PcdGet32 (PcdErrorCodeSetVariable),\r
1510 0,\r
1511 NULL,\r
1512 &gEdkiiStatusCodeDataTypeVariableGuid,\r
1513 SetVariableStatus,\r
1514 sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize\r
1515 );\r
1516\r
1517 FreePool (SetVariableStatus);\r
1518 }\r
1519 }\r
1520\r
95276127 1521 FreePool (Variable);\r
1522\r
1523 return ;\r
1524}\r
1525\r
e49ef433 1526\r
1527/**\r
8fd98315 1528 Remove terminal device path from Console Device Environment Variables.\r
e49ef433 1529\r
8fd98315 1530 @param VariableName Console Device Environment Variables.\r
11baadb6 1531 @param ParentDevicePath The terminal device path to be updated.\r
e49ef433 1532\r
e49ef433 1533**/\r
95276127 1534VOID\r
1535TerminalRemoveConsoleDevVariable (\r
1536 IN CHAR16 *VariableName,\r
1537 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
1538 )\r
95276127 1539{\r
1540 EFI_STATUS Status;\r
1541 BOOLEAN FoundOne;\r
1542 BOOLEAN Match;\r
1543 UINTN VariableSize;\r
1544 UINTN InstanceSize;\r
1545 UINT8 TerminalType;\r
1546 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
1547 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1548 EFI_DEVICE_PATH_PROTOCOL *OriginalVariable;\r
1549 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1550 EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;\r
1551 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1552\r
95276127 1553 Instance = NULL;\r
1554\r
1555 //\r
1556 // Get global variable and its size according to the name given.\r
1557 //\r
f01b91ae 1558 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
95276127 1559 if (Variable == NULL) {\r
1560 return ;\r
1561 }\r
1562\r
1563 FoundOne = FALSE;\r
1564 OriginalVariable = Variable;\r
1565 NewVariable = NULL;\r
1566\r
1567 //\r
1568 // Get first device path instance from Variable\r
1569 //\r
1570 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1571 if (Instance == NULL) {\r
1572 FreePool (OriginalVariable);\r
1573 return ;\r
1574 }\r
1575 //\r
1576 // Loop through all the device path instances of Variable\r
1577 //\r
1578 do {\r
1579 //\r
1580 // Loop through all the terminal types that this driver supports\r
1581 //\r
1582 Match = FALSE;\r
6e3227c8 1583 for (TerminalType = PCANSITYPE; TerminalType <= TTYTERMTYPE; TerminalType++) {\r
95276127 1584\r
1585 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1586\r
1587 //\r
11baadb6 1588 // Compare the generated device path to the current device path instance\r
95276127 1589 //\r
1590 if (TempDevicePath != NULL) {\r
1591 if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
1592 Match = TRUE;\r
1593 FoundOne = TRUE;\r
1594 }\r
1595\r
1596 FreePool (TempDevicePath);\r
1597 }\r
1598 }\r
1599 //\r
1600 // If a match was not found, then keep the current device path instance\r
1601 //\r
1602 if (!Match) {\r
1603 SavedNewVariable = NewVariable;\r
1604 NewVariable = AppendDevicePathInstance (NewVariable, Instance);\r
1605 if (SavedNewVariable != NULL) {\r
1606 FreePool (SavedNewVariable);\r
1607 }\r
1608 }\r
1609 //\r
1610 // Get next device path instance from Variable\r
1611 //\r
1612 FreePool (Instance);\r
1613 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1614 } while (Instance != NULL);\r
1615\r
1616 FreePool (OriginalVariable);\r
1617\r
1618 if (FoundOne) {\r
1619 VariableSize = GetDevicePathSize (NewVariable);\r
1620\r
1621 Status = gRT->SetVariable (\r
1622 VariableName,\r
1623 &gEfiGlobalVariableGuid,\r
1624 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1625 VariableSize,\r
1626 NewVariable\r
1627 );\r
5070befc
RN
1628 //\r
1629 // Shrinking variable with existing variable driver implementation shouldn't fail.\r
1630 //\r
1631 ASSERT_EFI_ERROR (Status);\r
95276127 1632 }\r
1633\r
1634 if (NewVariable != NULL) {\r
1635 FreePool (NewVariable);\r
1636 }\r
1637\r
1638 return ;\r
1639}\r
1640\r
8fd98315 1641/**\r
11baadb6 1642 Build terminal device path according to terminal type.\r
8fd98315 1643\r
1644 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.\r
11baadb6 1645 @param ParentDevicePath Parent device path.\r
8fd98315 1646 @param TerminalDevicePath Returned terminal device path, if building successfully.\r
1647\r
1648 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.\r
1649 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.\r
1650 @retval EFI_SUCCESS Build terminal device path successfully.\r
1651\r
1652**/\r
95276127 1653EFI_STATUS\r
1654SetTerminalDevicePath (\r
1655 IN UINT8 TerminalType,\r
1656 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
1657 OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath\r
1658 )\r
1659{\r
1660 VENDOR_DEVICE_PATH Node;\r
1661\r
1662 *TerminalDevicePath = NULL;\r
1663 Node.Header.Type = MESSAGING_DEVICE_PATH;\r
1664 Node.Header.SubType = MSG_VENDOR_DP;\r
1665\r
1666 //\r
ab76200c 1667 // Generate terminal device path node according to terminal type.\r
95276127 1668 //\r
1669 switch (TerminalType) {\r
1670\r
e49ef433 1671 case PCANSITYPE:\r
ab76200c 1672 CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
95276127 1673 break;\r
1674\r
e49ef433 1675 case VT100TYPE:\r
ab76200c 1676 CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
95276127 1677 break;\r
1678\r
e49ef433 1679 case VT100PLUSTYPE:\r
ab76200c 1680 CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
95276127 1681 break;\r
1682\r
e49ef433 1683 case VTUTF8TYPE:\r
ab76200c 1684 CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
95276127 1685 break;\r
1686\r
6e3227c8
RF
1687 case TTYTERMTYPE:\r
1688 CopyGuid (&Node.Guid, &gEfiTtyTermGuid);\r
1689 break;\r
1690\r
95276127 1691 default:\r
1692 return EFI_UNSUPPORTED;\r
95276127 1693 }\r
1694\r
ab76200c 1695 //\r
1696 // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
1697 //\r
95276127 1698 SetDevicePathNodeLength (\r
1699 &Node.Header,\r
1700 sizeof (VENDOR_DEVICE_PATH)\r
1701 );\r
ab76200c 1702\r
95276127 1703 //\r
ab76200c 1704 // Append the terminal node onto parent device path\r
95276127 1705 // to generate a complete terminal device path.\r
1706 //\r
1707 *TerminalDevicePath = AppendDevicePathNode (\r
1708 ParentDevicePath,\r
1709 (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
1710 );\r
1711 if (*TerminalDevicePath == NULL) {\r
1712 return EFI_OUT_OF_RESOURCES;\r
1713 }\r
1714\r
1715 return EFI_SUCCESS;\r
1716}\r
1717\r
97a079ed
A
1718/**\r
1719 The user Entry Point for module Terminal. The user code starts with this function.\r
1720\r
ab76200c 1721 @param ImageHandle The firmware allocated handle for the EFI image.\r
1722 @param SystemTable A pointer to the EFI System Table.\r
fb0b259e 1723\r
97a079ed
A
1724 @retval EFI_SUCCESS The entry point is executed successfully.\r
1725 @retval other Some error occurs when executing this entry point.\r
1726\r
1727**/\r
1728EFI_STATUS\r
1729EFIAPI\r
1730InitializeTerminal(\r
1731 IN EFI_HANDLE ImageHandle,\r
1732 IN EFI_SYSTEM_TABLE *SystemTable\r
1733 )\r
1734{\r
1735 EFI_STATUS Status;\r
1736\r
1737 //\r
1738 // Install driver model protocol(s).\r
1739 //\r
5bca971e 1740 Status = EfiLibInstallDriverBindingComponentName2 (\r
97a079ed
A
1741 ImageHandle,\r
1742 SystemTable,\r
1743 &gTerminalDriverBinding,\r
1744 ImageHandle,\r
1745 &gTerminalComponentName,\r
5bca971e 1746 &gTerminalComponentName2\r
97a079ed
A
1747 );\r
1748 ASSERT_EFI_ERROR (Status);\r
1749\r
97a079ed
A
1750 return Status;\r
1751}\r
f1aec6cc 1752\r
1753/**\r
1754 Check if the device supports hot-plug through its device path.\r
1755\r
1756 This function could be updated to check more types of Hot Plug devices.\r
1757 Currently, it checks USB and PCCard device.\r
1758\r
1759 @param DevicePath Pointer to device's device path.\r
1760\r
1761 @retval TRUE The devcie is a hot-plug device\r
1762 @retval FALSE The devcie is not a hot-plug device.\r
1763\r
1764**/\r
1765BOOLEAN\r
1766IsHotPlugDevice (\r
1767 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1768 )\r
1769{\r
1770 EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
1771\r
1772 CheckDevicePath = DevicePath;\r
1773 while (!IsDevicePathEnd (CheckDevicePath)) {\r
1774 //\r
1775 // Check device whether is hot plug device or not throught Device Path\r
e3dcffcc 1776 //\r
f1aec6cc 1777 if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
1778 (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
1779 DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
1780 DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
1781 //\r
1782 // If Device is USB device\r
1783 //\r
1784 return TRUE;\r
1785 }\r
1786 if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
1787 (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
1788 //\r
1789 // If Device is PCCard\r
1790 //\r
1791 return TRUE;\r
1792 }\r
e3dcffcc 1793\r
f1aec6cc 1794 CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
1795 }\r
1796\r
1797 return FALSE;\r
1798}\r
1799\r