]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
roll back the changes as NT32 could not use PciLib
[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
8fd98315 19/**\r
20 Free notify functions list.\r
21\r
22 @param ListHead The list head\r
23\r
24 @retval EFI_SUCCESS Free the notify list successfully.\r
25 @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
26\r
27**/\r
66aa04e4 28EFI_STATUS\r
29TerminalFreeNotifyList (\r
30 IN OUT LIST_ENTRY *ListHead\r
fb0b259e 31 );\r
66aa04e4 32\r
95276127 33//\r
34// Globals\r
35//\r
36EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = {\r
37 TerminalDriverBindingSupported,\r
38 TerminalDriverBindingStart,\r
39 TerminalDriverBindingStop,\r
40 0xa,\r
41 NULL,\r
42 NULL\r
43};\r
44\r
45\r
6b88ceec
A
46EFI_GUID *gTerminalType[] = {\r
47 &gEfiPcAnsiGuid,\r
48 &gEfiVT100Guid,\r
49 &gEfiVT100PlusGuid,\r
50 &gEfiVTUTF8Guid\r
51};\r
52\r
53\r
54TERMINAL_DEV gTerminalDevTemplate = {\r
55 TERMINAL_DEV_SIGNATURE,\r
56 NULL,\r
57 0,\r
58 NULL,\r
59 NULL,\r
60 { // SimpleTextInput\r
61 TerminalConInReset,\r
62 TerminalConInReadKeyStroke,\r
63 NULL\r
64 },\r
65 { // SimpleTextOutput\r
66 TerminalConOutReset,\r
67 TerminalConOutOutputString,\r
68 TerminalConOutTestString,\r
69 TerminalConOutQueryMode,\r
70 TerminalConOutSetMode,\r
71 TerminalConOutSetAttribute,\r
72 TerminalConOutClearScreen,\r
73 TerminalConOutSetCursorPosition,\r
74 TerminalConOutEnableCursor,\r
75 NULL\r
76 },\r
77 { // SimpleTextOutputMode\r
78 1, // MaxMode\r
79 0, // Mode?\r
80 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
81 0, // CursorColumn\r
82 0, // CursorRow\r
83 TRUE // CursorVisible\r
84 },\r
85 0,\r
86 {\r
87 0,\r
88 0,\r
89 { 0 }\r
90 },\r
91 {\r
92 0,\r
93 0,\r
94 { 0 }\r
95 },\r
96 {\r
97 0,\r
98 0,\r
84b5c78e 99 { {0} }\r
6b88ceec
A
100 },\r
101 NULL, // ControllerNameTable\r
fb0b259e 102 NULL,\r
6b88ceec
A
103 INPUT_STATE_DEFAULT,\r
104 RESET_STATE_DEFAULT,\r
66aa04e4 105 FALSE,\r
106 { // SimpleTextInputEx\r
107 TerminalConInResetEx,\r
108 TerminalConInReadKeyStrokeEx,\r
109 NULL,\r
110 TerminalConInSetState,\r
111 TerminalConInRegisterKeyNotify,\r
112 TerminalConInUnregisterKeyNotify,\r
113 },\r
114 {\r
115 NULL,\r
116 NULL,\r
117 }\r
6b88ceec
A
118};\r
119\r
120\r
8fd98315 121/**\r
122 Test to see if this driver supports ControllerHandle. \r
123\r
124 @param This Protocol instance pointer.\r
125 @param ControllerHandle Handle of device to test\r
126 @param RemainingDevicePath Optional parameter use to pick a specific child\r
127 device to start.\r
128\r
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
8fd98315 233 Start this driver on ControllerHandle by opening a Serial IO protocol,\r
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
239 @param ControllerHandle Handle of device to bind driver to\r
240 @param RemainingDevicePath Optional parameter use to pick a specific child\r
241 device to start.\r
e49ef433 242\r
8fd98315 243 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
244 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\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
A
385 CopyMem (&DefaultNode->Guid, gTerminalType[TerminalType], sizeof (EFI_GUID));\r
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
6b88ceec 408 TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &gTerminalDevTemplate);\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
8fd98315 756 Stop this driver on ControllerHandle by closing Simple Text In, Simple Text\r
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
761 @param ControllerHandle Handle of device to stop driver on\r
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
8fd98315 766 @retval EFI_SUCCESS This driver is removed ControllerHandle.\r
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
975 gBS->FreePool (NotifyNode);\r
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
1175 @return Caller is repsoncible freeing the buffer.\r
1176 @retval NULL Variable was not read\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
1266 // generate terminal device path node according to terminal type.\r
1267 //\r
1268 switch (TerminalType) {\r
1269\r
e49ef433 1270 case PCANSITYPE:\r
95276127 1271 CopyMem (\r
1272 &Node.Guid,\r
1273 &gEfiPcAnsiGuid,\r
1274 sizeof (EFI_GUID)\r
1275 );\r
1276 break;\r
1277\r
e49ef433 1278 case VT100TYPE:\r
95276127 1279 CopyMem (\r
1280 &Node.Guid,\r
1281 &gEfiVT100Guid,\r
1282 sizeof (EFI_GUID)\r
1283 );\r
1284 break;\r
1285\r
e49ef433 1286 case VT100PLUSTYPE:\r
95276127 1287 CopyMem (\r
1288 &Node.Guid,\r
1289 &gEfiVT100PlusGuid,\r
1290 sizeof (EFI_GUID)\r
1291 );\r
1292 break;\r
1293\r
e49ef433 1294 case VTUTF8TYPE:\r
95276127 1295 CopyMem (\r
1296 &Node.Guid,\r
1297 &gEfiVTUTF8Guid,\r
1298 sizeof (EFI_GUID)\r
1299 );\r
1300 break;\r
1301\r
1302 default:\r
1303 return EFI_UNSUPPORTED;\r
1304 break;\r
1305 }\r
1306\r
1307 SetDevicePathNodeLength (\r
1308 &Node.Header,\r
1309 sizeof (VENDOR_DEVICE_PATH)\r
1310 );\r
1311 //\r
1312 // append the terminal node onto parent device path\r
1313 // to generate a complete terminal device path.\r
1314 //\r
1315 *TerminalDevicePath = AppendDevicePathNode (\r
1316 ParentDevicePath,\r
1317 (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
1318 );\r
1319 if (*TerminalDevicePath == NULL) {\r
1320 return EFI_OUT_OF_RESOURCES;\r
1321 }\r
1322\r
1323 return EFI_SUCCESS;\r
1324}\r
1325\r
8fd98315 1326/**\r
1327 Initialize the Raw Data FIFO.\r
1328\r
1329 @param TerminalDevice The terminal device.\r
1330\r
1331 @return None.\r
1332\r
1333**/\r
95276127 1334VOID\r
1335InitializeRawFiFo (\r
1336 IN TERMINAL_DEV *TerminalDevice\r
1337 )\r
1338{\r
1339 //\r
1340 // Make the raw fifo empty.\r
1341 //\r
1342 TerminalDevice->RawFiFo.Head = TerminalDevice->RawFiFo.Tail;\r
1343}\r
1344\r
8fd98315 1345/**\r
1346 Initialize the Unicode FIFO.\r
1347\r
1348 @param TerminalDevice The terminal device.\r
1349\r
1350 @return None.\r
1351\r
1352**/\r
95276127 1353VOID\r
1354InitializeUnicodeFiFo (\r
1355 IN TERMINAL_DEV *TerminalDevice\r
1356 )\r
1357{\r
1358 //\r
1359 // Make the unicode fifo empty\r
1360 //\r
1361 TerminalDevice->UnicodeFiFo.Head = TerminalDevice->UnicodeFiFo.Tail;\r
1362}\r
1363\r
8fd98315 1364/**\r
1365 Initialize the EFI Key FIFO.\r
1366\r
1367 @param TerminalDevice The terminal device.\r
1368\r
1369 @return None.\r
1370\r
1371**/\r
95276127 1372VOID\r
1373InitializeEfiKeyFiFo (\r
1374 IN TERMINAL_DEV *TerminalDevice\r
1375 )\r
1376{\r
1377 //\r
1378 // Make the efi key fifo empty\r
1379 //\r
1380 TerminalDevice->EfiKeyFiFo.Head = TerminalDevice->EfiKeyFiFo.Tail;\r
1381}\r
97a079ed
A
1382\r
1383\r
1384/**\r
1385 The user Entry Point for module Terminal. The user code starts with this function.\r
1386\r
fb0b259e 1387 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
97a079ed 1388 @param[in] SystemTable A pointer to the EFI System Table.\r
fb0b259e 1389\r
97a079ed
A
1390 @retval EFI_SUCCESS The entry point is executed successfully.\r
1391 @retval other Some error occurs when executing this entry point.\r
1392\r
1393**/\r
1394EFI_STATUS\r
1395EFIAPI\r
1396InitializeTerminal(\r
1397 IN EFI_HANDLE ImageHandle,\r
1398 IN EFI_SYSTEM_TABLE *SystemTable\r
1399 )\r
1400{\r
1401 EFI_STATUS Status;\r
1402\r
1403 //\r
1404 // Install driver model protocol(s).\r
1405 //\r
5bca971e 1406 Status = EfiLibInstallDriverBindingComponentName2 (\r
97a079ed
A
1407 ImageHandle,\r
1408 SystemTable,\r
1409 &gTerminalDriverBinding,\r
1410 ImageHandle,\r
1411 &gTerminalComponentName,\r
5bca971e 1412 &gTerminalComponentName2\r
97a079ed
A
1413 );\r
1414 ASSERT_EFI_ERROR (Status);\r
1415\r
1416\r
1417 return Status;\r
1418}\r