3.15.7 ConOut

As with ConIn, firmware connects the ConOut devices using the device paths in the ConOut global UEFI variable. If ConIn was not complicated enough, the ConOut global UEFI device path in this example is a compound device path and indicates that the ConOut device is being mirrored with the console splitter driver to two separate devices.

  ConOut = Acpi(HWP0002,0,PNP0A03)/Pci(1|1)/Uart(9600 N81)/VenMsg(Vt100+);Acpi(HWP0002,0,PNP0A03)/Pci(4|0)

The UEFI connection process searches the handle database for a device path that matches the first device path in the ConOut variable:

Acpi(HWP0002,0,PNP0A03)/Pci(1|1)/Uart(9600 N81)/VenMsg(Vt100+)`

Luckily, the device path already exists on handle 3C in its entirety thanks to the connection work done for ConIn.

  3C: Txtin Txtout ConIn ConOut StdErr DevPath
  (Acpi(HWP0002,0,PNP0A03)/Pci(1|1)/Uart(9600 N81)/VenMsg(Vt100+))

UEFI performs a ConnectController() on handle 3C. Because this step was previously done with ConIn, there is nothing more to be done here.

The connection process has not yet been completed for ConOut because the device path is a compound device path and a second device needs to be connected:

  Acpi(HWP0002,0,PNP0A03)/Pci(4|0)

The UEFI connection process searches the handle database for a device path that matches Acpi(HWP0002,0,PNP0A03)/Pci(4|0). The device path already exists in its entirety on handle 1C and was created by the PCI bus driver when it started and exposed the PCI devices.

  1C: PciIo DevPath (Acpi(HWP0002,0,PNP0A03)/Pci(4|0))

UEFI now performs a ConnectController() on handle 1C. Note that the device path is a complete match, so there is no remaining device path to pass in this time. ConnectController() constructs the prioritized list of drivers in the system and calls the Supported() service for each one, passing in the device handle 1C. The only driver that returns EFI_SUCCESS is the GraphicsOutput driver.

  2E: Image(CirrusLogic5430Dxe) Driver Binding ComponentName2 ComponentName

ConnectController() calls this driver's Start() function and Start() consumes the device's EFI_PCI_IO_PROTOCOL and installs the EFI_GRAPHICS_OUTPUT_PROTOCOL onto the device handle 1C.

  1C: PciIo GraphicsOutput DevPath (Acpi(HWP0002,0,PNP0A03)/ Pci(4|0))

ConnectController() continues to process its list of drivers and finds that the GraphicsConsole driver's Supported() service returns EFI_SUCCESS.

  2D: Image(GraphicsConsoleDxe) DriverBinding ComponentName2 ComponentName

Next, the graphics console driver's Start() service consumes the EFI_GRAPHICS_OUTPUT_PROTOCOL and produces the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on the same device handle 1C.

  1C: Txtout PciIo GraphicsOutput DevPath (Acpi(HWP0002,0,PNP0A03)/
Pci(4|0))

ConnectController() continues to process its list of drivers, now searching for a driver that supports this controller, and finds two driver handles that return EFI_SUCCESS from their Supported() services. These two driver handles are from the platform console management driver:

  32: Image(ConPlatformDxe) DriverBinding ComponentName2 ComponentName

Driver handle 32 installs a ConOut Tag GUID on the handle if the device path is listed in the ConOut global UEFI variable. In this example, the case is true. Driver 32 also installs a StdErr Tag GUID on the handle if the device path is listed in the ErrOut global UEFI variable. This case is also true in the example. Therefore, handle 1C has two new protocols on it: ConOut and StdErr.

  1C: Txtout PciIo ConOut StdErr DevPath (Acpi(HWP0002,0,PNP0A03)/Pci(4|0))

These two protocols (ConOut and StdErr) are used to mark devices in the system that have been user-selected as ConOut and StdErr. These protocols are actually just Tag GUID without any functions or data.

There are two other driver handles that return EFI_SUCCESS to the Supported() service. These driver handles are from the console splitter driver for the ConOut and StdErr devices in the system.

  36: DriverBindingComponentName
  37: DriverBindingComponentName

Remember that when the console splitter driver was first loaded, it created three virtual handles.

  38: TxtinEx TxtIn SimplePointer AbsolutePointer
  39: Txtout GraphicsOutput UgaDraw
  3A: Txtout

The console splitter driver's Supported() service for driver handle 36 examines the handle 1C for a ConOut Protocol. Having found it, EFI_SUCCESS is returned. The Start() service then opens the ConOut protocol on device handle 1C such that the device handle 39 becomes a child controller and starts aggregating the SIMPLE_TEXT_OUTPUT_PROTOCOL services.

The same thing happens for driver handle 37 with StdErr; the SIMPLE_TEXT_OUTPUT_PROTOCOL functionality on device handle 1C is aggregated into the SIMPLE_TEXT_OUTPUT_PROTOCOL on device handle 3A.