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