3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 #include "ConPlatform.h"
26 // The protocols, PPI and GUID defintions for this module
28 #include <Protocol/SimpleTextOut.h>
29 #include <Guid/GlobalVariable.h>
30 #include <Guid/ConsoleInDevice.h>
31 #include <Protocol/DevicePath.h>
32 #include <Protocol/SimpleTextIn.h>
33 #include <Guid/HotPlugDevice.h>
34 #include <Guid/StandardErrorDevice.h>
35 #include <Guid/ConsoleOutDevice.h>
37 // The Library classes this module consumes
39 #include <Library/DebugLib.h>
40 #include <Library/UefiDriverEntryPoint.h>
41 #include <Library/UefiLib.h>
42 #include <Library/BaseMemoryLib.h>
43 #include <Library/UefiBootServicesTableLib.h>
44 #include <Library/UefiRuntimeServicesTableLib.h>
45 #include <Library/DevicePathLib.h>
46 #include <Library/MemoryAllocationLib.h>
48 // Driver Binding Externs
50 extern EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding
;
51 extern EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName
;
52 extern EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding
;
53 extern EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName
;
55 EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding
= {
56 ConPlatformTextInDriverBindingSupported
,
57 ConPlatformTextInDriverBindingStart
,
58 ConPlatformTextInDriverBindingStop
,
64 EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding
= {
65 ConPlatformTextOutDriverBindingSupported
,
66 ConPlatformTextOutDriverBindingStart
,
67 ConPlatformTextOutDriverBindingStop
,
74 The user Entry Point for module ConPlatform. The user code starts with this function.
76 @param[in] ImageHandle The firmware allocated handle for the EFI image.
77 @param[in] SystemTable A pointer to the EFI System Table.
79 @retval EFI_SUCCESS The entry point is executed successfully.
80 @retval other Some error occurs when executing this entry point.
85 InitializeConPlatform(
86 IN EFI_HANDLE ImageHandle
,
87 IN EFI_SYSTEM_TABLE
*SystemTable
93 // Install driver model protocol(s).
95 Status
= EfiLibInstallAllDriverProtocols (
98 &gConPlatformTextInDriverBinding
,
100 &gConPlatformComponentName
,
104 ASSERT_EFI_ERROR (Status
);
106 Status
= EfiLibInstallAllDriverProtocols (
109 &gConPlatformTextOutDriverBinding
,
111 &gConPlatformComponentName
,
115 ASSERT_EFI_ERROR (Status
);
124 ConPlatformTextInDriverBindingSupported (
125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
126 IN EFI_HANDLE ControllerHandle
,
127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
135 (Standard DriverBinding Protocol Supported() function)
143 return ConPlatformDriverBindingSupported (
147 &gEfiSimpleTextInProtocolGuid
153 ConPlatformTextOutDriverBindingSupported (
154 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
155 IN EFI_HANDLE ControllerHandle
,
156 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
164 (Standard DriverBinding Protocol Supported() function)
172 return ConPlatformDriverBindingSupported (
176 &gEfiSimpleTextOutProtocolGuid
181 ConPlatformDriverBindingSupported (
182 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
183 IN EFI_HANDLE ControllerHandle
,
184 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
185 IN EFI_GUID
*ProtocolGuid
193 (Standard DriverBinding Protocol Supported() function)
205 // Test to see if this is a physical device by checking to see if
206 // it has a Device Path Protocol
208 Status
= gBS
->OpenProtocol (
210 &gEfiDevicePathProtocolGuid
,
212 This
->DriverBindingHandle
,
214 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
216 if (EFI_ERROR (Status
)) {
220 // Test to see if this device supports the Simple Text Output Protocol
222 Status
= gBS
->OpenProtocol (
225 (VOID
**) &Interface
,
226 This
->DriverBindingHandle
,
228 EFI_OPEN_PROTOCOL_BY_DRIVER
230 if (EFI_ERROR (Status
)) {
237 This
->DriverBindingHandle
,
246 ConPlatformTextInDriverBindingStart (
247 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
248 IN EFI_HANDLE ControllerHandle
,
249 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
257 (Standard DriverBinding Protocol Start() function)
265 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
266 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*TextIn
;
269 // Get the Device Path Protocol so the environment variables can be updated
271 Status
= gBS
->OpenProtocol (
273 &gEfiDevicePathProtocolGuid
,
274 (VOID
**) &DevicePath
,
275 This
->DriverBindingHandle
,
277 EFI_OPEN_PROTOCOL_GET_PROTOCOL
279 if (EFI_ERROR (Status
)) {
283 // Open the Simple Input Protocol BY_DRIVER
285 Status
= gBS
->OpenProtocol (
287 &gEfiSimpleTextInProtocolGuid
,
289 This
->DriverBindingHandle
,
291 EFI_OPEN_PROTOCOL_BY_DRIVER
293 if (EFI_ERROR (Status
)) {
297 // Check the device handle, if it is a hot plug device,
298 // do not put the device path into ConInDev, and install
299 // gEfiConsoleInDeviceGuid to the device handle directly.
300 // The policy is, make hot plug device plug in and play immediately.
302 if (IsHotPlugDevice (This
->DriverBindingHandle
, ControllerHandle
)) {
303 gBS
->InstallMultipleProtocolInterfaces (
305 &gEfiConsoleInDeviceGuid
,
311 // Append the device path to the ConInDev environment variable
313 ConPlatformUpdateDeviceVariable (
320 // If the device path is an instance in the ConIn environment variable,
321 // then install EfiConsoleInDeviceGuid onto ControllerHandle
323 Status
= ConPlatformUpdateDeviceVariable (
329 if (!EFI_ERROR (Status
)) {
330 gBS
->InstallMultipleProtocolInterfaces (
332 &gEfiConsoleInDeviceGuid
,
339 &gEfiSimpleTextInProtocolGuid
,
340 This
->DriverBindingHandle
,
351 ConPlatformTextOutDriverBindingStart (
352 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
353 IN EFI_HANDLE ControllerHandle
,
354 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
362 (Standard DriverBinding Protocol Start() function)
370 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
371 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*TextOut
;
377 // Get the Device Path Protocol so the environment variables can be updated
379 Status
= gBS
->OpenProtocol (
381 &gEfiDevicePathProtocolGuid
,
382 (VOID
**) &DevicePath
,
383 This
->DriverBindingHandle
,
385 EFI_OPEN_PROTOCOL_GET_PROTOCOL
387 if (EFI_ERROR (Status
)) {
391 // Open the Simple Text Output Protocol BY_DRIVER
393 Status
= gBS
->OpenProtocol (
395 &gEfiSimpleTextOutProtocolGuid
,
397 This
->DriverBindingHandle
,
399 EFI_OPEN_PROTOCOL_BY_DRIVER
401 if (EFI_ERROR (Status
)) {
405 // Check the device handle, if it is a hot plug device,
406 // do not put the device path into ConOutDev and StdErrDev,
407 // and install gEfiConsoleOutDeviceGuid to the device handle directly.
408 // The policy is, make hot plug device plug in and play immediately.
410 if (IsHotPlugDevice (This
->DriverBindingHandle
, ControllerHandle
)) {
411 gBS
->InstallMultipleProtocolInterfaces (
413 &gEfiConsoleOutDeviceGuid
,
419 // Append the device path to the ConOutDev environment variable
421 ConPlatformUpdateDeviceVariable (
427 // Append the device path to the StdErrDev environment variable
429 ConPlatformUpdateDeviceVariable (
436 // If the device path is an instance in the ConOut environment variable,
437 // then install EfiConsoleOutDeviceGuid onto ControllerHandle
439 Status
= ConPlatformUpdateDeviceVariable (
445 if (!EFI_ERROR (Status
)) {
447 Status
= gBS
->InstallMultipleProtocolInterfaces (
449 &gEfiConsoleOutDeviceGuid
,
455 // If the device path is an instance in the StdErr environment variable,
456 // then install EfiStandardErrorDeviceGuid onto ControllerHandle
458 Status
= ConPlatformUpdateDeviceVariable (
463 if (!EFI_ERROR (Status
)) {
465 gBS
->InstallMultipleProtocolInterfaces (
467 &gEfiStandardErrorDeviceGuid
,
476 &gEfiSimpleTextOutProtocolGuid
,
477 This
->DriverBindingHandle
,
488 ConPlatformTextInDriverBindingStop (
489 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
490 IN EFI_HANDLE ControllerHandle
,
491 IN UINTN NumberOfChildren
,
492 IN EFI_HANDLE
*ChildHandleBuffer
499 (Standard DriverBinding Protocol Stop() function)
508 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
511 // hot plug device is not included into the console associated variables,
512 // so no need to check variable for those hot plug devices.
514 if (!IsHotPlugDevice (This
->DriverBindingHandle
, ControllerHandle
)) {
516 // Get the Device Path Protocol so the environment variables can be updated
518 Status
= gBS
->OpenProtocol (
520 &gEfiDevicePathProtocolGuid
,
521 (VOID
**) &DevicePath
,
522 This
->DriverBindingHandle
,
524 EFI_OPEN_PROTOCOL_GET_PROTOCOL
526 if (!EFI_ERROR (Status
)) {
528 // Remove DevicePath from ConInDev
530 ConPlatformUpdateDeviceVariable (
538 // Uninstall the Console Device GUIDs from Controller Handle
540 ConPlatformUnInstallProtocol (
543 &gEfiConsoleInDeviceGuid
547 // Close the Simple Input Protocol
551 &gEfiSimpleTextInProtocolGuid
,
552 This
->DriverBindingHandle
,
561 ConPlatformTextOutDriverBindingStop (
562 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
563 IN EFI_HANDLE ControllerHandle
,
564 IN UINTN NumberOfChildren
,
565 IN EFI_HANDLE
*ChildHandleBuffer
572 (Standard DriverBinding Protocol Stop() function)
581 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
584 // hot plug device is not included into the console associated variables,
585 // so no need to check variable for those hot plug devices.
587 if (!IsHotPlugDevice (This
->DriverBindingHandle
, ControllerHandle
)) {
589 // Get the Device Path Protocol so the environment variables can be updated
591 Status
= gBS
->OpenProtocol (
593 &gEfiDevicePathProtocolGuid
,
594 (VOID
**) &DevicePath
,
595 This
->DriverBindingHandle
,
597 EFI_OPEN_PROTOCOL_GET_PROTOCOL
599 if (!EFI_ERROR (Status
)) {
601 // Remove DevicePath from ConOutDev, and StdErrDev
603 ConPlatformUpdateDeviceVariable (
608 ConPlatformUpdateDeviceVariable (
616 // Uninstall the Console Device GUIDs from Controller Handle
618 ConPlatformUnInstallProtocol (
621 &gEfiConsoleOutDeviceGuid
624 ConPlatformUnInstallProtocol (
627 &gEfiStandardErrorDeviceGuid
631 // Close the Simple Text Output Protocol
635 &gEfiSimpleTextOutProtocolGuid
,
636 This
->DriverBindingHandle
,
645 ConPlatformUnInstallProtocol (
646 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
647 IN EFI_HANDLE Handle
,
648 IN EFI_GUID
*ProtocolGuid
653 Status
= gBS
->OpenProtocol (
657 This
->DriverBindingHandle
,
659 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
662 if (!EFI_ERROR (Status
)) {
663 gBS
->UninstallMultipleProtocolInterfaces (
675 ConPlatformGetVariable (
681 Read the EFI variable (Name) and return a dynamically allocated
682 buffer, and the size of the buffer. On failure return NULL.
685 Name - String part of EFI variable name
688 Dynamically allocated memory that contains a copy of the EFI variable.
689 Caller is repsoncible freeing the buffer.
691 NULL - Variable was not read
703 // Test to see if the variable exists. If it doesn't reuturn NULL
705 Status
= gRT
->GetVariable (
707 &gEfiGlobalVariableGuid
,
713 if (Status
== EFI_BUFFER_TOO_SMALL
) {
715 // Allocate the buffer to return
717 Buffer
= AllocatePool (BufferSize
);
718 if (Buffer
== NULL
) {
722 // Read variable into the allocated buffer.
724 Status
= gRT
->GetVariable (
726 &gEfiGlobalVariableGuid
,
731 if (EFI_ERROR (Status
)) {
741 ConPlatformMatchDevicePaths (
742 IN EFI_DEVICE_PATH_PROTOCOL
* Multi
,
743 IN EFI_DEVICE_PATH_PROTOCOL
* Single
,
744 IN EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath OPTIONAL
,
750 Function compares a device path data structure to that of all the nodes of a
751 second device path instance.
754 Multi - A pointer to a multi-instance device path data structure.
756 Single - A pointer to a single-instance device path data structure.
758 NewDevicePath - If Delete is TRUE, this parameter must not be null, and it
759 points to the remaining device path data structure.
760 (remaining device path = Multi - Single.)
762 Delete - If TRUE, means removing Single from Multi.
763 If FALSE, the routine just check whether Single matches
764 with any instance in Multi.
768 The function returns EFI_SUCCESS if the Single is contained within Multi.
769 Otherwise, EFI_NOT_FOUND is returned.
773 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
774 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath1
;
775 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath2
;
776 EFI_DEVICE_PATH_PROTOCOL
*DevicePathInst
;
780 // The passed in DevicePath should not be NULL
782 if ((!Multi
) || (!Single
)) {
783 return EFI_NOT_FOUND
;
786 // if performing Delete operation, the NewDevicePath must not be NULL.
788 TempDevicePath1
= NULL
;
791 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
794 // search for the match of 'Single' in 'Multi'
796 while (DevicePathInst
) {
797 if (CompareMem (Single
, DevicePathInst
, Size
) == 0) {
799 FreePool (DevicePathInst
);
804 TempDevicePath2
= AppendDevicePathInstance (
808 if (TempDevicePath1
!= NULL
) {
809 FreePool (TempDevicePath1
);
811 TempDevicePath1
= TempDevicePath2
;
815 FreePool (DevicePathInst
);
816 DevicePathInst
= GetNextDevicePathInstance (&DevicePath
, &Size
);
820 *NewDevicePath
= TempDevicePath1
;
824 return EFI_NOT_FOUND
;
828 ConPlatformUpdateDeviceVariable (
829 IN CHAR16
*VariableName
,
830 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
831 IN CONPLATFORM_VAR_OPERATION Operation
847 EFI_DEVICE_PATH_PROTOCOL
*VariableDevicePath
;
848 EFI_DEVICE_PATH_PROTOCOL
*NewVariableDevicePath
;
850 VariableDevicePath
= NULL
;
851 NewVariableDevicePath
= NULL
;
854 // Get Variable according to variable name.
855 // The memory for Variable is allocated within ConPlatformGetVarible(),
856 // it is the caller's responsibility to free the memory before return.
858 VariableDevicePath
= ConPlatformGetVariable (VariableName
);
860 if (Operation
!= DELETE
) {
862 Status
= ConPlatformMatchDevicePaths (
869 if ((Operation
== CHECK
) || (!EFI_ERROR (Status
))) {
871 // The device path is already in the variable
873 if (VariableDevicePath
!= NULL
) {
874 FreePool (VariableDevicePath
);
880 // The device path is not in variable. Append DevicePath to the
881 // environment variable that is a multi-instance device path.
883 Status
= EFI_SUCCESS
;
884 NewVariableDevicePath
= AppendDevicePathInstance (
888 if (NewVariableDevicePath
== NULL
) {
889 Status
= EFI_OUT_OF_RESOURCES
;
894 // Remove DevicePath from the environment variable that
895 // is a multi-instance device path.
897 Status
= ConPlatformMatchDevicePaths (
900 &NewVariableDevicePath
,
905 if (VariableDevicePath
!= NULL
) {
906 FreePool (VariableDevicePath
);
909 if (EFI_ERROR (Status
)) {
913 Status
= gRT
->SetVariable (
915 &gEfiGlobalVariableGuid
,
916 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
917 GetDevicePathSize (NewVariableDevicePath
),
918 NewVariableDevicePath
921 FreePool (NewVariableDevicePath
);
928 EFI_HANDLE DriverBindingHandle
,
929 EFI_HANDLE ControllerHandle
935 // HotPlugDeviceGuid indicates ControllerHandle stands for a hot plug device.
937 Status
= gBS
->OpenProtocol (
939 &gEfiHotPlugDeviceGuid
,
943 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
945 if (EFI_ERROR (Status
)) {