]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / Console / ConPlatformDxe / ConPlatform.c
CommitLineData
fb0b259e 1/** @file\r
dfe687ca 2 Console Platform DXE Driver, install Console Device Guids and update Console\r
9359e53f 3 Environment Variables.\r
95276127 4\r
d1102dba 5Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
95276127 7\r
fb0b259e 8**/\r
95276127 9\r
0ad02bbd 10#include "ConPlatform.h"\r
95276127 11\r
1436aea4 12EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding = {\r
95276127 13 ConPlatformTextInDriverBindingSupported,\r
14 ConPlatformTextInDriverBindingStart,\r
15 ConPlatformTextInDriverBindingStop,\r
16 0xa,\r
17 NULL,\r
18 NULL\r
19};\r
20\r
1436aea4 21EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding = {\r
95276127 22 ConPlatformTextOutDriverBindingSupported,\r
23 ConPlatformTextOutDriverBindingStart,\r
24 ConPlatformTextOutDriverBindingStop,\r
25 0xa,\r
26 NULL,\r
27 NULL\r
28};\r
29\r
30/**\r
c5ed97f6 31 Entrypoint of this module.\r
32\r
33 This function is the entrypoint of this module. It installs Driver Binding\r
34 Protocols together with Component Name Protocols.\r
95276127 35\r
7b9ff698 36 @param ImageHandle The firmware allocated handle for the EFI image.\r
37 @param SystemTable A pointer to the EFI System Table.\r
c62a593c 38\r
95276127 39 @retval EFI_SUCCESS The entry point is executed successfully.\r
95276127 40\r
41**/\r
42EFI_STATUS\r
43EFIAPI\r
1436aea4
MK
44InitializeConPlatform (\r
45 IN EFI_HANDLE ImageHandle,\r
46 IN EFI_SYSTEM_TABLE *SystemTable\r
95276127 47 )\r
48{\r
1436aea4 49 EFI_STATUS Status;\r
95276127 50\r
5bca971e 51 Status = EfiLibInstallDriverBindingComponentName2 (\r
95276127 52 ImageHandle,\r
53 SystemTable,\r
54 &gConPlatformTextInDriverBinding,\r
55 ImageHandle,\r
56 &gConPlatformComponentName,\r
5bca971e 57 &gConPlatformComponentName2\r
95276127 58 );\r
59 ASSERT_EFI_ERROR (Status);\r
60\r
5bca971e 61 Status = EfiLibInstallDriverBindingComponentName2 (\r
95276127 62 ImageHandle,\r
63 SystemTable,\r
64 &gConPlatformTextOutDriverBinding,\r
65 NULL,\r
66 &gConPlatformComponentName,\r
5bca971e 67 &gConPlatformComponentName2\r
95276127 68 );\r
69 ASSERT_EFI_ERROR (Status);\r
70\r
c5ed97f6 71 return EFI_SUCCESS;\r
95276127 72}\r
73\r
9359e53f 74/**\r
d1102dba 75 Test to see if EFI_SIMPLE_TEXT_INPUT_PROTOCOL is supported on ControllerHandle.\r
9359e53f 76\r
77 @param This Protocol instance pointer.\r
78 @param ControllerHandle Handle of device to test.\r
79 @param RemainingDevicePath Optional parameter use to pick a specific child\r
80 device to start.\r
81\r
7b9ff698 82 @retval EFI_SUCCESS This driver supports this device.\r
83 @retval other This driver does not support this device.\r
9359e53f 84\r
85**/\r
95276127 86EFI_STATUS\r
87EFIAPI\r
88ConPlatformTextInDriverBindingSupported (\r
89 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
90 IN EFI_HANDLE ControllerHandle,\r
c5ed97f6 91 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
95276127 92 )\r
95276127 93{\r
94 return ConPlatformDriverBindingSupported (\r
c5ed97f6 95 This,\r
96 ControllerHandle,\r
97 &gEfiSimpleTextInProtocolGuid\r
98 );\r
95276127 99}\r
100\r
9359e53f 101/**\r
d1102dba 102 Test to see if EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL is supported on ControllerHandle.\r
9359e53f 103\r
104 @param This Protocol instance pointer.\r
105 @param ControllerHandle Handle of device to test.\r
106 @param RemainingDevicePath Optional parameter use to pick a specific child\r
107 device to start.\r
108\r
7b9ff698 109 @retval EFI_SUCCESS This driver supports this device.\r
110 @retval other This driver does not support this device.\r
9359e53f 111\r
112**/\r
95276127 113EFI_STATUS\r
114EFIAPI\r
115ConPlatformTextOutDriverBindingSupported (\r
116 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
117 IN EFI_HANDLE ControllerHandle,\r
c5ed97f6 118 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
95276127 119 )\r
95276127 120{\r
121 return ConPlatformDriverBindingSupported (\r
c5ed97f6 122 This,\r
123 ControllerHandle,\r
124 &gEfiSimpleTextOutProtocolGuid\r
125 );\r
95276127 126}\r
127\r
9359e53f 128/**\r
d1102dba 129 Test to see if the specified protocol is supported on ControllerHandle.\r
9359e53f 130\r
131 @param This Protocol instance pointer.\r
132 @param ControllerHandle Handle of device to test.\r
9359e53f 133 @param ProtocolGuid The specfic protocol.\r
134\r
7b9ff698 135 @retval EFI_SUCCESS This driver supports this device.\r
136 @retval other This driver does not support this device.\r
9359e53f 137\r
138**/\r
95276127 139EFI_STATUS\r
140ConPlatformDriverBindingSupported (\r
141 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
142 IN EFI_HANDLE ControllerHandle,\r
95276127 143 IN EFI_GUID *ProtocolGuid\r
144 )\r
95276127 145{\r
146 EFI_STATUS Status;\r
147 VOID *Interface;\r
148\r
149 //\r
7b9ff698 150 // Test to see if this is a physical device by checking if\r
151 // it has a Device Path Protocol.\r
95276127 152 //\r
153 Status = gBS->OpenProtocol (\r
154 ControllerHandle,\r
155 &gEfiDevicePathProtocolGuid,\r
156 NULL,\r
157 This->DriverBindingHandle,\r
158 ControllerHandle,\r
159 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
160 );\r
161 if (EFI_ERROR (Status)) {\r
162 return Status;\r
163 }\r
1436aea4 164\r
95276127 165 //\r
7b9ff698 166 // Test to see if this device supports the specified Protocol.\r
95276127 167 //\r
168 Status = gBS->OpenProtocol (\r
169 ControllerHandle,\r
170 ProtocolGuid,\r
1436aea4 171 (VOID **)&Interface,\r
95276127 172 This->DriverBindingHandle,\r
173 ControllerHandle,\r
174 EFI_OPEN_PROTOCOL_BY_DRIVER\r
175 );\r
176 if (EFI_ERROR (Status)) {\r
177 return Status;\r
178 }\r
179\r
180 gBS->CloseProtocol (\r
c5ed97f6 181 ControllerHandle,\r
182 ProtocolGuid,\r
183 This->DriverBindingHandle,\r
184 ControllerHandle\r
185 );\r
95276127 186\r
187 return EFI_SUCCESS;\r
188}\r
189\r
9359e53f 190/**\r
c5ed97f6 191 Start this driver on the device for console input.\r
192\r
193 Start this driver on ControllerHandle by opening Simple Text Input Protocol,\r
24248368 194 reading Device Path, and installing Console In Devcice GUID on ControllerHandle.\r
9359e53f 195\r
5c9ac43f 196 Append its device path into the console environment variables ConInDev.\r
d1102dba 197\r
9359e53f 198 @param This Protocol instance pointer.\r
199 @param ControllerHandle Handle of device to bind driver to\r
200 @param RemainingDevicePath Optional parameter use to pick a specific child\r
201 device to start.\r
202\r
203 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
204 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
415df2a3 205 @retval other This driver does not support this device.\r
9359e53f 206\r
207**/\r
95276127 208EFI_STATUS\r
209EFIAPI\r
210ConPlatformTextInDriverBindingStart (\r
1436aea4
MK
211 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
212 IN EFI_HANDLE ControllerHandle,\r
213 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
95276127 214 )\r
95276127 215{\r
1436aea4
MK
216 EFI_STATUS Status;\r
217 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
218 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;\r
219 BOOLEAN IsInConInVariable;\r
95276127 220\r
221 //\r
222 // Get the Device Path Protocol so the environment variables can be updated\r
223 //\r
224 Status = gBS->OpenProtocol (\r
225 ControllerHandle,\r
226 &gEfiDevicePathProtocolGuid,\r
1436aea4 227 (VOID **)&DevicePath,\r
95276127 228 This->DriverBindingHandle,\r
229 ControllerHandle,\r
230 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
231 );\r
232 if (EFI_ERROR (Status)) {\r
233 return Status;\r
234 }\r
1436aea4 235\r
95276127 236 //\r
c5ed97f6 237 // Open the Simple Text Input Protocol BY_DRIVER\r
95276127 238 //\r
239 Status = gBS->OpenProtocol (\r
240 ControllerHandle,\r
241 &gEfiSimpleTextInProtocolGuid,\r
1436aea4 242 (VOID **)&TextIn,\r
95276127 243 This->DriverBindingHandle,\r
244 ControllerHandle,\r
245 EFI_OPEN_PROTOCOL_BY_DRIVER\r
246 );\r
247 if (EFI_ERROR (Status)) {\r
248 return Status;\r
249 }\r
1436aea4 250\r
ca6b86ef 251 //\r
252 // Check if the device path is in ConIn Variable\r
253 //\r
254 IsInConInVariable = FALSE;\r
1436aea4
MK
255 Status = ConPlatformUpdateDeviceVariable (\r
256 L"ConIn",\r
257 DevicePath,\r
258 Check\r
259 );\r
ca6b86ef 260 if (!EFI_ERROR (Status)) {\r
261 IsInConInVariable = TRUE;\r
262 }\r
263\r
95276127 264 //\r
5c9ac43f 265 // Append the device path to the ConInDev environment variable\r
95276127 266 //\r
5c9ac43f
RN
267 ConPlatformUpdateDeviceVariable (\r
268 L"ConInDev",\r
269 DevicePath,\r
270 Append\r
271 );\r
272\r
273 //\r
274 // If the device path is an instance in the ConIn environment variable,\r
275 // then install EfiConsoleInDeviceGuid onto ControllerHandle\r
276 //\r
277 if (IsInConInVariable) {\r
95276127 278 gBS->InstallMultipleProtocolInterfaces (\r
c5ed97f6 279 &ControllerHandle,\r
280 &gEfiConsoleInDeviceGuid,\r
281 NULL,\r
282 NULL\r
283 );\r
95276127 284 } else {\r
5c9ac43f
RN
285 gBS->CloseProtocol (\r
286 ControllerHandle,\r
287 &gEfiSimpleTextInProtocolGuid,\r
288 This->DriverBindingHandle,\r
289 ControllerHandle\r
290 );\r
95276127 291 }\r
292\r
293 return EFI_SUCCESS;\r
294}\r
295\r
9359e53f 296/**\r
0a18956d 297 Start this driver on the device for console output and standard error output.\r
c5ed97f6 298\r
299 Start this driver on ControllerHandle by opening Simple Text Output Protocol,\r
24248368 300 reading Device Path, and installing Console Out Devcic GUID, Standard Error\r
9359e53f 301 Device GUID on ControllerHandle.\r
302\r
5c9ac43f 303 Append its device path into the console environment variables ConOutDev, ErrOutDev.\r
d1102dba 304\r
9359e53f 305 @param This Protocol instance pointer.\r
306 @param ControllerHandle Handle of device to bind driver to\r
307 @param RemainingDevicePath Optional parameter use to pick a specific child\r
308 device to start.\r
309\r
310 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
311 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
312 @retval other This driver does not support this device\r
313\r
314**/\r
95276127 315EFI_STATUS\r
316EFIAPI\r
317ConPlatformTextOutDriverBindingStart (\r
1436aea4
MK
318 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
319 IN EFI_HANDLE ControllerHandle,\r
320 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
95276127 321 )\r
95276127 322{\r
c5ed97f6 323 EFI_STATUS Status;\r
324 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
95276127 325 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
c5ed97f6 326 BOOLEAN NeedClose;\r
ca6b86ef 327 BOOLEAN IsInConOutVariable;\r
328 BOOLEAN IsInErrOutVariable;\r
95276127 329\r
330 NeedClose = TRUE;\r
331\r
332 //\r
333 // Get the Device Path Protocol so the environment variables can be updated\r
334 //\r
335 Status = gBS->OpenProtocol (\r
336 ControllerHandle,\r
337 &gEfiDevicePathProtocolGuid,\r
1436aea4 338 (VOID **)&DevicePath,\r
95276127 339 This->DriverBindingHandle,\r
340 ControllerHandle,\r
341 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
342 );\r
343 if (EFI_ERROR (Status)) {\r
344 return Status;\r
345 }\r
1436aea4 346\r
95276127 347 //\r
348 // Open the Simple Text Output Protocol BY_DRIVER\r
349 //\r
350 Status = gBS->OpenProtocol (\r
351 ControllerHandle,\r
352 &gEfiSimpleTextOutProtocolGuid,\r
1436aea4 353 (VOID **)&TextOut,\r
95276127 354 This->DriverBindingHandle,\r
355 ControllerHandle,\r
356 EFI_OPEN_PROTOCOL_BY_DRIVER\r
357 );\r
358 if (EFI_ERROR (Status)) {\r
359 return Status;\r
360 }\r
1436aea4 361\r
ca6b86ef 362 //\r
363 // Check if the device path is in ConOut & ErrOut Variable\r
364 //\r
365 IsInConOutVariable = FALSE;\r
1436aea4
MK
366 Status = ConPlatformUpdateDeviceVariable (\r
367 L"ConOut",\r
368 DevicePath,\r
369 Check\r
370 );\r
ca6b86ef 371 if (!EFI_ERROR (Status)) {\r
372 IsInConOutVariable = TRUE;\r
373 }\r
374\r
375 IsInErrOutVariable = FALSE;\r
1436aea4
MK
376 Status = ConPlatformUpdateDeviceVariable (\r
377 L"ErrOut",\r
378 DevicePath,\r
379 Check\r
380 );\r
ca6b86ef 381 if (!EFI_ERROR (Status)) {\r
382 IsInErrOutVariable = TRUE;\r
383 }\r
384\r
95276127 385 //\r
5c9ac43f
RN
386 // Append the device path to the ConOutDev and ErrOutDev environment variable.\r
387 // For GOP device path, append the sibling device path as well.\r
95276127 388 //\r
5c9ac43f
RN
389 if (!ConPlatformUpdateGopCandidate (DevicePath)) {\r
390 ConPlatformUpdateDeviceVariable (\r
391 L"ConOutDev",\r
392 DevicePath,\r
393 Append\r
394 );\r
395 //\r
396 // Then append the device path to the ErrOutDev environment variable\r
397 //\r
398 ConPlatformUpdateDeviceVariable (\r
399 L"ErrOutDev",\r
400 DevicePath,\r
401 Append\r
402 );\r
403 }\r
404\r
405 //\r
406 // If the device path is an instance in the ConOut environment variable,\r
407 // then install EfiConsoleOutDeviceGuid onto ControllerHandle\r
408 //\r
409 if (IsInConOutVariable) {\r
410 NeedClose = FALSE;\r
1436aea4
MK
411 Status = gBS->InstallMultipleProtocolInterfaces (\r
412 &ControllerHandle,\r
413 &gEfiConsoleOutDeviceGuid,\r
414 NULL,\r
415 NULL\r
416 );\r
5c9ac43f 417 }\r
1436aea4 418\r
5c9ac43f
RN
419 //\r
420 // If the device path is an instance in the ErrOut environment variable,\r
421 // then install EfiStandardErrorDeviceGuid onto ControllerHandle\r
422 //\r
423 if (IsInErrOutVariable) {\r
424 NeedClose = FALSE;\r
95276127 425 gBS->InstallMultipleProtocolInterfaces (\r
c5ed97f6 426 &ControllerHandle,\r
5c9ac43f 427 &gEfiStandardErrorDeviceGuid,\r
c5ed97f6 428 NULL,\r
429 NULL\r
430 );\r
5c9ac43f 431 }\r
95276127 432\r
5c9ac43f
RN
433 if (NeedClose) {\r
434 gBS->CloseProtocol (\r
435 ControllerHandle,\r
436 &gEfiSimpleTextOutProtocolGuid,\r
437 This->DriverBindingHandle,\r
438 ControllerHandle\r
439 );\r
95276127 440 }\r
441\r
442 return EFI_SUCCESS;\r
443}\r
444\r
9359e53f 445/**\r
d1102dba 446 Stop this driver on ControllerHandle by removing Console In Devcice GUID\r
c5ed97f6 447 and closing the Simple Text Input protocol on ControllerHandle.\r
9359e53f 448\r
449 @param This Protocol instance pointer.\r
450 @param ControllerHandle Handle of device to stop driver on\r
451 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
452 children is zero stop the entire bus driver.\r
453 @param ChildHandleBuffer List of Child Handles to Stop.\r
454\r
455 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
456 @retval other This driver was not removed from this device\r
457\r
458**/\r
95276127 459EFI_STATUS\r
460EFIAPI\r
461ConPlatformTextInDriverBindingStop (\r
462 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
463 IN EFI_HANDLE ControllerHandle,\r
464 IN UINTN NumberOfChildren,\r
465 IN EFI_HANDLE *ChildHandleBuffer\r
466 )\r
95276127 467{\r
468 EFI_STATUS Status;\r
469 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
470\r
471 //\r
f1aec6cc 472 // Get the Device Path Protocol firstly\r
95276127 473 //\r
f1aec6cc 474 Status = gBS->OpenProtocol (\r
475 ControllerHandle,\r
476 &gEfiDevicePathProtocolGuid,\r
1436aea4 477 (VOID **)&DevicePath,\r
f1aec6cc 478 This->DriverBindingHandle,\r
479 ControllerHandle,\r
480 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
481 );\r
482 //\r
483 // If there is device path on ControllerHandle\r
484 //\r
485 if (!EFI_ERROR (Status)) {\r
95276127 486 //\r
ca6b86ef 487 // Remove DevicePath from ConInDev if exists.\r
4986c561 488 //\r
ca6b86ef 489 ConPlatformUpdateDeviceVariable (\r
490 L"ConInDev",\r
491 DevicePath,\r
1ccdbf2a 492 Delete\r
ca6b86ef 493 );\r
95276127 494 }\r
f1aec6cc 495\r
95276127 496 //\r
497 // Uninstall the Console Device GUIDs from Controller Handle\r
498 //\r
499 ConPlatformUnInstallProtocol (\r
500 This,\r
501 ControllerHandle,\r
502 &gEfiConsoleInDeviceGuid\r
503 );\r
504\r
505 //\r
c5ed97f6 506 // Close the Simple Text Input Protocol\r
95276127 507 //\r
508 gBS->CloseProtocol (\r
ca6b86ef 509 ControllerHandle,\r
510 &gEfiSimpleTextInProtocolGuid,\r
511 This->DriverBindingHandle,\r
512 ControllerHandle\r
513 );\r
95276127 514\r
515 return EFI_SUCCESS;\r
516}\r
517\r
9359e53f 518/**\r
d1102dba 519 Stop this driver on ControllerHandle by removing Console Out Devcice GUID\r
c5ed97f6 520 and closing the Simple Text Output protocol on ControllerHandle.\r
9359e53f 521\r
522 @param This Protocol instance pointer.\r
523 @param ControllerHandle Handle of device to stop driver on\r
524 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
525 children is zero stop the entire bus driver.\r
526 @param ChildHandleBuffer List of Child Handles to Stop.\r
527\r
528 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
529 @retval other This driver was not removed from this device\r
530\r
531**/\r
95276127 532EFI_STATUS\r
533EFIAPI\r
534ConPlatformTextOutDriverBindingStop (\r
535 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
536 IN EFI_HANDLE ControllerHandle,\r
537 IN UINTN NumberOfChildren,\r
538 IN EFI_HANDLE *ChildHandleBuffer\r
539 )\r
95276127 540{\r
541 EFI_STATUS Status;\r
542 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
543\r
544 //\r
f1aec6cc 545 // Get the Device Path Protocol firstly\r
95276127 546 //\r
f1aec6cc 547 Status = gBS->OpenProtocol (\r
548 ControllerHandle,\r
549 &gEfiDevicePathProtocolGuid,\r
1436aea4 550 (VOID **)&DevicePath,\r
f1aec6cc 551 This->DriverBindingHandle,\r
552 ControllerHandle,\r
553 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
554 );\r
555 if (!EFI_ERROR (Status)) {\r
95276127 556 //\r
ca6b86ef 557 // Remove DevicePath from ConOutDev and ErrOutDev if exists.\r
95276127 558 //\r
ca6b86ef 559 ConPlatformUpdateDeviceVariable (\r
560 L"ConOutDev",\r
561 DevicePath,\r
1ccdbf2a 562 Delete\r
ca6b86ef 563 );\r
564 ConPlatformUpdateDeviceVariable (\r
565 L"ErrOutDev",\r
566 DevicePath,\r
1ccdbf2a 567 Delete\r
ca6b86ef 568 );\r
95276127 569 }\r
f1aec6cc 570\r
95276127 571 //\r
572 // Uninstall the Console Device GUIDs from Controller Handle\r
573 //\r
574 ConPlatformUnInstallProtocol (\r
575 This,\r
576 ControllerHandle,\r
577 &gEfiConsoleOutDeviceGuid\r
578 );\r
579\r
580 ConPlatformUnInstallProtocol (\r
581 This,\r
582 ControllerHandle,\r
583 &gEfiStandardErrorDeviceGuid\r
584 );\r
585\r
586 //\r
587 // Close the Simple Text Output Protocol\r
588 //\r
589 gBS->CloseProtocol (\r
1436aea4
MK
590 ControllerHandle,\r
591 &gEfiSimpleTextOutProtocolGuid,\r
592 This->DriverBindingHandle,\r
593 ControllerHandle\r
594 );\r
95276127 595\r
596 return EFI_SUCCESS;\r
597}\r
598\r
9359e53f 599/**\r
7b9ff698 600 Uninstall the specified protocol.\r
9359e53f 601\r
602 @param This Protocol instance pointer.\r
7b9ff698 603 @param Handle Handle of device to uninstall protocol on.\r
604 @param ProtocolGuid The specified protocol need to be uninstalled.\r
9359e53f 605\r
9359e53f 606**/\r
95276127 607VOID\r
608ConPlatformUnInstallProtocol (\r
609 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
610 IN EFI_HANDLE Handle,\r
611 IN EFI_GUID *ProtocolGuid\r
612 )\r
613{\r
614 EFI_STATUS Status;\r
615\r
616 Status = gBS->OpenProtocol (\r
617 Handle,\r
618 ProtocolGuid,\r
619 NULL,\r
620 This->DriverBindingHandle,\r
621 Handle,\r
622 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
623 );\r
624\r
625 if (!EFI_ERROR (Status)) {\r
626 gBS->UninstallMultipleProtocolInterfaces (\r
c5ed97f6 627 Handle,\r
628 ProtocolGuid,\r
629 NULL,\r
630 NULL\r
631 );\r
95276127 632 }\r
633\r
1436aea4 634 return;\r
95276127 635}\r
636\r
9359e53f 637/**\r
7772b176 638 Get the necessary size of buffer and read the variable.\r
c5ed97f6 639\r
640 First get the necessary size of buffer. Then read the\r
641 EFI variable (Name) and return a dynamically allocated\r
642 buffer. On failure return NULL.\r
95276127 643\r
9359e53f 644 @param Name String part of EFI variable name\r
95276127 645\r
9359e53f 646 @return Dynamically allocated memory that contains a copy of the EFI variable.\r
d1102dba 647 Caller is repsoncible freeing the buffer. Return NULL means Variable\r
7b9ff698 648 was not read.\r
95276127 649\r
9359e53f 650**/\r
651VOID *\r
652ConPlatformGetVariable (\r
1436aea4 653 IN CHAR16 *Name\r
9359e53f 654 )\r
95276127 655{\r
656 EFI_STATUS Status;\r
657 VOID *Buffer;\r
658 UINTN BufferSize;\r
659\r
1436aea4
MK
660 BufferSize = 0;\r
661 Buffer = NULL;\r
95276127 662\r
663 //\r
c5ed97f6 664 // Test to see if the variable exists. If it doesn't, return NULL.\r
95276127 665 //\r
666 Status = gRT->GetVariable (\r
667 Name,\r
668 &gEfiGlobalVariableGuid,\r
669 NULL,\r
670 &BufferSize,\r
671 Buffer\r
672 );\r
673\r
674 if (Status == EFI_BUFFER_TOO_SMALL) {\r
675 //\r
676 // Allocate the buffer to return\r
677 //\r
678 Buffer = AllocatePool (BufferSize);\r
679 if (Buffer == NULL) {\r
680 return NULL;\r
681 }\r
1436aea4 682\r
95276127 683 //\r
684 // Read variable into the allocated buffer.\r
685 //\r
686 Status = gRT->GetVariable (\r
687 Name,\r
688 &gEfiGlobalVariableGuid,\r
689 NULL,\r
690 &BufferSize,\r
691 Buffer\r
692 );\r
693 if (EFI_ERROR (Status)) {\r
694 FreePool (Buffer);\r
7b9ff698 695 //\r
696 // To make sure Buffer is NULL if any error occurs.\r
697 //\r
95276127 698 Buffer = NULL;\r
699 }\r
700 }\r
701\r
702 return Buffer;\r
703}\r
704\r
19f50882
RN
705/**\r
706 Function returns TRUE when the two input device paths point to the two\r
707 GOP child handles that have the same parent.\r
708\r
709 @param Left A pointer to a device path data structure.\r
710 @param Right A pointer to a device path data structure.\r
711\r
712 @retval TRUE Left and Right share the same parent.\r
713 @retval FALSE Left and Right don't share the same parent or either of them is not\r
714 a GOP device path.\r
715**/\r
716BOOLEAN\r
717IsGopSibling (\r
718 IN EFI_DEVICE_PATH_PROTOCOL *Left,\r
719 IN EFI_DEVICE_PATH_PROTOCOL *Right\r
720 )\r
721{\r
722 EFI_DEVICE_PATH_PROTOCOL *NodeLeft;\r
723 EFI_DEVICE_PATH_PROTOCOL *NodeRight;\r
724\r
725 for (NodeLeft = Left; !IsDevicePathEndType (NodeLeft); NodeLeft = NextDevicePathNode (NodeLeft)) {\r
1436aea4
MK
726 if (((DevicePathType (NodeLeft) == ACPI_DEVICE_PATH) && (DevicePathSubType (NodeLeft) == ACPI_ADR_DP)) ||\r
727 ((DevicePathType (NodeLeft) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (NodeLeft) == HW_CONTROLLER_DP) &&\r
728 (DevicePathType (NextDevicePathNode (NodeLeft)) == ACPI_DEVICE_PATH) && (DevicePathSubType (NextDevicePathNode (NodeLeft)) == ACPI_ADR_DP)))\r
729 {\r
19f50882
RN
730 break;\r
731 }\r
732 }\r
733\r
734 if (IsDevicePathEndType (NodeLeft)) {\r
735 return FALSE;\r
736 }\r
737\r
738 for (NodeRight = Right; !IsDevicePathEndType (NodeRight); NodeRight = NextDevicePathNode (NodeRight)) {\r
1436aea4
MK
739 if (((DevicePathType (NodeRight) == ACPI_DEVICE_PATH) && (DevicePathSubType (NodeRight) == ACPI_ADR_DP)) ||\r
740 ((DevicePathType (NodeRight) == HARDWARE_DEVICE_PATH) && (DevicePathSubType (NodeRight) == HW_CONTROLLER_DP) &&\r
741 (DevicePathType (NextDevicePathNode (NodeRight)) == ACPI_DEVICE_PATH) && (DevicePathSubType (NextDevicePathNode (NodeRight)) == ACPI_ADR_DP)))\r
742 {\r
19f50882
RN
743 break;\r
744 }\r
745 }\r
746\r
747 if (IsDevicePathEndType (NodeRight)) {\r
748 return FALSE;\r
749 }\r
750\r
1436aea4 751 if (((UINTN)NodeLeft - (UINTN)Left) != ((UINTN)NodeRight - (UINTN)Right)) {\r
19f50882
RN
752 return FALSE;\r
753 }\r
754\r
1436aea4 755 return (BOOLEAN)(CompareMem (Left, Right, (UINTN)NodeLeft - (UINTN)Left) == 0);\r
19f50882
RN
756}\r
757\r
5c9ac43f
RN
758/**\r
759 Check whether a USB device match the specified USB Class device path. This\r
760 function follows "Load Option Processing" behavior in UEFI specification.\r
761\r
762 @param UsbIo USB I/O protocol associated with the USB device.\r
763 @param UsbClass The USB Class device path to match.\r
764\r
765 @retval TRUE The USB device match the USB Class device path.\r
766 @retval FALSE The USB device does not match the USB Class device path.\r
767\r
768**/\r
769BOOLEAN\r
770MatchUsbClass (\r
1436aea4
MK
771 IN EFI_USB_IO_PROTOCOL *UsbIo,\r
772 IN USB_CLASS_DEVICE_PATH *UsbClass\r
5c9ac43f
RN
773 )\r
774{\r
775 EFI_STATUS Status;\r
776 EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
777 EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
778 UINT8 DeviceClass;\r
779 UINT8 DeviceSubClass;\r
780 UINT8 DeviceProtocol;\r
781\r
782 if ((DevicePathType (UsbClass) != MESSAGING_DEVICE_PATH) ||\r
1436aea4
MK
783 (DevicePathSubType (UsbClass) != MSG_USB_CLASS_DP))\r
784 {\r
5c9ac43f
RN
785 return FALSE;\r
786 }\r
787\r
788 //\r
789 // Check Vendor Id and Product Id.\r
790 //\r
791 Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
792 if (EFI_ERROR (Status)) {\r
793 return FALSE;\r
794 }\r
795\r
796 if ((UsbClass->VendorId != 0xffff) &&\r
1436aea4
MK
797 (UsbClass->VendorId != DevDesc.IdVendor))\r
798 {\r
5c9ac43f
RN
799 return FALSE;\r
800 }\r
801\r
802 if ((UsbClass->ProductId != 0xffff) &&\r
1436aea4
MK
803 (UsbClass->ProductId != DevDesc.IdProduct))\r
804 {\r
5c9ac43f
RN
805 return FALSE;\r
806 }\r
807\r
808 DeviceClass = DevDesc.DeviceClass;\r
809 DeviceSubClass = DevDesc.DeviceSubClass;\r
810 DeviceProtocol = DevDesc.DeviceProtocol;\r
811 if (DeviceClass == 0) {\r
812 //\r
813 // If Class in Device Descriptor is set to 0, use the Class, SubClass and\r
814 // Protocol in Interface Descriptor instead.\r
815 //\r
816 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
817 if (EFI_ERROR (Status)) {\r
818 return FALSE;\r
819 }\r
820\r
821 DeviceClass = IfDesc.InterfaceClass;\r
822 DeviceSubClass = IfDesc.InterfaceSubClass;\r
823 DeviceProtocol = IfDesc.InterfaceProtocol;\r
824 }\r
825\r
826 //\r
827 // Check Class, SubClass and Protocol.\r
828 //\r
829 if ((UsbClass->DeviceClass != 0xff) &&\r
1436aea4
MK
830 (UsbClass->DeviceClass != DeviceClass))\r
831 {\r
5c9ac43f
RN
832 return FALSE;\r
833 }\r
834\r
835 if ((UsbClass->DeviceSubClass != 0xff) &&\r
1436aea4
MK
836 (UsbClass->DeviceSubClass != DeviceSubClass))\r
837 {\r
5c9ac43f
RN
838 return FALSE;\r
839 }\r
840\r
841 if ((UsbClass->DeviceProtocol != 0xff) &&\r
1436aea4
MK
842 (UsbClass->DeviceProtocol != DeviceProtocol))\r
843 {\r
5c9ac43f
RN
844 return FALSE;\r
845 }\r
846\r
847 return TRUE;\r
848}\r
849\r
850/**\r
851 Check whether a USB device match the specified USB WWID device path. This\r
852 function follows "Load Option Processing" behavior in UEFI specification.\r
853\r
854 @param UsbIo USB I/O protocol associated with the USB device.\r
855 @param UsbWwid The USB WWID device path to match.\r
856\r
857 @retval TRUE The USB device match the USB WWID device path.\r
858 @retval FALSE The USB device does not match the USB WWID device path.\r
859\r
860**/\r
861BOOLEAN\r
862MatchUsbWwid (\r
1436aea4
MK
863 IN EFI_USB_IO_PROTOCOL *UsbIo,\r
864 IN USB_WWID_DEVICE_PATH *UsbWwid\r
5c9ac43f
RN
865 )\r
866{\r
1436aea4
MK
867 EFI_STATUS Status;\r
868 EFI_USB_DEVICE_DESCRIPTOR DevDesc;\r
869 EFI_USB_INTERFACE_DESCRIPTOR IfDesc;\r
870 UINT16 *LangIdTable;\r
871 UINT16 TableSize;\r
872 UINT16 Index;\r
873 CHAR16 *CompareStr;\r
874 UINTN CompareLen;\r
875 CHAR16 *SerialNumberStr;\r
876 UINTN Length;\r
5c9ac43f
RN
877\r
878 if ((DevicePathType (UsbWwid) != MESSAGING_DEVICE_PATH) ||\r
1436aea4
MK
879 (DevicePathSubType (UsbWwid) != MSG_USB_WWID_DP))\r
880 {\r
5c9ac43f
RN
881 return FALSE;\r
882 }\r
883\r
884 //\r
885 // Check Vendor Id and Product Id.\r
886 //\r
887 Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);\r
888 if (EFI_ERROR (Status)) {\r
889 return FALSE;\r
890 }\r
1436aea4 891\r
5c9ac43f 892 if ((DevDesc.IdVendor != UsbWwid->VendorId) ||\r
1436aea4
MK
893 (DevDesc.IdProduct != UsbWwid->ProductId))\r
894 {\r
5c9ac43f
RN
895 return FALSE;\r
896 }\r
897\r
898 //\r
899 // Check Interface Number.\r
900 //\r
901 Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);\r
902 if (EFI_ERROR (Status)) {\r
903 return FALSE;\r
904 }\r
1436aea4 905\r
5c9ac43f
RN
906 if (IfDesc.InterfaceNumber != UsbWwid->InterfaceNumber) {\r
907 return FALSE;\r
908 }\r
909\r
910 //\r
911 // Check Serial Number.\r
912 //\r
913 if (DevDesc.StrSerialNumber == 0) {\r
914 return FALSE;\r
915 }\r
916\r
917 //\r
918 // Get all supported languages.\r
919 //\r
1436aea4 920 TableSize = 0;\r
5c9ac43f 921 LangIdTable = NULL;\r
1436aea4 922 Status = UsbIo->UsbGetSupportedLanguages (UsbIo, &LangIdTable, &TableSize);\r
5c9ac43f
RN
923 if (EFI_ERROR (Status) || (TableSize == 0) || (LangIdTable == NULL)) {\r
924 return FALSE;\r
925 }\r
926\r
927 //\r
928 // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.\r
929 //\r
1436aea4 930 CompareStr = (CHAR16 *)(UINTN)(UsbWwid + 1);\r
5c9ac43f
RN
931 CompareLen = (DevicePathNodeLength (UsbWwid) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);\r
932 if (CompareStr[CompareLen - 1] == L'\0') {\r
933 CompareLen--;\r
934 }\r
935\r
936 //\r
937 // Compare serial number in each supported language.\r
938 //\r
939 for (Index = 0; Index < TableSize / sizeof (UINT16); Index++) {\r
940 SerialNumberStr = NULL;\r
1436aea4
MK
941 Status = UsbIo->UsbGetStringDescriptor (\r
942 UsbIo,\r
943 LangIdTable[Index],\r
944 DevDesc.StrSerialNumber,\r
945 &SerialNumberStr\r
946 );\r
5c9ac43f
RN
947 if (EFI_ERROR (Status) || (SerialNumberStr == NULL)) {\r
948 continue;\r
949 }\r
950\r
951 Length = StrLen (SerialNumberStr);\r
952 if ((Length >= CompareLen) &&\r
1436aea4
MK
953 (CompareMem (SerialNumberStr + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 0))\r
954 {\r
5c9ac43f
RN
955 FreePool (SerialNumberStr);\r
956 return TRUE;\r
957 }\r
958\r
959 FreePool (SerialNumberStr);\r
960 }\r
961\r
962 return FALSE;\r
963}\r
964\r
965/**\r
966 Compare whether a full console device path matches a USB shortform device path.\r
967\r
968 @param[in] FullPath Full console device path.\r
969 @param[in] ShortformPath Short-form device path. Short-form device node may in the beginning or in the middle.\r
970\r
971 @retval TRUE The full console device path matches the short-form device path.\r
972 @retval FALSE The full console device path doesn't match the short-form device path.\r
973**/\r
974BOOLEAN\r
975MatchUsbShortformDevicePath (\r
976 IN EFI_DEVICE_PATH_PROTOCOL *FullPath,\r
977 IN EFI_DEVICE_PATH_PROTOCOL *ShortformPath\r
978 )\r
979{\r
980 EFI_STATUS Status;\r
981 EFI_DEVICE_PATH_PROTOCOL *ShortformNode;\r
982 UINTN ParentDevicePathSize;\r
983 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
984 EFI_USB_IO_PROTOCOL *UsbIo;\r
985 EFI_HANDLE Handle;\r
986\r
987 for ( ShortformNode = ShortformPath\r
1436aea4
MK
988 ; !IsDevicePathEnd (ShortformNode)\r
989 ; ShortformNode = NextDevicePathNode (ShortformNode)\r
990 )\r
991 {\r
5c9ac43f
RN
992 if ((DevicePathType (ShortformNode) == MESSAGING_DEVICE_PATH) &&\r
993 ((DevicePathSubType (ShortformNode) == MSG_USB_CLASS_DP) ||\r
994 (DevicePathSubType (ShortformNode) == MSG_USB_WWID_DP))\r
1436aea4
MK
995 )\r
996 {\r
5c9ac43f
RN
997 break;\r
998 }\r
999 }\r
1000\r
1001 //\r
1002 // Skip further compare when it's not a shortform device path.\r
1003 //\r
1004 if (IsDevicePathEnd (ShortformNode)) {\r
1005 return FALSE;\r
1006 }\r
1007\r
1008 //\r
1009 // Compare the parent device path when the ShortformPath doesn't start with short-form node.\r
1010 //\r
1436aea4 1011 ParentDevicePathSize = (UINTN)ShortformNode - (UINTN)ShortformPath;\r
5c9ac43f
RN
1012 RemainingDevicePath = FullPath;\r
1013 Status = gBS->LocateDevicePath (&gEfiUsbIoProtocolGuid, &RemainingDevicePath, &Handle);\r
1014 if (EFI_ERROR (Status)) {\r
1015 return FALSE;\r
1016 }\r
1436aea4 1017\r
5c9ac43f 1018 if (ParentDevicePathSize != 0) {\r
1436aea4
MK
1019 if ((ParentDevicePathSize > (UINTN)RemainingDevicePath - (UINTN)FullPath) ||\r
1020 (CompareMem (FullPath, ShortformPath, ParentDevicePathSize) != 0))\r
1021 {\r
5c9ac43f
RN
1022 return FALSE;\r
1023 }\r
1024 }\r
1025\r
1026 //\r
1027 // Compar the USB layer.\r
1028 //\r
1436aea4 1029 Status = gBS->HandleProtocol (\r
5c9ac43f
RN
1030 Handle,\r
1031 &gEfiUsbIoProtocolGuid,\r
1436aea4 1032 (VOID **)&UsbIo\r
5c9ac43f
RN
1033 );\r
1034 ASSERT_EFI_ERROR (Status);\r
1035\r
1036 return MatchUsbClass (UsbIo, (USB_CLASS_DEVICE_PATH *)ShortformNode) ||\r
1037 MatchUsbWwid (UsbIo, (USB_WWID_DEVICE_PATH *)ShortformNode);\r
1038}\r
1039\r
9359e53f 1040/**\r
95276127 1041 Function compares a device path data structure to that of all the nodes of a\r
1042 second device path instance.\r
1043\r
9359e53f 1044 @param Multi A pointer to a multi-instance device path data structure.\r
1045 @param Single A pointer to a single-instance device path data structure.\r
1046 @param NewDevicePath If Delete is TRUE, this parameter must not be null, and it\r
1047 points to the remaining device path data structure.\r
1048 (remaining device path = Multi - Single.)\r
1049 @param Delete If TRUE, means removing Single from Multi.\r
1050 If FALSE, the routine just check whether Single matches\r
1051 with any instance in Multi.\r
95276127 1052\r
c5ed97f6 1053 @retval EFI_SUCCESS If the Single is contained within Multi.\r
1054 @retval EFI_NOT_FOUND If the Single is not contained within Multi.\r
1055 @retval EFI_INVALID_PARAMETER Multi is NULL.\r
1056 @retval EFI_INVALID_PARAMETER Single is NULL.\r
1057 @retval EFI_INVALID_PARAMETER NewDevicePath is NULL when Delete is TRUE.\r
95276127 1058\r
9359e53f 1059**/\r
1060EFI_STATUS\r
1061ConPlatformMatchDevicePaths (\r
1062 IN EFI_DEVICE_PATH_PROTOCOL *Multi,\r
1063 IN EFI_DEVICE_PATH_PROTOCOL *Single,\r
7b9ff698 1064 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath OPTIONAL,\r
9359e53f 1065 IN BOOLEAN Delete\r
1066 )\r
95276127 1067{\r
1068 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
7b9ff698 1069 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath1;\r
1070 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath2;\r
95276127 1071 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
1072 UINTN Size;\r
1073\r
1074 //\r
1075 // The passed in DevicePath should not be NULL\r
1076 //\r
9359e53f 1077 if ((Multi == NULL) || (Single == NULL)) {\r
c5ed97f6 1078 return EFI_INVALID_PARAMETER;\r
95276127 1079 }\r
7b9ff698 1080\r
95276127 1081 //\r
7b9ff698 1082 // If performing Delete operation, the NewDevicePath must not be NULL.\r
95276127 1083 //\r
7b9ff698 1084 if (Delete) {\r
c5ed97f6 1085 if (NewDevicePath == NULL) {\r
1086 return EFI_INVALID_PARAMETER;\r
1087 }\r
7b9ff698 1088 }\r
1089\r
1090 TempDevicePath1 = NULL;\r
95276127 1091\r
1436aea4
MK
1092 DevicePath = Multi;\r
1093 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
95276127 1094\r
1095 //\r
7b9ff698 1096 // Search for the match of 'Single' in 'Multi'\r
95276127 1097 //\r
9359e53f 1098 while (DevicePathInst != NULL) {\r
5c9ac43f 1099 if ((CompareMem (Single, DevicePathInst, Size) == 0) ||\r
1436aea4
MK
1100 IsGopSibling (Single, DevicePathInst) || MatchUsbShortformDevicePath (Single, DevicePathInst))\r
1101 {\r
95276127 1102 if (!Delete) {\r
7b9ff698 1103 //\r
1104 // If Delete is FALSE, return EFI_SUCCESS if Single is found in Multi.\r
1105 //\r
95276127 1106 FreePool (DevicePathInst);\r
1107 return EFI_SUCCESS;\r
1108 }\r
1109 } else {\r
1110 if (Delete) {\r
7b9ff698 1111 //\r
c5ed97f6 1112 // If the node of Multi does not match Single, then added it back to the result.\r
1113 // That is, the node matching Single will be dropped and deleted from result.\r
7b9ff698 1114 //\r
1115 TempDevicePath2 = AppendDevicePathInstance (\r
1116 TempDevicePath1,\r
95276127 1117 DevicePathInst\r
1118 );\r
676df92c 1119 if (TempDevicePath1 != NULL) {\r
1120 FreePool (TempDevicePath1);\r
1121 }\r
1436aea4 1122\r
7b9ff698 1123 TempDevicePath1 = TempDevicePath2;\r
95276127 1124 }\r
1125 }\r
1126\r
1127 FreePool (DevicePathInst);\r
1128 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
1129 }\r
1130\r
1131 if (Delete) {\r
7b9ff698 1132 //\r
c5ed97f6 1133 // Return the new device path data structure with specified node deleted.\r
7b9ff698 1134 //\r
1135 *NewDevicePath = TempDevicePath1;\r
95276127 1136 return EFI_SUCCESS;\r
1137 }\r
1138\r
1139 return EFI_NOT_FOUND;\r
1140}\r
1141\r
9359e53f 1142/**\r
d1102dba 1143 Update console environment variables.\r
9359e53f 1144\r
1145 @param VariableName Console environment variables, ConOutDev, ConInDev\r
7772b176 1146 ErrOutDev, ConIn ,ConOut or ErrOut.\r
9359e53f 1147 @param DevicePath Console devcie's device path.\r
c5ed97f6 1148 @param Operation Variable operations, including APPEND, CHECK and DELETE.\r
9359e53f 1149\r
1150 @retval EFI_SUCCESS Variable operates successfully.\r
1151 @retval EFI_OUT_OF_RESOURCES If variable cannot be appended.\r
1152 @retval other Variable updating failed.\r
1153\r
1154**/\r
95276127 1155EFI_STATUS\r
1156ConPlatformUpdateDeviceVariable (\r
1436aea4
MK
1157 IN CHAR16 *VariableName,\r
1158 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1159 IN CONPLATFORM_VAR_OPERATION Operation\r
95276127 1160 )\r
95276127 1161{\r
1162 EFI_STATUS Status;\r
1163 EFI_DEVICE_PATH_PROTOCOL *VariableDevicePath;\r
1164 EFI_DEVICE_PATH_PROTOCOL *NewVariableDevicePath;\r
1165\r
1166 VariableDevicePath = NULL;\r
1167 NewVariableDevicePath = NULL;\r
1168\r
1169 //\r
1170 // Get Variable according to variable name.\r
1171 // The memory for Variable is allocated within ConPlatformGetVarible(),\r
1172 // it is the caller's responsibility to free the memory before return.\r
1173 //\r
1174 VariableDevicePath = ConPlatformGetVariable (VariableName);\r
1175\r
1ccdbf2a 1176 if (Operation != Delete) {\r
7b9ff698 1177 //\r
1178 // Match specified DevicePath in Console Variable.\r
d1102dba 1179 //\r
95276127 1180 Status = ConPlatformMatchDevicePaths (\r
c5ed97f6 1181 VariableDevicePath,\r
1182 DevicePath,\r
1183 NULL,\r
1184 FALSE\r
1185 );\r
95276127 1186\r
1ccdbf2a 1187 if ((Operation == Check) || (!EFI_ERROR (Status))) {\r
95276127 1188 //\r
c5ed97f6 1189 // Branch here includes 2 cases:\r
1190 // 1. Operation is CHECK, simply return Status.\r
1191 // 2. Operation is APPEND, and device path already exists in variable, also return.\r
95276127 1192 //\r
1193 if (VariableDevicePath != NULL) {\r
1194 FreePool (VariableDevicePath);\r
1195 }\r
1196\r
1197 return Status;\r
1198 }\r
1436aea4 1199\r
95276127 1200 //\r
c5ed97f6 1201 // We reach here to append a device path that does not exist in variable.\r
95276127 1202 //\r
1436aea4 1203 Status = EFI_SUCCESS;\r
95276127 1204 NewVariableDevicePath = AppendDevicePathInstance (\r
1205 VariableDevicePath,\r
1206 DevicePath\r
1207 );\r
1208 if (NewVariableDevicePath == NULL) {\r
1209 Status = EFI_OUT_OF_RESOURCES;\r
1210 }\r
95276127 1211 } else {\r
1212 //\r
c5ed97f6 1213 // We reach here to remove DevicePath from the environment variable that\r
95276127 1214 // is a multi-instance device path.\r
1215 //\r
1216 Status = ConPlatformMatchDevicePaths (\r
c5ed97f6 1217 VariableDevicePath,\r
1218 DevicePath,\r
1219 &NewVariableDevicePath,\r
1220 TRUE\r
1221 );\r
95276127 1222 }\r
1223\r
1224 if (VariableDevicePath != NULL) {\r
1225 FreePool (VariableDevicePath);\r
1226 }\r
1227\r
1228 if (EFI_ERROR (Status)) {\r
1229 return Status;\r
1230 }\r
1231\r
c62a593c 1232 if (NewVariableDevicePath != NULL) {\r
7b9ff698 1233 //\r
1234 // Update Console Environment Variable.\r
1235 //\r
c62a593c 1236 Status = gRT->SetVariable (\r
1237 VariableName,\r
1238 &gEfiGlobalVariableGuid,\r
1239 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
1240 GetDevicePathSize (NewVariableDevicePath),\r
1241 NewVariableDevicePath\r
1242 );\r
95276127 1243\r
c62a593c 1244 FreePool (NewVariableDevicePath);\r
1245 }\r
95276127 1246\r
1247 return Status;\r
1248}\r
1249\r
5b7183ef
RN
1250/**\r
1251 Update ConOutDev and ErrOutDev variables to add the device path of\r
1252 GOP controller itself and the sibling controllers.\r
1253\r
1254 @param DevicePath Pointer to device's device path.\r
1255\r
1256 @retval TRUE The devcie is a GOP device.\r
1257 @retval FALSE The devcie is not a GOP device.\r
1258\r
1259**/\r
1260BOOLEAN\r
1261ConPlatformUpdateGopCandidate (\r
1436aea4 1262 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
5b7183ef
RN
1263 )\r
1264{\r
1436aea4
MK
1265 EFI_STATUS Status;\r
1266 EFI_HANDLE PciHandle;\r
1267 EFI_HANDLE GopHandle;\r
1268 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
5b7183ef
RN
1269\r
1270 //\r
1271 // Check whether it's a GOP device.\r
1272 //\r
1273 TempDevicePath = DevicePath;\r
1436aea4 1274 Status = gBS->LocateDevicePath (&gEfiGraphicsOutputProtocolGuid, &TempDevicePath, &GopHandle);\r
5b7183ef
RN
1275 if (EFI_ERROR (Status)) {\r
1276 return FALSE;\r
1277 }\r
1436aea4 1278\r
5b7183ef
RN
1279 //\r
1280 // Get the parent PciIo handle in order to find all the children\r
1281 //\r
1282 Status = gBS->LocateDevicePath (&gEfiPciIoProtocolGuid, &DevicePath, &PciHandle);\r
1283 if (EFI_ERROR (Status)) {\r
1284 return FALSE;\r
1285 }\r
1436aea4 1286\r
56dee83a
RN
1287 TempDevicePath = EfiBootManagerGetGopDevicePath (PciHandle);\r
1288 if (TempDevicePath != NULL) {\r
1289 ConPlatformUpdateDeviceVariable (L"ConOutDev", TempDevicePath, Append);\r
1290 ConPlatformUpdateDeviceVariable (L"ErrOutDev", TempDevicePath, Append);\r
5b7183ef 1291 }\r
1436aea4 1292\r
5b7183ef
RN
1293 return TRUE;\r
1294}\r