1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311 |
- /** @file
- Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Ip4Impl.h"
- EFI_IPSEC2_PROTOCOL *mIpSec = NULL;
- /**
- Gets the current operational settings for this instance of the EFI IPv4 Protocol driver.
- The GetModeData() function returns the current operational mode data for this
- driver instance. The data fields in EFI_IP4_MODE_DATA are read only. This
- function is used optionally to retrieve the operational mode data of underlying
- networks or drivers.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[out] Ip4ModeData Pointer to the EFI IPv4 Protocol mode data structure.
- @param[out] MnpConfigData Pointer to the managed network configuration data structure.
- @param[out] SnpModeData Pointer to the simple network mode data structure.
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4GetModeData (
- IN CONST EFI_IP4_PROTOCOL *This,
- OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,
- OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
- OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
- );
- /**
- Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance.
- The Configure() function is used to set, change, or reset the operational
- parameters and filter settings for this EFI IPv4 Protocol instance. Until these
- parameters have been set, no network traffic can be sent or received by this
- instance. Once the parameters have been reset (by calling this function with
- IpConfigData set to NULL), no more traffic can be sent or received until these
- parameters have been set again. Each EFI IPv4 Protocol instance can be started
- and stopped independently of each other by enabling or disabling their receive
- filter settings with the Configure() function.
- When IpConfigData.UseDefaultAddress is set to FALSE, the new station address will
- be appended as an alias address into the addresses list in the EFI IPv4 Protocol
- driver. While set to TRUE, Configure() will trigger the EFI_IP4_CONFIG_PROTOCOL
- to retrieve the default IPv4 address if it is not available yet. Clients could
- frequently call GetModeData() to check the status to ensure that the default IPv4
- address is ready.
- If operational parameters are reset or changed, any pending transmit and receive
- requests will be cancelled. Their completion token status will be set to EFI_ABORTED
- and their events will be signaled.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] IpConfigData Pointer to the EFI IPv4 Protocol configuration data structure.
- @retval EFI_SUCCESS The driver instance was successfully opened.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- @retval EFI_UNSUPPORTED One or more of the following conditions is TRUE:
- A configuration protocol (DHCP, BOOTP, RARP, etc.) could
- not be located when clients choose to use the default IPv4
- address. This EFI IPv4 Protocol implementation does not
- support this requested filter or timeout setting.
- @retval EFI_OUT_OF_RESOURCES The EFI IPv4 Protocol driver instance data could not be allocated.
- @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the
- IPv4 address or subnet mask can be changed. The interface must
- also be stopped when switching to/from raw packet mode.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv4
- Protocol driver instance is not opened.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Configure (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_CONFIG_DATA *IpConfigData OPTIONAL
- );
- /**
- Joins and leaves multicast groups.
- The Groups() function is used to join and leave multicast group sessions. Joining
- a group will enable reception of matching multicast packets. Leaving a group will
- disable the multicast packet reception.
- If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave.
- @param[in] GroupAddress Pointer to the IPv4 multicast address.
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
- - This is NULL.
- - JoinFlag is TRUE and GroupAddress is NULL.
- - GroupAddress is not NULL and *GroupAddress is
- not a multicast IPv4 address.
- @retval EFI_NOT_STARTED This instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_OUT_OF_RESOURCES System resources could not be allocated.
- @retval EFI_UNSUPPORTED This EFI IPv4 Protocol implementation does not support multicast groups.
- @retval EFI_ALREADY_STARTED The group address is already in the group table (when
- JoinFlag is TRUE).
- @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Groups (
- IN EFI_IP4_PROTOCOL *This,
- IN BOOLEAN JoinFlag,
- IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL
- );
- /**
- Adds and deletes routing table entries.
- The Routes() function adds a route to or deletes a route from the routing table.
- Routes are determined by comparing the SubnetAddress with the destination IPv4
- address arithmetically AND-ed with the SubnetMask. The gateway address must be
- on the same subnet as the configured station address.
- The default route is added with SubnetAddress and SubnetMask both set to 0.0.0.0.
- The default route matches all destination IPv4 addresses that do not match any
- other routes.
- A GatewayAddress that is zero is a nonroute. Packets are sent to the destination
- IP address if it can be found in the ARP cache or on the local subnet. One automatic
- nonroute entry will be inserted into the routing table for outgoing packets that
- are addressed to a local subnet (gateway address of 0.0.0.0).
- Each EFI IPv4 Protocol instance has its own independent routing table. Those EFI
- IPv4 Protocol instances that use the default IPv4 address will also have copies
- of the routing table that was provided by the EFI_IP4_CONFIG_PROTOCOL, and these
- copies will be updated whenever the EIF IPv4 Protocol driver reconfigures its
- instances. As a result, client modification to the routing table will be lost.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to
- FALSE to add this route to the routing table. SubnetAddress
- and SubnetMask are used as the key to each route entry.
- @param[in] SubnetAddress The address of the subnet that needs to be routed.
- @param[in] SubnetMask The subnet mask of SubnetAddress.
- @param[in] GatewayAddress The unicast gateway IPv4 address for this route.
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_NOT_STARTED The driver instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- - This is NULL.
- - SubnetAddress is NULL.
- - SubnetMask is NULL.
- - GatewayAddress is NULL.
- - *SubnetAddress is not a valid subnet address.
- - *SubnetMask is not a valid subnet mask.
- - *GatewayAddress is not a valid unicast IPv4 address.
- @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
- @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE).
- @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when
- DeleteRoute is FALSE).
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Routes (
- IN EFI_IP4_PROTOCOL *This,
- IN BOOLEAN DeleteRoute,
- IN EFI_IPv4_ADDRESS *SubnetAddress,
- IN EFI_IPv4_ADDRESS *SubnetMask,
- IN EFI_IPv4_ADDRESS *GatewayAddress
- );
- /**
- Places outgoing data packets into the transmit queue.
- The Transmit() function places a sending request in the transmit queue of this
- EFI IPv4 Protocol instance. Whenever the packet in the token is sent out or some
- errors occur, the event in the token will be signaled and the status is updated.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] Token Pointer to the transmit token.
- @retval EFI_SUCCESS The data has been queued for transmission.
- @retval EFI_NOT_STARTED This instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event
- was already in the transmit queue.
- @retval EFI_NOT_READY The completion token could not be queued because the transmit
- queue is full.
- @retval EFI_NOT_FOUND Not route is found to destination address.
- @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.
- @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too
- short to transmit.
- @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is
- greater than MTU (or greater than the maximum packet size if
- Token.Packet.TxData.OverrideData.
- DoNotFragment is TRUE.)
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Transmit (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_COMPLETION_TOKEN *Token
- );
- /**
- Places a receiving request into the receiving queue.
- The Receive() function places a completion token into the receive packet queue.
- This function is always asynchronous.
- The Token.Event field in the completion token must be filled in by the caller
- and cannot be NULL. When the receive operation completes, the EFI IPv4 Protocol
- driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event
- is signaled.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] Token Pointer to a token that is associated with the receive data descriptor.
- @retval EFI_SUCCESS The receive completion token was cached.
- @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, RARP, etc.)
- is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- - This is NULL.
- - Token is NULL.
- - Token.Event is NULL.
- @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system
- resources (usually memory).
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- The EFI IPv4 Protocol instance has been reset to startup defaults.
- EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already
- in the receive queue.
- @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.
- @retval EFI_ICMP_ERROR An ICMP error packet was received.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Receive (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_COMPLETION_TOKEN *Token
- );
- /**
- Abort an asynchronous transmit or receive request.
- The Cancel() function is used to abort a pending transmit or receive request.
- If the token is in the transmit or receive request queues, after calling this
- function, Token->Status will be set to EFI_ABORTED and then Token->Event will
- be signaled. If the token is not in one of the queues, which usually means the
- asynchronous operation has completed, this function will not signal the token
- and EFI_NOT_FOUND is returned.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] Token Pointer to a token that has been issued by
- EFI_IP4_PROTOCOL.Transmit() or
- EFI_IP4_PROTOCOL.Receive(). If NULL, all pending
- tokens are aborted. Type EFI_IP4_COMPLETION_TOKEN is
- defined in EFI_IP4_PROTOCOL.Transmit().
- @retval EFI_SUCCESS The asynchronous I/O request was aborted and
- Token.->Event was signaled. When Token is NULL, all
- pending requests were aborted and their events were signaled.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_NOT_STARTED This instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was
- not found in the transmit or receive queue. It has either completed
- or was not issued by Transmit() and Receive().
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Cancel (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL
- );
- /**
- Polls for incoming data packets and processes outgoing data packets.
- The Poll() function polls for incoming data packets and processes outgoing data
- packets. Network drivers and applications can call the EFI_IP4_PROTOCOL.Poll()
- function to increase the rate that data packets are moved between the communications
- device and the transmit and receive queues.
- In some systems the periodic timer event may not poll the underlying communications
- device fast enough to transmit and/or receive all data packets without missing
- incoming packets or dropping outgoing packets. Drivers and applications that are
- experiencing packet loss should try calling the EFI_IP4_PROTOCOL.Poll() function
- more often.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @retval EFI_SUCCESS Incoming or outgoing data was processed.
- @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- @retval EFI_NOT_READY No incoming or outgoing data is processed.
- @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
- Consider increasing the polling rate.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Poll (
- IN EFI_IP4_PROTOCOL *This
- );
- EFI_IP4_PROTOCOL
- mEfiIp4ProtocolTemplete = {
- EfiIp4GetModeData,
- EfiIp4Configure,
- EfiIp4Groups,
- EfiIp4Routes,
- EfiIp4Transmit,
- EfiIp4Receive,
- EfiIp4Cancel,
- EfiIp4Poll
- };
- /**
- Gets the current operational settings for this instance of the EFI IPv4 Protocol driver.
- The GetModeData() function returns the current operational mode data for this
- driver instance. The data fields in EFI_IP4_MODE_DATA are read only. This
- function is used optionally to retrieve the operational mode data of underlying
- networks or drivers.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[out] Ip4ModeData Pointer to the EFI IPv4 Protocol mode data structure.
- @param[out] MnpConfigData Pointer to the managed network configuration data structure.
- @param[out] SnpModeData Pointer to the simple network mode data structure.
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4GetModeData (
- IN CONST EFI_IP4_PROTOCOL *This,
- OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,
- OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
- OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
- )
- {
- IP4_PROTOCOL *IpInstance;
- IP4_SERVICE *IpSb;
- EFI_IP4_CONFIG_DATA *Config;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- IP4_ADDR Ip;
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- IpSb = IpInstance->Service;
- if (Ip4ModeData != NULL) {
- //
- // IsStarted is "whether the EfiIp4Configure has been called".
- // IsConfigured is "whether the station address has been configured"
- //
- Ip4ModeData->IsStarted = (BOOLEAN)(IpInstance->State == IP4_STATE_CONFIGED);
- CopyMem (&Ip4ModeData->ConfigData, &IpInstance->ConfigData, sizeof (Ip4ModeData->ConfigData));
- Ip4ModeData->IsConfigured = FALSE;
- Ip4ModeData->GroupCount = IpInstance->GroupCount;
- Ip4ModeData->GroupTable = (EFI_IPv4_ADDRESS *)IpInstance->Groups;
- Ip4ModeData->IcmpTypeCount = 23;
- Ip4ModeData->IcmpTypeList = mIp4SupportedIcmp;
- Ip4ModeData->RouteTable = NULL;
- Ip4ModeData->RouteCount = 0;
- Ip4ModeData->MaxPacketSize = IpSb->MaxPacketSize;
- //
- // return the current station address for this IP child. So,
- // the user can get the default address through this. Some
- // application wants to know it station address even it is
- // using the default one, such as a ftp server.
- //
- if (Ip4ModeData->IsStarted) {
- Config = &Ip4ModeData->ConfigData;
- Ip = HTONL (IpInstance->Interface->Ip);
- CopyMem (&Config->StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
- Ip = HTONL (IpInstance->Interface->SubnetMask);
- CopyMem (&Config->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
- Ip4ModeData->IsConfigured = IpInstance->Interface->Configured;
- //
- // Build a EFI route table for user from the internal route table.
- //
- Status = Ip4BuildEfiRouteTable (IpInstance);
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- Ip4ModeData->RouteTable = IpInstance->EfiRouteTable;
- Ip4ModeData->RouteCount = IpInstance->EfiRouteCount;
- }
- }
- //
- // Get fresh mode data from MNP, since underlying media status may change
- //
- Status = IpSb->Mnp->GetModeData (IpSb->Mnp, MnpConfigData, SnpModeData);
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Config the MNP parameter used by IP. The IP driver use one MNP
- child to transmit/receive frames. By default, it configures MNP
- to receive unicast/multicast/broadcast. And it will enable/disable
- the promiscous receive according to whether there is IP child
- enable that or not. If Force is FALSE, it will iterate through
- all the IP children to check whether the promiscuous receive
- setting has been changed. If it hasn't been changed, it won't
- reconfigure the MNP. If Force is TRUE, the MNP is configured no
- matter whether that is changed or not.
- @param[in] IpSb The IP4 service instance that is to be changed.
- @param[in] Force Force the configuration or not.
- @retval EFI_SUCCESS The MNP is successfully configured/reconfigured.
- @retval Others Configuration failed.
- **/
- EFI_STATUS
- Ip4ServiceConfigMnp (
- IN IP4_SERVICE *IpSb,
- IN BOOLEAN Force
- )
- {
- LIST_ENTRY *Entry;
- LIST_ENTRY *ProtoEntry;
- IP4_INTERFACE *IpIf;
- IP4_PROTOCOL *IpInstance;
- BOOLEAN Reconfig;
- BOOLEAN PromiscReceive;
- EFI_STATUS Status;
- Reconfig = FALSE;
- PromiscReceive = FALSE;
- if (!Force) {
- //
- // Iterate through the IP children to check whether promiscuous
- // receive setting has been changed. Update the interface's receive
- // filter also.
- //
- NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
- IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
- IpIf->PromiscRecv = FALSE;
- NET_LIST_FOR_EACH (ProtoEntry, &IpIf->IpInstances) {
- IpInstance = NET_LIST_USER_STRUCT (ProtoEntry, IP4_PROTOCOL, AddrLink);
- if (IpInstance->ConfigData.AcceptPromiscuous) {
- IpIf->PromiscRecv = TRUE;
- PromiscReceive = TRUE;
- }
- }
- }
- //
- // If promiscuous receive isn't changed, it isn't necessary to reconfigure.
- //
- if (PromiscReceive == IpSb->MnpConfigData.EnablePromiscuousReceive) {
- return EFI_SUCCESS;
- }
- Reconfig = TRUE;
- IpSb->MnpConfigData.EnablePromiscuousReceive = PromiscReceive;
- }
- Status = IpSb->Mnp->Configure (IpSb->Mnp, &IpSb->MnpConfigData);
- //
- // recover the original configuration if failed to set the configure.
- //
- if (EFI_ERROR (Status) && Reconfig) {
- IpSb->MnpConfigData.EnablePromiscuousReceive = (BOOLEAN) !PromiscReceive;
- }
- return Status;
- }
- /**
- Initialize the IP4_PROTOCOL structure to the unconfigured states.
- @param IpSb The IP4 service instance.
- @param IpInstance The IP4 child instance.
- **/
- VOID
- Ip4InitProtocol (
- IN IP4_SERVICE *IpSb,
- IN OUT IP4_PROTOCOL *IpInstance
- )
- {
- ASSERT ((IpSb != NULL) && (IpInstance != NULL));
- ZeroMem (IpInstance, sizeof (IP4_PROTOCOL));
- IpInstance->Signature = IP4_PROTOCOL_SIGNATURE;
- CopyMem (&IpInstance->Ip4Proto, &mEfiIp4ProtocolTemplete, sizeof (IpInstance->Ip4Proto));
- IpInstance->State = IP4_STATE_UNCONFIGED;
- IpInstance->InDestroy = FALSE;
- IpInstance->Service = IpSb;
- InitializeListHead (&IpInstance->Link);
- NetMapInit (&IpInstance->RxTokens);
- NetMapInit (&IpInstance->TxTokens);
- InitializeListHead (&IpInstance->Received);
- InitializeListHead (&IpInstance->Delivered);
- InitializeListHead (&IpInstance->AddrLink);
- EfiInitializeLock (&IpInstance->RecycleLock, TPL_NOTIFY);
- }
- /**
- Configure the IP4 child. If the child is already configured,
- change the configuration parameter. Otherwise configure it
- for the first time. The caller should validate the configuration
- before deliver them to it. It also don't do configure NULL.
- @param[in, out] IpInstance The IP4 child to configure.
- @param[in] Config The configure data.
- @retval EFI_SUCCESS The IP4 child is successfully configured.
- @retval EFI_DEVICE_ERROR Failed to free the pending transive or to
- configure underlying MNP or other errors.
- @retval EFI_NO_MAPPING The IP4 child is configured to use default
- address, but the default address hasn't been
- configured. The IP4 child doesn't need to be
- reconfigured when default address is configured.
- @retval EFI_OUT_OF_RESOURCES No more memory space is available.
- @retval other Other error occurs.
- **/
- EFI_STATUS
- Ip4ConfigProtocol (
- IN OUT IP4_PROTOCOL *IpInstance,
- IN EFI_IP4_CONFIG_DATA *Config
- )
- {
- IP4_SERVICE *IpSb;
- IP4_INTERFACE *IpIf;
- EFI_STATUS Status;
- IP4_ADDR Ip;
- IP4_ADDR Netmask;
- EFI_ARP_PROTOCOL *Arp;
- EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
- EFI_IP4_CONFIG2_POLICY Policy;
- IpSb = IpInstance->Service;
- Ip4Config2 = NULL;
- //
- // User is changing packet filters. It must be stopped
- // before the station address can be changed.
- //
- if (IpInstance->State == IP4_STATE_CONFIGED) {
- //
- // Cancel all the pending transmit/receive from upper layer
- //
- Status = Ip4Cancel (IpInstance, NULL);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData));
- return EFI_SUCCESS;
- }
- //
- // Configure a fresh IP4 protocol instance. Create a route table.
- // Each IP child has its own route table, which may point to the
- // default table if it is using default address.
- //
- Status = EFI_OUT_OF_RESOURCES;
- IpInstance->RouteTable = Ip4CreateRouteTable ();
- if (IpInstance->RouteTable == NULL) {
- return Status;
- }
- //
- // Set up the interface.
- //
- CopyMem (&Ip, &Config->StationAddress, sizeof (IP4_ADDR));
- CopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));
- Ip = NTOHL (Ip);
- Netmask = NTOHL (Netmask);
- if (!Config->UseDefaultAddress) {
- //
- // Find whether there is already an interface with the same
- // station address. All the instances with the same station
- // address shares one interface.
- //
- IpIf = Ip4FindStationAddress (IpSb, Ip, Netmask);
- if (IpIf != NULL) {
- NET_GET_REF (IpIf);
- } else {
- IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);
- if (IpIf == NULL) {
- goto ON_ERROR;
- }
- Status = Ip4SetAddress (IpIf, Ip, Netmask);
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- Ip4FreeInterface (IpIf, IpInstance);
- goto ON_ERROR;
- }
- InsertTailList (&IpSb->Interfaces, &IpIf->Link);
- }
- //
- // Add a route to this connected network in the instance route table.
- //
- Ip4AddRoute (
- IpInstance->RouteTable,
- Ip & Netmask,
- Netmask,
- IP4_ALLZERO_ADDRESS
- );
- } else {
- //
- // Use the default address. Check the state.
- //
- if (IpSb->State == IP4_SERVICE_UNSTARTED) {
- //
- // Trigger the EFI_IP4_CONFIG2_PROTOCOL to retrieve the
- // default IPv4 address if it is not available yet.
- //
- Policy = IpSb->Ip4Config2Instance.Policy;
- if (Policy != Ip4Config2PolicyDhcp) {
- Ip4Config2 = &IpSb->Ip4Config2Instance.Ip4Config2;
- Policy = Ip4Config2PolicyDhcp;
- Status = Ip4Config2->SetData (
- Ip4Config2,
- Ip4Config2DataTypePolicy,
- sizeof (EFI_IP4_CONFIG2_POLICY),
- &Policy
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- }
- }
- IpIf = IpSb->DefaultInterface;
- NET_GET_REF (IpSb->DefaultInterface);
- //
- // If default address is used, so is the default route table.
- // Any route set by the instance has the precedence over the
- // routes in the default route table. Link the default table
- // after the instance's table. Routing will search the local
- // table first.
- //
- NET_GET_REF (IpSb->DefaultRouteTable);
- IpInstance->RouteTable->Next = IpSb->DefaultRouteTable;
- }
- IpInstance->Interface = IpIf;
- if (IpIf->Arp != NULL) {
- Arp = NULL;
- Status = gBS->OpenProtocol (
- IpIf->ArpHandle,
- &gEfiArpProtocolGuid,
- (VOID **)&Arp,
- gIp4DriverBinding.DriverBindingHandle,
- IpInstance->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- if (EFI_ERROR (Status)) {
- Ip4FreeInterface (IpIf, IpInstance);
- goto ON_ERROR;
- }
- }
- InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink);
- CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData));
- IpInstance->State = IP4_STATE_CONFIGED;
- //
- // Although EFI_NO_MAPPING is an error code, the IP child has been
- // successfully configured and doesn't need reconfiguration when
- // default address is acquired.
- //
- if (Config->UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {
- return EFI_NO_MAPPING;
- }
- return EFI_SUCCESS;
- ON_ERROR:
- Ip4FreeRouteTable (IpInstance->RouteTable);
- IpInstance->RouteTable = NULL;
- return Status;
- }
- /**
- Clean up the IP4 child, release all the resources used by it.
- @param[in] IpInstance The IP4 child to clean up.
- @retval EFI_SUCCESS The IP4 child is cleaned up.
- @retval EFI_DEVICE_ERROR Some resources failed to be released.
- **/
- EFI_STATUS
- Ip4CleanProtocol (
- IN IP4_PROTOCOL *IpInstance
- )
- {
- if (EFI_ERROR (Ip4Cancel (IpInstance, NULL))) {
- return EFI_DEVICE_ERROR;
- }
- if (EFI_ERROR (Ip4Groups (IpInstance, FALSE, NULL))) {
- return EFI_DEVICE_ERROR;
- }
- //
- // Some packets haven't been recycled. It is because either the
- // user forgets to recycle the packets, or because the callback
- // hasn't been called. Just leave it alone.
- //
- if (!IsListEmpty (&IpInstance->Delivered)) {
- }
- if (IpInstance->Interface != NULL) {
- RemoveEntryList (&IpInstance->AddrLink);
- if (IpInstance->Interface->Arp != NULL) {
- gBS->CloseProtocol (
- IpInstance->Interface->ArpHandle,
- &gEfiArpProtocolGuid,
- gIp4DriverBinding.DriverBindingHandle,
- IpInstance->Handle
- );
- }
- Ip4FreeInterface (IpInstance->Interface, IpInstance);
- IpInstance->Interface = NULL;
- }
- if (IpInstance->RouteTable != NULL) {
- if (IpInstance->RouteTable->Next != NULL) {
- Ip4FreeRouteTable (IpInstance->RouteTable->Next);
- }
- Ip4FreeRouteTable (IpInstance->RouteTable);
- IpInstance->RouteTable = NULL;
- }
- if (IpInstance->EfiRouteTable != NULL) {
- FreePool (IpInstance->EfiRouteTable);
- IpInstance->EfiRouteTable = NULL;
- IpInstance->EfiRouteCount = 0;
- }
- if (IpInstance->Groups != NULL) {
- FreePool (IpInstance->Groups);
- IpInstance->Groups = NULL;
- IpInstance->GroupCount = 0;
- }
- NetMapClean (&IpInstance->TxTokens);
- NetMapClean (&IpInstance->RxTokens);
- return EFI_SUCCESS;
- }
- /**
- Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance.
- The Configure() function is used to set, change, or reset the operational
- parameters and filter settings for this EFI IPv4 Protocol instance. Until these
- parameters have been set, no network traffic can be sent or received by this
- instance. Once the parameters have been reset (by calling this function with
- IpConfigData set to NULL), no more traffic can be sent or received until these
- parameters have been set again. Each EFI IPv4 Protocol instance can be started
- and stopped independently of each other by enabling or disabling their receive
- filter settings with the Configure() function.
- When IpConfigData.UseDefaultAddress is set to FALSE, the new station address will
- be appended as an alias address into the addresses list in the EFI IPv4 Protocol
- driver. While set to TRUE, Configure() will trigger the EFI_IP4_CONFIG_PROTOCOL
- to retrieve the default IPv4 address if it is not available yet. Clients could
- frequently call GetModeData() to check the status to ensure that the default IPv4
- address is ready.
- If operational parameters are reset or changed, any pending transmit and receive
- requests will be cancelled. Their completion token status will be set to EFI_ABORTED
- and their events will be signaled.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] IpConfigData Pointer to the EFI IPv4 Protocol configuration data structure.
- @retval EFI_SUCCESS The driver instance was successfully opened.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- @retval EFI_UNSUPPORTED One or more of the following conditions is TRUE:
- A configuration protocol (DHCP, BOOTP, RARP, etc.) could
- not be located when clients choose to use the default IPv4
- address. This EFI IPv4 Protocol implementation does not
- support this requested filter or timeout setting.
- @retval EFI_OUT_OF_RESOURCES The EFI IPv4 Protocol driver instance data could not be allocated.
- @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the
- IPv4 address or subnet mask can be changed. The interface must
- also be stopped when switching to/from raw packet mode.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv4
- Protocol driver instance is not opened.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Configure (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_CONFIG_DATA *IpConfigData OPTIONAL
- )
- {
- IP4_PROTOCOL *IpInstance;
- EFI_IP4_CONFIG_DATA *Current;
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- BOOLEAN AddrOk;
- IP4_ADDR IpAddress;
- IP4_ADDR SubnetMask;
- //
- // First, validate the parameters
- //
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- //
- // Validate the configuration first.
- //
- if (IpConfigData != NULL) {
- CopyMem (&IpAddress, &IpConfigData->StationAddress, sizeof (IP4_ADDR));
- CopyMem (&SubnetMask, &IpConfigData->SubnetMask, sizeof (IP4_ADDR));
- IpAddress = NTOHL (IpAddress);
- SubnetMask = NTOHL (SubnetMask);
- //
- // Check whether the station address is a valid unicast address
- //
- if (!IpConfigData->UseDefaultAddress) {
- AddrOk = Ip4StationAddressValid (IpAddress, SubnetMask);
- if (!AddrOk) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
- }
- //
- // User can only update packet filters when already configured.
- // If it wants to change the station address, it must configure(NULL)
- // the instance first.
- //
- if (IpInstance->State == IP4_STATE_CONFIGED) {
- Current = &IpInstance->ConfigData;
- if (Current->UseDefaultAddress != IpConfigData->UseDefaultAddress) {
- Status = EFI_ALREADY_STARTED;
- goto ON_EXIT;
- }
- if (!Current->UseDefaultAddress &&
- (!EFI_IP4_EQUAL (&Current->StationAddress, &IpConfigData->StationAddress) ||
- !EFI_IP4_EQUAL (&Current->SubnetMask, &IpConfigData->SubnetMask)))
- {
- Status = EFI_ALREADY_STARTED;
- goto ON_EXIT;
- }
- if (Current->UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {
- Status = EFI_NO_MAPPING;
- goto ON_EXIT;
- }
- }
- }
- //
- // Configure the instance or clean it up.
- //
- if (IpConfigData != NULL) {
- Status = Ip4ConfigProtocol (IpInstance, IpConfigData);
- } else {
- Status = Ip4CleanProtocol (IpInstance);
- //
- // Consider the following valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,
- // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED,
- // the unload fails miserably.
- //
- if (IpInstance->State == IP4_STATE_CONFIGED) {
- IpInstance->State = IP4_STATE_UNCONFIGED;
- }
- }
- //
- // Update the MNP's configure data. Ip4ServiceConfigMnp will check
- // whether it is necessary to reconfigure the MNP.
- //
- Ip4ServiceConfigMnp (IpInstance->Service, FALSE);
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Change the IP4 child's multicast setting. The caller
- should make sure that the parameters is valid.
- @param[in] IpInstance The IP4 child to change the setting.
- @param[in] JoinFlag TRUE to join the group, otherwise leave it.
- @param[in] GroupAddress The target group address.
- @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
- @retval EFI_DEVICE_ERROR Failed to set the group configuration.
- @retval EFI_SUCCESS Successfully updated the group setting.
- @retval EFI_NOT_FOUND Try to leave the group which it isn't a member.
- **/
- EFI_STATUS
- Ip4Groups (
- IN IP4_PROTOCOL *IpInstance,
- IN BOOLEAN JoinFlag,
- IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL
- )
- {
- IP4_ADDR *Members;
- IP4_ADDR Group;
- UINT32 Index;
- //
- // Add it to the instance's Groups, and join the group by IGMP.
- // IpInstance->Groups is in network byte order. IGMP operates in
- // host byte order
- //
- if (JoinFlag) {
- //
- // When JoinFlag is TRUE, GroupAddress shouldn't be NULL.
- //
- ASSERT (GroupAddress != NULL);
- CopyMem (&Group, GroupAddress, sizeof (IP4_ADDR));
- for (Index = 0; Index < IpInstance->GroupCount; Index++) {
- if (IpInstance->Groups[Index] == Group) {
- return EFI_ALREADY_STARTED;
- }
- }
- Members = Ip4CombineGroups (IpInstance->Groups, IpInstance->GroupCount, Group);
- if (Members == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- if (EFI_ERROR (Ip4JoinGroup (IpInstance, NTOHL (Group)))) {
- FreePool (Members);
- return EFI_DEVICE_ERROR;
- }
- if (IpInstance->Groups != NULL) {
- FreePool (IpInstance->Groups);
- }
- IpInstance->Groups = Members;
- IpInstance->GroupCount++;
- return EFI_SUCCESS;
- }
- //
- // Leave the group. Leave all the groups if GroupAddress is NULL.
- // Must iterate from the end to the beginning because the GroupCount
- // is decremented each time an address is removed..
- //
- for (Index = IpInstance->GroupCount; Index > 0; Index--) {
- ASSERT (IpInstance->Groups != NULL);
- Group = IpInstance->Groups[Index - 1];
- if ((GroupAddress == NULL) || EFI_IP4_EQUAL (&Group, GroupAddress)) {
- if (EFI_ERROR (Ip4LeaveGroup (IpInstance, NTOHL (Group)))) {
- return EFI_DEVICE_ERROR;
- }
- Ip4RemoveGroupAddr (IpInstance->Groups, IpInstance->GroupCount, Group);
- IpInstance->GroupCount--;
- if (IpInstance->GroupCount == 0) {
- ASSERT (Index == 1);
- FreePool (IpInstance->Groups);
- IpInstance->Groups = NULL;
- }
- if (GroupAddress != NULL) {
- return EFI_SUCCESS;
- }
- }
- }
- return ((GroupAddress != NULL) ? EFI_NOT_FOUND : EFI_SUCCESS);
- }
- /**
- Joins and leaves multicast groups.
- The Groups() function is used to join and leave multicast group sessions. Joining
- a group will enable reception of matching multicast packets. Leaving a group will
- disable the multicast packet reception.
- If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave.
- @param[in] GroupAddress Pointer to the IPv4 multicast address.
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_INVALID_PARAMETER One or more of the following is TRUE:
- - This is NULL.
- - JoinFlag is TRUE and GroupAddress is NULL.
- - GroupAddress is not NULL and *GroupAddress is
- not a multicast IPv4 address.
- @retval EFI_NOT_STARTED This instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_OUT_OF_RESOURCES System resources could not be allocated.
- @retval EFI_UNSUPPORTED This EFI IPv4 Protocol implementation does not support multicast groups.
- @retval EFI_ALREADY_STARTED The group address is already in the group table (when
- JoinFlag is TRUE).
- @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Groups (
- IN EFI_IP4_PROTOCOL *This,
- IN BOOLEAN JoinFlag,
- IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL
- )
- {
- IP4_PROTOCOL *IpInstance;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- IP4_ADDR McastIp;
- if ((This == NULL) || (JoinFlag && (GroupAddress == NULL))) {
- return EFI_INVALID_PARAMETER;
- }
- if (GroupAddress != NULL) {
- CopyMem (&McastIp, GroupAddress, sizeof (IP4_ADDR));
- if (!IP4_IS_MULTICAST (NTOHL (McastIp))) {
- return EFI_INVALID_PARAMETER;
- }
- }
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- if (IpInstance->State != IP4_STATE_CONFIGED) {
- Status = EFI_NOT_STARTED;
- goto ON_EXIT;
- }
- if (IpInstance->ConfigData.UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {
- Status = EFI_NO_MAPPING;
- goto ON_EXIT;
- }
- Status = Ip4Groups (IpInstance, JoinFlag, GroupAddress);
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Adds and deletes routing table entries.
- The Routes() function adds a route to or deletes a route from the routing table.
- Routes are determined by comparing the SubnetAddress with the destination IPv4
- address arithmetically AND-ed with the SubnetMask. The gateway address must be
- on the same subnet as the configured station address.
- The default route is added with SubnetAddress and SubnetMask both set to 0.0.0.0.
- The default route matches all destination IPv4 addresses that do not match any
- other routes.
- A GatewayAddress that is zero is a nonroute. Packets are sent to the destination
- IP address if it can be found in the ARP cache or on the local subnet. One automatic
- nonroute entry will be inserted into the routing table for outgoing packets that
- are addressed to a local subnet (gateway address of 0.0.0.0).
- Each EFI IPv4 Protocol instance has its own independent routing table. Those EFI
- IPv4 Protocol instances that use the default IPv4 address will also have copies
- of the routing table that was provided by the EFI_IP4_CONFIG_PROTOCOL, and these
- copies will be updated whenever the EIF IPv4 Protocol driver reconfigures its
- instances. As a result, client modification to the routing table will be lost.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to
- FALSE to add this route to the routing table. SubnetAddress
- and SubnetMask are used as the key to each route entry.
- @param[in] SubnetAddress The address of the subnet that needs to be routed.
- @param[in] SubnetMask The subnet mask of SubnetAddress.
- @param[in] GatewayAddress The unicast gateway IPv4 address for this route.
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_NOT_STARTED The driver instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- - This is NULL.
- - SubnetAddress is NULL.
- - SubnetMask is NULL.
- - GatewayAddress is NULL.
- - *SubnetAddress is not a valid subnet address.
- - *SubnetMask is not a valid subnet mask.
- - *GatewayAddress is not a valid unicast IPv4 address.
- @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
- @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE).
- @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when
- DeleteRoute is FALSE).
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Routes (
- IN EFI_IP4_PROTOCOL *This,
- IN BOOLEAN DeleteRoute,
- IN EFI_IPv4_ADDRESS *SubnetAddress,
- IN EFI_IPv4_ADDRESS *SubnetMask,
- IN EFI_IPv4_ADDRESS *GatewayAddress
- )
- {
- IP4_PROTOCOL *IpInstance;
- IP4_INTERFACE *IpIf;
- IP4_ADDR Dest;
- IP4_ADDR Netmask;
- IP4_ADDR Nexthop;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- //
- // First, validate the parameters
- //
- if ((This == NULL) || (SubnetAddress == NULL) ||
- (SubnetMask == NULL) || (GatewayAddress == NULL))
- {
- return EFI_INVALID_PARAMETER;
- }
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- if (IpInstance->State != IP4_STATE_CONFIGED) {
- Status = EFI_NOT_STARTED;
- goto ON_EXIT;
- }
- if (IpInstance->ConfigData.UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {
- Status = EFI_NO_MAPPING;
- goto ON_EXIT;
- }
- CopyMem (&Dest, SubnetAddress, sizeof (IP4_ADDR));
- CopyMem (&Netmask, SubnetMask, sizeof (IP4_ADDR));
- CopyMem (&Nexthop, GatewayAddress, sizeof (IP4_ADDR));
- Dest = NTOHL (Dest);
- Netmask = NTOHL (Netmask);
- Nexthop = NTOHL (Nexthop);
- IpIf = IpInstance->Interface;
- if (!IP4_IS_VALID_NETMASK (Netmask)) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
- //
- // the gateway address must be a unicast on the connected network if not zero.
- //
- if ((Nexthop != IP4_ALLZERO_ADDRESS) &&
- (((IpIf->SubnetMask != IP4_ALLONE_ADDRESS) && !IP4_NET_EQUAL (Nexthop, IpIf->Ip, IpIf->SubnetMask)) ||
- IP4_IS_BROADCAST (Ip4GetNetCast (Nexthop, IpIf))))
- {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
- if (DeleteRoute) {
- Status = Ip4DelRoute (IpInstance->RouteTable, Dest, Netmask, Nexthop);
- } else {
- Status = Ip4AddRoute (IpInstance->RouteTable, Dest, Netmask, Nexthop);
- }
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Check whether the user's token or event has already
- been enqueued on IP4's list.
- @param[in] Map The container of either user's transmit or receive
- token.
- @param[in] Item Current item to check against.
- @param[in] Context The Token to check against.
- @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP.
- @retval EFI_SUCCESS The current item isn't the same token/event as the
- context.
- **/
- EFI_STATUS
- EFIAPI
- Ip4TokenExist (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Context
- )
- {
- EFI_IP4_COMPLETION_TOKEN *Token;
- EFI_IP4_COMPLETION_TOKEN *TokenInItem;
- Token = (EFI_IP4_COMPLETION_TOKEN *)Context;
- TokenInItem = (EFI_IP4_COMPLETION_TOKEN *)Item->Key;
- if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
- return EFI_ACCESS_DENIED;
- }
- return EFI_SUCCESS;
- }
- /**
- Validate the user's token against current station address.
- @param[in] Token User's token to validate.
- @param[in] IpIf The IP4 child's interface.
- @param[in] RawData Set to TRUE to send unformatted packets.
- @retval EFI_INVALID_PARAMETER Some parameters are invalid.
- @retval EFI_BAD_BUFFER_SIZE The user's option/data is too long.
- @retval EFI_SUCCESS The token is valid.
- **/
- EFI_STATUS
- Ip4TxTokenValid (
- IN EFI_IP4_COMPLETION_TOKEN *Token,
- IN IP4_INTERFACE *IpIf,
- IN BOOLEAN RawData
- )
- {
- EFI_IP4_TRANSMIT_DATA *TxData;
- EFI_IP4_OVERRIDE_DATA *Override;
- IP4_ADDR Src;
- IP4_ADDR Gateway;
- UINT32 Offset;
- UINT32 Index;
- UINT32 HeadLen;
- if ((Token == NULL) || (Token->Event == NULL) || (Token->Packet.TxData == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- TxData = Token->Packet.TxData;
- //
- // Check the fragment table: no empty fragment, and length isn't bogus.
- //
- if ((TxData->TotalDataLength == 0) || (TxData->FragmentCount == 0)) {
- return EFI_INVALID_PARAMETER;
- }
- Offset = TxData->TotalDataLength;
- if (Offset > IP4_MAX_PACKET_SIZE) {
- return EFI_BAD_BUFFER_SIZE;
- }
- for (Index = 0; Index < TxData->FragmentCount; Index++) {
- if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) ||
- (TxData->FragmentTable[Index].FragmentLength == 0))
- {
- return EFI_INVALID_PARAMETER;
- }
- Offset -= TxData->FragmentTable[Index].FragmentLength;
- }
- if (Offset != 0) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // NOTE that OptionsLength/OptionsBuffer/OverrideData are ignored if RawData
- // is TRUE.
- //
- if (RawData) {
- return EFI_SUCCESS;
- }
- //
- // Check the IP options: no more than 40 bytes and format is OK
- //
- if (TxData->OptionsLength != 0) {
- if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) {
- return EFI_INVALID_PARAMETER;
- }
- }
- //
- // Check the source and gateway: they must be a valid unicast.
- // Gateway must also be on the connected network.
- //
- if (TxData->OverrideData != NULL) {
- Override = TxData->OverrideData;
- CopyMem (&Src, &Override->SourceAddress, sizeof (IP4_ADDR));
- CopyMem (&Gateway, &Override->GatewayAddress, sizeof (IP4_ADDR));
- Src = NTOHL (Src);
- Gateway = NTOHL (Gateway);
- if ((NetGetIpClass (Src) > IP4_ADDR_CLASSC) ||
- (Src == IP4_ALLONE_ADDRESS) ||
- IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf)))
- {
- return EFI_INVALID_PARAMETER;
- }
- //
- // If gateway isn't zero, it must be a unicast address, and
- // on the connected network.
- //
- if ((Gateway != IP4_ALLZERO_ADDRESS) &&
- ((NetGetIpClass (Gateway) > IP4_ADDR_CLASSC) ||
- !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask) ||
- IP4_IS_BROADCAST (Ip4GetNetCast (Gateway, IpIf))))
- {
- return EFI_INVALID_PARAMETER;
- }
- }
- //
- // Check the packet length: Head length and packet length all has a limit
- //
- HeadLen = sizeof (IP4_HEAD) + ((TxData->OptionsLength + 3) &~0x03);
- if ((HeadLen > IP4_MAX_HEADLEN) ||
- (TxData->TotalDataLength + HeadLen > IP4_MAX_PACKET_SIZE))
- {
- return EFI_BAD_BUFFER_SIZE;
- }
- return EFI_SUCCESS;
- }
- /**
- The callback function for the net buffer which wraps the user's
- transmit token. Although it seems this function is pretty simple,
- there are some subtle things.
- When user requests the IP to transmit a packet by passing it a
- token, the token is wrapped in an IP4_TXTOKEN_WRAP and the data
- is wrapped in an net buffer. the net buffer's Free function is
- set to Ip4FreeTxToken. The Token and token wrap are added to the
- IP child's TxToken map. Then the buffer is passed to Ip4Output for
- transmission. If something error happened before that, the buffer
- is freed, which in turn will free the token wrap. The wrap may
- have been added to the TxToken map or not, and the user's event
- shouldn't be fired because we are still in the EfiIp4Transmit. If
- the buffer has been sent by Ip4Output, it should be removed from
- the TxToken map and user's event signaled. The token wrap and buffer
- are bound together. Check the comments in Ip4Output for information
- about IP fragmentation.
- @param[in] Context The token's wrap.
- **/
- VOID
- EFIAPI
- Ip4FreeTxToken (
- IN VOID *Context
- )
- {
- IP4_TXTOKEN_WRAP *Wrap;
- NET_MAP_ITEM *Item;
- Wrap = (IP4_TXTOKEN_WRAP *)Context;
- //
- // Signal IpSecRecycleEvent to inform IPsec free the memory
- //
- if (Wrap->IpSecRecycleSignal != NULL) {
- gBS->SignalEvent (Wrap->IpSecRecycleSignal);
- }
- //
- // Find the token in the instance's map. EfiIp4Transmit put the
- // token to the map. If that failed, NetMapFindKey will return NULL.
- //
- Item = NetMapFindKey (&Wrap->IpInstance->TxTokens, Wrap->Token);
- if (Item != NULL) {
- NetMapRemoveItem (&Wrap->IpInstance->TxTokens, Item, NULL);
- }
- if (Wrap->Sent) {
- gBS->SignalEvent (Wrap->Token->Event);
- //
- // Dispatch the DPC queued by the NotifyFunction of Token->Event.
- //
- DispatchDpc ();
- }
- FreePool (Wrap);
- }
- /**
- The callback function to Ip4Output to update the transmit status.
- @param Ip4Instance The Ip4Instance that request the transmit.
- @param Packet The user's transmit request.
- @param IoStatus The result of the transmission.
- @param Flag Not used during transmission.
- @param Context The token's wrap.
- **/
- VOID
- Ip4OnPacketSent (
- IP4_PROTOCOL *Ip4Instance,
- NET_BUF *Packet,
- EFI_STATUS IoStatus,
- UINT32 Flag,
- VOID *Context
- )
- {
- IP4_TXTOKEN_WRAP *Wrap;
- //
- // This is the transmission request from upper layer,
- // not the IP4 driver itself.
- //
- ASSERT (Ip4Instance != NULL);
- //
- // The first fragment of the packet has been sent. Update
- // the token's status. That is, if fragmented, the transmit's
- // status is the first fragment's status. The Wrap will be
- // release when all the fragments are release. Check the comments
- // in Ip4FreeTxToken and Ip4Output for information.
- //
- Wrap = (IP4_TXTOKEN_WRAP *)Context;
- Wrap->Token->Status = IoStatus;
- NetbufFree (Wrap->Packet);
- }
- /**
- Places outgoing data packets into the transmit queue.
- The Transmit() function places a sending request in the transmit queue of this
- EFI IPv4 Protocol instance. Whenever the packet in the token is sent out or some
- errors occur, the event in the token will be signaled and the status is updated.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] Token Pointer to the transmit token.
- @retval EFI_SUCCESS The data has been queued for transmission.
- @retval EFI_NOT_STARTED This instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event
- was already in the transmit queue.
- @retval EFI_NOT_READY The completion token could not be queued because the transmit
- queue is full.
- @retval EFI_NOT_FOUND Not route is found to destination address.
- @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.
- @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too
- short to transmit.
- @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is
- greater than MTU (or greater than the maximum packet size if
- Token.Packet.TxData.OverrideData.
- DoNotFragment is TRUE).
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Transmit (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_COMPLETION_TOKEN *Token
- )
- {
- IP4_SERVICE *IpSb;
- IP4_PROTOCOL *IpInstance;
- IP4_INTERFACE *IpIf;
- IP4_TXTOKEN_WRAP *Wrap;
- EFI_IP4_TRANSMIT_DATA *TxData;
- EFI_IP4_CONFIG_DATA *Config;
- EFI_IP4_OVERRIDE_DATA *Override;
- IP4_HEAD Head;
- IP4_ADDR GateWay;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- BOOLEAN DontFragment;
- UINT32 HeadLen;
- UINT8 RawHdrLen;
- UINT32 OptionsLength;
- UINT8 *OptionsBuffer;
- VOID *FirstFragment;
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- if (IpInstance->State != IP4_STATE_CONFIGED) {
- return EFI_NOT_STARTED;
- }
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- IpSb = IpInstance->Service;
- IpIf = IpInstance->Interface;
- Config = &IpInstance->ConfigData;
- if (Config->UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {
- Status = EFI_NO_MAPPING;
- goto ON_EXIT;
- }
- //
- // make sure that token is properly formatted
- //
- Status = Ip4TxTokenValid (Token, IpIf, Config->RawData);
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- //
- // Check whether the token or signal already existed.
- //
- if (EFI_ERROR (NetMapIterate (&IpInstance->TxTokens, Ip4TokenExist, Token))) {
- Status = EFI_ACCESS_DENIED;
- goto ON_EXIT;
- }
- //
- // Build the IP header, need to fill in the Tos, TotalLen, Id,
- // fragment, Ttl, protocol, Src, and Dst.
- //
- TxData = Token->Packet.TxData;
- FirstFragment = NULL;
- if (Config->RawData) {
- //
- // When RawData is TRUE, first buffer in FragmentTable points to a raw
- // IPv4 fragment including IPv4 header and options.
- //
- FirstFragment = TxData->FragmentTable[0].FragmentBuffer;
- CopyMem (&RawHdrLen, FirstFragment, sizeof (UINT8));
- RawHdrLen = (UINT8)(RawHdrLen & 0x0f);
- if (RawHdrLen < 5) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
- RawHdrLen = (UINT8)(RawHdrLen << 2);
- CopyMem (&Head, FirstFragment, IP4_MIN_HEADLEN);
- Ip4NtohHead (&Head);
- HeadLen = 0;
- DontFragment = IP4_DO_NOT_FRAGMENT (Head.Fragment);
- if (!DontFragment) {
- Status = EFI_INVALID_PARAMETER;
- goto ON_EXIT;
- }
- GateWay = IP4_ALLZERO_ADDRESS;
- //
- // Get IPv4 options from first fragment.
- //
- if (RawHdrLen == IP4_MIN_HEADLEN) {
- OptionsLength = 0;
- OptionsBuffer = NULL;
- } else {
- OptionsLength = RawHdrLen - IP4_MIN_HEADLEN;
- OptionsBuffer = (UINT8 *)FirstFragment + IP4_MIN_HEADLEN;
- }
- //
- // Trim off IPv4 header and options from first fragment.
- //
- TxData->FragmentTable[0].FragmentBuffer = (UINT8 *)FirstFragment + RawHdrLen;
- TxData->FragmentTable[0].FragmentLength = TxData->FragmentTable[0].FragmentLength - RawHdrLen;
- } else {
- CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR));
- Head.Dst = NTOHL (Head.Dst);
- if (TxData->OverrideData != NULL) {
- Override = TxData->OverrideData;
- Head.Protocol = Override->Protocol;
- Head.Tos = Override->TypeOfService;
- Head.Ttl = Override->TimeToLive;
- DontFragment = Override->DoNotFragment;
- CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR));
- CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR));
- Head.Src = NTOHL (Head.Src);
- GateWay = NTOHL (GateWay);
- } else {
- Head.Src = IpIf->Ip;
- GateWay = IP4_ALLZERO_ADDRESS;
- Head.Protocol = Config->DefaultProtocol;
- Head.Tos = Config->TypeOfService;
- Head.Ttl = Config->TimeToLive;
- DontFragment = Config->DoNotFragment;
- }
- Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0);
- HeadLen = (TxData->OptionsLength + 3) & (~0x03);
- OptionsLength = TxData->OptionsLength;
- OptionsBuffer = (UINT8 *)(TxData->OptionsBuffer);
- }
- //
- // If don't fragment and fragment needed, return error
- //
- if (DontFragment && (TxData->TotalDataLength + HeadLen > IpSb->MaxPacketSize)) {
- Status = EFI_BAD_BUFFER_SIZE;
- goto ON_EXIT;
- }
- //
- // OK, it survives all the validation check. Wrap the token in
- // a IP4_TXTOKEN_WRAP and the data in a netbuf
- //
- Status = EFI_OUT_OF_RESOURCES;
- Wrap = AllocateZeroPool (sizeof (IP4_TXTOKEN_WRAP));
- if (Wrap == NULL) {
- goto ON_EXIT;
- }
- Wrap->IpInstance = IpInstance;
- Wrap->Token = Token;
- Wrap->Sent = FALSE;
- Wrap->Life = IP4_US_TO_SEC (Config->TransmitTimeout);
- Wrap->Packet = NetbufFromExt (
- (NET_FRAGMENT *)TxData->FragmentTable,
- TxData->FragmentCount,
- IP4_MAX_HEADLEN,
- 0,
- Ip4FreeTxToken,
- Wrap
- );
- if (Wrap->Packet == NULL) {
- FreePool (Wrap);
- goto ON_EXIT;
- }
- Token->Status = EFI_NOT_READY;
- if (EFI_ERROR (NetMapInsertTail (&IpInstance->TxTokens, Token, Wrap))) {
- //
- // NetbufFree will call Ip4FreeTxToken, which in turn will
- // free the IP4_TXTOKEN_WRAP. Now, the token wrap hasn't been
- // enqueued.
- //
- if (Config->RawData) {
- //
- // Restore pointer of first fragment in RawData mode.
- //
- TxData->FragmentTable[0].FragmentBuffer = (UINT8 *)FirstFragment;
- }
- NetbufFree (Wrap->Packet);
- goto ON_EXIT;
- }
- //
- // Mark the packet sent before output it. Mark it not sent again if the
- // returned status is not EFI_SUCCESS;
- //
- Wrap->Sent = TRUE;
- Status = Ip4Output (
- IpSb,
- IpInstance,
- Wrap->Packet,
- &Head,
- OptionsBuffer,
- OptionsLength,
- GateWay,
- Ip4OnPacketSent,
- Wrap
- );
- if (EFI_ERROR (Status)) {
- Wrap->Sent = FALSE;
- if (Config->RawData) {
- //
- // Restore pointer of first fragment in RawData mode.
- //
- TxData->FragmentTable[0].FragmentBuffer = (UINT8 *)FirstFragment;
- }
- NetbufFree (Wrap->Packet);
- }
- if (Config->RawData) {
- //
- // Restore pointer of first fragment in RawData mode.
- //
- TxData->FragmentTable[0].FragmentBuffer = (UINT8 *)FirstFragment;
- }
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Places a receiving request into the receiving queue.
- The Receive() function places a completion token into the receive packet queue.
- This function is always asynchronous.
- The Token.Event field in the completion token must be filled in by the caller
- and cannot be NULL. When the receive operation completes, the EFI IPv4 Protocol
- driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event
- is signaled.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] Token Pointer to a token that is associated with the receive data descriptor.
- @retval EFI_SUCCESS The receive completion token was cached.
- @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, RARP, etc.)
- is not finished yet.
- @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
- - This is NULL.
- - Token is NULL.
- - Token.Event is NULL.
- @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system
- resources (usually memory).
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- The EFI IPv4 Protocol instance has been reset to startup defaults.
- EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already
- in the receive queue.
- @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.
- @retval EFI_ICMP_ERROR An ICMP error packet was received.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Receive (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_COMPLETION_TOKEN *Token
- )
- {
- IP4_PROTOCOL *IpInstance;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- //
- // First validate the parameters
- //
- if ((This == NULL) || (Token == NULL) || (Token->Event == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- if (IpInstance->State != IP4_STATE_CONFIGED) {
- Status = EFI_NOT_STARTED;
- goto ON_EXIT;
- }
- //
- // Check whether the toke is already on the receive queue.
- //
- Status = NetMapIterate (&IpInstance->RxTokens, Ip4TokenExist, Token);
- if (EFI_ERROR (Status)) {
- Status = EFI_ACCESS_DENIED;
- goto ON_EXIT;
- }
- //
- // Queue the token then check whether there is pending received packet.
- //
- Status = NetMapInsertTail (&IpInstance->RxTokens, Token, NULL);
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- Status = Ip4InstanceDeliverPacket (IpInstance);
- //
- // Dispatch the DPC queued by the NotifyFunction of this instane's receive
- // event.
- //
- DispatchDpc ();
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Cancel the transmitted but not recycled packet. If a matching
- token is found, it will call Ip4CancelPacket to cancel the
- packet. Ip4CancelPacket will cancel all the fragments of the
- packet. When all the fragments are freed, the IP4_TXTOKEN_WRAP
- will be deleted from the Map, and user's event signalled.
- Because Ip4CancelPacket and other functions are all called in
- line, so, after Ip4CancelPacket returns, the Item has been freed.
- @param[in] Map The IP4 child's transmit queue.
- @param[in] Item The current transmitted packet to test.
- @param[in] Context The user's token to cancel.
- @retval EFI_SUCCESS Continue to check the next Item.
- @retval EFI_ABORTED The user's Token (Token != NULL) is cancelled.
- **/
- EFI_STATUS
- EFIAPI
- Ip4CancelTxTokens (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Context
- )
- {
- EFI_IP4_COMPLETION_TOKEN *Token;
- IP4_TXTOKEN_WRAP *Wrap;
- Token = (EFI_IP4_COMPLETION_TOKEN *)Context;
- //
- // Return EFI_SUCCESS to check the next item in the map if
- // this one doesn't match.
- //
- if ((Token != NULL) && (Token != Item->Key)) {
- return EFI_SUCCESS;
- }
- Wrap = (IP4_TXTOKEN_WRAP *)Item->Value;
- ASSERT (Wrap != NULL);
- //
- // Don't access the Item, Wrap and Token's members after this point.
- // Item and wrap has been freed. And we no longer own the Token.
- //
- Ip4CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);
- //
- // If only one item is to be cancel, return EFI_ABORTED to stop
- // iterating the map any more.
- //
- if (Token != NULL) {
- return EFI_ABORTED;
- }
- return EFI_SUCCESS;
- }
- /**
- Cancel the receive request. This is quiet simple, because
- it is only enqueued in our local receive map.
- @param[in] Map The IP4 child's receive queue.
- @param[in] Item Current receive request to cancel.
- @param[in] Context The user's token to cancel.
- @retval EFI_SUCCESS Continue to check the next receive request on the
- queue.
- @retval EFI_ABORTED The user's token (token != NULL) has been
- cancelled.
- **/
- EFI_STATUS
- EFIAPI
- Ip4CancelRxTokens (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Context
- )
- {
- EFI_IP4_COMPLETION_TOKEN *Token;
- EFI_IP4_COMPLETION_TOKEN *This;
- Token = (EFI_IP4_COMPLETION_TOKEN *)Context;
- This = Item->Key;
- if ((Token != NULL) && (Token != This)) {
- return EFI_SUCCESS;
- }
- NetMapRemoveItem (Map, Item, NULL);
- This->Status = EFI_ABORTED;
- This->Packet.RxData = NULL;
- gBS->SignalEvent (This->Event);
- if (Token != NULL) {
- return EFI_ABORTED;
- }
- return EFI_SUCCESS;
- }
- /**
- Cancel the user's receive/transmit request.
- @param[in] IpInstance The IP4 child.
- @param[in] Token The token to cancel. If NULL, all token will be
- cancelled.
- @retval EFI_SUCCESS The token is cancelled.
- @retval EFI_NOT_FOUND The token isn't found on either the
- transmit/receive queue.
- @retval EFI_DEVICE_ERROR Not all token is cancelled when Token is NULL.
- **/
- EFI_STATUS
- Ip4Cancel (
- IN IP4_PROTOCOL *IpInstance,
- IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL
- )
- {
- EFI_STATUS Status;
- //
- // First check the transmitted packet. Ip4CancelTxTokens returns
- // EFI_ABORTED to mean that the token has been cancelled when
- // token != NULL. So, return EFI_SUCCESS for this condition.
- //
- Status = NetMapIterate (&IpInstance->TxTokens, Ip4CancelTxTokens, Token);
- if (EFI_ERROR (Status)) {
- if ((Token != NULL) && (Status == EFI_ABORTED)) {
- return EFI_SUCCESS;
- }
- return Status;
- }
- //
- // Check the receive queue. Ip4CancelRxTokens also returns EFI_ABORT
- // for Token!=NULL and it is cancelled.
- //
- Status = NetMapIterate (&IpInstance->RxTokens, Ip4CancelRxTokens, Token);
- //
- // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's
- // events.
- //
- DispatchDpc ();
- if (EFI_ERROR (Status)) {
- if ((Token != NULL) && (Status == EFI_ABORTED)) {
- return EFI_SUCCESS;
- }
- return Status;
- }
- //
- // OK, if the Token is found when Token != NULL, the NetMapIterate
- // will return EFI_ABORTED, which has been interrupted as EFI_SUCCESS.
- //
- if (Token != NULL) {
- return EFI_NOT_FOUND;
- }
- //
- // If Token == NULL, cancel all the tokens. return error if no
- // all of them are cancelled.
- //
- if (!NetMapIsEmpty (&IpInstance->TxTokens) ||
- !NetMapIsEmpty (&IpInstance->RxTokens))
- {
- return EFI_DEVICE_ERROR;
- }
- return EFI_SUCCESS;
- }
- /**
- Abort an asynchronous transmit or receive request.
- The Cancel() function is used to abort a pending transmit or receive request.
- If the token is in the transmit or receive request queues, after calling this
- function, Token->Status will be set to EFI_ABORTED and then Token->Event will
- be signaled. If the token is not in one of the queues, which usually means the
- asynchronous operation has completed, this function will not signal the token
- and EFI_NOT_FOUND is returned.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @param[in] Token Pointer to a token that has been issued by
- EFI_IP4_PROTOCOL.Transmit() or
- EFI_IP4_PROTOCOL.Receive(). If NULL, all pending
- tokens are aborted. Type EFI_IP4_COMPLETION_TOKEN is
- defined in EFI_IP4_PROTOCOL.Transmit().
- @retval EFI_SUCCESS The asynchronous I/O request was aborted and
- Token.->Event was signaled. When Token is NULL, all
- pending requests were aborted and their events were signaled.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_NOT_STARTED This instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was
- not found in the transmit or receive queue. It has either completed
- or was not issued by Transmit() and Receive().
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Cancel (
- IN EFI_IP4_PROTOCOL *This,
- IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL
- )
- {
- IP4_PROTOCOL *IpInstance;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- if (IpInstance->State != IP4_STATE_CONFIGED) {
- Status = EFI_NOT_STARTED;
- goto ON_EXIT;
- }
- if (IpInstance->ConfigData.UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {
- Status = EFI_NO_MAPPING;
- goto ON_EXIT;
- }
- Status = Ip4Cancel (IpInstance, Token);
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Polls for incoming data packets and processes outgoing data packets.
- The Poll() function polls for incoming data packets and processes outgoing data
- packets. Network drivers and applications can call the EFI_IP4_PROTOCOL.Poll()
- function to increase the rate that data packets are moved between the communications
- device and the transmit and receive queues.
- In some systems the periodic timer event may not poll the underlying communications
- device fast enough to transmit and/or receive all data packets without missing
- incoming packets or dropping outgoing packets. Drivers and applications that are
- experiencing packet loss should try calling the EFI_IP4_PROTOCOL.Poll() function
- more often.
- @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.
- @retval EFI_SUCCESS Incoming or outgoing data was processed.
- @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,
- RARP, etc.) is not finished yet.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- @retval EFI_NOT_READY No incoming or outgoing data is processed.
- @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.
- Consider increasing the polling rate.
- **/
- EFI_STATUS
- EFIAPI
- EfiIp4Poll (
- IN EFI_IP4_PROTOCOL *This
- )
- {
- IP4_PROTOCOL *IpInstance;
- EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
- if (IpInstance->State == IP4_STATE_UNCONFIGED) {
- return EFI_NOT_STARTED;
- }
- Mnp = IpInstance->Service->Mnp;
- //
- // Don't lock the Poll function to enable the deliver of
- // the packet polled up.
- //
- return Mnp->Poll (Mnp);
- }
- /**
- Decrease the life of the transmitted packets. If it is
- decreased to zero, cancel the packet. This function is
- called by Ip4PacketTimerTicking which time out both the
- received-but-not-delivered and transmitted-but-not-recycle
- packets.
- @param[in] Map The IP4 child's transmit map.
- @param[in] Item Current transmitted packet.
- @param[in] Context Not used.
- @retval EFI_SUCCESS Always returns EFI_SUCCESS.
- **/
- EFI_STATUS
- EFIAPI
- Ip4SentPacketTicking (
- IN NET_MAP *Map,
- IN NET_MAP_ITEM *Item,
- IN VOID *Context
- )
- {
- IP4_TXTOKEN_WRAP *Wrap;
- Wrap = (IP4_TXTOKEN_WRAP *)Item->Value;
- ASSERT (Wrap != NULL);
- if ((Wrap->Life > 0) && (--Wrap->Life == 0)) {
- Ip4CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);
- }
- return EFI_SUCCESS;
- }
- /**
- This heart beat timer of IP4 service instance times out all of its IP4 children's
- received-but-not-delivered and transmitted-but-not-recycle packets, and provides
- time input for its IGMP protocol.
- @param[in] Event The IP4 service instance's heart beat timer.
- @param[in] Context The IP4 service instance.
- **/
- VOID
- EFIAPI
- Ip4TimerTicking (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- IP4_SERVICE *IpSb;
- IpSb = (IP4_SERVICE *)Context;
- NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
- Ip4PacketTimerTicking (IpSb);
- Ip4IgmpTicking (IpSb);
- }
- /**
- This dedicated timer is used to poll underlying network media status. In case
- of cable swap or wireless network switch, a new round auto configuration will
- be initiated. The timer will signal the IP4 to run DHCP configuration again.
- IP4 driver will free old IP address related resource, such as route table and
- Interface, then initiate a DHCP process to acquire new IP, eventually create
- route table for new IP address.
- @param[in] Event The IP4 service instance's heart beat timer.
- @param[in] Context The IP4 service instance.
- **/
- VOID
- EFIAPI
- Ip4TimerReconfigChecking (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- IP4_SERVICE *IpSb;
- BOOLEAN OldMediaPresent;
- EFI_STATUS Status;
- EFI_SIMPLE_NETWORK_MODE SnpModeData;
- IpSb = (IP4_SERVICE *)Context;
- NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
- OldMediaPresent = IpSb->MediaPresent;
- //
- // Get fresh mode data from MNP, since underlying media status may change.
- // Here, it needs to mention that the MediaPresent can also be checked even if
- // EFI_NOT_STARTED returned while this MNP child driver instance isn't configured.
- //
- Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &SnpModeData);
- if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
- return;
- }
- IpSb->MediaPresent = SnpModeData.MediaPresent;
- //
- // Media transimit Unpresent to Present means new link movement is detected.
- //
- if (!OldMediaPresent && IpSb->MediaPresent && (IpSb->Ip4Config2Instance.Policy == Ip4Config2PolicyDhcp)) {
- //
- // Signal the IP4 to run the dhcp configuration again. IP4 driver will free
- // old IP address related resource, such as route table and Interface, then
- // initiate a DHCP round to acquire new IP, eventually
- // create route table for new IP address.
- //
- if (IpSb->ReconfigEvent != NULL) {
- Status = gBS->SignalEvent (IpSb->ReconfigEvent);
- DispatchDpc ();
- }
- }
- }
|