BOOLEAN DevicePathIsChildDevice ( IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, IN EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath ) { if (ParentDevicePath == NULL || ParentDevicePath == NULL) { return FALSE; } while (!(IsDevicePathEnd (ParentDevicePath) || IsDevicePathEnd (ChildDevicePath))) { if (_DevPathCompareDefault (ParentDevicePath, ChildDevicePath) != 0) { return FALSE; } ParentDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (ParentDevicePath); ChildDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (ChildDevicePath); } if (IsDevicePathEnd (ParentDevicePath)) { return TRUE; } return FALSE; }
EFI_STATUS JudgeHandleIsPCIDevice( EFI_HANDLE Handle, UINT8 Device, UINT8 Funs ) { EFI_STATUS Status; EFI_DEVICE_PATH *DPath; EFI_DEVICE_PATH *DevicePath; Status = gBS->HandleProtocol ( Handle, &gEfiDevicePathProtocolGuid, (VOID **) &DPath ); if(!EFI_ERROR(Status)) { DevicePath = DPath; while(!IsDevicePathEnd(DPath)) { if((DPath->Type == HARDWARE_DEVICE_PATH) && (DPath->SubType == HW_PCI_DP)) { PCI_DEVICE_PATH *PCIPath; PCIPath = (PCI_DEVICE_PATH*) DPath; DPath = NextDevicePathNode(DPath); if(IsDevicePathEnd(DPath) && (PCIPath->Device == Device) && (PCIPath->Function == Funs)) { return EFI_SUCCESS; } } else { DPath = NextDevicePathNode(DPath); } } } return EFI_UNSUPPORTED; }
/*++ * @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; }
EFI_DEVICE_PATH * UnpackDevicePath ( IN EFI_DEVICE_PATH *DevPath ) { EFI_DEVICE_PATH *Src, *Dest, *NewPath; UINTN Size; // // Walk device path and round sizes to valid boundries // Src = DevPath; Size = 0; for (; ;) { Size += DevicePathNodeLength(Src); Size += ALIGN_SIZE(Size); if (IsDevicePathEnd(Src)) { break; } Src = NextDevicePathNode(Src); } // // Allocate space for the unpacked path // NewPath = AllocateZeroPool (Size); if (NewPath) { ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0); // // Copy each node // Src = DevPath; Dest = NewPath; for (; ;) { Size = DevicePathNodeLength(Src); CopyMem (Dest, Src, Size); Size += ALIGN_SIZE(Size); SetDevicePathNodeLength (Dest, Size); Dest->Type |= EFI_DP_TYPE_UNPACKED; Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size); if (IsDevicePathEnd(Src)) { break; } Src = NextDevicePathNode(Src); } } return NewPath; }
/** Update the device path that describing a terminal device based on the new BaudRate, Data Bits, parity and Stop Bits set. @param DevicePath terminal device's path **/ VOID ChangeVariableDevicePath ( IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_DEVICE_PATH_PROTOCOL *Node; ACPI_HID_DEVICE_PATH *Acpi; UART_DEVICE_PATH *Uart; UINTN Com; BM_TERMINAL_CONTEXT *NewTerminalContext; BM_MENU_ENTRY *NewMenuEntry; Node = DevicePath; Node = NextDevicePathNode (Node); Com = 0; while (!IsDevicePathEnd (Node)) { Acpi = (ACPI_HID_DEVICE_PATH *) Node; if (IsIsaSerialNode (Acpi)) { CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); } if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { NewMenuEntry = BOpt_GetMenuEntry ( &TerminalMenu, Com ); ASSERT (NewMenuEntry != NULL); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; Uart = (UART_DEVICE_PATH *) Node; CopyMem ( &Uart->BaudRate, &NewTerminalContext->BaudRate, sizeof (UINT64) ); CopyMem ( &Uart->DataBits, &NewTerminalContext->DataBits, sizeof (UINT8) ); CopyMem ( &Uart->Parity, &NewTerminalContext->Parity, sizeof (UINT8) ); CopyMem ( &Uart->StopBits, &NewTerminalContext->StopBits, sizeof (UINT8) ); } Node = NextDevicePathNode (Node); } }
EFI_DEVICE_PATH_PROTOCOL * AppendDevicePathInstance ( IN EFI_DEVICE_PATH_PROTOCOL *Src, IN EFI_DEVICE_PATH_PROTOCOL *Instance ) /*++ Routine Description: Function is used to add a device path instance to a device path. Arguments: Src - A pointer to a device path data structure Instance - A pointer to a device path instance. Returns: This function returns a pointer to the new device path. If there is not enough temporary pool memory available to complete this function, then NULL is returned. It is up to the caller to free the memory used by Src and Instance if they are no longer needed. --*/ { UINT8 *Ptr; EFI_DEVICE_PATH_PROTOCOL *DevPath; UINTN SrcSize; UINTN InstanceSize; if (Src == NULL) { return DuplicateDevicePath (Instance); } SrcSize = DevicePathSize(Src); InstanceSize = DevicePathSize(Instance); Ptr = AllocatePool (SrcSize + InstanceSize); DevPath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr; ASSERT(DevPath); CopyMem (Ptr, Src, SrcSize); // FreePool (Src); while (!IsDevicePathEnd(DevPath)) { DevPath = NextDevicePathNode(DevPath); } // // Convert the End to an End Instance, since we are // appending another instacne after this one its a good // idea. // DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; DevPath = NextDevicePathNode(DevPath); CopyMem (DevPath, Instance, InstanceSize); return (EFI_DEVICE_PATH_PROTOCOL *)Ptr; }
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 device path node right before the end node static EFI_DEVICE_PATH* GetLastDevicePath(CONST EFI_DEVICE_PATH* dp) { EFI_DEVICE_PATH *next, *p; if (IsDevicePathEnd(dp)) return NULL; for (p = (EFI_DEVICE_PATH *) dp, next = NextDevicePathNode(p); !IsDevicePathEnd(next); p = next, next = NextDevicePathNode(next)); return p; }
EFI_STATUS BdsGetDeviceHd ( IN EFI_DEVICE_PATH* RemovableDevicePath, OUT EFI_HANDLE* DeviceHandle, OUT EFI_DEVICE_PATH** NewDevicePath ) { EFI_STATUS Status; UINTN Index; UINTN PartitionHandleCount; EFI_HANDLE *PartitionBuffer; EFI_DEVICE_PATH* PartitionDevicePath; EFI_DEVICE_PATH* TmpDevicePath; HARDDRIVE_DEVICE_PATH* HardDriveDevicePath1; HARDDRIVE_DEVICE_PATH* HardDriveDevicePath2; // Get all the DiskIo handles PartitionHandleCount = 0; Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &PartitionHandleCount, &PartitionBuffer); if (EFI_ERROR(Status) || (PartitionHandleCount == 0)) { return Status; } // Check if one of the handles matches the Hard Disk Description for (Index = 0; Index < PartitionHandleCount; Index++) { Status = gBS->HandleProtocol (PartitionBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &PartitionDevicePath); if (!EFI_ERROR(Status)) { TmpDevicePath = PartitionDevicePath; while (!IsDevicePathEnd (TmpDevicePath)) { // Check if the Device Path node is a HD Removable device Path node if (BdsIsRemovableHd (TmpDevicePath)) { HardDriveDevicePath1 = (HARDDRIVE_DEVICE_PATH*)RemovableDevicePath; HardDriveDevicePath2 = (HARDDRIVE_DEVICE_PATH*)TmpDevicePath; if ((HardDriveDevicePath1->SignatureType == HardDriveDevicePath2->SignatureType) && (CompareGuid ((EFI_GUID *)HardDriveDevicePath1->Signature,(EFI_GUID *)HardDriveDevicePath2->Signature) == TRUE) && (HardDriveDevicePath1->PartitionNumber == HardDriveDevicePath2->PartitionNumber)) { *DeviceHandle = PartitionBuffer[Index]; // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path *NewDevicePath = AppendDevicePath (PartitionDevicePath, NextDevicePathNode(RemovableDevicePath)); return EFI_SUCCESS; } } TmpDevicePath = NextDevicePathNode (TmpDevicePath); } } } return EFI_NOT_FOUND; }
EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]) { EFI_DEVICE_PATH *device_path; EFI_STATUS r = EFI_NOT_FOUND; /* export the device path this image is started from */ device_path = DevicePathFromHandle(handle); if (device_path) { EFI_DEVICE_PATH *path, *paths; paths = UnpackDevicePath(device_path); for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) { HARDDRIVE_DEVICE_PATH *drive; if (DevicePathType(path) != MEDIA_DEVICE_PATH) continue; if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP) continue; drive = (HARDDRIVE_DEVICE_PATH *)path; if (drive->SignatureType != SIGNATURE_TYPE_GUID) continue; GuidToString(uuid, (EFI_GUID *)&drive->Signature); r = EFI_SUCCESS; break; } FreePool(paths); } return r; }
// // append file path // EFI_DEVICE_PATH_PROTOCOL* DevPathAppendFilePath(EFI_DEVICE_PATH_PROTOCOL* devicePath, CHAR16 CONST* fileName) { if(!devicePath || !fileName || !fileName[0]) return nullptr; UINTN devicePathSize = DevPathGetSize(devicePath); if(!devicePathSize) return nullptr; UINTN size = (wcslen(fileName) + 1) * sizeof(CHAR16); EFI_DEVICE_PATH_PROTOCOL* filePath = static_cast<EFI_DEVICE_PATH_PROTOCOL*>(MmAllocatePool(size + devicePathSize + SIZE_OF_FILEPATH_DEVICE_PATH)); if(!filePath) return nullptr; devicePathSize -= END_DEVICE_PATH_LENGTH; memcpy(filePath, devicePath, devicePathSize); FILEPATH_DEVICE_PATH* filePathNode = Add2Ptr(filePath, devicePathSize, FILEPATH_DEVICE_PATH*); filePathNode->Header.Type = MEDIA_DEVICE_PATH; filePathNode->Header.SubType = MEDIA_FILEPATH_DP; SetDevicePathNodeLength(&filePathNode->Header, size + SIZE_OF_FILEPATH_DEVICE_PATH); memcpy(filePathNode->PathName, fileName, size); EFI_DEVICE_PATH_PROTOCOL* endOfPath = NextDevicePathNode(&filePathNode->Header); SetDevicePathEndNode(endOfPath); return filePath; }
UINTN DevicePathSize ( IN EFI_DEVICE_PATH_PROTOCOL *DevPath ) /*++ Routine Description: Function returns the size of a device path in bytes. Arguments: DevPath - A pointer to a device path data structure Returns: Size is returned. --*/ { EFI_DEVICE_PATH_PROTOCOL *Start; // // Search for the end of the device path structure // Start = DevPath; while (!IsDevicePathEnd(DevPath)) { DevPath = NextDevicePathNode(DevPath); } // // Compute the size // return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL); }
EFI_DEVICE_PATH_PROTOCOL * FileDevicePath ( IN EFI_HANDLE Device OPTIONAL, IN CHAR16 *FileName ) /*++ Routine Description: Function allocates a device path for a file and appends it to an existing device path. Arguments: Device - A pointer to a device handle. FileName - A pointer to a Null-terminated Unicode string. Returns: If Device is not a valid device handle, then a device path for the file specified by FileName is allocated and returned. Results are allocated from pool. The caller must FreePool the resulting device path structure --*/ { UINTN Size; FILEPATH_DEVICE_PATH *FilePath; EFI_DEVICE_PATH_PROTOCOL *Eop, *DevicePath; Size = StrSize(FileName); FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH_PROTOCOL)); DevicePath = NULL; if (FilePath) { // // Build a file path // FilePath->Header.Type = MEDIA_DEVICE_PATH; FilePath->Header.SubType = MEDIA_FILEPATH_DP; SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); CopyMem (FilePath->PathName, FileName, Size); Eop = NextDevicePathNode(&FilePath->Header); SetDevicePathEndNode(Eop); // // Append file path to device's device path // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) FilePath; if (Device) { DevicePath = AppendDevicePath ( DevicePathFromHandle(Device), DevicePath ); FreePool(FilePath); } } 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); } }
/** Returns the size of a device path in bytes. This function returns the size, in bytes, of the device path data structure specified by DevicePath including the end of device path node. If DevicePath is NULL, then 0 is returned. If the length of the device path is bigger than MaxSize, also return 0 to indicate this is an invalidate device path. @param DevicePath A pointer to a device path data structure. @param MaxSize Max valid device path size. If big than this size, return error. @retval 0 An invalid device path. @retval Others The size of a device path in bytes. **/ UINTN BmGetDevicePathSizeEx ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN MaxSize ) { UINTN Size; UINTN NodeSize; if (DevicePath == NULL) { return 0; } // // Search for the end of the device path structure // Size = 0; while (!IsDevicePathEnd (DevicePath)) { NodeSize = DevicePathNodeLength (DevicePath); if (NodeSize == 0) { return 0; } Size += NodeSize; if (Size > MaxSize) { return 0; } DevicePath = NextDevicePathNode (DevicePath); } Size += DevicePathNodeLength (DevicePath); if (Size > MaxSize) { return 0; } return Size; }
EFI_DEVICE_PATH * AppendDevicePathNode ( IN EFI_DEVICE_PATH *Src1, IN EFI_DEVICE_PATH *Src2 ) // Src1 may have multiple "instances" and each instance is appended // Src2 is a signal device path node (without a terminator) that is // appended to each instance is Src1. { EFI_DEVICE_PATH *Temp, *Eop; UINTN Length; // // Build a Src2 that has a terminator on it // Length = DevicePathNodeLength(Src2); Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH)); if (!Temp) { return NULL; } CopyMem (Temp, Src2, Length); Eop = NextDevicePathNode(Temp); SetDevicePathEndNode(Eop); // // Append device paths // Src1 = AppendDevicePath (Src1, Temp); FreePool (Temp); return Src1; }
/** Returns the size of a device path in bytes. This function returns the size, in bytes, of the device path data structure specified by DevicePath including the end of device path node. If DevicePath is NULL or invalid, then 0 is returned. @param DevicePath A pointer to a device path data structure. @retval 0 If DevicePath is NULL or invalid. @retval Others The size of a device path in bytes. **/ UINTN EFIAPI UefiDevicePathLibGetDevicePathSize ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { CONST EFI_DEVICE_PATH_PROTOCOL *Start; if (DevicePath == NULL) { return 0; } if (!IsDevicePathValid (DevicePath, 0)) { return 0; } // // Search for the end of the device path structure // Start = DevicePath; while (!IsDevicePathEnd (DevicePath)) { DevicePath = NextDevicePathNode (DevicePath); } // // Compute the size and add back in the size of the end device path structure // return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath); }
EFI_DEVICE_PATH * LibDuplicateDevicePathInstance ( IN EFI_DEVICE_PATH *DevPath ) { EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp; UINTN Size = 0; // // get the size of an instance from the input // Temp = DevPath; DevicePathInst = DevicePathInstance (&Temp, &Size); // // Make a copy and set proper end type // NewDevPath = NULL; if (Size) { NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH)); } if (NewDevPath) { CopyMem (NewDevPath, DevicePathInst, Size); Temp = NextDevicePathNode(NewDevPath); SetDevicePathEndNode(Temp); } return NewDevPath; }
BOOLEAN BdsTftpSupport ( IN EFI_DEVICE_PATH* DevicePath, IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH* RemainingDevicePath ) { EFI_STATUS Status; EFI_DEVICE_PATH *NextDevicePath; EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol; // Validate the Remaining Device Path if (IsDevicePathEnd(RemainingDevicePath)) { return FALSE; } if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) && !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) { return FALSE; } NextDevicePath = NextDevicePathNode (RemainingDevicePath); if (IsDevicePathEnd(NextDevicePath)) { return FALSE; } if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) { return FALSE; } Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol); if (EFI_ERROR (Status)) { return FALSE; } else { return TRUE; } }
EFI_STATUS BdsLoadOptionPxeList ( IN OUT LIST_ENTRY* BdsLoadOptionList ) { EFI_STATUS Status; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINTN Index; BDS_SUPPORTED_DEVICE *SupportedDevice; EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet; CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX]; EFI_MAC_ADDRESS *Mac; EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; // List all the PXE Protocols Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { return Status; } for (Index = 0; Index < HandleCount; Index++) { // We only select the handle WITH a Device Path AND the PXE Protocol Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); if (!EFI_ERROR(Status)) { // Allocate BDS Supported Device structure SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE)); //Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet); Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&SimpleNet); if (!EFI_ERROR(Status)) { Mac = &SimpleNet->Mode->CurrentAddress; UnicodeSPrint (DeviceDescription,BOOT_DEVICE_DESCRIPTION_MAX,L"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]); } else { Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription); ASSERT_EFI_ERROR (Status); } UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"PXE on %s",DeviceDescription); if(NULL != SupportedDevice) { SupportedDevice->DevicePathProtocol = DevicePathProtocol; DevicePathNode = DevicePathProtocol; while (!IsDevicePathEnd (DevicePathNode)) { if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) && ( DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP) ) { SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_PXE]; InsertTailList (BdsLoadOptionList,&SupportedDevice->Link); break; } DevicePathNode = NextDevicePathNode (DevicePathNode); } } } } return EFI_SUCCESS; }
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; }
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; }
/** Determine whether a given device path is valid. If DevicePath is NULL, then ASSERT(). @param DevicePath A pointer to a device path data structure. @param MaxSize The maximum size of the device path data structure. @retval TRUE DevicePath is valid. @retval FALSE The length of any node node in the DevicePath is less than sizeof (EFI_DEVICE_PATH_PROTOCOL). @retval FALSE If MaxSize is not zero, the size of the DevicePath exceeds MaxSize. @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node count of the DevicePath exceeds PcdMaximumDevicePathNodeCount. **/ BOOLEAN EFIAPI IsDevicePathValid ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN MaxSize ) { UINTN Count; UINTN Size; UINTN NodeLength; ASSERT (DevicePath != NULL); if (MaxSize == 0) { MaxSize = MAX_UINTN; } // // Validate the input size big enough to touch the first node. // if (MaxSize < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { return FALSE; } for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { NodeLength = DevicePathNodeLength (DevicePath); if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { return FALSE; } if (NodeLength > MAX_UINTN - Size) { return FALSE; } Size += NodeLength; // // Validate next node before touch it. // if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) { return FALSE; } if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) { Count++; if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) { return FALSE; } } } // // Only return TRUE when the End Device Path node is valid. // return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH); }
/** * Get the device path of floppy disk. */ EFI_STATUS GetFloppyDevicePath ( OUT EFI_DEVICE_PATH_PROTOCOL **FloppyDevicePath ) { EFI_STATUS Status; UINTN NoHandle; EFI_HANDLE *Buffer; UINTN Index; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *RemainPath; EFI_DEVICE_PATH_PROTOCOL *LastNode; ACPI_HID_DEVICE_PATH *AcpiNode; Status = gtBS->LocateHandleBuffer ( ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &NoHandle, &Buffer ); if (EFI_ERROR(Status)) { return Status; } for (Index = 0; Index < NoHandle; Index++) { Status = gtBS->HandleProtocol ( Buffer[Index], &gEfiDevicePathProtocolGuid, &DevicePath ); RemainPath = DevicePath; LastNode = DevicePath; while (!IsDevicePathEnd (RemainPath)) { LastNode = RemainPath; RemainPath = NextDevicePathNode (RemainPath); } // // Is LastNode ACPI device path node ? // if ((DevicePathType (LastNode) == 2) && (DevicePathSubType (LastNode) == 1)) { AcpiNode = (ACPI_HID_DEVICE_PATH*)LastNode; // // Is floppy device path ? // if (EISA_ID_TO_NUM(AcpiNode->HID) == 0x0604) { *FloppyDevicePath = DevicePath; return EFI_SUCCESS; } } } return EFI_NOT_FOUND; }
/** Create an action OpCode with QuestionID and DevicePath on a given OpCodeHandle. @param[in] QuestionID The question ID. @param[in] DevicePath Points to device path. @param[in] OpCodeHandle Points to container for dynamic created opcodes. **/ VOID AddDevicePath ( IN UINTN QuestionID, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN VOID *OpCodeHandle ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *Next; EFI_STRING_ID NameID; EFI_STRING DriverName; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText; // // Locate device path to text protocol. // Status = gBS->LocateProtocol ( &gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevicePathText ); if (EFI_ERROR (Status)) { return ; } // // Get driver file name node. // Next = DevicePath; while (!IsDevicePathEnd (Next)) { DevicePath = Next; Next = NextDevicePathNode (Next); } // // Display the device path in form. // DriverName = DevicePathText->ConvertDevicePathToText (DevicePath, FALSE, FALSE); NameID = HiiSetString (mCallbackInfo->HiiHandle, 0, DriverName, NULL); FreePool (DriverName); if (NameID == 0) { return ; } HiiCreateActionOpCode ( OpCodeHandle, // Container for dynamic created opcodes (UINT16) QuestionID, // Question ID NameID, // Prompt text STRING_TOKEN (STR_NULL_STRING), // Help text EFI_IFR_FLAG_CALLBACK, // Question flag 0 // Action String ID ); }
/** Check to see if this driver supports the given controller @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param Controller The handle of the controller to test. @param RemainingDevicePath A pointer to the remaining portion of a device path. @return EFI_SUCCESS This driver can support the given controller **/ EFI_STATUS EFIAPI SerialControllerDriverSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; UART_DEVICE_PATH *Uart; UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; // // Test RemainingDevicePath // if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) { Status = EFI_UNSUPPORTED; Uart = SkipControllerDevicePathNode (RemainingDevicePath, NULL, NULL); if (DevicePathType (Uart) != MESSAGING_DEVICE_PATH || DevicePathSubType (Uart) != MSG_UART_DP || DevicePathNodeLength (Uart) != sizeof (UART_DEVICE_PATH) ) { return EFI_UNSUPPORTED; } // // Do a rough check because Clock Rate is unknown until DriverBindingStart() // if (!VerifyUartParameters (0, Uart->BaudRate, Uart->DataBits, Uart->Parity, Uart->StopBits, NULL, NULL)) { return EFI_UNSUPPORTED; } FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); if (IsUartFlowControlDevicePathNode (FlowControl)) { // // If the second node is Flow Control Node, // return error when it request other than hardware flow control. // if ((ReadUnaligned32 (&FlowControl->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) { return EFI_UNSUPPORTED; } } } Status = IsSioSerialController (Controller); if (EFI_ERROR (Status)) { Status = IsPciSerialController (Controller); } return Status; }
VOID AddLoadFileBootOptions ( VOID ) { EFI_STATUS Status; EFI_HANDLE *HandleArray; UINTN HandleArrayCount; UINTN Index; EFI_DEVICE_PATH_PROTOCOL *FilePath; EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; CHAR16 *FileName; EFI_SIMPLE_NETWORK_PROTOCOL *Snp; // // If there is a removable media device that does not have media present do a read. // The read will cause media to be detected and the partition drivers and file system // drivers to layer on top following the EFI driver model // Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleArrayCount, &HandleArray); if (EFI_ERROR (Status)) { return; } for (Index = 0; Index < HandleArrayCount; Index++) { // // if the LoadFileProtocol is provided by PXE, skip it. BdsLibBootOptionNetwork() will handle it. // Status = gBS->HandleProtocol (HandleArray[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp); if (!EFI_ERROR (Status)) { continue; } // // Add the file name // Status = gBS->HandleProtocol (HandleArray[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FilePath); if (!EFI_ERROR (Status)) { FileName = L"Load File"; DevicePathNode = FilePath; while (!IsDevicePathEnd (DevicePathNode)) { if (DevicePathNode->Type == MEDIA_DEVICE_PATH && DevicePathNode->SubType == MEDIA_FILEPATH_DP) { FileName = (CHAR16 *)(DevicePathNode + 1); break; } DevicePathNode = NextDevicePathNode (DevicePathNode); } BdsPlatformAddBootableImage (FileName, FilePath); } } FreePool (HandleArray); }
EFI_DEVICE_PATH_PROTOCOL * AppendDevicePathNode ( IN EFI_DEVICE_PATH_PROTOCOL *Src1, IN EFI_DEVICE_PATH_PROTOCOL *Src2 ) /*++ Routine Description: Function is used to append a device path node to all the instances in another device path. Arguments: Src1 - A pointer to a device path data structure. Src2 - A pointer to a device path data structure. Returns: This function returns a pointer to the new device path. If there is not enough temporary pool memory available to complete this function, then NULL is returned. Src1 may have multiple "instances" and each instance is appended Src2 is a signal device path node (without a terminator) that is appended to each instance is Src1. --*/ { EFI_DEVICE_PATH_PROTOCOL *Temp, *Eop; UINTN Length; // // Build a Src2 that has a terminator on it // Length = DevicePathNodeLength(Src2); Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH_PROTOCOL)); if (!Temp) { return NULL; } CopyMem (Temp, Src2, Length); Eop = NextDevicePathNode(Temp); SetDevicePathEndNode(Eop); // // Append device paths // Src1 = AppendDevicePath (Src1, Temp); FreePool (Temp); return Src1; }
EFI_DEVICE_PATH * FileDevicePath ( IN EFI_HANDLE Device OPTIONAL, IN CHAR16 *FileName ) /*++ N.B. Results are allocated from pool. The caller must FreePool the resulting device path structure --*/ { UINTN Size; FILEPATH_DEVICE_PATH *FilePath; EFI_DEVICE_PATH *Eop, *DevicePath; Size = StrSize(FileName); FilePath = (FILEPATH_DEVICE_PATH *) AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH)); DevicePath = (EFI_DEVICE_PATH *) NULL; if (FilePath) { // // Build a file path // FilePath->Header.Type = MEDIA_DEVICE_PATH; FilePath->Header.SubType = MEDIA_FILEPATH_DP; SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); BS->CopyMem (FilePath->PathName, FileName, Size); Eop = NextDevicePathNode(&FilePath->Header); SetDevicePathEndNode(Eop); // // Append file path to device's device path // DevicePath = (EFI_DEVICE_PATH *) FilePath; if (Device) { DevicePath = AppendDevicePath ( DevicePathFromHandle(Device), DevicePath ); BS->FreePool(FilePath); } } return DevicePath; }