]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
MdeModulePkg TerminalDxe: Execute key notify func at TPL_CALLBACK
[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
47b612db 5Copyright (c) 2006 - 2016, 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
47b612db 78 NULL, // EfiKeyFiFoForNotify\r
5c998646 79\r
6b88ceec 80 NULL, // ControllerNameTable\r
f0368006 81 NULL, // TimerEvent\r
11baadb6 82 NULL, // TwoSecondTimeOut\r
6b88ceec
A
83 INPUT_STATE_DEFAULT,\r
84 RESET_STATE_DEFAULT,\r
014f93ac
RF
85 {\r
86 0,\r
87 0,\r
88 0\r
89 },\r
90 0,\r
66aa04e4 91 FALSE,\r
92 { // SimpleTextInputEx\r
93 TerminalConInResetEx,\r
94 TerminalConInReadKeyStrokeEx,\r
95 NULL,\r
96 TerminalConInSetState,\r
97 TerminalConInRegisterKeyNotify,\r
98 TerminalConInUnregisterKeyNotify,\r
99 },\r
11baadb6 100 { // NotifyList\r
66aa04e4 101 NULL,\r
102 NULL,\r
47b612db
SZ
103 },\r
104 NULL // KeyNotifyProcessEvent\r
6b88ceec
A
105};\r
106\r
79d07c66 107TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
108 {100, 31},\r
109 //\r
110 // New modes can be added here.\r
79d07c66 111 //\r
79d07c66 112};\r
113\r
8fd98315 114/**\r
677fdb90 115 Test to see if this driver supports Controller.\r
8fd98315 116\r
117 @param This Protocol instance pointer.\r
ab76200c 118 @param Controller Handle of device to test\r
8fd98315 119 @param RemainingDevicePath Optional parameter use to pick a specific child\r
120 device to start.\r
121\r
ab76200c 122 @retval EFI_SUCCESS This driver supports this device.\r
123 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
124 @retval other This driver does not support this device.\r
6b88ceec 125\r
8fd98315 126**/\r
95276127 127EFI_STATUS\r
128EFIAPI\r
129TerminalDriverBindingSupported (\r
130 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
131 IN EFI_HANDLE Controller,\r
132 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
137 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
138 VENDOR_DEVICE_PATH *Node;\r
139\r
140 //\r
141 // If remaining device path is not NULL, then make sure it is a\r
142 // device path that describes a terminal communications protocol.\r
143 //\r
144 if (RemainingDevicePath != NULL) {\r
95276127 145 //\r
e3dcffcc 146 // Check if RemainingDevicePath is the End of Device Path Node,\r
af4a6385 147 // if yes, go on checking other conditions\r
95276127 148 //\r
af4a6385 149 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
150 //\r
151 // If RemainingDevicePath isn't the End of Device Path Node,\r
152 // check its validation\r
153 //\r
154 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
e3dcffcc 155\r
af4a6385 156 if (Node->Header.Type != MESSAGING_DEVICE_PATH ||\r
157 Node->Header.SubType != MSG_VENDOR_DP ||\r
158 DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {\r
e3dcffcc 159\r
af4a6385 160 return EFI_UNSUPPORTED;\r
e3dcffcc 161\r
af4a6385 162 }\r
163 //\r
6e3227c8 164 // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types\r
af4a6385 165 //\r
166 if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
167 !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
168 !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
6e3227c8
RF
169 !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid) &&\r
170 !CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
e3dcffcc 171\r
af4a6385 172 return EFI_UNSUPPORTED;\r
173 }\r
95276127 174 }\r
175 }\r
176 //\r
177 // Open the IO Abstraction(s) needed to perform the supported test\r
af4a6385 178 // The Controller must support the Serial I/O Protocol.\r
179 // This driver is a bus driver with at most 1 child device, so it is\r
180 // ok for it to be already started.\r
95276127 181 //\r
182 Status = gBS->OpenProtocol (\r
183 Controller,\r
af4a6385 184 &gEfiSerialIoProtocolGuid,\r
185 (VOID **) &SerialIo,\r
95276127 186 This->DriverBindingHandle,\r
187 Controller,\r
188 EFI_OPEN_PROTOCOL_BY_DRIVER\r
189 );\r
190 if (Status == EFI_ALREADY_STARTED) {\r
191 return EFI_SUCCESS;\r
192 }\r
193\r
194 if (EFI_ERROR (Status)) {\r
195 return Status;\r
196 }\r
197\r
af4a6385 198 //\r
199 // Close the I/O Abstraction(s) used to perform the supported test\r
200 //\r
95276127 201 gBS->CloseProtocol (\r
202 Controller,\r
af4a6385 203 &gEfiSerialIoProtocolGuid,\r
95276127 204 This->DriverBindingHandle,\r
205 Controller\r
206 );\r
207\r
208 //\r
af4a6385 209 // Open the EFI Device Path protocol needed to perform the supported test\r
95276127 210 //\r
211 Status = gBS->OpenProtocol (\r
212 Controller,\r
af4a6385 213 &gEfiDevicePathProtocolGuid,\r
214 (VOID **) &ParentDevicePath,\r
95276127 215 This->DriverBindingHandle,\r
216 Controller,\r
217 EFI_OPEN_PROTOCOL_BY_DRIVER\r
218 );\r
219 if (Status == EFI_ALREADY_STARTED) {\r
220 return EFI_SUCCESS;\r
221 }\r
222\r
223 if (EFI_ERROR (Status)) {\r
224 return Status;\r
225 }\r
af4a6385 226\r
95276127 227 //\r
af4a6385 228 // Close protocol, don't use device path protocol in the Support() function\r
95276127 229 //\r
230 gBS->CloseProtocol (\r
231 Controller,\r
af4a6385 232 &gEfiDevicePathProtocolGuid,\r
95276127 233 This->DriverBindingHandle,\r
234 Controller\r
235 );\r
236\r
237 return Status;\r
238}\r
239\r
e3dcffcc 240/**\r
241 Build the terminal device path for the child device according to the\r
242 terminal type.\r
243\r
244 @param ParentDevicePath Parent device path.\r
245 @param RemainingDevicePath A specific child device.\r
246\r
247 @return The child device path built.\r
248\r
249**/\r
250EFI_DEVICE_PATH_PROTOCOL*\r
251EFIAPI\r
252BuildTerminalDevpath (\r
253 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
254 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
255 )\r
256{\r
257 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
258 UINT8 TerminalType;\r
259 VENDOR_DEVICE_PATH *Node;\r
260 EFI_STATUS Status;\r
261\r
262 TerminalDevicePath = NULL;\r
e3dcffcc 263\r
264 //\r
265 // Use the RemainingDevicePath to determine the terminal type\r
266 //\r
267 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
268 if (Node == NULL) {\r
cf1e634b 269 TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
e3dcffcc 270\r
271 } else if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
272\r
273 TerminalType = PCANSITYPE;\r
274\r
275 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
276\r
277 TerminalType = VT100TYPE;\r
278\r
279 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
280\r
281 TerminalType = VT100PLUSTYPE;\r
282\r
283 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
284\r
285 TerminalType = VTUTF8TYPE;\r
286\r
6e3227c8
RF
287 } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
288\r
289 TerminalType = TTYTERMTYPE;\r
290\r
e3dcffcc 291 } else {\r
292 return NULL;\r
293 }\r
294\r
295 //\r
296 // Build the device path for the child device\r
297 //\r
298 Status = SetTerminalDevicePath (\r
299 TerminalType,\r
300 ParentDevicePath,\r
301 &TerminalDevicePath\r
302 );\r
303 if (EFI_ERROR (Status)) {\r
304 return NULL;\r
305 }\r
306 return TerminalDevicePath;\r
307}\r
308\r
309/**\r
310 Compare a device path data structure to that of all the nodes of a\r
311 second device path instance.\r
312\r
313 @param Multi A pointer to a multi-instance device path data structure.\r
314 @param Single A pointer to a single-instance device path data structure.\r
315\r
316 @retval TRUE If the Single is contained within Multi.\r
317 @retval FALSE The Single is not match within Multi.\r
318\r
319**/\r
320BOOLEAN\r
321MatchDevicePaths (\r
322 IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
323 IN EFI_DEVICE_PATH_PROTOCOL *Single\r
324 )\r
325{\r
326 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
327 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
328 UINTN Size;\r
329\r
330 DevicePath = Multi;\r
331 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
332 //\r
333 // Search for the match of 'Single' in 'Multi'\r
334 //\r
335 while (DevicePathInst != NULL) {\r
336 //\r
337 // If the single device path is found in multiple device paths,\r
338 // return success\r
339 //\r
340 if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
341 FreePool (DevicePathInst);\r
342 return TRUE;\r
343 }\r
344\r
345 FreePool (DevicePathInst);\r
346 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
347 }\r
348\r
349 return FALSE;\r
350}\r
351\r
352/**\r
353 Check whether the terminal device path is in the global variable.\r
354\r
355 @param VariableName Pointer to one global variable.\r
356 @param TerminalDevicePath Pointer to the terminal device's device path.\r
357\r
358 @retval TRUE The devcie is in the global variable.\r
359 @retval FALSE The devcie is not in the global variable.\r
360\r
361**/\r
362BOOLEAN\r
363IsTerminalInConsoleVariable (\r
364 IN CHAR16 *VariableName,\r
365 IN EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath\r
366 )\r
367{\r
368 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
369 BOOLEAN ReturnFlag;\r
370\r
371 //\r
372 // Get global variable and its size according to the name given.\r
373 //\r
f01b91ae 374 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
e3dcffcc 375 if (Variable == NULL) {\r
376 return FALSE;\r
377 }\r
378\r
379 //\r
380 // Check whether the terminal device path is one of the variable instances.\r
381 //\r
382 ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
383\r
384 FreePool (Variable);\r
385\r
386 return ReturnFlag;\r
387}\r
388\r
389/**\r
390 Free notify functions list.\r
391\r
392 @param ListHead The list head\r
393\r
394 @retval EFI_SUCCESS Free the notify list successfully.\r
395 @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
396\r
397**/\r
398EFI_STATUS\r
399TerminalFreeNotifyList (\r
400 IN OUT LIST_ENTRY *ListHead\r
401 )\r
402{\r
403 TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
404\r
405 if (ListHead == NULL) {\r
406 return EFI_INVALID_PARAMETER;\r
407 }\r
408 while (!IsListEmpty (ListHead)) {\r
409 NotifyNode = CR (\r
410 ListHead->ForwardLink,\r
411 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
412 NotifyEntry,\r
413 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
414 );\r
415 RemoveEntryList (ListHead->ForwardLink);\r
416 FreePool (NotifyNode);\r
417 }\r
418\r
419 return EFI_SUCCESS;\r
420}\r
421\r
79d07c66 422/**\r
423 Initialize all the text modes which the terminal console supports.\r
424\r
425 It returns information for available text modes that the terminal can support.\r
426\r
427 @param[out] TextModeCount The total number of text modes that terminal console supports.\r
428 @param[out] TextModeData The buffer to the text modes column and row information.\r
429 Caller is responsible to free it when it's non-NULL.\r
430\r
431 @retval EFI_SUCCESS The supporting mode information is returned.\r
432 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
433\r
434**/\r
435EFI_STATUS\r
436InitializeTerminalConsoleTextMode (\r
437 OUT UINTN *TextModeCount,\r
438 OUT TERMINAL_CONSOLE_MODE_DATA **TextModeData\r
439 )\r
440{\r
441 UINTN Index;\r
442 UINTN Count;\r
443 TERMINAL_CONSOLE_MODE_DATA *ModeBuffer;\r
444 TERMINAL_CONSOLE_MODE_DATA *NewModeBuffer;\r
445 UINTN ValidCount;\r
446 UINTN ValidIndex;\r
447 \r
448 if ((TextModeCount == NULL) || (TextModeData == NULL)) {\r
449 return EFI_INVALID_PARAMETER;\r
450 }\r
451 \r
79d07c66 452 Count = sizeof (mTerminalConsoleModeData) / sizeof (TERMINAL_CONSOLE_MODE_DATA);\r
79d07c66 453 \r
454 //\r
455 // Get defined mode buffer pointer.\r
456 //\r
457 ModeBuffer = mTerminalConsoleModeData;\r
458 \r
459 //\r
460 // Here we make sure that the final mode exposed does not include the duplicated modes,\r
461 // and does not include the invalid modes which exceed the max column and row.\r
462 // Reserve 2 modes for 80x25, 80x50 of terminal console.\r
463 //\r
464 NewModeBuffer = AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA) * (Count + 2));\r
465 ASSERT (NewModeBuffer != NULL);\r
466\r
467 //\r
468 // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
469 //\r
470 ValidCount = 0; \r
471\r
472 NewModeBuffer[ValidCount].Columns = 80;\r
473 NewModeBuffer[ValidCount].Rows = 25;\r
474 ValidCount++;\r
475\r
476 NewModeBuffer[ValidCount].Columns = 80;\r
477 NewModeBuffer[ValidCount].Rows = 50;\r
478 ValidCount++;\r
479 \r
480 //\r
481 // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.\r
482 //\r
483 for (Index = 0; Index < Count; Index++) {\r
484 if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0)) {\r
485 //\r
486 // Skip the pre-defined mode which is invalid.\r
487 //\r
488 continue;\r
489 }\r
490 for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {\r
491 if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&\r
492 (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {\r
493 //\r
494 // Skip the duplicated mode.\r
495 //\r
496 break;\r
497 }\r
498 }\r
499 if (ValidIndex == ValidCount) {\r
500 NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;\r
501 NewModeBuffer[ValidCount].Rows = ModeBuffer[Index].Rows;\r
502 ValidCount++;\r
503 }\r
504 }\r
505 \r
506 DEBUG_CODE (\r
507 for (Index = 0; Index < ValidCount; Index++) {\r
508 DEBUG ((EFI_D_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n", \r
509 Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows)); \r
510 }\r
511 );\r
512 \r
513 //\r
514 // Return valid mode count and mode information buffer.\r
515 //\r
516 *TextModeCount = ValidCount;\r
517 *TextModeData = NewModeBuffer;\r
518 return EFI_SUCCESS;\r
519}\r
e3dcffcc 520\r
e49ef433 521/**\r
ab76200c 522 Start this driver on Controller by opening a Serial IO protocol,\r
8fd98315 523 reading Device Path, and creating a child handle with a Simple Text In,\r
524 Simple Text In Ex and Simple Text Out protocol, and device path protocol.\r
525 And store Console Device Environment Variables.\r
e49ef433 526\r
8fd98315 527 @param This Protocol instance pointer.\r
ab76200c 528 @param Controller Handle of device to bind driver to\r
8fd98315 529 @param RemainingDevicePath Optional parameter use to pick a specific child\r
530 device to start.\r
e49ef433 531\r
ab76200c 532 @retval EFI_SUCCESS This driver is added to Controller.\r
533 @retval EFI_ALREADY_STARTED This driver is already running on Controller.\r
534 @retval other This driver does not support this device.\r
e49ef433 535\r
536**/\r
95276127 537EFI_STATUS\r
538EFIAPI\r
539TerminalDriverBindingStart (\r
540 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
541 IN EFI_HANDLE Controller,\r
542 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
543 )\r
95276127 544{\r
545 EFI_STATUS Status;\r
546 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
547 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
548 VENDOR_DEVICE_PATH *Node;\r
95276127 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
cf1e634b
HG
568 ConInSelected = FALSE;\r
569 ConOutSelected = FALSE;\r
f8fdf8cd 570 NullRemaining = FALSE;\r
e3dcffcc 571 SimTxtInInstalled = FALSE;\r
572 SimTxtOutInstalled = FALSE;\r
573 FirstEnter = FALSE;\r
95276127 574 //\r
575 // Get the Device Path Protocol to build the device path of the child device\r
576 //\r
577 Status = gBS->OpenProtocol (\r
578 Controller,\r
579 &gEfiDevicePathProtocolGuid,\r
580 (VOID **) &ParentDevicePath,\r
581 This->DriverBindingHandle,\r
582 Controller,\r
583 EFI_OPEN_PROTOCOL_BY_DRIVER\r
584 );\r
585 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
586 return Status;\r
587 }\r
95276127 588\r
589 //\r
590 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.\r
591 //\r
592 Status = gBS->OpenProtocol (\r
593 Controller,\r
594 &gEfiSerialIoProtocolGuid,\r
595 (VOID **) &SerialIo,\r
596 This->DriverBindingHandle,\r
597 Controller,\r
598 EFI_OPEN_PROTOCOL_BY_DRIVER\r
599 );\r
600 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
601 return Status;\r
602 }\r
603\r
604 if (Status != EFI_ALREADY_STARTED) {\r
605 //\r
e3dcffcc 606 // the serial I/O protocol never be opened before, it is the first\r
607 // time to start the serial Io controller\r
95276127 608 //\r
e3dcffcc 609 FirstEnter = TRUE;\r
95276127 610 }\r
e3dcffcc 611\r
95276127 612 //\r
e3dcffcc 613 // Serial I/O is not already open by this driver, then tag the handle\r
614 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
615 // StdErrDev variables with the list of possible terminal types on this\r
616 // serial port.\r
95276127 617 //\r
e3dcffcc 618 Status = gBS->OpenProtocol (\r
95276127 619 Controller,\r
e3dcffcc 620 &gEfiCallerIdGuid,\r
621 NULL,\r
622 This->DriverBindingHandle,\r
623 Controller,\r
624 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
95276127 625 );\r
e3dcffcc 626 if (EFI_ERROR (Status)) {\r
627 Status = gBS->InstallMultipleProtocolInterfaces (\r
628 &Controller,\r
629 &gEfiCallerIdGuid,\r
630 DuplicateDevicePath (ParentDevicePath),\r
631 NULL\r
632 );\r
633 if (EFI_ERROR (Status)) {\r
634 goto Error;\r
95276127 635 }\r
636\r
e3dcffcc 637 if (!IsHotPlugDevice (ParentDevicePath)) {\r
638 //\r
639 // if the serial device is a hot plug device, do not update the\r
640 // ConInDev, ConOutDev, and StdErrDev variables.\r
641 //\r
642 TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
643 TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
644 TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 645 }\r
646 }\r
e3dcffcc 647\r
648 //\r
649 // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols\r
95276127 650 //\r
e3dcffcc 651 // Simple In/Out Protocol will not be installed onto the handle if the\r
652 // device path to the handle is not present in the ConIn/ConOut\r
653 // environment variable. But If RemainingDevicePath is NULL, then always\r
654 // produce both Simple In and Simple Text Output Protocols. This is required\r
655 // for the connect all sequences to make sure all possible consoles are\r
656 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 657 //\r
658 if (RemainingDevicePath == NULL) {\r
e3dcffcc 659 NullRemaining = TRUE;\r
660 }\r
661\r
662 DevicePath = BuildTerminalDevpath (ParentDevicePath, RemainingDevicePath);\r
663 if (DevicePath != NULL) {\r
664 ConInSelected = IsTerminalInConsoleVariable (L"ConIn", DevicePath);\r
665 ConOutSelected = IsTerminalInConsoleVariable (L"ConOut", DevicePath);\r
666 FreePool (DevicePath);\r
667 } else {\r
668 goto Error;\r
669 }\r
670 //\r
671 // Not create the child terminal handle if both Simple In/In Ex and\r
672 // Simple text Out protocols are not required to be published\r
673 //\r
674 if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
675 goto Error;\r
676 }\r
677\r
678 //\r
679 // create the child terminal handle during first entry\r
680 //\r
681 if (FirstEnter) {\r
682 //\r
0a18956d 683 // First enther the start function\r
e3dcffcc 684 //\r
685 FirstEnter = FALSE;\r
686 //\r
687 // Make sure a child handle does not already exist. This driver can only\r
688 // produce one child per serial port.\r
689 //\r
690 Status = gBS->OpenProtocolInformation (\r
691 Controller,\r
692 &gEfiSerialIoProtocolGuid,\r
693 &OpenInfoBuffer,\r
694 &EntryCount\r
695 );\r
696 if (!EFI_ERROR (Status)) {\r
697 Status = EFI_SUCCESS;\r
698 for (Index = 0; Index < EntryCount; Index++) {\r
699 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
700 Status = EFI_ALREADY_STARTED;\r
701 }\r
702 }\r
703\r
704 FreePool (OpenInfoBuffer);\r
705 if (EFI_ERROR (Status)) {\r
706 goto Error;\r
707 }\r
708 }\r
709\r
710 //\r
cf1e634b 711 // If RemainingDevicePath is NULL, use default terminal type\r
e3dcffcc 712 //\r
713 if (RemainingDevicePath == NULL) {\r
188e4e84 714 TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
e3dcffcc 715 //\r
6e3227c8 716 // Must be between PCANSITYPE (0) and TTYTERMTYPE (4)\r
e3dcffcc 717 //\r
6e3227c8 718 ASSERT (TerminalType <= TTYTERMTYPE);\r
e3dcffcc 719 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
720 //\r
721 // If RemainingDevicePath isn't the End of Device Path Node,\r
722 // Use the RemainingDevicePath to determine the terminal type\r
723 //\r
724 Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
725 if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
726 TerminalType = PCANSITYPE;\r
727 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
728 TerminalType = VT100TYPE;\r
729 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
730 TerminalType = VT100PLUSTYPE;\r
731 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
732 TerminalType = VTUTF8TYPE;\r
6e3227c8
RF
733 } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
734 TerminalType = TTYTERMTYPE;\r
e3dcffcc 735 } else {\r
736 goto Error;\r
737 }\r
738 } else {\r
739 //\r
740 // If RemainingDevicePath is the End of Device Path Node,\r
741 // skip enumerate any device and return EFI_SUCESSS\r
742 //\r
743 return EFI_SUCCESS;\r
744 }\r
745\r
746 //\r
747 // Initialize the Terminal Dev\r
748 //\r
749 TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
750 if (TerminalDevice == NULL) {\r
95276127 751 Status = EFI_OUT_OF_RESOURCES;\r
752 goto Error;\r
753 }\r
754\r
e3dcffcc 755 TerminalDevice->TerminalType = TerminalType;\r
756 TerminalDevice->SerialIo = SerialIo;\r
757\r
758 InitializeListHead (&TerminalDevice->NotifyList);\r
759 Status = gBS->CreateEvent (\r
760 EVT_NOTIFY_WAIT,\r
761 TPL_NOTIFY,\r
762 TerminalConInWaitForKeyEx,\r
f0368006 763 TerminalDevice,\r
e3dcffcc 764 &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
765 );\r
766 if (EFI_ERROR (Status)) {\r
767 goto Error;\r
768 }\r
769\r
770 Status = gBS->CreateEvent (\r
771 EVT_NOTIFY_WAIT,\r
772 TPL_NOTIFY,\r
773 TerminalConInWaitForKey,\r
f0368006 774 TerminalDevice,\r
e3dcffcc 775 &TerminalDevice->SimpleInput.WaitForKey\r
776 );\r
777 if (EFI_ERROR (Status)) {\r
778 goto Error;\r
779 }\r
8fd98315 780 //\r
e3dcffcc 781 // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
782 // the pre-read pending characters.\r
8fd98315 783 //\r
e3dcffcc 784 TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
785 if (TerminalDevice->RawFiFo == NULL) {\r
786 goto Error;\r
787 }\r
788 TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
789 if (TerminalDevice->UnicodeFiFo == NULL) {\r
790 goto Error;\r
791 }\r
792 TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
793 if (TerminalDevice->EfiKeyFiFo == NULL) {\r
794 goto Error;\r
795 }\r
47b612db
SZ
796 TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
797 if (TerminalDevice->EfiKeyFiFoForNotify == 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
6ba44b86 815 Mode->ReceiveFifoDepth,\r
e3dcffcc 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
47b612db
SZ
1009 Status = gBS->CreateEvent (\r
1010 EVT_NOTIFY_SIGNAL,\r
1011 TPL_CALLBACK,\r
1012 KeyNotifyProcessHandler,\r
1013 TerminalDevice,\r
1014 &TerminalDevice->KeyNotifyProcessEvent\r
1015 );\r
1016 ASSERT_EFI_ERROR (Status);\r
1017\r
e3dcffcc 1018 Status = gBS->InstallProtocolInterface (\r
1019 &TerminalDevice->Handle,\r
1020 &gEfiDevicePathProtocolGuid,\r
1021 EFI_NATIVE_INTERFACE,\r
1022 TerminalDevice->DevicePath\r
1023 );\r
1024 if (EFI_ERROR (Status)) {\r
1025 goto Error;\r
1026 }\r
95276127 1027\r
95276127 1028 //\r
e3dcffcc 1029 // Register the Parent-Child relationship via\r
1030 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
95276127 1031 //\r
e3dcffcc 1032 Status = gBS->OpenProtocol (\r
1033 Controller,\r
1034 &gEfiSerialIoProtocolGuid,\r
1035 (VOID **) &TerminalDevice->SerialIo,\r
1036 This->DriverBindingHandle,\r
1037 TerminalDevice->Handle,\r
1038 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1039 );\r
1040 if (EFI_ERROR (Status)) {\r
1041 goto Error;\r
1042 }\r
95276127 1043 }\r
95276127 1044\r
3012ce5c 1045 //\r
e3dcffcc 1046 // Find the child handle, and get its TerminalDevice private data\r
3012ce5c 1047 //\r
e3dcffcc 1048 Status = gBS->OpenProtocolInformation (\r
1049 Controller,\r
1050 &gEfiSerialIoProtocolGuid,\r
1051 &OpenInfoBuffer,\r
1052 &EntryCount\r
1053 );\r
1054 if (!EFI_ERROR (Status)) {\r
1055 Status = EFI_NOT_FOUND;\r
1056 ASSERT (OpenInfoBuffer != NULL);\r
1057 for (Index = 0; Index < EntryCount; Index++) {\r
1058 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
1059 //\r
1060 // Find the child terminal handle.\r
1061 // Test whether the SimpleTxtIn and SimpleTxtOut have been published\r
1062 //\r
1063 Status = gBS->OpenProtocol (\r
1064 OpenInfoBuffer[Index].ControllerHandle,\r
1065 &gEfiSimpleTextInProtocolGuid,\r
1066 (VOID **) &SimpleTextInput,\r
1067 This->DriverBindingHandle,\r
1068 OpenInfoBuffer[Index].ControllerHandle,\r
1069 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1070 );\r
1071 if (!EFI_ERROR (Status)) {\r
1072 SimTxtInInstalled = TRUE;\r
1073 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
1074 }\r
3012ce5c 1075\r
e3dcffcc 1076 Status = gBS->OpenProtocol (\r
1077 OpenInfoBuffer[Index].ControllerHandle,\r
1078 &gEfiSimpleTextOutProtocolGuid,\r
1079 (VOID **) &SimpleTextOutput,\r
1080 This->DriverBindingHandle,\r
1081 OpenInfoBuffer[Index].ControllerHandle,\r
1082 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1083 );\r
1084 if (!EFI_ERROR (Status)) {\r
1085 SimTxtOutInstalled = TRUE;\r
1086 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1087 }\r
1088 Status = EFI_SUCCESS;\r
1089 break;\r
1090 }\r
1091 }\r
95276127 1092\r
e3dcffcc 1093 FreePool (OpenInfoBuffer);\r
1094 if (EFI_ERROR (Status)) {\r
1095 goto ReportError;\r
1096 }\r
1097 } else {\r
95276127 1098 goto ReportError;\r
1099 }\r
1100\r
e3dcffcc 1101 ASSERT (TerminalDevice != NULL);\r
1102 //\r
1103 // Only do the reset if the device path is in the Conout variable\r
1104 //\r
1105 if (ConInSelected && !SimTxtInInstalled) {\r
1106 Status = TerminalDevice->SimpleInput.Reset (\r
1107 &TerminalDevice->SimpleInput,\r
1108 FALSE\r
1109 );\r
1110 if (EFI_ERROR (Status)) {\r
1111 //\r
1112 // Need to report Error Code first\r
1113 //\r
1114 goto ReportError;\r
1115 }\r
95276127 1116 }\r
95276127 1117\r
95276127 1118 //\r
e3dcffcc 1119 // Only output the configure string to remote terminal if the device path\r
1120 // is in the Conout variable\r
95276127 1121 //\r
e3dcffcc 1122 if (ConOutSelected && !SimTxtOutInstalled) {\r
1123 Status = TerminalDevice->SimpleTextOutput.SetAttribute (\r
1124 &TerminalDevice->SimpleTextOutput,\r
1125 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
1126 );\r
1127 if (EFI_ERROR (Status)) {\r
1128 goto ReportError;\r
1129 }\r
5bca971e 1130\r
e3dcffcc 1131 Status = TerminalDevice->SimpleTextOutput.Reset (\r
1132 &TerminalDevice->SimpleTextOutput,\r
1133 FALSE\r
1134 );\r
1135 if (EFI_ERROR (Status)) {\r
1136 goto ReportError;\r
1137 }\r
95276127 1138\r
e3dcffcc 1139 Status = TerminalDevice->SimpleTextOutput.SetMode (\r
1140 &TerminalDevice->SimpleTextOutput,\r
1141 0\r
1142 );\r
1143 if (EFI_ERROR (Status)) {\r
1144 goto ReportError;\r
1145 }\r
5bca971e 1146\r
e3dcffcc 1147 Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
1148 &TerminalDevice->SimpleTextOutput,\r
1149 TRUE\r
1150 );\r
1151 if (EFI_ERROR (Status)) {\r
1152 goto ReportError;\r
1153 }\r
95276127 1154 }\r
f1aec6cc 1155\r
95276127 1156 //\r
e3dcffcc 1157 // Simple In/Out Protocol will not be installed onto the handle if the\r
1158 // device path to the handle is not present in the ConIn/ConOut\r
1159 // environment variable. But If RemainingDevicePath is NULL, then always\r
1160 // produce both Simple In and Simple Text Output Protocols. This is required\r
1161 // for the connect all sequences to make sure all possible consoles are\r
1162 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 1163 //\r
e3dcffcc 1164 if (!SimTxtInInstalled && (ConInSelected || NullRemaining)) {\r
1165 Status = gBS->InstallMultipleProtocolInterfaces (\r
1166 &TerminalDevice->Handle,\r
1167 &gEfiSimpleTextInProtocolGuid,\r
1168 &TerminalDevice->SimpleInput,\r
1169 &gEfiSimpleTextInputExProtocolGuid,\r
1170 &TerminalDevice->SimpleInputEx,\r
1171 NULL\r
1172 );\r
1173 if (EFI_ERROR (Status)) {\r
1174 goto Error;\r
1175 }\r
95276127 1176 }\r
1177\r
e3dcffcc 1178 if (!SimTxtOutInstalled && (ConOutSelected || NullRemaining)) {\r
1179 Status = gBS->InstallProtocolInterface (\r
1180 &TerminalDevice->Handle,\r
1181 &gEfiSimpleTextOutProtocolGuid,\r
1182 EFI_NATIVE_INTERFACE,\r
1183 &TerminalDevice->SimpleTextOutput\r
1184 );\r
1185 if (EFI_ERROR (Status)) {\r
1186 goto Error;\r
1187 }\r
1188 }\r
95276127 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
47b612db
SZ
1240 if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {\r
1241 FreePool (TerminalDevice->EfiKeyFiFoForNotify);\r
1242 }\r
1243 \r
95276127 1244 if (TerminalDevice->ControllerNameTable != NULL) {\r
1245 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1246 }\r
1247\r
1248 if (TerminalDevice->DevicePath != NULL) {\r
1249 FreePool (TerminalDevice->DevicePath);\r
1250 }\r
1251\r
79d07c66 1252 if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
1253 FreePool (TerminalDevice->TerminalConsoleModeData);\r
1254 }\r
1255\r
95276127 1256 FreePool (TerminalDevice);\r
1257 }\r
1258 }\r
1259\r
95276127 1260 This->Stop (This, Controller, 0, NULL);\r
1261\r
1262 return Status;\r
1263}\r
1264\r
e49ef433 1265/**\r
ab76200c 1266 Stop this driver on Controller by closing Simple Text In, Simple Text\r
8fd98315 1267 In Ex, Simple Text Out protocol, and removing parent device path from\r
677fdb90 1268 Console Device Environment Variables.\r
e49ef433 1269\r
8fd98315 1270 @param This Protocol instance pointer.\r
ab76200c 1271 @param Controller Handle of device to stop driver on\r
8fd98315 1272 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
1273 children is zero stop the entire bus driver.\r
1274 @param ChildHandleBuffer List of Child Handles to Stop.\r
e49ef433 1275\r
ab76200c 1276 @retval EFI_SUCCESS This driver is removed Controller.\r
8fd98315 1277 @retval other This driver could not be removed from this device.\r
e49ef433 1278\r
1279**/\r
95276127 1280EFI_STATUS\r
1281EFIAPI\r
1282TerminalDriverBindingStop (\r
1283 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1284 IN EFI_HANDLE Controller,\r
1285 IN UINTN NumberOfChildren,\r
1286 IN EFI_HANDLE *ChildHandleBuffer\r
1287 )\r
95276127 1288{\r
1289 EFI_STATUS Status;\r
1290 UINTN Index;\r
1291 BOOLEAN AllChildrenStopped;\r
1292 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
1293 TERMINAL_DEV *TerminalDevice;\r
1294 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1295 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
1296 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1297\r
1298 Status = gBS->HandleProtocol (\r
1299 Controller,\r
1300 &gEfiDevicePathProtocolGuid,\r
1301 (VOID **) &DevicePath\r
1302 );\r
1303 if (EFI_ERROR (Status)) {\r
1304 return Status;\r
1305 }\r
95276127 1306\r
1307 //\r
1308 // Complete all outstanding transactions to Controller.\r
1309 // Don't allow any new transaction to Controller to be started.\r
1310 //\r
1311 if (NumberOfChildren == 0) {\r
1312 //\r
1313 // Close the bus driver\r
1314 //\r
1315 Status = gBS->OpenProtocol (\r
1316 Controller,\r
1317 &gEfiCallerIdGuid,\r
1318 (VOID **) &ParentDevicePath,\r
1319 This->DriverBindingHandle,\r
1320 Controller,\r
1321 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1322 );\r
1323 if (!EFI_ERROR (Status)) {\r
1324 //\r
1325 // Remove Parent Device Path from\r
1326 // the Console Device Environment Variables\r
1327 //\r
ff37790d
A
1328 TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
1329 TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
1330 TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 1331\r
1332 //\r
1333 // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
1334 //\r
1335 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1336 Controller,\r
1337 &gEfiCallerIdGuid,\r
1338 ParentDevicePath,\r
1339 NULL\r
1340 );\r
1341\r
1342 //\r
1343 // Free the ParentDevicePath that was duplicated in Start()\r
1344 //\r
1345 if (!EFI_ERROR (Status)) {\r
1346 FreePool (ParentDevicePath);\r
1347 }\r
1348 }\r
1349\r
1350 gBS->CloseProtocol (\r
1351 Controller,\r
1352 &gEfiSerialIoProtocolGuid,\r
1353 This->DriverBindingHandle,\r
1354 Controller\r
1355 );\r
1356\r
1357 gBS->CloseProtocol (\r
1358 Controller,\r
1359 &gEfiDevicePathProtocolGuid,\r
1360 This->DriverBindingHandle,\r
1361 Controller\r
1362 );\r
1363\r
1364 return EFI_SUCCESS;\r
1365 }\r
1366\r
1367 AllChildrenStopped = TRUE;\r
1368\r
1369 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1370\r
1371 Status = gBS->OpenProtocol (\r
1372 ChildHandleBuffer[Index],\r
1373 &gEfiSimpleTextOutProtocolGuid,\r
1374 (VOID **) &SimpleTextOutput,\r
1375 This->DriverBindingHandle,\r
1376 ChildHandleBuffer[Index],\r
1377 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1378 );\r
1379 if (!EFI_ERROR (Status)) {\r
1380\r
1381 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1382\r
1383 gBS->CloseProtocol (\r
1384 Controller,\r
1385 &gEfiSerialIoProtocolGuid,\r
1386 This->DriverBindingHandle,\r
1387 ChildHandleBuffer[Index]\r
1388 );\r
1389\r
1390 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1391 ChildHandleBuffer[Index],\r
1392 &gEfiSimpleTextInProtocolGuid,\r
1393 &TerminalDevice->SimpleInput,\r
66aa04e4 1394 &gEfiSimpleTextInputExProtocolGuid,\r
1395 &TerminalDevice->SimpleInputEx,\r
95276127 1396 &gEfiSimpleTextOutProtocolGuid,\r
1397 &TerminalDevice->SimpleTextOutput,\r
1398 &gEfiDevicePathProtocolGuid,\r
1399 TerminalDevice->DevicePath,\r
1400 NULL\r
1401 );\r
1402 if (EFI_ERROR (Status)) {\r
1403 gBS->OpenProtocol (\r
1404 Controller,\r
1405 &gEfiSerialIoProtocolGuid,\r
1406 (VOID **) &SerialIo,\r
1407 This->DriverBindingHandle,\r
1408 ChildHandleBuffer[Index],\r
1409 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1410 );\r
1411 } else {\r
1412\r
1413 if (TerminalDevice->ControllerNameTable != NULL) {\r
1414 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1415 }\r
1416\r
f0368006 1417 gBS->CloseEvent (TerminalDevice->TimerEvent);\r
95276127 1418 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
1419 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
66aa04e4 1420 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
47b612db 1421 gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
66aa04e4 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