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.
43 IN CONST EFI_IP4_PROTOCOL
*This
,
44 OUT EFI_IP4_MODE_DATA
*Ip4ModeData
, OPTIONAL
45 OUT EFI_MANAGED_NETWORK_CONFIG_DATA
*MnpConfigData
, OPTIONAL
46 OUT EFI_SIMPLE_NETWORK_MODE
*SnpModeData OPTIONAL
49 IP4_PROTOCOL
*IpInstance
;
51 EFI_IP4_CONFIG_DATA
*Config
;
57 return EFI_INVALID_PARAMETER
;
60 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
61 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
62 IpSb
= IpInstance
->Service
;
64 if (Ip4ModeData
!= NULL
) {
66 // IsStarted is "whether the EfiIp4Configure has been called".
67 // IsConfigured is "whether the station address has been configured"
69 Ip4ModeData
->IsStarted
= (BOOLEAN
)(IpInstance
->State
== IP4_STATE_CONFIGED
);
70 CopyMem (&Ip4ModeData
->ConfigData
, &IpInstance
->ConfigData
, sizeof (Ip4ModeData
->ConfigData
));
71 Ip4ModeData
->IsConfigured
= FALSE
;
73 Ip4ModeData
->GroupCount
= IpInstance
->GroupCount
;
74 Ip4ModeData
->GroupTable
= (EFI_IPv4_ADDRESS
*) IpInstance
->Groups
;
76 Ip4ModeData
->IcmpTypeCount
= 23;
77 Ip4ModeData
->IcmpTypeList
= mIp4SupportedIcmp
;
79 Ip4ModeData
->RouteTable
= NULL
;
80 Ip4ModeData
->RouteCount
= 0;
83 // return the current station address for this IP child. So,
84 // the user can get the default address through this. Some
85 // application wants to know it station address even it is
86 // using the default one, such as a ftp server.
88 if (Ip4ModeData
->IsStarted
) {
89 Config
= &Ip4ModeData
->ConfigData
;
91 Ip
= HTONL (IpInstance
->Interface
->Ip
);
92 NetCopyMem (&Config
->StationAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
94 Ip
= HTONL (IpInstance
->Interface
->SubnetMask
);
95 NetCopyMem (&Config
->SubnetMask
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
97 Ip4ModeData
->IsConfigured
= IpInstance
->Interface
->Configured
;
100 // Build a EFI route table for user from the internal route table.
102 Status
= Ip4BuildEfiRouteTable (IpInstance
);
104 if (EFI_ERROR (Status
)) {
105 NET_RESTORE_TPL (OldTpl
);
109 Ip4ModeData
->RouteTable
= IpInstance
->EfiRouteTable
;
110 Ip4ModeData
->RouteCount
= IpInstance
->EfiRouteCount
;
114 if (MnpConfigData
!= NULL
) {
115 CopyMem (MnpConfigData
, &IpSb
->MnpConfigData
, sizeof (*MnpConfigData
));
118 if (SnpModeData
!= NULL
) {
119 CopyMem (SnpModeData
, &IpSb
->SnpMode
, sizeof (*SnpModeData
));
122 NET_RESTORE_TPL (OldTpl
);
128 Config the MNP parameter used by IP. The IP driver use one MNP
129 child to transmit/receive frames. By default, it configures MNP
130 to receive unicast/multicast/broadcast. And it will enable/disable
131 the promiscous receive according to whether there is IP child
132 enable that or not. If Force isn't false, it will iterate through
133 all the IP children to check whether the promiscuous receive
134 setting has been changed. If it hasn't been changed, it won't
135 reconfigure the MNP. If Force is true, the MNP is configured no
136 matter whether that is changed or not.
138 @param IpSb The IP4 service instance that is to be changed.
139 @param Force Force the configuration or not.
141 @retval EFI_SUCCESS The MNP is successfully configured/reconfigured.
142 @retval Others Configuration failed.
146 Ip4ServiceConfigMnp (
147 IN IP4_SERVICE
*IpSb
,
151 NET_LIST_ENTRY
*Entry
;
152 NET_LIST_ENTRY
*ProtoEntry
;
154 IP4_PROTOCOL
*IpInstance
;
156 BOOLEAN PromiscReceive
;
160 PromiscReceive
= FALSE
;
164 // Iterate through the IP children to check whether promiscuous
165 // receive setting has been changed. Update the interface's receive
168 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
170 IpIf
= NET_LIST_USER_STRUCT (Entry
, IP4_INTERFACE
, Link
);
171 IpIf
->PromiscRecv
= FALSE
;
173 NET_LIST_FOR_EACH (ProtoEntry
, &IpIf
->IpInstances
) {
174 IpInstance
= NET_LIST_USER_STRUCT (ProtoEntry
, IP4_PROTOCOL
, AddrLink
);
176 if (IpInstance
->ConfigData
.AcceptPromiscuous
) {
177 IpIf
->PromiscRecv
= TRUE
;
178 PromiscReceive
= TRUE
;
184 // If promiscuous receive isn't changed, it isn't necessary to reconfigure.
186 if (PromiscReceive
== IpSb
->MnpConfigData
.EnablePromiscuousReceive
) {
191 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= PromiscReceive
;
194 Status
= IpSb
->Mnp
->Configure (IpSb
->Mnp
, &IpSb
->MnpConfigData
);
197 // recover the original configuration if failed to set the configure.
199 if (EFI_ERROR (Status
) && Reconfig
) {
200 IpSb
->MnpConfigData
.EnablePromiscuousReceive
= (BOOLEAN
) !PromiscReceive
;
208 The event handle for IP4 auto configuration. If IP is asked
209 to reconfigure the default address. The original default
210 interface and route table are removed as the default. If there
211 is active IP children using the default address, the interface
212 will remain valid until all the children have freed their
213 references. If IP is signalled when auto configuration is done,
214 it will configure the default interface and default route table
215 with the configuration information retrieved by IP4_CONFIGURE.
217 @param Event The event that is signalled.
218 @param Context The IP4 service binding instance.
225 Ip4AutoConfigCallBack (
230 EFI_IP4_CONFIG_PROTOCOL
*Ip4Config
;
231 EFI_IP4_IPCONFIG_DATA
*Data
;
232 EFI_IP4_ROUTE_TABLE
*RouteEntry
;
234 IP4_ROUTE_TABLE
*RouteTable
;
240 IpSb
= (IP4_SERVICE
*) Context
;
241 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
243 Ip4Config
= IpSb
->Ip4Config
;
246 // IP is asked to do the reconfiguration. If the default interface
247 // has been configured, release the default interface and route
248 // table, then create a new one. If there are some IP children
249 // using it, the interface won't be physically freed until all the
250 // children have released their reference to it. Also remember to
251 // restart the receive on the default address. IP4 driver only receive
252 // frames on the default address, and when the default interface is
253 // freed, Ip4AcceptFrame won't be informed.
255 if (Event
== IpSb
->ReconfigEvent
) {
257 if (IpSb
->DefaultInterface
->Configured
) {
258 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
264 RouteTable
= Ip4CreateRouteTable ();
266 if (RouteTable
== NULL
) {
267 Ip4FreeInterface (IpIf
, NULL
);
271 Ip4CancelReceive (IpSb
->DefaultInterface
);
272 Ip4FreeInterface (IpSb
->DefaultInterface
, NULL
);
273 Ip4FreeRouteTable (IpSb
->DefaultRouteTable
);
275 IpSb
->DefaultInterface
= IpIf
;
276 NetListInsertHead (&IpSb
->Interfaces
, &IpIf
->Link
);
278 IpSb
->DefaultRouteTable
= RouteTable
;
279 Ip4ReceiveFrame (IpIf
, NULL
, Ip4AccpetFrame
, IpSb
);
282 Ip4Config
->Stop (Ip4Config
);
283 Ip4Config
->Start (Ip4Config
, IpSb
->DoneEvent
, IpSb
->ReconfigEvent
);
288 // Get the configure data in two steps: get the length then the data.
292 if (Ip4Config
->GetData (Ip4Config
, &Len
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
296 Data
= NetAllocatePool (Len
);
302 Status
= Ip4Config
->GetData (Ip4Config
, &Len
, Data
);
304 if (EFI_ERROR (Status
)) {
308 IpIf
= IpSb
->DefaultInterface
;
311 // If the default address has been configured don't change it.
312 // This is unlikely to happen if EFI_IP4_CONFIG protocol has
313 // informed us to reconfigure each time it wants to change the
314 // configuration parameters.
316 if (IpIf
->Configured
) {
321 // Set the default interface's address, then add a directed
322 // route for it, that is, the route whose nexthop is zero.
324 Status
= Ip4SetAddress (
326 EFI_NTOHL (Data
->StationAddress
),
327 EFI_NTOHL (Data
->SubnetMask
)
330 if (EFI_ERROR (Status
)) {
335 IpSb
->DefaultRouteTable
,
336 EFI_NTOHL (Data
->StationAddress
),
337 EFI_NTOHL (Data
->SubnetMask
),
342 // Add routes returned by EFI_IP4_CONFIG protocol.
344 for (Index
= 0; Index
< Data
->RouteTableSize
; Index
++) {
345 RouteEntry
= &Data
->RouteTable
[Index
];
348 IpSb
->DefaultRouteTable
,
349 EFI_NTOHL (RouteEntry
->SubnetAddress
),
350 EFI_NTOHL (RouteEntry
->SubnetMask
),
351 EFI_NTOHL (RouteEntry
->GatewayAddress
)
355 IpSb
->State
= IP4_SERVICE_CONFIGED
;
357 Ip4SetVariableData (IpSb
);
365 Start the auto configuration for this IP service instance.
366 It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the
369 @param IpSb The IP4 service instance to configure
371 @retval EFI_SUCCESS The auto configuration is successfull started
372 @retval Others Failed to start auto configuration.
380 EFI_IP4_CONFIG_PROTOCOL
*Ip4Config
;
383 if (IpSb
->State
> IP4_SERVICE_UNSTARTED
) {
388 // Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG
390 Status
= gBS
->CreateEvent (
393 Ip4AutoConfigCallBack
,
398 if (EFI_ERROR (Status
)) {
402 Status
= gBS
->CreateEvent (
405 Ip4AutoConfigCallBack
,
410 if (EFI_ERROR (Status
)) {
411 goto CLOSE_DONE_EVENT
;
415 // Open the EFI_IP4_CONFIG protocol then start auto configure
417 Status
= gBS
->OpenProtocol (
419 &gEfiIp4ConfigProtocolGuid
,
420 (VOID
**) &Ip4Config
,
423 EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
426 if (EFI_ERROR (Status
)) {
427 Status
= EFI_UNSUPPORTED
;
428 goto CLOSE_RECONFIG_EVENT
;
431 Status
= Ip4Config
->Start (Ip4Config
, IpSb
->DoneEvent
, IpSb
->ReconfigEvent
);
433 if (EFI_ERROR (Status
)) {
436 &gEfiIp4ConfigProtocolGuid
,
441 goto CLOSE_RECONFIG_EVENT
;
444 IpSb
->Ip4Config
= Ip4Config
;
445 IpSb
->State
= IP4_SERVICE_STARTED
;
448 CLOSE_RECONFIG_EVENT
:
449 gBS
->CloseEvent (IpSb
->ReconfigEvent
);
450 IpSb
->ReconfigEvent
= NULL
;
453 gBS
->CloseEvent (IpSb
->DoneEvent
);
454 IpSb
->DoneEvent
= NULL
;
461 Intiialize the IP4_PROTOCOL structure to the unconfigured states.
463 @param IpSb The IP4 service instance.
464 @param IpInstance The IP4 child instance.
471 IN IP4_SERVICE
*IpSb
,
472 IN IP4_PROTOCOL
*IpInstance
475 ASSERT ((IpSb
!= NULL
) && (IpInstance
!= NULL
));
477 NetZeroMem (IpInstance
, sizeof (IP4_PROTOCOL
));
479 IpInstance
->Signature
= IP4_PROTOCOL_SIGNATURE
;
480 CopyMem (&IpInstance
->Ip4Proto
, &mEfiIp4ProtocolTemplete
, sizeof (IpInstance
->Ip4Proto
));
481 IpInstance
->State
= IP4_STATE_UNCONFIGED
;
482 IpInstance
->Service
= IpSb
;
484 NetListInit (&IpInstance
->Link
);
485 NetMapInit (&IpInstance
->RxTokens
);
486 NetMapInit (&IpInstance
->TxTokens
);
487 NetListInit (&IpInstance
->Received
);
488 NetListInit (&IpInstance
->Delivered
);
489 NetListInit (&IpInstance
->AddrLink
);
491 NET_RECYCLE_LOCK_INIT (&IpInstance
->RecycleLock
);
496 Configure the IP4 child. If the child is already configured,
497 change the configuration parameter. Otherwise configure it
498 for the first time. The caller should validate the configuration
499 before deliver them to it. It also don't do configure NULL.
501 @param IpInstance The IP4 child to configure.
502 @param Config The configure data.
504 @retval EFI_SUCCESS The IP4 child is successfully configured.
505 @retval EFI_DEVICE_ERROR Failed to free the pending transive or to
506 configure underlying MNP or other errors.
507 @retval EFI_NO_MAPPING The IP4 child is configured to use default
508 address, but the default address hasn't been
509 configured. The IP4 child doesn't need to be
510 reconfigured when default address is configured.
515 IN IP4_PROTOCOL
*IpInstance
,
516 IN EFI_IP4_CONFIG_DATA
*Config
525 IpSb
= IpInstance
->Service
;
528 // User is changing packet filters. It must be stopped
529 // before the station address can be changed.
531 if (IpInstance
->State
== IP4_STATE_CONFIGED
) {
533 // Cancel all the pending transmit/receive from upper layer
535 Status
= Ip4Cancel (IpInstance
, NULL
);
537 if (EFI_ERROR (Status
)) {
538 return EFI_DEVICE_ERROR
;
541 CopyMem (&IpInstance
->ConfigData
, Config
, sizeof (IpInstance
->ConfigData
));
546 // Configure a fresh IP4 protocol instance. Create a route table.
547 // Each IP child has its own route table, which may point to the
548 // default table if it is using default address.
550 Status
= EFI_OUT_OF_RESOURCES
;
551 IpInstance
->RouteTable
= Ip4CreateRouteTable ();
553 if (IpInstance
->RouteTable
== NULL
) {
558 // Set up the interface.
560 NetCopyMem (&Ip
, &Config
->StationAddress
, sizeof (IP4_ADDR
));
561 NetCopyMem (&Netmask
, &Config
->SubnetMask
, sizeof (IP4_ADDR
));
564 Netmask
= NTOHL (Netmask
);
566 if (!Config
->UseDefaultAddress
) {
568 // Find whether there is already an interface with the same
569 // station address. All the instances with the same station
570 // address shares one interface.
572 IpIf
= Ip4FindStationAddress (IpSb
, Ip
, Netmask
);
578 IpIf
= Ip4CreateInterface (IpSb
->Mnp
, IpSb
->Controller
, IpSb
->Image
);
584 Status
= Ip4SetAddress (IpIf
, Ip
, Netmask
);
586 if (EFI_ERROR (Status
)) {
587 Status
= EFI_DEVICE_ERROR
;
588 Ip4FreeInterface (IpIf
, IpInstance
);
592 NetListInsertTail (&IpSb
->Interfaces
, &IpIf
->Link
);
596 // Add a route to this connected network in the route table
598 Ip4AddRoute (IpInstance
->RouteTable
, Ip
, Netmask
, IP4_ALLZERO_ADDRESS
);
602 // Use the default address. If the default configuration hasn't
603 // been started, start it.
605 if (IpSb
->State
== IP4_SERVICE_UNSTARTED
) {
606 Status
= Ip4StartAutoConfig (IpSb
);
608 if (EFI_ERROR (Status
)) {
613 IpIf
= IpSb
->DefaultInterface
;
614 NET_GET_REF (IpSb
->DefaultInterface
);
617 // If default address is used, so is the default route table.
618 // Any route set by the instance has the precedence over the
619 // routes in the default route table. Link the default table
620 // after the instance's table. Routing will search the local
623 NET_GET_REF (IpSb
->DefaultRouteTable
);
624 IpInstance
->RouteTable
->Next
= IpSb
->DefaultRouteTable
;
627 IpInstance
->Interface
= IpIf
;
628 NetListInsertTail (&IpIf
->IpInstances
, &IpInstance
->AddrLink
);
630 CopyMem (&IpInstance
->ConfigData
, Config
, sizeof (IpInstance
->ConfigData
));
631 IpInstance
->State
= IP4_STATE_CONFIGED
;
634 // Although EFI_NO_MAPPING is an error code, the IP child has been
635 // successfully configured and doesn't need reconfiguration when
636 // default address is acquired.
638 if (Config
->UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
639 return EFI_NO_MAPPING
;
645 Ip4FreeRouteTable (IpInstance
->RouteTable
);
646 IpInstance
->RouteTable
= NULL
;
652 Clean up the IP4 child, release all the resources used by it.
654 @param IpInstance The IP4 child to clean up.
656 @retval EFI_SUCCESS The IP4 child is cleaned up
657 @retval EFI_DEVICE_ERROR Some resources failed to be released
662 IN IP4_PROTOCOL
*IpInstance
665 if (EFI_ERROR (Ip4Cancel (IpInstance
, NULL
))) {
666 return EFI_DEVICE_ERROR
;
669 if (EFI_ERROR (Ip4Groups (IpInstance
, FALSE
, NULL
))) {
670 return EFI_DEVICE_ERROR
;
674 // Some packets haven't been recycled. It is because either the
675 // user forgets to recycle the packets, or because the callback
676 // hasn't been called. Just leave it alone.
678 if (!NetListIsEmpty (&IpInstance
->Delivered
)) {
682 if (IpInstance
->Interface
!= NULL
) {
683 NetListRemoveEntry (&IpInstance
->AddrLink
);
684 Ip4FreeInterface (IpInstance
->Interface
, IpInstance
);
685 IpInstance
->Interface
= NULL
;
688 if (IpInstance
->RouteTable
!= NULL
) {
689 if (IpInstance
->RouteTable
->Next
!= NULL
) {
690 Ip4FreeRouteTable (IpInstance
->RouteTable
->Next
);
693 Ip4FreeRouteTable (IpInstance
->RouteTable
);
694 IpInstance
->RouteTable
= NULL
;
697 if (IpInstance
->EfiRouteTable
!= NULL
) {
698 NetFreePool (IpInstance
->EfiRouteTable
);
699 IpInstance
->EfiRouteTable
= NULL
;
700 IpInstance
->EfiRouteCount
= 0;
703 if (IpInstance
->Groups
!= NULL
) {
704 NetFreePool (IpInstance
->Groups
);
705 IpInstance
->Groups
= NULL
;
706 IpInstance
->GroupCount
= 0;
709 NetMapClean (&IpInstance
->TxTokens
);
711 NetMapClean (&IpInstance
->RxTokens
);
718 Validate that Ip/Netmask pair is OK to be used as station
719 address. Only continuous netmasks are supported. and check
720 that StationAddress is a unicast address on the newtwork.
722 @param Ip The IP address to validate
723 @param Netmask The netmaks of the IP
725 @retval TRUE The Ip/Netmask pair is valid
730 Ip4StationAddressValid (
735 IP4_ADDR NetBrdcastMask
;
740 // Only support the station address with 0.0.0.0/0 to enable DHCP client.
742 if (Netmask
== IP4_ALLZERO_ADDRESS
) {
743 return (BOOLEAN
) (Ip
== IP4_ALLZERO_ADDRESS
);
747 // Only support the continuous net masks
749 if ((Len
= NetGetMaskLength (Netmask
)) == IP4_MASK_NUM
) {
754 // Station address can't be class D or class E address
756 if ((Type
= NetGetIpClass (Ip
)) > IP4_ADDR_CLASSC
) {
761 // Station address can't be subnet broadcast/net broadcast address
763 if ((Ip
== (Ip
& Netmask
)) || (Ip
== (Ip
| ~Netmask
))) {
767 NetBrdcastMask
= mIp4AllMasks
[NET_MIN (Len
, Type
<< 3)];
769 if (Ip
== (Ip
| ~NetBrdcastMask
)) {
778 Configure the EFI_IP4_PROTOCOL instance. If IpConfigData is NULL,
779 the instance is cleaned up. If the instance hasn't been configure
780 before, it will be initialized. Otherwise, the filter setting of
781 the instance is updated.
783 @param This The IP4 child to configure
784 @param IpConfigData The configuration to apply. If NULL, clean it up.
786 @retval EFI_INVALID_PARAMETER The parameter is invalid
787 @retval EFI_NO_MAPPING The default address hasn't been configured and the
788 instance wants to use it.
789 @retval EFI_SUCCESS The instance is configured.
796 IN EFI_IP4_PROTOCOL
*This
,
797 IN EFI_IP4_CONFIG_DATA
*IpConfigData OPTIONAL
800 IP4_PROTOCOL
*IpInstance
;
801 EFI_IP4_CONFIG_DATA
*Current
;
809 // First, validate the parameters
812 return EFI_INVALID_PARAMETER
;
815 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
816 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
819 // Validate the configuration first.
821 if (IpConfigData
!= NULL
) {
823 // This implementation doesn't support RawData
825 if (IpConfigData
->RawData
) {
826 Status
= EFI_UNSUPPORTED
;
831 NetCopyMem (&IpAddress
, &IpConfigData
->StationAddress
, sizeof (IP4_ADDR
));
832 NetCopyMem (&SubnetMask
, &IpConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
834 IpAddress
= NTOHL (IpAddress
);
835 SubnetMask
= NTOHL (SubnetMask
);
838 // Check whether the station address is a valid unicast address
840 if (!IpConfigData
->UseDefaultAddress
) {
841 AddrOk
= Ip4StationAddressValid (IpAddress
, SubnetMask
);
844 Status
= EFI_INVALID_PARAMETER
;
850 // User can only update packet filters when already configured.
851 // If it wants to change the station address, it must configure(NULL)
852 // the instance first.
854 if (IpInstance
->State
== IP4_STATE_CONFIGED
) {
855 Current
= &IpInstance
->ConfigData
;
857 if (Current
->UseDefaultAddress
!= IpConfigData
->UseDefaultAddress
) {
858 Status
= EFI_ALREADY_STARTED
;
862 if (!Current
->UseDefaultAddress
&&
863 (!EFI_IP4_EQUAL (&Current
->StationAddress
, &IpConfigData
->StationAddress
) ||
864 !EFI_IP4_EQUAL (&Current
->SubnetMask
, &IpConfigData
->SubnetMask
))) {
865 Status
= EFI_ALREADY_STARTED
;
869 if (Current
->UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
870 return EFI_NO_MAPPING
;
876 // Configure the instance or clean it up.
878 if (IpConfigData
!= NULL
) {
879 Status
= Ip4ConfigProtocol (IpInstance
, IpConfigData
);
881 Status
= Ip4CleanProtocol (IpInstance
);
884 // Don't change the state if it is DESTORY, consider the following
885 // valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,
886 // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED,
887 // the unload fails miserably.
889 if (IpInstance
->State
== IP4_STATE_CONFIGED
) {
890 IpInstance
->State
= IP4_STATE_UNCONFIGED
;
895 // Update the MNP's configure data. Ip4ServiceConfigMnp will check
896 // whether it is necessary to reconfigure the MNP.
898 Ip4ServiceConfigMnp (IpInstance
->Service
, FALSE
);
901 // Update the variable data.
903 Ip4SetVariableData (IpInstance
->Service
);
906 NET_RESTORE_TPL (OldTpl
);
913 Change the IP4 child's multicast setting. The caller
914 should make sure that the parameters is valid.
916 @param IpInstance The IP4 child to change the setting.
917 @param JoinFlag TRUE to join the group, otherwise leave it
918 @param GroupAddress The target group address
920 @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it
921 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
922 @retval EFI_DEVICE_ERROR Failed to set the group configuraton
923 @retval EFI_SUCCESS Successfully updated the group setting.
924 @retval EFI_NOT_FOUND Try to leave the group which it isn't a member.
929 IN IP4_PROTOCOL
*IpInstance
,
931 IN EFI_IPv4_ADDRESS
*GroupAddress OPTIONAL
939 // Add it to the instance's Groups, and join the group by IGMP.
940 // IpInstance->Groups is in network byte order. IGMP operates in
944 NetCopyMem (&Group
, GroupAddress
, sizeof (IP4_ADDR
));
946 for (Index
= 0; Index
< IpInstance
->GroupCount
; Index
++) {
947 if (IpInstance
->Groups
[Index
] == Group
) {
948 return EFI_ALREADY_STARTED
;
952 Members
= Ip4CombineGroups (IpInstance
->Groups
, IpInstance
->GroupCount
, Group
);
954 if (Members
== NULL
) {
955 return EFI_OUT_OF_RESOURCES
;
958 if (EFI_ERROR (Ip4JoinGroup (IpInstance
, NTOHL (Group
)))) {
959 NetFreePool (Members
);
960 return EFI_DEVICE_ERROR
;
963 if (IpInstance
->Groups
!= NULL
) {
964 NetFreePool (IpInstance
->Groups
);
967 IpInstance
->Groups
= Members
;
968 IpInstance
->GroupCount
++;
974 // Leave the group. Leave all the groups if GroupAddress is NULL.
975 // Must iterate from the end to the beginning because the GroupCount
976 // is decreamented each time an address is removed..
978 for (Index
= IpInstance
->GroupCount
; Index
> 0 ; Index
--) {
979 Group
= IpInstance
->Groups
[Index
- 1];
981 if ((GroupAddress
== NULL
) || EFI_IP4_EQUAL (&Group
, GroupAddress
)) {
982 if (EFI_ERROR (Ip4LeaveGroup (IpInstance
, NTOHL (Group
)))) {
983 return EFI_DEVICE_ERROR
;
986 Ip4RemoveGroupAddr (IpInstance
->Groups
, IpInstance
->GroupCount
, Group
);
987 IpInstance
->GroupCount
--;
989 if (IpInstance
->GroupCount
== 0) {
992 NetFreePool (IpInstance
->Groups
);
993 IpInstance
->Groups
= NULL
;
996 if (GroupAddress
!= NULL
) {
1002 return ((GroupAddress
!= NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
);
1007 Change the IP4 child's multicast setting. If JoinFlag is true,
1008 the child wants to join the group. Otherwise it wants to leave
1009 the group. If JoinFlag is false, and GroupAddress is NULL,
1010 it will leave all the groups which is a member.
1012 @param This The IP4 child to change the setting.
1013 @param JoinFlag TRUE to join the group, otherwise leave it.
1014 @param GroupAddress The target group address
1016 @retval EFI_INVALID_PARAMETER The parameters are invalid
1017 @retval EFI_SUCCESS The group setting has been changed.
1018 @retval Otherwise It failed to change the setting.
1025 IN EFI_IP4_PROTOCOL
*This
,
1026 IN BOOLEAN JoinFlag
,
1027 IN EFI_IPv4_ADDRESS
*GroupAddress OPTIONAL
1030 IP4_PROTOCOL
*IpInstance
;
1035 if ((This
== NULL
) || (JoinFlag
&& (GroupAddress
== NULL
))) {
1036 return EFI_INVALID_PARAMETER
;
1039 if (GroupAddress
!= NULL
) {
1040 NetCopyMem (&McastIp
, GroupAddress
, sizeof (IP4_ADDR
));
1042 if (!IP4_IS_MULTICAST (NTOHL (McastIp
))) {
1043 return EFI_INVALID_PARAMETER
;
1047 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1048 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
1050 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1051 Status
= EFI_NOT_STARTED
;
1055 if (IpInstance
->ConfigData
.UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1056 Status
= EFI_NO_MAPPING
;
1060 Status
= Ip4Groups (IpInstance
, JoinFlag
, GroupAddress
);
1063 NET_RESTORE_TPL (OldTpl
);
1069 Modify the IP child's route table. Each instance has its own
1072 @param This The IP4 child to modify the route
1073 @param DeleteRoute TRUE to delete the route, otherwise add it
1074 @param SubnetAddress The destination network
1075 @param SubnetMask The destination network's mask
1076 @param GatewayAddress The next hop address.
1078 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1079 @retval EFI_SUCCESS The route table is successfully modified.
1080 @retval Others Failed to modify the route table
1087 IN EFI_IP4_PROTOCOL
*This
,
1088 IN BOOLEAN DeleteRoute
,
1089 IN EFI_IPv4_ADDRESS
*SubnetAddress
,
1090 IN EFI_IPv4_ADDRESS
*SubnetMask
,
1091 IN EFI_IPv4_ADDRESS
*GatewayAddress
1094 IP4_PROTOCOL
*IpInstance
;
1095 IP4_INTERFACE
*IpIf
;
1103 // First, validate the parameters
1105 if ((This
== NULL
) || (SubnetAddress
== NULL
) ||
1106 (SubnetMask
== NULL
) || (GatewayAddress
== NULL
)) {
1107 return EFI_INVALID_PARAMETER
;
1110 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1111 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
1113 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1114 Status
= EFI_NOT_STARTED
;
1118 if (IpInstance
->ConfigData
.UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1119 Status
= EFI_NO_MAPPING
;
1123 NetCopyMem (&Dest
, SubnetAddress
, sizeof (IP4_ADDR
));
1124 NetCopyMem (&Netmask
, SubnetMask
, sizeof (IP4_ADDR
));
1125 NetCopyMem (&Nexthop
, GatewayAddress
, sizeof (IP4_ADDR
));
1127 Dest
= NTOHL (Dest
);
1128 Netmask
= NTOHL (Netmask
);
1129 Nexthop
= NTOHL (Nexthop
);
1131 IpIf
= IpInstance
->Interface
;
1133 if (!IP4_IS_VALID_NETMASK (Netmask
)) {
1134 Status
= EFI_INVALID_PARAMETER
;
1139 // the gateway address must be a unicast on the connected network if not zero.
1141 if ((Nexthop
!= IP4_ALLZERO_ADDRESS
) &&
1142 (!IP4_NET_EQUAL (Nexthop
, IpIf
->Ip
, IpIf
->SubnetMask
) ||
1143 IP4_IS_BROADCAST (Ip4GetNetCast (Nexthop
, IpIf
)))) {
1145 Status
= EFI_INVALID_PARAMETER
;
1150 Status
= Ip4DelRoute (IpInstance
->RouteTable
, Dest
, Netmask
, Nexthop
);
1152 Status
= Ip4AddRoute (IpInstance
->RouteTable
, Dest
, Netmask
, Nexthop
);
1156 NET_RESTORE_TPL (OldTpl
);
1162 Check whether the user's token or event has already
1163 been enqueue on IP4's list.
1165 @param Map The container of either user's transmit or receive
1167 @param Item Current item to check against
1168 @param Context The Token to check againist.
1170 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP
1171 @retval EFI_SUCCESS The current item isn't the same token/event as the
1179 IN NET_MAP_ITEM
*Item
,
1183 EFI_IP4_COMPLETION_TOKEN
*Token
;
1184 EFI_IP4_COMPLETION_TOKEN
*TokenInItem
;
1186 Token
= (EFI_IP4_COMPLETION_TOKEN
*) Context
;
1187 TokenInItem
= (EFI_IP4_COMPLETION_TOKEN
*) Item
->Key
;
1189 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
1190 return EFI_ACCESS_DENIED
;
1198 Validate the user's token against current station address.
1200 @param Token User's token to validate
1201 @param IpIf The IP4 child's interface.
1203 @retval EFI_INVALID_PARAMETER Some parameters are invalid
1204 @retval EFI_BAD_BUFFER_SIZE The user's option/data is too long.
1205 @retval EFI_SUCCESS The token is OK
1211 IN EFI_IP4_COMPLETION_TOKEN
*Token
,
1212 IN IP4_INTERFACE
*IpIf
1215 EFI_IP4_TRANSMIT_DATA
*TxData
;
1216 EFI_IP4_OVERRIDE_DATA
*Override
;
1223 if ((Token
== NULL
) || (Token
->Event
== NULL
) || (Token
->Packet
.TxData
== NULL
)) {
1224 return EFI_INVALID_PARAMETER
;
1227 TxData
= Token
->Packet
.TxData
;
1230 // Check the IP options: no more than 40 bytes and format is OK
1232 if (TxData
->OptionsLength
!= 0) {
1233 if ((TxData
->OptionsLength
> 40) || (TxData
->OptionsBuffer
== NULL
)) {
1234 return EFI_INVALID_PARAMETER
;
1237 if (!Ip4OptionIsValid (TxData
->OptionsBuffer
, TxData
->OptionsLength
, FALSE
)) {
1238 return EFI_INVALID_PARAMETER
;
1243 // Check the fragment table: no empty fragment, and length isn't bogus
1245 if ((TxData
->TotalDataLength
== 0) || (TxData
->FragmentCount
== 0)) {
1246 return EFI_INVALID_PARAMETER
;
1249 Offset
= TxData
->TotalDataLength
;
1251 for (Index
= 0; Index
< TxData
->FragmentCount
; Index
++) {
1252 if ((TxData
->FragmentTable
[Index
].FragmentBuffer
== NULL
) ||
1253 (TxData
->FragmentTable
[Index
].FragmentLength
== 0)) {
1255 return EFI_INVALID_PARAMETER
;
1258 Offset
-= TxData
->FragmentTable
[Index
].FragmentLength
;
1262 return EFI_INVALID_PARAMETER
;
1266 // Check the source and gateway: they must be a valid unicast.
1267 // Gateway must also be on the connected network.
1269 if (TxData
->OverrideData
) {
1270 Override
= TxData
->OverrideData
;
1272 NetCopyMem (&Src
, &Override
->SourceAddress
, sizeof (IP4_ADDR
));
1273 NetCopyMem (&Gateway
, &Override
->GatewayAddress
, sizeof (IP4_ADDR
));
1276 Gateway
= NTOHL (Gateway
);
1278 if ((NetGetIpClass (Src
) > IP4_ADDR_CLASSC
) ||
1279 (Src
== IP4_ALLONE_ADDRESS
) ||
1280 IP4_IS_BROADCAST (Ip4GetNetCast (Src
, IpIf
))) {
1282 return EFI_INVALID_PARAMETER
;
1286 // If gateway isn't zero, it must be a unicast address, and
1287 // on the connected network.
1289 if ((Gateway
!= IP4_ALLZERO_ADDRESS
) &&
1290 ((NetGetIpClass (Gateway
) > IP4_ADDR_CLASSC
) ||
1291 !IP4_NET_EQUAL (Gateway
, IpIf
->Ip
, IpIf
->SubnetMask
) ||
1292 IP4_IS_BROADCAST (Ip4GetNetCast (Gateway
, IpIf
)))) {
1294 return EFI_INVALID_PARAMETER
;
1299 // Check the packet length: Head length and packet length all has a limit
1301 HeadLen
= sizeof (IP4_HEAD
) + ((TxData
->OptionsLength
+ 3) &~0x03);
1303 if ((HeadLen
> IP4_MAX_HEADLEN
) ||
1304 (TxData
->TotalDataLength
+ HeadLen
> IP4_MAX_PACKET_SIZE
)) {
1306 return EFI_BAD_BUFFER_SIZE
;
1314 The callback function for the net buffer which wraps the user's
1315 transmit token. Although it seems this function is pretty simple,
1316 there are some subtle things.
1317 When user requests the IP to transmit a packet by passing it a
1318 token, the token is wrapped in an IP4_TXTOKEN_WRAP and the data
1319 is wrapped in an net buffer. the net buffer's Free function is
1320 set to Ip4FreeTxToken. The Token and token wrap are added to the
1321 IP child's TxToken map. Then the buffer is passed to Ip4Output for
1322 transmission. If something error happened before that, the buffer
1323 is freed, which in turn will free the token wrap. The wrap may
1324 have been added to the TxToken map or not, and the user's event
1325 shouldn't be fired because we are still in the EfiIp4Transmit. If
1326 the buffer has been sent by Ip4Output, it should be removed from
1327 the TxToken map and user's event signaled. The token wrap and buffer
1328 are bound together. Check the comments in Ip4Output for information
1329 about IP fragmentation.
1331 @param Context The token's wrap
1342 IP4_TXTOKEN_WRAP
*Wrap
;
1345 Wrap
= (IP4_TXTOKEN_WRAP
*) Context
;
1348 // Find the token in the instance's map. EfiIp4Transmit put the
1349 // token to the map. If that failed, NetMapFindKey will return NULL.
1351 Item
= NetMapFindKey (&Wrap
->IpInstance
->TxTokens
, Wrap
->Token
);
1354 NetMapRemoveItem (&Wrap
->IpInstance
->TxTokens
, Item
, NULL
);
1358 gBS
->SignalEvent (Wrap
->Token
->Event
);
1366 The callback function to Ip4Output to update the transmit status.
1368 @param Ip4Instance The Ip4Instance that request the transmit.
1369 @param Packet The user's transmit request
1370 @param IoStatus The result of the transmission
1371 @param Flag Not used during transmission
1372 @param Context The token's wrap.
1380 IP4_PROTOCOL
*Ip4Instance
,
1382 EFI_STATUS IoStatus
,
1387 IP4_TXTOKEN_WRAP
*Wrap
;
1390 // This is the transmission request from upper layer,
1391 // not the IP4 driver itself.
1393 ASSERT (Ip4Instance
!= NULL
);
1396 // The first fragment of the packet has been sent. Update
1397 // the token's status. That is, if fragmented, the transmit's
1398 // status is the first fragment's status. The Wrap will be
1399 // release when all the fragments are release. Check the comments
1400 // in Ip4FreeTxToken and Ip4Output for information.
1402 Wrap
= (IP4_TXTOKEN_WRAP
*) Context
;
1403 Wrap
->Token
->Status
= IoStatus
;
1405 NetbufFree (Wrap
->Packet
);
1410 Transmit the user's data asynchronously. When transmission
1411 completed,the Token's status is updated and its event signalled.
1413 @param This The IP4 child instance
1414 @param Token The user's transmit token, which contains user's
1415 data, the result and an event to signal when
1418 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1419 @retval EFI_NOT_STARTED The IP4 child hasn't been started.
1420 @retval EFI_SUCCESS The user's data has been successfully enqueued
1428 IN EFI_IP4_PROTOCOL
*This
,
1429 IN EFI_IP4_COMPLETION_TOKEN
*Token
1433 IP4_PROTOCOL
*IpInstance
;
1434 IP4_INTERFACE
*IpIf
;
1435 IP4_TXTOKEN_WRAP
*Wrap
;
1436 EFI_IP4_TRANSMIT_DATA
*TxData
;
1437 EFI_IP4_CONFIG_DATA
*Config
;
1438 EFI_IP4_OVERRIDE_DATA
*Override
;
1443 BOOLEAN DontFragment
;
1447 return EFI_INVALID_PARAMETER
;
1450 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1452 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1453 return EFI_NOT_STARTED
;
1456 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
1458 IpSb
= IpInstance
->Service
;
1459 IpIf
= IpInstance
->Interface
;
1460 Config
= &IpInstance
->ConfigData
;
1462 if (Config
->UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1463 Status
= EFI_NO_MAPPING
;
1468 // make sure that token is properly formated
1470 Status
= Ip4TxTokenValid (Token
, IpIf
);
1472 if (EFI_ERROR (Status
)) {
1477 // Check whether the token or signal already existed.
1479 if (EFI_ERROR (NetMapIterate (&IpInstance
->TxTokens
, Ip4TokenExist
, Token
))) {
1480 Status
= EFI_ACCESS_DENIED
;
1485 // Build the IP header, need to fill in the Tos, TotalLen, Id,
1486 // fragment, Ttl, protocol, Src, and Dst.
1488 TxData
= Token
->Packet
.TxData
;
1490 NetCopyMem (&Head
.Dst
, &TxData
->DestinationAddress
, sizeof (IP4_ADDR
));
1491 Head
.Dst
= NTOHL (Head
.Dst
);
1493 if (TxData
->OverrideData
) {
1494 Override
= TxData
->OverrideData
;
1495 Head
.Protocol
= Override
->Protocol
;
1496 Head
.Tos
= Override
->TypeOfService
;
1497 Head
.Ttl
= Override
->TimeToLive
;
1498 DontFragment
= Override
->DoNotFragment
;
1500 NetCopyMem (&Head
.Src
, &Override
->SourceAddress
, sizeof (IP4_ADDR
));
1501 NetCopyMem (&GateWay
, &Override
->GatewayAddress
, sizeof (IP4_ADDR
));
1503 Head
.Src
= NTOHL (Head
.Src
);
1504 GateWay
= NTOHL (GateWay
);
1506 Head
.Src
= IpIf
->Ip
;
1507 GateWay
= IP4_ALLZERO_ADDRESS
;
1508 Head
.Protocol
= Config
->DefaultProtocol
;
1509 Head
.Tos
= Config
->TypeOfService
;
1510 Head
.Ttl
= Config
->TimeToLive
;
1511 DontFragment
= Config
->DoNotFragment
;
1514 Head
.Fragment
= IP4_HEAD_FRAGMENT_FIELD (DontFragment
, FALSE
, 0);
1515 HeadLen
= sizeof (IP4_HEAD
) + ((TxData
->OptionsLength
+ 3) &~0x03);
1518 // If don't fragment and fragment needed, return error
1520 if (DontFragment
&& (TxData
->TotalDataLength
+ HeadLen
> IpSb
->SnpMode
.MaxPacketSize
)) {
1521 Status
= EFI_BAD_BUFFER_SIZE
;
1526 // OK, it survives all the validation check. Wrap the token in
1527 // a IP4_TXTOKEN_WRAP and the data in a netbuf
1529 Status
= EFI_OUT_OF_RESOURCES
;
1530 Wrap
= NetAllocatePool (sizeof (IP4_TXTOKEN_WRAP
));
1535 Wrap
->IpInstance
= IpInstance
;
1536 Wrap
->Token
= Token
;
1538 Wrap
->Life
= IP4_US_TO_SEC (Config
->TransmitTimeout
);
1539 Wrap
->Packet
= NetbufFromExt (
1540 (NET_FRAGMENT
*) TxData
->FragmentTable
,
1541 TxData
->FragmentCount
,
1548 if (Wrap
->Packet
== NULL
) {
1553 Token
->Status
= EFI_NOT_READY
;
1555 if (EFI_ERROR (NetMapInsertTail (&IpInstance
->TxTokens
, Token
, Wrap
))) {
1557 // NetbufFree will call Ip4FreeTxToken, which in turn will
1558 // free the IP4_TXTOKEN_WRAP. Now, the token wrap hasn't been
1561 NetbufFree (Wrap
->Packet
);
1565 Status
= Ip4Output (
1570 TxData
->OptionsBuffer
,
1571 TxData
->OptionsLength
,
1577 if (EFI_ERROR (Status
)) {
1578 NetbufFree (Wrap
->Packet
);
1583 // Mark the packet sent, so when Ip4FreeTxToken is called, it
1584 // will signal the upper layer.
1589 NET_RESTORE_TPL (OldTpl
);
1595 Receive a packet for the upper layer. If there are packets
1596 pending on the child's receive queue, the receive request
1597 will be fulfilled immediately. Otherwise, the request is
1598 enqueued. When receive request is completed, the status in
1599 the Token is updated and its event is signalled.
1601 @param This The IP4 child to receive packet.
1602 @param Token The user's receive token
1604 @retval EFI_INVALID_PARAMETER The token is invalid.
1605 @retval EFI_NOT_STARTED The IP4 child hasn't been started
1606 @retval EFI_ACCESS_DENIED The token or event is already queued.
1607 @retval EFI_SUCCESS The receive request has been issued.
1614 IN EFI_IP4_PROTOCOL
*This
,
1615 IN EFI_IP4_COMPLETION_TOKEN
*Token
1618 IP4_PROTOCOL
*IpInstance
;
1623 // First validate the parameters
1625 if ((This
== NULL
) || (Token
== NULL
) || (Token
->Event
== NULL
)) {
1626 return EFI_INVALID_PARAMETER
;
1629 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1631 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
1633 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1634 Status
= EFI_NOT_STARTED
;
1639 // Current Udp implementation creates an IP child for each Udp child.
1640 // It initates a asynchronous receive immediately no matter whether
1641 // there is no mapping or not. Disable this for now.
1644 if (Config
->UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1645 Status
= EFI_NO_MAPPING
;
1651 // Check whether the toke is already on the receive queue.
1653 Status
= NetMapIterate (&IpInstance
->RxTokens
, Ip4TokenExist
, Token
);
1655 if (EFI_ERROR (Status
)) {
1656 Status
= EFI_ACCESS_DENIED
;
1661 // Queue the token then check whether there is pending received packet.
1663 Status
= NetMapInsertTail (&IpInstance
->RxTokens
, Token
, NULL
);
1665 if (EFI_ERROR (Status
)) {
1669 Status
= Ip4InstanceDeliverPacket (IpInstance
);
1672 NET_RESTORE_TPL (OldTpl
);
1678 Cancel the transmitted but not recycled packet. If a matching
1679 token is found, it will call Ip4CancelPacket to cancel the
1680 packet. Ip4CancelPacket will cancel all the fragments of the
1681 packet. When all the fragments are freed, the IP4_TXTOKEN_WRAP
1682 will be deleted from the Map, and user's event signalled.
1683 Because Ip4CancelPacket and other functions are all called in
1684 line, so, after Ip4CancelPacket returns, the Item has been freed.
1686 @param Map The IP4 child's transmit queue
1687 @param Item The current transmitted packet to test.
1688 @param Context The user's token to cancel.
1690 @retval EFI_SUCCESS Continue to check the next Item.
1691 @retval EFI_ABORTED The user's Token (Token != NULL) is cancelled.
1698 IN NET_MAP_ITEM
*Item
,
1702 EFI_IP4_COMPLETION_TOKEN
*Token
;
1703 IP4_TXTOKEN_WRAP
*Wrap
;
1705 Token
= (EFI_IP4_COMPLETION_TOKEN
*) Context
;
1708 // Return EFI_SUCCESS to check the next item in the map if
1709 // this one doesn't match.
1711 if ((Token
!= NULL
) && (Token
!= Item
->Key
)) {
1715 Wrap
= (IP4_TXTOKEN_WRAP
*) Item
->Value
;
1716 ASSERT (Wrap
!= NULL
);
1719 // Don't access the Item, Wrap and Token's members after this point.
1720 // Item and wrap has been freed. And we no longer own the Token.
1722 Ip4CancelPacket (Wrap
->IpInstance
->Interface
, Wrap
->Packet
, EFI_ABORTED
);
1725 // If only one item is to be cancel, return EFI_ABORTED to stop
1726 // iterating the map any more.
1728 if (Token
!= NULL
) {
1737 Cancel the receive request. This is quiet simple, because
1738 it is only enqueued in our local receive map.
1740 @param Map The IP4 child's receive queue
1741 @param Item Current receive request to cancel.
1742 @param Context The user's token to cancel
1744 @retval EFI_SUCCESS Continue to check the next receive request on the
1746 @retval EFI_ABORTED The user's token (token != NULL) has been
1754 IN NET_MAP_ITEM
*Item
,
1758 EFI_IP4_COMPLETION_TOKEN
*Token
;
1759 EFI_IP4_COMPLETION_TOKEN
*This
;
1761 Token
= (EFI_IP4_COMPLETION_TOKEN
*) Context
;
1764 if ((Token
!= NULL
) && (Token
!= This
)) {
1768 NetMapRemoveItem (Map
, Item
, NULL
);
1770 This
->Status
= EFI_ABORTED
;
1771 This
->Packet
.RxData
= NULL
;
1772 gBS
->SignalEvent (This
->Event
);
1774 if (Token
!= NULL
) {
1783 Cancel the user's receive/transmit request.
1785 @param IpInstance The IP4 child
1786 @param Token The token to cancel. If NULL, all token will be
1789 @retval EFI_SUCCESS The token is cancelled
1790 @retval EFI_NOT_FOUND The token isn't found on either the
1791 transmit/receive queue
1792 @retval EFI_DEVICE_ERROR Not all token is cancelled when Token is NULL.
1797 IN IP4_PROTOCOL
*IpInstance
,
1798 IN EFI_IP4_COMPLETION_TOKEN
*Token OPTIONAL
1804 // First check the transmitted packet. Ip4CancelTxTokens returns
1805 // EFI_ABORTED to mean that the token has been cancelled when
1806 // token != NULL. So, return EFI_SUCCESS for this condition.
1808 Status
= NetMapIterate (&IpInstance
->TxTokens
, Ip4CancelTxTokens
, Token
);
1810 if (EFI_ERROR (Status
)) {
1811 if ((Token
!= NULL
) && (Status
== EFI_ABORTED
)) {
1819 // Check the receive queue. Ip4CancelRxTokens also returns EFI_ABORT
1820 // for Token!=NULL and it is cancelled.
1822 Status
= NetMapIterate (&IpInstance
->RxTokens
, Ip4CancelRxTokens
, Token
);
1824 if (EFI_ERROR (Status
)) {
1825 if ((Token
!= NULL
) && (Status
== EFI_ABORTED
)) {
1833 // OK, if the Token is found when Token != NULL, the NetMapIterate
1834 // will return EFI_ABORTED, which has been interrupted as EFI_SUCCESS.
1836 if (Token
!= NULL
) {
1837 return EFI_NOT_FOUND
;
1841 // If Token == NULL, cancel all the tokens. return error if no
1842 // all of them are cancelled.
1844 if (!NetMapIsEmpty (&IpInstance
->TxTokens
) ||
1845 !NetMapIsEmpty (&IpInstance
->RxTokens
)) {
1847 return EFI_DEVICE_ERROR
;
1855 Cancel the queued receive/transmit requests. If Token is NULL,
1856 all the queued requests will be cancelled. It just validate
1857 the parameter then pass them to Ip4Cancel.
1859 @param This The IP4 child to cancel the request
1860 @param Token The token to cancel, if NULL, cancel all.
1862 @retval EFI_INVALID_PARAMETER This is NULL
1863 @retval EFI_NOT_STARTED The IP4 child hasn't been configured.
1864 @retval EFI_NO_MAPPING The IP4 child is configured to use the default,
1865 but the default address hasn't been acquired.
1866 @retval EFI_SUCCESS The Token is cancelled.
1873 IN EFI_IP4_PROTOCOL
*This
,
1874 IN EFI_IP4_COMPLETION_TOKEN
*Token OPTIONAL
1877 IP4_PROTOCOL
*IpInstance
;
1882 return EFI_INVALID_PARAMETER
;
1885 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1887 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
1889 if (IpInstance
->State
!= IP4_STATE_CONFIGED
) {
1890 Status
= EFI_NOT_STARTED
;
1894 if (IpInstance
->ConfigData
.UseDefaultAddress
&& IP4_NO_MAPPING (IpInstance
)) {
1895 Status
= EFI_NO_MAPPING
;
1899 Status
= Ip4Cancel (IpInstance
, Token
);
1902 NET_RESTORE_TPL (OldTpl
);
1908 Poll the network stack. The EFI network stack is poll based. There
1909 is no interrupt support for the network interface card.
1911 @param This The IP4 child to poll through
1913 @retval EFI_INVALID_PARAMETER The parameter is invalid
1914 @retval EFI_NOT_STARTED The IP4 child hasn't been configured.
1921 IN EFI_IP4_PROTOCOL
*This
1924 IP4_PROTOCOL
*IpInstance
;
1925 EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
;
1928 return EFI_INVALID_PARAMETER
;
1931 IpInstance
= IP4_INSTANCE_FROM_PROTOCOL (This
);
1933 if (IpInstance
->State
== IP4_STATE_UNCONFIGED
) {
1934 return EFI_NOT_STARTED
;
1937 Mnp
= IpInstance
->Service
->Mnp
;
1940 // Don't lock the Poll function to enable the deliver of
1941 // the packet polled up.
1943 return Mnp
->Poll (Mnp
);
1947 mEfiIp4ProtocolTemplete
= {
1960 Decrease the life of the transmitted packets. If it is
1961 decreased to zero, cancel the packet. This function is
1962 called by Ip4packetTimerTicking which time out both the
1963 received-but-not-delivered and transmitted-but-not-recycle
1966 @param Map The IP4 child's transmit map.
1967 @param Item Current transmitted packet
1968 @param Context Not used.
1970 @retval EFI_SUCCESS Always returns EFI_SUCCESS
1974 Ip4SentPacketTicking (
1976 IN NET_MAP_ITEM
*Item
,
1980 IP4_TXTOKEN_WRAP
*Wrap
;
1982 Wrap
= (IP4_TXTOKEN_WRAP
*) Item
->Value
;
1983 ASSERT (Wrap
!= NULL
);
1985 if ((Wrap
->Life
> 0) && (--Wrap
->Life
== 0)) {
1986 Ip4CancelPacket (Wrap
->IpInstance
->Interface
, Wrap
->Packet
, EFI_ABORTED
);
1994 The heart beat timer of IP4 service instance. It times out
1995 all of its IP4 children's received-but-not-delivered and
1996 transmitted-but-not-recycle packets, and provides time input
1997 for its IGMP protocol.
1999 @param Event The IP4 service instance's heart beat timer.
2000 @param Context The IP4 service instance.
2014 IpSb
= (IP4_SERVICE
*) Context
;
2015 NET_CHECK_SIGNATURE (IpSb
, IP4_SERVICE_SIGNATURE
);
2017 Ip4PacketTimerTicking (IpSb
);
2018 Ip4IgmpTicking (IpSb
);