]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
Add AccessMsrDb.s for MSFT tool chain. It uses raw data to represent instructions...
[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
11baadb6 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
491 // Simple Text Output Protocol\r
492 //\r
11baadb6 493 SimpleTextOutput = TerminalDevice->SimpleTextOutput;\r
494 \r
495 SimpleTextOutput.Reset = TerminalConOutReset;\r
496 SimpleTextOutput.OutputString = TerminalConOutOutputString;\r
497 SimpleTextOutput.TestString = TerminalConOutTestString;\r
498 SimpleTextOutput.QueryMode = TerminalConOutQueryMode;\r
499 SimpleTextOutput.SetMode = TerminalConOutSetMode;\r
500 SimpleTextOutput.SetAttribute = TerminalConOutSetAttribute;\r
501 SimpleTextOutput.ClearScreen = TerminalConOutClearScreen;\r
502 SimpleTextOutput.SetCursorPosition = TerminalConOutSetCursorPosition;\r
503 SimpleTextOutput.EnableCursor = TerminalConOutEnableCursor;\r
504 SimpleTextOutput.Mode = &TerminalDevice->SimpleTextOutputMode;\r
95276127 505\r
7347d5d6 506 TerminalDevice->SimpleTextOutputMode.MaxMode = 3;\r
3012ce5c 507 //\r
508 // For terminal devices, cursor is always visible\r
509 //\r
510 TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
11baadb6 511 Status = SimpleTextOutput.SetAttribute (\r
512 &TerminalDevice->SimpleTextOutput,\r
513 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
514 );\r
3012ce5c 515 if (EFI_ERROR (Status)) {\r
516 goto ReportError;\r
517 }\r
518\r
11baadb6 519 Status = SimpleTextOutput.Reset (\r
520 &TerminalDevice->SimpleTextOutput,\r
521 FALSE\r
522 );\r
95276127 523 if (EFI_ERROR (Status)) {\r
524 goto ReportError;\r
525 }\r
526\r
11baadb6 527 Status = SimpleTextOutput.SetMode (\r
528 &TerminalDevice->SimpleTextOutput,\r
529 0\r
530 );\r
95276127 531 if (EFI_ERROR (Status)) {\r
532 goto ReportError;\r
533 }\r
534\r
11baadb6 535 Status = SimpleTextOutput.EnableCursor (\r
536 &TerminalDevice->SimpleTextOutput,\r
537 TRUE\r
538 );\r
95276127 539 if (EFI_ERROR (Status)) {\r
540 goto ReportError;\r
541 }\r
95276127 542\r
543 Status = gBS->CreateEvent (\r
544 EVT_TIMER,\r
545 TPL_CALLBACK,\r
546 NULL,\r
547 NULL,\r
548 &TerminalDevice->TwoSecondTimeOut\r
549 );\r
550\r
551 //\r
552 // Build the component name for the child device\r
553 //\r
554 TerminalDevice->ControllerNameTable = NULL;\r
555 switch (TerminalDevice->TerminalType) {\r
e49ef433 556 case PCANSITYPE:\r
5bca971e 557 AddUnicodeString2 (\r
95276127 558 "eng",\r
559 gTerminalComponentName.SupportedLanguages,\r
560 &TerminalDevice->ControllerNameTable,\r
5bca971e 561 (CHAR16 *)L"PC-ANSI Serial Console",\r
562 TRUE\r
95276127 563 );\r
5bca971e 564 AddUnicodeString2 (\r
565 "en",\r
566 gTerminalComponentName2.SupportedLanguages,\r
567 &TerminalDevice->ControllerNameTable,\r
568 (CHAR16 *)L"PC-ANSI Serial Console",\r
569 FALSE\r
570 );\r
571\r
95276127 572 break;\r
573\r
e49ef433 574 case VT100TYPE:\r
5bca971e 575 AddUnicodeString2 (\r
95276127 576 "eng",\r
577 gTerminalComponentName.SupportedLanguages,\r
578 &TerminalDevice->ControllerNameTable,\r
5bca971e 579 (CHAR16 *)L"VT-100 Serial Console",\r
580 TRUE\r
95276127 581 );\r
5bca971e 582 AddUnicodeString2 (\r
583 "en",\r
584 gTerminalComponentName2.SupportedLanguages,\r
585 &TerminalDevice->ControllerNameTable,\r
586 (CHAR16 *)L"VT-100 Serial Console",\r
587 FALSE\r
588 );\r
589\r
95276127 590 break;\r
591\r
e49ef433 592 case VT100PLUSTYPE:\r
5bca971e 593 AddUnicodeString2 (\r
95276127 594 "eng",\r
595 gTerminalComponentName.SupportedLanguages,\r
596 &TerminalDevice->ControllerNameTable,\r
5bca971e 597 (CHAR16 *)L"VT-100+ Serial Console",\r
598 TRUE\r
95276127 599 );\r
5bca971e 600 AddUnicodeString2 (\r
601 "en",\r
602 gTerminalComponentName2.SupportedLanguages,\r
603 &TerminalDevice->ControllerNameTable,\r
604 (CHAR16 *)L"VT-100+ Serial Console",\r
605 FALSE\r
606 );\r
607\r
95276127 608 break;\r
609\r
e49ef433 610 case VTUTF8TYPE:\r
5bca971e 611 AddUnicodeString2 (\r
95276127 612 "eng",\r
613 gTerminalComponentName.SupportedLanguages,\r
614 &TerminalDevice->ControllerNameTable,\r
5bca971e 615 (CHAR16 *)L"VT-UTF8 Serial Console",\r
616 TRUE\r
95276127 617 );\r
5bca971e 618 AddUnicodeString2 (\r
619 "en",\r
620 gTerminalComponentName2.SupportedLanguages,\r
621 &TerminalDevice->ControllerNameTable,\r
622 (CHAR16 *)L"VT-UTF8 Serial Console",\r
623 FALSE\r
624 );\r
625\r
95276127 626 break;\r
627 }\r
628 //\r
629 // Install protocol interfaces for the serial device.\r
630 //\r
631 Status = gBS->InstallMultipleProtocolInterfaces (\r
632 &TerminalDevice->Handle,\r
633 &gEfiDevicePathProtocolGuid,\r
634 TerminalDevice->DevicePath,\r
635 &gEfiSimpleTextInProtocolGuid,\r
636 &TerminalDevice->SimpleInput,\r
66aa04e4 637 &gEfiSimpleTextInputExProtocolGuid,\r
638 &TerminalDevice->SimpleInputEx,\r
95276127 639 &gEfiSimpleTextOutProtocolGuid,\r
640 &TerminalDevice->SimpleTextOutput,\r
641 NULL\r
642 );\r
643 if (EFI_ERROR (Status)) {\r
644 goto Error;\r
645 }\r
646 //\r
647 // if the serial device is a hot plug device, attaches the HotPlugGuid\r
648 // onto the terminal device handle.\r
649 //\r
650 Status = gBS->OpenProtocol (\r
651 Controller,\r
652 &gEfiHotPlugDeviceGuid,\r
653 NULL,\r
654 This->DriverBindingHandle,\r
655 Controller,\r
656 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
657 );\r
658 if (!EFI_ERROR (Status)) {\r
659 Status = gBS->InstallMultipleProtocolInterfaces (\r
660 &TerminalDevice->Handle,\r
661 &gEfiHotPlugDeviceGuid,\r
662 NULL,\r
663 NULL\r
664 );\r
665 }\r
666 //\r
667 // Register the Parent-Child relationship via\r
668 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
669 //\r
670 Status = gBS->OpenProtocol (\r
671 Controller,\r
672 &gEfiSerialIoProtocolGuid,\r
673 (VOID **) &TerminalDevice->SerialIo,\r
674 This->DriverBindingHandle,\r
675 TerminalDevice->Handle,\r
676 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
677 );\r
678 if (EFI_ERROR (Status)) {\r
679 goto Error;\r
680 }\r
681\r
682 if (DefaultNode != NULL) {\r
683 FreePool (DefaultNode);\r
684 }\r
685\r
686 return EFI_SUCCESS;\r
687\r
688ReportError:\r
689 //\r
690 // Report error code before exiting\r
691 //\r
692 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
693 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
97a079ed 694 PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
95276127 695 DevicePath\r
696 );\r
697\r
698Error:\r
699 //\r
700 // Use the Stop() function to free all resources allocated in Start()\r
701 //\r
702 if (TerminalDevice != NULL) {\r
703\r
704 if (TerminalDevice->Handle != NULL) {\r
705 This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
706 } else {\r
707\r
708 if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
709 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
710 }\r
711\r
712 if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
713 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
714 }\r
715\r
66aa04e4 716 if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
717 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
718 }\r
719\r
720 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
721\r
95276127 722 if (TerminalDevice->ControllerNameTable != NULL) {\r
723 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
724 }\r
725\r
726 if (TerminalDevice->DevicePath != NULL) {\r
727 FreePool (TerminalDevice->DevicePath);\r
728 }\r
729\r
730 FreePool (TerminalDevice);\r
731 }\r
732 }\r
733\r
734 if (DefaultNode != NULL) {\r
735 FreePool (DefaultNode);\r
736 }\r
737\r
738 This->Stop (This, Controller, 0, NULL);\r
739\r
740 return Status;\r
741}\r
742\r
e49ef433 743/**\r
ab76200c 744 Stop this driver on Controller by closing Simple Text In, Simple Text\r
8fd98315 745 In Ex, Simple Text Out protocol, and removing parent device path from\r
746 Console Device Environment Variables. \r
e49ef433 747\r
8fd98315 748 @param This Protocol instance pointer.\r
ab76200c 749 @param Controller Handle of device to stop driver on\r
8fd98315 750 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
751 children is zero stop the entire bus driver.\r
752 @param ChildHandleBuffer List of Child Handles to Stop.\r
e49ef433 753\r
ab76200c 754 @retval EFI_SUCCESS This driver is removed Controller.\r
8fd98315 755 @retval other This driver could not be removed from this device.\r
e49ef433 756\r
757**/\r
95276127 758EFI_STATUS\r
759EFIAPI\r
760TerminalDriverBindingStop (\r
761 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
762 IN EFI_HANDLE Controller,\r
763 IN UINTN NumberOfChildren,\r
764 IN EFI_HANDLE *ChildHandleBuffer\r
765 )\r
95276127 766{\r
767 EFI_STATUS Status;\r
768 UINTN Index;\r
769 BOOLEAN AllChildrenStopped;\r
770 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
771 TERMINAL_DEV *TerminalDevice;\r
772 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
773 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
774 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
775\r
776 Status = gBS->HandleProtocol (\r
777 Controller,\r
778 &gEfiDevicePathProtocolGuid,\r
779 (VOID **) &DevicePath\r
780 );\r
781 if (EFI_ERROR (Status)) {\r
782 return Status;\r
783 }\r
95276127 784\r
785 //\r
786 // Complete all outstanding transactions to Controller.\r
787 // Don't allow any new transaction to Controller to be started.\r
788 //\r
789 if (NumberOfChildren == 0) {\r
790 //\r
791 // Close the bus driver\r
792 //\r
793 Status = gBS->OpenProtocol (\r
794 Controller,\r
795 &gEfiCallerIdGuid,\r
796 (VOID **) &ParentDevicePath,\r
797 This->DriverBindingHandle,\r
798 Controller,\r
799 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
800 );\r
801 if (!EFI_ERROR (Status)) {\r
802 //\r
803 // Remove Parent Device Path from\r
804 // the Console Device Environment Variables\r
805 //\r
ff37790d
A
806 TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
807 TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
808 TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 809\r
810 //\r
811 // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
812 //\r
813 Status = gBS->UninstallMultipleProtocolInterfaces (\r
814 Controller,\r
815 &gEfiCallerIdGuid,\r
816 ParentDevicePath,\r
817 NULL\r
818 );\r
819\r
820 //\r
821 // Free the ParentDevicePath that was duplicated in Start()\r
822 //\r
823 if (!EFI_ERROR (Status)) {\r
824 FreePool (ParentDevicePath);\r
825 }\r
826 }\r
827\r
828 gBS->CloseProtocol (\r
829 Controller,\r
830 &gEfiSerialIoProtocolGuid,\r
831 This->DriverBindingHandle,\r
832 Controller\r
833 );\r
834\r
835 gBS->CloseProtocol (\r
836 Controller,\r
837 &gEfiDevicePathProtocolGuid,\r
838 This->DriverBindingHandle,\r
839 Controller\r
840 );\r
841\r
842 return EFI_SUCCESS;\r
843 }\r
844\r
845 AllChildrenStopped = TRUE;\r
846\r
847 for (Index = 0; Index < NumberOfChildren; Index++) {\r
848\r
849 Status = gBS->OpenProtocol (\r
850 ChildHandleBuffer[Index],\r
851 &gEfiSimpleTextOutProtocolGuid,\r
852 (VOID **) &SimpleTextOutput,\r
853 This->DriverBindingHandle,\r
854 ChildHandleBuffer[Index],\r
855 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
856 );\r
857 if (!EFI_ERROR (Status)) {\r
858\r
859 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
860\r
861 gBS->CloseProtocol (\r
862 Controller,\r
863 &gEfiSerialIoProtocolGuid,\r
864 This->DriverBindingHandle,\r
865 ChildHandleBuffer[Index]\r
866 );\r
867\r
868 Status = gBS->UninstallMultipleProtocolInterfaces (\r
869 ChildHandleBuffer[Index],\r
870 &gEfiSimpleTextInProtocolGuid,\r
871 &TerminalDevice->SimpleInput,\r
66aa04e4 872 &gEfiSimpleTextInputExProtocolGuid,\r
873 &TerminalDevice->SimpleInputEx,\r
95276127 874 &gEfiSimpleTextOutProtocolGuid,\r
875 &TerminalDevice->SimpleTextOutput,\r
876 &gEfiDevicePathProtocolGuid,\r
877 TerminalDevice->DevicePath,\r
878 NULL\r
879 );\r
880 if (EFI_ERROR (Status)) {\r
881 gBS->OpenProtocol (\r
882 Controller,\r
883 &gEfiSerialIoProtocolGuid,\r
884 (VOID **) &SerialIo,\r
885 This->DriverBindingHandle,\r
886 ChildHandleBuffer[Index],\r
887 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
888 );\r
889 } else {\r
890\r
891 if (TerminalDevice->ControllerNameTable != NULL) {\r
892 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
893 }\r
894\r
895 Status = gBS->OpenProtocol (\r
896 ChildHandleBuffer[Index],\r
897 &gEfiHotPlugDeviceGuid,\r
898 NULL,\r
899 This->DriverBindingHandle,\r
900 Controller,\r
901 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
902 );\r
903 if (!EFI_ERROR (Status)) {\r
904 Status = gBS->UninstallMultipleProtocolInterfaces (\r
905 ChildHandleBuffer[Index],\r
906 &gEfiHotPlugDeviceGuid,\r
907 NULL,\r
908 NULL\r
909 );\r
910 } else {\r
911 Status = EFI_SUCCESS;\r
912 }\r
913\r
914 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
915 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
66aa04e4 916 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
917 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
95276127 918 FreePool (TerminalDevice->DevicePath);\r
919 FreePool (TerminalDevice);\r
920 }\r
921 }\r
922\r
923 if (EFI_ERROR (Status)) {\r
924 AllChildrenStopped = FALSE;\r
925 }\r
926 }\r
927\r
928 if (!AllChildrenStopped) {\r
929 return EFI_DEVICE_ERROR;\r
930 }\r
931\r
932 return EFI_SUCCESS;\r
933}\r
934\r
66aa04e4 935\r
e49ef433 936/**\r
8fd98315 937 Free notify functions list.\r
66aa04e4 938\r
e49ef433 939 @param ListHead The list head\r
66aa04e4 940\r
8fd98315 941 @retval EFI_SUCCESS Free the notify list successfully.\r
942 @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
66aa04e4 943\r
e49ef433 944**/\r
945EFI_STATUS\r
946TerminalFreeNotifyList (\r
947 IN OUT LIST_ENTRY *ListHead\r
948 )\r
66aa04e4 949{\r
950 TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
951\r
952 if (ListHead == NULL) {\r
953 return EFI_INVALID_PARAMETER;\r
954 }\r
955 while (!IsListEmpty (ListHead)) {\r
956 NotifyNode = CR (\r
fb0b259e 957 ListHead->ForwardLink,\r
958 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
959 NotifyEntry,\r
66aa04e4 960 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
961 );\r
962 RemoveEntryList (ListHead->ForwardLink);\r
ab76200c 963 FreePool (NotifyNode);\r
66aa04e4 964 }\r
fb0b259e 965\r
66aa04e4 966 return EFI_SUCCESS;\r
967}\r
968\r
969\r
8fd98315 970/**\r
971 Update terminal device path in Console Device Environment Variables.\r
972\r
973 @param VariableName The Console Device Environment Variable.\r
11baadb6 974 @param ParentDevicePath The terminal device path to be updated.\r
8fd98315 975\r
976 @return None.\r
66aa04e4 977\r
8fd98315 978**/\r
95276127 979VOID\r
980TerminalUpdateConsoleDevVariable (\r
981 IN CHAR16 *VariableName,\r
982 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
983 )\r
984{\r
985 EFI_STATUS Status;\r
986 UINTN VariableSize;\r
987 UINT8 TerminalType;\r
988 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
989 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
990 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
991\r
992 Variable = NULL;\r
993\r
994 //\r
995 // Get global variable and its size according to the name given.\r
996 //\r
997 Variable = TerminalGetVariableAndSize (\r
998 VariableName,\r
999 &gEfiGlobalVariableGuid,\r
1000 &VariableSize\r
1001 );\r
1002 //\r
1003 // Append terminal device path onto the variable.\r
1004 //\r
e49ef433 1005 for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
95276127 1006 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1007 NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
1008 if (Variable != NULL) {\r
1009 FreePool (Variable);\r
1010 }\r
1011\r
1012 if (TempDevicePath != NULL) {\r
1013 FreePool (TempDevicePath);\r
1014 }\r
1015\r
1016 Variable = NewVariable;\r
1017 }\r
1018\r
1019 VariableSize = GetDevicePathSize (Variable);\r
1020\r
1021 Status = gRT->SetVariable (\r
1022 VariableName,\r
1023 &gEfiGlobalVariableGuid,\r
1024 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1025 VariableSize,\r
1026 Variable\r
1027 );\r
1028 ASSERT_EFI_ERROR (Status);\r
1029 FreePool (Variable);\r
1030\r
1031 return ;\r
1032}\r
1033\r
e49ef433 1034\r
1035/**\r
8fd98315 1036 Remove terminal device path from Console Device Environment Variables.\r
e49ef433 1037\r
8fd98315 1038 @param VariableName Console Device Environment Variables.\r
11baadb6 1039 @param ParentDevicePath The terminal device path to be updated.\r
e49ef433 1040\r
1041 @return None.\r
1042\r
1043**/\r
95276127 1044VOID\r
1045TerminalRemoveConsoleDevVariable (\r
1046 IN CHAR16 *VariableName,\r
1047 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
1048 )\r
95276127 1049{\r
1050 EFI_STATUS Status;\r
1051 BOOLEAN FoundOne;\r
1052 BOOLEAN Match;\r
1053 UINTN VariableSize;\r
1054 UINTN InstanceSize;\r
1055 UINT8 TerminalType;\r
1056 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
1057 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1058 EFI_DEVICE_PATH_PROTOCOL *OriginalVariable;\r
1059 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1060 EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;\r
1061 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1062\r
1063 Variable = NULL;\r
1064 Instance = NULL;\r
1065\r
1066 //\r
1067 // Get global variable and its size according to the name given.\r
1068 //\r
1069 Variable = TerminalGetVariableAndSize (\r
1070 VariableName,\r
1071 &gEfiGlobalVariableGuid,\r
1072 &VariableSize\r
1073 );\r
1074 if (Variable == NULL) {\r
1075 return ;\r
1076 }\r
1077\r
1078 FoundOne = FALSE;\r
1079 OriginalVariable = Variable;\r
1080 NewVariable = NULL;\r
1081\r
1082 //\r
1083 // Get first device path instance from Variable\r
1084 //\r
1085 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1086 if (Instance == NULL) {\r
1087 FreePool (OriginalVariable);\r
1088 return ;\r
1089 }\r
1090 //\r
1091 // Loop through all the device path instances of Variable\r
1092 //\r
1093 do {\r
1094 //\r
1095 // Loop through all the terminal types that this driver supports\r
1096 //\r
1097 Match = FALSE;\r
e49ef433 1098 for (TerminalType = PCANSITYPE; TerminalType <= VTUTF8TYPE; TerminalType++) {\r
95276127 1099\r
1100 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1101\r
1102 //\r
11baadb6 1103 // Compare the generated device path to the current device path instance\r
95276127 1104 //\r
1105 if (TempDevicePath != NULL) {\r
1106 if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
1107 Match = TRUE;\r
1108 FoundOne = TRUE;\r
1109 }\r
1110\r
1111 FreePool (TempDevicePath);\r
1112 }\r
1113 }\r
1114 //\r
1115 // If a match was not found, then keep the current device path instance\r
1116 //\r
1117 if (!Match) {\r
1118 SavedNewVariable = NewVariable;\r
1119 NewVariable = AppendDevicePathInstance (NewVariable, Instance);\r
1120 if (SavedNewVariable != NULL) {\r
1121 FreePool (SavedNewVariable);\r
1122 }\r
1123 }\r
1124 //\r
1125 // Get next device path instance from Variable\r
1126 //\r
1127 FreePool (Instance);\r
1128 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1129 } while (Instance != NULL);\r
1130\r
1131 FreePool (OriginalVariable);\r
1132\r
1133 if (FoundOne) {\r
1134 VariableSize = GetDevicePathSize (NewVariable);\r
1135\r
1136 Status = gRT->SetVariable (\r
1137 VariableName,\r
1138 &gEfiGlobalVariableGuid,\r
1139 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1140 VariableSize,\r
1141 NewVariable\r
1142 );\r
1143 ASSERT_EFI_ERROR (Status);\r
1144 }\r
1145\r
1146 if (NewVariable != NULL) {\r
1147 FreePool (NewVariable);\r
1148 }\r
1149\r
1150 return ;\r
1151}\r
1152\r
95276127 1153\r
e49ef433 1154/**\r
95276127 1155 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
1156 buffer, and the size of the buffer. On failure return NULL.\r
1157\r
e49ef433 1158 @param Name String part of EFI variable name\r
1159 @param VendorGuid GUID part of EFI variable name\r
1160 @param VariableSize Returns the size of the EFI variable that was read\r
95276127 1161\r
e49ef433 1162 @return Dynamically allocated memory that contains a copy of the EFI variable.\r
11baadb6 1163 Caller is responsible freeing the buffer. If variable was not read, \r
1164 NULL returned.\r
95276127 1165\r
e49ef433 1166**/\r
1167VOID *\r
1168TerminalGetVariableAndSize (\r
1169 IN CHAR16 *Name,\r
1170 IN EFI_GUID *VendorGuid,\r
1171 OUT UINTN *VariableSize\r
1172 )\r
95276127 1173{\r
1174 EFI_STATUS Status;\r
1175 UINTN BufferSize;\r
1176 VOID *Buffer;\r
1177\r
1178 Buffer = NULL;\r
1179\r
1180 //\r
1181 // Pass in a small size buffer to find the actual variable size.\r
1182 //\r
1183 BufferSize = 1;\r
1184 Buffer = AllocatePool (BufferSize);\r
1185 if (Buffer == NULL) {\r
1186 *VariableSize = 0;\r
1187 return NULL;\r
1188 }\r
1189\r
1190 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1191\r
1192 if (Status == EFI_SUCCESS) {\r
1193 *VariableSize = BufferSize;\r
1194 return Buffer;\r
1195\r
1196 } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
1197 //\r
1198 // Allocate the buffer to return\r
1199 //\r
1200 FreePool (Buffer);\r
1201 Buffer = AllocatePool (BufferSize);\r
1202 if (Buffer == NULL) {\r
1203 *VariableSize = 0;\r
1204 return NULL;\r
1205 }\r
1206 //\r
1207 // Read variable into the allocated buffer.\r
1208 //\r
1209 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1210 if (EFI_ERROR (Status)) {\r
1211 BufferSize = 0;\r
1212 FreePool (Buffer);\r
1213 Buffer = NULL;\r
1214 }\r
1215 } else {\r
1216 //\r
1217 // Variable not found or other errors met.\r
1218 //\r
1219 BufferSize = 0;\r
1220 FreePool (Buffer);\r
1221 Buffer = NULL;\r
1222 }\r
1223\r
1224 *VariableSize = BufferSize;\r
1225 return Buffer;\r
1226}\r
1227\r
8fd98315 1228/**\r
11baadb6 1229 Build terminal device path according to terminal type.\r
8fd98315 1230\r
1231 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.\r
11baadb6 1232 @param ParentDevicePath Parent device path.\r
8fd98315 1233 @param TerminalDevicePath Returned terminal device path, if building successfully.\r
1234\r
1235 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.\r
1236 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.\r
1237 @retval EFI_SUCCESS Build terminal device path successfully.\r
1238\r
1239**/\r
95276127 1240EFI_STATUS\r
1241SetTerminalDevicePath (\r
1242 IN UINT8 TerminalType,\r
1243 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
1244 OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath\r
1245 )\r
1246{\r
1247 VENDOR_DEVICE_PATH Node;\r
1248\r
1249 *TerminalDevicePath = NULL;\r
1250 Node.Header.Type = MESSAGING_DEVICE_PATH;\r
1251 Node.Header.SubType = MSG_VENDOR_DP;\r
1252\r
1253 //\r
ab76200c 1254 // Generate terminal device path node according to terminal type.\r
95276127 1255 //\r
1256 switch (TerminalType) {\r
1257\r
e49ef433 1258 case PCANSITYPE:\r
ab76200c 1259 CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
95276127 1260 break;\r
1261\r
e49ef433 1262 case VT100TYPE:\r
ab76200c 1263 CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
95276127 1264 break;\r
1265\r
e49ef433 1266 case VT100PLUSTYPE:\r
ab76200c 1267 CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
95276127 1268 break;\r
1269\r
e49ef433 1270 case VTUTF8TYPE:\r
ab76200c 1271 CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
95276127 1272 break;\r
1273\r
1274 default:\r
1275 return EFI_UNSUPPORTED;\r
95276127 1276 }\r
1277\r
ab76200c 1278 //\r
1279 // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
1280 //\r
95276127 1281 SetDevicePathNodeLength (\r
1282 &Node.Header,\r
1283 sizeof (VENDOR_DEVICE_PATH)\r
1284 );\r
ab76200c 1285\r
95276127 1286 //\r
ab76200c 1287 // Append the terminal node onto parent device path\r
95276127 1288 // to generate a complete terminal device path.\r
1289 //\r
1290 *TerminalDevicePath = AppendDevicePathNode (\r
1291 ParentDevicePath,\r
1292 (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
1293 );\r
1294 if (*TerminalDevicePath == NULL) {\r
1295 return EFI_OUT_OF_RESOURCES;\r
1296 }\r
1297\r
1298 return EFI_SUCCESS;\r
1299}\r
1300\r
8fd98315 1301/**\r
1302 Initialize the Raw Data FIFO.\r
1303\r
1304 @param TerminalDevice The terminal device.\r
1305\r
1306 @return None.\r
1307\r
1308**/\r
95276127 1309VOID\r
1310InitializeRawFiFo (\r
1311 IN TERMINAL_DEV *TerminalDevice\r
1312 )\r
1313{\r
1314 //\r
11baadb6 1315 // Make the raw FIFO empty.\r
95276127 1316 //\r
1317 TerminalDevice->RawFiFo.Head = TerminalDevice->RawFiFo.Tail;\r
1318}\r
1319\r
8fd98315 1320/**\r
1321 Initialize the Unicode FIFO.\r
1322\r
1323 @param TerminalDevice The terminal device.\r
1324\r
1325 @return None.\r
1326\r
1327**/\r
95276127 1328VOID\r
1329InitializeUnicodeFiFo (\r
1330 IN TERMINAL_DEV *TerminalDevice\r
1331 )\r
1332{\r
1333 //\r
11baadb6 1334 // Make the unicode FIFO empty\r
95276127 1335 //\r
1336 TerminalDevice->UnicodeFiFo.Head = TerminalDevice->UnicodeFiFo.Tail;\r
1337}\r
1338\r
8fd98315 1339/**\r
1340 Initialize the EFI Key FIFO.\r
1341\r
1342 @param TerminalDevice The terminal device.\r
1343\r
1344 @return None.\r
1345\r
1346**/\r
95276127 1347VOID\r
1348InitializeEfiKeyFiFo (\r
1349 IN TERMINAL_DEV *TerminalDevice\r
1350 )\r
1351{\r
1352 //\r
11baadb6 1353 // Make the efi key FIFO empty\r
95276127 1354 //\r
1355 TerminalDevice->EfiKeyFiFo.Head = TerminalDevice->EfiKeyFiFo.Tail;\r
1356}\r
97a079ed
A
1357\r
1358\r
1359/**\r
1360 The user Entry Point for module Terminal. The user code starts with this function.\r
1361\r
ab76200c 1362 @param ImageHandle The firmware allocated handle for the EFI image.\r
1363 @param SystemTable A pointer to the EFI System Table.\r
fb0b259e 1364\r
97a079ed
A
1365 @retval EFI_SUCCESS The entry point is executed successfully.\r
1366 @retval other Some error occurs when executing this entry point.\r
1367\r
1368**/\r
1369EFI_STATUS\r
1370EFIAPI\r
1371InitializeTerminal(\r
1372 IN EFI_HANDLE ImageHandle,\r
1373 IN EFI_SYSTEM_TABLE *SystemTable\r
1374 )\r
1375{\r
1376 EFI_STATUS Status;\r
1377\r
1378 //\r
1379 // Install driver model protocol(s).\r
1380 //\r
5bca971e 1381 Status = EfiLibInstallDriverBindingComponentName2 (\r
97a079ed
A
1382 ImageHandle,\r
1383 SystemTable,\r
1384 &gTerminalDriverBinding,\r
1385 ImageHandle,\r
1386 &gTerminalComponentName,\r
5bca971e 1387 &gTerminalComponentName2\r
97a079ed
A
1388 );\r
1389 ASSERT_EFI_ERROR (Status);\r
1390\r
97a079ed
A
1391 return Status;\r
1392}\r