3 Copyright (c) 2005 - 2007, 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.
26 Get the IP child's current operational data. This can
27 all be used to get the underlying MNP and SNP data.
29 @param This The IP4 protocol instance
30 @param Ip4ModeData The IP4 operation data
31 @param MnpConfigData The MNP configure data
32 @param SnpModeData The SNP operation data
34 @retval EFI_INVALID_PARAMETER The parameter is invalid because This == NULL
35 @retval EFI_SUCCESS The operational parameter is returned.
36 @retval Others Failed to retrieve the IP4 route table.
42 IN CONST EFI_IP4_PROTOCOL
*This
,
43 OUT EFI_IP4_MODE_DATA
*Ip4ModeData
, OPTIONAL
44 OUT EFI_MANAGED_NETWORK_CONFIG_DATA
*MnpConfigData
, OPTIONAL
45 OUT EFI_SIMPLE_NETWORK_MODE
*SnpModeData OPTIONAL
48 IP4_PROTOCOL
*IpInstance
;
50 EFI_IP4_CONFIG_DATA
*Config
;
56 return EFI_INVALID_PARAMETER
;
59 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
60 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
61 IpSb
= IpInstance
->Service
;
63 if (Ip4ModeData
!= NULL
) {
65 // IsStarted is "whether the EfiIp4Configure has been called".
66 // IsConfigured is "whether the station address has been configured"
68 Ip4ModeData
->IsStarted
= (BOOLEAN
)(IpInstance
->State
== IP4_STATE_CONFIGED
);
69 CopyMem (&Ip4ModeData
->ConfigData
, &IpInstance
->ConfigData
, sizeof (Ip4ModeData
->ConfigData
));
70 Ip4ModeData
->IsConfigured
= FALSE
;
72 Ip4ModeData
->GroupCount
= IpInstance
->GroupCount
;
73 Ip4ModeData
->GroupTable
= (EFI_IPv4_ADDRESS
*) IpInstance
->Groups
;
75 Ip4ModeData
->IcmpTypeCount
= 23;
76 Ip4ModeData
->IcmpTypeList
= mIp4SupportedIcmp
;
78 Ip4ModeData
->RouteTable
= NULL
;
79 Ip4ModeData
->RouteCount
= 0;
82 // return the current station address for this IP child. So,
83 // the user can get the default address through this. Some
84 // application wants to know it station address even it is
85 // using the default one, such as a ftp server.
87 if (Ip4ModeData
->IsStarted
) {
88 Config
= &Ip4ModeData
->ConfigData
;
90 Ip
= HTONL (IpInstance
->Interface
->Ip
);
91 CopyMem (&Config
->StationAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
93 Ip
= HTONL (IpInstance
->Interface
->SubnetMask
);
94 CopyMem (&Config
->SubnetMask
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
96 Ip4ModeData
->IsConfigured
= IpInstance
->Interface
->Configured
;
99 // Build a EFI route table for user from the internal route table.
101 Status
= Ip4BuildEfiRouteTable (IpInstance
);
103 if (EFI_ERROR (Status
)) {
104 gBS
->RestoreTPL (OldTpl
);
108 Ip4ModeData
->RouteTable
= IpInstance
->EfiRouteTable
;
109 Ip4ModeData
->RouteCount
= IpInstance
->EfiRouteCount
;
113 if (MnpConfigData
!= NULL
) {
114 CopyMem (MnpConfigData
, &IpSb
->MnpConfigData
, sizeof (*MnpConfigData
));
117 if (SnpModeData
!= NULL
) {
118 CopyMem (SnpModeData
, &IpSb
->SnpMode
, sizeof (*SnpModeData
));
121 gBS
->RestoreTPL (OldTpl
);
127 Config the MNP parameter used by IP. The IP driver use one MNP
128 child to transmit/receive frames. By default, it configures MNP
129 to receive unicast/multicast/broadcast. And it will enable/disable
130 the promiscous receive according to whether there is IP child
131 enable that or not. If Force isn't false, it will iterate through
132 all the IP children to check whether the promiscuous receive
133 setting has been changed. If it hasn't been changed, it won't
134 reconfigure the MNP. If Force is true, the MNP is configured no
135 matter whether that is changed or not.
137 @param IpSb The IP4 service instance that is to be changed.
138 @param Force Force the configuration or not.
140 @retval EFI_SUCCESS The MNP is successfully configured/reconfigured.
141 @retval Others Configuration failed.
145 Ip4ServiceConfigMnp (
146 IN IP4_SERVICE
*IpSb
,
151 LIST_ENTRY
*ProtoEntry
;
153 IP4_PROTOCOL
*IpInstance
;
155 BOOLEAN PromiscReceive
;
159 PromiscReceive
= FALSE
;
163 // Iterate through the IP children to check whether promiscuous
164 // receive setting has been changed. Update the interface's receive
167 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
169 IpIf
= NET_LIST_USER_STRUCT (Entry
, IP4_INTERFACE
, Link
);
170 IpIf
->PromiscRecv
= FALSE
;
172 NET_LIST_FOR_EACH (ProtoEntry
, &IpIf
->IpInstances
) {
173 IpInstance
= NET_LIST_USER_STRUCT (ProtoEntry
, IP4_PROTOCOL
, AddrLink
);
175 if (IpInstance
->ConfigData
.AcceptPromiscuous
) {
176 IpIf
->PromiscRecv
= TRUE
;
177 PromiscReceive
= TRUE
;
183 // If promiscuous receive isn't changed, it isn't necessary to reconfigure.
185 if (PromiscReceive
== IpSb
->MnpConfigData
.EnablePromiscuousReceive
) {
190 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= PromiscReceive
;
193 Status
= IpSb
->Mnp
->Configure (IpSb
->Mnp
, &IpSb
->MnpConfigData
);
196 // recover the original configuration if failed to set the configure.
198 if (EFI_ERROR (Status
) && Reconfig
) {
199 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= (BOOLEAN
) !PromiscReceive
;
207 The event handle for IP4 auto configuration. If IP is asked
208 to reconfigure the default address. The original default
209 interface and route table are removed as the default. If there
210 is active IP children using the default address, the interface
211 will remain valid until all the children have freed their
212 references. If IP is signalled when auto configuration is done,
213 it will configure the default interface and default route table
214 with the configuration information retrieved by IP4_CONFIGURE.
216 @param Context The IP4 service binding instance.
223 Ip4AutoConfigCallBackDpc (
227 EFI_IP4_CONFIG_PROTOCOL
*Ip4Config
;
228 EFI_IP4_IPCONFIG_DATA
*Data
;
229 EFI_IP4_ROUTE_TABLE
*RouteEntry
;
231 IP4_ROUTE_TABLE
*RouteTable
;
237 IpSb
= (IP4_SERVICE
*) Context
;
238 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
240 Ip4Config
= IpSb
->Ip4Config
;
243 // IP is asked to do the reconfiguration. If the default interface
244 // has been configured, release the default interface and route
245 // table, then create a new one. If there are some IP children
246 // using it, the interface won't be physically freed until all the
247 // children have released their reference to it. Also remember to
248 // restart the receive on the default address. IP4 driver only receive
249 // frames on the default address, and when the default interface is
250 // freed, Ip4AcceptFrame won't be informed.
252 if (IpSb
->ActiveEvent
== IpSb
->ReconfigEvent
) {
254 if (IpSb
->DefaultInterface
->Configured
) {
255 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
261 RouteTable
= Ip4CreateRouteTable ();
263 if (RouteTable
== NULL
) {
264 Ip4FreeInterface (IpIf
, NULL
);
268 Ip4CancelReceive (IpSb
->DefaultInterface
);
269 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
270 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
272 IpSb
->DefaultInterface
= IpIf
;
273 InsertHeadList (&IpSb
->Interfaces
, &IpIf
->Link
);
275 IpSb
->DefaultRouteTable
= RouteTable
;
276 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
279 Ip4Config
->Stop (Ip4Config
);
280 Ip4Config
->Start (Ip4Config
, IpSb
->DoneEvent
, IpSb
->ReconfigEvent
);
285 // Get the configure data in two steps: get the length then the data.
289 if (Ip4Config
->GetData (Ip4Config
, &Len
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
293 Data
= AllocatePool (Len
);
299 Status
= Ip4Config
->GetData (Ip4Config
, &Len
, Data
);
301 if (EFI_ERROR (Status
)) {
305 IpIf
= IpSb
->DefaultInterface
;
308 // If the default address has been configured don't change it.
309 // This is unlikely to happen if EFI_IP4_CONFIG protocol has
310 // informed us to reconfigure each time it wants to change the
311 // configuration parameters.
313 if (IpIf
->Configured
) {
318 // Set the default interface's address, then add a directed
319 // route for it, that is, the route whose nexthop is zero.
321 Status
= Ip4SetAddress (
323 EFI_NTOHL (Data
->StationAddress
),
324 EFI_NTOHL (Data
->SubnetMask
)
327 if (EFI_ERROR (Status
)) {
332 IpSb
->DefaultRouteTable
,
333 EFI_NTOHL (Data
->StationAddress
),
334 EFI_NTOHL (Data
->SubnetMask
),
339 // Add routes returned by EFI_IP4_CONFIG protocol.
341 for (Index
= 0; Index
< Data
->RouteTableSize
; Index
++) {
342 RouteEntry
= &Data
->RouteTable
[Index
];
345 IpSb
->DefaultRouteTable
,
346 EFI_NTOHL (RouteEntry
->SubnetAddress
),
347 EFI_NTOHL (RouteEntry
->SubnetMask
),
348 EFI_NTOHL (RouteEntry
->GatewayAddress
)
352 IpSb
->State
= IP4_SERVICE_CONFIGED
;
354 Ip4SetVariableData (IpSb
);
357 gBS
->FreePool (Data
);
362 Ip4AutoConfigCallBack (
370 Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK
374 Event - The event that is signalled.
375 Context - The IP4 service binding instance.
385 IpSb
= (IP4_SERVICE
*) Context
;
386 IpSb
->ActiveEvent
= Event
;
389 // Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK
391 NetLibQueueDpc (TPL_CALLBACK
, Ip4AutoConfigCallBackDpc
, Context
);
396 Start the auto configuration for this IP service instance.
397 It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the
400 @param IpSb The IP4 service instance to configure
402 @retval EFI_SUCCESS The auto configuration is successfull started
403 @retval Others Failed to start auto configuration.
411 EFI_IP4_CONFIG_PROTOCOL
*Ip4Config
;
414 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
419 // Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG
421 Status
= gBS
->CreateEvent (
424 Ip4AutoConfigCallBack
,
429 if (EFI_ERROR (Status
)) {
433 Status
= gBS
->CreateEvent (
436 Ip4AutoConfigCallBack
,
441 if (EFI_ERROR (Status
)) {
442 goto CLOSE_DONE_EVENT
;
446 // Open the EFI_IP4_CONFIG protocol then start auto configure
448 Status
= gBS
->OpenProtocol (
450 &gEfiIp4ConfigProtocolGuid
,
451 (VOID
**) &Ip4Config
,
454 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
457 if (EFI_ERROR (Status
)) {
458 Status
= EFI_UNSUPPORTED
;
459 goto CLOSE_RECONFIG_EVENT
;
462 Status
= Ip4Config
->Start (Ip4Config
, IpSb
->DoneEvent
, IpSb
->ReconfigEvent
);
464 if (EFI_ERROR (Status
)) {
467 &gEfiIp4ConfigProtocolGuid
,
472 goto CLOSE_RECONFIG_EVENT
;
475 IpSb
->Ip4Config
= Ip4Config
;
476 IpSb
->State
= IP4_SERVICE_STARTED
;
479 CLOSE_RECONFIG_EVENT
:
480 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
481 IpSb
->ReconfigEvent
= NULL
;
484 gBS
->CloseEvent (IpSb
->DoneEvent
);
485 IpSb
->DoneEvent
= NULL
;
492 Intiialize the IP4_PROTOCOL structure to the unconfigured states.
494 @param IpSb The IP4 service instance.
495 @param IpInstance The IP4 child instance.
502 IN IP4_SERVICE
*IpSb
,
503 IN IP4_PROTOCOL
*IpInstance
506 ASSERT ((IpSb
!= NULL
) && (IpInstance
!= NULL
));
508 ZeroMem (IpInstance
, sizeof (IP4_PROTOCOL
));
510 IpInstance
->Signature
= IP4_PROTOCOL_SIGNATURE
;
511 CopyMem (&IpInstance
->Ip4Proto
, &mEfiIp4ProtocolTemplete
, sizeof (IpInstance
->Ip4Proto
));
512 IpInstance
->State
= IP4_STATE_UNCONFIGED
;
513 IpInstance
->Service
= IpSb
;
515 InitializeListHead (&IpInstance
->Link
);
516 NetMapInit (&IpInstance
->RxTokens
);
517 NetMapInit (&IpInstance
->TxTokens
);
518 InitializeListHead (&IpInstance
->Received
);
519 InitializeListHead (&IpInstance
->Delivered
);
520 InitializeListHead (&IpInstance
->AddrLink
);
522 EfiInitializeLock (&IpInstance
->RecycleLock
, TPL_NOTIFY
);
527 Configure the IP4 child. If the child is already configured,
528 change the configuration parameter. Otherwise configure it
529 for the first time. The caller should validate the configuration
530 before deliver them to it. It also don't do configure NULL.
532 @param IpInstance The IP4 child to configure.
533 @param Config The configure data.
535 @retval EFI_SUCCESS The IP4 child is successfully configured.
536 @retval EFI_DEVICE_ERROR Failed to free the pending transive or to
537 configure underlying MNP or other errors.
538 @retval EFI_NO_MAPPING The IP4 child is configured to use default
539 address, but the default address hasn't been
540 configured. The IP4 child doesn't need to be
541 reconfigured when default address is configured.
546 IN IP4_PROTOCOL
*IpInstance
,
547 IN EFI_IP4_CONFIG_DATA
*Config
556 IpSb
= IpInstance
->Service
;
559 // User is changing packet filters. It must be stopped
560 // before the station address can be changed.
562 if (IpInstance
->State
== IP4_STATE_CONFIGED
) {
564 // Cancel all the pending transmit/receive from upper layer
566 Status
= Ip4Cancel (IpInstance
, NULL
);
568 if (EFI_ERROR (Status
)) {
569 return EFI_DEVICE_ERROR
;
572 CopyMem (&IpInstance
->ConfigData
, Config
, sizeof (IpInstance
->ConfigData
));
577 // Configure a fresh IP4 protocol instance. Create a route table.
578 // Each IP child has its own route table, which may point to the
579 // default table if it is using default address.
581 Status
= EFI_OUT_OF_RESOURCES
;
582 IpInstance
->RouteTable
= Ip4CreateRouteTable ();
584 if (IpInstance
->RouteTable
== NULL
) {
589 // Set up the interface.
591 CopyMem (&Ip
, &Config
->StationAddress
, sizeof (IP4_ADDR
));
592 CopyMem (&Netmask
, &Config
->SubnetMask
, sizeof (IP4_ADDR
));
595 Netmask
= NTOHL (Netmask
);
597 if (!Config
->UseDefaultAddress
) {
599 // Find whether there is already an interface with the same
600 // station address. All the instances with the same station
601 // address shares one interface.
603 IpIf
= Ip4FindStationAddress (IpSb
, Ip
, Netmask
);
609 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
615 Status
= Ip4SetAddress (IpIf
, Ip
, Netmask
);
617 if (EFI_ERROR (Status
)) {
618 Status
= EFI_DEVICE_ERROR
;
619 Ip4FreeInterface (IpIf
, IpInstance
);
623 InsertTailList (&IpSb
->Interfaces
, &IpIf
->Link
);
627 // Add a route to this connected network in the route table
629 Ip4AddRoute (IpInstance
->RouteTable
, Ip
, Netmask
, IP4_ALLZERO_ADDRESS
);
633 // Use the default address. If the default configuration hasn't
634 // been started, start it.
636 if (IpSb
->State
== IP4_SERVICE_UNSTARTED
) {
637 Status
= Ip4StartAutoConfig (IpSb
);
639 if (EFI_ERROR (Status
)) {
644 IpIf
= IpSb
->DefaultInterface
;
645 NET_GET_REF (IpSb
->DefaultInterface
);
648 // If default address is used, so is the default route table.
649 // Any route set by the instance has the precedence over the
650 // routes in the default route table. Link the default table
651 // after the instance's table. Routing will search the local
654 NET_GET_REF (IpSb
->DefaultRouteTable
);
655 IpInstance
->RouteTable
->Next
= IpSb
->DefaultRouteTable
;
658 IpInstance
->Interface
= IpIf
;
659 InsertTailList (&IpIf
->IpInstances
, &IpInstance
->AddrLink
);
661 CopyMem (&IpInstance
->ConfigData
, Config
, sizeof (IpInstance
->ConfigData
));
662 IpInstance
->State
= IP4_STATE_CONFIGED
;
665 // Although EFI_NO_MAPPING is an error code, the IP child has been
666 // successfully configured and doesn't need reconfiguration when
667 // default address is acquired.
669 if (Config
->UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
670 return EFI_NO_MAPPING
;
676 Ip4FreeRouteTable (IpInstance
->RouteTable
);
677 IpInstance
->RouteTable
= NULL
;
683 Clean up the IP4 child, release all the resources used by it.
685 @param IpInstance The IP4 child to clean up.
687 @retval EFI_SUCCESS The IP4 child is cleaned up
688 @retval EFI_DEVICE_ERROR Some resources failed to be released
693 IN IP4_PROTOCOL
*IpInstance
696 if (EFI_ERROR (Ip4Cancel (IpInstance
, NULL
))) {
697 return EFI_DEVICE_ERROR
;
700 if (EFI_ERROR (Ip4Groups (IpInstance
, FALSE
, NULL
))) {
701 return EFI_DEVICE_ERROR
;
705 // Some packets haven't been recycled. It is because either the
706 // user forgets to recycle the packets, or because the callback
707 // hasn't been called. Just leave it alone.
709 if (!IsListEmpty (&IpInstance
->Delivered
)) {
713 if (IpInstance
->Interface
!= NULL
) {
714 RemoveEntryList (&IpInstance
->AddrLink
);
715 Ip4FreeInterface (IpInstance
->Interface
, IpInstance
);
716 IpInstance
->Interface
= NULL
;
719 if (IpInstance
->RouteTable
!= NULL
) {
720 if (IpInstance
->RouteTable
->Next
!= NULL
) {
721 Ip4FreeRouteTable (IpInstance
->RouteTable
->Next
);
724 Ip4FreeRouteTable (IpInstance
->RouteTable
);
725 IpInstance
->RouteTable
= NULL
;
728 if (IpInstance
->EfiRouteTable
!= NULL
) {
729 gBS
->FreePool (IpInstance
->EfiRouteTable
);
730 IpInstance
->EfiRouteTable
= NULL
;
731 IpInstance
->EfiRouteCount
= 0;
734 if (IpInstance
->Groups
!= NULL
) {
735 gBS
->FreePool (IpInstance
->Groups
);
736 IpInstance
->Groups
= NULL
;
737 IpInstance
->GroupCount
= 0;
740 NetMapClean (&IpInstance
->TxTokens
);
742 NetMapClean (&IpInstance
->RxTokens
);
749 Validate that Ip/Netmask pair is OK to be used as station
750 address. Only continuous netmasks are supported. and check
751 that StationAddress is a unicast address on the newtwork.
753 @param Ip The IP address to validate
754 @param Netmask The netmaks of the IP
756 @retval TRUE The Ip/Netmask pair is valid
761 Ip4StationAddressValid (
766 IP4_ADDR NetBrdcastMask
;
771 // Only support the station address with 0.0.0.0/0 to enable DHCP client.
773 if (Netmask
== IP4_ALLZERO_ADDRESS
) {
774 return (BOOLEAN
) (Ip
== IP4_ALLZERO_ADDRESS
);
778 // Only support the continuous net masks
780 if ((Len
= NetGetMaskLength (Netmask
)) == IP4_MASK_NUM
) {
785 // Station address can't be class D or class E address
787 if ((Type
= NetGetIpClass (Ip
)) > IP4_ADDR_CLASSC
) {
792 // Station address can't be subnet broadcast/net broadcast address
794 if ((Ip
== (Ip
& Netmask
)) || (Ip
== (Ip
| ~Netmask
))) {
798 NetBrdcastMask
= gIp4AllMasks
[MIN (Len
, Type
<< 3)];
800 if (Ip
== (Ip
| ~NetBrdcastMask
)) {
809 Configure the EFI_IP4_PROTOCOL instance. If IpConfigData is NULL,
810 the instance is cleaned up. If the instance hasn't been configure
811 before, it will be initialized. Otherwise, the filter setting of
812 the instance is updated.
814 @param This The IP4 child to configure
815 @param IpConfigData The configuration to apply. If NULL, clean it up.
817 @retval EFI_INVALID_PARAMETER The parameter is invalid
818 @retval EFI_NO_MAPPING The default address hasn't been configured and the
819 instance wants to use it.
820 @retval EFI_SUCCESS The instance is configured.
826 IN EFI_IP4_PROTOCOL
*This
,
827 IN EFI_IP4_CONFIG_DATA
*IpConfigData OPTIONAL
830 IP4_PROTOCOL
*IpInstance
;
831 EFI_IP4_CONFIG_DATA
*Current
;
839 // First, validate the parameters
842 return EFI_INVALID_PARAMETER
;
845 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
846 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
849 // Validate the configuration first.
851 if (IpConfigData
!= NULL
) {
853 // This implementation doesn't support RawData
855 if (IpConfigData
->RawData
) {
856 Status
= EFI_UNSUPPORTED
;
861 CopyMem (&IpAddress
, &IpConfigData
->StationAddress
, sizeof (IP4_ADDR
));
862 CopyMem (&SubnetMask
, &IpConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
864 IpAddress
= NTOHL (IpAddress
);
865 SubnetMask
= NTOHL (SubnetMask
);
868 // Check whether the station address is a valid unicast address
870 if (!IpConfigData
->UseDefaultAddress
) {
871 AddrOk
= Ip4StationAddressValid (IpAddress
, SubnetMask
);
874 Status
= EFI_INVALID_PARAMETER
;
880 // User can only update packet filters when already configured.
881 // If it wants to change the station address, it must configure(NULL)
882 // the instance first.
884 if (IpInstance
->State
== IP4_STATE_CONFIGED
) {
885 Current
= &IpInstance
->ConfigData
;
887 if (Current
->UseDefaultAddress
!= IpConfigData
->UseDefaultAddress
) {
888 Status
= EFI_ALREADY_STARTED
;
892 if (!Current
->UseDefaultAddress
&&
893 (!EFI_IP4_EQUAL (&Current
->StationAddress
, &IpConfigData
->StationAddress
) ||
894 !EFI_IP4_EQUAL (&Current
->SubnetMask
, &IpConfigData
->SubnetMask
))) {
895 Status
= EFI_ALREADY_STARTED
;
899 if (Current
->UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
900 return EFI_NO_MAPPING
;
906 // Configure the instance or clean it up.
908 if (IpConfigData
!= NULL
) {
909 Status
= Ip4ConfigProtocol (IpInstance
, IpConfigData
);
911 Status
= Ip4CleanProtocol (IpInstance
);
914 // Don't change the state if it is DESTORY, consider the following
915 // valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,
916 // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED,
917 // the unload fails miserably.
919 if (IpInstance
->State
== IP4_STATE_CONFIGED
) {
920 IpInstance
->State
= IP4_STATE_UNCONFIGED
;
925 // Update the MNP's configure data. Ip4ServiceConfigMnp will check
926 // whether it is necessary to reconfigure the MNP.
928 Ip4ServiceConfigMnp (IpInstance
->Service
, FALSE
);
931 // Update the variable data.
933 Ip4SetVariableData (IpInstance
->Service
);
936 gBS
->RestoreTPL (OldTpl
);
943 Change the IP4 child's multicast setting. The caller
944 should make sure that the parameters is valid.
946 @param IpInstance The IP4 child to change the setting.
947 @param JoinFlag TRUE to join the group, otherwise leave it
948 @param GroupAddress The target group address
950 @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it
951 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
952 @retval EFI_DEVICE_ERROR Failed to set the group configuraton
953 @retval EFI_SUCCESS Successfully updated the group setting.
954 @retval EFI_NOT_FOUND Try to leave the group which it isn't a member.
959 IN IP4_PROTOCOL
*IpInstance
,
961 IN EFI_IPv4_ADDRESS
*GroupAddress OPTIONAL
969 // Add it to the instance's Groups, and join the group by IGMP.
970 // IpInstance->Groups is in network byte order. IGMP operates in
974 CopyMem (&Group
, GroupAddress
, sizeof (IP4_ADDR
));
976 for (Index
= 0; Index
< IpInstance
->GroupCount
; Index
++) {
977 if (IpInstance
->Groups
[Index
] == Group
) {
978 return EFI_ALREADY_STARTED
;
982 Members
= Ip4CombineGroups (IpInstance
->Groups
, IpInstance
->GroupCount
, Group
);
984 if (Members
== NULL
) {
985 return EFI_OUT_OF_RESOURCES
;
988 if (EFI_ERROR (Ip4JoinGroup (IpInstance
, NTOHL (Group
)))) {
989 gBS
->FreePool (Members
);
990 return EFI_DEVICE_ERROR
;
993 if (IpInstance
->Groups
!= NULL
) {
994 gBS
->FreePool (IpInstance
->Groups
);
997 IpInstance
->Groups
= Members
;
998 IpInstance
->GroupCount
++;
1004 // Leave the group. Leave all the groups if GroupAddress is NULL.
1005 // Must iterate from the end to the beginning because the GroupCount
1006 // is decreamented each time an address is removed..
1008 for (Index
= IpInstance
->GroupCount
; Index
> 0 ; Index
--) {
1009 Group
= IpInstance
->Groups
[Index
- 1];
1011 if ((GroupAddress
== NULL
) || EFI_IP4_EQUAL (&Group
, GroupAddress
)) {
1012 if (EFI_ERROR (Ip4LeaveGroup (IpInstance
, NTOHL (Group
)))) {
1013 return EFI_DEVICE_ERROR
;
1016 Ip4RemoveGroupAddr (IpInstance
->Groups
, IpInstance
->GroupCount
, Group
);
1017 IpInstance
->GroupCount
--;
1019 if (IpInstance
->GroupCount
== 0) {
1020 ASSERT (Index
== 1);
1022 gBS
->FreePool (IpInstance
->Groups
);
1023 IpInstance
->Groups
= NULL
;
1026 if (GroupAddress
!= NULL
) {
1032 return ((GroupAddress
!= NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
);
1037 Change the IP4 child's multicast setting. If JoinFlag is true,
1038 the child wants to join the group. Otherwise it wants to leave
1039 the group. If JoinFlag is false, and GroupAddress is NULL,
1040 it will leave all the groups which is a member.
1042 @param This The IP4 child to change the setting.
1043 @param JoinFlag TRUE to join the group, otherwise leave it.
1044 @param GroupAddress The target group address
1046 @retval EFI_INVALID_PARAMETER The parameters are invalid
1047 @retval EFI_SUCCESS The group setting has been changed.
1048 @retval Otherwise It failed to change the setting.
1054 IN EFI_IP4_PROTOCOL
*This
,
1055 IN BOOLEAN JoinFlag
,
1056 IN EFI_IPv4_ADDRESS
*GroupAddress OPTIONAL
1059 IP4_PROTOCOL
*IpInstance
;
1064 if ((This
== NULL
) || (JoinFlag
&& (GroupAddress
== NULL
))) {
1065 return EFI_INVALID_PARAMETER
;
1068 if (GroupAddress
!= NULL
) {
1069 CopyMem (&McastIp
, GroupAddress
, sizeof (IP4_ADDR
));
1071 if (!IP4_IS_MULTICAST (NTOHL (McastIp
))) {
1072 return EFI_INVALID_PARAMETER
;
1076 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1077 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1079 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1080 Status
= EFI_NOT_STARTED
;
1084 if (IpInstance
->ConfigData
.UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1085 Status
= EFI_NO_MAPPING
;
1089 Status
= Ip4Groups (IpInstance
, JoinFlag
, GroupAddress
);
1092 gBS
->RestoreTPL (OldTpl
);
1098 Modify the IP child's route table. Each instance has its own
1101 @param This The IP4 child to modify the route
1102 @param DeleteRoute TRUE to delete the route, otherwise add it
1103 @param SubnetAddress The destination network
1104 @param SubnetMask The destination network's mask
1105 @param GatewayAddress The next hop address.
1107 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1108 @retval EFI_SUCCESS The route table is successfully modified.
1109 @retval Others Failed to modify the route table
1115 IN EFI_IP4_PROTOCOL
*This
,
1116 IN BOOLEAN DeleteRoute
,
1117 IN EFI_IPv4_ADDRESS
*SubnetAddress
,
1118 IN EFI_IPv4_ADDRESS
*SubnetMask
,
1119 IN EFI_IPv4_ADDRESS
*GatewayAddress
1122 IP4_PROTOCOL
*IpInstance
;
1123 IP4_INTERFACE
*IpIf
;
1131 // First, validate the parameters
1133 if ((This
== NULL
) || (SubnetAddress
== NULL
) ||
1134 (SubnetMask
== NULL
) || (GatewayAddress
== NULL
)) {
1135 return EFI_INVALID_PARAMETER
;
1138 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1139 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1141 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1142 Status
= EFI_NOT_STARTED
;
1146 if (IpInstance
->ConfigData
.UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1147 Status
= EFI_NO_MAPPING
;
1151 CopyMem (&Dest
, SubnetAddress
, sizeof (IP4_ADDR
));
1152 CopyMem (&Netmask
, SubnetMask
, sizeof (IP4_ADDR
));
1153 CopyMem (&Nexthop
, GatewayAddress
, sizeof (IP4_ADDR
));
1155 Dest
= NTOHL (Dest
);
1156 Netmask
= NTOHL (Netmask
);
1157 Nexthop
= NTOHL (Nexthop
);
1159 IpIf
= IpInstance
->Interface
;
1161 if (!IP4_IS_VALID_NETMASK (Netmask
)) {
1162 Status
= EFI_INVALID_PARAMETER
;
1167 // the gateway address must be a unicast on the connected network if not zero.
1169 if ((Nexthop
!= IP4_ALLZERO_ADDRESS
) &&
1170 (!IP4_NET_EQUAL (Nexthop
, IpIf
->Ip
, IpIf
->SubnetMask
) ||
1171 IP4_IS_BROADCAST (Ip4GetNetCast (Nexthop
, IpIf
)))) {
1173 Status
= EFI_INVALID_PARAMETER
;
1178 Status
= Ip4DelRoute (IpInstance
->RouteTable
, Dest
, Netmask
, Nexthop
);
1180 Status
= Ip4AddRoute (IpInstance
->RouteTable
, Dest
, Netmask
, Nexthop
);
1184 gBS
->RestoreTPL (OldTpl
);
1190 Check whether the user's token or event has already
1191 been enqueue on IP4's list.
1193 @param Map The container of either user's transmit or receive
1195 @param Item Current item to check against
1196 @param Context The Token to check againist.
1198 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1199 @retval EFI_SUCCESS The current item isn't the same token/event as the
1206 IN NET_MAP_ITEM
*Item
,
1210 EFI_IP4_COMPLETION_TOKEN
*Token
;
1211 EFI_IP4_COMPLETION_TOKEN
*TokenInItem
;
1213 Token
= (EFI_IP4_COMPLETION_TOKEN
*) Context
;
1214 TokenInItem
= (EFI_IP4_COMPLETION_TOKEN
*) Item
->Key
;
1216 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
1217 return EFI_ACCESS_DENIED
;
1225 Validate the user's token against current station address.
1227 @param Token User's token to validate
1228 @param IpIf The IP4 child's interface.
1230 @retval EFI_INVALID_PARAMETER Some parameters are invalid
1231 @retval EFI_BAD_BUFFER_SIZE The user's option/data is too long.
1232 @retval EFI_SUCCESS The token is OK
1237 IN EFI_IP4_COMPLETION_TOKEN
*Token
,
1238 IN IP4_INTERFACE
*IpIf
1241 EFI_IP4_TRANSMIT_DATA
*TxData
;
1242 EFI_IP4_OVERRIDE_DATA
*Override
;
1249 if ((Token
== NULL
) || (Token
->Event
== NULL
) || (Token
->Packet
.TxData
== NULL
)) {
1250 return EFI_INVALID_PARAMETER
;
1253 TxData
= Token
->Packet
.TxData
;
1256 // Check the IP options: no more than 40 bytes and format is OK
1258 if (TxData
->OptionsLength
!= 0) {
1259 if ((TxData
->OptionsLength
> 40) || (TxData
->OptionsBuffer
== NULL
)) {
1260 return EFI_INVALID_PARAMETER
;
1263 if (!Ip4OptionIsValid (TxData
->OptionsBuffer
, TxData
->OptionsLength
, FALSE
)) {
1264 return EFI_INVALID_PARAMETER
;
1269 // Check the fragment table: no empty fragment, and length isn't bogus
1271 if ((TxData
->TotalDataLength
== 0) || (TxData
->FragmentCount
== 0)) {
1272 return EFI_INVALID_PARAMETER
;
1275 Offset
= TxData
->TotalDataLength
;
1277 for (Index
= 0; Index
< TxData
->FragmentCount
; Index
++) {
1278 if ((TxData
->FragmentTable
[Index
].FragmentBuffer
== NULL
) ||
1279 (TxData
->FragmentTable
[Index
].FragmentLength
== 0)) {
1281 return EFI_INVALID_PARAMETER
;
1284 Offset
-= TxData
->FragmentTable
[Index
].FragmentLength
;
1288 return EFI_INVALID_PARAMETER
;
1292 // Check the source and gateway: they must be a valid unicast.
1293 // Gateway must also be on the connected network.
1295 if (TxData
->OverrideData
) {
1296 Override
= TxData
->OverrideData
;
1298 CopyMem (&Src
, &Override
->SourceAddress
, sizeof (IP4_ADDR
));
1299 CopyMem (&Gateway
, &Override
->GatewayAddress
, sizeof (IP4_ADDR
));
1302 Gateway
= NTOHL (Gateway
);
1304 if ((NetGetIpClass (Src
) > IP4_ADDR_CLASSC
) ||
1305 (Src
== IP4_ALLONE_ADDRESS
) ||
1306 IP4_IS_BROADCAST (Ip4GetNetCast (Src
, IpIf
))) {
1308 return EFI_INVALID_PARAMETER
;
1312 // If gateway isn't zero, it must be a unicast address, and
1313 // on the connected network.
1315 if ((Gateway
!= IP4_ALLZERO_ADDRESS
) &&
1316 ((NetGetIpClass (Gateway
) > IP4_ADDR_CLASSC
) ||
1317 !IP4_NET_EQUAL (Gateway
, IpIf
->Ip
, IpIf
->SubnetMask
) ||
1318 IP4_IS_BROADCAST (Ip4GetNetCast (Gateway
, IpIf
)))) {
1320 return EFI_INVALID_PARAMETER
;
1325 // Check the packet length: Head length and packet length all has a limit
1327 HeadLen
= sizeof (IP4_HEAD
) + ((TxData
->OptionsLength
+ 3) &~0x03);
1329 if ((HeadLen
> IP4_MAX_HEADLEN
) ||
1330 (TxData
->TotalDataLength
+ HeadLen
> IP4_MAX_PACKET_SIZE
)) {
1332 return EFI_BAD_BUFFER_SIZE
;
1340 The callback function for the net buffer which wraps the user's
1341 transmit token. Although it seems this function is pretty simple,
1342 there are some subtle things.
1343 When user requests the IP to transmit a packet by passing it a
1344 token, the token is wrapped in an IP4_TXTOKEN_WRAP and the data
1345 is wrapped in an net buffer. the net buffer's Free function is
1346 set to Ip4FreeTxToken. The Token and token wrap are added to the
1347 IP child's TxToken map. Then the buffer is passed to Ip4Output for
1348 transmission. If something error happened before that, the buffer
1349 is freed, which in turn will free the token wrap. The wrap may
1350 have been added to the TxToken map or not, and the user's event
1351 shouldn't be fired because we are still in the EfiIp4Transmit. If
1352 the buffer has been sent by Ip4Output, it should be removed from
1353 the TxToken map and user's event signaled. The token wrap and buffer
1354 are bound together. Check the comments in Ip4Output for information
1355 about IP fragmentation.
1357 @param Context The token's wrap
1367 IP4_TXTOKEN_WRAP
*Wrap
;
1370 Wrap
= (IP4_TXTOKEN_WRAP
*) Context
;
1373 // Find the token in the instance's map. EfiIp4Transmit put the
1374 // token to the map. If that failed, NetMapFindKey will return NULL.
1376 Item
= NetMapFindKey (&Wrap
->IpInstance
->TxTokens
, Wrap
->Token
);
1379 NetMapRemoveItem (&Wrap
->IpInstance
->TxTokens
, Item
, NULL
);
1383 gBS
->SignalEvent (Wrap
->Token
->Event
);
1386 // Dispatch the DPC queued by the NotifyFunction of Token->Event.
1388 NetLibDispatchDpc ();
1391 gBS
->FreePool (Wrap
);
1396 The callback function to Ip4Output to update the transmit status.
1398 @param Ip4Instance The Ip4Instance that request the transmit.
1399 @param Packet The user's transmit request
1400 @param IoStatus The result of the transmission
1401 @param Flag Not used during transmission
1402 @param Context The token's wrap.
1409 IP4_PROTOCOL
*Ip4Instance
,
1411 EFI_STATUS IoStatus
,
1416 IP4_TXTOKEN_WRAP
*Wrap
;
1419 // This is the transmission request from upper layer,
1420 // not the IP4 driver itself.
1422 ASSERT (Ip4Instance
!= NULL
);
1425 // The first fragment of the packet has been sent. Update
1426 // the token's status. That is, if fragmented, the transmit's
1427 // status is the first fragment's status. The Wrap will be
1428 // release when all the fragments are release. Check the comments
1429 // in Ip4FreeTxToken and Ip4Output for information.
1431 Wrap
= (IP4_TXTOKEN_WRAP
*) Context
;
1432 Wrap
->Token
->Status
= IoStatus
;
1434 NetbufFree (Wrap
->Packet
);
1439 Transmit the user's data asynchronously. When transmission
1440 completed,the Token's status is updated and its event signalled.
1442 @param This The IP4 child instance
1443 @param Token The user's transmit token, which contains user's
1444 data, the result and an event to signal when
1447 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1448 @retval EFI_NOT_STARTED The IP4 child hasn't been started.
1449 @retval EFI_SUCCESS The user's data has been successfully enqueued
1456 IN EFI_IP4_PROTOCOL
*This
,
1457 IN EFI_IP4_COMPLETION_TOKEN
*Token
1461 IP4_PROTOCOL
*IpInstance
;
1462 IP4_INTERFACE
*IpIf
;
1463 IP4_TXTOKEN_WRAP
*Wrap
;
1464 EFI_IP4_TRANSMIT_DATA
*TxData
;
1465 EFI_IP4_CONFIG_DATA
*Config
;
1466 EFI_IP4_OVERRIDE_DATA
*Override
;
1471 BOOLEAN DontFragment
;
1475 return EFI_INVALID_PARAMETER
;
1478 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1480 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1481 return EFI_NOT_STARTED
;
1484 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1486 IpSb
= IpInstance
->Service
;
1487 IpIf
= IpInstance
->Interface
;
1488 Config
= &IpInstance
->ConfigData
;
1490 if (Config
->UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1491 Status
= EFI_NO_MAPPING
;
1496 // make sure that token is properly formated
1498 Status
= Ip4TxTokenValid (Token
, IpIf
);
1500 if (EFI_ERROR (Status
)) {
1505 // Check whether the token or signal already existed.
1507 if (EFI_ERROR (NetMapIterate (&IpInstance
->TxTokens
, Ip4TokenExist
, Token
))) {
1508 Status
= EFI_ACCESS_DENIED
;
1513 // Build the IP header, need to fill in the Tos, TotalLen, Id,
1514 // fragment, Ttl, protocol, Src, and Dst.
1516 TxData
= Token
->Packet
.TxData
;
1518 CopyMem (&Head
.Dst
, &TxData
->DestinationAddress
, sizeof (IP4_ADDR
));
1519 Head
.Dst
= NTOHL (Head
.Dst
);
1521 if (TxData
->OverrideData
) {
1522 Override
= TxData
->OverrideData
;
1523 Head
.Protocol
= Override
->Protocol
;
1524 Head
.Tos
= Override
->TypeOfService
;
1525 Head
.Ttl
= Override
->TimeToLive
;
1526 DontFragment
= Override
->DoNotFragment
;
1528 CopyMem (&Head
.Src
, &Override
->SourceAddress
, sizeof (IP4_ADDR
));
1529 CopyMem (&GateWay
, &Override
->GatewayAddress
, sizeof (IP4_ADDR
));
1531 Head
.Src
= NTOHL (Head
.Src
);
1532 GateWay
= NTOHL (GateWay
);
1534 Head
.Src
= IpIf
->Ip
;
1535 GateWay
= IP4_ALLZERO_ADDRESS
;
1536 Head
.Protocol
= Config
->DefaultProtocol
;
1537 Head
.Tos
= Config
->TypeOfService
;
1538 Head
.Ttl
= Config
->TimeToLive
;
1539 DontFragment
= Config
->DoNotFragment
;
1542 Head
.Fragment
= IP4_HEAD_FRAGMENT_FIELD (DontFragment
, FALSE
, 0);
1543 HeadLen
= sizeof (IP4_HEAD
) + ((TxData
->OptionsLength
+ 3) &~0x03);
1546 // If don't fragment and fragment needed, return error
1548 if (DontFragment
&& (TxData
->TotalDataLength
+ HeadLen
> IpSb
->SnpMode
.MaxPacketSize
)) {
1549 Status
= EFI_BAD_BUFFER_SIZE
;
1554 // OK, it survives all the validation check. Wrap the token in
1555 // a IP4_TXTOKEN_WRAP and the data in a netbuf
1557 Status
= EFI_OUT_OF_RESOURCES
;
1558 Wrap
= AllocatePool (sizeof (IP4_TXTOKEN_WRAP
));
1563 Wrap
->IpInstance
= IpInstance
;
1564 Wrap
->Token
= Token
;
1566 Wrap
->Life
= IP4_US_TO_SEC (Config
->TransmitTimeout
);
1567 Wrap
->Packet
= NetbufFromExt (
1568 (NET_FRAGMENT
*) TxData
->FragmentTable
,
1569 TxData
->FragmentCount
,
1576 if (Wrap
->Packet
== NULL
) {
1577 gBS
->FreePool (Wrap
);
1581 Token
->Status
= EFI_NOT_READY
;
1583 if (EFI_ERROR (NetMapInsertTail (&IpInstance
->TxTokens
, Token
, Wrap
))) {
1585 // NetbufFree will call Ip4FreeTxToken, which in turn will
1586 // free the IP4_TXTOKEN_WRAP. Now, the token wrap hasn't been
1589 NetbufFree (Wrap
->Packet
);
1594 // Mark the packet sent before output it. Mark it not sent again if the
1595 // returned status is not EFI_SUCCESS;
1599 Status
= Ip4Output (
1604 TxData
->OptionsBuffer
,
1605 TxData
->OptionsLength
,
1611 if (EFI_ERROR (Status
)) {
1613 NetbufFree (Wrap
->Packet
);
1617 gBS
->RestoreTPL (OldTpl
);
1623 Receive a packet for the upper layer. If there are packets
1624 pending on the child's receive queue, the receive request
1625 will be fulfilled immediately. Otherwise, the request is
1626 enqueued. When receive request is completed, the status in
1627 the Token is updated and its event is signalled.
1629 @param This The IP4 child to receive packet.
1630 @param Token The user's receive token
1632 @retval EFI_INVALID_PARAMETER The token is invalid.
1633 @retval EFI_NOT_STARTED The IP4 child hasn't been started
1634 @retval EFI_ACCESS_DENIED The token or event is already queued.
1635 @retval EFI_SUCCESS The receive request has been issued.
1641 IN EFI_IP4_PROTOCOL
*This
,
1642 IN EFI_IP4_COMPLETION_TOKEN
*Token
1645 IP4_PROTOCOL
*IpInstance
;
1650 // First validate the parameters
1652 if ((This
== NULL
) || (Token
== NULL
) || (Token
->Event
== NULL
)) {
1653 return EFI_INVALID_PARAMETER
;
1656 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1658 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1660 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1661 Status
= EFI_NOT_STARTED
;
1666 // Check whether the toke is already on the receive queue.
1668 Status
= NetMapIterate (&IpInstance
->RxTokens
, Ip4TokenExist
, Token
);
1670 if (EFI_ERROR (Status
)) {
1671 Status
= EFI_ACCESS_DENIED
;
1676 // Queue the token then check whether there is pending received packet.
1678 Status
= NetMapInsertTail (&IpInstance
->RxTokens
, Token
, NULL
);
1680 if (EFI_ERROR (Status
)) {
1684 Status
= Ip4InstanceDeliverPacket (IpInstance
);
1687 // Dispatch the DPC queued by the NotifyFunction of this instane's receive
1690 NetLibDispatchDpc ();
1693 gBS
->RestoreTPL (OldTpl
);
1699 Cancel the transmitted but not recycled packet. If a matching
1700 token is found, it will call Ip4CancelPacket to cancel the
1701 packet. Ip4CancelPacket will cancel all the fragments of the
1702 packet. When all the fragments are freed, the IP4_TXTOKEN_WRAP
1703 will be deleted from the Map, and user's event signalled.
1704 Because Ip4CancelPacket and other functions are all called in
1705 line, so, after Ip4CancelPacket returns, the Item has been freed.
1707 @param Map The IP4 child's transmit queue
1708 @param Item The current transmitted packet to test.
1709 @param Context The user's token to cancel.
1711 @retval EFI_SUCCESS Continue to check the next Item.
1712 @retval EFI_ABORTED The user's Token (Token != NULL) is cancelled.
1718 IN NET_MAP_ITEM
*Item
,
1722 EFI_IP4_COMPLETION_TOKEN
*Token
;
1723 IP4_TXTOKEN_WRAP
*Wrap
;
1725 Token
= (EFI_IP4_COMPLETION_TOKEN
*) Context
;
1728 // Return EFI_SUCCESS to check the next item in the map if
1729 // this one doesn't match.
1731 if ((Token
!= NULL
) && (Token
!= Item
->Key
)) {
1735 Wrap
= (IP4_TXTOKEN_WRAP
*) Item
->Value
;
1736 ASSERT (Wrap
!= NULL
);
1739 // Don't access the Item, Wrap and Token's members after this point.
1740 // Item and wrap has been freed. And we no longer own the Token.
1742 Ip4CancelPacket (Wrap
->IpInstance
->Interface
, Wrap
->Packet
, EFI_ABORTED
);
1745 // If only one item is to be cancel, return EFI_ABORTED to stop
1746 // iterating the map any more.
1748 if (Token
!= NULL
) {
1757 Cancel the receive request. This is quiet simple, because
1758 it is only enqueued in our local receive map.
1760 @param Map The IP4 child's receive queue
1761 @param Item Current receive request to cancel.
1762 @param Context The user's token to cancel
1764 @retval EFI_SUCCESS Continue to check the next receive request on the
1766 @retval EFI_ABORTED The user's token (token != NULL) has been
1773 IN NET_MAP_ITEM
*Item
,
1777 EFI_IP4_COMPLETION_TOKEN
*Token
;
1778 EFI_IP4_COMPLETION_TOKEN
*This
;
1780 Token
= (EFI_IP4_COMPLETION_TOKEN
*) Context
;
1783 if ((Token
!= NULL
) && (Token
!= This
)) {
1787 NetMapRemoveItem (Map
, Item
, NULL
);
1789 This
->Status
= EFI_ABORTED
;
1790 This
->Packet
.RxData
= NULL
;
1791 gBS
->SignalEvent (This
->Event
);
1793 if (Token
!= NULL
) {
1802 Cancel the user's receive/transmit request.
1804 @param IpInstance The IP4 child
1805 @param Token The token to cancel. If NULL, all token will be
1808 @retval EFI_SUCCESS The token is cancelled
1809 @retval EFI_NOT_FOUND The token isn't found on either the
1810 transmit/receive queue
1811 @retval EFI_DEVICE_ERROR Not all token is cancelled when Token is NULL.
1816 IN IP4_PROTOCOL
*IpInstance
,
1817 IN EFI_IP4_COMPLETION_TOKEN
*Token OPTIONAL
1823 // First check the transmitted packet. Ip4CancelTxTokens returns
1824 // EFI_ABORTED to mean that the token has been cancelled when
1825 // token != NULL. So, return EFI_SUCCESS for this condition.
1827 Status
= NetMapIterate (&IpInstance
->TxTokens
, Ip4CancelTxTokens
, Token
);
1829 if (EFI_ERROR (Status
)) {
1830 if ((Token
!= NULL
) && (Status
== EFI_ABORTED
)) {
1838 // Check the receive queue. Ip4CancelRxTokens also returns EFI_ABORT
1839 // for Token!=NULL and it is cancelled.
1841 Status
= NetMapIterate (&IpInstance
->RxTokens
, Ip4CancelRxTokens
, Token
);
1843 // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's
1846 NetLibDispatchDpc ();
1847 if (EFI_ERROR (Status
)) {
1848 if ((Token
!= NULL
) && (Status
== EFI_ABORTED
)) {
1856 // OK, if the Token is found when Token != NULL, the NetMapIterate
1857 // will return EFI_ABORTED, which has been interrupted as EFI_SUCCESS.
1859 if (Token
!= NULL
) {
1860 return EFI_NOT_FOUND
;
1864 // If Token == NULL, cancel all the tokens. return error if no
1865 // all of them are cancelled.
1867 if (!NetMapIsEmpty (&IpInstance
->TxTokens
) ||
1868 !NetMapIsEmpty (&IpInstance
->RxTokens
)) {
1870 return EFI_DEVICE_ERROR
;
1878 Cancel the queued receive/transmit requests. If Token is NULL,
1879 all the queued requests will be cancelled. It just validate
1880 the parameter then pass them to Ip4Cancel.
1882 @param This The IP4 child to cancel the request
1883 @param Token The token to cancel, if NULL, cancel all.
1885 @retval EFI_INVALID_PARAMETER This is NULL
1886 @retval EFI_NOT_STARTED The IP4 child hasn't been configured.
1887 @retval EFI_NO_MAPPING The IP4 child is configured to use the default,
1888 but the default address hasn't been acquired.
1889 @retval EFI_SUCCESS The Token is cancelled.
1895 IN EFI_IP4_PROTOCOL
*This
,
1896 IN EFI_IP4_COMPLETION_TOKEN
*Token OPTIONAL
1899 IP4_PROTOCOL
*IpInstance
;
1904 return EFI_INVALID_PARAMETER
;
1907 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1909 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1911 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1912 Status
= EFI_NOT_STARTED
;
1916 if (IpInstance
->ConfigData
.UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1917 Status
= EFI_NO_MAPPING
;
1921 Status
= Ip4Cancel (IpInstance
, Token
);
1924 gBS
->RestoreTPL (OldTpl
);
1930 Poll the network stack. The EFI network stack is poll based. There
1931 is no interrupt support for the network interface card.
1933 @param This The IP4 child to poll through
1935 @retval EFI_INVALID_PARAMETER The parameter is invalid
1936 @retval EFI_NOT_STARTED The IP4 child hasn't been configured.
1942 IN EFI_IP4_PROTOCOL
*This
1945 IP4_PROTOCOL
*IpInstance
;
1946 EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
;
1949 return EFI_INVALID_PARAMETER
;
1952 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1954 if (IpInstance
->State
== IP4_STATE_UNCONFIGED
) {
1955 return EFI_NOT_STARTED
;
1958 Mnp
= IpInstance
->Service
->Mnp
;
1961 // Don't lock the Poll function to enable the deliver of
1962 // the packet polled up.
1964 return Mnp
->Poll (Mnp
);
1968 mEfiIp4ProtocolTemplete
= {
1981 Decrease the life of the transmitted packets. If it is
1982 decreased to zero, cancel the packet. This function is
1983 called by Ip4packetTimerTicking which time out both the
1984 received-but-not-delivered and transmitted-but-not-recycle
1987 @param Map The IP4 child's transmit map.
1988 @param Item Current transmitted packet
1989 @param Context Not used.
1991 @retval EFI_SUCCESS Always returns EFI_SUCCESS
1995 Ip4SentPacketTicking (
1997 IN NET_MAP_ITEM
*Item
,
2001 IP4_TXTOKEN_WRAP
*Wrap
;
2003 Wrap
= (IP4_TXTOKEN_WRAP
*) Item
->Value
;
2004 ASSERT (Wrap
!= NULL
);
2006 if ((Wrap
->Life
> 0) && (--Wrap
->Life
== 0)) {
2007 Ip4CancelPacket (Wrap
->IpInstance
->Interface
, Wrap
->Packet
, EFI_ABORTED
);
2015 The heart beat timer of IP4 service instance. It times out
2016 all of its IP4 children's received-but-not-delivered and
2017 transmitted-but-not-recycle packets, and provides time input
2018 for its IGMP protocol.
2020 @param Event The IP4 service instance's heart beat timer.
2021 @param Context The IP4 service instance.
2035 IpSb
= (IP4_SERVICE
*) Context
;
2036 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
2038 Ip4PacketTimerTicking (IpSb
);
2039 Ip4IgmpTicking (IpSb
);