33 Len = (UINT8)
MIN (PXEBC_DISPLAY_MAX_LINE, Len);
77 Mode = Private->PxeBc.Mode;
78 Cache = Mode->ProxyOfferReceived ? &Private->ProxyOffer : &Private->DhcpAck;
79 OfferType = Mode->UsingIpv6 ? Cache->Dhcp6.OfferType : Cache->Dhcp4.OfferType;
84 if ((OfferType != PxeOfferTypeProxyPxe10) && (OfferType != PxeOfferTypeDhcpPxe10)) {
91 ASSERT (!Mode->UsingIpv6);
93 VendorOpt = &Cache->Dhcp4.VendorOpt;
100 if (IS_DISABLE_PROMPT_MENU (VendorOpt->DiscoverCtrl) &&
101 (Cache->Dhcp4.OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] !=
NULL))
106 if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) {
110 Timeout = VendorOpt->MenuPrompt->Timeout;
111 Prompt = VendorOpt->MenuPrompt->Prompt;
112 PromptLen = (UINT8)(VendorOpt->MenuPromptLen - 1);
121 if (Timeout == 255) {
128 Status =
gBS->CreateEvent (
135 if (EFI_ERROR (Status)) {
139 Status =
gBS->SetTimer (
144 if (EFI_ERROR (Status)) {
151 Status =
gBS->CreateEvent (
158 if (EFI_ERROR (Status)) {
162 Status =
gBS->SetTimer (
167 if (EFI_ERROR (Status)) {
182 Status = EFI_TIMEOUT;
183 while (EFI_ERROR (
gBS->CheckEvent (TimeoutEvent))) {
184 if (!EFI_ERROR (
gBS->CheckEvent (DescendEvent))) {
190 gBS->Stall (10 * TICKS_PER_MS);
198 if (InputKey.ScanCode == 0) {
199 switch (InputKey.UnicodeChar) {
201 Status = EFI_ABORTED;
214 switch (InputKey.ScanCode) {
220 Status = EFI_ABORTED;
237 if (DescendEvent !=
NULL) {
238 gBS->CloseEvent (DescendEvent);
241 if (TimeoutEvent !=
NULL) {
242 gBS->CloseEvent (TimeoutEvent);
264 IN BOOLEAN UseDefaultItem
279 CHAR8 Blank[PXEBC_DISPLAY_MAX_LINE];
287 Mode = Private->PxeBc.Mode;
288 Cache = Mode->ProxyOfferReceived ? &Private->ProxyOffer : &Private->DhcpAck;
289 OfferType = Mode->UsingIpv6 ? Cache->Dhcp6.OfferType : Cache->Dhcp4.OfferType;
294 ASSERT (!Mode->UsingIpv6);
295 ASSERT (OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeDhcpPxe10);
297 VendorOpt = &Cache->Dhcp4.VendorOpt;
298 if (!IS_VALID_BOOT_MENU (VendorOpt->BitMap)) {
305 SetMem (Blank,
sizeof (Blank),
' ');
307 MenuSize = VendorOpt->BootMenuLen;
308 MenuItem = VendorOpt->BootMenu;
311 return EFI_DEVICE_ERROR;
314 while (MenuSize > 0 && Index < PXEBC_MENU_MAX_NUM) {
315 ASSERT (MenuItem !=
NULL);
316 MenuArray[Index] = MenuItem;
317 MenuSize = (UINT8)(MenuSize - (MenuItem->DescLen + 3));
322 if (UseDefaultItem) {
323 ASSERT (MenuArray[0] !=
NULL);
324 CopyMem (Type, &MenuArray[0]->Type,
sizeof (UINT16));
325 *Type = NTOHS (*Type);
331 for (Index = 0; Index < MenuNum; Index++) {
332 ASSERT (MenuArray[Index] !=
NULL);
347 ASSERT (Select < PXEBC_MENU_MAX_NUM);
348 ASSERT (MenuArray[Select] !=
NULL);
349 Blank[MenuArray[Select]->DescLen] = 0;
355 while (
gST->
ConIn->ReadKeyStroke (
gST->
ConIn, &InputKey) == EFI_NOT_READY) {
356 gBS->Stall (10 * TICKS_PER_MS);
359 if (InputKey.ScanCode == 0) {
360 switch (InputKey.UnicodeChar) {
362 InputKey.ScanCode = SCAN_ESC;
374 InputKey.ScanCode = SCAN_DOWN;
380 InputKey.ScanCode = SCAN_UP;
384 InputKey.ScanCode = 0;
388 switch (InputKey.ScanCode) {
399 if (++Select == MenuNum) {
412 Select = (UINT16)(MenuNum - 1);
424 ASSERT (LastSelect < PXEBC_MENU_MAX_NUM);
425 ASSERT (MenuArray[LastSelect] !=
NULL);
426 Blank[MenuArray[LastSelect]->DescLen] = 0;
435 ASSERT (Select < PXEBC_MENU_MAX_NUM);
436 ASSERT (MenuArray[Select] !=
NULL);
437 CopyMem (Type, &MenuArray[Select]->Type,
sizeof (UINT16));
438 *Type = NTOHS (*Type);
456 OUT UINT64 *BufferSize
467 PxeBc = &Private->PxeBc;
475 if (Mode->PxeReplyReceived) {
476 Cache4 = &Private->PxeReply.Dhcp4;
477 }
else if (Mode->ProxyOfferReceived) {
478 Cache4 = &Private->ProxyOffer.Dhcp4;
480 Cache4 = &Private->DhcpAck.Dhcp4;
483 if (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] ==
NULL) {
495 return EFI_PROTOCOL_ERROR;
504 VendorOpt = &Cache4->VendorOpt;
505 if (IS_DISABLE_PROMPT_MENU (VendorOpt->DiscoverCtrl) && IS_VALID_BOOT_SERVERS (VendorOpt->BitMap)) {
506 Entry = VendorOpt->BootSvr;
516 if (Private->ServerIp.Addr[0] == 0) {
528 if (Private->ServerIp.Addr[0] == 0) {
534 Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->
Data,
542 Private->BootFileName = Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->
Data;
544 if (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] !=
NULL) {
548 CopyMem (&Value, Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN]->
Data, sizeof (Value));
549 Value = NTOHS (Value);
553 *BufferSize = 512 * Value;
558 Status = PxeBc->Mtftp (
560 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
566 Private->BootFileName,
575 Private->BootFileSize = (
UINTN)*BufferSize;
582 AsciiPrint (
"\n NBP filename is %a", Private->BootFileName);
583 AsciiPrint (
"\n NBP filesize is %d Bytes", Private->BootFileSize);
602 OUT UINT64 *BufferSize
611 PxeBc = &Private->PxeBc;
619 if (Mode->PxeReplyReceived) {
620 Cache6 = &Private->PxeReply.Dhcp6;
621 }
else if (Mode->ProxyOfferReceived) {
622 Cache6 = &Private->ProxyOffer.Dhcp6;
624 Cache6 = &Private->DhcpAck.Dhcp6;
627 if (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] ==
NULL) {
639 return EFI_PROTOCOL_ERROR;
646 if (EFI_ERROR (Status)) {
655 &Private->BootFileName,
656 &Private->ServerIp.v6,
657 (CHAR8 *)(Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->
Data),
658 NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->
OpLen)
660 if (EFI_ERROR (Status)) {
667 if (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_PARAM] !=
NULL) {
672 if (EFI_ERROR (Status)) {
679 *BufferSize = 512 * Value;
684 Status = PxeBc->Mtftp (
686 EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
692 Private->BootFileName,
701 Private->BootFileSize = (
UINTN)*BufferSize;
708 AsciiPrint (
"\n NBP filename is %a", Private->BootFileName);
709 AsciiPrint (
"\n NBP filesize is %d Bytes", Private->BootFileSize);
745 Mode = Private->PxeBc.Mode;
746 Info = *DiscoverInfo;
748 if (Mode->UsingIpv6) {
750 Info->UseUCast =
TRUE;
752 Info->SrvList[0].Type = Type;
753 Info->SrvList[0].AcceptAnyResponse =
FALSE;
760 *SrvList = Info->SrvList;
764 Cache4 = (Mode->ProxyOfferReceived) ? &Private->ProxyOffer.Dhcp4 : &Private->DhcpAck.Dhcp4;
765 VendorOpt = &Cache4->VendorOpt;
767 if (!Mode->DhcpAckReceived || !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt->BitMap)) {
771 return EFI_INVALID_PARAMETER;
777 Info->UseMCast = (BOOLEAN) !IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl);
778 Info->UseBCast = (BOOLEAN) !IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl);
779 Info->MustUseList = (BOOLEAN)IS_ENABLE_USE_SERVER_LIST (VendorOpt->DiscoverCtrl);
780 Info->UseUCast = (BOOLEAN)IS_VALID_BOOT_SERVERS (VendorOpt->BitMap);
782 if (Info->UseMCast) {
791 if (Info->UseUCast) {
792 Entry = VendorOpt->BootSvr;
794 while (((UINT8)(Entry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) {
795 if (Entry->Type == HTONS (Type)) {
800 Entry = GET_NEXT_BOOT_SVR_ENTRY (Entry);
804 return EFI_DEVICE_ERROR;
807 Info->IpCnt = Entry->IpCnt;
808 if (Info->IpCnt >= 1) {
809 *DiscoverInfo =
AllocatePool (
sizeof (*Info) + (Info->IpCnt - 1) * sizeof (**SrvList));
810 if (*DiscoverInfo ==
NULL) {
811 return EFI_OUT_OF_RESOURCES;
814 CopyMem (*DiscoverInfo, Info,
sizeof (*Info));
815 Info = *DiscoverInfo;
818 for (Index = 0; Index < Info->IpCnt; Index++) {
820 Info->SrvList[Index].AcceptAnyResponse = !Info->MustUseList;
821 Info->SrvList[Index].Type = NTOHS (Entry->Type);
826 *SrvList = Info->SrvList;
860 if (Private->PxeBc.Mode->UsingIpv6) {
896 OUT UINT64 *BufferSize
906 PxeBc = &Private->PxeBc;
908 Type = EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP;
909 Layer = EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL;
915 Status = PxeBc->Dhcp (PxeBc,
TRUE);
916 if (EFI_ERROR (Status)) {
930 }
else if (Status == EFI_TIMEOUT) {
937 if (!EFI_ERROR (Status)) {
938 if (Type == EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP) {
949 UseBis = (BOOLEAN)(Mode->BisSupported && Mode->BisDetected);
950 Status = PxeBc->Discover (PxeBc, Type, &Layer, UseBis,
NULL);
951 if (EFI_ERROR (Status)) {
955 if (Mode->PxeReplyReceived && !Mode->ProxyOfferReceived) {
960 if (Mode->UsingIpv6) {
962 &Mode->ProxyOffer.Dhcpv6,
963 &Mode->PxeReply.Dhcpv6,
964 Private->PxeReply.Dhcp6.Packet.Ack.Length
968 &Mode->ProxyOffer.Dhcpv4,
969 &Mode->PxeReply.Dhcpv4,
970 Private->PxeReply.Dhcp4.Packet.Ack.Length
974 Mode->ProxyOfferReceived =
TRUE;
981 if (Mode->UsingIpv6) {
1003 OUT BOOLEAN *NewMakeCallback
1012 PxeBc = &Private->PxeBc;
1013 Status =
gBS->HandleProtocol (
1014 Private->Mode.UsingIpv6 ? Private->Ip6Nic->Controller : Private->Ip4Nic->Controller,
1015 &gEfiPxeBaseCodeCallbackProtocolGuid,
1016 (VOID **)&Private->PxeBcCallback
1018 if (Status == EFI_UNSUPPORTED) {
1020 &Private->LoadFileCallback,
1021 &gPxeBcCallBackTemplate,
1028 Status =
gBS->InstallProtocolInterface (
1029 Private->Mode.UsingIpv6 ? &Private->Ip6Nic->Controller : &Private->Ip4Nic->Controller,
1030 &gEfiPxeBaseCodeCallbackProtocolGuid,
1032 &Private->LoadFileCallback
1035 (*NewMakeCallback) = (BOOLEAN)(Status ==
EFI_SUCCESS);
1037 Status = PxeBc->SetParameters (PxeBc,
NULL,
NULL,
NULL,
NULL, NewMakeCallback);
1038 if (EFI_ERROR (Status)) {
1039 PxeBc->Stop (PxeBc);
1058 IN BOOLEAN NewMakeCallback
1063 PxeBc = &Private->PxeBc;
1065 if (NewMakeCallback) {
1066 NewMakeCallback =
FALSE;
1070 gBS->UninstallProtocolInterface (
1071 Private->Mode.UsingIpv6 ? Private->Ip6Nic->Controller : Private->Ip4Nic->Controller,
1072 &gEfiPxeBaseCodeCallbackProtocolGuid,
1073 &Private->LoadFileCallback
1095 IN OUT UINT64 *BufferSize,
1096 IN VOID *Buffer OPTIONAL
1102 PxeBc = &Private->PxeBc;
1107 if (Buffer !=
NULL) {
1108 Status = PxeBc->Mtftp (
1110 EFI_PXE_BASE_CODE_TFTP_READ_FILE,
1114 &Private->BlockSize,
1116 Private->BootFileName,
1121 Status = EFI_BUFFER_TOO_SMALL;
1145 IN VOID *Buffer OPTIONAL
1148 BOOLEAN NewMakeCallback;
1149 UINT64 RequiredSize;
1155 NewMakeCallback =
FALSE;
1156 PxeBc = &Private->PxeBc;
1157 PxeBcMode = &Private->Mode;
1158 CurrentSize = *BufferSize;
1165 if (EFI_ERROR (Status)) {
1169 if (Private->BootFileSize == 0) {
1174 if (EFI_ERROR (Status)) {
1178 if (PXEBC_IS_SIZE_OVERFLOWED (RequiredSize)) {
1182 Status = EFI_DEVICE_ERROR;
1184 }
else if (RequiredSize > 0) {
1188 if ((CurrentSize < RequiredSize) || (Buffer ==
NULL)) {
1192 CurrentSize = RequiredSize;
1193 Status = EFI_BUFFER_TOO_SMALL;
1197 CurrentSize = RequiredSize;
1198 }
else if ((RequiredSize == 0) && PxeBcMode->UsingIpv6) {
1206 }
else if ((CurrentSize < Private->BootFileSize) || (Buffer ==
NULL)) {
1210 CurrentSize = Private->BootFileSize;
1211 Status = EFI_BUFFER_TOO_SMALL;
1219 if (PxeBcMode->UsingIpv6) {
1226 Status = PxeBc->Mtftp (
1228 EFI_PXE_BASE_CODE_TFTP_READ_FILE,
1232 &Private->BlockSize,
1234 Private->BootFileName,
1241 *BufferSize = (
UINTN)CurrentSize;
1245 AsciiPrint (
"\n NBP file downloaded successfully.\n");
1247 }
else if ((Status == EFI_BUFFER_TOO_SMALL) && (Buffer !=
NULL)) {
1248 AsciiPrint (
"\n PXE-E05: Buffer size is smaller than the requested file.\n");
1249 }
else if (Status == EFI_DEVICE_ERROR) {
1250 AsciiPrint (
"\n PXE-E07: Network device error.\n");
1251 }
else if (Status == EFI_OUT_OF_RESOURCES) {
1252 AsciiPrint (
"\n PXE-E09: Could not allocate I/O buffers.\n");
1253 }
else if (Status == EFI_NO_MEDIA) {
1254 AsciiPrint (
"\n PXE-E12: Could not detect network connection.\n");
1255 }
else if (Status == EFI_NO_RESPONSE) {
1256 AsciiPrint (
"\n PXE-E16: No valid offer received.\n");
1257 }
else if (Status == EFI_TIMEOUT) {
1258 AsciiPrint (
"\n PXE-E18: Server response timeout.\n");
1259 }
else if (Status == EFI_ABORTED) {
1260 AsciiPrint (
"\n PXE-E21: Remote boot cancelled.\n");
1261 }
else if (Status == EFI_ICMP_ERROR) {
1262 AsciiPrint (
"\n PXE-E22: Client received ICMP error from server.\n");
1263 }
else if (Status == EFI_TFTP_ERROR) {
1264 AsciiPrint (
"\n PXE-E23: Client received TFTP error from server.\n");
1265 }
else if (Status == EFI_NOT_FOUND) {
1266 AsciiPrint (
"\n PXE-E53: No boot filename received.\n");
1267 }
else if (Status != EFI_BUFFER_TOO_SMALL) {
1268 AsciiPrint (
"\n PXE-E99: Unexpected network error.\n");
1274 (VOID *)&(PxeBcMode->UsingIpv6),
1275 sizeof (PxeBcMode->UsingIpv6)
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
#define REPORT_STATUS_CODE_WITH_EXTENDED_DATA(Type, Value, ExtendedData, ExtendedDataSize)
UINT32 EFI_STATUS_CODE_VALUE
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_STATUS PxeBcReadBootFileList(IN PXEBC_PRIVATE_DATA *Private, IN OUT UINT64 *BufferSize, IN VOID *Buffer OPTIONAL)
VOID PxeBcDisplayBootItem(IN UINT8 *Str, IN UINT8 Len)
VOID PxeBcUninstallCallback(IN PXEBC_PRIVATE_DATA *Private, IN BOOLEAN NewMakeCallback)
EFI_STATUS PxeBcSelectBootPrompt(IN PXEBC_PRIVATE_DATA *Private)
EFI_STATUS PxeBcDiscoverBootServer(IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, IN UINT16 *Layer, IN BOOLEAN UseBis, IN EFI_IP_ADDRESS *DestIp, IN UINT16 IpCount, IN EFI_PXE_BASE_CODE_SRVLIST *SrvList)
EFI_STATUS PxeBcSelectBootMenu(IN PXEBC_PRIVATE_DATA *Private, OUT UINT16 *Type, IN BOOLEAN UseDefaultItem)
EFI_STATUS PxeBcExtractDiscoverInfo(IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO **DiscoverInfo, OUT PXEBC_BOOT_SVR_ENTRY **BootEntry, OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList)
EFI_STATUS PxeBcDiscoverBootFile(IN OUT PXEBC_PRIVATE_DATA *Private, OUT UINT64 *BufferSize)
EFI_STATUS PxeBcLoadBootFile(IN PXEBC_PRIVATE_DATA *Private, IN OUT UINTN *BufferSize, IN VOID *Buffer OPTIONAL)
EFI_STATUS PxeBcDhcp6BootInfo(IN OUT PXEBC_PRIVATE_DATA *Private, OUT UINT64 *BufferSize)
EFI_STATUS PxeBcInstallCallback(IN OUT PXEBC_PRIVATE_DATA *Private, OUT BOOLEAN *NewMakeCallback)
EFI_STATUS PxeBcDhcp4BootInfo(IN OUT PXEBC_PRIVATE_DATA *Private, OUT UINT64 *BufferSize)
EFI_STATUS PxeBcDhcp4Discover(IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, IN UINT16 *Layer, IN BOOLEAN UseBis, IN EFI_IP_ADDRESS *DestIp, IN UINT16 IpCount, IN EFI_PXE_BASE_CODE_SRVLIST *SrvList)
EFI_STATUS PxeBcSetIp6Address(IN PXEBC_PRIVATE_DATA *Private)
EFI_STATUS PxeBcExtractBootFileUrl(IN PXEBC_PRIVATE_DATA *Private, OUT UINT8 **FileName, IN OUT EFI_IPv6_ADDRESS *SrvAddr, IN CHAR8 *BootFile, IN UINT16 Length)
EFI_STATUS PxeBcExtractBootFileParam(IN CHAR8 *BootFilePara, OUT UINT16 *BootFileSize)
EFI_STATUS PxeBcDhcp6Discover(IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, IN UINT16 *Layer, IN BOOLEAN UseBis, IN EFI_IP_ADDRESS *DestIp)
VOID PxeBcShowIp6Addr(IN EFI_IPv6_ADDRESS *Ip)
VOID PxeBcShowIp4Addr(IN EFI_IPv4_ADDRESS *Ip)
UINTN EFIAPI AsciiPrint(IN CONST CHAR8 *Format,...)
EFI_PXE_BASE_CODE_MODE * Mode
EFI_SIMPLE_TEXT_OUTPUT_MODE * Mode
EFI_IPv4_ADDRESS ServerAddr
IP address of next server in bootstrap.
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * ConIn
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut