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