示例#1
0
文件: IsaFloppy.c 项目: Kohrara/edk
EFI_STATUS
EFIAPI
FdcControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
/*++

Routine Description:

  ControllerDriver Protocol Method

Arguments:

Returns:

--*/
// GC_TODO:    This - add argument and description to function comment
// GC_TODO:    Controller - add argument and description to function comment
// GC_TODO:    RemainingDevicePath - add argument and description to function comment
{
  EFI_STATUS                          Status;
  EFI_INTERFACE_DEFINITION_FOR_ISA_IO *IsaIo;

  //
  // Open the ISA I/O Protocol
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  EFI_ISA_IO_PROTOCOL_VERSION,
                  (VOID **) &IsaIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Use the ISA I/O Protocol to see if Controller is a Floppy Disk Controller
  //
  Status = EFI_SUCCESS;
  if ((IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) && (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x700))) {
    Status = EFI_UNSUPPORTED;
  }
  //
  // Close the ISA I/O Protocol
  //
  gBS->CloseProtocol (
         Controller,
         EFI_ISA_IO_PROTOCOL_VERSION,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
示例#2
0
文件: Ps2Keyboard.c 项目: Kohrara/edk
EFI_STATUS
EFIAPI
KbdControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
/*++

Routine Description:

  ControllerDriver Protocol Method

Arguments:

Returns:

--*/
// GC_TODO:    This - add argument and description to function comment
// GC_TODO:    Controller - add argument and description to function comment
// GC_TODO:    RemainingDevicePath - add argument and description to function comment
{
  EFI_STATUS                          Status;
  EFI_INTERFACE_DEFINITION_FOR_ISA_IO *IsaIo;

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  EFI_ISA_IO_PROTOCOL_VERSION,
                  (VOID **) &IsaIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
  //
  if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
    Status = EFI_UNSUPPORTED;
  }
  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
  gBS->CloseProtocol (
         Controller,
         EFI_ISA_IO_PROTOCOL_VERSION,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
示例#3
0
/**
  Check whether the device path node is ISA Serial Node.

  @param Acpi           Device path node to be checked

  @retval TRUE          It's ISA Serial Node.
  @retval FALSE         It's NOT ISA Serial Node.

**/
BOOLEAN
IsIsaSerialNode (
  IN ACPI_HID_DEVICE_PATH *Acpi
  )
{
  return (BOOLEAN) (
      (DevicePathType (Acpi) == ACPI_DEVICE_PATH) &&
      (DevicePathSubType (Acpi) == ACPI_DP) &&
      (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501))
      );
}
示例#4
0
BOOLEAN
RetrieveUartUid (
    IN EFI_HANDLE   Handle,
    IN OUT UINT32   *AcpiUid
)
/*++

Routine Description:
  Retrieve ACPI UID of UART from device path

Arguments:
  Handles   -   EFI_SERIAL_IO_PROTOCOL handle

Returns:
  TRUE  - Find valid UID from device path
  FALSE - Can't find

--*/
{
    UINT32                    Match;
    UINT8                     *Ptr;
    ACPI_HID_DEVICE_PATH      *Acpi;
    EFI_DEVICE_PATH_PROTOCOL  *DevicePath;

    gBS->HandleProtocol (
        Handle,
        &gEfiDevicePathProtocolGuid,
        &DevicePath
    );
    Ptr = (UINT8 *) DevicePath;

    while (*Ptr != END_DEVICE_PATH_TYPE) {
        Ptr++;
    }

    Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
    Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;
    Match = EISA_PNP_ID (0x0501);

    if (EfiCompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
        if (AcpiUid != NULL) {
            *AcpiUid = Acpi->UID;
        }
        return TRUE;
    } else {
        return FALSE;
    }
}
示例#5
0
/**
  Test controller is a keyboard Controller.
  
  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
  @param Controller           driver's controller
  @param RemainingDevicePath  children device path
  
  @retval EFI_UNSUPPORTED controller is not floppy disk
  @retval EFI_SUCCESS     controller is floppy disk
**/
EFI_STATUS
EFIAPI
KbdControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                          Status;
  EFI_ISA_IO_PROTOCOL                 *IsaIo;

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiIsaIoProtocolGuid,
                  (VOID **) &IsaIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
  //
  if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
    Status = EFI_UNSUPPORTED;
  }
  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
  gBS->CloseProtocol (
         Controller,
         &gEfiIsaIoProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
示例#6
0
EFI_STATUS
UpdateComAttributeFromVariable (
    EFI_DEVICE_PATH_PROTOCOL  *DevicePath
)
/*++

Routine Description:
  Update Com Ports attributes from DevicePath

Arguments:
  DevicePath  -   DevicePath that contains Com ports

Returns:

--*/
{
    EFI_DEVICE_PATH_PROTOCOL  *Node;
    EFI_DEVICE_PATH_PROTOCOL  *SerialNode;
    ACPI_HID_DEVICE_PATH      *Acpi;
    UART_DEVICE_PATH          *Uart;
    UART_DEVICE_PATH          *Uart1;
    UINT32                    Match;
    UINTN                     TerminalNumber;
    BM_MENU_ENTRY             *NewMenuEntry;
    BM_TERMINAL_CONTEXT       *NewTerminalContext;
    UINTN                     Index;

    Match           = EISA_PNP_ID (0x0501);
    Node            = DevicePath;
    Node            = NextDevicePathNode (Node);
    TerminalNumber  = 0;
    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
        while (!IsDevicePathEnd (Node)) {
            if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
                Acpi = (ACPI_HID_DEVICE_PATH *) Node;
                if (EfiCompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
                    EfiCopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32));
                }
            }

            if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
                Uart          = (UART_DEVICE_PATH *) Node;
                NewMenuEntry  = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber);
                if (NULL == NewMenuEntry) {
                    return EFI_NOT_FOUND;
                }

                NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
                EfiCopyMem (
                    &NewTerminalContext->BaudRate,
                    &Uart->BaudRate,
                    sizeof (UINT64)
                );

                EfiCopyMem (
                    &NewTerminalContext->DataBits,
                    &Uart->DataBits,
                    sizeof (UINT8)
                );

                EfiCopyMem (
                    &NewTerminalContext->Parity,
                    &Uart->Parity,
                    sizeof (UINT8)
                );

                EfiCopyMem (
                    &NewTerminalContext->StopBits,
                    &Uart->StopBits,
                    sizeof (UINT8)
                );

                SerialNode  = NewTerminalContext->DevicePath;
                SerialNode  = NextDevicePathNode (SerialNode);
                while (!IsDevicePathEnd (SerialNode)) {
                    if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) {
                        //
                        // Update following device paths according to
                        // previous acquired uart attributes
                        //
                        Uart1 = (UART_DEVICE_PATH *) SerialNode;
                        EfiCopyMem (
                            &Uart1->BaudRate,
                            &NewTerminalContext->BaudRate,
                            sizeof (UINT64)
                        );

                        EfiCopyMem (
                            &Uart1->DataBits,
                            &NewTerminalContext->DataBits,
                            sizeof (UINT8)
                        );
                        EfiCopyMem (
                            &Uart1->Parity,
                            &NewTerminalContext->Parity,
                            sizeof (UINT8)
                        );
                        EfiCopyMem (
                            &Uart1->StopBits,
                            &NewTerminalContext->StopBits,
                            sizeof (UINT8)
                        );

                        break;
                    }

                    SerialNode = NextDevicePathNode (SerialNode);
                }
                //
                // end while
                //
            }

            Node = NextDevicePathNode (Node);
        }
        //
        // end while
        //
    }

    return EFI_SUCCESS;
}
示例#7
0
BOOLEAN
IsTerminalDevicePath (
    IN  EFI_DEVICE_PATH_PROTOCOL *DevicePath,
    OUT TYPE_OF_TERMINAL         *Termi,
    OUT UINTN                    *Com
)
/*++

Routine Description:
  Test whether DevicePath is a valid Terminal

Arguments:
  DevicePath  -   DevicePath to be checked
  Termi       -   If is terminal, give its type
  Com         -   If is Com Port, give its type

Returns:
  TRUE        -   If DevicePath point to a Terminal
  FALSE

--*/
{
    UINT8                 *Ptr;
    BOOLEAN               IsTerminal;
    VENDOR_DEVICE_PATH    *Vendor;
    ACPI_HID_DEVICE_PATH  *Acpi;
    UINT32                Match;
    EFI_GUID              TempGuid;

    IsTerminal = FALSE;

    //
    // Parse the Device Path, should be change later!!!
    //
    Ptr = (UINT8 *) DevicePath;
    while (*Ptr != END_DEVICE_PATH_TYPE) {
        Ptr++;
    }

    Ptr     = Ptr - sizeof (VENDOR_DEVICE_PATH);
    Vendor  = (VENDOR_DEVICE_PATH *) Ptr;

    //
    // There are four kinds of Terminal types
    // check to see whether this devicepath
    // is one of that type
    //
    EfiCopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID));

    if (EfiCompareGuid (&TempGuid, &Guid[0])) {
        *Termi      = PC_ANSI;
        IsTerminal  = TRUE;
    } else {
        if (EfiCompareGuid (&TempGuid, &Guid[1])) {
            *Termi      = VT_100;
            IsTerminal  = TRUE;
        } else {
            if (EfiCompareGuid (&TempGuid, &Guid[2])) {
                *Termi      = VT_100_PLUS;
                IsTerminal  = TRUE;
            } else {
                if (EfiCompareGuid (&TempGuid, &Guid[3])) {
                    *Termi      = VT_UTF8;
                    IsTerminal  = TRUE;
                } else {
                    IsTerminal = FALSE;
                }
            }
        }
    }

    if (!IsTerminal) {
        return FALSE;
    }

    Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
    Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;
    Match = EISA_PNP_ID (0x0501);
    if (EfiCompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
        EfiCopyMem (Com, &Acpi->UID, sizeof (UINT32));
    } else {
        return FALSE;
    }

    return TRUE;
}
示例#8
0
EFI_STATUS
LocateSerialIo (
    VOID
)
/*++

Routine Description:
  Build a list containing all serial devices

Arguments:

Returns:

--*/
{
    UINT8                     *Ptr;
    UINTN                     Index;
    UINTN                     Index2;
    UINTN                     NoHandles;
    EFI_HANDLE                *Handles;
    EFI_STATUS                Status;
    ACPI_HID_DEVICE_PATH      *Acpi;
    EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    UINT32                    Match;
    EFI_SERIAL_IO_PROTOCOL    *SerialIo;
    EFI_DEVICE_PATH_PROTOCOL  *OutDevicePath;
    EFI_DEVICE_PATH_PROTOCOL  *InpDevicePath;
    EFI_DEVICE_PATH_PROTOCOL  *ErrDevicePath;
    BM_MENU_ENTRY             *NewMenuEntry;
    BM_TERMINAL_CONTEXT       *NewTerminalContext;
    EFI_DEVICE_PATH_PROTOCOL  *NewDevicePath;
    VENDOR_DEVICE_PATH        Vendor;
    //
    // Get all handles that have SerialIo protocol installed
    //
    InitializeListHead (&TerminalMenu.Head);
    TerminalMenu.MenuNumber = 0;
    Status = gBS->LocateHandleBuffer (
                 ByProtocol,
                 &gEfiSerialIoProtocolGuid,
                 NULL,
                 &NoHandles,
                 &Handles
             );
    if (EFI_ERROR (Status)) {
        //
        // No serial ports present
        //
        return EFI_UNSUPPORTED;
    }

    //
    // Sort Uart handles array with Acpi->UID from low to high
    // then Terminal menu can be built from low Acpi->UID to high Acpi->UID
    //
    SortedUartHandle (Handles, NoHandles);

    for (Index = 0; Index < NoHandles; Index++) {
        //
        // Check to see whether the handle has DevicePath Protocol installed
        //
        gBS->HandleProtocol (
            Handles[Index],
            &gEfiDevicePathProtocolGuid,
            &DevicePath
        );
        Ptr = (UINT8 *) DevicePath;
        while (*Ptr != END_DEVICE_PATH_TYPE) {
            Ptr++;
        }

        Ptr   = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH);
        Acpi  = (ACPI_HID_DEVICE_PATH *) Ptr;
        Match = EISA_PNP_ID (0x0501);

        if (EfiCompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
            NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT);
            if (!NewMenuEntry) {
                SafeFreePool (Handles);
                return EFI_OUT_OF_RESOURCES;
            }

            NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
            EfiCopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32));
            NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath);
            //
            // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system!
            // coz' the misc data for each platform is not correct, actually it's the device path stored in
            // datahub which is not completed, so a searching for end of device path will enter a
            // dead-loop.
            //
            NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath);
            if (NULL == NewMenuEntry->DisplayString) {
                NewMenuEntry->DisplayString = DevicePathToStr (DevicePath);
            }

            NewMenuEntry->HelpString = NULL;

            gBS->HandleProtocol (
                Handles[Index],
                &gEfiSerialIoProtocolGuid,
                &SerialIo
            );

            EfiCopyMem (
                &NewTerminalContext->BaudRate,
                &SerialIo->Mode->BaudRate,
                sizeof (UINT64)
            );

            EfiCopyMem (
                &NewTerminalContext->DataBits,
                &SerialIo->Mode->DataBits,
                sizeof (UINT8)
            );

            EfiCopyMem (
                &NewTerminalContext->Parity,
                &SerialIo->Mode->Parity,
                sizeof (UINT8)
            );

            EfiCopyMem (
                &NewTerminalContext->StopBits,
                &SerialIo->Mode->StopBits,
                sizeof (UINT8)
            );
            InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link);
            TerminalMenu.MenuNumber++;
        }
    }
    SafeFreePool (Handles);

    //
    // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var
    //
    OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid);
    InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid);
    ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid);
    if (OutDevicePath) {
        UpdateComAttributeFromVariable (OutDevicePath);
    }

    if (InpDevicePath) {
        UpdateComAttributeFromVariable (InpDevicePath);
    }

    if (ErrDevicePath) {
        UpdateComAttributeFromVariable (ErrDevicePath);
    }

    for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
        NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
        if (NULL == NewMenuEntry) {
            return EFI_NOT_FOUND;
        }

        NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;

        NewTerminalContext->TerminalType  = 0;
        NewTerminalContext->IsConIn       = FALSE;
        NewTerminalContext->IsConOut      = FALSE;
        NewTerminalContext->IsStdErr      = FALSE;

        Vendor.Header.Type                = MESSAGING_DEVICE_PATH;
        Vendor.Header.SubType             = MSG_VENDOR_DP;

        for (Index2 = 0; Index2 < 4; Index2++) {
            EfiCopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID));
            SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH));
            NewDevicePath = EfiAppendDevicePathNode (
                                NewTerminalContext->DevicePath,
                                (EFI_DEVICE_PATH_PROTOCOL *) &Vendor
                            );
            SafeFreePool (NewMenuEntry->HelpString);
            //
            // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath);
            // NewMenuEntry->DisplayString = NewMenuEntry->HelpString;
            //
            NewMenuEntry->HelpString = NULL;

            if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) {
                NewTerminalContext->IsConOut      = TRUE;
                NewTerminalContext->TerminalType  = (UINT8) Index2;
            }

            if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) {
                NewTerminalContext->IsConIn       = TRUE;
                NewTerminalContext->TerminalType  = (UINT8) Index2;
            }

            if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) {
                NewTerminalContext->IsStdErr      = TRUE;
                NewTerminalContext->TerminalType  = (UINT8) Index2;
            }
        }
    }

    return EFI_SUCCESS;
}
示例#9
0
EFI_STATUS
ChangeTerminalDevicePath (
    EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
    BOOLEAN                   ChangeTerminal
)
{
    EFI_DEVICE_PATH_PROTOCOL  *Node;
    EFI_DEVICE_PATH_PROTOCOL  *Node1;
    ACPI_HID_DEVICE_PATH      *Acpi;
    UART_DEVICE_PATH          *Uart;
    UART_DEVICE_PATH          *Uart1;
    UINTN                     Com;
    UINT32                    Match;
    BM_TERMINAL_CONTEXT       *NewTerminalContext;
    BM_MENU_ENTRY             *NewMenuEntry;

    Match = EISA_PNP_ID (0x0501);
    Node  = DevicePath;
    Node  = NextDevicePathNode (Node);
    Com   = 0;
    while (!IsDevicePathEnd (Node)) {
        if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
            Acpi = (ACPI_HID_DEVICE_PATH *) Node;
            if (EfiCompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
                EfiCopyMem (&Com, &Acpi->UID, sizeof (UINT32));
            }
        }

        NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com);
        if (NULL == NewMenuEntry) {
            return EFI_NOT_FOUND;
        }

        NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
        if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
            Uart = (UART_DEVICE_PATH *) Node;
            EfiCopyMem (
                &Uart->BaudRate,
                &NewTerminalContext->BaudRate,
                sizeof (UINT64)
            );

            EfiCopyMem (
                &Uart->DataBits,
                &NewTerminalContext->DataBits,
                sizeof (UINT8)
            );

            EfiCopyMem (
                &Uart->Parity,
                &NewTerminalContext->Parity,
                sizeof (UINT8)
            );

            EfiCopyMem (
                &Uart->StopBits,
                &NewTerminalContext->StopBits,
                sizeof (UINT8)
            );
            //
            // Change the device path in the ComPort
            //
            if (ChangeTerminal) {
                Node1 = NewTerminalContext->DevicePath;
                Node1 = NextDevicePathNode (Node1);
                while (!IsDevicePathEnd (Node1)) {
                    if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) {
                        Uart1 = (UART_DEVICE_PATH *) Node1;
                        EfiCopyMem (
                            &Uart1->BaudRate,
                            &NewTerminalContext->BaudRate,
                            sizeof (UINT64)
                        );

                        EfiCopyMem (
                            &Uart1->DataBits,
                            &NewTerminalContext->DataBits,
                            sizeof (UINT8)
                        );

                        EfiCopyMem (
                            &Uart1->Parity,
                            &NewTerminalContext->Parity,
                            sizeof (UINT8)
                        );

                        EfiCopyMem (
                            &Uart1->StopBits,
                            &NewTerminalContext->StopBits,
                            sizeof (UINT8)
                        );
                        break;
                    }
                    //
                    // end if
                    //
                    Node1 = NextDevicePathNode (Node1);
                }
                //
                // end while
                //
                break;
            }
        }

        Node = NextDevicePathNode (Node);
    }

    return EFI_SUCCESS;

}
示例#10
0
VOID
ChangeVariableDevicePath (
    EFI_DEVICE_PATH_PROTOCOL  *DevicePath
)
{
    EFI_DEVICE_PATH_PROTOCOL  *Node;
    ACPI_HID_DEVICE_PATH      *Acpi;
    UART_DEVICE_PATH          *Uart;
    UINTN                     Com;
    UINT32                    Match;
    BM_TERMINAL_CONTEXT       *NewTerminalContext;
    BM_MENU_ENTRY             *NewMenuEntry;

    Match = EISA_PNP_ID (0x0501);
    Node  = DevicePath;
    Node  = NextDevicePathNode (Node);
    Com   = 0;
    while (!IsDevicePathEnd (Node)) {
        if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) {
            Acpi = (ACPI_HID_DEVICE_PATH *) Node;
            if (EfiCompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) {
                EfiCopyMem (&Com, &Acpi->UID, sizeof (UINT32));
            }
        }

        if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) {
            NewMenuEntry = BOpt_GetMenuEntry (
                               &TerminalMenu,
                               Com
                           );
            ASSERT (NewMenuEntry != NULL);
            NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
            Uart                = (UART_DEVICE_PATH *) Node;
            EfiCopyMem (
                &Uart->BaudRate,
                &NewTerminalContext->BaudRate,
                sizeof (UINT64)
            );

            EfiCopyMem (
                &Uart->DataBits,
                &NewTerminalContext->DataBits,
                sizeof (UINT8)
            );

            EfiCopyMem (
                &Uart->Parity,
                &NewTerminalContext->Parity,
                sizeof (UINT8)
            );

            EfiCopyMem (
                &Uart->StopBits,
                &NewTerminalContext->StopBits,
                sizeof (UINT8)
            );
        }

        Node = NextDevicePathNode (Node);
    }

    return ;
}
示例#11
0
/**
  Test controller is a keyboard Controller.

  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
  @param Controller           driver's controller
  @param RemainingDevicePath  children device path

  @retval EFI_UNSUPPORTED controller is not floppy disk
  @retval EFI_SUCCESS     controller is floppy disk
**/
EFI_STATUS
EFIAPI
KbdControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                                 Status;
  EFI_SIO_PROTOCOL                           *Sio;
  EFI_DEVICE_PATH_PROTOCOL                   *DevicePath;
  ACPI_HID_DEVICE_PATH                       *Acpi;

  //
  // Check whether the controller is keyboard.
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &DevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  do {
    Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
    DevicePath = NextDevicePathNode (DevicePath);
  } while (!IsDevicePathEnd (DevicePath));

  if (DevicePathType (Acpi) != ACPI_DEVICE_PATH ||
      (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != ACPI_EXTENDED_DP)) {
    return EFI_UNSUPPORTED;
  }

  if (Acpi->HID != EISA_PNP_ID (0x303) || Acpi->UID != 0) {
    return EFI_UNSUPPORTED;
  }

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiSioProtocolGuid,
                  (VOID **) &Sio,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
  gBS->CloseProtocol (
         Controller,
         &gEfiSioProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
示例#12
0
/**
  Checks the state of the floppy and if media is inserted.
  
  This routine checks the state of the floppy and if media is inserted.
  There are 3 cases:
  No floppy present         - Set BBS entry to ignore
  Floppy present & no media - Set BBS entry to lowest priority. We cannot
  set it to ignore since 16-bit CSM will
  indicate no floppy and thus drive A: is
  unusable. CSM-16 will not try floppy since
  lowest priority and thus not incur boot
  time penality.
  Floppy present & media    - Set BBS entry to some priority.

  @return  State of floppy media

**/
UINT8
HasMediaInFloppy (
  VOID
  )
{
  EFI_STATUS                            Status;
  UINTN                                 HandleCount;
  EFI_HANDLE                            *HandleBuffer;
  UINTN                                 Index;
  EFI_ISA_IO_PROTOCOL                   *IsaIo;
  EFI_BLOCK_IO_PROTOCOL                 *BlkIo;

  HandleBuffer  = NULL;
  HandleCount   = 0;

  gBS->LocateHandleBuffer (
        ByProtocol,
        &gEfiIsaIoProtocolGuid,
        NULL,
        &HandleCount,
        &HandleBuffer
        );

  //
  // If don't find any ISA/IO protocol assume no floppy. Need for floppy
  // free system
  //
  if (HandleCount == 0) {
    return FLOPPY_NOT_PRESENT;
  }

  ASSERT (HandleBuffer != NULL);

  for (Index = 0; Index < HandleCount; Index++) {
    Status = gBS->HandleProtocol (
                    HandleBuffer[Index],
                    &gEfiIsaIoProtocolGuid,
                    (VOID **) &IsaIo
                    );
    if (EFI_ERROR (Status)) {
      continue;
    }

    if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
      continue;
    }
    //
    // Update blockio in case the floppy is inserted in during BdsTimeout
    //
    Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);

    if (EFI_ERROR (Status)) {
      continue;
    }

    Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);

    if (EFI_ERROR (Status)) {
      continue;
    }

    Status = gBS->HandleProtocol (
                    HandleBuffer[Index],
                    &gEfiBlockIoProtocolGuid,
                    (VOID **) &BlkIo
                    );
    if (EFI_ERROR (Status)) {
      continue;
    }

    if (BlkIo->Media->MediaPresent) {
      FreePool (HandleBuffer);
      return FLOPPY_PRESENT_WITH_MEDIA;
    } else {
      FreePool (HandleBuffer);
      return FLOPPY_PRESENT_NO_MEDIA;
    }
  }

  FreePool (HandleBuffer);

  return FLOPPY_NOT_PRESENT;

}
示例#13
0
文件: Ps2Mouse.c 项目: M1cha/edk2
/**
  Test to see if this driver supports ControllerHandle. Any ControllerHandle
  than contains a IsaIo protocol can be supported.

  @param  This                Protocol instance pointer.
  @param  ControllerHandle    Handle of device to test
  @param  RemainingDevicePath Optional parameter use to pick a specific child
                              device to start.

  @retval EFI_SUCCESS         This driver supports this device
  @retval EFI_ALREADY_STARTED This driver is already running on this device
  @retval other               This driver does not support this device

**/
EFI_STATUS
EFIAPI
PS2MouseDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                        Status;
  EFI_SIO_PROTOCOL                  *Sio;
  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
  ACPI_HID_DEVICE_PATH              *Acpi;

  //
  // Check whether the controller is keyboard.
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &DevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  do {
    Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
    DevicePath = NextDevicePathNode (DevicePath);
  } while (!IsDevicePathEnd (DevicePath));

  if (DevicePathType (Acpi) != ACPI_DEVICE_PATH ||
      (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != ACPI_EXTENDED_DP)) {
    return EFI_UNSUPPORTED;
  }

  switch (Acpi->HID) {
  case EISA_PNP_ID (0xF03):
    //
    // Microsoft PS/2 style mouse
    //
  case EISA_PNP_ID (0xF13):
    //
    // PS/2 Port for PS/2-style Mice
    //
    break;

  case EISA_PNP_ID (0x303):
    //
    // IBM Enhanced (101/102-key, PS/2 mouse support)
    //
    if (Acpi->UID == 1) {
      break;
    }

  default:
    return EFI_UNSUPPORTED;
    break;
  }

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiSioProtocolGuid,
                  (VOID **) &Sio,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
  gBS->CloseProtocol (
         Controller,
         &gEfiSioProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
示例#14
0
  UINT32                  Signature;
  EFI_PCI_IO_DEVICE_PATH  DevicePath;
  EFI_PCI_IO_PROTOCOL     PciIoProtocol;
  PCI_TYPE00              *ConfigSpace;
  PCI_ROOT_BRIDGE         RootBridge;
  UINTN                   Segment;
} EFI_PCI_IO_PRIVATE_DATA;

