3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 Miscellaneous support routines for PxeDhcp4 protocol.
25 // #define DebugPrint(x) Aprint x
28 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
34 return (UINT16
) ((n
>> 8) | (n
<< 8));
37 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
43 return (UINT32
) ((n
>> 24) | ((n
>> 8) & 0xFF00) | ((n
& 0xFF00) << 8) | (n
<< 24));
46 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
56 if (Context
!= NULL
) {
57 ((PXE_DHCP4_PRIVATE_DATA
*) Context
)->TimeoutOccurred
= TRUE
;
61 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
71 if (Context
!= NULL
) {
72 ((PXE_DHCP4_PRIVATE_DATA
*) Context
)->PeriodicOccurred
= TRUE
;
76 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
79 IN DHCP4_PACKET
*Packet
,
86 Locate option inside DHCP packet.
89 Packet := Pointer to DHCP packet structure.
90 OpCode := Option op-code to find.
91 Skip := Number of found op-codes to skip.
92 OpPtr := Pointer to found op-code pointer.
95 EFI_SUCCESS := Option was found
96 EFI_INVALID_PARAMETER := Packet == NULL || OpPtr == NULL
97 EFI_INVALID_PARAMETER := OpCode == DHCP4_PAD
98 EFI_INVALID_PARAMETER := OpCode == DHCP4_END && Skip != 0
99 EFI_INVALID_PARAMETER := DHCP magik number in Packet is not valid
100 EFI_NOT_FOUND := op-code was not found in packet
101 EFI_INVALID_PARAMETER := If present, DHCP_MAX_MESSAGE_SIZE option
102 does not have a valid value.
113 // Verify parameters.
115 if (Packet
== NULL
|| OpPtr
== NULL
|| OpCode
== DHCP4_PAD
|| (OpCode
== DHCP4_END
&& Skip
!= 0)) {
116 return EFI_INVALID_PARAMETER
;
119 if (Packet
->dhcp4
.magik
!= htonl (DHCP4_MAGIK_NUMBER
)) {
120 return EFI_INVALID_PARAMETER
;
123 // Initialize search variables.
127 msg_size
= DHCP4_MAX_PACKET_SIZE
- (DHCP4_UDP_HEADER_SIZE
+ DHCP4_IP_HEADER_SIZE
);
132 buf
= Packet
->dhcp4
.options
;
133 buf_len
= msg_size
- (Packet
->dhcp4
.options
- Packet
->raw
);
136 // Start searching for requested option.
140 // If match is found, decrement skip count and return
141 // when desired match is found.
143 if (buf
[n
] == OpCode
) {
144 *OpPtr
= (DHCP4_OP
*) &buf
[n
];
151 // Skip past current option. Check for option overload
152 // and message size options since these will affect the
153 // amount of data to be searched.
158 // Remember the first pad byte of a group. This
159 // could be the end of a badly formed packet.
161 if (end_ptr
== NULL
) {
170 // If we reach the end we are done.
173 return EFI_NOT_FOUND
;
175 case DHCP4_OPTION_OVERLOAD
:
177 // Remember the option overload value since it
178 // could cause the search to continue into
179 // the fname and sname fields.
183 if (buf
[n
+ 1] == 1) {
184 overload
= buf
[n
+ 2];
190 case DHCP4_MAX_MESSAGE_SIZE
:
192 // Remember the message size value since it could
193 // change the amount of option buffer to search.
197 if (buf
[n
+ 1] == 2 && buf
== Packet
->dhcp4
.options
) {
198 msg_size
= ((buf
[n
+ 2] << 8) | buf
[n
+ 3]) - (DHCP4_UDP_HEADER_SIZE
+ DHCP4_IP_HEADER_SIZE
);
200 if (msg_size
< 328) {
201 return EFI_INVALID_PARAMETER
;
204 buf_len
= msg_size
- (Packet
->dhcp4
.options
- Packet
->raw
);
206 if (n
+ 2 + buf
[n
+ 1] > buf_len
) {
207 return EFI_INVALID_PARAMETER
;
218 // Keep searching until the end of the buffer is reached.
224 // Reached end of current buffer. Check if we are supposed
225 // to search the fname and sname buffers.
227 if (buf
== Packet
->dhcp4
.options
&&
228 (overload
== DHCP4_OVERLOAD_FNAME
|| overload
== DHCP4_OVERLOAD_FNAME_AND_SNAME
)
230 buf
= Packet
->dhcp4
.fname
;
236 if (buf
!= Packet
->dhcp4
.sname
&& (overload
== DHCP4_OVERLOAD_SNAME
|| overload
== DHCP4_OVERLOAD_FNAME_AND_SNAME
)) {
237 buf
= Packet
->dhcp4
.sname
;
243 // End of last buffer reached. If this was a search
244 // for the end of the options, go back to the start
245 // of the current pad block.
247 if (OpCode
== DHCP4_END
&& end_ptr
!= NULL
) {
248 *OpPtr
= (DHCP4_OP
*) end_ptr
;
252 return EFI_NOT_FOUND
;
256 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
259 IN DHCP4_PACKET
*Packet
,
264 Add option to DHCP packet.
267 Packet := Pointer to DHCP packet structure.
268 OpPtr := Pointer to DHCP option.
271 EFI_INVALID_PARAMETER := Packet == NULL || OpPtr == NULL
272 EFI_INVALID_PARAMETER := OpPtr->op == DHCP4_PAD || OpPtr->op == DHCP4_END
273 EFI_INVALID_PARAMETER := DHCP magik number in DHCP packet is not valid
274 EFI_INVALID_PARAMETER := If DHCP_MAX_MESSAGE_SIZE option is present and
276 EFI_INVALID_PARAMETER := If DHCP_OPTION_OVERLOAD option is present and
278 EFI_DEVICE_ERROR := Cannot determine end of packet
279 EFI_BUFFER_TOO_SMALL := Not enough room in packet to add option
280 EFI_SUCCESS := Option added to DHCP packet
283 EFI_STATUS efi_status
;
284 DHCP4_OP
*msg_size_op
;
285 DHCP4_OP
*overload_op
;
293 // Verify parameters.
298 if (Packet
== NULL
|| OpPtr
== NULL
) {
299 return EFI_INVALID_PARAMETER
;
306 // No adding PAD or END.
308 return EFI_INVALID_PARAMETER
;
311 // Check the DHCP magik number.
313 CopyMem (&magik
, &Packet
->dhcp4
.magik
, 4);
315 if (magik
!= htonl (DHCP4_MAGIK_NUMBER
)) {
316 return EFI_INVALID_PARAMETER
;
319 // Find the DHCP message size option.
321 msg_size
= DHCP4_DEFAULT_MAX_MESSAGE_SIZE
;
323 efi_status
= find_opt (
325 DHCP4_MAX_MESSAGE_SIZE
,
330 if (EFI_ERROR (efi_status
)) {
331 if (efi_status
!= EFI_NOT_FOUND
) {
343 CopyMem (&msg_size
, msg_size_op
->data
, 2);
344 msg_size
= htons (msg_size
);
346 if (msg_size
< DHCP4_DEFAULT_MAX_MESSAGE_SIZE
) {
347 return EFI_INVALID_PARAMETER
;
351 // Find the DHCP option overload option.
353 efi_status
= find_opt (
355 DHCP4_OPTION_OVERLOAD
,
360 if (EFI_ERROR (efi_status
)) {
361 if (efi_status
!= EFI_NOT_FOUND
) {
373 if (overload_op
->len
!= 1) {
374 return EFI_INVALID_PARAMETER
;
377 switch (overload_op
->data
[0]) {
384 return EFI_INVALID_PARAMETER
;
388 // Find the end of the packet.
390 efi_status
= find_opt (Packet
, DHCP4_END
, 0, &op
);
392 if (EFI_ERROR (efi_status
)) {
393 return EFI_INVALID_PARAMETER
;
396 // Find which buffer the end is in.
398 if ((UINTN
) op
>= (UINTN
) (buf
= Packet
->dhcp4
.options
)) {
399 buf_len
= (msg_size
- ((UINT8
*) &Packet
->dhcp4
.options
- (UINT8
*) &Packet
->raw
)) - (DHCP4_UDP_HEADER_SIZE
+ DHCP4_IP_HEADER_SIZE
);
400 } else if ((UINTN
) op
>= (UINTN
) (buf
= Packet
->dhcp4
.fname
)) {
402 } else if ((UINTN
) op
>= (UINTN
) (buf
= Packet
->dhcp4
.sname
)) {
405 return EFI_DEVICE_ERROR
;
408 // Add option to current buffer if there is no overlow.
410 if ((UINTN
) ((&op
->op
- buf
) + 3 + op
->len
) < buf_len
) {
411 CopyMem (op
, OpPtr
, OpPtr
->len
+ 2);
413 op
->data
[op
->len
] = DHCP4_END
;
418 // Error if there is no space for option.
420 return EFI_BUFFER_TOO_SMALL
;
423 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
426 IN PXE_DHCP4_PRIVATE_DATA
*Private
,
427 IN OPTIONAL EFI_IP_ADDRESS
*StationIp
,
428 IN OPTIONAL EFI_IP_ADDRESS
*SubnetMask
432 Setup PXE BaseCode UDP stack.
435 Private := Pointer to PxeDhcp4 private data.
436 StationIp := Pointer to IP address or NULL if not known.
437 SubnetMask := Pointer to subnet mask or NULL if not known.
440 EFI_INVALID_PARAMETER := Private == NULL || Private->PxeBc == NULL
441 EFI_INVALID_PARAMETER := Only one of StationIp and SubnetMask is given
442 EFI_SUCCESS := UDP stack is ready
443 other := Error from PxeBc->SetIpFilter() or PxeBc->SetStationIp()
446 EFI_PXE_BASE_CODE_IP_FILTER bcast_filter
;
447 EFI_STATUS efi_status
;
453 ASSERT (Private
->PxeBc
);
455 if (Private
== NULL
) {
456 return EFI_INVALID_PARAMETER
;
459 if (Private
->PxeBc
== NULL
) {
460 return EFI_INVALID_PARAMETER
;
463 if (StationIp
!= NULL
&& SubnetMask
== NULL
) {
464 return EFI_INVALID_PARAMETER
;
467 if (StationIp
== NULL
&& SubnetMask
!= NULL
) {
468 return EFI_INVALID_PARAMETER
;
471 // Setup broadcast receive filter...
473 ZeroMem (&bcast_filter
, sizeof (EFI_PXE_BASE_CODE_IP_FILTER
));
475 bcast_filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
;
476 bcast_filter
.IpCnt
= 0;
478 efi_status
= Private
->PxeBc
->SetIpFilter (
483 if (EFI_ERROR (efi_status
)) {
484 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
488 // Configure station IP address and subnet mask...
490 efi_status
= Private
->PxeBc
->SetStationIp (
496 if (EFI_ERROR (efi_status
)) {
497 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
503 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
506 IN PXE_DHCP4_PRIVATE_DATA
*Private
513 ASSERT (Private
->PxeBc
);
516 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
518 start_receive_events (
519 IN PXE_DHCP4_PRIVATE_DATA
*Private
,
520 IN UINTN SecondsTimeout
524 Create periodic and timeout receive events.
527 Private := Pointer to PxeDhcp4 private data.
528 SecondsTimeout := Number of seconds to wait before timeout.
533 EFI_STATUS efi_status
;
540 ASSERT (SecondsTimeout
);
542 if (Private
== NULL
|| SecondsTimeout
== 0) {
543 return EFI_INVALID_PARAMETER
;
546 // Need a bettern randomizer...
547 // For now adjust the timeout value by the least significant
548 // digit in the MAC address.
552 if (Private
->PxeDhcp4
.Data
!= NULL
) {
553 if (Private
->PxeDhcp4
.Data
->Discover
.dhcp4
.hlen
!= 0 && Private
->PxeDhcp4
.Data
->Discover
.dhcp4
.hlen
<= 16) {
554 random
= 0xFFF & Private
->PxeDhcp4
.Data
->Discover
.dhcp4
.chaddr
[Private
->PxeDhcp4
.Data
->Discover
.dhcp4
.hlen
- 1];
558 // Setup timeout event and start timer.
560 efi_status
= gBS
->CreateEvent (
561 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
565 &Private
->TimeoutEvent
568 if (EFI_ERROR (efi_status
)) {
569 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
573 efi_status
= gBS
->SetTimer (
574 Private
->TimeoutEvent
,
576 SecondsTimeout
* 10000000 + random
579 if (EFI_ERROR (efi_status
)) {
580 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
581 gBS
->CloseEvent (Private
->TimeoutEvent
);
585 Private
->TimeoutOccurred
= FALSE
;
588 // Setup periodic event for callbacks
590 efi_status
= gBS
->CreateEvent (
591 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
595 &Private
->PeriodicEvent
598 if (EFI_ERROR (efi_status
)) {
599 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
600 gBS
->CloseEvent (Private
->TimeoutEvent
);
604 efi_status
= gBS
->SetTimer (
605 Private
->PeriodicEvent
,
608 ); /* 1/10th second */
610 if (EFI_ERROR (efi_status
)) {
611 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
612 gBS
->CloseEvent (Private
->TimeoutEvent
);
613 gBS
->CloseEvent (Private
->PeriodicEvent
);
617 Private
->PeriodicOccurred
= FALSE
;
622 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
624 stop_receive_events (
625 IN PXE_DHCP4_PRIVATE_DATA
*Private
633 if (Private
== NULL
) {
639 gBS
->CloseEvent (Private
->TimeoutEvent
);
640 Private
->TimeoutOccurred
= FALSE
;
645 gBS
->CloseEvent (Private
->PeriodicEvent
);
646 Private
->PeriodicOccurred
= FALSE
;
649 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
652 IN PXE_DHCP4_PRIVATE_DATA
*Private
,
653 IN EFI_IP_ADDRESS
*dest_ip
,
654 IN OPTIONAL EFI_IP_ADDRESS
*gateway_ip
,
655 IN EFI_IP_ADDRESS
*src_ip
,
661 Transmit DHCP packet.
664 Private := Pointer to PxeDhcp4 private data
665 dest_ip := Pointer to destination IP address
666 gateway_ip := Pointer to gateway IP address or NULL
667 src_ip := Pointer to source IP address or NULL
668 buffer := Pointer to buffer to transmit
669 BufferSize := Size of buffer in bytes
672 EFI_INVALID_PARAMETER := Private == NULL || dest_ip == NULL ||
673 buffer == NULL || BufferSize < 300 || Private->PxeBc == NULL
674 EFI_SUCCESS := Buffer was transmitted
675 other := Return from PxeBc->UdpWrite()
678 EFI_PXE_BASE_CODE_UDP_PORT dest_port
;
679 EFI_PXE_BASE_CODE_UDP_PORT src_port
;
680 EFI_IP_ADDRESS zero_ip
;
688 ASSERT (BufferSize
>= 300);
690 if (Private
== NULL
|| dest_ip
== NULL
|| buffer
== NULL
|| BufferSize
< 300) {
691 return EFI_INVALID_PARAMETER
;
694 ASSERT (Private
->PxeBc
);
696 if (Private
->PxeBc
== NULL
) {
697 return EFI_INVALID_PARAMETER
;
700 // Transmit DHCP discover packet...
702 ZeroMem (&zero_ip
, sizeof (EFI_IP_ADDRESS
));
704 if (src_ip
== NULL
) {
708 dest_port
= DHCP4_SERVER_PORT
;
709 src_port
= DHCP4_CLIENT_PORT
;
711 return Private
->PxeBc
->UdpWrite (
713 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
726 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
729 IN PXE_DHCP4_PRIVATE_DATA
*Private
,
731 IN OUT UINTN
*BufferSize
,
732 IN OUT EFI_IP_ADDRESS
*dest_ip
,
733 IN OUT EFI_IP_ADDRESS
*src_ip
,
741 Private := Pointer to PxeDhcp4 private data
742 buffer := Pointer to buffer to receive DHCP packet
743 BufferSize := Pointer to buffer size in bytes
744 dest_ip := Pointer to destination IP address
745 src_ip := Pointer to source IP address
746 op_flags := UDP receive operation flags
749 EFI_INVALID_PARAMETER :=
750 EFI_SUCCESS := Packet received
751 other := Return from PxeBc->UdpRead()
754 EFI_PXE_BASE_CODE_UDP_PORT dest_port
;
755 EFI_PXE_BASE_CODE_UDP_PORT src_port
;
765 if (Private
== NULL
|| buffer
== NULL
|| dest_ip
== NULL
|| src_ip
== NULL
|| BufferSize
== NULL
) {
766 return EFI_INVALID_PARAMETER
;
769 ASSERT (Private
->PxeBc
);
771 if (Private
->PxeBc
== NULL
) {
772 return EFI_INVALID_PARAMETER
;
777 *BufferSize
= sizeof (DHCP4_PACKET
);
779 dest_port
= DHCP4_CLIENT_PORT
;
780 src_port
= DHCP4_SERVER_PORT
;
782 return Private
->PxeBc
->UdpRead (
796 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
799 IN PXE_DHCP4_PRIVATE_DATA
*Private
,
800 IN OUT EFI_IP_ADDRESS
*ServerIp
,
801 IN OPTIONAL EFI_IP_ADDRESS
*gateway_ip
,
802 IN OPTIONAL EFI_IP_ADDRESS
*client_ip
,
803 IN OPTIONAL EFI_IP_ADDRESS
*SubnetMask
,
804 IN DHCP4_PACKET
*tx_pkt
,
805 OUT DHCP4_PACKET
*rx_pkt
,
807 IN PXE_DHCP4_PRIVATE_DATA
*Private
,
808 IN DHCP4_PACKET
*tx_pkt
,
809 IN DHCP4_PACKET
*rx_pkt
,
812 IN UINTN SecondsTimeout
816 Transmit DHCP packet and wait for replies.
819 Private := Pointer to PxeDhcp4 private data
820 ServerIp := Pointer to server IP address
821 gateway_ip := Pointer to gateway IP address or NULL
822 client_ip := Pointer to client IP address or NULL
823 SubnetMask := Pointer to subnet mask or NULL
824 tx_pkt := Pointer to DHCP packet to transmit
825 rx_pkt := Pointer to DHCP packet receive buffer
826 rx_vfy := Pointer to DHCP packet receive verification routine
827 SecondsTimeout := Number of seconds until timeout
830 EFI_INVALID_PARAMETER := Private == NULL || ServerIp == NULL ||
831 tx_pkt == NULL || rx_pkt == NULL || rx_vfy == NULL || Private->PxeBc == NULL
832 EFI_ABORTED := Receive aborted
833 EFI_TIMEOUT := No packets received
834 EFI_SUCCESS := Packet(s) received
835 other := Returns from other PxeDhcp4 support routines
838 EFI_PXE_DHCP4_CALLBACK_STATUS CallbackStatus
;
839 EFI_IP_ADDRESS dest_ip
;
840 EFI_IP_ADDRESS src_ip
;
841 EFI_STATUS efi_status
;
842 DHCP4_OP
*msg_size_op
;
851 // Bad programmer check...
859 if (Private
== NULL
|| ServerIp
== NULL
|| tx_pkt
== NULL
|| rx_pkt
== NULL
|| rx_vfy
== NULL
) {
860 return EFI_INVALID_PARAMETER
;
863 ASSERT (Private
->PxeBc
);
865 if (Private
->PxeBc
== NULL
) {
866 return EFI_INVALID_PARAMETER
;
871 efi_status
= start_udp (Private
, client_ip
, SubnetMask
);
873 if (EFI_ERROR (efi_status
)) {
874 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
878 // Get length of transmit packet...
880 msg_size
= DHCP4_DEFAULT_MAX_MESSAGE_SIZE
;
882 efi_status
= find_opt (
884 DHCP4_MAX_MESSAGE_SIZE
,
889 if (!EFI_ERROR (efi_status
)) {
890 CopyMem (&msg_size
, msg_size_op
->data
, 2);
892 if ((msg_size
= htons (msg_size
)) < 328) {
897 // Transmit packet...
899 efi_status
= tx_udp (
905 msg_size
- (DHCP4_UDP_HEADER_SIZE
+ DHCP4_IP_HEADER_SIZE
)
908 if (EFI_ERROR (efi_status
)) {
909 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
914 // Enable periodic and timeout events...
916 efi_status
= start_receive_events (Private
, SecondsTimeout
);
918 if (EFI_ERROR (efi_status
)) {
919 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
924 // Wait for packet(s)...
928 Aprint ("client_ip == NULL ");
931 "client_ip == %d.%d.%d.%d ",
932 client_ip
->v4
.Addr
[0],
933 client_ip
->v4
.Addr
[1],
934 client_ip
->v4
.Addr
[2],
935 client_ip
->v4
.Addr
[3]
940 Aprint ("ServerIp == NULL\n");
943 "ServerIp == %d.%d.%d.%d\n",
944 ServerIp
->v4
.Addr
[0],
945 ServerIp
->v4
.Addr
[1],
946 ServerIp
->v4
.Addr
[2],
957 // Check for timeout event...
959 if (Private
->TimeoutOccurred
) {
960 efi_status
= EFI_SUCCESS
;
964 // Check for periodic event...
966 if (Private
->PeriodicOccurred
&& Private
->callback
!= NULL
) {
967 CallbackStatus
= EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE
;
969 if (Private
->callback
->Callback
!= NULL
) {
970 CallbackStatus
= (Private
->callback
->Callback
) (&Private
->PxeDhcp4
, Private
->function
, 0, NULL
);
973 switch (CallbackStatus
) {
974 case EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE
:
977 case EFI_PXE_DHCP4_CALLBACK_STATUS_ABORT
:
979 stop_receive_events (Private
);
984 Private
->PeriodicOccurred
= FALSE
;
987 // Check for packet...
989 if (client_ip
== NULL
) {
990 SetMem (&dest_ip
, sizeof (EFI_IP_ADDRESS
), 0xFF);
992 CopyMem (&dest_ip
, client_ip
, sizeof (EFI_IP_ADDRESS
));
995 SetMem (&src_ip
, sizeof (EFI_IP_ADDRESS
), 0xFF);
997 if (CompareMem (&src_ip
, &ServerIp
, sizeof (EFI_IP_ADDRESS
))) {
998 ZeroMem (&src_ip
, sizeof (EFI_IP_ADDRESS
));
999 op_flags
= EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
;
1004 efi_status
= rx_udp (
1013 if (efi_status
== EFI_TIMEOUT
) {
1014 efi_status
= EFI_SUCCESS
;
1018 if (EFI_ERROR (efi_status
)) {
1022 // Some basic packet sanity checks..
1024 if (pkt_size
< 300) {
1028 if (rx_pkt
->dhcp4
.op
!= BOOTP_REPLY
) {
1032 if (tx_pkt
->dhcp4
.htype
!= rx_pkt
->dhcp4
.htype
) {
1036 if ((n
= tx_pkt
->dhcp4
.hlen
) != rx_pkt
->dhcp4
.hlen
) {
1040 if (CompareMem (&tx_pkt
->dhcp4
.xid
, &rx_pkt
->dhcp4
.xid
, 4)) {
1049 if (CompareMem (tx_pkt
->dhcp4
.chaddr
, rx_pkt
->dhcp4
.chaddr
, n
)) {
1054 // Internal callback packet verification...
1056 switch ((*rx_vfy
) (Private
, tx_pkt
, rx_pkt
, pkt_size
)) {
1057 case -2: /* ignore and stop */
1058 stop_receive_events (Private
);
1062 case -1: /* ignore and wait */
1065 case 0: /* accept and wait */
1068 case 1: /* accept and stop */
1076 // External callback packet verification...
1078 CallbackStatus
= EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE
;
1080 if (Private
->callback
!= NULL
) {
1081 if (Private
->callback
->Callback
!= NULL
) {
1082 CallbackStatus
= (Private
->callback
->Callback
) (&Private
->PxeDhcp4
, Private
->function
, (UINT32
) pkt_size
, rx_pkt
);
1086 switch (CallbackStatus
) {
1087 case EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_CONTINUE
:
1090 case EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_ABORT
:
1094 case EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_ABORT
:
1095 stop_receive_events (Private
);
1099 case EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE
:
1104 // We did! We did get a packet!
1111 stop_receive_events (Private
);
1114 if (EFI_ERROR (efi_status
)) {
1115 DebugPrint (("%s:%d:%r\n", __FILE__
, __LINE__
, efi_status
));
1126 /* eof - support.c */