]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
MdeModulePkg/TerminalDxe: Separate controller name init logic
[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
8ce87fff 5Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 6This program and the accompanying materials\r
95276127 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
f9163275 32EFI_GUID *mTerminalType[] = {\r
6b88ceec
A
33 &gEfiPcAnsiGuid,\r
34 &gEfiVT100Guid,\r
35 &gEfiVT100PlusGuid,\r
6e3227c8
RF
36 &gEfiVTUTF8Guid,\r
37 &gEfiTtyTermGuid\r
6b88ceec
A
38};\r
39\r
40\r
fa3f99e5
RN
41CHAR16 *mSerialConsoleNames[] = {\r
42 L"PC-ANSI Serial Console",\r
43 L"VT-100 Serial Console",\r
44 L"VT-100+ Serial Console",\r
45 L"VT-UTF8 Serial Console",\r
46 L"Tty Terminal Serial Console"\r
47};\r
48\r
204ba917 49TERMINAL_DEV mTerminalDevTemplate = {\r
6b88ceec
A
50 TERMINAL_DEV_SIGNATURE,\r
51 NULL,\r
52 0,\r
53 NULL,\r
54 NULL,\r
55 { // SimpleTextInput\r
56 TerminalConInReset,\r
57 TerminalConInReadKeyStroke,\r
58 NULL\r
59 },\r
60 { // SimpleTextOutput\r
61 TerminalConOutReset,\r
62 TerminalConOutOutputString,\r
63 TerminalConOutTestString,\r
64 TerminalConOutQueryMode,\r
65 TerminalConOutSetMode,\r
66 TerminalConOutSetAttribute,\r
67 TerminalConOutClearScreen,\r
68 TerminalConOutSetCursorPosition,\r
69 TerminalConOutEnableCursor,\r
70 NULL\r
71 },\r
72 { // SimpleTextOutputMode\r
73 1, // MaxMode\r
11baadb6 74 0, // Mode\r
6b88ceec
A
75 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK), // Attribute\r
76 0, // CursorColumn\r
77 0, // CursorRow\r
78 TRUE // CursorVisible\r
79 },\r
79d07c66 80 NULL, // TerminalConsoleModeData\r
11baadb6 81 0, // SerialInTimeOut\r
5c998646 82\r
83 NULL, // RawFifo\r
84 NULL, // UnicodeFiFo\r
85 NULL, // EfiKeyFiFo\r
47b612db 86 NULL, // EfiKeyFiFoForNotify\r
5c998646 87\r
6b88ceec 88 NULL, // ControllerNameTable\r
f0368006 89 NULL, // TimerEvent\r
11baadb6 90 NULL, // TwoSecondTimeOut\r
6b88ceec
A
91 INPUT_STATE_DEFAULT,\r
92 RESET_STATE_DEFAULT,\r
014f93ac
RF
93 {\r
94 0,\r
95 0,\r
96 0\r
97 },\r
98 0,\r
66aa04e4 99 FALSE,\r
100 { // SimpleTextInputEx\r
101 TerminalConInResetEx,\r
102 TerminalConInReadKeyStrokeEx,\r
103 NULL,\r
104 TerminalConInSetState,\r
105 TerminalConInRegisterKeyNotify,\r
106 TerminalConInUnregisterKeyNotify,\r
107 },\r
11baadb6 108 { // NotifyList\r
66aa04e4 109 NULL,\r
110 NULL,\r
47b612db
SZ
111 },\r
112 NULL // KeyNotifyProcessEvent\r
6b88ceec
A
113};\r
114\r
79d07c66 115TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {\r
116 {100, 31},\r
117 //\r
118 // New modes can be added here.\r
79d07c66 119 //\r
79d07c66 120};\r
121\r
f9163275
RN
122/**\r
123 Convert the GUID representation of terminal type to enum type.\r
124\r
125 @param Guid The GUID representation of terminal type.\r
126\r
127 @return The terminal type in enum type.\r
128**/\r
129TERMINAL_TYPE\r
130TerminalTypeFromGuid (\r
131 IN EFI_GUID *Guid\r
132)\r
133{\r
134 TERMINAL_TYPE Type;\r
135\r
136 for (Type = 0; Type < ARRAY_SIZE (mTerminalType); Type++) {\r
137 if (CompareGuid (Guid, mTerminalType[Type])) {\r
138 break;\r
139 }\r
140 }\r
141 return Type;\r
142}\r
143\r
8fd98315 144/**\r
677fdb90 145 Test to see if this driver supports Controller.\r
8fd98315 146\r
147 @param This Protocol instance pointer.\r
ab76200c 148 @param Controller Handle of device to test\r
8fd98315 149 @param RemainingDevicePath Optional parameter use to pick a specific child\r
150 device to start.\r
151\r
ab76200c 152 @retval EFI_SUCCESS This driver supports this device.\r
153 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
154 @retval other This driver does not support this device.\r
6b88ceec 155\r
8fd98315 156**/\r
95276127 157EFI_STATUS\r
158EFIAPI\r
159TerminalDriverBindingSupported (\r
160 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
161 IN EFI_HANDLE Controller,\r
162 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
163 )\r
164{\r
165 EFI_STATUS Status;\r
166 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
167 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
168 VENDOR_DEVICE_PATH *Node;\r
169\r
170 //\r
171 // If remaining device path is not NULL, then make sure it is a\r
172 // device path that describes a terminal communications protocol.\r
173 //\r
174 if (RemainingDevicePath != NULL) {\r
95276127 175 //\r
e3dcffcc 176 // Check if RemainingDevicePath is the End of Device Path Node,\r
af4a6385 177 // if yes, go on checking other conditions\r
95276127 178 //\r
af4a6385 179 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
180 //\r
181 // If RemainingDevicePath isn't the End of Device Path Node,\r
182 // check its validation\r
183 //\r
184 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
e3dcffcc 185\r
af4a6385 186 if (Node->Header.Type != MESSAGING_DEVICE_PATH ||\r
187 Node->Header.SubType != MSG_VENDOR_DP ||\r
188 DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) {\r
e3dcffcc 189\r
af4a6385 190 return EFI_UNSUPPORTED;\r
e3dcffcc 191\r
af4a6385 192 }\r
193 //\r
6e3227c8 194 // only supports PC ANSI, VT100, VT100+, VT-UTF8, and TtyTerm terminal types\r
af4a6385 195 //\r
f9163275 196 if (TerminalTypeFromGuid (&Node->Guid) == ARRAY_SIZE (mTerminalType)) {\r
af4a6385 197 return EFI_UNSUPPORTED;\r
198 }\r
95276127 199 }\r
200 }\r
201 //\r
202 // Open the IO Abstraction(s) needed to perform the supported test\r
af4a6385 203 // The Controller must support the Serial I/O Protocol.\r
204 // This driver is a bus driver with at most 1 child device, so it is\r
205 // ok for it to be already started.\r
95276127 206 //\r
207 Status = gBS->OpenProtocol (\r
208 Controller,\r
af4a6385 209 &gEfiSerialIoProtocolGuid,\r
210 (VOID **) &SerialIo,\r
95276127 211 This->DriverBindingHandle,\r
212 Controller,\r
213 EFI_OPEN_PROTOCOL_BY_DRIVER\r
214 );\r
215 if (Status == EFI_ALREADY_STARTED) {\r
216 return EFI_SUCCESS;\r
217 }\r
218\r
219 if (EFI_ERROR (Status)) {\r
220 return Status;\r
221 }\r
222\r
af4a6385 223 //\r
224 // Close the I/O Abstraction(s) used to perform the supported test\r
225 //\r
95276127 226 gBS->CloseProtocol (\r
227 Controller,\r
af4a6385 228 &gEfiSerialIoProtocolGuid,\r
95276127 229 This->DriverBindingHandle,\r
230 Controller\r
231 );\r
232\r
233 //\r
af4a6385 234 // Open the EFI Device Path protocol needed to perform the supported test\r
95276127 235 //\r
236 Status = gBS->OpenProtocol (\r
237 Controller,\r
af4a6385 238 &gEfiDevicePathProtocolGuid,\r
239 (VOID **) &ParentDevicePath,\r
95276127 240 This->DriverBindingHandle,\r
241 Controller,\r
242 EFI_OPEN_PROTOCOL_BY_DRIVER\r
243 );\r
244 if (Status == EFI_ALREADY_STARTED) {\r
245 return EFI_SUCCESS;\r
246 }\r
247\r
248 if (EFI_ERROR (Status)) {\r
249 return Status;\r
250 }\r
af4a6385 251\r
95276127 252 //\r
af4a6385 253 // Close protocol, don't use device path protocol in the Support() function\r
95276127 254 //\r
255 gBS->CloseProtocol (\r
256 Controller,\r
af4a6385 257 &gEfiDevicePathProtocolGuid,\r
95276127 258 This->DriverBindingHandle,\r
259 Controller\r
260 );\r
261\r
262 return Status;\r
263}\r
264\r
e3dcffcc 265/**\r
266 Build the terminal device path for the child device according to the\r
267 terminal type.\r
268\r
269 @param ParentDevicePath Parent device path.\r
270 @param RemainingDevicePath A specific child device.\r
271\r
272 @return The child device path built.\r
273\r
274**/\r
275EFI_DEVICE_PATH_PROTOCOL*\r
276EFIAPI\r
277BuildTerminalDevpath (\r
278 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
279 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
280 )\r
281{\r
282 EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath;\r
8ce87fff 283 TERMINAL_TYPE TerminalType;\r
e3dcffcc 284 VENDOR_DEVICE_PATH *Node;\r
285 EFI_STATUS Status;\r
286\r
287 TerminalDevicePath = NULL;\r
e3dcffcc 288\r
289 //\r
290 // Use the RemainingDevicePath to determine the terminal type\r
291 //\r
292 Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath;\r
293 if (Node == NULL) {\r
cf1e634b 294 TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
e3dcffcc 295\r
296 } else if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) {\r
297\r
8ce87fff 298 TerminalType = TerminalTypePcAnsi;\r
e3dcffcc 299\r
300 } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) {\r
301\r
8ce87fff 302 TerminalType = TerminalTypeVt100;\r
e3dcffcc 303\r
304 } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) {\r
305\r
8ce87fff 306 TerminalType = TerminalTypeVt100Plus;\r
e3dcffcc 307\r
308 } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) {\r
309\r
8ce87fff 310 TerminalType = TerminalTypeVtUtf8;\r
e3dcffcc 311\r
6e3227c8
RF
312 } else if (CompareGuid (&Node->Guid, &gEfiTtyTermGuid)) {\r
313\r
8ce87fff 314 TerminalType = TerminalTypeTtyTerm;\r
6e3227c8 315\r
e3dcffcc 316 } else {\r
317 return NULL;\r
318 }\r
319\r
320 //\r
321 // Build the device path for the child device\r
322 //\r
323 Status = SetTerminalDevicePath (\r
324 TerminalType,\r
325 ParentDevicePath,\r
326 &TerminalDevicePath\r
327 );\r
328 if (EFI_ERROR (Status)) {\r
329 return NULL;\r
330 }\r
331 return TerminalDevicePath;\r
332}\r
333\r
334/**\r
335 Compare a device path data structure to that of all the nodes of a\r
336 second device path instance.\r
337\r
338 @param Multi A pointer to a multi-instance device path data structure.\r
339 @param Single A pointer to a single-instance device path data structure.\r
340\r
341 @retval TRUE If the Single is contained within Multi.\r
342 @retval FALSE The Single is not match within Multi.\r
343\r
344**/\r
345BOOLEAN\r
346MatchDevicePaths (\r
347 IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
348 IN EFI_DEVICE_PATH_PROTOCOL *Single\r
349 )\r
350{\r
351 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
352 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
353 UINTN Size;\r
354\r
355 DevicePath = Multi;\r
356 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
357 //\r
358 // Search for the match of 'Single' in 'Multi'\r
359 //\r
360 while (DevicePathInst != NULL) {\r
361 //\r
362 // If the single device path is found in multiple device paths,\r
363 // return success\r
364 //\r
365 if (CompareMem (Single, DevicePathInst, Size) == 0) {\r
366 FreePool (DevicePathInst);\r
367 return TRUE;\r
368 }\r
369\r
370 FreePool (DevicePathInst);\r
371 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
372 }\r
373\r
374 return FALSE;\r
375}\r
376\r
377/**\r
378 Check whether the terminal device path is in the global variable.\r
379\r
380 @param VariableName Pointer to one global variable.\r
381 @param TerminalDevicePath Pointer to the terminal device's device path.\r
382\r
383 @retval TRUE The devcie is in the global variable.\r
384 @retval FALSE The devcie is not in the global variable.\r
385\r
386**/\r
387BOOLEAN\r
388IsTerminalInConsoleVariable (\r
389 IN CHAR16 *VariableName,\r
390 IN EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath\r
391 )\r
392{\r
393 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
394 BOOLEAN ReturnFlag;\r
395\r
396 //\r
397 // Get global variable and its size according to the name given.\r
398 //\r
f01b91ae 399 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
e3dcffcc 400 if (Variable == NULL) {\r
401 return FALSE;\r
402 }\r
403\r
404 //\r
405 // Check whether the terminal device path is one of the variable instances.\r
406 //\r
407 ReturnFlag = MatchDevicePaths (Variable, TerminalDevicePath);\r
408\r
409 FreePool (Variable);\r
410\r
411 return ReturnFlag;\r
412}\r
413\r
414/**\r
415 Free notify functions list.\r
416\r
417 @param ListHead The list head\r
418\r
419 @retval EFI_SUCCESS Free the notify list successfully.\r
420 @retval EFI_INVALID_PARAMETER ListHead is NULL.\r
421\r
422**/\r
423EFI_STATUS\r
424TerminalFreeNotifyList (\r
425 IN OUT LIST_ENTRY *ListHead\r
426 )\r
427{\r
428 TERMINAL_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
429\r
430 if (ListHead == NULL) {\r
431 return EFI_INVALID_PARAMETER;\r
432 }\r
433 while (!IsListEmpty (ListHead)) {\r
434 NotifyNode = CR (\r
435 ListHead->ForwardLink,\r
436 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
437 NotifyEntry,\r
438 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
439 );\r
440 RemoveEntryList (ListHead->ForwardLink);\r
441 FreePool (NotifyNode);\r
442 }\r
443\r
444 return EFI_SUCCESS;\r
445}\r
446\r
79d07c66 447/**\r
448 Initialize all the text modes which the terminal console supports.\r
449\r
450 It returns information for available text modes that the terminal can support.\r
451\r
452 @param[out] TextModeCount The total number of text modes that terminal console supports.\r
453 @param[out] TextModeData The buffer to the text modes column and row information.\r
454 Caller is responsible to free it when it's non-NULL.\r
455\r
456 @retval EFI_SUCCESS The supporting mode information is returned.\r
457 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
458\r
459**/\r
460EFI_STATUS\r
461InitializeTerminalConsoleTextMode (\r
462 OUT UINTN *TextModeCount,\r
463 OUT TERMINAL_CONSOLE_MODE_DATA **TextModeData\r
464 )\r
465{\r
466 UINTN Index;\r
467 UINTN Count;\r
468 TERMINAL_CONSOLE_MODE_DATA *ModeBuffer;\r
469 TERMINAL_CONSOLE_MODE_DATA *NewModeBuffer;\r
470 UINTN ValidCount;\r
471 UINTN ValidIndex;\r
472 \r
473 if ((TextModeCount == NULL) || (TextModeData == NULL)) {\r
474 return EFI_INVALID_PARAMETER;\r
475 }\r
476 \r
79d07c66 477 Count = sizeof (mTerminalConsoleModeData) / sizeof (TERMINAL_CONSOLE_MODE_DATA);\r
79d07c66 478 \r
479 //\r
480 // Get defined mode buffer pointer.\r
481 //\r
482 ModeBuffer = mTerminalConsoleModeData;\r
483 \r
484 //\r
485 // Here we make sure that the final mode exposed does not include the duplicated modes,\r
486 // and does not include the invalid modes which exceed the max column and row.\r
487 // Reserve 2 modes for 80x25, 80x50 of terminal console.\r
488 //\r
489 NewModeBuffer = AllocateZeroPool (sizeof (TERMINAL_CONSOLE_MODE_DATA) * (Count + 2));\r
490 ASSERT (NewModeBuffer != NULL);\r
491\r
492 //\r
493 // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec.\r
494 //\r
495 ValidCount = 0; \r
496\r
497 NewModeBuffer[ValidCount].Columns = 80;\r
498 NewModeBuffer[ValidCount].Rows = 25;\r
499 ValidCount++;\r
500\r
501 NewModeBuffer[ValidCount].Columns = 80;\r
502 NewModeBuffer[ValidCount].Rows = 50;\r
503 ValidCount++;\r
504 \r
505 //\r
506 // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer.\r
507 //\r
508 for (Index = 0; Index < Count; Index++) {\r
509 if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0)) {\r
510 //\r
511 // Skip the pre-defined mode which is invalid.\r
512 //\r
513 continue;\r
514 }\r
515 for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) {\r
516 if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) &&\r
517 (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) {\r
518 //\r
519 // Skip the duplicated mode.\r
520 //\r
521 break;\r
522 }\r
523 }\r
524 if (ValidIndex == ValidCount) {\r
525 NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns;\r
526 NewModeBuffer[ValidCount].Rows = ModeBuffer[Index].Rows;\r
527 ValidCount++;\r
528 }\r
529 }\r
530 \r
531 DEBUG_CODE (\r
532 for (Index = 0; Index < ValidCount; Index++) {\r
533 DEBUG ((EFI_D_INFO, "Terminal - Mode %d, Column = %d, Row = %d\n", \r
534 Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows)); \r
535 }\r
536 );\r
537 \r
538 //\r
539 // Return valid mode count and mode information buffer.\r
540 //\r
541 *TextModeCount = ValidCount;\r
542 *TextModeData = NewModeBuffer;\r
543 return EFI_SUCCESS;\r
544}\r
e3dcffcc 545\r
fa3f99e5
RN
546/**\r
547 Initialize the controller name table.\r
548\r
549 @param TerminalType The terminal type.\r
550 @param ControllerNameTable The controller name table.\r
551\r
552 @retval EFI_SUCCESS The controller name table is initialized successfully.\r
553 @retval others Return status of AddUnicodeString2 ().\r
554**/\r
555EFI_STATUS\r
556InitializeControllerNameTable (\r
557 TERMINAL_TYPE TerminalType,\r
558 EFI_UNICODE_STRING_TABLE **ControllerNameTable\r
559)\r
560{\r
561 EFI_STATUS Status;\r
562 EFI_UNICODE_STRING_TABLE *Table;\r
563\r
564 ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
565 Table = NULL;\r
566 Status = AddUnicodeString2 (\r
567 "eng",\r
568 gTerminalComponentName.SupportedLanguages,\r
569 &Table,\r
570 mSerialConsoleNames[TerminalType],\r
571 TRUE\r
572 );\r
573 if (!EFI_ERROR (Status)) {\r
574 Status = AddUnicodeString2 (\r
575 "en",\r
576 gTerminalComponentName2.SupportedLanguages,\r
577 &Table,\r
578 mSerialConsoleNames[TerminalType],\r
579 FALSE\r
580 );\r
581 if (EFI_ERROR (Status)) {\r
582 FreeUnicodeStringTable (Table);\r
583 }\r
584 }\r
585 if (!EFI_ERROR (Status)) {\r
586 *ControllerNameTable = Table;\r
587 }\r
588 return Status;\r
589}\r
590\r
e49ef433 591/**\r
ab76200c 592 Start this driver on Controller by opening a Serial IO protocol,\r
8fd98315 593 reading Device Path, and creating a child handle with a Simple Text In,\r
594 Simple Text In Ex and Simple Text Out protocol, and device path protocol.\r
595 And store Console Device Environment Variables.\r
e49ef433 596\r
8fd98315 597 @param This Protocol instance pointer.\r
ab76200c 598 @param Controller Handle of device to bind driver to\r
8fd98315 599 @param RemainingDevicePath Optional parameter use to pick a specific child\r
600 device to start.\r
e49ef433 601\r
ab76200c 602 @retval EFI_SUCCESS This driver is added to Controller.\r
603 @retval EFI_ALREADY_STARTED This driver is already running on Controller.\r
604 @retval other This driver does not support this device.\r
e49ef433 605\r
606**/\r
95276127 607EFI_STATUS\r
608EFIAPI\r
609TerminalDriverBindingStart (\r
610 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
611 IN EFI_HANDLE Controller,\r
612 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
613 )\r
95276127 614{\r
615 EFI_STATUS Status;\r
616 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
617 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
618 VENDOR_DEVICE_PATH *Node;\r
95276127 619 EFI_SERIAL_IO_MODE *Mode;\r
620 UINTN SerialInTimeOut;\r
621 TERMINAL_DEV *TerminalDevice;\r
8ce87fff 622 TERMINAL_TYPE TerminalType;\r
95276127 623 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
624 UINTN EntryCount;\r
625 UINTN Index;\r
626 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
c4f9201e 627 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
e3dcffcc 628 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextInput;\r
629 BOOLEAN ConInSelected;\r
630 BOOLEAN ConOutSelected;\r
631 BOOLEAN NullRemaining;\r
632 BOOLEAN SimTxtInInstalled;\r
633 BOOLEAN SimTxtOutInstalled;\r
634 BOOLEAN FirstEnter;\r
79d07c66 635 UINTN ModeCount;\r
e3dcffcc 636\r
637 TerminalDevice = NULL;\r
cf1e634b
HG
638 ConInSelected = FALSE;\r
639 ConOutSelected = FALSE;\r
f8fdf8cd 640 NullRemaining = FALSE;\r
e3dcffcc 641 SimTxtInInstalled = FALSE;\r
642 SimTxtOutInstalled = FALSE;\r
643 FirstEnter = FALSE;\r
95276127 644 //\r
645 // Get the Device Path Protocol to build the device path of the child device\r
646 //\r
647 Status = gBS->OpenProtocol (\r
648 Controller,\r
649 &gEfiDevicePathProtocolGuid,\r
650 (VOID **) &ParentDevicePath,\r
651 This->DriverBindingHandle,\r
652 Controller,\r
653 EFI_OPEN_PROTOCOL_BY_DRIVER\r
654 );\r
655 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
656 return Status;\r
657 }\r
95276127 658\r
659 //\r
660 // Open the Serial I/O Protocol BY_DRIVER. It might already be started.\r
661 //\r
662 Status = gBS->OpenProtocol (\r
663 Controller,\r
664 &gEfiSerialIoProtocolGuid,\r
665 (VOID **) &SerialIo,\r
666 This->DriverBindingHandle,\r
667 Controller,\r
668 EFI_OPEN_PROTOCOL_BY_DRIVER\r
669 );\r
670 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
671 return Status;\r
672 }\r
673\r
674 if (Status != EFI_ALREADY_STARTED) {\r
675 //\r
e3dcffcc 676 // the serial I/O protocol never be opened before, it is the first\r
677 // time to start the serial Io controller\r
95276127 678 //\r
e3dcffcc 679 FirstEnter = TRUE;\r
95276127 680 }\r
e3dcffcc 681\r
95276127 682 //\r
e3dcffcc 683 // Serial I/O is not already open by this driver, then tag the handle\r
684 // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and\r
685 // StdErrDev variables with the list of possible terminal types on this\r
686 // serial port.\r
95276127 687 //\r
e3dcffcc 688 Status = gBS->OpenProtocol (\r
95276127 689 Controller,\r
e3dcffcc 690 &gEfiCallerIdGuid,\r
691 NULL,\r
692 This->DriverBindingHandle,\r
693 Controller,\r
694 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
95276127 695 );\r
e3dcffcc 696 if (EFI_ERROR (Status)) {\r
697 Status = gBS->InstallMultipleProtocolInterfaces (\r
698 &Controller,\r
699 &gEfiCallerIdGuid,\r
700 DuplicateDevicePath (ParentDevicePath),\r
701 NULL\r
702 );\r
703 if (EFI_ERROR (Status)) {\r
704 goto Error;\r
95276127 705 }\r
706\r
e3dcffcc 707 if (!IsHotPlugDevice (ParentDevicePath)) {\r
708 //\r
709 // if the serial device is a hot plug device, do not update the\r
710 // ConInDev, ConOutDev, and StdErrDev variables.\r
711 //\r
712 TerminalUpdateConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
713 TerminalUpdateConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
714 TerminalUpdateConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 715 }\r
716 }\r
e3dcffcc 717\r
718 //\r
719 // Check the requirement for the SimpleTxtIn and SimpleTxtOut protocols\r
95276127 720 //\r
e3dcffcc 721 // Simple In/Out Protocol will not be installed onto the handle if the\r
722 // device path to the handle is not present in the ConIn/ConOut\r
723 // environment variable. But If RemainingDevicePath is NULL, then always\r
724 // produce both Simple In and Simple Text Output Protocols. This is required\r
725 // for the connect all sequences to make sure all possible consoles are\r
726 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 727 //\r
728 if (RemainingDevicePath == NULL) {\r
e3dcffcc 729 NullRemaining = TRUE;\r
730 }\r
731\r
732 DevicePath = BuildTerminalDevpath (ParentDevicePath, RemainingDevicePath);\r
733 if (DevicePath != NULL) {\r
734 ConInSelected = IsTerminalInConsoleVariable (L"ConIn", DevicePath);\r
735 ConOutSelected = IsTerminalInConsoleVariable (L"ConOut", DevicePath);\r
736 FreePool (DevicePath);\r
737 } else {\r
738 goto Error;\r
739 }\r
740 //\r
741 // Not create the child terminal handle if both Simple In/In Ex and\r
742 // Simple text Out protocols are not required to be published\r
743 //\r
744 if ((!ConInSelected)&&(!ConOutSelected)&&(!NullRemaining)) {\r
745 goto Error;\r
746 }\r
747\r
748 //\r
749 // create the child terminal handle during first entry\r
750 //\r
751 if (FirstEnter) {\r
752 //\r
0a18956d 753 // First enther the start function\r
e3dcffcc 754 //\r
755 FirstEnter = FALSE;\r
756 //\r
757 // Make sure a child handle does not already exist. This driver can only\r
758 // produce one child per serial port.\r
759 //\r
760 Status = gBS->OpenProtocolInformation (\r
761 Controller,\r
762 &gEfiSerialIoProtocolGuid,\r
763 &OpenInfoBuffer,\r
764 &EntryCount\r
765 );\r
766 if (!EFI_ERROR (Status)) {\r
767 Status = EFI_SUCCESS;\r
768 for (Index = 0; Index < EntryCount; Index++) {\r
769 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
770 Status = EFI_ALREADY_STARTED;\r
771 }\r
772 }\r
773\r
774 FreePool (OpenInfoBuffer);\r
775 if (EFI_ERROR (Status)) {\r
776 goto Error;\r
777 }\r
778 }\r
779\r
780 //\r
cf1e634b 781 // If RemainingDevicePath is NULL, use default terminal type\r
e3dcffcc 782 //\r
783 if (RemainingDevicePath == NULL) {\r
188e4e84 784 TerminalType = PcdGet8 (PcdDefaultTerminalType);\r
e3dcffcc 785 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
786 //\r
787 // If RemainingDevicePath isn't the End of Device Path Node,\r
788 // Use the RemainingDevicePath to determine the terminal type\r
789 //\r
790 Node = (VENDOR_DEVICE_PATH *)RemainingDevicePath;\r
f9163275 791 TerminalType = TerminalTypeFromGuid (&Node->Guid);\r
e3dcffcc 792 } else {\r
793 //\r
794 // If RemainingDevicePath is the End of Device Path Node,\r
795 // skip enumerate any device and return EFI_SUCESSS\r
796 //\r
797 return EFI_SUCCESS;\r
798 }\r
799\r
f9163275
RN
800 ASSERT (TerminalType < ARRAY_SIZE (mTerminalType));\r
801\r
e3dcffcc 802 //\r
803 // Initialize the Terminal Dev\r
804 //\r
805 TerminalDevice = AllocateCopyPool (sizeof (TERMINAL_DEV), &mTerminalDevTemplate);\r
806 if (TerminalDevice == NULL) {\r
95276127 807 Status = EFI_OUT_OF_RESOURCES;\r
808 goto Error;\r
809 }\r
810\r
e3dcffcc 811 TerminalDevice->TerminalType = TerminalType;\r
812 TerminalDevice->SerialIo = SerialIo;\r
813\r
814 InitializeListHead (&TerminalDevice->NotifyList);\r
815 Status = gBS->CreateEvent (\r
816 EVT_NOTIFY_WAIT,\r
817 TPL_NOTIFY,\r
818 TerminalConInWaitForKeyEx,\r
f0368006 819 TerminalDevice,\r
e3dcffcc 820 &TerminalDevice->SimpleInputEx.WaitForKeyEx\r
821 );\r
822 if (EFI_ERROR (Status)) {\r
823 goto Error;\r
824 }\r
825\r
826 Status = gBS->CreateEvent (\r
827 EVT_NOTIFY_WAIT,\r
828 TPL_NOTIFY,\r
829 TerminalConInWaitForKey,\r
f0368006 830 TerminalDevice,\r
e3dcffcc 831 &TerminalDevice->SimpleInput.WaitForKey\r
832 );\r
833 if (EFI_ERROR (Status)) {\r
834 goto Error;\r
835 }\r
8fd98315 836 //\r
e3dcffcc 837 // Allocates and initializes the FIFO buffer to be zero, used for accommodating\r
838 // the pre-read pending characters.\r
8fd98315 839 //\r
e3dcffcc 840 TerminalDevice->RawFiFo = AllocateZeroPool (sizeof (RAW_DATA_FIFO));\r
841 if (TerminalDevice->RawFiFo == NULL) {\r
842 goto Error;\r
843 }\r
844 TerminalDevice->UnicodeFiFo = AllocateZeroPool (sizeof (UNICODE_FIFO));\r
845 if (TerminalDevice->UnicodeFiFo == NULL) {\r
846 goto Error;\r
847 }\r
848 TerminalDevice->EfiKeyFiFo = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
849 if (TerminalDevice->EfiKeyFiFo == NULL) {\r
850 goto Error;\r
851 }\r
47b612db
SZ
852 TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof (EFI_KEY_FIFO));\r
853 if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {\r
854 goto Error;\r
855 }\r
95276127 856\r
6b88ceec 857 //\r
e3dcffcc 858 // Set the timeout value of serial buffer for\r
859 // keystroke response performance issue\r
6b88ceec 860 //\r
e3dcffcc 861 Mode = TerminalDevice->SerialIo->Mode;\r
862\r
863 SerialInTimeOut = 0;\r
864 if (Mode->BaudRate != 0) {\r
865 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
866 }\r
867\r
868 Status = TerminalDevice->SerialIo->SetAttributes (\r
869 TerminalDevice->SerialIo,\r
870 Mode->BaudRate,\r
6ba44b86 871 Mode->ReceiveFifoDepth,\r
e3dcffcc 872 (UINT32) SerialInTimeOut,\r
873 (EFI_PARITY_TYPE) (Mode->Parity),\r
874 (UINT8) Mode->DataBits,\r
875 (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
876 );\r
877 if (EFI_ERROR (Status)) {\r
878 //\r
879 // if set attributes operation fails, invalidate\r
880 // the value of SerialInTimeOut,thus make it\r
881 // inconsistent with the default timeout value\r
882 // of serial buffer. This will invoke the recalculation\r
883 // in the readkeystroke routine.\r
884 //\r
885 TerminalDevice->SerialInTimeOut = 0;\r
6b88ceec 886 } else {\r
e3dcffcc 887 TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
6b88ceec 888 }\r
af4a6385 889 //\r
e3dcffcc 890 // Set Simple Text Output Protocol from template.\r
891 //\r
892 SimpleTextOutput = CopyMem (\r
893 &TerminalDevice->SimpleTextOutput,\r
894 &mTerminalDevTemplate.SimpleTextOutput,\r
895 sizeof (mTerminalDevTemplate.SimpleTextOutput)\r
896 );\r
897 SimpleTextOutput->Mode = &TerminalDevice->SimpleTextOutputMode;\r
79d07c66 898 \r
899 Status = InitializeTerminalConsoleTextMode (&ModeCount, &TerminalDevice->TerminalConsoleModeData);\r
900 if (EFI_ERROR (Status)) {\r
901 goto ReportError;\r
902 }\r
903 TerminalDevice->SimpleTextOutputMode.MaxMode = (INT32) ModeCount;\r
904 \r
e3dcffcc 905 //\r
906 // For terminal devices, cursor is always visible\r
907 //\r
908 TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE;\r
909 Status = TerminalConOutSetAttribute (\r
910 SimpleTextOutput,\r
911 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
912 );\r
913 if (EFI_ERROR (Status)) {\r
914 goto ReportError;\r
915 }\r
6b88ceec 916\r
e3dcffcc 917 //\r
918 // Build the component name for the child device\r
919 //\r
fa3f99e5
RN
920 Status = InitializeControllerNameTable (TerminalDevice->TerminalType, &TerminalDevice->ControllerNameTable);\r
921 if (EFI_ERROR (Status)) {\r
922 goto Error;\r
e3dcffcc 923 }\r
95276127 924\r
95276127 925 //\r
e3dcffcc 926 // Build the device path for the child device\r
95276127 927 //\r
e3dcffcc 928 Status = SetTerminalDevicePath (\r
929 TerminalDevice->TerminalType,\r
930 ParentDevicePath,\r
931 &TerminalDevice->DevicePath\r
932 );\r
933 if (EFI_ERROR (Status)) {\r
934 goto Error;\r
935 }\r
95276127 936\r
abef1c7a 937 Status = TerminalConOutReset (SimpleTextOutput, FALSE);\r
938 if (EFI_ERROR (Status)) {\r
939 goto ReportError;\r
940 }\r
941\r
942 Status = TerminalConOutSetMode (SimpleTextOutput, 0);\r
943 if (EFI_ERROR (Status)) {\r
944 goto ReportError;\r
945 }\r
946\r
947 Status = TerminalConOutEnableCursor (SimpleTextOutput, TRUE);\r
948 if (EFI_ERROR (Status)) {\r
949 goto ReportError;\r
950 }\r
951\r
f0368006
RN
952 Status = gBS->CreateEvent (\r
953 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
954 TPL_NOTIFY,\r
955 TerminalConInTimerHandler,\r
956 TerminalDevice,\r
957 &TerminalDevice->TimerEvent\r
958 );\r
959 ASSERT_EFI_ERROR (Status);\r
960\r
961 Status = gBS->SetTimer (\r
962 TerminalDevice->TimerEvent,\r
963 TimerPeriodic,\r
964 KEYBOARD_TIMER_INTERVAL\r
965 );\r
966 ASSERT_EFI_ERROR (Status);\r
967\r
abef1c7a 968 Status = gBS->CreateEvent (\r
969 EVT_TIMER,\r
970 TPL_CALLBACK,\r
971 NULL,\r
972 NULL,\r
973 &TerminalDevice->TwoSecondTimeOut\r
974 );\r
f0368006 975 ASSERT_EFI_ERROR (Status);\r
abef1c7a 976\r
47b612db
SZ
977 Status = gBS->CreateEvent (\r
978 EVT_NOTIFY_SIGNAL,\r
979 TPL_CALLBACK,\r
980 KeyNotifyProcessHandler,\r
981 TerminalDevice,\r
982 &TerminalDevice->KeyNotifyProcessEvent\r
983 );\r
984 ASSERT_EFI_ERROR (Status);\r
985\r
e3dcffcc 986 Status = gBS->InstallProtocolInterface (\r
987 &TerminalDevice->Handle,\r
988 &gEfiDevicePathProtocolGuid,\r
989 EFI_NATIVE_INTERFACE,\r
990 TerminalDevice->DevicePath\r
991 );\r
992 if (EFI_ERROR (Status)) {\r
993 goto Error;\r
994 }\r
95276127 995\r
95276127 996 //\r
e3dcffcc 997 // Register the Parent-Child relationship via\r
998 // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
95276127 999 //\r
e3dcffcc 1000 Status = gBS->OpenProtocol (\r
1001 Controller,\r
1002 &gEfiSerialIoProtocolGuid,\r
1003 (VOID **) &TerminalDevice->SerialIo,\r
1004 This->DriverBindingHandle,\r
1005 TerminalDevice->Handle,\r
1006 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1007 );\r
1008 if (EFI_ERROR (Status)) {\r
1009 goto Error;\r
1010 }\r
95276127 1011 }\r
95276127 1012\r
3012ce5c 1013 //\r
e3dcffcc 1014 // Find the child handle, and get its TerminalDevice private data\r
3012ce5c 1015 //\r
e3dcffcc 1016 Status = gBS->OpenProtocolInformation (\r
1017 Controller,\r
1018 &gEfiSerialIoProtocolGuid,\r
1019 &OpenInfoBuffer,\r
1020 &EntryCount\r
1021 );\r
1022 if (!EFI_ERROR (Status)) {\r
1023 Status = EFI_NOT_FOUND;\r
1024 ASSERT (OpenInfoBuffer != NULL);\r
1025 for (Index = 0; Index < EntryCount; Index++) {\r
1026 if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
1027 //\r
1028 // Find the child terminal handle.\r
1029 // Test whether the SimpleTxtIn and SimpleTxtOut have been published\r
1030 //\r
1031 Status = gBS->OpenProtocol (\r
1032 OpenInfoBuffer[Index].ControllerHandle,\r
1033 &gEfiSimpleTextInProtocolGuid,\r
1034 (VOID **) &SimpleTextInput,\r
1035 This->DriverBindingHandle,\r
1036 OpenInfoBuffer[Index].ControllerHandle,\r
1037 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1038 );\r
1039 if (!EFI_ERROR (Status)) {\r
1040 SimTxtInInstalled = TRUE;\r
1041 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (SimpleTextInput);\r
1042 }\r
3012ce5c 1043\r
e3dcffcc 1044 Status = gBS->OpenProtocol (\r
1045 OpenInfoBuffer[Index].ControllerHandle,\r
1046 &gEfiSimpleTextOutProtocolGuid,\r
1047 (VOID **) &SimpleTextOutput,\r
1048 This->DriverBindingHandle,\r
1049 OpenInfoBuffer[Index].ControllerHandle,\r
1050 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1051 );\r
1052 if (!EFI_ERROR (Status)) {\r
1053 SimTxtOutInstalled = TRUE;\r
1054 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1055 }\r
1056 Status = EFI_SUCCESS;\r
1057 break;\r
1058 }\r
1059 }\r
95276127 1060\r
e3dcffcc 1061 FreePool (OpenInfoBuffer);\r
1062 if (EFI_ERROR (Status)) {\r
1063 goto ReportError;\r
1064 }\r
1065 } else {\r
95276127 1066 goto ReportError;\r
1067 }\r
1068\r
e3dcffcc 1069 ASSERT (TerminalDevice != NULL);\r
1070 //\r
1071 // Only do the reset if the device path is in the Conout variable\r
1072 //\r
1073 if (ConInSelected && !SimTxtInInstalled) {\r
1074 Status = TerminalDevice->SimpleInput.Reset (\r
1075 &TerminalDevice->SimpleInput,\r
1076 FALSE\r
1077 );\r
1078 if (EFI_ERROR (Status)) {\r
1079 //\r
1080 // Need to report Error Code first\r
1081 //\r
1082 goto ReportError;\r
1083 }\r
95276127 1084 }\r
95276127 1085\r
95276127 1086 //\r
e3dcffcc 1087 // Only output the configure string to remote terminal if the device path\r
1088 // is in the Conout variable\r
95276127 1089 //\r
e3dcffcc 1090 if (ConOutSelected && !SimTxtOutInstalled) {\r
1091 Status = TerminalDevice->SimpleTextOutput.SetAttribute (\r
1092 &TerminalDevice->SimpleTextOutput,\r
1093 EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)\r
1094 );\r
1095 if (EFI_ERROR (Status)) {\r
1096 goto ReportError;\r
1097 }\r
5bca971e 1098\r
e3dcffcc 1099 Status = TerminalDevice->SimpleTextOutput.Reset (\r
1100 &TerminalDevice->SimpleTextOutput,\r
1101 FALSE\r
1102 );\r
1103 if (EFI_ERROR (Status)) {\r
1104 goto ReportError;\r
1105 }\r
95276127 1106\r
e3dcffcc 1107 Status = TerminalDevice->SimpleTextOutput.SetMode (\r
1108 &TerminalDevice->SimpleTextOutput,\r
1109 0\r
1110 );\r
1111 if (EFI_ERROR (Status)) {\r
1112 goto ReportError;\r
1113 }\r
5bca971e 1114\r
e3dcffcc 1115 Status = TerminalDevice->SimpleTextOutput.EnableCursor (\r
1116 &TerminalDevice->SimpleTextOutput,\r
1117 TRUE\r
1118 );\r
1119 if (EFI_ERROR (Status)) {\r
1120 goto ReportError;\r
1121 }\r
95276127 1122 }\r
f1aec6cc 1123\r
95276127 1124 //\r
e3dcffcc 1125 // Simple In/Out Protocol will not be installed onto the handle if the\r
1126 // device path to the handle is not present in the ConIn/ConOut\r
1127 // environment variable. But If RemainingDevicePath is NULL, then always\r
1128 // produce both Simple In and Simple Text Output Protocols. This is required\r
1129 // for the connect all sequences to make sure all possible consoles are\r
1130 // produced no matter what the current values of ConIn, ConOut, or StdErr are.\r
95276127 1131 //\r
e3dcffcc 1132 if (!SimTxtInInstalled && (ConInSelected || NullRemaining)) {\r
1133 Status = gBS->InstallMultipleProtocolInterfaces (\r
1134 &TerminalDevice->Handle,\r
1135 &gEfiSimpleTextInProtocolGuid,\r
1136 &TerminalDevice->SimpleInput,\r
1137 &gEfiSimpleTextInputExProtocolGuid,\r
1138 &TerminalDevice->SimpleInputEx,\r
1139 NULL\r
1140 );\r
1141 if (EFI_ERROR (Status)) {\r
1142 goto Error;\r
1143 }\r
95276127 1144 }\r
1145\r
e3dcffcc 1146 if (!SimTxtOutInstalled && (ConOutSelected || NullRemaining)) {\r
1147 Status = gBS->InstallProtocolInterface (\r
1148 &TerminalDevice->Handle,\r
1149 &gEfiSimpleTextOutProtocolGuid,\r
1150 EFI_NATIVE_INTERFACE,\r
1151 &TerminalDevice->SimpleTextOutput\r
1152 );\r
1153 if (EFI_ERROR (Status)) {\r
1154 goto Error;\r
1155 }\r
1156 }\r
95276127 1157\r
1158 return EFI_SUCCESS;\r
1159\r
1160ReportError:\r
1161 //\r
1162 // Report error code before exiting\r
1163 //\r
e3dcffcc 1164 DevicePath = ParentDevicePath;\r
95276127 1165 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1166 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
f9876ecf 1167 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),\r
95276127 1168 DevicePath\r
1169 );\r
1170\r
1171Error:\r
1172 //\r
1173 // Use the Stop() function to free all resources allocated in Start()\r
1174 //\r
1175 if (TerminalDevice != NULL) {\r
1176\r
1177 if (TerminalDevice->Handle != NULL) {\r
1178 This->Stop (This, Controller, 1, &TerminalDevice->Handle);\r
1179 } else {\r
1180\r
1181 if (TerminalDevice->TwoSecondTimeOut != NULL) {\r
1182 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
1183 }\r
1184\r
f0368006
RN
1185 if (TerminalDevice->TimerEvent != NULL) {\r
1186 gBS->CloseEvent (TerminalDevice->TimerEvent);\r
1187 }\r
1188\r
95276127 1189 if (TerminalDevice->SimpleInput.WaitForKey != NULL) {\r
1190 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
1191 }\r
1192\r
66aa04e4 1193 if (TerminalDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
1194 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
1195 }\r
1196\r
1197 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
1198\r
5c998646 1199 if (TerminalDevice->RawFiFo != NULL) {\r
1200 FreePool (TerminalDevice->RawFiFo);\r
1201 }\r
1202 if (TerminalDevice->UnicodeFiFo != NULL) {\r
1203 FreePool (TerminalDevice->UnicodeFiFo);\r
1204 }\r
1205 if (TerminalDevice->EfiKeyFiFo != NULL) {\r
1206 FreePool (TerminalDevice->EfiKeyFiFo);\r
1207 }\r
47b612db
SZ
1208 if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {\r
1209 FreePool (TerminalDevice->EfiKeyFiFoForNotify);\r
1210 }\r
1211 \r
95276127 1212 if (TerminalDevice->ControllerNameTable != NULL) {\r
1213 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1214 }\r
1215\r
1216 if (TerminalDevice->DevicePath != NULL) {\r
1217 FreePool (TerminalDevice->DevicePath);\r
1218 }\r
1219\r
79d07c66 1220 if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
1221 FreePool (TerminalDevice->TerminalConsoleModeData);\r
1222 }\r
1223\r
95276127 1224 FreePool (TerminalDevice);\r
1225 }\r
1226 }\r
1227\r
95276127 1228 This->Stop (This, Controller, 0, NULL);\r
1229\r
1230 return Status;\r
1231}\r
1232\r
e49ef433 1233/**\r
ab76200c 1234 Stop this driver on Controller by closing Simple Text In, Simple Text\r
8fd98315 1235 In Ex, Simple Text Out protocol, and removing parent device path from\r
677fdb90 1236 Console Device Environment Variables.\r
e49ef433 1237\r
8fd98315 1238 @param This Protocol instance pointer.\r
ab76200c 1239 @param Controller Handle of device to stop driver on\r
8fd98315 1240 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
1241 children is zero stop the entire bus driver.\r
1242 @param ChildHandleBuffer List of Child Handles to Stop.\r
e49ef433 1243\r
ab76200c 1244 @retval EFI_SUCCESS This driver is removed Controller.\r
8fd98315 1245 @retval other This driver could not be removed from this device.\r
e49ef433 1246\r
1247**/\r
95276127 1248EFI_STATUS\r
1249EFIAPI\r
1250TerminalDriverBindingStop (\r
1251 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1252 IN EFI_HANDLE Controller,\r
1253 IN UINTN NumberOfChildren,\r
1254 IN EFI_HANDLE *ChildHandleBuffer\r
1255 )\r
95276127 1256{\r
1257 EFI_STATUS Status;\r
1258 UINTN Index;\r
1259 BOOLEAN AllChildrenStopped;\r
1260 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput;\r
1261 TERMINAL_DEV *TerminalDevice;\r
1262 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1263 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
1264 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1265\r
1266 Status = gBS->HandleProtocol (\r
1267 Controller,\r
1268 &gEfiDevicePathProtocolGuid,\r
1269 (VOID **) &DevicePath\r
1270 );\r
1271 if (EFI_ERROR (Status)) {\r
1272 return Status;\r
1273 }\r
95276127 1274\r
1275 //\r
1276 // Complete all outstanding transactions to Controller.\r
1277 // Don't allow any new transaction to Controller to be started.\r
1278 //\r
1279 if (NumberOfChildren == 0) {\r
1280 //\r
1281 // Close the bus driver\r
1282 //\r
1283 Status = gBS->OpenProtocol (\r
1284 Controller,\r
1285 &gEfiCallerIdGuid,\r
1286 (VOID **) &ParentDevicePath,\r
1287 This->DriverBindingHandle,\r
1288 Controller,\r
1289 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1290 );\r
1291 if (!EFI_ERROR (Status)) {\r
1292 //\r
1293 // Remove Parent Device Path from\r
1294 // the Console Device Environment Variables\r
1295 //\r
ff37790d
A
1296 TerminalRemoveConsoleDevVariable (L"ConInDev", ParentDevicePath);\r
1297 TerminalRemoveConsoleDevVariable (L"ConOutDev", ParentDevicePath);\r
1298 TerminalRemoveConsoleDevVariable (L"ErrOutDev", ParentDevicePath);\r
95276127 1299\r
1300 //\r
1301 // Uninstall the Terminal Driver's GUID Tag from the Serial controller\r
1302 //\r
1303 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1304 Controller,\r
1305 &gEfiCallerIdGuid,\r
1306 ParentDevicePath,\r
1307 NULL\r
1308 );\r
1309\r
1310 //\r
1311 // Free the ParentDevicePath that was duplicated in Start()\r
1312 //\r
1313 if (!EFI_ERROR (Status)) {\r
1314 FreePool (ParentDevicePath);\r
1315 }\r
1316 }\r
1317\r
1318 gBS->CloseProtocol (\r
1319 Controller,\r
1320 &gEfiSerialIoProtocolGuid,\r
1321 This->DriverBindingHandle,\r
1322 Controller\r
1323 );\r
1324\r
1325 gBS->CloseProtocol (\r
1326 Controller,\r
1327 &gEfiDevicePathProtocolGuid,\r
1328 This->DriverBindingHandle,\r
1329 Controller\r
1330 );\r
1331\r
1332 return EFI_SUCCESS;\r
1333 }\r
1334\r
1335 AllChildrenStopped = TRUE;\r
1336\r
1337 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1338\r
1339 Status = gBS->OpenProtocol (\r
1340 ChildHandleBuffer[Index],\r
1341 &gEfiSimpleTextOutProtocolGuid,\r
1342 (VOID **) &SimpleTextOutput,\r
1343 This->DriverBindingHandle,\r
1344 ChildHandleBuffer[Index],\r
1345 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1346 );\r
1347 if (!EFI_ERROR (Status)) {\r
1348\r
1349 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput);\r
1350\r
1351 gBS->CloseProtocol (\r
1352 Controller,\r
1353 &gEfiSerialIoProtocolGuid,\r
1354 This->DriverBindingHandle,\r
1355 ChildHandleBuffer[Index]\r
1356 );\r
1357\r
1358 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1359 ChildHandleBuffer[Index],\r
1360 &gEfiSimpleTextInProtocolGuid,\r
1361 &TerminalDevice->SimpleInput,\r
66aa04e4 1362 &gEfiSimpleTextInputExProtocolGuid,\r
1363 &TerminalDevice->SimpleInputEx,\r
95276127 1364 &gEfiSimpleTextOutProtocolGuid,\r
1365 &TerminalDevice->SimpleTextOutput,\r
1366 &gEfiDevicePathProtocolGuid,\r
1367 TerminalDevice->DevicePath,\r
1368 NULL\r
1369 );\r
1370 if (EFI_ERROR (Status)) {\r
1371 gBS->OpenProtocol (\r
1372 Controller,\r
1373 &gEfiSerialIoProtocolGuid,\r
1374 (VOID **) &SerialIo,\r
1375 This->DriverBindingHandle,\r
1376 ChildHandleBuffer[Index],\r
1377 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1378 );\r
1379 } else {\r
1380\r
1381 if (TerminalDevice->ControllerNameTable != NULL) {\r
1382 FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);\r
1383 }\r
1384\r
f0368006 1385 gBS->CloseEvent (TerminalDevice->TimerEvent);\r
95276127 1386 gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);\r
1387 gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);\r
66aa04e4 1388 gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);\r
47b612db 1389 gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);\r
66aa04e4 1390 TerminalFreeNotifyList (&TerminalDevice->NotifyList);\r
95276127 1391 FreePool (TerminalDevice->DevicePath);\r
79d07c66 1392 if (TerminalDevice->TerminalConsoleModeData != NULL) {\r
1393 FreePool (TerminalDevice->TerminalConsoleModeData);\r
1394 }\r
95276127 1395 FreePool (TerminalDevice);\r
1396 }\r
1397 }\r
1398\r
1399 if (EFI_ERROR (Status)) {\r
1400 AllChildrenStopped = FALSE;\r
1401 }\r
1402 }\r
1403\r
1404 if (!AllChildrenStopped) {\r
1405 return EFI_DEVICE_ERROR;\r
1406 }\r
1407\r
1408 return EFI_SUCCESS;\r
1409}\r
1410\r
8fd98315 1411/**\r
1412 Update terminal device path in Console Device Environment Variables.\r
1413\r
1414 @param VariableName The Console Device Environment Variable.\r
11baadb6 1415 @param ParentDevicePath The terminal device path to be updated.\r
8fd98315 1416\r
8fd98315 1417**/\r
95276127 1418VOID\r
1419TerminalUpdateConsoleDevVariable (\r
1420 IN CHAR16 *VariableName,\r
1421 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
1422 )\r
1423{\r
1424 EFI_STATUS Status;\r
5070befc 1425 UINTN NameSize;\r
95276127 1426 UINTN VariableSize;\r
8ce87fff 1427 TERMINAL_TYPE TerminalType;\r
95276127 1428 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1429 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1430 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
5070befc 1431 EDKII_SET_VARIABLE_STATUS *SetVariableStatus;\r
95276127 1432\r
95276127 1433 //\r
1434 // Get global variable and its size according to the name given.\r
1435 //\r
f01b91ae 1436 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
e3dcffcc 1437 if (Variable == NULL) {\r
1438 return;\r
1439 }\r
1440\r
95276127 1441 //\r
1442 // Append terminal device path onto the variable.\r
1443 //\r
f9163275 1444 for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
95276127 1445 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1446 NewVariable = AppendDevicePathInstance (Variable, TempDevicePath);\r
4b0786b4 1447 ASSERT (NewVariable != NULL);\r
95276127 1448 if (Variable != NULL) {\r
1449 FreePool (Variable);\r
1450 }\r
1451\r
1452 if (TempDevicePath != NULL) {\r
1453 FreePool (TempDevicePath);\r
1454 }\r
1455\r
1456 Variable = NewVariable;\r
1457 }\r
1458\r
1459 VariableSize = GetDevicePathSize (Variable);\r
1460\r
1461 Status = gRT->SetVariable (\r
1462 VariableName,\r
1463 &gEfiGlobalVariableGuid,\r
1464 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1465 VariableSize,\r
1466 Variable\r
1467 );\r
5070befc
RN
1468\r
1469 if (EFI_ERROR (Status)) {\r
1470 NameSize = StrSize (VariableName);\r
1471 SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize);\r
1472 if (SetVariableStatus != NULL) {\r
1473 CopyGuid (&SetVariableStatus->Guid, &gEfiGlobalVariableGuid);\r
1474 SetVariableStatus->NameSize = NameSize;\r
1475 SetVariableStatus->DataSize = VariableSize;\r
1476 SetVariableStatus->SetStatus = Status;\r
1477 SetVariableStatus->Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;\r
1478 CopyMem (SetVariableStatus + 1, VariableName, NameSize);\r
1479 CopyMem (((UINT8 *) (SetVariableStatus + 1)) + NameSize, Variable, VariableSize);\r
1480\r
1481 REPORT_STATUS_CODE_EX (\r
1482 EFI_ERROR_CODE,\r
1483 PcdGet32 (PcdErrorCodeSetVariable),\r
1484 0,\r
1485 NULL,\r
1486 &gEdkiiStatusCodeDataTypeVariableGuid,\r
1487 SetVariableStatus,\r
1488 sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + VariableSize\r
1489 );\r
1490\r
1491 FreePool (SetVariableStatus);\r
1492 }\r
1493 }\r
1494\r
95276127 1495 FreePool (Variable);\r
1496\r
1497 return ;\r
1498}\r
1499\r
e49ef433 1500\r
1501/**\r
8fd98315 1502 Remove terminal device path from Console Device Environment Variables.\r
e49ef433 1503\r
8fd98315 1504 @param VariableName Console Device Environment Variables.\r
11baadb6 1505 @param ParentDevicePath The terminal device path to be updated.\r
e49ef433 1506\r
e49ef433 1507**/\r
95276127 1508VOID\r
1509TerminalRemoveConsoleDevVariable (\r
1510 IN CHAR16 *VariableName,\r
1511 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath\r
1512 )\r
95276127 1513{\r
1514 EFI_STATUS Status;\r
1515 BOOLEAN FoundOne;\r
1516 BOOLEAN Match;\r
1517 UINTN VariableSize;\r
1518 UINTN InstanceSize;\r
8ce87fff 1519 TERMINAL_TYPE TerminalType;\r
95276127 1520 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
1521 EFI_DEVICE_PATH_PROTOCOL *Variable;\r
1522 EFI_DEVICE_PATH_PROTOCOL *OriginalVariable;\r
1523 EFI_DEVICE_PATH_PROTOCOL *NewVariable;\r
1524 EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable;\r
1525 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1526\r
95276127 1527 Instance = NULL;\r
1528\r
1529 //\r
1530 // Get global variable and its size according to the name given.\r
1531 //\r
f01b91ae 1532 GetEfiGlobalVariable2 (VariableName, (VOID**)&Variable, NULL);\r
95276127 1533 if (Variable == NULL) {\r
1534 return ;\r
1535 }\r
1536\r
1537 FoundOne = FALSE;\r
1538 OriginalVariable = Variable;\r
1539 NewVariable = NULL;\r
1540\r
1541 //\r
1542 // Get first device path instance from Variable\r
1543 //\r
1544 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1545 if (Instance == NULL) {\r
1546 FreePool (OriginalVariable);\r
1547 return ;\r
1548 }\r
1549 //\r
1550 // Loop through all the device path instances of Variable\r
1551 //\r
1552 do {\r
1553 //\r
1554 // Loop through all the terminal types that this driver supports\r
1555 //\r
1556 Match = FALSE;\r
f9163275 1557 for (TerminalType = 0; TerminalType < ARRAY_SIZE (mTerminalType); TerminalType++) {\r
95276127 1558\r
1559 SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath);\r
1560\r
1561 //\r
11baadb6 1562 // Compare the generated device path to the current device path instance\r
95276127 1563 //\r
1564 if (TempDevicePath != NULL) {\r
1565 if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) {\r
1566 Match = TRUE;\r
1567 FoundOne = TRUE;\r
1568 }\r
1569\r
1570 FreePool (TempDevicePath);\r
1571 }\r
1572 }\r
1573 //\r
1574 // If a match was not found, then keep the current device path instance\r
1575 //\r
1576 if (!Match) {\r
1577 SavedNewVariable = NewVariable;\r
1578 NewVariable = AppendDevicePathInstance (NewVariable, Instance);\r
1579 if (SavedNewVariable != NULL) {\r
1580 FreePool (SavedNewVariable);\r
1581 }\r
1582 }\r
1583 //\r
1584 // Get next device path instance from Variable\r
1585 //\r
1586 FreePool (Instance);\r
1587 Instance = GetNextDevicePathInstance (&Variable, &InstanceSize);\r
1588 } while (Instance != NULL);\r
1589\r
1590 FreePool (OriginalVariable);\r
1591\r
1592 if (FoundOne) {\r
1593 VariableSize = GetDevicePathSize (NewVariable);\r
1594\r
1595 Status = gRT->SetVariable (\r
1596 VariableName,\r
1597 &gEfiGlobalVariableGuid,\r
1598 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1599 VariableSize,\r
1600 NewVariable\r
1601 );\r
5070befc
RN
1602 //\r
1603 // Shrinking variable with existing variable driver implementation shouldn't fail.\r
1604 //\r
1605 ASSERT_EFI_ERROR (Status);\r
95276127 1606 }\r
1607\r
1608 if (NewVariable != NULL) {\r
1609 FreePool (NewVariable);\r
1610 }\r
1611\r
1612 return ;\r
1613}\r
1614\r
8fd98315 1615/**\r
11baadb6 1616 Build terminal device path according to terminal type.\r
8fd98315 1617\r
1618 @param TerminalType The terminal type is PC ANSI, VT100, VT100+ or VT-UTF8.\r
11baadb6 1619 @param ParentDevicePath Parent device path.\r
8fd98315 1620 @param TerminalDevicePath Returned terminal device path, if building successfully.\r
1621\r
1622 @retval EFI_UNSUPPORTED Terminal does not belong to the supported type.\r
1623 @retval EFI_OUT_OF_RESOURCES Generate terminal device path failed.\r
1624 @retval EFI_SUCCESS Build terminal device path successfully.\r
1625\r
1626**/\r
95276127 1627EFI_STATUS\r
1628SetTerminalDevicePath (\r
8ce87fff 1629 IN TERMINAL_TYPE TerminalType,\r
95276127 1630 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
1631 OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath\r
1632 )\r
1633{\r
1634 VENDOR_DEVICE_PATH Node;\r
1635\r
1636 *TerminalDevicePath = NULL;\r
1637 Node.Header.Type = MESSAGING_DEVICE_PATH;\r
1638 Node.Header.SubType = MSG_VENDOR_DP;\r
1639\r
1640 //\r
ab76200c 1641 // Generate terminal device path node according to terminal type.\r
95276127 1642 //\r
1643 switch (TerminalType) {\r
1644\r
8ce87fff 1645 case TerminalTypePcAnsi:\r
ab76200c 1646 CopyGuid (&Node.Guid, &gEfiPcAnsiGuid);\r
95276127 1647 break;\r
1648\r
8ce87fff 1649 case TerminalTypeVt100:\r
ab76200c 1650 CopyGuid (&Node.Guid, &gEfiVT100Guid);\r
95276127 1651 break;\r
1652\r
8ce87fff 1653 case TerminalTypeVt100Plus:\r
ab76200c 1654 CopyGuid (&Node.Guid, &gEfiVT100PlusGuid);\r
95276127 1655 break;\r
1656\r
8ce87fff 1657 case TerminalTypeVtUtf8:\r
ab76200c 1658 CopyGuid (&Node.Guid, &gEfiVTUTF8Guid);\r
95276127 1659 break;\r
1660\r
8ce87fff 1661 case TerminalTypeTtyTerm:\r
6e3227c8
RF
1662 CopyGuid (&Node.Guid, &gEfiTtyTermGuid);\r
1663 break;\r
1664\r
95276127 1665 default:\r
1666 return EFI_UNSUPPORTED;\r
95276127 1667 }\r
1668\r
ab76200c 1669 //\r
1670 // Get VENDOR_DEVCIE_PATH size and put into Node.Header\r
1671 //\r
95276127 1672 SetDevicePathNodeLength (\r
1673 &Node.Header,\r
1674 sizeof (VENDOR_DEVICE_PATH)\r
1675 );\r
ab76200c 1676\r
95276127 1677 //\r
ab76200c 1678 // Append the terminal node onto parent device path\r
95276127 1679 // to generate a complete terminal device path.\r
1680 //\r
1681 *TerminalDevicePath = AppendDevicePathNode (\r
1682 ParentDevicePath,\r
1683 (EFI_DEVICE_PATH_PROTOCOL *) &Node\r
1684 );\r
1685 if (*TerminalDevicePath == NULL) {\r
1686 return EFI_OUT_OF_RESOURCES;\r
1687 }\r
1688\r
1689 return EFI_SUCCESS;\r
1690}\r
1691\r
97a079ed
A
1692/**\r
1693 The user Entry Point for module Terminal. The user code starts with this function.\r
1694\r
ab76200c 1695 @param ImageHandle The firmware allocated handle for the EFI image.\r
1696 @param SystemTable A pointer to the EFI System Table.\r
fb0b259e 1697\r
97a079ed
A
1698 @retval EFI_SUCCESS The entry point is executed successfully.\r
1699 @retval other Some error occurs when executing this entry point.\r
1700\r
1701**/\r
1702EFI_STATUS\r
1703EFIAPI\r
1704InitializeTerminal(\r
1705 IN EFI_HANDLE ImageHandle,\r
1706 IN EFI_SYSTEM_TABLE *SystemTable\r
1707 )\r
1708{\r
1709 EFI_STATUS Status;\r
1710\r
1711 //\r
1712 // Install driver model protocol(s).\r
1713 //\r
5bca971e 1714 Status = EfiLibInstallDriverBindingComponentName2 (\r
97a079ed
A
1715 ImageHandle,\r
1716 SystemTable,\r
1717 &gTerminalDriverBinding,\r
1718 ImageHandle,\r
1719 &gTerminalComponentName,\r
5bca971e 1720 &gTerminalComponentName2\r
97a079ed
A
1721 );\r
1722 ASSERT_EFI_ERROR (Status);\r
1723\r
97a079ed
A
1724 return Status;\r
1725}\r
f1aec6cc 1726\r
1727/**\r
1728 Check if the device supports hot-plug through its device path.\r
1729\r
1730 This function could be updated to check more types of Hot Plug devices.\r
1731 Currently, it checks USB and PCCard device.\r
1732\r
1733 @param DevicePath Pointer to device's device path.\r
1734\r
1735 @retval TRUE The devcie is a hot-plug device\r
1736 @retval FALSE The devcie is not a hot-plug device.\r
1737\r
1738**/\r
1739BOOLEAN\r
1740IsHotPlugDevice (\r
1741 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1742 )\r
1743{\r
1744 EFI_DEVICE_PATH_PROTOCOL *CheckDevicePath;\r
1745\r
1746 CheckDevicePath = DevicePath;\r
1747 while (!IsDevicePathEnd (CheckDevicePath)) {\r
1748 //\r
1749 // Check device whether is hot plug device or not throught Device Path\r
e3dcffcc 1750 //\r
f1aec6cc 1751 if ((DevicePathType (CheckDevicePath) == MESSAGING_DEVICE_PATH) &&\r
1752 (DevicePathSubType (CheckDevicePath) == MSG_USB_DP ||\r
1753 DevicePathSubType (CheckDevicePath) == MSG_USB_CLASS_DP ||\r
1754 DevicePathSubType (CheckDevicePath) == MSG_USB_WWID_DP)) {\r
1755 //\r
1756 // If Device is USB device\r
1757 //\r
1758 return TRUE;\r
1759 }\r
1760 if ((DevicePathType (CheckDevicePath) == HARDWARE_DEVICE_PATH) &&\r
1761 (DevicePathSubType (CheckDevicePath) == HW_PCCARD_DP)) {\r
1762 //\r
1763 // If Device is PCCard\r
1764 //\r
1765 return TRUE;\r
1766 }\r
e3dcffcc 1767\r
f1aec6cc 1768 CheckDevicePath = NextDevicePathNode (CheckDevicePath);\r
1769 }\r
1770\r
1771 return FALSE;\r
1772}\r
1773\r