#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE     SIGNATURE_32('p', 'c', 'i', 'o')
#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a)  CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)

EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate = 
{
  {
    { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0},
    EISA_PNP_ID(0x0A03),  // HID
    0                     // UID
  },
  {
    { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0},
    0,
    0
  },
  { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
};

STATIC
VOID
ConfigureUSBHost (
  VOID
  )
示例#15
0
文件: LegacySio.c 项目: MattDevo/edk2
/**
  Collect EFI Info about legacy devices through Super IO interface.

  @param  SioPtr       Pointer to SIO data.

  @retval EFI_SUCCESS   When SIO data is got successfully.
  @retval EFI_NOT_FOUND When ISA IO interface is absent.

**/
EFI_STATUS
LegacyBiosBuildSioDataFromSio (
  IN DEVICE_PRODUCER_DATA_HEADER             *SioPtr
  )
{
  EFI_STATUS                                 Status;
  DEVICE_PRODUCER_SERIAL                     *SioSerial;
  DEVICE_PRODUCER_PARALLEL                   *SioParallel;
  DEVICE_PRODUCER_FLOPPY                     *SioFloppy;
  UINTN                                      HandleCount;
  EFI_HANDLE                                 *HandleBuffer;
  UINTN                                      Index;
  UINTN                                      ChildIndex;
  EFI_SIO_PROTOCOL                           *Sio;
  ACPI_RESOURCE_HEADER_PTR                   Resources;
  EFI_ACPI_IO_PORT_DESCRIPTOR                *IoResource;
  EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIoResource;
  EFI_ACPI_DMA_DESCRIPTOR                    *DmaResource;
  EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR             *IrqResource;
  UINT16                                     Address;
  UINT8                                      Dma;
  UINT8                                      Irq;
  UINTN                                      EntryCount;
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY        *OpenInfoBuffer;
  EFI_BLOCK_IO_PROTOCOL                      *BlockIo;
  EFI_SERIAL_IO_PROTOCOL                     *SerialIo;
  EFI_DEVICE_PATH_PROTOCOL                   *DevicePath;
  ACPI_HID_DEVICE_PATH                       *Acpi;

  //
  // Get the list of ISA controllers in the system
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiSioProtocolGuid,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }
  //
  // Collect legacy information from each of the ISA controllers in the system
  //
  for (Index = 0; Index < HandleCount; Index++) {
    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSioProtocolGuid, (VOID **) &Sio);
    if (EFI_ERROR (Status)) {
      continue;
    }

    Address = MAX_UINT16;
    Dma     = MAX_UINT8;
    Irq     = MAX_UINT8;
    Status = Sio->GetResources (Sio, &Resources);
    if (!EFI_ERROR (Status)) {
      //
      // Get the base address information from ACPI resource descriptor.
      //
      while (Resources.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
        switch (Resources.SmallHeader->Byte) {
        case ACPI_IO_PORT_DESCRIPTOR:
          IoResource = (EFI_ACPI_IO_PORT_DESCRIPTOR *) Resources.SmallHeader;
          Address = IoResource->BaseAddressMin;
          break;

        case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR:
          FixedIoResource = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) Resources.SmallHeader;
          Address = FixedIoResource->BaseAddress;
          break;

        case ACPI_DMA_DESCRIPTOR:
          DmaResource = (EFI_ACPI_DMA_DESCRIPTOR *) Resources.SmallHeader;
          Dma = (UINT8) LowBitSet32 (DmaResource->ChannelMask);
          break;

        case ACPI_IRQ_DESCRIPTOR:
        case ACPI_IRQ_NOFLAG_DESCRIPTOR:
          IrqResource = (EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR *) Resources.SmallHeader;
          Irq = (UINT8) LowBitSet32 (IrqResource->Mask);
          break;

        default:
          break;
        }

        if (Resources.SmallHeader->Bits.Type == 0) {
          Resources.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) Resources.SmallHeader
                                                                  + Resources.SmallHeader->Bits.Length
                                                                  + sizeof (*Resources.SmallHeader));
        } else {
          Resources.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) Resources.LargeHeader
                                                                  + Resources.LargeHeader->Length
                                                                  + sizeof (*Resources.LargeHeader));
        }
      }
    }

    DEBUG ((EFI_D_INFO, "LegacySio: Address/Dma/Irq = %x/%d/%d\n", Address, Dma, Irq));

    DevicePath = DevicePathFromHandle (HandleBuffer[Index]);
    if (DevicePath == NULL) {
      continue;
    }

    Acpi = NULL;
    while (!IsDevicePathEnd (DevicePath)) {
      Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
      DevicePath = NextDevicePathNode (DevicePath);
    }

    if ((Acpi == NULL) || (DevicePathType (Acpi) != ACPI_DEVICE_PATH) ||
        ((DevicePathSubType (Acpi) != ACPI_DP) && (DevicePathSubType (Acpi) != ACPI_EXTENDED_DP))
        ) {
      continue;
    }

    //
    // See if this is an ISA serial port
    //
    // Ignore DMA resource since it is always returned NULL
    //
    if (Acpi->HID == EISA_PNP_ID (0x500) || Acpi->HID == EISA_PNP_ID (0x501)) {

      if (Acpi->UID < 4 && Address != MAX_UINT16 && Irq != MAX_UINT8) {
        //
        // Get the handle of the child device that has opened the Super I/O Protocol
        //
        Status = gBS->OpenProtocolInformation (
                        HandleBuffer[Index],
                        &gEfiSioProtocolGuid,
                        &OpenInfoBuffer,
                        &EntryCount
                        );
        if (EFI_ERROR (Status)) {
          continue;
        }
        for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {
          if ((OpenInfoBuffer[ChildIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
            Status = gBS->HandleProtocol (OpenInfoBuffer[ChildIndex].ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo);
            if (!EFI_ERROR (Status)) {
              SioSerial           = &SioPtr->Serial[Acpi->UID];
              SioSerial->Address  = Address;
              SioSerial->Irq      = Irq;
              SioSerial->Mode     = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;
              break;
            }
          }
        }

        FreePool (OpenInfoBuffer);
      }
    }
    //
    // See if this is an ISA parallel port
    //
    // Ignore DMA resource since it is always returned NULL, port
    // only used in output mode.
    //
    if (Acpi->HID == EISA_PNP_ID (0x400) || Acpi->HID == EISA_PNP_ID (0x401)) {
      if (Acpi->UID < 3 && Address != MAX_UINT16 && Irq != MAX_UINT8 && Dma != MAX_UINT8) {
        SioParallel           = &SioPtr->Parallel[Acpi->UID];
        SioParallel->Address  = Address;
        SioParallel->Irq      = Irq;
        SioParallel->Dma      = Dma;
        SioParallel->Mode     = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;
      }
    }
    //
    // See if this is an ISA floppy controller
    //
    if (Acpi->HID == EISA_PNP_ID (0x604)) {
      if (Address != MAX_UINT16 && Irq != MAX_UINT8 && Dma != MAX_UINT8) {
        Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
        if (!EFI_ERROR (Status)) {
          SioFloppy           = &SioPtr->Floppy;
          SioFloppy->Address  = Address;
          SioFloppy->Irq      = Irq;
          SioFloppy->Dma      = Dma;
          SioFloppy->NumberOfFloppy++;
        }
      }
    }
    //
    // See if this is a mouse
    // Always set mouse found so USB hot plug will work
    //
    // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
    //
    //    Hid = ResourceList->Device.HID & 0xff00ffff;
    //    PnpId = EISA_PNP_ID(0x0f00);
    //    if (Hid == PnpId) {
    //      if (ResourceList->Device.UID == 1) {
    //        Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
    //      if (!EFI_ERROR (Status)) {
    //
    SioPtr->MousePresent = 0x01;
    //
    //        }
    //      }
    //    }
    //
  }

  FreePool (HandleBuffer);
  return EFI_SUCCESS;

}
示例#16
0
EFI_STATUS
EFIAPI
LpcDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                Status;
  EFI_PCI_IO_PROTOCOL       *PciIo;
  EFI_DEVICE_PATH_PROTOCOL  *IsaBridgeDevicePath;

  ACPI_HID_DEVICE_PATH      *AcpiNode;
  PCI_DEVICE_PATH           *PciNode;
  PCI_TYPE00                Pci;

  //
  // Get the ISA bridge's Device Path and test it
  // the following code is specific
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **)&IsaBridgeDevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = EFI_SUCCESS;
  AcpiNode =  (ACPI_HID_DEVICE_PATH *)IsaBridgeDevicePath;
  if (AcpiNode->Header.Type != ACPI_DEVICE_PATH ||
      AcpiNode->Header.SubType != ACPI_DP ||
      DevicePathNodeLength (&AcpiNode->Header) != sizeof(ACPI_HID_DEVICE_PATH) ||
      AcpiNode -> HID != EISA_PNP_ID(0x0A03) ||
      AcpiNode -> UID != 0 ) {
    Status = EFI_UNSUPPORTED;
  } else {
    //
    // Get the next node
    //
    IsaBridgeDevicePath = NextDevicePathNode (IsaBridgeDevicePath);
    PciNode  = (PCI_DEVICE_PATH *)IsaBridgeDevicePath;
    if (PciNode->Header.Type != HARDWARE_DEVICE_PATH ||
        PciNode->Header.SubType != HW_PCI_DP ||
        DevicePathNodeLength (&PciNode->Header) != sizeof (PCI_DEVICE_PATH) ||
        PciNode -> Function != 0x00 ||
        PciNode -> Device != 0x1f ) {
      Status = EFI_UNSUPPORTED;
    }
  }

  gBS->CloseProtocol (
         Controller,
         &gEfiDevicePathProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  //
  // Get PciIo protocol instance
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiPciIoProtocolGuid,
                  (VOID **)&PciIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  Status = PciIo->Pci.Read (
                        PciIo,
                        EfiPciIoWidthUint32,
                        0,
                        sizeof(Pci) / sizeof(UINT32),
                        &Pci
                        );

  if (!EFI_ERROR (Status)) {
    Status = EFI_SUCCESS; //TODO: force return success as temp solution EFI_UNSUPPORTED;
    if ((Pci.Hdr.Command & 0x03) == 0x03) {
      if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
        //
        // See if this is a standard PCI to ISA Bridge from the Base Code
        // and Class Code
        //
        if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) {
          Status = EFI_SUCCESS;
        } else {
        }

        //
        // See if this is an Intel PCI to ISA bridge in Positive Decode Mode
        //
        if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE &&
            Pci.Hdr.VendorId == 0x8086 &&
            Pci.Hdr.DeviceId == 0x7110) {
          Status = EFI_SUCCESS;
        } else {
        }
      } else {
      }
    }
    else {
    }
  }

  gBS->CloseProtocol (
         Controller,
         &gEfiPciIoProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );
  return Status;
}
示例#17
0
文件: efiemu.c 项目: CSRedRat/reactos
/*++
 * @name EfiInitTranslateDevicePath
 *
 *     The EfiInitTranslateDevicePath routine 
 *
 * @param  DevicePath
 *         UEFI Image Handle for the current loaded application.
 *
 * @param  DeviceEntry
 *         Pointer to the UEFI System Table.
 *
 * @return None
 *
 *--*/
