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