EFIAPI AppendDevicePathInstanceProtocolInterface ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance ) { return AppendDevicePathInstance (DevicePath, DevicePathInstance); }
STATIC EFI_STATUS SupportedDevicePathsInit ( VOID ) { EFI_STATUS Status; CHAR16* DevicePathListStr; CHAR16* DevicePathStr; CHAR16* NextDevicePathStr; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; EFI_DEVICE_PATH_PROTOCOL *Instance; Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); ASSERT_EFI_ERROR (Status); // Initialize Variable DevicePathListStr = (CHAR16*)PcdGetPtr (PcdBootMonFsSupportedDevicePaths); mBootMonFsSupportedDevicePaths = NULL; // Extract the Device Path instances from the multi-device path string while ((DevicePathListStr != NULL) && (DevicePathListStr[0] != L'\0')) { NextDevicePathStr = StrStr (DevicePathListStr, L";"); if (NextDevicePathStr == NULL) { DevicePathStr = DevicePathListStr; DevicePathListStr = NULL; } else { DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DevicePathListStr + 1) * sizeof (CHAR16), DevicePathListStr); if (DevicePathStr == NULL) { return EFI_OUT_OF_RESOURCES; } *(DevicePathStr + (NextDevicePathStr - DevicePathListStr)) = L'\0'; DevicePathListStr = NextDevicePathStr; if (DevicePathListStr[0] == L';') { DevicePathListStr++; } } Instance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr); ASSERT (Instance != NULL); mBootMonFsSupportedDevicePaths = AppendDevicePathInstance (mBootMonFsSupportedDevicePaths, Instance); if (NextDevicePathStr != NULL) { FreePool (DevicePathStr); } FreePool (Instance); } if (mBootMonFsSupportedDevicePaths == NULL) { return EFI_UNSUPPORTED; } else { return EFI_SUCCESS; } }
/** Connect all the system drivers to controllers and create the network device list in NV storage. @retval EFI_SUCCESS Network devices are connected. @retval EFI_DEVICE_ERROR No network device is connected. **/ EFI_STATUS ConnectAllAndCreateNetworkDeviceList ( VOID ) { EFI_STATUS Status; EFI_HANDLE *Handles; UINTN HandleCount; EFI_DEVICE_PATH_PROTOCOL *SingleDevice; EFI_DEVICE_PATH_PROTOCOL *Devices; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EfiBootManagerConnectAll (); Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiManagedNetworkServiceBindingProtocolGuid, NULL, &HandleCount, &Handles); if (EFI_ERROR (Status)) { Handles = NULL; HandleCount = 0; } Devices = NULL; while (HandleCount-- != 0) { Status = gBS->HandleProtocol (Handles[HandleCount], &gEfiDevicePathProtocolGuid, (VOID **) &SingleDevice); if (EFI_ERROR (Status) || (SingleDevice == NULL)) { continue; } TempDevicePath = Devices; Devices = AppendDevicePathInstance (Devices, SingleDevice); if (TempDevicePath != NULL) { FreePool (TempDevicePath); } } if (Devices != NULL) { Status = gRT->SetVariable ( mNetworkDeviceList, &gEfiCallerIdGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, GetDevicePathSize (Devices), Devices ); // // Fails to save the network device list to NV storage is not a fatal error. // Only impact is performance. // FreePool (Devices); } return (Devices == NULL) ? EFI_DEVICE_ERROR : EFI_SUCCESS; }
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; }
/** This function delete and build multi-instance device path for specified type of console device. This function clear the EFI variable defined by ConsoleName and gEfiGlobalVariableGuid. It then build the multi-instance device path by appending the device path of the Console (In/Out/Err) instance in ConsoleMenu. Then it scan all corresponding console device by scanning Terminal (built from device supporting Serial I/O instances) devices in TerminalMenu. At last, it save a EFI variable specifed by ConsoleName and gEfiGlobalVariableGuid. @param ConsoleName The name for the console device type. They are usually "ConIn", "ConOut" and "ErrOut". @param ConsoleMenu The console memu which is a list of console devices. @param UpdatePageId The flag specifying which type of console device to be processed. @retval EFI_SUCCESS The function complete successfully. @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. **/ EFI_STATUS Var_UpdateConsoleOption ( IN UINT16 *ConsoleName, IN BM_MENU_OPTION *ConsoleMenu, IN UINT16 UpdatePageId ) { EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; BM_MENU_ENTRY *NewMenuEntry; BM_CONSOLE_CONTEXT *NewConsoleContext; BM_TERMINAL_CONTEXT *NewTerminalContext; EFI_STATUS Status; VENDOR_DEVICE_PATH Vendor; EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath; UINTN Index; GetEfiGlobalVariable2 (ConsoleName, (VOID**)&ConDevicePath, NULL); if (ConDevicePath != NULL) { EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid); FreePool (ConDevicePath); ConDevicePath = NULL; }; // // First add all console input device from console input menu // for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; if (NewConsoleContext->IsActive) { ConDevicePath = AppendDevicePathInstance ( ConDevicePath, NewConsoleContext->DevicePath ); } } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) || ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) || ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID)) ) { Vendor.Header.Type = MESSAGING_DEVICE_PATH; Vendor.Header.SubType = MSG_VENDOR_DP; ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0]))); CopyMem ( &Vendor.Guid, &TerminalTypeGuid[NewTerminalContext->TerminalType], sizeof (EFI_GUID) ); SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); TerminalDevicePath = AppendDevicePathNode ( NewTerminalContext->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Vendor ); ASSERT (TerminalDevicePath != NULL); ChangeTerminalDevicePath (TerminalDevicePath, TRUE); ConDevicePath = AppendDevicePathInstance ( ConDevicePath, TerminalDevicePath ); } } if (ConDevicePath != NULL) { Status = gRT->SetVariable ( ConsoleName, &gEfiGlobalVariableGuid, VAR_FLAG, GetDevicePathSize (ConDevicePath), ConDevicePath ); if (EFI_ERROR (Status)) { return Status; } } return EFI_SUCCESS; }
STATIC EFI_STATUS GetConsoleDevicePathFromVariable ( IN CHAR16* ConsoleVarName, IN CHAR16* DefaultConsolePaths, OUT EFI_DEVICE_PATH** DevicePaths ) { EFI_STATUS Status; UINTN Size; EFI_DEVICE_PATH_PROTOCOL* DevicePathInstances; EFI_DEVICE_PATH_PROTOCOL* DevicePathInstance; CHAR16* DevicePathStr; CHAR16* NextDevicePathStr; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; Status = GetGlobalEnvironmentVariable (ConsoleVarName, NULL, NULL, (VOID**)&DevicePathInstances); if (EFI_ERROR(Status)) { // In case no default console device path has been defined we assume a driver handles the console (eg: SimpleTextInOutSerial) if ((DefaultConsolePaths == NULL) || (DefaultConsolePaths[0] == L'\0')) { *DevicePaths = NULL; return EFI_SUCCESS; } Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); ASSERT_EFI_ERROR(Status); DevicePathInstances = NULL; // Extract the Device Path instances from the multi-device path string while ((DefaultConsolePaths != NULL) && (DefaultConsolePaths[0] != L'\0')) { NextDevicePathStr = StrStr (DefaultConsolePaths, L";"); if (NextDevicePathStr == NULL) { DevicePathStr = DefaultConsolePaths; DefaultConsolePaths = NULL; } else { DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DefaultConsolePaths + 1) * sizeof(CHAR16), DefaultConsolePaths); *(DevicePathStr + (NextDevicePathStr - DefaultConsolePaths)) = L'\0'; DefaultConsolePaths = NextDevicePathStr; if (DefaultConsolePaths[0] == L';') { DefaultConsolePaths++; } } DevicePathInstance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr); ASSERT(DevicePathInstance != NULL); DevicePathInstances = AppendDevicePathInstance (DevicePathInstances, DevicePathInstance); if (NextDevicePathStr != NULL) { FreePool (DevicePathStr); } FreePool (DevicePathInstance); } // Set the environment variable with this device path multi-instances Size = GetDevicePathSize (DevicePathInstances); if (Size > 0) { gRT->SetVariable ( ConsoleVarName, &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, Size, DevicePathInstances ); } else { Status = EFI_INVALID_PARAMETER; } } if (!EFI_ERROR(Status)) { *DevicePaths = DevicePathInstances; } return Status; }
/** 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; }
/** This function updates the console variable based on ConVarName. It can add or remove one specific console device path from the variable @param ConsoleType ConIn, ConOut, ErrOut, ConInDev, ConOutDev or ErrOutDev. @param CustomizedConDevicePath The console device path to be added to the console variable. Cannot be multi-instance. @param ExclusiveDevicePath The console device path to be removed from the console variable. Cannot be multi-instance. @retval EFI_UNSUPPORTED The added device path is the same as a removed one. @retval EFI_SUCCESS Successfully added or removed the device path from the console variable. @retval others Return status of RT->SetVariable(). **/ EFI_STATUS EFIAPI EfiBootManagerUpdateConsoleVariable ( IN CONSOLE_TYPE ConsoleType, IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *VarConsole; EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath; if (ConsoleType >= sizeof (mConVarName) / sizeof (mConVarName[0])) { return EFI_INVALID_PARAMETER; } // // 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 // GetEfiGlobalVariable2 (mConVarName[ConsoleType], (VOID **) &VarConsole, NULL); // // 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 = BmDelPartMatchInstance (VarConsole, ExclusiveDevicePath); } // // Try to append customized device path to NewDevicePath. // if (CustomizedConDevicePath != NULL) { if (!BmMatchDevicePaths (NewDevicePath, CustomizedConDevicePath)) { // // Check if there is part of CustomizedConDevicePath in NewDevicePath, delete it. // NewDevicePath = BmDelPartMatchInstance (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); } } } // // Finally, Update the variable of the default console by NewDevicePath // Status = gRT->SetVariable ( mConVarName[ConsoleType], &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | ((ConsoleType < ConInDev) ? EFI_VARIABLE_NON_VOLATILE : 0), GetDevicePathSize (NewDevicePath), NewDevicePath ); if (VarConsole == NewDevicePath) { if (VarConsole != NULL) { FreePool(VarConsole); } } else { if (VarConsole != NULL) { FreePool(VarConsole); } if (NewDevicePath != NULL) { FreePool(NewDevicePath); } } return Status; }
EFIAPI EfiBootManagerGetGopDevicePath ( IN EFI_HANDLE VideoController ) { UINTN Index; EFI_STATUS Status; EFI_GUID **ProtocolBuffer; UINTN ProtocolBufferCount; UINTN ProtocolIndex; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; UINTN EntryCount; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_DEVICE_PATH_PROTOCOL *Previous; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EFI_DEVICE_PATH_PROTOCOL *GopPool; EFI_DEVICE_PATH_PROTOCOL *ReturnDevicePath; Status = gBS->ProtocolsPerHandle ( VideoController, &ProtocolBuffer, &ProtocolBufferCount ); if (EFI_ERROR (Status)) { return NULL; } GopPool = NULL; for (ProtocolIndex = 0; ProtocolIndex < ProtocolBufferCount; ProtocolIndex++) { Status = gBS->OpenProtocolInformation ( VideoController, ProtocolBuffer[ProtocolIndex], &OpenInfoBuffer, &EntryCount ); if (EFI_ERROR (Status)) { continue; } for (Index = 0; Index < EntryCount; Index++) { // // Query all the children // if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { continue; } Previous = NULL; for (Next = DevicePath; !IsDevicePathEnd (Next); Next = NextDevicePathNode (Next)) { Previous = Next; } ASSERT (Previous != NULL); if (DevicePathType (Previous) == ACPI_DEVICE_PATH && DevicePathSubType (Previous) == ACPI_ADR_DP) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiGraphicsOutputProtocolGuid, NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (!EFI_ERROR (Status)) { // // Append the device path to GOP pool when there is GOP protocol installed. // TempDevicePath = GopPool; GopPool = AppendDevicePathInstance (GopPool, DevicePath); gBS->FreePool (TempDevicePath); } } if (DevicePathType (Previous) == HARDWARE_DEVICE_PATH && DevicePathSubType (Previous) == HW_CONTROLLER_DP) { // // Recursively look for GOP child in this frame buffer handle // DEBUG ((EFI_D_INFO, "[Bds] Looking for GOP child deeper ... \n")); TempDevicePath = GopPool; ReturnDevicePath = EfiBootManagerGetGopDevicePath (OpenInfoBuffer[Index].ControllerHandle); GopPool = AppendDevicePathInstance (GopPool, ReturnDevicePath); gBS->FreePool (ReturnDevicePath); gBS->FreePool (TempDevicePath); } } } FreePool (OpenInfoBuffer); } FreePool (ProtocolBuffer); return GopPool; }
EFIAPI EfiBootManagerGetGopDevicePath ( IN EFI_HANDLE VideoController ) { UINTN Index; EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath; EFI_DEVICE_PATH_PROTOCOL *GopPool; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; UINTN EntryCount; ASSERT (VideoController != NULL); GopPool = NULL; Status = gBS->OpenProtocolInformation ( VideoController, &gEfiPciIoProtocolGuid, &OpenInfoBuffer, &EntryCount ); if (EFI_ERROR (Status)) { EntryCount = 0; } for (Index = 0; Index < EntryCount; Index++) { // // Query all the children created by the GOP driver // if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **) &ChildDevicePath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiGraphicsOutputProtocolGuid, NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (!EFI_ERROR (Status)) { // // Append the device path to GOP pool when there is GOP protocol installed. // TempDevicePath = GopPool; GopPool = AppendDevicePathInstance (GopPool, ChildDevicePath); if (TempDevicePath != NULL) { FreePool (TempDevicePath); } } } } } FreePool (OpenInfoBuffer); return GopPool; }