2 Serial driver for PCI or SIO UARTS.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // ISA Serial Driver Global Variables
15 EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver
= {
16 SerialControllerDriverSupported
,
17 SerialControllerDriverStart
,
18 SerialControllerDriverStop
,
24 CONTROLLER_DEVICE_PATH mControllerDevicePathTemplate
= {
29 (UINT8
)(sizeof (CONTROLLER_DEVICE_PATH
)),
30 (UINT8
)((sizeof (CONTROLLER_DEVICE_PATH
)) >> 8)
36 SERIAL_DEV gSerialDevTemplate
= {
40 SERIAL_IO_INTERFACE_REVISION
,
50 SERIAL_PORT_SUPPORT_CONTROL_MASK
,
51 SERIAL_PORT_DEFAULT_TIMEOUT
,
59 NULL
, // ParentDevicePath
62 MESSAGING_DEVICE_PATH
,
65 (UINT8
)(sizeof (UART_DEVICE_PATH
)),
66 (UINT8
)((sizeof (UART_DEVICE_PATH
)) >> 8)
75 16, // ReceiveFifoDepth
77 16, // TransmitFifoDepth
78 { 0, 0 }, // Transmit;
79 FALSE
, // SoftwareLoopbackEnable;
80 FALSE
, // HardwareFlowControl;
81 NULL
, // *ControllerNameTable;
82 FALSE
, // ContainsControllerNode;
84 NULL
// *PciDeviceInfo;
88 Check the device path node whether it's the Flow Control node or not.
90 @param[in] FlowControl The device path node to be checked.
92 @retval TRUE It's the Flow Control node.
93 @retval FALSE It's not.
97 IsUartFlowControlDevicePathNode (
98 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
102 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
103 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
104 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
109 The user Entry Point for module PciSioSerial. The user code starts with this function.
111 @param[in] ImageHandle The firmware allocated handle for the EFI image.
112 @param[in] SystemTable A pointer to the EFI System Table.
114 @retval EFI_SUCCESS The entry point is executed successfully.
115 @retval other Some error occurs when executing this entry point.
120 InitializePciSioSerial (
121 IN EFI_HANDLE ImageHandle
,
122 IN EFI_SYSTEM_TABLE
*SystemTable
128 // Install driver model protocol(s).
130 Status
= EfiLibInstallDriverBindingComponentName2 (
133 &gSerialControllerDriver
,
135 &gPciSioSerialComponentName
,
136 &gPciSioSerialComponentName2
138 ASSERT_EFI_ERROR (Status
);
141 // Initialize UART default setting in gSerialDevTemplate
143 gSerialDevTemplate
.SerialMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
144 gSerialDevTemplate
.SerialMode
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
145 gSerialDevTemplate
.SerialMode
.Parity
= PcdGet8 (PcdUartDefaultParity
);
146 gSerialDevTemplate
.SerialMode
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
147 gSerialDevTemplate
.UartDevicePath
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
148 gSerialDevTemplate
.UartDevicePath
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
149 gSerialDevTemplate
.UartDevicePath
.Parity
= PcdGet8 (PcdUartDefaultParity
);
150 gSerialDevTemplate
.UartDevicePath
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
151 gSerialDevTemplate
.ClockRate
= PcdGet32 (PcdSerialClockRate
);
157 Return whether the controller is a SIO serial controller.
159 @param Controller The controller handle.
161 @retval EFI_SUCCESS The controller is a SIO serial controller.
162 @retval others The controller is not a SIO serial controller.
165 IsSioSerialController (
166 EFI_HANDLE Controller
170 EFI_SIO_PROTOCOL
*Sio
;
171 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
172 ACPI_HID_DEVICE_PATH
*Acpi
;
175 // Open the IO Abstraction(s) needed to perform the supported test
177 Status
= gBS
->OpenProtocol (
179 &gEfiSioProtocolGuid
,
181 gSerialControllerDriver
.DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
185 if (Status
== EFI_ALREADY_STARTED
) {
189 if (!EFI_ERROR (Status
)) {
191 // Close the I/O Abstraction(s) used to perform the supported test
195 &gEfiSioProtocolGuid
,
196 gSerialControllerDriver
.DriverBindingHandle
,
200 Status
= gBS
->OpenProtocol (
202 &gEfiDevicePathProtocolGuid
,
203 (VOID
**)&DevicePath
,
204 gSerialControllerDriver
.DriverBindingHandle
,
206 EFI_OPEN_PROTOCOL_BY_DRIVER
208 ASSERT (Status
!= EFI_ALREADY_STARTED
);
210 if (!EFI_ERROR (Status
)) {
212 Acpi
= (ACPI_HID_DEVICE_PATH
*)DevicePath
;
213 DevicePath
= NextDevicePathNode (DevicePath
);
214 } while (!IsDevicePathEnd (DevicePath
));
216 if ((DevicePathType (Acpi
) != ACPI_DEVICE_PATH
) ||
217 ((DevicePathSubType (Acpi
) != ACPI_DP
) && (DevicePathSubType (Acpi
) != ACPI_EXTENDED_DP
)) ||
218 (Acpi
->HID
!= EISA_PNP_ID (0x501))
221 Status
= EFI_UNSUPPORTED
;
226 // Close protocol, don't use device path protocol in the Support() function
230 &gEfiDevicePathProtocolGuid
,
231 gSerialControllerDriver
.DriverBindingHandle
,
240 Return whether the controller is a PCI serial controller.
242 @param Controller The controller handle.
244 @retval EFI_SUCCESS The controller is a PCI serial controller.
245 @retval others The controller is not a PCI serial controller.
248 IsPciSerialController (
249 EFI_HANDLE Controller
253 EFI_PCI_IO_PROTOCOL
*PciIo
;
254 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
256 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
259 // Open the IO Abstraction(s) needed to perform the supported test
261 Status
= gBS
->OpenProtocol (
263 &gEfiPciIoProtocolGuid
,
265 gSerialControllerDriver
.DriverBindingHandle
,
267 EFI_OPEN_PROTOCOL_BY_DRIVER
269 if (Status
== EFI_ALREADY_STARTED
) {
273 if (!EFI_ERROR (Status
)) {
274 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
275 if (!EFI_ERROR (Status
)) {
276 if (!IS_PCI_16550_SERIAL (&Pci
)) {
277 for (PciSerialParameter
= (PCI_SERIAL_PARAMETER
*)PcdGetPtr (PcdPciSerialParameters
)
278 ; PciSerialParameter
->VendorId
!= 0xFFFF
279 ; PciSerialParameter
++
282 if ((Pci
.Hdr
.VendorId
== PciSerialParameter
->VendorId
) &&
283 (Pci
.Hdr
.DeviceId
== PciSerialParameter
->DeviceId
)
290 if (PciSerialParameter
->VendorId
== 0xFFFF) {
291 Status
= EFI_UNSUPPORTED
;
293 Status
= EFI_SUCCESS
;
299 // Close the I/O Abstraction(s) used to perform the supported test
303 &gEfiPciIoProtocolGuid
,
304 gSerialControllerDriver
.DriverBindingHandle
,
309 if (EFI_ERROR (Status
)) {
314 // Open the EFI Device Path protocol needed to perform the supported test
316 Status
= gBS
->OpenProtocol (
318 &gEfiDevicePathProtocolGuid
,
319 (VOID
**)&DevicePath
,
320 gSerialControllerDriver
.DriverBindingHandle
,
322 EFI_OPEN_PROTOCOL_BY_DRIVER
324 ASSERT (Status
!= EFI_ALREADY_STARTED
);
327 // Close protocol, don't use device path protocol in the Support() function
331 &gEfiDevicePathProtocolGuid
,
332 gSerialControllerDriver
.DriverBindingHandle
,
340 Check to see if this driver supports the given controller
342 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
343 @param Controller The handle of the controller to test.
344 @param RemainingDevicePath A pointer to the remaining portion of a device path.
346 @return EFI_SUCCESS This driver can support the given controller
351 SerialControllerDriverSupported (
352 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
353 IN EFI_HANDLE Controller
,
354 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
359 UART_DEVICE_PATH
*Uart
;
360 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
363 // Test RemainingDevicePath
365 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
366 Status
= EFI_UNSUPPORTED
;
368 Uart
= SkipControllerDevicePathNode (RemainingDevicePath
, NULL
, NULL
);
369 if ((DevicePathType (Uart
) != MESSAGING_DEVICE_PATH
) ||
370 (DevicePathSubType (Uart
) != MSG_UART_DP
) ||
371 (DevicePathNodeLength (Uart
) != sizeof (UART_DEVICE_PATH
))
374 return EFI_UNSUPPORTED
;
378 // Do a rough check because Clock Rate is unknown until DriverBindingStart()
380 if (!VerifyUartParameters (0, Uart
->BaudRate
, Uart
->DataBits
, Uart
->Parity
, Uart
->StopBits
, NULL
, NULL
)) {
381 return EFI_UNSUPPORTED
;
384 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*)NextDevicePathNode (Uart
);
385 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
387 // If the second node is Flow Control Node,
388 // return error when it request other than hardware flow control.
390 if ((ReadUnaligned32 (&FlowControl
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
391 return EFI_UNSUPPORTED
;
396 Status
= IsSioSerialController (Controller
);
397 if (EFI_ERROR (Status
)) {
398 Status
= IsPciSerialController (Controller
);
405 Create the child serial device instance.
407 @param Controller The parent controller handle.
408 @param Uart Pointer to the UART device path node in RemainingDevicePath,
409 or NULL if RemainingDevicePath is NULL.
410 @param ParentDevicePath Pointer to the parent device path.
411 @param CreateControllerNode TRUE to create the controller node.
412 @param Instance Instance number of the serial device.
413 The value will be set to the controller node
414 if CreateControllerNode is TRUE.
415 @param ParentIo A union type pointer to either Sio or PciIo.
416 @param PciSerialParameter The PCI serial parameter to be used by current serial device.
417 NULL for SIO serial device.
418 @param PciDeviceInfo The PCI device info for the current serial device.
419 NULL for SIO serial device.
421 @retval EFI_SUCCESS The serial device was created successfully.
422 @retval others The serial device wasn't created.
426 IN EFI_HANDLE Controller
,
427 IN UART_DEVICE_PATH
*Uart
,
428 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
429 IN BOOLEAN CreateControllerNode
,
431 IN PARENT_IO_PROTOCOL_PTR ParentIo
,
432 IN PCI_SERIAL_PARAMETER
*PciSerialParameter OPTIONAL
,
433 IN PCI_DEVICE_INFO
*PciDeviceInfo OPTIONAL
437 SERIAL_DEV
*SerialDevice
;
440 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
441 UINT32 FlowControlMap
;
442 ACPI_RESOURCE_HEADER_PTR Resources
;
443 EFI_ACPI_IO_PORT_DESCRIPTOR
*Io
;
444 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIo
;
445 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AddressSpace
;
446 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
454 // Initialize the serial device instance
456 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTemplate
);
457 ASSERT (SerialDevice
!= NULL
);
459 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
460 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
461 SerialDevice
->PciDeviceInfo
= PciDeviceInfo
;
462 SerialDevice
->Instance
= Instance
;
465 CopyMem (&SerialDevice
->UartDevicePath
, Uart
, sizeof (UART_DEVICE_PATH
));
466 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*)NextDevicePathNode (Uart
);
467 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
468 FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
475 // For PCI serial device, use the information from PCD
477 if (PciSerialParameter
!= NULL
) {
478 BarIndex
= (PciSerialParameter
->BarIndex
== MAX_UINT8
) ? 0 : PciSerialParameter
->BarIndex
;
479 Offset
= PciSerialParameter
->Offset
;
480 if (PciSerialParameter
->RegisterStride
!= 0) {
481 SerialDevice
->RegisterStride
= PciSerialParameter
->RegisterStride
;
484 if (PciSerialParameter
->ClockRate
!= 0) {
485 SerialDevice
->ClockRate
= PciSerialParameter
->ClockRate
;
488 if (PciSerialParameter
->ReceiveFifoDepth
!= 0) {
489 SerialDevice
->ReceiveFifoDepth
= PciSerialParameter
->ReceiveFifoDepth
;
492 if (PciSerialParameter
->TransmitFifoDepth
!= 0) {
493 SerialDevice
->TransmitFifoDepth
= PciSerialParameter
->TransmitFifoDepth
;
498 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
499 // DriverBindingStart() shouldn't create a handle with different UART device path.
501 if (!VerifyUartParameters (
502 SerialDevice
->ClockRate
,
503 SerialDevice
->UartDevicePath
.BaudRate
,
504 SerialDevice
->UartDevicePath
.DataBits
,
505 SerialDevice
->UartDevicePath
.Parity
,
506 SerialDevice
->UartDevicePath
.StopBits
,
511 Status
= EFI_INVALID_PARAMETER
;
515 if (PciSerialParameter
== NULL
) {
516 Status
= ParentIo
.Sio
->GetResources (ParentIo
.Sio
, &Resources
);
518 Status
= ParentIo
.PciIo
->GetBarAttributes (ParentIo
.PciIo
, BarIndex
, NULL
, (VOID
**)&Resources
);
521 if (!EFI_ERROR (Status
)) {
523 // Get the base address information from ACPI resource descriptor.
524 // ACPI_IO_PORT_DESCRIPTOR and ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR are returned from Sio;
525 // ACPI_ADDRESS_SPACE_DESCRIPTOR is returned from PciIo.
527 while ((Resources
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) && (SerialDevice
->BaseAddress
== 0)) {
528 switch (Resources
.SmallHeader
->Byte
) {
529 case ACPI_IO_PORT_DESCRIPTOR
:
530 Io
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*)Resources
.SmallHeader
;
531 if (Io
->Length
!= 0) {
532 SerialDevice
->BaseAddress
= Io
->BaseAddressMin
;
537 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
538 FixedIo
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*)Resources
.SmallHeader
;
539 if (FixedIo
->Length
!= 0) {
540 SerialDevice
->BaseAddress
= FixedIo
->BaseAddress
;
545 case ACPI_ADDRESS_SPACE_DESCRIPTOR
:
546 AddressSpace
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Resources
.SmallHeader
;
547 if (AddressSpace
->AddrLen
!= 0) {
548 if (AddressSpace
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
549 SerialDevice
->MmioAccess
= TRUE
;
552 SerialDevice
->BaseAddress
= AddressSpace
->AddrRangeMin
+ Offset
;
558 if (Resources
.SmallHeader
->Bits
.Type
== 0) {
559 Resources
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*)((UINT8
*)Resources
.SmallHeader
560 + Resources
.SmallHeader
->Bits
.Length
561 + sizeof (*Resources
.SmallHeader
));
563 Resources
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*)((UINT8
*)Resources
.LargeHeader
564 + Resources
.LargeHeader
->Length
565 + sizeof (*Resources
.LargeHeader
));
570 if (SerialDevice
->BaseAddress
== 0) {
571 Status
= EFI_INVALID_PARAMETER
;
575 SerialDevice
->HardwareFlowControl
= (BOOLEAN
)(FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
578 // Report status code the serial present
580 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
582 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
583 SerialDevice
->ParentDevicePath
586 if (!SerialPresent (SerialDevice
)) {
587 Status
= EFI_DEVICE_ERROR
;
588 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
590 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
591 SerialDevice
->ParentDevicePath
597 // 1. Append Controller device path node.
599 if (CreateControllerNode
) {
600 mControllerDevicePathTemplate
.ControllerNumber
= SerialDevice
->Instance
;
601 SerialDevice
->DevicePath
= AppendDevicePathNode (
602 SerialDevice
->ParentDevicePath
,
603 (EFI_DEVICE_PATH_PROTOCOL
*)&mControllerDevicePathTemplate
605 SerialDevice
->ContainsControllerNode
= TRUE
;
609 // 2. Append UART device path node.
610 // The Uart setings are zero here.
611 // SetAttribute() will update them to match the default setings.
613 TempDevicePath
= SerialDevice
->DevicePath
;
614 if (TempDevicePath
!= NULL
) {
615 SerialDevice
->DevicePath
= AppendDevicePathNode (
617 (EFI_DEVICE_PATH_PROTOCOL
*)&SerialDevice
->UartDevicePath
619 FreePool (TempDevicePath
);
621 SerialDevice
->DevicePath
= AppendDevicePathNode (
622 SerialDevice
->ParentDevicePath
,
623 (EFI_DEVICE_PATH_PROTOCOL
*)&SerialDevice
->UartDevicePath
628 // 3. Append the Flow Control device path node.
629 // Only produce the Flow Control node when remaining device path has it
631 if (FlowControl
!= NULL
) {
632 TempDevicePath
= SerialDevice
->DevicePath
;
633 if (TempDevicePath
!= NULL
) {
634 SerialDevice
->DevicePath
= AppendDevicePathNode (
636 (EFI_DEVICE_PATH_PROTOCOL
*)FlowControl
638 FreePool (TempDevicePath
);
642 ASSERT (SerialDevice
->DevicePath
!= NULL
);
645 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
647 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
648 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
649 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
650 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
653 // Issue a reset to initialize the COM port
655 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
656 if (EFI_ERROR (Status
)) {
657 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
659 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
660 SerialDevice
->DevicePath
665 AddName (SerialDevice
, Instance
);
667 // Install protocol interfaces for the serial device.
669 Status
= gBS
->InstallMultipleProtocolInterfaces (
670 &SerialDevice
->Handle
,
671 &gEfiDevicePathProtocolGuid
,
672 SerialDevice
->DevicePath
,
673 &gEfiSerialIoProtocolGuid
,
674 &SerialDevice
->SerialIo
,
677 if (EFI_ERROR (Status
)) {
682 // Open For Child Device
684 Status
= gBS
->OpenProtocol (
686 PciSerialParameter
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
688 gSerialControllerDriver
.DriverBindingHandle
,
689 SerialDevice
->Handle
,
690 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
693 if (EFI_ERROR (Status
)) {
694 gBS
->UninstallMultipleProtocolInterfaces (
695 SerialDevice
->Handle
,
696 &gEfiDevicePathProtocolGuid
,
697 SerialDevice
->DevicePath
,
698 &gEfiSerialIoProtocolGuid
,
699 &SerialDevice
->SerialIo
,
705 if (EFI_ERROR (Status
)) {
706 if (SerialDevice
->DevicePath
!= NULL
) {
707 FreePool (SerialDevice
->DevicePath
);
710 if (SerialDevice
->ControllerNameTable
!= NULL
) {
711 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
714 FreePool (SerialDevice
);
721 Returns an array of pointers containing all the child serial device pointers.
723 @param Controller The parent controller handle.
724 @param IoProtocolGuid The protocol GUID, either equals to gEfiSioProtocolGuid
725 or equals to gEfiPciIoProtocolGuid.
726 @param Count Count of the serial devices.
728 @return An array of pointers containing all the child serial device pointers.
731 GetChildSerialDevices (
732 IN EFI_HANDLE Controller
,
733 IN EFI_GUID
*IoProtocolGuid
,
739 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
741 SERIAL_DEV
**SerialDevices
;
742 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
743 BOOLEAN OpenByDriver
;
747 // If the SerialIo instance specified by RemainingDevicePath is already created,
748 // update the attributes/control.
750 Status
= gBS
->OpenProtocolInformation (
756 if (EFI_ERROR (Status
)) {
760 SerialDevices
= AllocatePool (EntryCount
* sizeof (SERIAL_DEV
*));
761 ASSERT (SerialDevices
!= NULL
);
764 OpenByDriver
= FALSE
;
765 for (Index
= 0; Index
< EntryCount
; Index
++) {
766 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
767 Status
= gBS
->OpenProtocol (
768 OpenInfoBuffer
[Index
].ControllerHandle
,
769 &gEfiSerialIoProtocolGuid
,
771 gSerialControllerDriver
.DriverBindingHandle
,
773 EFI_OPEN_PROTOCOL_GET_PROTOCOL
775 if (!EFI_ERROR (Status
)) {
776 SerialDevices
[(*Count
)++] = SERIAL_DEV_FROM_THIS (SerialIo
);
780 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
781 ASSERT (OpenInfoBuffer
[Index
].AgentHandle
== gSerialControllerDriver
.DriverBindingHandle
);
786 if (OpenInfoBuffer
!= NULL
) {
787 FreePool (OpenInfoBuffer
);
790 ASSERT ((*Count
== 0) || (OpenByDriver
));
792 return SerialDevices
;
796 Start to management the controller passed in
798 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
799 @param Controller The handle of the controller to test.
800 @param RemainingDevicePath A pointer to the remaining portion of a device path.
802 @return EFI_SUCCESS Driver is started successfully
806 SerialControllerDriverStart (
807 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
808 IN EFI_HANDLE Controller
,
809 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
814 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
815 EFI_DEVICE_PATH_PROTOCOL
*Node
;
816 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
817 UINT32 ControllerNumber
;
818 UART_DEVICE_PATH
*Uart
;
819 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
821 PARENT_IO_PROTOCOL_PTR ParentIo
;
822 ACPI_HID_DEVICE_PATH
*Acpi
;
823 EFI_GUID
*IoProtocolGuid
;
824 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
825 PCI_SERIAL_PARAMETER DefaultPciSerialParameter
;
827 UINT32 PciSerialCount
;
828 SERIAL_DEV
**SerialDevices
;
829 UINTN SerialDeviceCount
;
830 PCI_DEVICE_INFO
*PciDeviceInfo
;
832 BOOLEAN ContainsControllerNode
;
835 // Get the Parent Device Path
837 Status
= gBS
->OpenProtocol (
839 &gEfiDevicePathProtocolGuid
,
840 (VOID
**)&ParentDevicePath
,
841 This
->DriverBindingHandle
,
843 EFI_OPEN_PROTOCOL_BY_DRIVER
845 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
850 // Report status code enable the serial
852 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
854 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
859 // Grab the IO abstraction we need to get any work done
861 IoProtocolGuid
= &gEfiSioProtocolGuid
;
862 Status
= gBS
->OpenProtocol (
866 This
->DriverBindingHandle
,
868 EFI_OPEN_PROTOCOL_BY_DRIVER
870 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
871 IoProtocolGuid
= &gEfiPciIoProtocolGuid
;
872 Status
= gBS
->OpenProtocol (
876 This
->DriverBindingHandle
,
878 EFI_OPEN_PROTOCOL_BY_DRIVER
882 ASSERT (!EFI_ERROR (Status
) || Status
== EFI_ALREADY_STARTED
);
885 // Do nothing for END device path node
887 if ((RemainingDevicePath
!= NULL
) && IsDevicePathEnd (RemainingDevicePath
)) {
891 ControllerNumber
= 0;
892 ContainsControllerNode
= FALSE
;
893 SerialDevices
= GetChildSerialDevices (Controller
, IoProtocolGuid
, &SerialDeviceCount
);
895 if (SerialDeviceCount
!= 0) {
896 if (RemainingDevicePath
== NULL
) {
898 // If the SerialIo instance is already created, NULL as RemainingDevicePath is treated
899 // as to create the same SerialIo instance.
904 // Update the attributes/control of the SerialIo instance specified by RemainingDevicePath.
906 Uart
= (UART_DEVICE_PATH
*)SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
907 for (Index
= 0; Index
< SerialDeviceCount
; Index
++) {
908 ASSERT ((SerialDevices
!= NULL
) && (SerialDevices
[Index
] != NULL
));
909 if ((!SerialDevices
[Index
]->ContainsControllerNode
&& !ContainsControllerNode
) ||
910 (SerialDevices
[Index
]->ContainsControllerNode
&& ContainsControllerNode
&& (SerialDevices
[Index
]->Instance
== ControllerNumber
))
913 SerialIo
= &SerialDevices
[Index
]->SerialIo
;
914 Status
= EFI_INVALID_PARAMETER
;
916 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
917 // DriverBindingStart() shouldn't create a handle with different UART device path.
919 if (VerifyUartParameters (
920 SerialDevices
[Index
]->ClockRate
,
923 (EFI_PARITY_TYPE
)Uart
->Parity
,
924 (EFI_STOP_BITS_TYPE
)Uart
->StopBits
,
929 Status
= SerialIo
->SetAttributes (
932 SerialIo
->Mode
->ReceiveFifoDepth
,
933 SerialIo
->Mode
->Timeout
,
934 (EFI_PARITY_TYPE
)Uart
->Parity
,
936 (EFI_STOP_BITS_TYPE
)Uart
->StopBits
940 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*)NextDevicePathNode (Uart
);
941 if (!EFI_ERROR (Status
) && IsUartFlowControlDevicePathNode (FlowControl
)) {
942 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
943 if (!EFI_ERROR (Status
)) {
944 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
945 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
947 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
951 // Clear the bits that are not allowed to pass to SetControl
953 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
954 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
955 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
956 Status
= SerialIo
->SetControl (SerialIo
, Control
);
964 if (Index
!= SerialDeviceCount
) {
966 // Directly return if the SerialIo instance specified by RemainingDevicePath is found and updated.
967 // Otherwise continue to create the instance specified by RemainingDevicePath.
969 if (SerialDevices
!= NULL
) {
970 FreePool (SerialDevices
);
978 if (RemainingDevicePath
!= NULL
) {
979 Uart
= (UART_DEVICE_PATH
*)SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
984 PciDeviceInfo
= NULL
;
985 if (IoProtocolGuid
== &gEfiSioProtocolGuid
) {
986 Status
= EFI_NOT_FOUND
;
987 if ((RemainingDevicePath
== NULL
) || !ContainsControllerNode
) {
988 Node
= ParentDevicePath
;
990 Acpi
= (ACPI_HID_DEVICE_PATH
*)Node
;
991 Node
= NextDevicePathNode (Node
);
992 } while (!IsDevicePathEnd (Node
));
994 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, Acpi
->UID
, ParentIo
, NULL
, NULL
);
995 DEBUG ((DEBUG_INFO
, "PciSioSerial: Create SIO child serial device - %r\n", Status
));
998 Status
= ParentIo
.PciIo
->Pci
.Read (ParentIo
.PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
999 if (!EFI_ERROR (Status
)) {
1001 // PcdPciSerialParameters takes the higher priority.
1004 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
1005 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
1006 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
)
1013 if (SerialDeviceCount
== 0) {
1015 // Enable the IO & MEM decoding when creating the first child.
1016 // Restore the PCI attributes when all children is destroyed (PciDeviceInfo->ChildCount == 0).
1018 PciDeviceInfo
= AllocatePool (sizeof (PCI_DEVICE_INFO
));
1019 ASSERT (PciDeviceInfo
!= NULL
);
1020 PciDeviceInfo
->ChildCount
= 0;
1021 PciDeviceInfo
->PciIo
= ParentIo
.PciIo
;
1022 Status
= ParentIo
.PciIo
->Attributes (
1024 EfiPciIoAttributeOperationGet
,
1026 &PciDeviceInfo
->PciAttributes
1029 if (!EFI_ERROR (Status
)) {
1030 Status
= ParentIo
.PciIo
->Attributes (
1032 EfiPciIoAttributeOperationSupported
,
1036 if (!EFI_ERROR (Status
)) {
1037 Supports
&= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
);
1038 Status
= ParentIo
.PciIo
->Attributes (
1040 EfiPciIoAttributeOperationEnable
,
1048 // Re-use the PciDeviceInfo stored in existing children.
1050 ASSERT ((SerialDevices
!= NULL
) && (SerialDevices
[0] != NULL
));
1051 PciDeviceInfo
= SerialDevices
[0]->PciDeviceInfo
;
1052 ASSERT (PciDeviceInfo
!= NULL
);
1055 Status
= EFI_NOT_FOUND
;
1056 if (PciSerialCount
<= 1) {
1058 // PCI serial device contains only one UART
1060 if ((RemainingDevicePath
== NULL
) || !ContainsControllerNode
) {
1062 // This PCI serial device is matched by class code in Supported()
1064 if (PciSerialCount
== 0) {
1065 DefaultPciSerialParameter
.VendorId
= Pci
.Hdr
.VendorId
;
1066 DefaultPciSerialParameter
.DeviceId
= Pci
.Hdr
.DeviceId
;
1067 DefaultPciSerialParameter
.BarIndex
= 0;
1068 DefaultPciSerialParameter
.Offset
= 0;
1069 DefaultPciSerialParameter
.RegisterStride
= 0;
1070 DefaultPciSerialParameter
.ClockRate
= 0;
1071 PciSerialParameter
= &DefaultPciSerialParameter
;
1072 } else if (PciSerialCount
== 1) {
1073 PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
);
1076 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, 0, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1077 DEBUG ((DEBUG_INFO
, "PciSioSerial: Create PCI child serial device (single) - %r\n", Status
));
1078 if (!EFI_ERROR (Status
)) {
1079 PciDeviceInfo
->ChildCount
++;
1084 // PCI serial device contains multiple UARTs
1086 if ((RemainingDevicePath
== NULL
) || ContainsControllerNode
) {
1088 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
1089 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
1090 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
) &&
1091 ((RemainingDevicePath
== NULL
) || (ControllerNumber
== PciSerialCount
))
1095 // Create controller node when PCI serial device contains multiple UARTs
1097 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, TRUE
, PciSerialCount
, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1099 DEBUG ((DEBUG_INFO
, "PciSioSerial: Create PCI child serial device (multiple) - %r\n", Status
));
1100 if (!EFI_ERROR (Status
)) {
1101 PciDeviceInfo
->ChildCount
++;
1110 if (SerialDevices
!= NULL
) {
1111 FreePool (SerialDevices
);
1115 // For multiple PCI serial devices, set Status to SUCCESS if one child is created successfully
1117 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
!= 0)) {
1118 Status
= EFI_SUCCESS
;
1121 if (EFI_ERROR (Status
) && (SerialDeviceCount
== 0)) {
1122 if (PciDeviceInfo
!= NULL
) {
1123 Status
= ParentIo
.PciIo
->Attributes (
1125 EfiPciIoAttributeOperationSet
,
1126 PciDeviceInfo
->PciAttributes
,
1129 ASSERT_EFI_ERROR (Status
);
1130 FreePool (PciDeviceInfo
);
1133 gBS
->CloseProtocol (
1135 &gEfiDevicePathProtocolGuid
,
1136 This
->DriverBindingHandle
,
1139 gBS
->CloseProtocol (
1142 This
->DriverBindingHandle
,
1151 Disconnect this driver with the controller, uninstall related protocol instance
1153 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1154 @param Controller The handle of the controller to test.
1155 @param NumberOfChildren Number of child device.
1156 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
1158 @retval EFI_SUCCESS Operation successfully
1159 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
1164 SerialControllerDriverStop (
1165 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1166 IN EFI_HANDLE Controller
,
1167 IN UINTN NumberOfChildren
,
1168 IN EFI_HANDLE
*ChildHandleBuffer
1174 BOOLEAN AllChildrenStopped
;
1175 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1176 SERIAL_DEV
*SerialDevice
;
1178 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1179 PCI_DEVICE_INFO
*PciDeviceInfo
;
1181 PciDeviceInfo
= NULL
;
1183 Status
= gBS
->HandleProtocol (
1185 &gEfiDevicePathProtocolGuid
,
1186 (VOID
**)&DevicePath
1190 // Report the status code disable the serial
1192 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1194 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
1198 if (NumberOfChildren
== 0) {
1200 // Close the bus driver
1202 Status
= gBS
->OpenProtocol (
1204 &gEfiPciIoProtocolGuid
,
1206 This
->DriverBindingHandle
,
1208 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1210 gBS
->CloseProtocol (
1212 !EFI_ERROR (Status
) ? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1213 This
->DriverBindingHandle
,
1217 gBS
->CloseProtocol (
1219 &gEfiDevicePathProtocolGuid
,
1220 This
->DriverBindingHandle
,
1226 AllChildrenStopped
= TRUE
;
1228 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1229 Status
= gBS
->OpenProtocol (
1230 ChildHandleBuffer
[Index
],
1231 &gEfiSerialIoProtocolGuid
,
1233 This
->DriverBindingHandle
,
1235 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1237 if (!EFI_ERROR (Status
)) {
1238 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
1239 ASSERT ((PciDeviceInfo
== NULL
) || (PciDeviceInfo
== SerialDevice
->PciDeviceInfo
));
1240 PciDeviceInfo
= SerialDevice
->PciDeviceInfo
;
1242 Status
= gBS
->CloseProtocol (
1244 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1245 This
->DriverBindingHandle
,
1246 ChildHandleBuffer
[Index
]
1249 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1250 ChildHandleBuffer
[Index
],
1251 &gEfiDevicePathProtocolGuid
,
1252 SerialDevice
->DevicePath
,
1253 &gEfiSerialIoProtocolGuid
,
1254 &SerialDevice
->SerialIo
,
1257 if (EFI_ERROR (Status
)) {
1260 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1262 This
->DriverBindingHandle
,
1263 ChildHandleBuffer
[Index
],
1264 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1267 FreePool (SerialDevice
->DevicePath
);
1268 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
1269 FreePool (SerialDevice
);
1271 if (PciDeviceInfo
!= NULL
) {
1272 ASSERT (PciDeviceInfo
->ChildCount
!= 0);
1273 PciDeviceInfo
->ChildCount
--;
1278 if (EFI_ERROR (Status
)) {
1279 AllChildrenStopped
= FALSE
;
1283 if (!AllChildrenStopped
) {
1284 return EFI_DEVICE_ERROR
;
1287 // If all children are destroyed, restore the PCI attributes.
1289 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
== 0)) {
1290 ASSERT (PciDeviceInfo
->PciIo
!= NULL
);
1291 Status
= PciDeviceInfo
->PciIo
->Attributes (
1292 PciDeviceInfo
->PciIo
,
1293 EfiPciIoAttributeOperationSet
,
1294 PciDeviceInfo
->PciAttributes
,
1297 ASSERT_EFI_ERROR (Status
);
1298 FreePool (PciDeviceInfo
);