EFIAPI GetNextDevicePathInstanceProtocolInterface ( IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT UINTN *Size ) { return GetNextDevicePathInstance (DevicePath, Size); }
EFIAPI BdsLibDelPartMatchInstance ( IN EFI_DEVICE_PATH_PROTOCOL *Multi, IN EFI_DEVICE_PATH_PROTOCOL *Single ) { EFI_DEVICE_PATH_PROTOCOL *Instance; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath; UINTN InstanceSize; UINTN SingleDpSize; UINTN Size; NewDevicePath = NULL; TempNewDevicePath = NULL; if (Multi == NULL || Single == NULL) { return Multi; } Instance = GetNextDevicePathInstance (&Multi, &InstanceSize); SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH; InstanceSize -= END_DEVICE_PATH_LENGTH; while (Instance != NULL) { Size = (SingleDpSize < InstanceSize) ? SingleDpSize : InstanceSize; if ((CompareMem (Instance, Single, Size) != 0)) { // // Append the device path instance which does not match with Single // TempNewDevicePath = NewDevicePath; NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance); if (TempNewDevicePath != NULL) { FreePool(TempNewDevicePath); } } FreePool(Instance); Instance = GetNextDevicePathInstance (&Multi, &InstanceSize); InstanceSize -= END_DEVICE_PATH_LENGTH; } return NewDevicePath; }
/** Function compares a device path data structure to that of all the nodes of a second device path instance. @param Multi A pointer to a multi-instance device path data structure. @param Single A pointer to a single-instance device path data structure. @retval TRUE If the Single device path is contained within Multi device path. @retval FALSE The Single device path is not match within Multi device path. **/ BOOLEAN EFIAPI BdsLibMatchDevicePaths ( IN EFI_DEVICE_PATH_PROTOCOL *Multi, IN EFI_DEVICE_PATH_PROTOCOL *Single ) { EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; UINTN Size; if (Multi == NULL || Single == NULL) { return FALSE; } DevicePath = Multi; DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); // // Search for the match of 'Single' in 'Multi' // while (DevicePathInst != NULL) { // // If the single device path is found in multiple device paths, // return success // if (CompareMem (Single, DevicePathInst, Size) == 0) { FreePool (DevicePathInst); return TRUE; } FreePool (DevicePathInst); DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); } return FALSE; }
/** Function is used to determine the number of device path instances that exist in a device path. @param DevicePath A pointer to a device path data structure. @return This function counts and returns the number of device path instances in DevicePath. **/ UINTN EfiDevicePathInstanceCount ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { UINTN Count; UINTN Size; Count = 0; while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) { Count += 1; } return Count; }
/** Connect the network devices. @retval EFI_SUCCESS At least one network device was connected. @retval EFI_DEVICE_ERROR Network devices were not connected due to an error. **/ EFI_STATUS ConnectNetwork ( VOID ) { EFI_STATUS Status; BOOLEAN OneConnected; EFI_DEVICE_PATH_PROTOCOL *Devices; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EFI_DEVICE_PATH_PROTOCOL *SingleDevice; UINTN Size; OneConnected = FALSE; GetVariable2 (mNetworkDeviceList, &gEfiCallerIdGuid, (VOID **) &Devices, NULL); TempDevicePath = Devices; while (TempDevicePath != NULL) { SingleDevice = GetNextDevicePathInstance (&TempDevicePath, &Size); Status = EfiBootManagerConnectDevicePath (SingleDevice, NULL); if (!EFI_ERROR (Status)) { OneConnected = TRUE; } FreePool (SingleDevice); } if (Devices != NULL) { FreePool (Devices); } if (OneConnected) { return EFI_SUCCESS; } else { // // Cached network devices list doesn't exist or is NOT valid. // return ConnectAllAndCreateNetworkDeviceList (); } }
STATIC EFI_STATUS InitializeConsolePipe ( IN EFI_DEVICE_PATH *ConsoleDevicePaths, IN EFI_GUID *Protocol, OUT EFI_HANDLE *Handle, OUT VOID* *Interface ) { EFI_STATUS Status; UINTN Size; UINTN NoHandles; EFI_HANDLE *Buffer; EFI_DEVICE_PATH_PROTOCOL* DevicePath; // Connect all the Device Path Consoles while (ConsoleDevicePaths != NULL) { DevicePath = GetNextDevicePathInstance (&ConsoleDevicePaths, &Size); Status = BdsConnectDevicePath (DevicePath, Handle, NULL); DEBUG_CODE_BEGIN(); if (EFI_ERROR(Status)) { // We convert back to the text representation of the device Path EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; CHAR16* DevicePathTxt; EFI_STATUS Status; Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); if (!EFI_ERROR(Status)) { DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePath, TRUE, TRUE); DEBUG((EFI_D_ERROR,"Fail to start the console with the Device Path '%s'. (Error '%r')\n", DevicePathTxt, Status)); FreePool (DevicePathTxt); } } DEBUG_CODE_END(); // If the console splitter driver is not supported by the platform then use the first Device Path // instance for the console interface. if (!EFI_ERROR(Status) && (*Interface == NULL)) { Status = gBS->HandleProtocol (*Handle, Protocol, Interface); } } // No Device Path has been defined for this console interface. We take the first protocol implementation if (*Interface == NULL) { Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer); if (EFI_ERROR (Status)) { BdsConnectAllDrivers(); Status = gBS->LocateHandleBuffer (ByProtocol, Protocol, NULL, &NoHandles, &Buffer); } if (!EFI_ERROR(Status)) { *Handle = Buffer[0]; Status = gBS->HandleProtocol (*Handle, Protocol, Interface); ASSERT_EFI_ERROR(Status); FreePool (Buffer); } } else { Status = EFI_SUCCESS; } return Status; }
EFI_STATUS EFIAPI BdsLibConnectDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; EFI_DEVICE_PATH_PROTOCOL *Instance; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_HANDLE Handle; EFI_HANDLE PreviousHandle; UINTN Size; if (DevPathToTxt == NULL) { Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevPathToTxt); ASSERT((!EFI_ERROR(Status))); } if (DevicePathToConnect == NULL) { return EFI_SUCCESS; } DEBUG((DEBUG_INFO, "%a:%d dev path '%s' to connect\n", __FILE__, __LINE__, DevPathToTxt->ConvertDevicePathToText(DevicePathToConnect, TRUE, FALSE))); DevicePath = DuplicateDevicePath (DevicePathToConnect); if (DevicePath == NULL) { return EFI_OUT_OF_RESOURCES; } CopyOfDevicePath = DevicePath; do { // // The outer loop handles multi instance device paths. // Only console variables contain multiple instance device paths. // // After this call DevicePath points to the next Instance // Instance = GetNextDevicePathInstance (&DevicePath, &Size); if (Instance == NULL) { FreePool (CopyOfDevicePath); return EFI_OUT_OF_RESOURCES; } Next = Instance; while (!IsDevicePathEndType (Next)) { Next = NextDevicePathNode (Next); } SetDevicePathEndNode (Next); // // Start the real work of connect with RemainingDevicePath // PreviousHandle = NULL; do { // // Find the handle that best matches the Device Path. If it is only a // partial match the remaining part of the device path is returned in // RemainingDevicePath. // RemainingDevicePath = Instance; Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle); if (!EFI_ERROR (Status)) { if (Handle == PreviousHandle) { // // If no forward progress is made try invoking the Dispatcher. // A new FV may have been added to the system an new drivers // may now be found. // Status == EFI_SUCCESS means a driver was dispatched // Status == EFI_NOT_FOUND means no new drivers were dispatched // Status = gDS->Dispatch (); } if (!EFI_ERROR (Status)) { PreviousHandle = Handle; // // Connect all drivers that apply to Handle and RemainingDevicePath, // the Recursive flag is FALSE so only one level will be expanded. // // Do not check the connect status here, if the connect controller fail, // then still give the chance to do dispatch, because partial // RemainingDevicepath may be in the new FV // // 1. If the connect fail, RemainingDevicepath and handle will not // change, so next time will do the dispatch, then dispatch's status // will take effect // 2. If the connect success, the RemainingDevicepath and handle will // change, then avoid the dispatch, we have chance to continue the // next connection // gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE); } } // // Loop until RemainingDevicePath is an empty device path // } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); } while (DevicePath != NULL); if (CopyOfDevicePath != NULL) { FreePool (CopyOfDevicePath); } // // All handle with DevicePath exists in the handle database // return Status; }
/** Build up Console Menu based on types passed in. The type can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT and BM_CONSOLE_ERR_CONTEXT_SELECT. @param ConsoleMenuType Can be BM_CONSOLE_IN_CONTEXT_SELECT, BM_CONSOLE_OUT_CONTEXT_SELECT and BM_CONSOLE_ERR_CONTEXT_SELECT. @retval EFI_UNSUPPORTED The type passed in is not in the 3 types defined. @retval EFI_NOT_FOUND If the EFI Variable defined in UEFI spec with name "ConOutDev", "ConInDev" or "ConErrDev" doesn't exists. @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operations. @retval EFI_SUCCESS Function completes successfully. **/ EFI_STATUS GetConsoleMenu ( IN UINTN ConsoleMenuType ) { EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; UINTN Size; UINTN AllCount; UINTN Index; UINTN Index2; BM_MENU_ENTRY *NewMenuEntry; BM_CONSOLE_CONTEXT *NewConsoleContext; TYPE_OF_TERMINAL Terminal; UINTN Com; BM_MENU_OPTION *ConsoleMenu; DevicePath = NULL; AllDevicePath = NULL; AllCount = 0; switch (ConsoleMenuType) { case BM_CONSOLE_IN_CONTEXT_SELECT: ConsoleMenu = &ConsoleInpMenu; DevicePath = EfiLibGetVariable ( L"ConIn", &gEfiGlobalVariableGuid ); AllDevicePath = EfiLibGetVariable ( L"ConInDev", &gEfiGlobalVariableGuid ); break; case BM_CONSOLE_OUT_CONTEXT_SELECT: ConsoleMenu = &ConsoleOutMenu; DevicePath = EfiLibGetVariable ( L"ConOut", &gEfiGlobalVariableGuid ); AllDevicePath = EfiLibGetVariable ( L"ConOutDev", &gEfiGlobalVariableGuid ); break; case BM_CONSOLE_ERR_CONTEXT_SELECT: ConsoleMenu = &ConsoleErrMenu; DevicePath = EfiLibGetVariable ( L"ErrOut", &gEfiGlobalVariableGuid ); AllDevicePath = EfiLibGetVariable ( L"ErrOutDev", &gEfiGlobalVariableGuid ); break; default: return EFI_UNSUPPORTED; } if (NULL == AllDevicePath) { return EFI_NOT_FOUND; } InitializeListHead (&ConsoleMenu->Head); AllCount = EfiDevicePathInstanceCount (AllDevicePath); ConsoleMenu->MenuNumber = 0; // // Following is menu building up for Console Devices selected. // MultiDevicePath = AllDevicePath; Index2 = 0; for (Index = 0; Index < AllCount; Index++) { DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; NewMenuEntry->OptionNumber = Index2; NewConsoleContext->DevicePath = DuplicateDevicePath (DevicePathInst); ASSERT (NewConsoleContext->DevicePath != NULL); NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); if (NULL == NewMenuEntry->DisplayString) { NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath); } NewConsoleContext->IsTerminal = IsTerminalDevicePath ( NewConsoleContext->DevicePath, &Terminal, &Com ); NewConsoleContext->IsActive = BdsLibMatchDevicePaths ( DevicePath, NewConsoleContext->DevicePath ); if (NewConsoleContext->IsTerminal) { BOpt_DestroyMenuEntry (NewMenuEntry); } else { Index2++; ConsoleMenu->MenuNumber++; InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); } } return EFI_SUCCESS; }
/** Do a connect from an EFI variable via it's key name. @param[in] Key The name of the EFI Variable. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS ShellConnectFromDevPaths ( IN CONST CHAR16 *Key ) { EFI_DEVICE_PATH_PROTOCOL *DevPath; EFI_DEVICE_PATH_PROTOCOL *CopyOfDevPath; EFI_DEVICE_PATH_PROTOCOL *Instance; EFI_DEVICE_PATH_PROTOCOL *Next; UINTN Length; UINTN Index; UINTN HandleArrayCount; UINTN Size; EFI_HANDLE *HandleArray; EFI_STATUS Status; BOOLEAN AtLeastOneConnected; EFI_PCI_IO_PROTOCOL *PciIo; UINT8 Class[3]; DevPath = NULL; Length = 0; AtLeastOneConnected = FALSE; // // Get the DevicePath buffer from the variable... // Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath); if (Status == EFI_BUFFER_TOO_SMALL) { DevPath = AllocateZeroPool(Length); if (DevPath == NULL) { return EFI_OUT_OF_RESOURCES; } Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath); if (EFI_ERROR (Status)) { if (DevPath != NULL) { FreePool (DevPath); } return Status; } } else if (EFI_ERROR (Status)) { return Status; } Status = EFI_NOT_FOUND; CopyOfDevPath = DevPath; // // walk the list of devices and connect them // do { // // Check every instance of the console variable // Instance = GetNextDevicePathInstance (&CopyOfDevPath, &Size); if (Instance == NULL) { if (DevPath != NULL) { FreePool (DevPath); } return EFI_UNSUPPORTED; } Next = Instance; while (!IsDevicePathEndType (Next)) { Next = NextDevicePathNode (Next); } SetDevicePathEndNode (Next); // // connect short form device path // if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP) )) { Status = ShellConnectPciRootBridge (); if (EFI_ERROR(Status)) { FreePool(Instance); FreePool(DevPath); return Status; } Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleArrayCount, &HandleArray ); if (!EFI_ERROR (Status)) { for (Index = 0; Index < HandleArrayCount; Index++) { Status = gBS->HandleProtocol ( HandleArray[Index], &gEfiPciIoProtocolGuid, (VOID **)&PciIo ); if (!EFI_ERROR (Status)) { Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class); if (!EFI_ERROR (Status)) { if ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1])) { Status = gBS->ConnectController ( HandleArray[Index], NULL, Instance, FALSE ); if (!EFI_ERROR(Status)) { AtLeastOneConnected = TRUE; } } } } } } if (HandleArray != NULL) { FreePool (HandleArray); } } else { // // connect the entire device path // Status = ShellConnectDevicePath (Instance); if (!EFI_ERROR (Status)) { AtLeastOneConnected = TRUE; } } FreePool (Instance); } while (CopyOfDevPath != NULL); if (DevPath != NULL) { FreePool(DevPath); } if (AtLeastOneConnected) { return EFI_SUCCESS; } else { return EFI_NOT_FOUND; } }
/** Fill console handle in System Table if there are no valid console handle in. Firstly, check the validation of console handle in System Table. If it is invalid, update it by the first console device handle from EFI console variable. @param VarName The name of the EFI console variable. @param ConsoleGuid Specified Console protocol GUID. @param ConsoleHandle On IN, console handle in System Table to be checked. On OUT, new console handle in system table. @param ProtocolInterface On IN, console protocol on console handle in System Table to be checked. On OUT, new console protocol on new console handle in system table. @retval TRUE System Table has been updated. @retval FALSE System Table hasn't been updated. **/ BOOLEAN UpdateSystemTableConsole ( IN CHAR16 *VarName, IN EFI_GUID *ConsoleGuid, IN OUT EFI_HANDLE *ConsoleHandle, IN OUT VOID **ProtocolInterface ) { EFI_STATUS Status; UINTN DevicePathSize; EFI_DEVICE_PATH_PROTOCOL *FullDevicePath; EFI_DEVICE_PATH_PROTOCOL *VarConsole; EFI_DEVICE_PATH_PROTOCOL *Instance; VOID *Interface; EFI_HANDLE NewHandle; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; ASSERT (VarName != NULL); ASSERT (ConsoleHandle != NULL); ASSERT (ConsoleGuid != NULL); ASSERT (ProtocolInterface != NULL); if (*ConsoleHandle != NULL) { Status = gBS->HandleProtocol ( *ConsoleHandle, ConsoleGuid, &Interface ); if (Status == EFI_SUCCESS && Interface == *ProtocolInterface) { // // If ConsoleHandle is valid and console protocol on this handle also // also matched, just return. // return FALSE; } } // // Get all possible consoles device path from EFI variable // VarConsole = BdsLibGetVariableAndSize ( VarName, &gEfiGlobalVariableGuid, &DevicePathSize ); if (VarConsole == NULL) { // // If there is no any console device, just return. // return FALSE; } FullDevicePath = VarConsole; do { // // Check every instance of the console variable // Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize); if (Instance == NULL) { FreePool (FullDevicePath); ASSERT (FALSE); } // // Find console device handle by device path instance // Status = gBS->LocateDevicePath ( ConsoleGuid, &Instance, &NewHandle ); if (!EFI_ERROR (Status)) { // // Get the console protocol on this console device handle // Status = gBS->HandleProtocol ( NewHandle, ConsoleGuid, &Interface ); if (!EFI_ERROR (Status)) { // // Update new console handle in System Table. // *ConsoleHandle = NewHandle; *ProtocolInterface = Interface; if (CompareGuid (ConsoleGuid, &gEfiSimpleTextOutProtocolGuid)) { // // If it is console out device, set console mode 80x25 if current mode is invalid. // TextOut = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) Interface; if (TextOut->Mode->Mode == -1) { TextOut->SetMode (TextOut, 0); } } return TRUE; } } } while (Instance != NULL); // // No any available console devcie found. // return FALSE; }
/** Connect the console device base on the variable ConVarName, if device path of the ConVarName is multi-instance device path and anyone of the instances is connected success, then this function will return success. If the handle associate with one device path node can not be created successfully, then still give chance to do the dispatch, which load the missing drivers if possible.. @param ConVarName Console related variable name, ConIn, ConOut, ErrOut. @retval EFI_NOT_FOUND There is not any console devices connected success @retval EFI_SUCCESS Success connect any one instance of the console device path base on the variable ConVarName. **/ EFI_STATUS EFIAPI BdsLibConnectConsoleVariable ( IN CHAR16 *ConVarName ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *StartDevicePath; UINTN VariableSize; EFI_DEVICE_PATH_PROTOCOL *Instance; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; UINTN Size; BOOLEAN DeviceExist; Status = EFI_SUCCESS; DeviceExist = FALSE; // // Check if the console variable exist // StartDevicePath = BdsLibGetVariableAndSize ( ConVarName, &gEfiGlobalVariableGuid, &VariableSize ); if (StartDevicePath == NULL) { return EFI_UNSUPPORTED; } CopyOfDevicePath = StartDevicePath; do { // // Check every instance of the console variable // Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size); if (Instance == NULL) { FreePool (StartDevicePath); return EFI_UNSUPPORTED; } Next = Instance; while (!IsDevicePathEndType (Next)) { Next = NextDevicePathNode (Next); } SetDevicePathEndNode (Next); // // Connect the USB console // USB console device path is a short-form device path that // starts with the first element being a USB WWID // or a USB Class device path // if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP) )) { Status = BdsLibConnectUsbDevByShortFormDP (0xFF, Instance); if (!EFI_ERROR (Status)) { DeviceExist = TRUE; } } else { // // Connect the instance device path // Status = BdsLibConnectDevicePath (Instance); if (EFI_ERROR (Status)) { // // Delete the instance from the console varialbe // BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance); } else { DeviceExist = TRUE; } } FreePool(Instance); } while (CopyOfDevicePath != NULL); FreePool (StartDevicePath); if (!DeviceExist) { return EFI_NOT_FOUND; } return EFI_SUCCESS; }
/** Connect the console device base on the variable ConsoleType. @param ConsoleType ConIn, ConOut or ErrOut. @retval EFI_NOT_FOUND There is not any console devices connected success @retval EFI_SUCCESS Success connect any one instance of the console device path base on the variable ConVarName. **/ EFI_STATUS EFIAPI EfiBootManagerConnectConsoleVariable ( IN CONSOLE_TYPE ConsoleType ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *StartDevicePath; EFI_DEVICE_PATH_PROTOCOL *Instance; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; UINTN Size; BOOLEAN DeviceExist; EFI_HANDLE Handle; if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) { return EFI_INVALID_PARAMETER; } Status = EFI_SUCCESS; DeviceExist = FALSE; Handle = NULL; // // Check if the console variable exist // GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &StartDevicePath, NULL); if (StartDevicePath == NULL) { return EFI_UNSUPPORTED; } CopyOfDevicePath = StartDevicePath; do { // // Check every instance of the console variable // Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size); if (Instance == NULL) { FreePool (StartDevicePath); return EFI_UNSUPPORTED; } Next = Instance; while (!IsDevicePathEndType (Next)) { Next = NextDevicePathNode (Next); } SetDevicePathEndNode (Next); // // Connect the USB console // USB console device path is a short-form device path that // starts with the first element being a USB WWID // or a USB Class device path // if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)) ) { Status = BmConnectUsbShortFormDevicePath (Instance); if (!EFI_ERROR (Status)) { DeviceExist = TRUE; } } else { for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) { if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) { break; } else if (DevicePathType (Next) == HARDWARE_DEVICE_PATH && DevicePathSubType (Next) == HW_CONTROLLER_DP && DevicePathType (NextDevicePathNode (Next)) == ACPI_DEVICE_PATH && DevicePathSubType (NextDevicePathNode (Next)) == ACPI_ADR_DP ) { break; } } if (!IsDevicePathEnd (Next)) { // // For GOP device path, start the video driver with NULL remaining device path // SetDevicePathEndNode (Next); Status = EfiBootManagerConnectDevicePath (Instance, &Handle); if (!EFI_ERROR (Status)) { gBS->ConnectController (Handle, NULL, NULL, TRUE); } } else { Status = EfiBootManagerConnectDevicePath (Instance, NULL); } if (EFI_ERROR (Status)) { // // Delete the instance from the console varialbe // EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance); } else { DeviceExist = TRUE; } } FreePool(Instance); } while (CopyOfDevicePath != NULL); FreePool (StartDevicePath); if (!DeviceExist) { return EFI_NOT_FOUND; } return EFI_SUCCESS; }
/** Connect the console device base on the variable ConsoleType. @param ConsoleType ConIn, ConOut or ErrOut. @param NeedDispatch Whether need to dispatch. @retval EFI_NOT_FOUND There is not any console devices connected success @retval EFI_SUCCESS Success connect any one instance of the console device path base on the variable ConVarName. **/ EFI_STATUS EFIAPI EfiBootManagerConnectConsoleVariable ( IN CONSOLE_TYPE ConsoleType, IN BOOLEAN NeedDispatch ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *StartDevicePath; UINTN VariableSize; EFI_DEVICE_PATH_PROTOCOL *Instance; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; UINTN Size; BOOLEAN DeviceExist; EFI_HANDLE Handle; if ((ConsoleType != ConIn) && (ConsoleType != ConOut) && (ConsoleType != ErrOut)) { return EFI_INVALID_PARAMETER; } Status = EFI_SUCCESS; DeviceExist = FALSE; // // Check if the console variable exist // StartDevicePath = EfiBootManagerGetVariableAndSize ( mConVarName[ConsoleType], &gEfiGlobalVariableGuid, &VariableSize ); if (StartDevicePath == NULL) { return EFI_UNSUPPORTED; } CopyOfDevicePath = StartDevicePath; do { // // Check every instance of the console variable // Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size); if (Instance == NULL) { FreePool (StartDevicePath); return EFI_UNSUPPORTED; } Next = Instance; while (!IsDevicePathEndType (Next)) { Next = NextDevicePathNode (Next); } SetDevicePathEndNode (Next); // // Connect the USB console // USB console device path is a short-form device path that // starts with the first element being a USB WWID // or a USB Class device path // if (FeaturePcdGet (PcdShortformBootSupport) && (DevicePathType (Instance) == MESSAGING_DEVICE_PATH) && ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP) || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)) ) { Status = EfiBootManagerConnectUsbShortFormDevicePath (Instance); if (!EFI_ERROR (Status)) { DeviceExist = TRUE; } } else { // // Connect the instance device path // Status = ConnectDevicePath (Instance, NeedDispatch, NULL); if (EFI_ERROR (Status)) { // // Do not delete the instance from the console variable if the device path is of GOP type // and the parent controller exists in the system // This is to support the monitor hotplug in a headless boot // for (Next = Instance; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) { if (DevicePathType (Next) == ACPI_DEVICE_PATH && DevicePathSubType (Next) == ACPI_ADR_DP) { break; } } if (!IsDevicePathEnd (Next)) { Next = Instance; Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Next, &Handle); if (!EFI_ERROR (Status) && (DevicePathType (Next) != ACPI_DEVICE_PATH || DevicePathSubType (Next) != ACPI_ADR_DP)) { // // We found the parent controller but it's not the direct parent of the ADR device path instance // which indicates the video controller doesn't exist. // If this happens, we need to delete the invalid device path from ConOut // Status = EFI_NOT_FOUND; } } } else { DeviceExist = TRUE; } if (EFI_ERROR (Status)) { // // Delete the instance from the console variable // EfiBootManagerUpdateConsoleVariable (ConsoleType, NULL, Instance); } } FreePool(Instance); } while (CopyOfDevicePath != NULL); FreePool (StartDevicePath); if ((ConsoleType == ConOut) && FeaturePcdGet (PcdBdsFindDisplay) && !HasLocalDisplay ()) { // // Force to connect local video controller // Backward compatible to old platforms which don't insert the GOP device path to ConOut // DEBUG ((EFI_D_ERROR, "[Bds] Local display isn't found, find & connect it automatically\n")); Status = ConnectVideoController (); if (!EFI_ERROR (Status)) { DeviceExist = TRUE; } } if (!DeviceExist) { return EFI_NOT_FOUND; } return EFI_SUCCESS; }