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; BM_TERMINAL_CONTEXT *NewTerminalContext; TYPE_OF_TERMINAL Terminal; BM_MENU_ENTRY *NewTerminalMenuEntry; 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 Out Devices // MultiDevicePath = AllDevicePath; Index2 = 0; for (Index = 0; Index < AllCount; Index++) { DevicePathInst = EfiDevicePathInstance (&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 = DevicePathInstanceDup (DevicePathInst); 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 ); NewTerminalMenuEntry = NULL; NewTerminalContext = NULL; if (NewConsoleContext->IsTerminal) { BOpt_DestroyMenuEntry (NewMenuEntry); } else { Index2++; ConsoleMenu->MenuNumber++; InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); } } return EFI_SUCCESS; }
/** Build a list containing all serial devices. @retval EFI_SUCCESS The function complete successfully. @retval EFI_UNSUPPORTED No serial ports present. **/ EFI_STATUS LocateSerialIo ( VOID ) { UINTN Index; UINTN Index2; UINTN NoHandles; EFI_HANDLE *Handles; EFI_STATUS Status; ACPI_HID_DEVICE_PATH *Acpi; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_SERIAL_IO_PROTOCOL *SerialIo; EFI_DEVICE_PATH_PROTOCOL *Node; 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; UINT32 FlowControl; // // 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, (VOID **) &DevicePath ); Acpi = NULL; for (Node = DevicePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) { if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { break; } // // Acpi points to the node before Uart node // Acpi = (ACPI_HID_DEVICE_PATH *) Node; } if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); if (NewMenuEntry == NULL) { FreePool (Handles); return EFI_OUT_OF_RESOURCES; } NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); NewTerminalContext->DevicePath = DuplicateDevicePath (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, (VOID **) &SerialIo ); CopyMem ( &NewTerminalContext->BaudRate, &SerialIo->Mode->BaudRate, sizeof (UINT64) ); CopyMem ( &NewTerminalContext->DataBits, &SerialIo->Mode->DataBits, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->Parity, &SerialIo->Mode->Parity, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->StopBits, &SerialIo->Mode->StopBits, sizeof (UINT8) ); NewTerminalContext->FlowControl = 0; SerialIo->GetControl(SerialIo, &FlowControl); if ((FlowControl & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) != 0) { NewTerminalContext->FlowControl = UART_FLOW_CONTROL_HARDWARE; } InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); TerminalMenu.MenuNumber++; } } if (Handles != NULL) { FreePool (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 != NULL) { UpdateComAttributeFromVariable (OutDevicePath); } if (InpDevicePath != NULL) { UpdateComAttributeFromVariable (InpDevicePath); } if (ErrDevicePath != NULL) { 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++) { CopyMem (&Vendor.Guid, &TerminalTypeGuid[Index2], sizeof (EFI_GUID)); SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); NewDevicePath = AppendDevicePathNode ( NewTerminalContext->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Vendor ); if (NewMenuEntry->HelpString != NULL) { FreePool (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; }
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; }
/** This function update console variable based on ConVarName, it can add or remove one specific console device path from the variable @param ConVarName Console related variable name, ConIn, ConOut, ErrOut. @param CustomizedConDevicePath The console device path which will be added to the console variable ConVarName, this parameter can not be multi-instance. @param ExclusiveDevicePath The console device path which will be removed from the console variable ConVarName, this parameter can not be multi-instance. @retval EFI_UNSUPPORTED The added device path is same to the removed one. @retval EFI_SUCCESS Success add or remove the device path from the console variable. **/ EFI_STATUS EFIAPI BdsLibUpdateConsoleVariable ( IN CHAR16 *ConVarName, IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *VarConsole; UINTN DevicePathSize; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath; UINT32 Attributes; VarConsole = NULL; DevicePathSize = 0; // // Notes: check the device path point, here should check // with compare memory // if (CustomizedConDevicePath == ExclusiveDevicePath) { return EFI_UNSUPPORTED; } // // Delete the ExclusiveDevicePath from current default console // VarConsole = BdsLibGetVariableAndSize ( ConVarName, &gEfiGlobalVariableGuid, &DevicePathSize ); // // Initialize NewDevicePath // NewDevicePath = VarConsole; // // If ExclusiveDevicePath is even the part of the instance in VarConsole, delete it. // In the end, NewDevicePath is the final device path. // if (ExclusiveDevicePath != NULL && VarConsole != NULL) { NewDevicePath = BdsLibDelPartMatchInstance (VarConsole, ExclusiveDevicePath); } // // Try to append customized device path to NewDevicePath. // if (CustomizedConDevicePath != NULL) { if (!BdsLibMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) { // // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it. // NewDevicePath = BdsLibDelPartMatchInstance (NewDevicePath, CustomizedConDevicePath); // // In the first check, the default console variable will be _ModuleEntryPoint, // just append current customized device path // TempNewDevicePath = NewDevicePath; NewDevicePath = AppendDevicePathInstance (NewDevicePath, CustomizedConDevicePath); if (TempNewDevicePath != NULL) { FreePool(TempNewDevicePath); } } } // // The attribute for ConInDev, ConOutDev and ErrOutDev does not include NV. // if (IsNvNeed(ConVarName)) { // // ConVarName has NV attribute. // Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE; } else { // // ConVarName does not have NV attribute. // Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; } // // Finally, Update the variable of the default console by NewDevicePath // DevicePathSize = GetDevicePathSize (NewDevicePath); Status = SetVariableAndReportStatusCodeOnError ( ConVarName, &gEfiGlobalVariableGuid, Attributes, DevicePathSize, NewDevicePath ); if ((DevicePathSize == 0) && (Status == EFI_NOT_FOUND)) { Status = EFI_SUCCESS; } if (VarConsole == NewDevicePath) { if (VarConsole != NULL) { FreePool(VarConsole); } } else { if (VarConsole != NULL) { FreePool(VarConsole); } if (NewDevicePath != NULL) { FreePool(NewDevicePath); } } return Status; }