/*++ * @name EfiInitpGetDeviceNode * * The EfiInitpGetDeviceNode routine * * @param DevicePath * UEFI Image Handle for the current loaded application. * * @return None * *--*/ EFI_DEVICE_PATH_PROTOCOL* EfiInitpGetDeviceNode ( _In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_DEVICE_PATH_PROTOCOL* NextPath; /* Check if we hit the end terminator */ if (IsDevicePathEndType(DevicePath)) { return DevicePath; } /* Loop each device path, until we get to the end or to a file path device node */ for ((NextPath = NextDevicePathNode(DevicePath)); !(IsDevicePathEndType(NextPath)) && ((NextPath->Type != MEDIA_DEVICE_PATH) || (NextPath->SubType != MEDIA_FILEPATH_DP)); (NextPath = NextDevicePathNode(NextPath))) { /* Keep iterating down */ DevicePath = NextPath; } /* Return the path found */ return DevicePath; }
/* Currently this function is useless */ void GetFilePathList(BDS_LOAD_OPTION* BdsLoadOption, char* buffer, int descSize) { if (BdsLoadOption->FilePathListLength <= 0) return; EFI_DEVICE_PATH_PROTOCOL* DevicePathNode = BdsLoadOption->FilePathList; // File path fields DevicePathNode = BdsLoadOption->FilePathList; if (DevicePathType(DevicePathNode) != MEDIA_DEVICE_PATH_TYPE) return; while (!IsDevicePathEndType(DevicePathNode)) { switch (DevicePathSubType(DevicePathNode)) { case HARDDRIVE_SUBTYPE: printf("HDD"); break; case FILE_PATH_SUBTYPE: printf("FILE"); break; } DevicePathNode = NextDevicePathNode(DevicePathNode); } }
EFI_DEVICE_PATH * DevicePathInstance ( IN OUT EFI_DEVICE_PATH **DevicePath, OUT UINTN *Size ) { EFI_DEVICE_PATH *Start, *Next, *DevPath; UINTN Count; DevPath = *DevicePath; Start = DevPath; if (!DevPath) { return NULL; } // // Check for end of device path type // for (Count = 0; ; Count++) { Next = NextDevicePathNode(DevPath); if (IsDevicePathEndType(DevPath)) { break; } if (Count > 01000) { // // BugBug: Debug code to catch bogus device paths // DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) )); DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start); break; } DevPath = Next; } ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE || DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE); // // Set next position // if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { Next = NULL; } *DevicePath = Next; // // Return size and start of device path instance // *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start); return Start; }
/** Determines if a device path node is an end node of a device path instance. Determines if a device path node specified by Node is an end node of a device path instance. If Node represents the end of a device path instance, then TRUE is returned. Otherwise, FALSE is returned. If Node is NULL, then ASSERT(). @param Node A pointer to a device path node data structure. @retval TRUE The device path node specified by Node is the end of a device path instance. @retval FALSE The device path node specified by Node is not the end of a device path instance. **/ BOOLEAN EFIAPI IsDevicePathEndInstance ( IN CONST VOID *Node ) { ASSERT (Node != NULL); return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE); }
static NVME_NAMESPACE_DEVICE_PATH *get_nvme_device_path(EFI_DEVICE_PATH *p) { for (; !IsDevicePathEndType(p); p = NextDevicePathNode(p)) { if (DevicePathType(p) == MESSAGING_DEVICE_PATH && DevicePathSubType(p) == MSG_NVME_NAMESPACE_DP) return (NVME_NAMESPACE_DEVICE_PATH *)p; } return NULL; }
PCI_DEVICE_PATH* get_pci_device_path(EFI_DEVICE_PATH *p) { while (!IsDevicePathEndType(p)) { if (DevicePathType(p) == HARDWARE_DEVICE_PATH && DevicePathSubType(p) == HW_PCI_DP) return (PCI_DEVICE_PATH *)p; p = NextDevicePathNode(p); } return NULL; }
EFIAPI GetNextDevicePathInstance ( IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT UINTN *Size ) { EFI_DEVICE_PATH_PROTOCOL *DevPath; EFI_DEVICE_PATH_PROTOCOL *ReturnValue; UINT8 Temp; ASSERT (Size != NULL); if (DevicePath == NULL || *DevicePath == NULL) { *Size = 0; return NULL; } if (!IsDevicePathValid (*DevicePath, 0)) { return NULL; } // // Find the end of the device path instance // DevPath = *DevicePath; while (!IsDevicePathEndType (DevPath)) { DevPath = NextDevicePathNode (DevPath); } // // Compute the size of the device path instance // *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); // // Make a copy and return the device path instance // Temp = DevPath->SubType; DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; ReturnValue = DuplicateDevicePath (*DevicePath); DevPath->SubType = Temp; // // If DevPath is the end of an entire device path, then another instance // does not follow, so *DevicePath is set to NULL. // if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { *DevicePath = NULL; } else { *DevicePath = NextDevicePathNode (DevPath); } return ReturnValue; }
// Return the last non end-type Device Path Node from a Device Path EFI_DEVICE_PATH* GetLastDevicePathNode ( IN EFI_DEVICE_PATH* DevicePath ) { EFI_DEVICE_PATH* PrevDevicePathNode; PrevDevicePathNode = DevicePath; while (!IsDevicePathEndType (DevicePath)) { PrevDevicePathNode = DevicePath; DevicePath = NextDevicePathNode (DevicePath); } return PrevDevicePathNode; }
BOOLEAN IsNodeInDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *Node, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_DEVICE_PATH_PROTOCOL *DevPath; UINTN Length; DevPath = DevicePath; while (!IsDevicePathEndType (DevPath)) { Length = (UINTN)(DevPath->Length[1] << 8 | DevPath->Length[0]); if (!CompareMem (DevPath, Node, Length)) { return TRUE; } DevPath = NextDevicePathNode (DevPath); } 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; }
EFI_DEVICE_PATH_PROTOCOL * DevicePathInstance ( IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT UINTN *Size ) /*++ Routine Description: Function retrieves the next device path instance from a device path data structure. Arguments: DevicePath - A pointer to a device path data structure. Size - A pointer to the size of a device path instance in bytes. Returns: This function returns a pointer to the current device path instance. In addition, it returns the size in bytes of the current device path instance in Size, and a pointer to the next device path instance in DevicePath. If there are no more device path instances in DevicePath, then DevicePath will be set to NULL. --*/ { EFI_DEVICE_PATH_PROTOCOL *Start, *Next, *DevPath; UINTN Count; DevPath = *DevicePath; Start = DevPath; if (!DevPath) { return NULL; } // // Check for end of device path type // for (Count = 0; ; Count++) { Next = NextDevicePathNode(DevPath); if (IsDevicePathEndType(DevPath)) { break; } if (Count > 01000) { // // BugBug: Debug code to catch bogus device paths // DEBUG((EFI_D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) )); DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start); break; } DevPath = Next; } ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE || DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE); // // Set next position // if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { Next = NULL; } *DevicePath = Next; // // Return size and start of device path instance // *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL); return Start; }
EFI_STATUS BdsLoadOptionMemMapList ( IN OUT LIST_ENTRY* BdsLoadOptionList ) { EFI_STATUS Status; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINTN DevicePathHandleCount; EFI_HANDLE *DevicePathHandleBuffer; BOOLEAN IsParent; UINTN Index; UINTN Index2; BDS_SUPPORTED_DEVICE *SupportedDevice; EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; EFI_DEVICE_PATH* DevicePath; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileProtocol; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; // List all the BlockIo Protocols Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { return Status; } for (Index = 0; Index < HandleCount; Index++) { // We only select handles WITH a Device Path AND not part of Media (to // avoid duplication with HardDisk, CDROM, etc). Skip handles used by // Simple Filesystem or used for Variable Storage. Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID *)&FileProtocol); if (!EFI_ERROR(Status)) { // SimpleFilesystem supported on this handle, skip continue; } Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiFirmwareVolumeBlockProtocolGuid, (VOID *)&FvbProtocol); if (!EFI_ERROR(Status)) { // Firmware Volme Block / Variable storage supported on this handle, skip continue; } Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiFirmwareVolumeBlock2ProtocolGuid, (VOID *)&FvbProtocol); if (!EFI_ERROR(Status)) { // Firmware Volme Block / Variable storage supported on this handle, skip continue; } Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); if (!EFI_ERROR(Status)) { // BlockIo is not part of Media Device Path DevicePath = DevicePathProtocol; while (!IsDevicePathEndType (DevicePath) && (DevicePathType (DevicePath) != MEDIA_DEVICE_PATH)) { DevicePath = NextDevicePathNode (DevicePath); } if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) { continue; } // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &DevicePathHandleCount, &DevicePathHandleBuffer); ASSERT_EFI_ERROR (Status); IsParent = FALSE; for (Index2 = 0; (Index2 < DevicePathHandleCount) && !IsParent; Index2++) { if (HandleBuffer[Index] != DevicePathHandleBuffer[Index2]) { gBS->HandleProtocol (DevicePathHandleBuffer[Index2], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath); if (IsParentDevicePath (DevicePathProtocol, DevicePath)) { IsParent = TRUE; } } } if (IsParent) { continue; } // Allocate BDS Supported Device structure SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE)); Status = GenerateDeviceDescriptionName (HandleBuffer[Index], SupportedDevice->Description); ASSERT_EFI_ERROR (Status); if(NULL != SupportedDevice) { SupportedDevice->DevicePathProtocol = DevicePathProtocol; SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_MEMMAP]; } InsertTailList (BdsLoadOptionList,&SupportedDevice->Link); } } return EFI_SUCCESS; }
/* Initialise: Open the Android NVM device and find the partitions on it. Save them in a list along with the "PartitionName" fields for their GPT entries. We will use these partition names as the key in ArmFastbootPlatformFlashPartition. */ EFI_STATUS ArmFastbootPlatformInit ( VOID ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *NextNode; HARDDRIVE_DEVICE_PATH *PartitionNode; UINTN NumHandles; EFI_HANDLE *AllHandles; UINTN LoopIndex; EFI_HANDLE FlashHandle; EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; EFI_PARTITION_ENTRY *PartitionEntries; FASTBOOT_PARTITION_LIST *Entry; InitializeListHead (&mPartitionListHead); // // Get EFI_HANDLES for all the partitions on the block devices pointed to by // PcdFastbootFlashDevicePath, also saving their GPT partition labels. // There's no way to find all of a device's children, so we get every handle // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones // that don't represent partitions on the flash device. // FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath)); // // Open the Disk IO protocol on the flash device - this will be used to read // partition names out of the GPT entries // // Create another device path pointer because LocateDevicePath will modify it. FlashDevicePathDup = FlashDevicePath; Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &FlashHandle); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status)); // Failing to locate partitions should not prevent to do other Android FastBoot actions return EFI_SUCCESS; } Status = gBS->OpenProtocol ( FlashHandle, &gEfiBlockIoProtocolGuid, (VOID **) &FlashBlockIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status)); return EFI_DEVICE_ERROR; } // Read the GPT partition entry array into memory so we can get the partition names Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status)); // Failing to locate partitions should not prevent to do other Android FastBoot actions return EFI_SUCCESS; } // Get every Block IO protocol instance installed in the system Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &NumHandles, &AllHandles ); ASSERT_EFI_ERROR (Status); // Filter out handles that aren't children of the flash device for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) { // Get the device path for the handle Status = gBS->OpenProtocol ( AllHandles[LoopIndex], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); ASSERT_EFI_ERROR (Status); // Check if it is a sub-device of the flash device if (!CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { // Device path starts with path of flash device. Check it isn't the flash // device itself. NextNode = NextDevicePathNode (DevicePath); if (IsDevicePathEndType (NextNode)) { continue; } // Assert that this device path node represents a partition. ASSERT (NextNode->Type == MEDIA_DEVICE_PATH && NextNode->SubType == MEDIA_HARDDRIVE_DP); PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode; // Assert that the partition type is GPT. ReadPartitionEntries checks for // presence of a GPT, so we should never find MBR partitions. // ("MBRType" is a misnomer - this field is actually called "Partition // Format") ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER); // The firmware may install a handle for "partition 0", representing the // whole device. Ignore it. if (PartitionNode->PartitionNumber == 0) { continue; } // // Add the partition handle to the list // // Create entry Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); if (Entry == NULL) { Status = EFI_OUT_OF_RESOURCES; FreePartitionList (); goto Exit; } // Copy handle and partition name Entry->PartitionHandle = AllHandles[LoopIndex]; StrnCpy ( Entry->PartitionName, PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1. PARTITION_NAME_MAX_LENGTH ); InsertTailList (&mPartitionListHead, &Entry->Link); // Print a debug message if the partition label is empty or looks like // garbage. if (!IS_ALPHA (Entry->PartitionName[0])) { DEBUG ((EFI_D_ERROR, "Warning: Partition %d doesn't seem to have a GPT partition label. " "You won't be able to flash it with Fastboot.\n", PartitionNode->PartitionNumber )); } } } Exit: FreePool (PartitionEntries); FreePool (FlashDevicePath); FreePool (AllHandles); return Status; }
/** 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; }
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; }
/** Get a human readable name for an image handle. The following methods will be tried orderly: 1. Image PDB 2. ComponentName2 protocol 3. FFS UI section 4. Image GUID 5. Image DevicePath 6. Unknown Driver Name @param[in] Handle @post The resulting Unicode name string is stored in the mGaugeString global array. **/ VOID DpGetNameFromHandle ( IN EFI_HANDLE Handle ) { EFI_STATUS Status; EFI_LOADED_IMAGE_PROTOCOL *Image; CHAR8 *PdbFileName; EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; EFI_STRING StringPtr; EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_GUID *NameGuid; CHAR16 *NameString; UINTN StringSize; CHAR8 *PlatformLanguage; EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2; Image = NULL; LoadedImageDevicePath = NULL; DevicePath = NULL; // // Method 1: Get the name string from image PDB // Status = gBS->HandleProtocol ( Handle, &gEfiLoadedImageProtocolGuid, (VOID **) &Image ); if (EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( Handle, &gEfiDriverBindingProtocolGuid, (VOID **) &DriverBinding, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { Status = gBS->HandleProtocol ( DriverBinding->ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &Image ); } } if (!EFI_ERROR (Status)) { PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase); if (PdbFileName != NULL) { DpGetShortPdbFileName (PdbFileName, mGaugeString); return; } } // // Method 2: Get the name string from ComponentName2 protocol // Status = gBS->HandleProtocol ( Handle, &gEfiComponentName2ProtocolGuid, (VOID **) &ComponentName2 ); if (!EFI_ERROR (Status)) { // // Get the current platform language setting // PlatformLanguage = GetBestLanguageForDriver(ComponentName2->SupportedLanguages, NULL, FALSE); Status = ComponentName2->GetDriverName ( ComponentName2, PlatformLanguage != NULL ? PlatformLanguage : "en-US", &StringPtr ); if (!EFI_ERROR (Status)) { SHELL_FREE_NON_NULL (PlatformLanguage); StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH); mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; return; } } Status = gBS->HandleProtocol ( Handle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &LoadedImageDevicePath ); if (!EFI_ERROR (Status) && (LoadedImageDevicePath != NULL)) { DevicePath = LoadedImageDevicePath; } else if (Image != NULL) { DevicePath = Image->FilePath; } if (DevicePath != NULL) { // // Try to get image GUID from image DevicePath // NameGuid = NULL; while (!IsDevicePathEndType (DevicePath)) { NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath); if (NameGuid != NULL) { break; } DevicePath = NextDevicePathNode (DevicePath); } if (NameGuid != NULL) { // // Try to get the image's FFS UI section by image GUID // NameString = NULL; StringSize = 0; Status = GetSectionFromAnyFv ( NameGuid, EFI_SECTION_USER_INTERFACE, 0, (VOID **) &NameString, &StringSize ); if (!EFI_ERROR (Status)) { // // Method 3. Get the name string from FFS UI section // StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH); mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; FreePool (NameString); } else { // // Method 4: Get the name string from image GUID // UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", NameGuid); } return; } else { // // Method 5: Get the name string from image DevicePath // NameString = ConvertDevicePathToText (DevicePath, TRUE, FALSE); if (NameString != NULL) { StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH); mGaugeString[DP_GAUGE_STRING_LENGTH] = 0; FreePool (NameString); return; } } } // // Method 6: Unknown Driver Name // StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL); ASSERT (StringPtr != NULL); StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH); FreePool (StringPtr); }
BOOL ValidateBootEntry(UINT8* buffer) { //char buffer[512]; //Block of bytes BDS_LOAD_OPTION* pBootEntry; if (!buffer) return FALSE; //Alocate New BootDevice pBootEntry = (BDS_LOAD_OPTION*)calloc(1, sizeof(BDS_LOAD_OPTION)); if (!pBootEntry) return FALSE; //Get Attributes pBootEntry->Attributes = GET_ATTRIBUTES(buffer); //Get FilePathListLength pBootEntry->FilePathListLength = GET_FILELISTLENGTH(buffer); //Get Description int descSize = wstrlen((WCHAR*)DESCRIPTION_OFFSET(buffer));// GET_DESCRIPTION_LENGTH(buffer); if (descSize == 0) return FALSE; pBootEntry->Description = ALLOCATE_WCHAR_STRING(descSize); if (pBootEntry->Description == NULL) return FALSE; memcpy(pBootEntry->Description, DESCRIPTION_OFFSET(buffer), descSize); //Get FilePathList pBootEntry->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)calloc(1, pBootEntry->FilePathListLength); if (pBootEntry->FilePathList == NULL) return FALSE; memcpy(pBootEntry->FilePathList, (EFI_DEVICE_PATH_PROTOCOL*)(DESCRIPTION_OFFSET(buffer) + descSize), pBootEntry->FilePathListLength); //Read FilePathList //GetFilePathList(pBootEntry, buffer, descSize); if (pBootEntry->FilePathListLength <= 0) return FALSE; EFI_DEVICE_PATH_PROTOCOL* DevicePathNode = pBootEntry->FilePathList; // File path fields DevicePathNode = pBootEntry->FilePathList; if (DevicePathType(DevicePathNode) != MEDIA_DEVICE_PATH_TYPE) return FALSE; while (!IsDevicePathEndType(DevicePathNode)) { DevicePathNode = NextDevicePathNode(DevicePathNode); } GUID* pG; while (!IsDevicePathEndType(DevicePathNode)) { if (DevicePathNode->Type != 0x7F) if (DevicePathNode->Type < 0x01 || DevicePathNode->Type > 0x05) { return FALSE; } switch (DevicePathSubType(DevicePathNode)) { case HARDDRIVE_SUBTYPE: HARDDRIVE_DEVICE_PATH* hd; hd = (HARDDRIVE_DEVICE_PATH *)DevicePathNode; #if 0 wprintf(L"\t PartitionFormat:%d\n", hd->PartitionFormat); wprintf(L"\t Partition No:%d\n", hd->PartitionNumber); wprintf(L"\t Partition Size:%d\n", hd->PartitionSize); wprintf(L"\t Partition Start:%d\n", hd->PartitionStart); wprintf(L"\t Signature type:%d\n", hd->SignatureType); pG = (GUID*)&hd->Signature; LPOLESTR xds; _GUID y; StringFromCLSID(*pG, &xds); wprintf(L"\t Partition Signature:%s\n", xds); #endif break; case FILE_PATH_SUBTYPE: FILEPATH_DEVICE_PATH* f; f = (FILEPATH_DEVICE_PATH*)DevicePathNode; #if 0 wprintf(L"\t PathName:%s\n", f->PathName); #endif break; } DevicePathNode = NextDevicePathNode(DevicePathNode); } return TRUE; }
/** For a bootable Device path, return its boot type. @param DevicePath The bootable device Path to check @retval AcpiFloppyBoot If given device path contains ACPI_DEVICE_PATH type device path node which HID is floppy device. @retval MessageAtapiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node and its last device path node's subtype is MSG_ATAPI_DP. @retval MessageSataBoot If given device path contains MESSAGING_DEVICE_PATH type device path node and its last device path node's subtype is MSG_SATA_DP. @retval MessageScsiBoot If given device path contains MESSAGING_DEVICE_PATH type device path node and its last device path node's subtype is MSG_SCSI_DP. @retval MessageUsbBoot If given device path contains MESSAGING_DEVICE_PATH type device path node and its last device path node's subtype is MSG_USB_DP. @retval BmMiscBoot If tiven device path doesn't match the above condition. **/ BM_BOOT_TYPE BmDevicePathType ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_DEVICE_PATH_PROTOCOL *Node; EFI_DEVICE_PATH_PROTOCOL *NextNode; ASSERT (DevicePath != NULL); for (Node = DevicePath; !IsDevicePathEndType (Node); Node = NextDevicePathNode (Node)) { switch (DevicePathType (Node)) { case ACPI_DEVICE_PATH: if (EISA_ID_TO_NUM (((ACPI_HID_DEVICE_PATH *) Node)->HID) == 0x0604) { return BmAcpiFloppyBoot; } break; case HARDWARE_DEVICE_PATH: if (DevicePathSubType (Node) == HW_CONTROLLER_DP) { return BmHardwareDeviceBoot; } break; case MESSAGING_DEVICE_PATH: // // Skip LUN device node // NextNode = Node; do { NextNode = NextDevicePathNode (NextNode); } while ( (DevicePathType (NextNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType(NextNode) == MSG_DEVICE_LOGICAL_UNIT_DP) ); // // If the device path not only point to driver device, it is not a messaging device path, // if (!IsDevicePathEndType (NextNode)) { continue; } switch (DevicePathSubType (Node)) { case MSG_ATAPI_DP: return BmMessageAtapiBoot; break; case MSG_SATA_DP: return BmMessageSataBoot; break; case MSG_USB_DP: return BmMessageUsbBoot; break; case MSG_SCSI_DP: return BmMessageScsiBoot; break; } } } return BmMiscBoot; }
/** 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; }
/*++ * @name EfiInitpConvertEfiDevicePath * * The EfiInitpConvertEfiDevicePath routine * * @param DevicePath * UEFI Image Handle for the current loaded application. * * @param DeviceType * Pointer to the UEFI System Table. * * @param Option * Pointer to the UEFI System Table. * * @param MaximumLength * Pointer to the UEFI System Table. * * @return None * *--*/ NTSTATUS EfiInitpConvertEfiFilePath ( _In_ EFI_DEVICE_PATH_PROTOCOL *DevicePath, _In_ ULONG PathType, _In_ PBL_BCD_OPTION Option, _In_ ULONG MaximumLength ) { ULONG BytesAppended, DataSize, StringLength; PWCHAR StringEntry, PathString; FILEPATH_DEVICE_PATH *FilePath; NTSTATUS Status; /* Make sure we have enough space for the option */ if (MaximumLength < sizeof(*Option)) { return STATUS_INVALID_PARAMETER; } /* Set the initial size of the option, and consume from our buffer */ DataSize = sizeof(*Option); MaximumLength -= sizeof(*Option); /* Zero out and fill the option header */ RtlZeroMemory(Option, DataSize); Option->Type = PathType; Option->DataOffset = sizeof(*Option); /* Extract the string option */ StringEntry = (PWCHAR)(Option + 1); PathString = StringEntry; /* Start parsing the device path */ FilePath = (FILEPATH_DEVICE_PATH*)DevicePath; while (IsDevicePathEndType(FilePath) == FALSE) { /* Is this a file path? */ if ((FilePath->Header.Type == MEDIA_DEVICE_PATH) && (FilePath->Header.SubType == MEDIA_FILEPATH_DP)) { /* Get the length of the file path string, avoiding overflow */ StringLength = DevicePathNodeLength(FilePath) - FIELD_OFFSET(FILEPATH_DEVICE_PATH, PathName); if (StringLength < (ULONG)FIELD_OFFSET(FILEPATH_DEVICE_PATH, PathName)) { Status = STATUS_INTEGER_OVERFLOW; goto Quickie; } /* Append this path string to the current path string */ Status = EfiInitpAppendPathString(PathString, MaximumLength, FilePath->PathName, StringLength, &BytesAppended); if (!NT_SUCCESS(Status)) { return Status; } /* Increase the size of the data, consume buffer space */ DataSize += BytesAppended; MaximumLength -= BytesAppended; /* Move to the next path string */ PathString = (PWCHAR)((ULONG_PTR)PathString + BytesAppended); } /* Move to the next path node */ FilePath = (FILEPATH_DEVICE_PATH*)NextDevicePathNode(FilePath); } /* Check if we still have space for a NULL-terminator */ if (MaximumLength < sizeof(UNICODE_NULL)) { Status = STATUS_INVALID_PARAMETER; goto Quickie; } /* We do -- NULL-terminate the string */ *PathString = UNICODE_NULL; DataSize += sizeof(UNICODE_NULL); /* Check if all of this has amounted to a single NULL-char */ if (PathString == StringEntry) { /* Then this option is empty */ Option->Empty = TRUE; } /* Set the final size of the option */ Option->DataSize = DataSize; Quickie: return STATUS_SUCCESS; }
/** Get the image type. @param[in] File This is a pointer to the device path of the file that is being dispatched. @return UINT32 Image Type **/ UINT32 GetFileType ( IN CONST EFI_DEVICE_PATH_PROTOCOL *File ) { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; EFI_BLOCK_IO_PROTOCOL *BlockIo; // // First check to see if File is from a Firmware Volume // DeviceHandle = NULL; TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File; Status = gBS->LocateDevicePath ( &gEfiFirmwareVolume2ProtocolGuid, &TempDevicePath, &DeviceHandle ); if (!EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( DeviceHandle, &gEfiFirmwareVolume2ProtocolGuid, NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (!EFI_ERROR (Status)) { return IMAGE_FROM_FV; } } // // Next check to see if File is from a Block I/O device // DeviceHandle = NULL; TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File; Status = gBS->LocateDevicePath ( &gEfiBlockIoProtocolGuid, &TempDevicePath, &DeviceHandle ); if (!EFI_ERROR (Status)) { BlockIo = NULL; Status = gBS->OpenProtocol ( DeviceHandle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status) && BlockIo != NULL) { if (BlockIo->Media != NULL) { if (BlockIo->Media->RemovableMedia) { // // Block I/O is present and specifies the media is removable // return IMAGE_FROM_REMOVABLE_MEDIA; } else { // // Block I/O is present and specifies the media is not removable // return IMAGE_FROM_FIXED_MEDIA; } } } } // // File is not in a Firmware Volume or on a Block I/O device, so check to see if // the device path supports the Simple File System Protocol. // DeviceHandle = NULL; TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File; Status = gBS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &TempDevicePath, &DeviceHandle ); if (!EFI_ERROR (Status)) { // // Simple File System is present without Block I/O, so assume media is fixed. // return IMAGE_FROM_FIXED_MEDIA; } // // File is not from an FV, Block I/O or Simple File System, so the only options // left are a PCI Option ROM and a Load File Protocol such as a PXE Boot from a NIC. // TempDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)File; while (!IsDevicePathEndType (TempDevicePath)) { switch (DevicePathType (TempDevicePath)) { case MEDIA_DEVICE_PATH: if (DevicePathSubType (TempDevicePath) == MEDIA_RELATIVE_OFFSET_RANGE_DP) { return IMAGE_FROM_OPTION_ROM; } break; case MESSAGING_DEVICE_PATH: if (DevicePathSubType(TempDevicePath) == MSG_MAC_ADDR_DP) { return IMAGE_FROM_REMOVABLE_MEDIA; } break; default: break; } TempDevicePath = NextDevicePathNode (TempDevicePath); } return IMAGE_UNKNOWN; }
/** 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; } }