/** This function invokes Boot Manager. If all devices have not a chance to be connected, the connect all will be triggered. It then enumerate all boot options. If a boot option from the Boot Manager page is selected, Boot Manager will boot from this boot option. **/ VOID UpdateBootManager ( VOID ) { UINTN Index; EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; UINTN BootOptionCount; EFI_STRING_ID Token; CHAR16 *HelpString; EFI_STRING_ID HelpToken; UINT16 *TempStr; EFI_HII_HANDLE HiiHandle; UINTN TempSize; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; UINT16 DeviceType; BOOLEAN IsLegacyOption; BOOLEAN NeedEndOp; UINTN MaxLen; DeviceType = (UINT16) -1; EfiBootManagerConnectAll (); // // for better user experience // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option // EfiBootManagerRefreshAllBootOption (); // // BdsDxe doesn't group the legacy boot options for the same device type // It's UI's choice. // GroupMultipleLegacyBootOption4SameType (); BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); HiiHandle = gBootManagerPrivate.HiiHandle; // // Allocate space for creation of UpdateData Buffer // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); // // Create Hii Extend Label OpCode as the start opcode // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_BOOT_OPTION; // // Create Hii Extend Label OpCode as the end opcode // EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_BOOT_OPTION_END; mKeyInput = 0; NeedEndOp = FALSE; for (Index = 0; Index < BootOptionCount; Index++) { // // At this stage we are creating a menu entry, thus the Keys are reproduceable // mKeyInput++; // // Don't display the hidden/inactive boot option // if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) { continue; } // // Group the legacy boot option in the sub title created dynamically // IsLegacyOption = (BOOLEAN) ( (DevicePathType (BootOption[Index].FilePath) == BBS_DEVICE_PATH) && (DevicePathSubType (BootOption[Index].FilePath) == BBS_BBS_DP) ); if (!IsLegacyOption && NeedEndOp) { NeedEndOp = FALSE; HiiCreateEndOpCode (StartOpCodeHandle); } if (IsLegacyOption && DeviceType != ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) { if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } DeviceType = ((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType; Token = HiiSetString ( HiiHandle, 0, mDeviceTypeStr[ MIN (DeviceType & 0xF, sizeof (mDeviceTypeStr) / sizeof (mDeviceTypeStr[0]) - 1) ], NULL ); HiiCreateSubTitleOpCode (StartOpCodeHandle, Token, 0, 0, 1); NeedEndOp = TRUE; } ASSERT (BootOption[Index].Description != NULL); Token = HiiSetString (HiiHandle, 0, BootOption[Index].Description, NULL); TempStr = BmDevicePathToStr (BootOption[Index].FilePath); TempSize = StrSize (TempStr); HelpString = AllocateZeroPool (TempSize + StrSize (L"Device Path : ")); MaxLen = (TempSize + StrSize (L"Device Path : "))/sizeof(CHAR16); ASSERT (HelpString != NULL); StrCatS (HelpString, MaxLen, L"Device Path : "); StrCatS (HelpString, MaxLen, TempStr); HelpToken = HiiSetString (HiiHandle, 0, HelpString, NULL); HiiCreateActionOpCode ( StartOpCodeHandle, mKeyInput, Token, HelpToken, EFI_IFR_FLAG_CALLBACK, 0 ); } if (NeedEndOp) { HiiCreateEndOpCode (StartOpCodeHandle); } HiiUpdateForm ( HiiHandle, &mBootManagerGuid, BOOT_MANAGER_FORM_ID, StartOpCodeHandle, EndOpCodeHandle ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); }
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; }
BOOLEAN BdsIsRemovableUsb ( IN EFI_DEVICE_PATH* DevicePath ) { return ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) || (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP))); }
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; }
/* 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_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; }
/** 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); }
/** 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); } }
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; }
/** * 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; }
/** Check whether the device path node is ISA Serial Node. @param Acpi Device path node to be checked @retval TRUE It's ISA Serial Node. @retval FALSE It's NOT ISA Serial Node. **/ BOOLEAN IsIsaSerialNode ( IN ACPI_HID_DEVICE_PATH *Acpi ) { return (BOOLEAN) ( (DevicePathType (Acpi) == ACPI_DEVICE_PATH) && (DevicePathSubType (Acpi) == ACPI_DP) && (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501)) ); }
/** Check the device path node whether it's the Flow Control node or not. @param[in] FlowControl The device path node to be checked. @retval TRUE It's the Flow Control node. @retval FALSE It's not. **/ BOOLEAN IsUartFlowControlNode ( IN UART_FLOW_CONTROL_DEVICE_PATH *FlowControl ) { return (BOOLEAN) ( (DevicePathType (FlowControl) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (FlowControl) == MSG_VENDOR_DP) && (CompareGuid (&FlowControl->Guid, &gEfiUartDevicePathGuid)) ); }
// Compare device paths static INTN CompareDevicePaths(CONST EFI_DEVICE_PATH *dp1, CONST EFI_DEVICE_PATH *dp2) { if (dp1 == NULL || dp2 == NULL) return -1; while (1) { UINT8 type1, type2; UINT8 subtype1, subtype2; UINT16 len1, len2; INTN ret; type1 = DevicePathType(dp1); type2 = DevicePathType(dp2); if (type1 != type2) return (int) type2 - (int) type1; subtype1 = DevicePathSubType(dp1); subtype2 = DevicePathSubType(dp2); if (subtype1 != subtype2) return (int) subtype1 - (int) subtype2; len1 = DevicePathNodeLength(dp1); len2 = DevicePathNodeLength(dp2); if (len1 != len2) return (int) len1 - (int) len2; ret = CompareMem(dp1, dp2, len1); if (ret != 0) return ret; if (IsDevicePathEnd(dp1)) break; dp1 = (EFI_DEVICE_PATH*) ((char *)dp1 + len1); dp2 = (EFI_DEVICE_PATH*) ((char *)dp2 + len2); } return 0; }
/** 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 SEnvPrintDevicePathEntry ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN Verbose ) /*++ Routine Description: Arguments: DevicePath - The device path Verbose - Verbose Returns: --*/ { UINT8 Type; UINT8 SubType; INTN Index; // // Process print device path entry // Type = (UINT8) DevicePathType (DevicePath); SubType = DevicePathSubType (DevicePath); for (Index = 0; SEnvDP_Strings[Index].Type != END_DEVICE_PATH_TYPE; Index++) { if (Type == SEnvDP_Strings[Index].Type) { if (SubType > SEnvDP_Strings[Index].MaxSubType) { SubType = 0; } PrintToken ( STRING_TOKEN (STR_SHELLENV_DPROT_DEVICE_PATH_FOR), HiiEnvHandle, SEnvDP_Strings[Index].TypeString, SEnvDP_Strings[Index].SubTypeStr[SubType] ); if (Verbose) { if (SEnvDP_Strings[Index].Function != NULL) { SEnvDP_Strings[Index].Function (DevicePath); } } return ; } } PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_DEVICE_PATH_ERROR), HiiEnvHandle); }
/** Get the URI address string from the input device path. Caller need to free the buffer in the UriAddress pointer. @param[in] FilePath Pointer to the device path which contains a URI device path node. @param[out] UriAddress The URI address string extract from the device path. @retval EFI_SUCCESS The URI string is returned. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. **/ EFI_STATUS HttpBootParseFilePath ( IN EFI_DEVICE_PATH_PROTOCOL *FilePath, OUT CHAR8 **UriAddress ) { EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; URI_DEVICE_PATH *UriDevicePath; CHAR8 *Uri; UINTN UriStrLength; if (FilePath == NULL) { return EFI_INVALID_PARAMETER; } *UriAddress = NULL; // // Extract the URI address from the FilePath // TempDevicePath = FilePath; while (!IsDevicePathEnd (TempDevicePath)) { if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (TempDevicePath) == MSG_URI_DP)) { UriDevicePath = (URI_DEVICE_PATH*) TempDevicePath; // // UEFI Spec doesn't require the URI to be a NULL-terminated string // So we allocate a new buffer and always append a '\0' to it. // UriStrLength = DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); if (UriStrLength == 0) { // // return a NULL UriAddress if it's a empty URI device path node. // break; } Uri = AllocatePool (UriStrLength + 1); if (Uri == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL)); Uri[DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL)] = '\0'; *UriAddress = Uri; } TempDevicePath = NextDevicePathNode (TempDevicePath); } return EFI_SUCCESS; }
EFIAPI EfiGetNameGuidFromFwVolDevicePathNode ( IN CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode ) { ASSERT (FvDevicePathNode != NULL); if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH && DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_PIWG_FW_FILE_DP) { return (EFI_GUID *) &FvDevicePathNode->FvFileName; } return NULL; }
/** Function to walk the device path looking for a dumpable node. @param[in] MappingItem The Item to fill with data. @param[in] DevicePath The path of the item to get data on. @return EFI_SUCCESS Always returns success. **/ EFI_STATUS EFIAPI GetDeviceConsistMappingInfo ( IN DEVICE_CONSIST_MAPPING_INFO *MappingItem, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { VOID (EFIAPI *SerialFun) (EFI_DEVICE_PATH_PROTOCOL *, DEVICE_CONSIST_MAPPING_INFO *); UINTN Index; ASSERT(DevicePath != NULL); ASSERT(MappingItem != NULL); SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0); while (!IsDevicePathEnd (DevicePath)) { // // Find the handler to dump this device path node // SerialFun = NULL; for (Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) { if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type && DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType ) { SerialFun = DevPathConsistMappingTable[Index].SerialFun; break; } } // // If not found, use a generic function // if (!SerialFun) { SerialFun = DevPathSerialDefault; } SerialFun (DevicePath, MappingItem); // // Next device path node // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath); } return EFI_SUCCESS; }
static INTN simple_scheme(device_t *tab, UINTN n) { EFI_DEVICE_PATH *dp1, *dp; devices_types_t *p; UINTN i; /* * note that this test is necessary but not sufficient to guarantee that this scheme * will work because, we have no way of detecting that the machine got actually * rebooted if the EDD30 variable was forced. this comes from the fact, that elilo * can be invoked once, aborted and then restarted with no machine reboot. * * XXX: there may be a way to detect this with the another variable which would * be in volatile memory only */ if (elilo_opt.edd30_on == 0) { VERB_PRT(4, Print(L"%s device naming scheme only works with EDD3.0 enabled\n", NAMING_SCHEME)); return -1; } for(i=0; i < n; i++) { dp = DevicePathFromHandle(tab[i].dev); if (dp == NULL) { ERR_PRT((L"cannot get device path for device %d", i)); continue; } dp1 = dp = UnpackDevicePath(dp); while (!IsDevicePathEnd(dp)) { p = dev_types; while (p->type) { if ( p->type == DevicePathType(dp) && p->subtype == DevicePathSubType(dp)) { (*p->device_func)(tab+i, dp); goto done; } p++; } dp = NextDevicePathNode(dp); } done: FreePool(dp1); } return 0; }
EFIAPI EfiGetNameGuidFromFwVolDevicePathNode ( IN CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode ) { ASSERT (FvDevicePathNode != NULL); // // EFI Specification extension on Media Device Path. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH is adopted by UEFI later and added in UEFI2.10. // In EdkCompatibility Package, we only support MEDIA_FW_VOL_FILEPATH_DEVICE_PATH that complies with // EFI 1.10 and UEFI 2.10. // if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH && DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_PIWG_FW_FILE_DP) { return (EFI_GUID *) &FvDevicePathNode->FvFileName; } return NULL; }
/** Print information about the Load File devices. If the device supports PXE dump out extra information @param File Open File for the device **/ VOID EblPrintLoadFileInfo ( IN EFI_OPEN_FILE *File ) { EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; MAC_ADDR_DEVICE_PATH *MacAddr; UINTN HwAddressSize; UINTN Index; if (File == NULL) { return; } AsciiPrint (" %a: %a ", File->DeviceName, EblLoadFileBootTypeString (File->EfiHandle)); if (File->DevicePath != NULL) { // Try to print out the MAC address for (DevicePathNode = File->DevicePath; !IsDevicePathEnd (DevicePathNode); DevicePathNode = NextDevicePathNode (DevicePathNode)) { if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP)) { MacAddr = (MAC_ADDR_DEVICE_PATH *)DevicePathNode; HwAddressSize = sizeof (EFI_MAC_ADDRESS); if (MacAddr->IfType == 0x01 || MacAddr->IfType == 0x00) { HwAddressSize = 6; } AsciiPrint ("MAC "); for (Index = 0; Index < HwAddressSize; Index++) { AsciiPrint ("%02x", MacAddr->MacAddress.Addr[Index] & 0xff); } } } } AsciiPrint ("\n"); EfiClose (File); return; }
static EFI_STATUS FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType, EFI_DEVICE_PATH **Out) { EFI_DEVICE_PATH *dp = In; if (!In || !Out) return EFI_INVALID_PARAMETER; for (dp = In; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { if (DevicePathType(dp) == Type && DevicePathSubType(dp) == SubType) { *Out = DuplicateDevicePath(dp); if (!*Out) return EFI_OUT_OF_RESOURCES; return EFI_SUCCESS; } } *Out = NULL; return EFI_NOT_FOUND; }
/** Retrieve ACPI UID of UART from device path @param Handle The handle for the UART device. @param AcpiUid The ACPI UID on output. @retval TRUE Find valid UID from device path @retval FALSE Can't find **/ BOOLEAN RetrieveUartUid ( IN EFI_HANDLE Handle, IN OUT UINT32 *AcpiUid ) { EFI_STATUS Status; ACPI_HID_DEVICE_PATH *Acpi; EFI_DEVICE_PATH_PROTOCOL *DevicePath; Status = gBS->HandleProtocol ( Handle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath ); if (EFI_ERROR (Status)) { return FALSE; } Acpi = NULL; for (; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_UART_DP)) { break; } // // Acpi points to the node before the Uart node // Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath; } if ((Acpi != NULL) && IsIsaSerialNode (Acpi)) { if (AcpiUid != NULL) { CopyMem (AcpiUid, &Acpi->UID, sizeof (UINT32)); } return TRUE; } else { return FALSE; } }
/** 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; }
/** Get file name from device path. The file name may contain one or more device path node. Save the file name in a buffer if file name is found. The caller is responsible to free the buffer. @param[in] DevicePath A pointer to a device path. @param[out] FileName The callee allocated buffer to save the file name if file name is found. @param[out] FileNameOffset The offset of file name in device path if file name is found. @retval UINTN The file name length. 0 means file name is not found. **/ UINTN GetFileName ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT UINT8 **FileName, OUT UINTN *FileNameOffset ) { UINTN Length; EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; EFI_DEVICE_PATH_PROTOCOL *RootDevicePath; CHAR8 *NodeStr; UINTN NodeStrLength; CHAR16 LastNodeChar; CHAR16 FirstNodeChar; // // Get the length of DevicePath before file name. // Length = 0; RootDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; while (!IsDevicePathEnd (RootDevicePath)) { if ((DevicePathType(RootDevicePath) == MEDIA_DEVICE_PATH) && (DevicePathSubType(RootDevicePath) == MEDIA_FILEPATH_DP)) { break; } Length += DevicePathNodeLength (RootDevicePath); RootDevicePath = NextDevicePathNode (RootDevicePath); } *FileNameOffset = Length; if (Length == 0) { return 0; } // // Get the file name length. // Length = 0; TmpDevicePath = RootDevicePath; while (!IsDevicePathEnd (TmpDevicePath)) { if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) { break; } Length += DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); TmpDevicePath = NextDevicePathNode (TmpDevicePath); } if (Length == 0) { return 0; } *FileName = AllocateZeroPool (Length); ASSERT (*FileName != NULL); // // Copy the file name to the buffer. // Length = 0; LastNodeChar = '\\'; TmpDevicePath = RootDevicePath; while (!IsDevicePathEnd (TmpDevicePath)) { if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) { break; } FirstNodeChar = (CHAR16) ReadUnaligned16 ((UINT16 *)((UINT8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL))); NodeStr = (CHAR8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL); NodeStrLength = DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof(CHAR16); if ((FirstNodeChar == '\\') && (LastNodeChar == '\\')) { // // Skip separator "\" when there are two separators. // NodeStr += sizeof (CHAR16); NodeStrLength -= sizeof (CHAR16); } else if ((FirstNodeChar != '\\') && (LastNodeChar != '\\')) { // // Add separator "\" when there is no separator. // WriteUnaligned16 ((UINT16 *)(*FileName + Length), '\\'); Length += sizeof (CHAR16); } CopyMem (*FileName + Length, NodeStr, NodeStrLength); Length += NodeStrLength; LastNodeChar = (CHAR16) ReadUnaligned16 ((UINT16 *) (NodeStr + NodeStrLength - sizeof(CHAR16))); TmpDevicePath = NextDevicePathNode (TmpDevicePath); } return Length; }
/** Return the description for network boot device. @param Handle Controller handle. @return The description string. **/ CHAR16 * BmGetNetworkDescription ( IN EFI_HANDLE Handle ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; MAC_ADDR_DEVICE_PATH *Mac; VLAN_DEVICE_PATH *Vlan; EFI_DEVICE_PATH_PROTOCOL *Ip; EFI_DEVICE_PATH_PROTOCOL *Uri; CHAR16 *Description; UINTN DescriptionSize; Status = gBS->OpenProtocol ( Handle, &gEfiLoadFileProtocolGuid, NULL, gImageHandle, Handle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { return NULL; } Status = gBS->OpenProtocol ( Handle, &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath, gImageHandle, Handle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status) || (DevicePath == NULL)) { return NULL; } // // The PXE device path is like: // ....../Mac(...)[/Vlan(...)] // ....../Mac(...)[/Vlan(...)]/IPv4(...) // ....../Mac(...)[/Vlan(...)]/IPv6(...) // // The HTTP device path is like: // ....../Mac(...)[/Vlan(...)]/IPv4(...)/Uri(...) // ....../Mac(...)[/Vlan(...)]/IPv6(...)/Uri(...) // while (!IsDevicePathEnd (DevicePath) && ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) || (DevicePathSubType (DevicePath) != MSG_MAC_ADDR_DP)) ) { DevicePath = NextDevicePathNode (DevicePath); } if (IsDevicePathEnd (DevicePath)) { return NULL; } Mac = (MAC_ADDR_DEVICE_PATH *) DevicePath; DevicePath = NextDevicePathNode (DevicePath); if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_VLAN_DP) ) { Vlan = (VLAN_DEVICE_PATH *) DevicePath; DevicePath = NextDevicePathNode (DevicePath); } else { Vlan = NULL; } if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && ((DevicePathSubType (DevicePath) == MSG_IPv4_DP) || (DevicePathSubType (DevicePath) == MSG_IPv6_DP)) ) { Ip = DevicePath; DevicePath = NextDevicePathNode (DevicePath); } else { Ip = NULL; } if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePath) == MSG_URI_DP) ) { Uri = DevicePath; DevicePath = NextDevicePathNode (DevicePath); } else { Uri = NULL; } // // Build description like below: // "PXEv6 (MAC:112233445566 VLAN1)" // "HTTPv4 (MAC:112233445566)" // DescriptionSize = sizeof (L"HTTPv6 (MAC:112233445566 VLAN65535)"); Description = AllocatePool (DescriptionSize); ASSERT (Description != NULL); UnicodeSPrint ( Description, DescriptionSize, (Vlan == NULL) ? L"%sv%d (MAC:%02x%02x%02x%02x%02x%02x)" : L"%sv%d (MAC:%02x%02x%02x%02x%02x%02x VLAN%d)", (Uri == NULL) ? L"PXE" : L"HTTP", ((Ip == NULL) || (DevicePathSubType (Ip) == MSG_IPv4_DP)) ? 4 : 6, Mac->MacAddress.Addr[0], Mac->MacAddress.Addr[1], Mac->MacAddress.Addr[2], Mac->MacAddress.Addr[3], Mac->MacAddress.Addr[4], Mac->MacAddress.Addr[5], (Vlan == NULL) ? 0 : Vlan->VlanId ); return Description; }
/** Install child handles if the Handle supports MBR format. @param This Calling context. @param Handle Parent Handle. @param DiskIo Parent DiskIo interface. @param BlockIo Parent BlockIo interface. @param DevicePath Parent Device Path. @retval EFI_SUCCESS A child handle was added. @retval EFI_MEDIA_CHANGED Media change was detected. @retval Others MBR partition was not found. **/ EFI_STATUS PartitionInstallMbrChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; MASTER_BOOT_RECORD *Mbr; UINT32 ExtMbrStartingLba; UINTN Index; HARDDRIVE_DEVICE_PATH HdDev; HARDDRIVE_DEVICE_PATH ParentHdDev; EFI_STATUS Found; UINT32 PartitionNumber; EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode; Found = EFI_NOT_FOUND; Mbr = AllocatePool (BlockIo->Media->BlockSize); if (Mbr == NULL) { return Found; } Status = DiskIo->ReadDisk ( DiskIo, BlockIo->Media->MediaId, 0, BlockIo->Media->BlockSize, Mbr ); if (EFI_ERROR (Status)) { Found = Status; goto Done; } if (!PartitionValidMbr (Mbr, BlockIo->Media->LastBlock)) { goto Done; } // // We have a valid mbr - add each partition // // // Get starting and ending LBA of the parent block device. // LastDevicePathNode = NULL; ZeroMem (&ParentHdDev, sizeof (ParentHdDev)); DevicePathNode = DevicePath; while (!IsDevicePathEnd (DevicePathNode)) { LastDevicePathNode = DevicePathNode; DevicePathNode = NextDevicePathNode (DevicePathNode); } if (LastDevicePathNode != NULL) { if (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH && DevicePathSubType (LastDevicePathNode) == MEDIA_HARDDRIVE_DP ) { CopyMem (&ParentHdDev, LastDevicePathNode, sizeof (ParentHdDev)); } else { LastDevicePathNode = NULL; } } PartitionNumber = 1; ZeroMem (&HdDev, sizeof (HdDev)); HdDev.Header.Type = MEDIA_DEVICE_PATH; HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); HdDev.MBRType = MBR_TYPE_PCAT; HdDev.SignatureType = SIGNATURE_TYPE_MBR; if (LastDevicePathNode == NULL) { // // This is a MBR, add each partition // for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA) == 0) { // // Don't use null MBR entries // continue; } if (Mbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION) { // // This is the guard MBR for the GPT. If you ever see a GPT disk with zero partitions you can get here. // We can not produce an MBR BlockIo for this device as the MBR spans the GPT headers. So formating // this BlockIo would corrupt the GPT structures and require a recovery that would corrupt the format // that corrupted the GPT partition. // continue; } HdDev.PartitionNumber = PartitionNumber ++; HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[Index].StartingLBA); HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA); CopyMem (HdDev.Signature, &(Mbr->UniqueMbrSignature[0]), sizeof (Mbr->UniqueMbrSignature)); Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, HdDev.PartitionStart, HdDev.PartitionStart + HdDev.PartitionSize - 1, MBR_SIZE, (BOOLEAN) (Mbr->Partition[Index].OSIndicator == EFI_PARTITION) ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } else { // // It's an extended partition. Follow the extended partition // chain to get all the logical drives // ExtMbrStartingLba = 0; do { Status = DiskIo->ReadDisk ( DiskIo, BlockIo->Media->MediaId, MultU64x32 (ExtMbrStartingLba, BlockIo->Media->BlockSize), BlockIo->Media->BlockSize, Mbr ); if (EFI_ERROR (Status)) { Found = Status; goto Done; } if (UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA) == 0) { break; } if ((Mbr->Partition[0].OSIndicator == EXTENDED_DOS_PARTITION) || (Mbr->Partition[0].OSIndicator == EXTENDED_WINDOWS_PARTITION)) { ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA); continue; } HdDev.PartitionNumber = PartitionNumber ++; HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA) + ExtMbrStartingLba + ParentHdDev.PartitionStart; HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA); if ((HdDev.PartitionStart + HdDev.PartitionSize - 1 >= ParentHdDev.PartitionStart + ParentHdDev.PartitionSize) || (HdDev.PartitionStart <= ParentHdDev.PartitionStart)) { break; } // // The signature in EBR(Extended Boot Record) should always be 0. // *((UINT32 *) &HdDev.Signature[0]) = 0; Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, HdDev.PartitionStart - ParentHdDev.PartitionStart, HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1, MBR_SIZE, (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION) ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } if ((Mbr->Partition[1].OSIndicator != EXTENDED_DOS_PARTITION) && (Mbr->Partition[1].OSIndicator != EXTENDED_WINDOWS_PARTITION) ) { break; } ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[1].StartingLBA); // // Don't allow partition to be self referencing // if (ExtMbrStartingLba == 0) { break; } } while (ExtMbrStartingLba < ParentHdDev.PartitionSize); } Done: FreePool (Mbr); return Found; }
/** 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; }