]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
update hotplug check logic
[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
fb0b259e 5Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
95276127 6All rights reserved. This program and the accompanying materials\r
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
36 &gEfiVTUTF8Guid\r
37};\r
38\r
39\r
204ba917 40TERMINAL_DEV mTerminalDevTemplate = {\r
6b88ceec
A
41 TERMINAL_DEV_SIGNATURE,\r
42 NULL,\r
43 0,\r
44 NULL,\r
45 NULL,\r
46 { // SimpleTextInput\r
47 TerminalConInReset,\r
48 TerminalConInReadKeyStroke,\r
49 NULL\r
50 },\r
51 { // SimpleTextOutput\r
52 TerminalConOutReset,\r
53 TerminalConOutOutputString,\r
54 TerminalConOutTestString,\r
55 TerminalConOutQueryMode,\r
56 TerminalConOutSetMode,\r
57 TerminalConOutSetAttribute,\r
58 TerminalConOutClearScreen,\r
59 TerminalConOutSetCursorPosition,\r
60 TerminalConOutEnableCursor,\r
61 NULL\r
62 },\r
63 { // SimpleTextOutputMode\r
64 1, // MaxMode\r
11baadb6 65 0, // Mode\r
6b88ceec
A
66 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
67 0, // CursorColumn\r
68 0, // CursorRow\r
69 TRUE // CursorVisible\r
70 },\r
11baadb6 71 0, // SerialInTimeOut\r
5c998646 72\r
73 NULL, // RawFifo\r
74 NULL, // UnicodeFiFo\r
75 NULL, // EfiKeyFiFo\r
76\r
6b88ceec 77 NULL, // ControllerNameTable\r
11baadb6 78 NULL, // TwoSecondTimeOut\r
6b88ceec
A
79 INPUT_STATE_DEFAULT,\r
80 RESET_STATE_DEFAULT,\r
66aa04e4 81 FALSE,\r
82 { // SimpleTextInputEx\r
83 TerminalConInResetEx,\r
84 TerminalConInReadKeyStrokeEx,\r
85 NULL,\r
86 TerminalConInSetState,\r
87 TerminalConInRegisterKeyNotify,\r
88 TerminalConInUnregisterKeyNotify,\r
89 },\r
11baadb6 90 { // NotifyList\r
66aa04e4 91 NULL,\r
92 NULL,\r
93 }\r
6b88ceec
A
94};\r
95\r
8fd98315 96/**\r
677fdb90 97 Test to see if this driver supports Controller.\r
8fd98315 98\r
99 @param This Protocol instance pointer.\r
ab76200c 100 @param Controller Handle of device to test\r
8fd98315 101 @param RemainingDevicePath Optional parameter use to pick a specific child\r
102 device to start.\r
103\r
ab76200c 104 @retval EFI_SUCCESS This driver supports this device.\r
105 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
106 @retval other This driver does not support this device.\r
6b88ceec 107\r
8fd98315 108**/\r
95276127 109EFI_STATUS\r
110EFIAPI\r
111TerminalDriverBindingSupported (\r
112 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
113 IN EFI_HANDLE Controller,\r
114 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
115 )\r
116{\r
117 EFI_STATUS Status;\r
118 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
119 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
120 VENDOR_DEVICE_PATH *Node;\r
121\r
122 //\r
123 // If remaining device path is not NULL, then make sure it is a\r
124 // device path that describes a terminal communications protocol.\r
125 //\r
126 if (RemainingDevicePath != NULL) {\r
127\r
128 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
129\r
130 if (Node->Header.Type != MESSAGING_DEVICE_PATH ||\r
131 Node->Header.SubType != MSG_VENDOR_DP ||\r
132 DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {\r
133\r
134 return EFI_UNSUPPORTED;\r
135\r
136 }\r
137 //\r
138 // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types\r
139 //\r
140 if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) &&\r
141 !CompareGuid (&Node->Guid, &gEfiVT100Guid) &&\r
142 !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) &&\r
143 !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
144\r
145 return EFI_UNSUPPORTED;\r
146 }\r
147 }\r
148 //\r
149 // Open the IO Abstraction(s) needed to perform the supported test\r
150 //\r
151 Status = gBS->OpenProtocol (\r
152 Controller,\r
153 &gEfiDevicePathProtocolGuid,\r
154 (VOID **) &ParentDevicePath,\r
155 This->DriverBindingHandle,\r
156 Controller,\r
157 EFI_OPEN_PROTOCOL_BY_DRIVER\r
158 );\r
159 if (Status == EFI_ALREADY_STARTED) {\r
160 return EFI_SUCCESS;\r
161 }\r
162\r
163 if (EFI_ERROR (Status)) {\r
164 return Status;\r
165 }\r
166\r
167 gBS->CloseProtocol (\r
168 Controller,\r
169 &gEfiDevicePathProtocolGuid,\r
170 This->DriverBindingHandle,\r
171 Controller\r
172 );\r
173\r
174 //\r
175 // The Controller must support the Serial I/O Protocol.\r
176 // This driver is a bus driver with at most 1 child device, so it is\r
177 // ok for it to be already started.\r
178 //\r
179 Status = gBS->OpenProtocol (\r
180 Controller,\r
181 &gEfiSerialIoProtocolGuid,\r
182 (VOID **) &SerialIo,\r
183 This->DriverBindingHandle,\r
184 Controller,\r
185 EFI_OPEN_PROTOCOL_BY_DRIVER\r
186 );\r
187 if (Status == EFI_ALREADY_STARTED) {\r
188 return EFI_SUCCESS;\r
189 }\r
190\r
191 if (EFI_ERROR (Status)) {\r
192 return Status;\r
193 }\r
194 //\r
195 // Close the I/O Abstraction(s) used to perform the supported test\r
196 //\r
197 gBS->CloseProtocol (\r
198 Controller,\r
199 &gEfiSerialIoProtocolGuid,\r
200 This->DriverBindingHandle,\r
201 Controller\r
202 );\r
203\r
204 return Status;\r
205}\r
206\r
e49ef433 207/**\r
ab76200c 208 Start this driver on Controller by opening a Serial IO protocol,\r
8fd98315 209 reading Device Path, and creating a child handle with a Simple Text In,\r
210 Simple Text In Ex and Simple Text Out protocol, and device path protocol.\r
211 And store Console Device Environment Variables.\r
e49ef433 212\r
8fd98315 213 @param This Protocol instance pointer.\r
ab76200c 214 @param Controller Handle of device to bind driver to\r
8fd98315 215 @param RemainingDevicePath Optional parameter use to pick a specific child\r
216 device to start.\r
e49ef433 217\r
ab76200c 218 @retval EFI_SUCCESS This driver is added to Controller.\r
219 @retval EFI_ALREADY_STARTED This driver is already running on Controller.\r
220 @retval other This driver does not support this device.\r
e49ef433 221\r
222**/\r
95276127 223EFI_STATUS\r
224EFIAPI\r
225TerminalDriverBindingStart (\r
226 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
227 IN EFI_HANDLE Controller,\r
228 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
229 )\r
95276127 230{\r
231 EFI_STATUS Status;\r
232 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
233 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
234 VENDOR_DEVICE_PATH *Node;\r
235 VENDOR_DEVICE_PATH *DefaultNode;\r
236 EFI_SERIAL_IO_MODE *Mode;\r
237 UINTN SerialInTimeOut;\r
238 TERMINAL_DEV *TerminalDevice;\r
239 UINT8 TerminalType;\r
240 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
241 UINTN EntryCount;\r
242 UINTN Index;\r
243 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
c4f9201e 244 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
95276127 245\r
246 TerminalDevice = NULL;\r
247 DefaultNode = NULL;\r
248 //\r
249 // Get the Device Path Protocol to build the device path of the child device\r
250 //\r
251 Status = gBS->OpenProtocol (\r
252 Controller,\r
253 &gEfiDevicePathProtocolGuid,\r
254 (VOID **) &ParentDevicePath,\r
255 This->DriverBindingHandle,\r
256 Controller,\r
257 EFI_OPEN_PROTOCOL_BY_DRIVER\r
258 );\r
259 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
260 return Status;\r
261 }\r
95276127 262\r
263 //\r
264 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.\r
265 //\r
266 Status = gBS->OpenProtocol (\r
267 Controller,\r
268 &gEfiSerialIoProtocolGuid,\r
269 (VOID **) &SerialIo,\r
270 This->DriverBindingHandle,\r
271 Controller,\r
272 EFI_OPEN_PROTOCOL_BY_DRIVER\r
273 );\r
274 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
275 return Status;\r
276 }\r
277\r
278 if (Status != EFI_ALREADY_STARTED) {\r
279 //\r
280 // If Serial I/O is not already open by this driver, then tag the handle\r
281 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
282 // StdErrDev variables with the list of possible terminal types on this\r
283 // serial port.\r
284 //\r
285 Status = gBS->OpenProtocol (\r
286 Controller,\r
287 &gEfiCallerIdGuid,\r
288 NULL,\r
289 This->DriverBindingHandle,\r
290 Controller,\r
291 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
292 );\r
293 if (EFI_ERROR (Status)) {\r
294 Status = gBS->InstallMultipleProtocolInterfaces (\r
295 &Controller,\r
296 &gEfiCallerIdGuid,\r
297 DuplicateDevicePath (ParentDevicePath),\r
298 NULL\r
299 );\r
300 if (EFI_ERROR (Status)) {\r
301 goto Error;\r
302 }\r
f1aec6cc 303\r
7c2228d2 304 if (!IsHotPlugDevice (ParentDevicePath)) {\r
f1aec6cc 305 //\r
306 // if the serial device is a hot plug device, do not update the\r
307 // ConInDev, ConOutDev, and StdErrDev variables.\r
308 //\r
ff37790d 309 TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
84ea1415 310 TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
ff37790d 311 TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 312 }\r
313 }\r
314 }\r
315 //\r
316 // Make sure a child handle does not already exist. This driver can only\r
317 // produce one child per serial port.\r
318 //\r
319 Status = gBS->OpenProtocolInformation (\r
320 Controller,\r
321 &gEfiSerialIoProtocolGuid,\r
322 &OpenInfoBuffer,\r
323 &EntryCount\r
324 );\r
325 if (!EFI_ERROR (Status)) {\r
326 Status = EFI_SUCCESS;\r
327 for (Index = 0; Index < EntryCount; Index++) {\r
677fdb90 328 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
95276127 329 Status = EFI_ALREADY_STARTED;\r
330 }\r
331 }\r
332\r
333 FreePool (OpenInfoBuffer);\r
334 if (EFI_ERROR (Status)) {\r
335 return Status;\r
336 }\r
337 }\r
338 //\r
339 // If RemainingDevicePath is NULL, then create default device path node\r
340 //\r
341 if (RemainingDevicePath == NULL) {\r
6b88ceec 342 DefaultNode = AllocateZeroPool (sizeof (VENDOR_DEVICE_PATH));\r
95276127 343 if (DefaultNode == NULL) {\r
344 Status = EFI_OUT_OF_RESOURCES;\r
345 goto Error;\r
346 }\r
347\r
e8cb61fe 348 TerminalType = FixedPcdGet8 (PcdDefaultTerminalType);\r
8fd98315 349 //\r
350 // Must be between PCANSITYPE (0) and VTUTF8TYPE (3)\r
351 //\r
e49ef433 352 ASSERT (TerminalType <= VTUTF8TYPE);\r
95276127 353\r
6b88ceec 354 CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
ab76200c 355 RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DefaultNode;\r
95276127 356 } else {\r
6b88ceec
A
357 //\r
358 // Use the RemainingDevicePath to determine the terminal type\r
359 //\r
360 Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
361 if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
e49ef433 362 TerminalType = PCANSITYPE;\r
6b88ceec 363 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
e49ef433 364 TerminalType = VT100TYPE;\r
6b88ceec 365 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
e49ef433 366 TerminalType = VT100PLUSTYPE;\r
6b88ceec 367 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
e49ef433 368 TerminalType = VTUTF8TYPE;\r
6b88ceec
A
369 } else {\r
370 goto Error;\r
371 }\r
95276127 372 }\r
6b88ceec 373\r
95276127 374 //\r
375 // Initialize the Terminal Dev\r
376 //\r
204ba917 377 TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
95276127 378 if (TerminalDevice == NULL) {\r
379 Status = EFI_OUT_OF_RESOURCES;\r
380 goto Error;\r
381 }\r
382\r
95276127 383 TerminalDevice->TerminalType = TerminalType;\r
95276127 384 TerminalDevice->SerialIo = SerialIo;\r
385\r
66aa04e4 386 InitializeListHead (&TerminalDevice->NotifyList);\r
387 Status = gBS->CreateEvent (\r
388 EVT_NOTIFY_WAIT,\r
389 TPL_NOTIFY,\r
390 TerminalConInWaitForKeyEx,\r
391 &TerminalDevice->SimpleInputEx,\r
392 &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
393 );\r
394 if (EFI_ERROR (Status)) {\r
395 goto Error;\r
396 }\r
397\r
398\r
95276127 399 Status = gBS->CreateEvent (\r
400 EVT_NOTIFY_WAIT,\r
401 TPL_NOTIFY,\r
402 TerminalConInWaitForKey,\r
403 &TerminalDevice->SimpleInput,\r
404 &TerminalDevice->SimpleInput.WaitForKey\r
405 );\r
406 if (EFI_ERROR (Status)) {\r
407 goto Error;\r
408 }\r
409 //\r
5c998646 410 // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
411 // the pre-read pending characters.\r
95276127 412 //\r
5c998646 413 TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
414 if (TerminalDevice->RawFiFo == NULL) {\r
415 goto Error;\r
416 }\r
417 TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
418 if (TerminalDevice->UnicodeFiFo == NULL) {\r
419 goto Error;\r
420 }\r
421 TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
422 if (TerminalDevice->EfiKeyFiFo == NULL) {\r
423 goto Error;\r
424 }\r
95276127 425\r
426 //\r
427 // Set the timeout value of serial buffer for\r
428 // keystroke response performance issue\r
429 //\r
430 Mode = TerminalDevice->SerialIo->Mode;\r
66aa04e4 431\r
95276127 432 SerialInTimeOut = 0;\r
433 if (Mode->BaudRate != 0) {\r
434 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
435 }\r
436\r
437 Status = TerminalDevice->SerialIo->SetAttributes (\r
438 TerminalDevice->SerialIo,\r
439 Mode->BaudRate,\r
440 Mode->ReceiveFifoDepth,\r
441 (UINT32) SerialInTimeOut,\r
442 (EFI_PARITY_TYPE) (Mode->Parity),\r
443 (UINT8) Mode->DataBits,\r
444 (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
445 );\r
446 if (EFI_ERROR (Status)) {\r
447 //\r
448 // if set attributes operation fails, invalidate\r
449 // the value of SerialInTimeOut,thus make it\r
450 // inconsistent with the default timeout value\r
451 // of serial buffer. This will invoke the recalculation\r
452 // in the readkeystroke routine.\r
453 //\r
454 TerminalDevice->SerialInTimeOut = 0;\r
455 } else {\r
456 TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
457 }\r
458 //\r
459 // Build the device path for the child device\r
460 //\r
461 Status = SetTerminalDevicePath (\r
462 TerminalDevice->TerminalType,\r
463 ParentDevicePath,\r
464 &TerminalDevice->DevicePath\r
465 );\r
466 if (EFI_ERROR (Status)) {\r
467 goto Error;\r
468 }\r
469\r
470 DevicePath = TerminalDevice->DevicePath;\r
471\r
472 Status = TerminalDevice->SimpleInput.Reset (\r
473 &TerminalDevice->SimpleInput,\r
474 FALSE\r
475 );\r
476 if (EFI_ERROR (Status)) {\r
477 //\r
478 // Need to report Error Code first\r
479 //\r
480 goto ReportError;\r
481 }\r
482 //\r
c4f9201e 483 // Set Simple Text Output Protocol from template.\r
95276127 484 //\r
c4f9201e 485 SimpleTextOutput = CopyMem (\r
486 &TerminalDevice->SimpleTextOutput,\r
487 &mTerminalDevTemplate.SimpleTextOutput,\r
488 sizeof (mTerminalDevTemplate.SimpleTextOutput)\r
489 );\r
490 SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
95276127 491\r
7347d5d6 492 TerminalDevice->SimpleTextOutputMode.MaxMode = 3;\r
3012ce5c 493 //\r
494 // For terminal devices, cursor is always visible\r
495 //\r
496 TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
c4f9201e 497 Status = TerminalConOutSetAttribute (\r
498 SimpleTextOutput,\r
499 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
500 );\r
3012ce5c 501 if (EFI_ERROR (Status)) {\r
502 goto ReportError;\r
503 }\r
504\r
c4f9201e 505 Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
95276127 506 if (EFI_ERROR (Status)) {\r
507 goto ReportError;\r
508 }\r
509\r
c4f9201e 510 Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
95276127 511 if (EFI_ERROR (Status)) {\r
512 goto ReportError;\r
513 }\r
514\r
c4f9201e 515 Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
95276127 516 if (EFI_ERROR (Status)) {\r
517 goto ReportError;\r
518 }\r
95276127 519\r
520 Status = gBS->CreateEvent (\r
521 EVT_TIMER,\r
522 TPL_CALLBACK,\r
523 NULL,\r
524 NULL,\r
525 &TerminalDevice->TwoSecondTimeOut\r
526 );\r
527\r
528 //\r
529 // Build the component name for the child device\r
530 //\r
531 TerminalDevice->ControllerNameTable = NULL;\r
532 switch (TerminalDevice->TerminalType) {\r
e49ef433 533 case PCANSITYPE:\r
5bca971e 534 AddUnicodeString2 (\r
95276127 535 "eng",\r
536 gTerminalComponentName.SupportedLanguages,\r
537 &TerminalDevice->ControllerNameTable,\r
5bca971e 538 (CHAR16 *)L"PC-ANSI Serial Console",\r
539 TRUE\r
95276127 540 );\r
5bca971e 541 AddUnicodeString2 (\r
542 "en",\r
543 gTerminalComponentName2.SupportedLanguages,\r
544 &TerminalDevice->ControllerNameTable,\r
545 (CHAR16 *)L"PC-ANSI Serial Console",\r
546 FALSE\r
547 );\r
548\r
95276127 549 break;\r
550\r
e49ef433 551 case VT100TYPE:\r
5bca971e 552 AddUnicodeString2 (\r
95276127 553 "eng",\r
554 gTerminalComponentName.SupportedLanguages,\r
555 &TerminalDevice->ControllerNameTable,\r
5bca971e 556 (CHAR16 *)L"VT-100 Serial Console",\r
557 TRUE\r
95276127 558 );\r
5bca971e 559 AddUnicodeString2 (\r
560 "en",\r
561 gTerminalComponentName2.SupportedLanguages,\r
562 &TerminalDevice->ControllerNameTable,\r
563 (CHAR16 *)L"VT-100 Serial Console",\r
564 FALSE\r
565 );\r
566\r
95276127 567 break;\r
568\r
e49ef433 569 case VT100PLUSTYPE:\r
5bca971e 570 AddUnicodeString2 (\r
95276127 571 "eng",\r
572 gTerminalComponentName.SupportedLanguages,\r
573 &TerminalDevice->ControllerNameTable,\r
5bca971e 574 (CHAR16 *)L"VT-100+ Serial Console",\r
575 TRUE\r
95276127 576 );\r
5bca971e 577 AddUnicodeString2 (\r
578 "en",\r
579 gTerminalComponentName2.SupportedLanguages,\r
580 &TerminalDevice->ControllerNameTable,\r
581 (CHAR16 *)L"VT-100+ Serial Console",\r
582 FALSE\r
583 );\r
584\r
95276127 585 break;\r
586\r
e49ef433 587 case VTUTF8TYPE:\r
5bca971e 588 AddUnicodeString2 (\r
95276127 589 "eng",\r
590 gTerminalComponentName.SupportedLanguages,\r
591 &TerminalDevice->ControllerNameTable,\r
5bca971e 592 (CHAR16 *)L"VT-UTF8 Serial Console",\r
593 TRUE\r
95276127 594 );\r
5bca971e 595 AddUnicodeString2 (\r
596 "en",\r
597 gTerminalComponentName2.SupportedLanguages,\r
598 &TerminalDevice->ControllerNameTable,\r
599 (CHAR16 *)L"VT-UTF8 Serial Console",\r
600 FALSE\r
601 );\r
602\r
95276127 603 break;\r
604 }\r
605 //\r
606 // Install protocol interfaces for the serial device.\r
607 //\r
608 Status = gBS->InstallMultipleProtocolInterfaces (\r
609 &TerminalDevice->Handle,\r
610 &gEfiDevicePathProtocolGuid,\r
611 TerminalDevice->DevicePath,\r
612 &gEfiSimpleTextInProtocolGuid,\r
613 &TerminalDevice->SimpleInput,\r
66aa04e4 614 &gEfiSimpleTextInputExProtocolGuid,\r
615 &TerminalDevice->SimpleInputEx,\r
95276127 616 &gEfiSimpleTextOutProtocolGuid,\r
617 &TerminalDevice->SimpleTextOutput,\r
618 NULL\r
619 );\r
620 if (EFI_ERROR (Status)) {\r
621 goto Error;\r
622 }\r
f1aec6cc 623\r
95276127 624 //\r
625 // Register the Parent-Child relationship via\r
626 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
627 //\r
628 Status = gBS->OpenProtocol (\r
629 Controller,\r
630 &gEfiSerialIoProtocolGuid,\r
631 (VOID **) &TerminalDevice->SerialIo,\r
632 This->DriverBindingHandle,\r
633 TerminalDevice->Handle,\r
634 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
635 );\r
636 if (EFI_ERROR (Status)) {\r
637 goto Error;\r
638 }\r
639\r
640 if (DefaultNode != NULL) {\r
641 FreePool (DefaultNode);\r
642 }\r
643\r
644 return EFI_SUCCESS;\r
645\r
646ReportError:\r
647 //\r
648 // Report error code before exiting\r
649 //\r
650 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
651 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
97a079ed 652 PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
95276127 653 DevicePath\r
654 );\r
655\r
656Error:\r
657 //\r
658 // Use the Stop() function to free all resources allocated in Start()\r
659 //\r
660 if (TerminalDevice != NULL) {\r
661\r
662 if (TerminalDevice->Handle != NULL) {\r
663 This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
664 } else {\r
665\r
666 if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
667 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
668 }\r
669\r
670 if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
671 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
672 }\r
673\r
66aa04e4 674 if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
675 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
676 }\r
677\r
678 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
679\r
5c998646 680 if (TerminalDevice->RawFiFo != NULL) {\r
681 FreePool (TerminalDevice->RawFiFo);\r
682 }\r
683 if (TerminalDevice->UnicodeFiFo != NULL) {\r
684 FreePool (TerminalDevice->UnicodeFiFo);\r
685 }\r
686 if (TerminalDevice->EfiKeyFiFo != NULL) {\r
687 FreePool (TerminalDevice->EfiKeyFiFo);\r
688 }\r
689\r
95276127 690 if (TerminalDevice->ControllerNameTable != NULL) {\r
691 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
692 }\r
693\r
694 if (TerminalDevice->DevicePath != NULL) {\r
695 FreePool (TerminalDevice->DevicePath);\r
696 }\r
697\r
698 FreePool (TerminalDevice);\r
699 }\r
700 }\r
701\r
702 if (DefaultNode != NULL) {\r
703 FreePool (DefaultNode);\r
704 }\r
705\r
706 This->Stop (This, Controller, 0, NULL);\r
707\r
708 return Status;\r
709}\r
710\r
e49ef433 711/**\r
ab76200c 712 Stop this driver on Controller by closing Simple Text In, Simple Text\r
8fd98315 713 In Ex, Simple Text Out protocol, and removing parent device path from\r
677fdb90 714 Console Device Environment Variables.\r
e49ef433 715\r
8fd98315 716 @param This Protocol instance pointer.\r
ab76200c 717 @param Controller Handle of device to stop driver on\r
8fd98315 718 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
719 children is zero stop the entire bus driver.\r
720 @param ChildHandleBuffer List of Child Handles to Stop.\r
e49ef433 721\r
ab76200c 722 @retval EFI_SUCCESS This driver is removed Controller.\r
8fd98315 723 @retval other This driver could not be removed from this device.\r
e49ef433 724\r
725**/\r
95276127 726EFI_STATUS\r
727EFIAPI\r
728TerminalDriverBindingStop (\r
729 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
730 IN EFI_HANDLE Controller,\r
731 IN UINTN NumberOfChildren,\r
732 IN EFI_HANDLE *ChildHandleBuffer\r
733 )\r
95276127 734{\r
735 EFI_STATUS Status;\r
736 UINTN Index;\r
737 BOOLEAN AllChildrenStopped;\r
738 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
739 TERMINAL_DEV *TerminalDevice;\r
740 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
741 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
742 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
743\r
744 Status = gBS->HandleProtocol (\r
745 Controller,\r
746 &gEfiDevicePathProtocolGuid,\r
747 (VOID **) &DevicePath\r
748 );\r
749 if (EFI_ERROR (Status)) {\r
750 return Status;\r
751 }\r
95276127 752\r
753 //\r
754 // Complete all outstanding transactions to Controller.\r
755 // Don't allow any new transaction to Controller to be started.\r
756 //\r
757 if (NumberOfChildren == 0) {\r
758 //\r
759 // Close the bus driver\r
760 //\r
761 Status = gBS->OpenProtocol (\r
762 Controller,\r
763 &gEfiCallerIdGuid,\r
764 (VOID **) &ParentDevicePath,\r
765 This->DriverBindingHandle,\r
766 Controller,\r
767 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
768 );\r
769 if (!EFI_ERROR (Status)) {\r
770 //\r
771 // Remove Parent Device Path from\r
772 // the Console Device Environment Variables\r
773 //\r
ff37790d
A
774 TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
775 TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
776 TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 777\r
778 //\r
779 // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
780 //\r
781 Status = gBS->UninstallMultipleProtocolInterfaces (\r
782 Controller,\r
783 &gEfiCallerIdGuid,\r
784 ParentDevicePath,\r
785 NULL\r
786 );\r
787\r
788 //\r
789 // Free the ParentDevicePath that was duplicated in Start()\r
790 //\r
791 if (!EFI_ERROR (Status)) {\r
792 FreePool (ParentDevicePath);\r
793 }\r
794 }\r
795\r
796 gBS->CloseProtocol (\r
797 Controller,\r
798 &gEfiSerialIoProtocolGuid,\r
799 This->DriverBindingHandle,\r
800 Controller\r
801 );\r
802\r
803 gBS->CloseProtocol (\r
804 Controller,\r
805 &gEfiDevicePathProtocolGuid,\r
806 This->DriverBindingHandle,\r
807 Controller\r
808 );\r
809\r
810 return EFI_SUCCESS;\r
811 }\r
812\r
813 AllChildrenStopped = TRUE;\r
814\r
815 for (Index = 0; Index < NumberOfChildren; Index++) {\r
816\r
817 Status = gBS->OpenProtocol (\r
818 ChildHandleBuffer[Index],\r
819 &gEfiSimpleTextOutProtocolGuid,\r
820 (VOID **) &SimpleTextOutput,\r
821 This->DriverBindingHandle,\r
822 ChildHandleBuffer[Index],\r
823 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
824 );\r
825 if (!EFI_ERROR (Status)) {\r
826\r
827 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
828\r
829 gBS->CloseProtocol (\r
830 Controller,\r
831 &gEfiSerialIoProtocolGuid,\r
832 This->DriverBindingHandle,\r
833 ChildHandleBuffer[Index]\r
834 );\r
835\r
836 Status = gBS->UninstallMultipleProtocolInterfaces (\r
837 ChildHandleBuffer[Index],\r
838 &gEfiSimpleTextInProtocolGuid,\r
839 &TerminalDevice->SimpleInput,\r
66aa04e4 840 &gEfiSimpleTextInputExProtocolGuid,\r
841 &TerminalDevice->SimpleInputEx,\r
95276127 842 &gEfiSimpleTextOutProtocolGuid,\r
843 &TerminalDevice->SimpleTextOutput,\r
844 &gEfiDevicePathProtocolGuid,\r
845 TerminalDevice->DevicePath,\r
846 NULL\r
847 );\r
848 if (EFI_ERROR (Status)) {\r
849 gBS->OpenProtocol (\r
850 Controller,\r
851 &gEfiSerialIoProtocolGuid,\r
852 (VOID **) &SerialIo,\r
853 This->DriverBindingHandle,\r
854 ChildHandleBuffer[Index],\r
855 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
856 );\r
857 } else {\r
858\r
859 if (TerminalDevice->ControllerNameTable != NULL) {\r
860 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
861 }\r
862\r
95276127 863 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
864 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
66aa04e4 865 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
866 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
95276127 867 FreePool (TerminalDevice->DevicePath);\r
868 FreePool (TerminalDevice);\r
869 }\r
870 }\r
871\r
872 if (EFI_ERROR (Status)) {\r
873 AllChildrenStopped = FALSE;\r
874 }\r
875 }\r
876\r
877 if (!AllChildrenStopped) {\r
878 return EFI_DEVICE_ERROR;\r
879 }\r
880\r
881 return EFI_SUCCESS;\r
882}\r
883\r
66aa04e4 884\r
e49ef433 885/**\r
8fd98315 886 Free notify functions list.\r
66aa04e4 887\r
e49ef433 888 @param ListHead The list head\r
66aa04e4 889\r
8fd98315 890 @retval EFI_SUCCESS Free the notify list successfully.\r
891 @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
66aa04e4 892\r
e49ef433 893**/\r
894EFI_STATUS\r
895TerminalFreeNotifyList (\r
896 IN OUT LIST_ENTRY *ListHead\r
897 )\r
66aa04e4 898{\r
899 TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
900\r
901 if (ListHead == NULL) {\r
902 return EFI_INVALID_PARAMETER;\r
903 }\r
904 while (!IsListEmpty (ListHead)) {\r
905 NotifyNode = CR (\r
fb0b259e 906 ListHead->ForwardLink,\r
907 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
908 NotifyEntry,\r
66aa04e4 909 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
910 );\r
911 RemoveEntryList (ListHead->ForwardLink);\r
ab76200c 912 FreePool (NotifyNode);\r
66aa04e4 913 }\r
fb0b259e 914\r
66aa04e4 915 return EFI_SUCCESS;\r
916}\r
917\r
918\r
8fd98315 919/**\r
920 Update terminal device path in Console Device Environment Variables.\r
921\r
922 @param VariableName The Console Device Environment Variable.\r
11baadb6 923 @param ParentDevicePath The terminal device path to be updated.\r
8fd98315 924\r
8fd98315 925**/\r
95276127 926VOID\r
927TerminalUpdateConsoleDevVariable (\r
928 IN CHAR16 *VariableName,\r
929 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
930 )\r
931{\r
932 EFI_STATUS Status;\r
933 UINTN VariableSize;\r
934 UINT8 TerminalType;\r
935 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
936 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
937 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
938\r
939 Variable = NULL;\r
940\r
941 //\r
942 // Get global variable and its size according to the name given.\r
943 //\r
944 Variable = TerminalGetVariableAndSize (\r
945 VariableName,\r
946 &gEfiGlobalVariableGuid,\r
947 &VariableSize\r
948 );\r
949 //\r
950 // Append terminal device path onto the variable.\r
951 //\r
e49ef433 952 for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
95276127 953 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
954 NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
955 if (Variable != NULL) {\r
956 FreePool (Variable);\r
957 }\r
958\r
959 if (TempDevicePath != NULL) {\r
960 FreePool (TempDevicePath);\r
961 }\r
962\r
963 Variable = NewVariable;\r
964 }\r
965\r
966 VariableSize = GetDevicePathSize (Variable);\r
967\r
968 Status = gRT->SetVariable (\r
969 VariableName,\r
970 &gEfiGlobalVariableGuid,\r
971 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
972 VariableSize,\r
973 Variable\r
974 );\r
975 ASSERT_EFI_ERROR (Status);\r
976 FreePool (Variable);\r
977\r
978 return ;\r
979}\r
980\r
e49ef433 981\r
982/**\r
8fd98315 983 Remove terminal device path from Console Device Environment Variables.\r
e49ef433 984\r
8fd98315 985 @param VariableName Console Device Environment Variables.\r
11baadb6 986 @param ParentDevicePath The terminal device path to be updated.\r
e49ef433 987\r
e49ef433 988**/\r
95276127 989VOID\r
990TerminalRemoveConsoleDevVariable (\r
991 IN CHAR16 *VariableName,\r
992 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
993 )\r
95276127 994{\r
995 EFI_STATUS Status;\r
996 BOOLEAN FoundOne;\r
997 BOOLEAN Match;\r
998 UINTN VariableSize;\r
999 UINTN InstanceSize;\r
1000 UINT8 TerminalType;\r
1001 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
1002 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1003 EFI_DEVICE_PATH_PROTOCOL *OriginalVariable;\r
1004 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1005 EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;\r
1006 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1007\r
1008 Variable = NULL;\r
1009 Instance = NULL;\r
1010\r
1011 //\r
1012 // Get global variable and its size according to the name given.\r
1013 //\r
1014 Variable = TerminalGetVariableAndSize (\r
1015 VariableName,\r
1016 &gEfiGlobalVariableGuid,\r
1017 &VariableSize\r
1018 );\r
1019 if (Variable == NULL) {\r
1020 return ;\r
1021 }\r
1022\r
1023 FoundOne = FALSE;\r
1024 OriginalVariable = Variable;\r
1025 NewVariable = NULL;\r
1026\r
1027 //\r
1028 // Get first device path instance from Variable\r
1029 //\r
1030 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1031 if (Instance == NULL) {\r
1032 FreePool (OriginalVariable);\r
1033 return ;\r
1034 }\r
1035 //\r
1036 // Loop through all the device path instances of Variable\r
1037 //\r
1038 do {\r
1039 //\r
1040 // Loop through all the terminal types that this driver supports\r
1041 //\r
1042 Match = FALSE;\r
e49ef433 1043 for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
95276127 1044\r
1045 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1046\r
1047 //\r
11baadb6 1048 // Compare the generated device path to the current device path instance\r
95276127 1049 //\r
1050 if (TempDevicePath != NULL) {\r
1051 if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
1052 Match = TRUE;\r
1053 FoundOne = TRUE;\r
1054 }\r
1055\r
1056 FreePool (TempDevicePath);\r
1057 }\r
1058 }\r
1059 //\r
1060 // If a match was not found, then keep the current device path instance\r
1061 //\r
1062 if (!Match) {\r
1063 SavedNewVariable = NewVariable;\r
1064 NewVariable = AppendDevicePathInstance (NewVariable, Instance);\r
1065 if (SavedNewVariable != NULL) {\r
1066 FreePool (SavedNewVariable);\r
1067 }\r
1068 }\r
1069 //\r
1070 // Get next device path instance from Variable\r
1071 //\r
1072 FreePool (Instance);\r
1073 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1074 } while (Instance != NULL);\r
1075\r
1076 FreePool (OriginalVariable);\r
1077\r
1078 if (FoundOne) {\r
1079 VariableSize = GetDevicePathSize (NewVariable);\r
1080\r
1081 Status = gRT->SetVariable (\r
1082 VariableName,\r
1083 &gEfiGlobalVariableGuid,\r
1084 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1085 VariableSize,\r
1086 NewVariable\r
1087 );\r
1088 ASSERT_EFI_ERROR (Status);\r
1089 }\r
1090\r
1091 if (NewVariable != NULL) {\r
1092 FreePool (NewVariable);\r
1093 }\r
1094\r
1095 return ;\r
1096}\r
1097\r
95276127 1098\r
e49ef433 1099/**\r
95276127 1100 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
1101 buffer, and the size of the buffer. On failure return NULL.\r
1102\r
e49ef433 1103 @param Name String part of EFI variable name\r
1104 @param VendorGuid GUID part of EFI variable name\r
1105 @param VariableSize Returns the size of the EFI variable that was read\r
95276127 1106\r
e49ef433 1107 @return Dynamically allocated memory that contains a copy of the EFI variable.\r
677fdb90 1108 Caller is responsible freeing the buffer. If variable was not read,\r
11baadb6 1109 NULL returned.\r
95276127 1110\r
e49ef433 1111**/\r
1112VOID *\r
1113TerminalGetVariableAndSize (\r
1114 IN CHAR16 *Name,\r
1115 IN EFI_GUID *VendorGuid,\r
1116 OUT UINTN *VariableSize\r
1117 )\r
95276127 1118{\r
1119 EFI_STATUS Status;\r
1120 UINTN BufferSize;\r
1121 VOID *Buffer;\r
1122\r
1123 Buffer = NULL;\r
1124\r
1125 //\r
1126 // Pass in a small size buffer to find the actual variable size.\r
1127 //\r
1128 BufferSize = 1;\r
1129 Buffer = AllocatePool (BufferSize);\r
1130 if (Buffer == NULL) {\r
1131 *VariableSize = 0;\r
1132 return NULL;\r
1133 }\r
1134\r
1135 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1136\r
1137 if (Status == EFI_SUCCESS) {\r
1138 *VariableSize = BufferSize;\r
1139 return Buffer;\r
1140\r
1141 } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
1142 //\r
1143 // Allocate the buffer to return\r
1144 //\r
1145 FreePool (Buffer);\r
1146 Buffer = AllocatePool (BufferSize);\r
1147 if (Buffer == NULL) {\r
1148 *VariableSize = 0;\r
1149 return NULL;\r
1150 }\r
1151 //\r
1152 // Read variable into the allocated buffer.\r
1153 //\r
1154 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1155 if (EFI_ERROR (Status)) {\r
1156 BufferSize = 0;\r
1157 FreePool (Buffer);\r
1158 Buffer = NULL;\r
1159 }\r
1160 } else {\r
1161 //\r
1162 // Variable not found or other errors met.\r
1163 //\r
1164 BufferSize = 0;\r
1165 FreePool (Buffer);\r
1166 Buffer = NULL;\r
1167 }\r
1168\r
1169 *VariableSize = BufferSize;\r
1170 return Buffer;\r
1171}\r
1172\r
8fd98315 1173/**\r
11baadb6 1174 Build terminal device path according to terminal type.\r
8fd98315 1175\r
1176 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.\r
11baadb6 1177 @param ParentDevicePath Parent device path.\r
8fd98315 1178 @param TerminalDevicePath Returned terminal device path, if building successfully.\r
1179\r
1180 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.\r
1181 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.\r
1182 @retval EFI_SUCCESS Build terminal device path successfully.\r
1183\r
1184**/\r
95276127 1185EFI_STATUS\r
1186SetTerminalDevicePath (\r
1187 IN UINT8 TerminalType,\r
1188 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
1189 OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath\r
1190 )\r
1191{\r
1192 VENDOR_DEVICE_PATH Node;\r
1193\r
1194 *TerminalDevicePath = NULL;\r
1195 Node.Header.Type = MESSAGING_DEVICE_PATH;\r
1196 Node.Header.SubType = MSG_VENDOR_DP;\r
1197\r
1198 //\r
ab76200c 1199 // Generate terminal device path node according to terminal type.\r
95276127 1200 //\r
1201 switch (TerminalType) {\r
1202\r
e49ef433 1203 case PCANSITYPE:\r
ab76200c 1204 CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
95276127 1205 break;\r
1206\r
e49ef433 1207 case VT100TYPE:\r
ab76200c 1208 CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
95276127 1209 break;\r
1210\r
e49ef433 1211 case VT100PLUSTYPE:\r
ab76200c 1212 CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
95276127 1213 break;\r
1214\r
e49ef433 1215 case VTUTF8TYPE:\r
ab76200c 1216 CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
95276127 1217 break;\r
1218\r
1219 default:\r
1220 return EFI_UNSUPPORTED;\r
95276127 1221 }\r
1222\r
ab76200c 1223 //\r
1224 // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
1225 //\r
95276127 1226 SetDevicePathNodeLength (\r
1227 &Node.Header,\r
1228 sizeof (VENDOR_DEVICE_PATH)\r
1229 );\r
ab76200c 1230\r
95276127 1231 //\r
ab76200c 1232 // Append the terminal node onto parent device path\r
95276127 1233 // to generate a complete terminal device path.\r
1234 //\r
1235 *TerminalDevicePath = AppendDevicePathNode (\r
1236 ParentDevicePath,\r
1237 (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
1238 );\r
1239 if (*TerminalDevicePath == NULL) {\r
1240 return EFI_OUT_OF_RESOURCES;\r
1241 }\r
1242\r
1243 return EFI_SUCCESS;\r
1244}\r
1245\r
97a079ed
A
1246/**\r
1247 The user Entry Point for module Terminal. The user code starts with this function.\r
1248\r
ab76200c 1249 @param ImageHandle The firmware allocated handle for the EFI image.\r
1250 @param SystemTable A pointer to the EFI System Table.\r
fb0b259e 1251\r
97a079ed
A
1252 @retval EFI_SUCCESS The entry point is executed successfully.\r
1253 @retval other Some error occurs when executing this entry point.\r
1254\r
1255**/\r
1256EFI_STATUS\r
1257EFIAPI\r
1258InitializeTerminal(\r
1259 IN EFI_HANDLE ImageHandle,\r
1260 IN EFI_SYSTEM_TABLE *SystemTable\r
1261 )\r
1262{\r
1263 EFI_STATUS Status;\r
1264\r
1265 //\r
1266 // Install driver model protocol(s).\r
1267 //\r
5bca971e 1268 Status = EfiLibInstallDriverBindingComponentName2 (\r
97a079ed
A
1269 ImageHandle,\r
1270 SystemTable,\r
1271 &gTerminalDriverBinding,\r
1272 ImageHandle,\r
1273 &gTerminalComponentName,\r
5bca971e 1274 &gTerminalComponentName2\r
97a079ed
A
1275 );\r
1276 ASSERT_EFI_ERROR (Status);\r
1277\r
97a079ed
A
1278 return Status;\r
1279}\r
f1aec6cc 1280\r
1281/**\r
1282 Check if the device supports hot-plug through its device path.\r
1283\r
1284 This function could be updated to check more types of Hot Plug devices.\r
1285 Currently, it checks USB and PCCard device.\r
1286\r
1287 @param DevicePath Pointer to device's device path.\r
1288\r
1289 @retval TRUE The devcie is a hot-plug device\r
1290 @retval FALSE The devcie is not a hot-plug device.\r
1291\r
1292**/\r
1293BOOLEAN\r
1294IsHotPlugDevice (\r
1295 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1296 )\r
1297{\r
1298 EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
1299\r
1300 CheckDevicePath = DevicePath;\r
1301 while (!IsDevicePathEnd (CheckDevicePath)) {\r
1302 //\r
1303 // Check device whether is hot plug device or not throught Device Path\r
1304 // \r
1305 if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
1306 (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
1307 DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
1308 DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
1309 //\r
1310 // If Device is USB device\r
1311 //\r
1312 return TRUE;\r
1313 }\r
1314 if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
1315 (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
1316 //\r
1317 // If Device is PCCard\r
1318 //\r
1319 return TRUE;\r
1320 }\r
1321 \r
1322 CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
1323 }\r
1324\r
1325 return FALSE;\r
1326}\r
1327\r