NTSTATUS
EfiInitTranslateDevicePath (
    _In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath,
    _In_ PBL_DEVICE_DESCRIPTOR DeviceEntry
    )
{
    NTSTATUS Status;
    EFI_DEVICE_PATH_PROTOCOL* DeviceNode;
    MEMMAP_DEVICE_PATH* MemDevicePath;
    ACPI_HID_DEVICE_PATH *AcpiPath;
    HARDDRIVE_DEVICE_PATH *DiskPath;

    /* Assume failure */
    Status = STATUS_UNSUCCESSFUL;

    /* Set size first */
    DeviceEntry->Size = sizeof(*DeviceEntry);

    /* Check if we are booting from a RAM Disk */
    if ((DevicePath->Type == HARDWARE_DEVICE_PATH) &&
        (DevicePath->SubType == HW_MEMMAP_DP))
    {
        /* Get the EFI data structure matching this */
        MemDevicePath = (MEMMAP_DEVICE_PATH*)DevicePath;

        /* Set the boot library specific device types */
        DeviceEntry->DeviceType = LocalDevice;
        DeviceEntry->Local.Type = RamDiskDevice;

        /* Extract the base, size, and offset */
        DeviceEntry->Local.RamDisk.ImageBase.QuadPart = MemDevicePath->StartingAddress;
        DeviceEntry->Local.RamDisk.ImageSize.QuadPart = MemDevicePath->EndingAddress -
                                                        MemDevicePath->StartingAddress;
        DeviceEntry->Local.RamDisk.ImageOffset = 0;
        return STATUS_SUCCESS;
    }

    /* Otherwise, check what kind of device node this is */
    DeviceNode = EfiInitpGetDeviceNode(DevicePath);
    switch (DeviceNode->Type)
    {
        /* ACPI */
        case ACPI_DEVICE_PATH:

            /* We only support floppy drives */
            AcpiPath = (ACPI_HID_DEVICE_PATH*)DeviceNode;
            if ((AcpiPath->HID != EISA_PNP_ID(0x604)) &&
                (AcpiPath->HID != EISA_PNP_ID(0x700)))
            {
                return Status;
            }

            /* Set the boot library specific device types */
            DeviceEntry->DeviceType = LocalDevice;
            DeviceEntry->Local.Type = FloppyDevice;

            /* The ACPI UID is the drive number */
            DeviceEntry->Local.FloppyDisk.DriveNumber = AcpiPath->UID;
            return STATUS_SUCCESS;

        /* Network, ATAPI, SCSI, USB */
        case MESSAGING_DEVICE_PATH:

            /* Check if it's network */
            if ((DeviceNode->SubType == MSG_MAC_ADDR_DP) ||
                (DeviceNode->SubType == MSG_IPv4_DP))
            {
                /* Set the boot library specific device types */
                DeviceEntry->DeviceType = UdpDevice;
                DeviceEntry->Remote.Unknown = 256;
                return STATUS_SUCCESS;
            }

            /* Other types should come in as MEDIA_DEVICE_PATH -- Windows assumes this is a floppy */
            DeviceEntry->DeviceType = DiskDevice;
            DeviceEntry->Local.Type = FloppyDevice;
            DeviceEntry->Local.FloppyDisk.DriveNumber = 0;
            return STATUS_SUCCESS;

        /* Disk or CDROM */
        case MEDIA_DEVICE_PATH:

            /* Extract the disk path and check if it's a physical disk */
            DiskPath = (HARDDRIVE_DEVICE_PATH*)DeviceNode;
            if (DeviceNode->SubType == MEDIA_HARDDRIVE_DP)
            {
                /* Check if this is an MBR partition */
                if (DiskPath->SignatureType == SIGNATURE_TYPE_MBR)
                {
                    /* Set that this is a local partition */
                    DeviceEntry->DeviceType = LegacyPartitionDevice;
                    DeviceEntry->Partition.Disk.Type = LocalDevice;

                    DeviceEntry->Partition.Disk.HardDisk.PartitionType = MbrPartition;
                    DeviceEntry->Partition.Disk.HardDisk.Mbr.PartitionSignature =
                        *(PULONG)&DiskPath->Signature[0];
                    DeviceEntry->Partition.Mbr.PartitionNumber = DiskPath->PartitionNumber;
                    return STATUS_SUCCESS;
                }

                /* Check if it's a GPT partition */
                if (DiskPath->SignatureType == SIGNATURE_TYPE_GUID)
                {
                    /* Set that this is a local disk */
                    DeviceEntry->DeviceType = PartitionDevice;
                    DeviceEntry->Partition.Disk.Type = LocalDevice;

                    /* Set GPT partition ID */
                    DeviceEntry->Partition.Disk.HardDisk.PartitionType = GptPartition;

                    /* Copy the signature GUID */
                    RtlCopyMemory(&DeviceEntry->Partition.Gpt.PartitionGuid,
                                  DiskPath->Signature, 
                                  sizeof(GUID));

                    DeviceEntry->Flags |= 4u;
                    return STATUS_SUCCESS;
                }

                /* Otherwise, raw boot is not supported */
                DeviceEntry->DeviceType = PartitionDevice;
                DeviceEntry->Partition.Disk.Type = LocalDevice;
                DeviceEntry->Partition.Disk.HardDisk.PartitionType = RawPartition;
                DeviceEntry->Partition.Disk.HardDisk.Raw.DiskNumber = 0;
            }
            else if (DeviceNode->SubType == MEDIA_CDROM_DP)
            {
                /* Set the right type for a CDROM */
                DeviceEntry->DeviceType = DiskDevice;
                DeviceEntry->Local.Type = CdRomDevice;

                /* Set the drive number to zero */
                DeviceEntry->Local.FloppyDisk.DriveNumber = 0;
                return STATUS_SUCCESS;
            }

        /* Fail anything else */
        default:
            break;
    }

    /* Return here only on failure */
    return Status;
}
示例#18
0
文件: Serial.c 项目: MattDevo/edk2
/**
  Return whether the controller is a SIO serial controller.

  @param  Controller   The controller handle.

  @retval EFI_SUCCESS  The controller is a SIO serial controller.
  @retval others       The controller is not a SIO serial controller.
**/
EFI_STATUS
IsSioSerialController (
  EFI_HANDLE               Controller
  )
{
  EFI_STATUS               Status;
  EFI_SIO_PROTOCOL         *Sio;
  EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  ACPI_HID_DEVICE_PATH     *Acpi;

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiSioProtocolGuid,
                  (VOID **) &Sio,
                  gSerialControllerDriver.DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (Status == EFI_ALREADY_STARTED) {
    return EFI_SUCCESS;
  }

  if (!EFI_ERROR (Status)) {
    //
    // Close the I/O Abstraction(s) used to perform the supported test
    //
    gBS->CloseProtocol (
           Controller,
           &gEfiSioProtocolGuid,
           gSerialControllerDriver.DriverBindingHandle,
           Controller
           );

    Status = gBS->OpenProtocol (
      Controller,
      &gEfiDevicePathProtocolGuid,
      (VOID **) &DevicePath,
      gSerialControllerDriver.DriverBindingHandle,
      Controller,
      EFI_OPEN_PROTOCOL_BY_DRIVER
      );
    ASSERT (Status != EFI_ALREADY_STARTED);

    if (!EFI_ERROR (Status)) {
      do {
        Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
        DevicePath = NextDevicePathNode (DevicePath);
      } while (!IsDevicePathEnd (DevicePath));

      if (DevicePathType (Acpi) != ACPI_DEVICE_PATH ||
          (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != ACPI_EXTENDED_DP) ||
          Acpi->HID != EISA_PNP_ID (0x501)
          ) {
        Status = EFI_UNSUPPORTED;
      }
    }

    //
    // Close protocol, don't use device path protocol in the Support() function
    //
    gBS->CloseProtocol (
      Controller,
      &gEfiDevicePathProtocolGuid,
      gSerialControllerDriver.DriverBindingHandle,
      Controller
      );
  }
  return Status;
}
示例#19
0
/**
  Test to see if this driver supports ControllerHandle. Any ControllerHandle
  than contains a IsaIo protocol can be supported.

  @param  This                Protocol instance pointer.
  @param  ControllerHandle    Handle of device to test
  @param  RemainingDevicePath Optional parameter use to pick a specific child
                              device to start.

  @retval EFI_SUCCESS         This driver supports this device
  @retval EFI_ALREADY_STARTED This driver is already running on this device
  @retval other               This driver does not support this device

**/
EFI_STATUS
EFIAPI
PS2MouseAbsolutePointerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                          Status;
  EFI_ISA_IO_PROTOCOL                 *IsaIo;

  Status = EFI_SUCCESS;

  //
  // Open the IO Abstraction(s) needed to perform the supported test
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiIsaIoProtocolGuid,
                  (VOID **) &IsaIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Use the ISA I/O Protocol to see if Controller is the Mouse controller
  //
  switch (IsaIo->ResourceList->Device.HID) {
  case EISA_PNP_ID (0xF03):
  //
  // Microsoft PS/2 style mouse
  //
  case EISA_PNP_ID (0xF13):
    //
    // PS/2 Port for PS/2-style Mice
    //
    break;

  case EISA_PNP_ID (0x303):
    //
    // IBM Enhanced (101/102-key, PS/2 mouse support)
    //
    if (IsaIo->ResourceList->Device.UID == 1) {
      break;
    }

  default:
    Status = EFI_UNSUPPORTED;
    break;
  }
  //
  // Close the I/O Abstraction(s) used to perform the supported test
  //
  gBS->CloseProtocol (
         Controller,
         &gEfiIsaIoProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
示例#20
0
/**
  Test if the controller is a floppy disk drive device

  @param[in] This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  @param[in] Controller           The handle of the controller to test.
  @param[in] RemainingDevicePath  A pointer to the remaining portion of a device path.

  @retval EFI_SUCCESS             The device is supported by this driver.
  @retval EFI_ALREADY_STARTED     The device is already being managed by this driver.
  @retval EFI_ACCESS_DENIED       The device is already being managed by a different driver
                                  or an application that requires exclusive access.
  @retval EFI_UNSUPPORTED         The device is is not supported by this driver.
**/
EFI_STATUS
EFIAPI
FdcControllerDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   Controller,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
  )
{
  EFI_STATUS                Status;
  EFI_ISA_IO_PROTOCOL       *IsaIo;
  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;

  //
  // Ignore the parameter RemainingDevicePath because this is a device driver.
  //

  //
  // Open the device path protocol
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  gBS->CloseProtocol (
         Controller,
         &gEfiDevicePathProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  //
  // Open the ISA I/O Protocol
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiIsaIoProtocolGuid,
                  (VOID **) &IsaIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Use the ISA I/O Protocol to see if Controller is a floppy disk drive device
  //
  Status = EFI_SUCCESS;
  if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
    Status = EFI_UNSUPPORTED;
  }
  //
  // Close the ISA I/O Protocol
  //
  gBS->CloseProtocol (
         Controller,
         &gEfiIsaIoProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
示例#21
0
文件: LegacySio.c 项目: MattDevo/edk2
/**
  Collect EFI Info about legacy devices through ISA IO interface.

  @param  SioPtr       Pointer to SIO data.

  @retval EFI_SUCCESS   When SIO data is got successfully.
  @retval EFI_NOT_FOUND When ISA IO interface is absent.

**/
EFI_STATUS
LegacyBiosBuildSioDataFromIsaIo (
  IN DEVICE_PRODUCER_DATA_HEADER      *SioPtr
  )
{
  EFI_STATUS                          Status;
  DEVICE_PRODUCER_SERIAL              *SioSerial;
  DEVICE_PRODUCER_PARALLEL            *SioParallel;
  DEVICE_PRODUCER_FLOPPY              *SioFloppy;
  UINTN                               HandleCount;
  EFI_HANDLE                          *HandleBuffer;
  UINTN                               Index;
  UINTN                               ResourceIndex;
  UINTN                               ChildIndex;
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
  EFI_ISA_ACPI_RESOURCE_LIST          *ResourceList;
  EFI_ISA_ACPI_RESOURCE               *IoResource;
  EFI_ISA_ACPI_RESOURCE               *DmaResource;
  EFI_ISA_ACPI_RESOURCE               *InterruptResource;
  UINTN                               EntryCount;
  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
  EFI_BLOCK_IO_PROTOCOL               *BlockIo;
  EFI_SERIAL_IO_PROTOCOL              *SerialIo;

  //
  // Get the list of ISA controllers in the system
  //
  Status = gBS->LocateHandleBuffer (
                  ByProtocol,
                  &gEfiIsaIoProtocolGuid,
                  NULL,
                  &HandleCount,
                  &HandleBuffer
                  );
  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }
  //
  // Collect legacy information from each of the ISA controllers in the system
  //
  for (Index = 0; Index < HandleCount; Index++) {

    Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo);
    if (EFI_ERROR (Status)) {
      continue;
    }

    ResourceList = IsaIo->ResourceList;

    if (ResourceList == NULL) {
      continue;
    }
    //
    // Collect the resource types neededto fill in the SIO data structure
    //
    IoResource        = NULL;
    DmaResource       = NULL;
    InterruptResource = NULL;
    for (ResourceIndex = 0;
         ResourceList->ResourceItem[ResourceIndex].Type != EfiIsaAcpiResourceEndOfList;
         ResourceIndex++
        ) {
      switch (ResourceList->ResourceItem[ResourceIndex].Type) {
      case EfiIsaAcpiResourceIo:
        IoResource = &ResourceList->ResourceItem[ResourceIndex];
        break;

      case EfiIsaAcpiResourceMemory:
        break;

      case EfiIsaAcpiResourceDma:
        DmaResource = &ResourceList->ResourceItem[ResourceIndex];
        break;

      case EfiIsaAcpiResourceInterrupt:
        InterruptResource = &ResourceList->ResourceItem[ResourceIndex];
        break;

      default:
        break;
      }
    }
    //
    // See if this is an ISA serial port
    //
    // Ignore DMA resource since it is always returned NULL
    //
    if (ResourceList->Device.HID == EISA_PNP_ID (0x500) || ResourceList->Device.HID == EISA_PNP_ID (0x501)) {

      if (ResourceList->Device.UID <= 3 &&
          IoResource != NULL &&
          InterruptResource != NULL
          ) {
        //
        // Get the handle of the child device that has opened the ISA I/O Protocol
        //
        Status = gBS->OpenProtocolInformation (
                        HandleBuffer[Index],
                        &gEfiIsaIoProtocolGuid,
                        &OpenInfoBuffer,
                        &EntryCount
                        );
        if (EFI_ERROR (Status)) {
          continue;
        }
        //
        // We want resource for legacy even if no 32-bit driver installed
        //
        for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {
          if ((OpenInfoBuffer[ChildIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
            Status = gBS->HandleProtocol (OpenInfoBuffer[ChildIndex].ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo);
            if (!EFI_ERROR (Status)) {
              SioSerial           = &SioPtr->Serial[ResourceList->Device.UID];
              SioSerial->Address  = (UINT16) IoResource->StartRange;
              SioSerial->Irq      = (UINT8) InterruptResource->StartRange;
              SioSerial->Mode     = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;
              break;
            }
          }
        }

        FreePool (OpenInfoBuffer);
      }
    }
    //
    // See if this is an ISA parallel port
    //
    // Ignore DMA resource since it is always returned NULL, port
    // only used in output mode.
    //
    if (ResourceList->Device.HID == EISA_PNP_ID (0x400) || ResourceList->Device.HID == EISA_PNP_ID (0x401)) {
      if (ResourceList->Device.UID <= 2 &&
          IoResource != NULL &&
          InterruptResource != NULL &&
          DmaResource != NULL
          ) {
        SioParallel           = &SioPtr->Parallel[ResourceList->Device.UID];
        SioParallel->Address  = (UINT16) IoResource->StartRange;
        SioParallel->Irq      = (UINT8) InterruptResource->StartRange;
        SioParallel->Dma      = (UINT8) DmaResource->StartRange;
        SioParallel->Mode     = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;
      }
    }
    //
    // See if this is an ISA floppy controller
    //
    if (ResourceList->Device.HID == EISA_PNP_ID (0x604)) {
      if (IoResource != NULL && InterruptResource != NULL && DmaResource != NULL) {
        Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
        if (!EFI_ERROR (Status)) {
          SioFloppy           = &SioPtr->Floppy;
          SioFloppy->Address  = (UINT16) IoResource->StartRange;
          SioFloppy->Irq      = (UINT8) InterruptResource->StartRange;
          SioFloppy->Dma      = (UINT8) DmaResource->StartRange;
          SioFloppy->NumberOfFloppy++;
        }
      }
    }
    //
    // See if this is a mouse
    // Always set mouse found so USB hot plug will work
    //
    // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
    //
    //    Hid = ResourceList->Device.HID & 0xff00ffff;
    //    PnpId = EISA_PNP_ID(0x0f00);
    //    if (Hid == PnpId) {
    //      if (ResourceList->Device.UID == 1) {
    //        Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
    //      if (!EFI_ERROR (Status)) {
    //
    SioPtr->MousePresent = 0x01;
    //
    //        }
    //      }
    //    }
    //
  }

  FreePool (HandleBuffer);
  return EFI_SUCCESS;
}
示例#22
0
/**
  Create a structure that maps the relative positions of PCI root buses to bus
  numbers.

  In the "bootorder" fw_cfg file, QEMU refers to extra PCI root buses by their
  positions, in relative root bus number order, not by their actual PCI bus
  numbers. The ACPI HID device path nodes however that are associated with
  PciRootBridgeIo protocol instances in the system have their UID fields set to
  the bus numbers. Create a map that gives, for each extra PCI root bus's
  position (ie. "serial number") its actual PCI bus number.

  @param[out] ExtraRootBusMap  The data structure implementing the map.

  @retval EFI_SUCCESS           ExtraRootBusMap has been populated.

  @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.

  @retval EFI_ALREADY_STARTED   A duplicate root bus number has been found in
                                the system. (This should never happen.)

  @return                       Error codes returned by
                                gBS->LocateHandleBuffer() and
                                gBS->HandleProtocol().

**/
EFI_STATUS
CreateExtraRootBusMap (
  OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
  )
{
  EFI_STATUS               Status;
  UINTN                    NumHandles;
  EFI_HANDLE               *Handles;
  ORDERED_COLLECTION       *Collection;
  EXTRA_ROOT_BUS_MAP       *Map;
  UINTN                    Idx;
  ORDERED_COLLECTION_ENTRY *Entry, *Entry2;

  //
  // Handles and Collection are temporary / helper variables, while in Map we
  // build the return value.
  //

  Status = gBS->LocateHandleBuffer (ByProtocol,
                  &gEfiPciRootBridgeIoProtocolGuid, NULL /* SearchKey */,
                  &NumHandles, &Handles);
  if (EFI_ERROR (Status))  {
    return Status;
  }

  Collection = OrderedCollectionInit (RootBridgePathCompare,
                 RootBridgePathKeyCompare);
  if (Collection == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto FreeHandles;
  }

  Map = AllocateZeroPool (sizeof *Map);
  if (Map == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto FreeCollection;
  }

  //
  // Collect the ACPI device path protocols of the root bridges.
  //
  for (Idx = 0; Idx < NumHandles; ++Idx) {
    EFI_DEVICE_PATH_PROTOCOL *DevicePath;

    Status = gBS->HandleProtocol (Handles[Idx], &gEfiDevicePathProtocolGuid,
                    (VOID**)&DevicePath);
    if (EFI_ERROR (Status)) {
      goto FreeMap;
    }

    //
    // Examine if the device path is an ACPI HID one, and if so, if UID is
    // nonzero (ie. the root bridge that the bus number belongs to is "extra",
    // not the main one). In that case, link the device path into Collection.
    //
    if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH &&
        DevicePathSubType (DevicePath) == ACPI_DP &&
        ((ACPI_HID_DEVICE_PATH *)DevicePath)->HID == EISA_PNP_ID(0x0A03) &&
        ((ACPI_HID_DEVICE_PATH *)DevicePath)->UID > 0) {
      Status = OrderedCollectionInsert (Collection, NULL, DevicePath);
      if (EFI_ERROR (Status)) {
        goto FreeMap;
      }
      ++Map->Count;
    }
  }

  if (Map->Count > 0) {
    //
    // At least one extra PCI root bus exists.
    //
    Map->BusNumbers = AllocatePool (Map->Count * sizeof *Map->BusNumbers);
    if (Map->BusNumbers == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto FreeMap;
    }
  }

  //
  // Now collect the bus numbers of the extra PCI root buses into Map.
  //
  Idx = 0;
  Entry = OrderedCollectionMin (Collection);
  while (Idx < Map->Count) {
    ACPI_HID_DEVICE_PATH *Acpi;

    ASSERT (Entry != NULL);
    Acpi = OrderedCollectionUserStruct (Entry);
    Map->BusNumbers[Idx] = Acpi->UID;
    DEBUG ((EFI_D_VERBOSE,
      "%a: extra bus position 0x%Lx maps to bus number (UID) 0x%x\n",
      __FUNCTION__, (UINT64)(Idx + 1), Acpi->UID));
    ++Idx;
    Entry = OrderedCollectionNext (Entry);
  }
  ASSERT (Entry == NULL);

  *ExtraRootBusMap = Map;
  Status = EFI_SUCCESS;

  //
  // Fall through in order to release temporaries.
  //

FreeMap:
  if (EFI_ERROR (Status)) {
    if (Map->BusNumbers != NULL) {
      FreePool (Map->BusNumbers);
    }
    FreePool (Map);
  }

FreeCollection:
  for (Entry = OrderedCollectionMin (Collection); Entry != NULL;
       Entry = Entry2) {
    Entry2 = OrderedCollectionNext (Entry);
    OrderedCollectionDelete (Collection, Entry, NULL);
  }
  OrderedCollectionUninit (Collection);

FreeHandles:
  FreePool (Handles);

  return Status;
}