/** Parse out the boot information from the last Dhcp4 reply packet. @param[in, out] Private Pointer to PxeBc private data. @param[out] BufferSize Size of the boot file to be downloaded. @retval EFI_SUCCESS Successfully parsed out all the boot information. @retval Others Failed to parse out the boot information. **/ EFI_STATUS PxeBcDhcp4BootInfo ( IN OUT PXEBC_PRIVATE_DATA *Private, OUT UINT64 *BufferSize ) { EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; EFI_PXE_BASE_CODE_MODE *Mode; EFI_STATUS Status; PXEBC_DHCP4_PACKET_CACHE *Cache4; UINT16 Value; PXEBC_VENDOR_OPTION *VendorOpt; PXEBC_BOOT_SVR_ENTRY *Entry; PxeBc = &Private->PxeBc; Mode = PxeBc->Mode; Status = EFI_SUCCESS; *BufferSize = 0; // // Get the last received Dhcp4 reply packet. // if (Mode->PxeReplyReceived) { Cache4 = &Private->PxeReply.Dhcp4; } else if (Mode->ProxyOfferReceived) { Cache4 = &Private->ProxyOffer.Dhcp4; } else { Cache4 = &Private->DhcpAck.Dhcp4; } ASSERT (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL); // // Parse the boot server address. // If prompt/discover is disabled, get the first boot server from the boot servers list. // Otherwise, parse the boot server Ipv4 address from next server address field in DHCP header. // If all these fields are not available, use option 54 instead. // VendorOpt = &Cache4->VendorOpt; if (IS_DISABLE_PROMPT_MENU (VendorOpt->DiscoverCtrl) && IS_VALID_BOOT_SERVERS (VendorOpt->BitMap)) { Entry = VendorOpt->BootSvr; if (VendorOpt->BootSvrLen >= sizeof (PXEBC_BOOT_SVR_ENTRY) && Entry->IpCnt > 0) { CopyMem ( &Private->ServerIp, &Entry->IpAddr[0], sizeof (EFI_IPv4_ADDRESS) ); } } if (Private->ServerIp.Addr[0] == 0) { // // ServerIp.Addr[0] equals zero means we failed to get IP address from boot server list. // Try to use next server address field. // CopyMem ( &Private->ServerIp, &Cache4->Packet.Offer.Dhcp4.Header.ServerAddr, sizeof (EFI_IPv4_ADDRESS) ); } if (Private->ServerIp.Addr[0] == 0) { // // Still failed , use the IP address from option 54. // CopyMem ( &Private->ServerIp, Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data, sizeof (EFI_IPv4_ADDRESS) ); } // // Parse the boot file name by option. // Private->BootFileName = Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data; if (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] != NULL) { // // Parse the boot file size by option. // CopyMem (&Value, Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN]->Data, sizeof (Value)); Value = NTOHS (Value); // // The field of boot file size is 512 bytes in unit. // *BufferSize = 512 * Value; } else { // // Get the bootfile size by tftp command if no option available. // Status = PxeBc->Mtftp ( PxeBc, EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, NULL, FALSE, BufferSize, &Private->BlockSize, &Private->ServerIp, Private->BootFileName, NULL, FALSE ); } // // Save the value of boot file size. // Private->BootFileSize = (UINTN) *BufferSize; // // Display all the information: boot server address, boot file name and boot file size. // AsciiPrint ("\n Server IP address is "); PxeBcShowIp4Addr (&Private->ServerIp.v4); AsciiPrint ("\n NBP filename is %a", Private->BootFileName); AsciiPrint ("\n NBP filesize is %d Bytes", Private->BootFileSize); return Status; }
/** Parse out the boot information from the last Dhcp4 reply packet. @param[in, out] Private Pointer to PxeBc private data. @param[out] BufferSize Size of the boot file to be downloaded. @retval EFI_SUCCESS Successfully parsed out all the boot information. @retval Others Failed to parse out the boot information. **/ EFI_STATUS PxeBcDhcp4BootInfo ( IN OUT PXEBC_PRIVATE_DATA *Private, OUT UINT64 *BufferSize ) { EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; EFI_PXE_BASE_CODE_MODE *Mode; EFI_STATUS Status; PXEBC_DHCP4_PACKET_CACHE *Cache4; UINT16 Value; PxeBc = &Private->PxeBc; Mode = PxeBc->Mode; Status = EFI_SUCCESS; *BufferSize = 0; // // Get the last received Dhcp4 reply packet. // if (Mode->PxeReplyReceived) { Cache4 = &Private->PxeReply.Dhcp4; } else if (Mode->ProxyOfferReceived) { Cache4 = &Private->ProxyOffer.Dhcp4; } else { Cache4 = &Private->DhcpAck.Dhcp4; } // // Parse the boot server Ipv4 address by next server address. // If this field isn't available, use option 54 instead. // CopyMem ( &Private->ServerIp, &Cache4->Packet.Offer.Dhcp4.Header.ServerAddr, sizeof (EFI_IPv4_ADDRESS) ); if (Private->ServerIp.Addr[0] == 0) { CopyMem ( &Private->ServerIp, Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data, sizeof (EFI_IPv4_ADDRESS) ); } // // Parse the boot file name by option. // ASSERT (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL); Private->BootFileName = Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data; if (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] != NULL) { // // Parse the boot file size by option. // CopyMem (&Value, Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN]->Data, sizeof (Value)); Value = NTOHS (Value); // // The field of boot file size is 512 bytes in unit. // *BufferSize = 512 * Value; } else { // // Get the bootfile size by tftp command if no option available. // Status = PxeBc->Mtftp ( PxeBc, EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, NULL, FALSE, BufferSize, &Private->BlockSize, &Private->ServerIp, Private->BootFileName, NULL, FALSE ); } // // Save the value of boot file size. // Private->BootFileSize = (UINTN) *BufferSize; // // Display all the information: boot server address, boot file name and boot file size. // AsciiPrint ("\n Server IP address is "); PxeBcShowIp4Addr (&Private->ServerIp.v4); AsciiPrint ("\n NBP filename is %a", Private->BootFileName); AsciiPrint ("\n NBP filesize is %d Bytes", Private->BootFileSize); return Status; }