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