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