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