1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789 |
- /** @file
- This file implement the EFI_DHCP4_PROTOCOL interface.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Dhcp4Impl.h"
- /**
- Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.
- The GetModeData() function returns the current operating mode and cached data
- packet for the EFI DHCPv4 Protocol driver.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[out] Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.
- @retval EFI_SUCCESS The mode data was returned.
- @retval EFI_INVALID_PARAMETER This is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4GetModeData (
- IN EFI_DHCP4_PROTOCOL *This,
- OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData
- );
- /**
- Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.
- The Configure() function is used to initialize, change, or reset the operational
- settings of the EFI DHCPv4 Protocol driver for the communication device on which
- the EFI DHCPv4 Service Binding Protocol is installed. This function can be
- successfully called only if both of the following are true:
- * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,
- Dhcp4InitReboot, or Dhcp4Bound states.
- * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI
- DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4
- Protocol driver.
- When this driver is in the Dhcp4Stopped state, it can transfer into one of the
- following two possible initial states:
- * Dhcp4Init
- * Dhcp4InitReboot
- The driver can transfer into these states by calling Configure() with a non-NULL
- Dhcp4CfgData. The driver will transfer into the appropriate state based on the
- supplied client network address in the ClientAddress parameter and DHCP options
- in the OptionList parameter as described in RFC 2131.
- When Configure() is called successfully while Dhcp4CfgData is set to NULL, the
- default configuring data will be reset in the EFI DHCPv4 Protocol driver and
- the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance
- wants to make it possible for another instance to configure the EFI DHCPv4 Protocol
- driver, it must call this function with Dhcp4CfgData set to NULL.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or
- Dhcp4InitReboot state, if the original state of this driver
- was Dhcp4Stopped and the value of Dhcp4CfgData was
- not NULL. Otherwise, the state was left unchanged.
- @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the
- Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;
- Or another instance of this EFI DHCPv4 Protocol driver is already
- in a valid configured state.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Configure (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL
- );
- /**
- Starts the DHCP configuration process.
- The Start() function starts the DHCP configuration process. This function can
- be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or
- Dhcp4InitReboot state.
- If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol
- driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the
- Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.
- If the process aborts, either by the user or by some unexpected network error,
- the state is restored to the Dhcp4Init state. The Start() function can be called
- again to restart the process.
- Refer to RFC 2131 for precise state transitions during this process. At the
- time when each event occurs in this process, the callback function that was set
- by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this
- opportunity to control the process.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] CompletionEvent If not NULL, indicates the event that will be signaled when the
- EFI DHCPv4 Protocol driver is transferred into the
- Dhcp4Bound state or when the DHCP process is aborted.
- EFI_DHCP4_PROTOCOL.GetModeData() can be called to
- check the completion status. If NULL,
- EFI_DHCP4_PROTOCOL.Start() will wait until the driver
- is transferred into the Dhcp4Bound state or the process fails.
- @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed
- when CompletionEvent is NULL.
- @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
- state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_TIMEOUT The DHCP configuration process failed because no response was
- received from the server within the specified timeout value.
- @retval EFI_ABORTED The user aborted the DHCP process.
- @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the
- DHCP process.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Start (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_EVENT CompletionEvent OPTIONAL
- );
- /**
- Extends the lease time by sending a request packet.
- The RenewRebind() function is used to manually extend the lease time when the
- EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has
- not expired yet. This function will send a request packet to the previously
- found server (or to any server when RebindRequest is TRUE) and transfer the
- state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is
- TRUE). When a response is received, the state is returned to Dhcp4Bound.
- If no response is received before the try count is exceeded (the RequestTryCount
- field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that
- was issued by the previous server expires, the driver will return to the Dhcp4Bound
- state and the previous configuration is restored. The outgoing and incoming packets
- can be captured by the EFI_DHCP4_CALLBACK function.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] RebindRequest If TRUE, this function broadcasts the request packets and enters
- the Dhcp4Rebinding state. Otherwise, it sends a unicast
- request packet and enters the Dhcp4Renewing state.
- @param[in] CompletionEvent If not NULL, this event is signaled when the renew/rebind phase
- completes or some error occurs.
- EFI_DHCP4_PROTOCOL.GetModeData() can be called to
- check the completion status. If NULL,
- EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait
- until the DHCP process finishes.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the
- Dhcp4Renewing state or is back to the Dhcp4Bound state.
- @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
- state. EFI_DHCP4_PROTOCOL.Configure() needs to
- be called.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_TIMEOUT There was no response from the server when the try count was
- exceeded.
- @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4RenewRebind (
- IN EFI_DHCP4_PROTOCOL *This,
- IN BOOLEAN RebindRequest,
- IN EFI_EVENT CompletionEvent OPTIONAL
- );
- /**
- Releases the current address configuration.
- The Release() function releases the current configured IP address by doing either
- of the following:
- * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the
- Dhcp4Bound state
- * Setting the previously assigned IP address that was provided with the
- EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in
- Dhcp4InitReboot state
- After a successful call to this function, the EFI DHCPv4 Protocol driver returns
- to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Release (
- IN EFI_DHCP4_PROTOCOL *This
- );
- /**
- Stops the current address configuration.
- The Stop() function is used to stop the DHCP configuration process. After this
- function is called successfully, the EFI DHCPv4 Protocol driver is transferred
- into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called
- before DHCP configuration process can be started again. This function can be
- called when the EFI DHCPv4 Protocol driver is in any state.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.
- @retval EFI_INVALID_PARAMETER This is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Stop (
- IN EFI_DHCP4_PROTOCOL *This
- );
- /**
- Builds a DHCP packet, given the options to be appended or deleted or replaced.
- The Build() function is used to assemble a new packet from the original packet
- by replacing or deleting existing options or appending new options. This function
- does not change any state of the EFI DHCPv4 Protocol driver and can be used at
- any time.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] SeedPacket Initial packet to be used as a base for building new packet.
- @param[in] DeleteCount Number of opcodes in the DeleteList.
- @param[in] DeleteList List of opcodes to be deleted from the seed packet.
- Ignored if DeleteCount is zero.
- @param[in] AppendCount Number of entries in the OptionList.
- @param[in] AppendList Pointer to a DHCP option list to be appended to SeedPacket.
- If SeedPacket also contains options in this list, they are
- replaced by new options (except pad option). Ignored if
- AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION
- @param[out] NewPacket Pointer to storage for the pointer to the new allocated packet.
- Use the EFI Boot Service FreePool() on the resulting pointer
- when done with the packet.
- @retval EFI_SUCCESS The new packet was built.
- @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Build (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_PACKET *SeedPacket,
- IN UINT32 DeleteCount,
- IN UINT8 *DeleteList OPTIONAL,
- IN UINT32 AppendCount,
- IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
- OUT EFI_DHCP4_PACKET **NewPacket
- );
- /**
- Transmits a DHCP formatted packet and optionally waits for responses.
- The TransmitReceive() function is used to transmit a DHCP packet and optionally
- wait for the response from servers. This function does not change the state of
- the EFI DHCPv4 Protocol driver and thus can be used at any time.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.
- @retval EFI_SUCCESS The packet was successfully queued for transmission.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call
- this function after collection process completes.
- @retval EFI_NO_MAPPING The default station address is not available yet.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval Others Some other unexpected error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4TransmitReceive (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token
- );
- /**
- Parses the packed DHCP option data.
- The Parse() function is used to retrieve the option list from a DHCP packet.
- If *OptionCount isn't zero, and there is enough space for all the DHCP options
- in the Packet, each element of PacketOptionList is set to point to somewhere in
- the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,
- the caller should reassemble the parsed DHCP options to get the finial result.
- If *OptionCount is zero or there isn't enough space for all of them, the number
- of DHCP options in the Packet is returned in OptionCount.
- @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param Packet Pointer to packet to be parsed.
- @param OptionCount On input, the number of entries in the PacketOptionList.
- On output, the number of entries that were written into the
- PacketOptionList.
- @param PacketOptionList List of packet option entries to be filled in. End option or pad
- options are not included.
- @retval EFI_SUCCESS The packet was successfully parsed.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:
- 1) *OptionCount is smaller than the number of options that
- were found in the Packet.
- 2) PacketOptionList is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Parse (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_PACKET *Packet,
- IN OUT UINT32 *OptionCount,
- OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL
- );
- EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {
- EfiDhcp4GetModeData,
- EfiDhcp4Configure,
- EfiDhcp4Start,
- EfiDhcp4RenewRebind,
- EfiDhcp4Release,
- EfiDhcp4Stop,
- EfiDhcp4Build,
- EfiDhcp4TransmitReceive,
- EfiDhcp4Parse
- };
- /**
- Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.
- The GetModeData() function returns the current operating mode and cached data
- packet for the EFI DHCPv4 Protocol driver.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[out] Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.
- @retval EFI_SUCCESS The mode data was returned.
- @retval EFI_INVALID_PARAMETER This is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4GetModeData (
- IN EFI_DHCP4_PROTOCOL *This,
- OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData
- )
- {
- DHCP_PROTOCOL *Instance;
- DHCP_SERVICE *DhcpSb;
- DHCP_PARAMETER *Para;
- EFI_TPL OldTpl;
- IP4_ADDR Ip;
- //
- // First validate the parameters.
- //
- if ((This == NULL) || (Dhcp4ModeData == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- Instance = DHCP_INSTANCE_FROM_THIS (This);
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- DhcpSb = Instance->Service;
- //
- // Caller can use GetModeData to retrieve current DHCP states
- // no matter whether it is the active child or not.
- //
- Dhcp4ModeData->State = (EFI_DHCP4_STATE)DhcpSb->DhcpState;
- CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (Dhcp4ModeData->ConfigData));
- CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (Dhcp4ModeData->ClientMacAddress));
- Ip = HTONL (DhcpSb->ClientAddr);
- CopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
- Ip = HTONL (DhcpSb->Netmask);
- CopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
- Ip = HTONL (DhcpSb->ServerAddr);
- CopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
- Para = DhcpSb->Para;
- if (Para != NULL) {
- Ip = HTONL (Para->Router);
- CopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
- Dhcp4ModeData->LeaseTime = Para->Lease;
- } else {
- ZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));
- Dhcp4ModeData->LeaseTime = 0xffffffff;
- }
- Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;
- gBS->RestoreTPL (OldTpl);
- return EFI_SUCCESS;
- }
- /**
- Free the resource related to the configure parameters.
- DHCP driver will make a copy of the user's configure
- such as the time out value.
- @param Config The DHCP configure data
- **/
- VOID
- DhcpCleanConfigure (
- IN OUT EFI_DHCP4_CONFIG_DATA *Config
- )
- {
- UINT32 Index;
- if (Config->DiscoverTimeout != NULL) {
- FreePool (Config->DiscoverTimeout);
- }
- if (Config->RequestTimeout != NULL) {
- FreePool (Config->RequestTimeout);
- }
- if (Config->OptionList != NULL) {
- for (Index = 0; Index < Config->OptionCount; Index++) {
- if (Config->OptionList[Index] != NULL) {
- FreePool (Config->OptionList[Index]);
- }
- }
- FreePool (Config->OptionList);
- }
- ZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));
- }
- /**
- Allocate memory for configure parameter such as timeout value for Dst,
- then copy the configure parameter from Src to Dst.
- @param[out] Dst The destination DHCP configure data.
- @param[in] Src The source DHCP configure data.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval EFI_SUCCESS The configure is copied.
- **/
- EFI_STATUS
- DhcpCopyConfigure (
- OUT EFI_DHCP4_CONFIG_DATA *Dst,
- IN EFI_DHCP4_CONFIG_DATA *Src
- )
- {
- EFI_DHCP4_PACKET_OPTION **DstOptions;
- EFI_DHCP4_PACKET_OPTION **SrcOptions;
- UINTN Len;
- UINT32 Index;
- CopyMem (Dst, Src, sizeof (*Dst));
- Dst->DiscoverTimeout = NULL;
- Dst->RequestTimeout = NULL;
- Dst->OptionList = NULL;
- //
- // Allocate a memory then copy DiscoverTimeout to it
- //
- if (Src->DiscoverTimeout != NULL) {
- Len = Src->DiscoverTryCount * sizeof (UINT32);
- Dst->DiscoverTimeout = AllocatePool (Len);
- if (Dst->DiscoverTimeout == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- for (Index = 0; Index < Src->DiscoverTryCount; Index++) {
- Dst->DiscoverTimeout[Index] = MAX (Src->DiscoverTimeout[Index], 1);
- }
- }
- //
- // Allocate a memory then copy RequestTimeout to it
- //
- if (Src->RequestTimeout != NULL) {
- Len = Src->RequestTryCount * sizeof (UINT32);
- Dst->RequestTimeout = AllocatePool (Len);
- if (Dst->RequestTimeout == NULL) {
- goto ON_ERROR;
- }
- for (Index = 0; Index < Src->RequestTryCount; Index++) {
- Dst->RequestTimeout[Index] = MAX (Src->RequestTimeout[Index], 1);
- }
- }
- //
- // Allocate an array of dhcp option point, then allocate memory
- // for each option and copy the source option to it
- //
- if (Src->OptionList != NULL) {
- Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);
- Dst->OptionList = AllocateZeroPool (Len);
- if (Dst->OptionList == NULL) {
- goto ON_ERROR;
- }
- DstOptions = Dst->OptionList;
- SrcOptions = Src->OptionList;
- for (Index = 0; Index < Src->OptionCount; Index++) {
- Len = sizeof (EFI_DHCP4_PACKET_OPTION) + MAX (SrcOptions[Index]->Length - 1, 0);
- DstOptions[Index] = AllocatePool (Len);
- if (DstOptions[Index] == NULL) {
- goto ON_ERROR;
- }
- CopyMem (DstOptions[Index], SrcOptions[Index], Len);
- }
- }
- return EFI_SUCCESS;
- ON_ERROR:
- DhcpCleanConfigure (Dst);
- return EFI_OUT_OF_RESOURCES;
- }
- /**
- Give up the control of the DHCP service to let other child
- resume. Don't change the service's DHCP state and the Client
- address and option list configure as required by RFC2131.
- @param DhcpSb The DHCP service instance.
- **/
- VOID
- DhcpYieldControl (
- IN DHCP_SERVICE *DhcpSb
- )
- {
- EFI_DHCP4_CONFIG_DATA *Config;
- Config = &DhcpSb->ActiveConfig;
- DhcpSb->ServiceState = DHCP_UNCONFIGED;
- DhcpSb->ActiveChild = NULL;
- if (Config->DiscoverTimeout != NULL) {
- FreePool (Config->DiscoverTimeout);
- Config->DiscoverTryCount = 0;
- Config->DiscoverTimeout = NULL;
- }
- if (Config->RequestTimeout != NULL) {
- FreePool (Config->RequestTimeout);
- Config->RequestTryCount = 0;
- Config->RequestTimeout = NULL;
- }
- Config->Dhcp4Callback = NULL;
- Config->CallbackContext = NULL;
- }
- /**
- Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.
- The Configure() function is used to initialize, change, or reset the operational
- settings of the EFI DHCPv4 Protocol driver for the communication device on which
- the EFI DHCPv4 Service Binding Protocol is installed. This function can be
- successfully called only if both of the following are true:
- * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,
- Dhcp4InitReboot, or Dhcp4Bound states.
- * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI
- DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4
- Protocol driver.
- When this driver is in the Dhcp4Stopped state, it can transfer into one of the
- following two possible initial states:
- * Dhcp4Init
- * Dhcp4InitReboot
- The driver can transfer into these states by calling Configure() with a non-NULL
- Dhcp4CfgData. The driver will transfer into the appropriate state based on the
- supplied client network address in the ClientAddress parameter and DHCP options
- in the OptionList parameter as described in RFC 2131.
- When Configure() is called successfully while Dhcp4CfgData is set to NULL, the
- default configuring data will be reset in the EFI DHCPv4 Protocol driver and
- the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance
- wants to make it possible for another instance to configure the EFI DHCPv4 Protocol
- driver, it must call this function with Dhcp4CfgData set to NULL.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or
- Dhcp4InitReboot state, if the original state of this driver
- was Dhcp4Stopped and the value of Dhcp4CfgData was
- not NULL. Otherwise, the state was left unchanged.
- @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the
- Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;
- Or another instance of this EFI DHCPv4 Protocol driver is already
- in a valid configured state.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Configure (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL
- )
- {
- EFI_DHCP4_CONFIG_DATA *Config;
- DHCP_PROTOCOL *Instance;
- DHCP_SERVICE *DhcpSb;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- UINT32 Index;
- IP4_ADDR Ip;
- //
- // First validate the parameters
- //
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- if (Dhcp4CfgData != NULL) {
- if ((Dhcp4CfgData->DiscoverTryCount != 0) && (Dhcp4CfgData->DiscoverTimeout == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((Dhcp4CfgData->RequestTryCount != 0) && (Dhcp4CfgData->RequestTimeout == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((Dhcp4CfgData->OptionCount != 0) && (Dhcp4CfgData->OptionList == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- CopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));
- if (IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
- return EFI_INVALID_PARAMETER;
- }
- }
- Instance = DHCP_INSTANCE_FROM_THIS (This);
- if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- DhcpSb = Instance->Service;
- Config = &DhcpSb->ActiveConfig;
- Status = EFI_ACCESS_DENIED;
- if ((DhcpSb->DhcpState != Dhcp4Stopped) &&
- (DhcpSb->DhcpState != Dhcp4Init) &&
- (DhcpSb->DhcpState != Dhcp4InitReboot) &&
- (DhcpSb->DhcpState != Dhcp4Bound))
- {
- goto ON_EXIT;
- }
- if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {
- goto ON_EXIT;
- }
- if (Dhcp4CfgData != NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- DhcpCleanConfigure (Config);
- if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {
- goto ON_EXIT;
- }
- DhcpSb->UserOptionLen = 0;
- for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {
- DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;
- }
- DhcpSb->ActiveChild = Instance;
- if (DhcpSb->DhcpState == Dhcp4Stopped) {
- DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);
- if (DhcpSb->ClientAddr != 0) {
- DhcpSb->DhcpState = Dhcp4InitReboot;
- } else {
- DhcpSb->DhcpState = Dhcp4Init;
- }
- }
- DhcpSb->ServiceState = DHCP_CONFIGED;
- Status = EFI_SUCCESS;
- } else if (DhcpSb->ActiveChild == Instance) {
- Status = EFI_SUCCESS;
- DhcpYieldControl (DhcpSb);
- }
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Starts the DHCP configuration process.
- The Start() function starts the DHCP configuration process. This function can
- be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or
- Dhcp4InitReboot state.
- If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol
- driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the
- Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.
- If the process aborts, either by the user or by some unexpected network error,
- the state is restored to the Dhcp4Init state. The Start() function can be called
- again to restart the process.
- Refer to RFC 2131 for precise state transitions during this process. At the
- time when each event occurs in this process, the callback function that was set
- by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this
- opportunity to control the process.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] CompletionEvent If not NULL, indicates the event that will be signaled when the
- EFI DHCPv4 Protocol driver is transferred into the
- Dhcp4Bound state or when the DHCP process is aborted.
- EFI_DHCP4_PROTOCOL.GetModeData() can be called to
- check the completion status. If NULL,
- EFI_DHCP4_PROTOCOL.Start() will wait until the driver
- is transferred into the Dhcp4Bound state or the process fails.
- @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed
- when CompletionEvent is NULL.
- @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
- state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval EFI_TIMEOUT The DHCP configuration process failed because no response was
- received from the server within the specified timeout value.
- @retval EFI_ABORTED The user aborted the DHCP process.
- @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the
- DHCP process.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- @retval EFI_NO_MEDIA There was a media error.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Start (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_EVENT CompletionEvent OPTIONAL
- )
- {
- DHCP_PROTOCOL *Instance;
- DHCP_SERVICE *DhcpSb;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- EFI_STATUS MediaStatus;
- //
- // First validate the parameters
- //
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- Instance = DHCP_INSTANCE_FROM_THIS (This);
- if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- DhcpSb = Instance->Service;
- if (DhcpSb->DhcpState == Dhcp4Stopped) {
- Status = EFI_NOT_STARTED;
- goto ON_ERROR;
- }
- if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {
- Status = EFI_ALREADY_STARTED;
- goto ON_ERROR;
- }
- //
- // Check Media Status.
- //
- MediaStatus = EFI_SUCCESS;
- NetLibDetectMediaWaitTimeout (DhcpSb->Controller, DHCP_CHECK_MEDIA_WAITING_TIME, &MediaStatus);
- if (MediaStatus != EFI_SUCCESS) {
- Status = EFI_NO_MEDIA;
- goto ON_ERROR;
- }
- DhcpSb->IoStatus = EFI_ALREADY_STARTED;
- if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {
- goto ON_ERROR;
- }
- Instance->CompletionEvent = CompletionEvent;
- //
- // Restore the TPL now, don't call poll function at TPL_CALLBACK.
- //
- gBS->RestoreTPL (OldTpl);
- if (CompletionEvent == NULL) {
- while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
- DhcpSb->UdpIo->Protocol.Udp4->Poll (DhcpSb->UdpIo->Protocol.Udp4);
- }
- return DhcpSb->IoStatus;
- }
- return EFI_SUCCESS;
- ON_ERROR:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Extends the lease time by sending a request packet.
- The RenewRebind() function is used to manually extend the lease time when the
- EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has
- not expired yet. This function will send a request packet to the previously
- found server (or to any server when RebindRequest is TRUE) and transfer the
- state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is
- TRUE). When a response is received, the state is returned to Dhcp4Bound.
- If no response is received before the try count is exceeded (the RequestTryCount
- field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that
- was issued by the previous server expires, the driver will return to the Dhcp4Bound
- state and the previous configuration is restored. The outgoing and incoming packets
- can be captured by the EFI_DHCP4_CALLBACK function.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] RebindRequest If TRUE, this function broadcasts the request packets and enters
- the Dhcp4Rebinding state. Otherwise, it sends a unicast
- request packet and enters the Dhcp4Renewing state.
- @param[in] CompletionEvent If not NULL, this event is signaled when the renew/rebind phase
- completes or some error occurs.
- EFI_DHCP4_PROTOCOL.GetModeData() can be called to
- check the completion status. If NULL,
- EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait
- until the DHCP process finishes.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the
- Dhcp4Renewing state or is back to the Dhcp4Bound state.
- @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
- state. EFI_DHCP4_PROTOCOL.Configure() needs to
- be called.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_TIMEOUT There was no response from the server when the try count was
- exceeded.
- @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4RenewRebind (
- IN EFI_DHCP4_PROTOCOL *This,
- IN BOOLEAN RebindRequest,
- IN EFI_EVENT CompletionEvent OPTIONAL
- )
- {
- DHCP_PROTOCOL *Instance;
- DHCP_SERVICE *DhcpSb;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- //
- // First validate the parameters
- //
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- Instance = DHCP_INSTANCE_FROM_THIS (This);
- if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- DhcpSb = Instance->Service;
- if (DhcpSb->DhcpState == Dhcp4Stopped) {
- Status = EFI_NOT_STARTED;
- goto ON_EXIT;
- }
- if (DhcpSb->DhcpState != Dhcp4Bound) {
- Status = EFI_ACCESS_DENIED;
- goto ON_EXIT;
- }
- if (DHCP_IS_BOOTP (DhcpSb->Para)) {
- Status = EFI_SUCCESS;
- goto ON_EXIT;
- }
- //
- // Transit the states then send a extra DHCP request
- //
- if (!RebindRequest) {
- DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);
- } else {
- DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);
- }
- //
- // Clear initial time to make sure that elapsed-time
- // is set to 0 for first REQUEST in renewal process.
- //
- Instance->ElaspedTime = 0;
- Status = DhcpSendMessage (
- DhcpSb,
- DhcpSb->Selected,
- DhcpSb->Para,
- DHCP_MSG_REQUEST,
- (UINT8 *)"Extra renew/rebind by the application"
- );
- if (EFI_ERROR (Status)) {
- DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);
- goto ON_EXIT;
- }
- DhcpSb->ExtraRefresh = TRUE;
- DhcpSb->IoStatus = EFI_ALREADY_STARTED;
- Instance->RenewRebindEvent = CompletionEvent;
- gBS->RestoreTPL (OldTpl);
- if (CompletionEvent == NULL) {
- while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
- DhcpSb->UdpIo->Protocol.Udp4->Poll (DhcpSb->UdpIo->Protocol.Udp4);
- }
- return DhcpSb->IoStatus;
- }
- return EFI_SUCCESS;
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Releases the current address configuration.
- The Release() function releases the current configured IP address by doing either
- of the following:
- * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the
- Dhcp4Bound state
- * Setting the previously assigned IP address that was provided with the
- EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in
- Dhcp4InitReboot state
- After a successful call to this function, the EFI DHCPv4 Protocol driver returns
- to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.
- @retval EFI_INVALID_PARAMETER This is NULL.
- @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.
- @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Release (
- IN EFI_DHCP4_PROTOCOL *This
- )
- {
- DHCP_PROTOCOL *Instance;
- DHCP_SERVICE *DhcpSb;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- //
- // First validate the parameters
- //
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- Instance = DHCP_INSTANCE_FROM_THIS (This);
- if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
- Status = EFI_SUCCESS;
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- DhcpSb = Instance->Service;
- if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {
- Status = EFI_ACCESS_DENIED;
- goto ON_EXIT;
- }
- if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {
- Status = DhcpSendMessage (
- DhcpSb,
- DhcpSb->Selected,
- DhcpSb->Para,
- DHCP_MSG_RELEASE,
- NULL
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto ON_EXIT;
- }
- }
- DhcpCleanLease (DhcpSb);
- ON_EXIT:
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Stops the current address configuration.
- The Stop() function is used to stop the DHCP configuration process. After this
- function is called successfully, the EFI DHCPv4 Protocol driver is transferred
- into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called
- before DHCP configuration process can be started again. This function can be
- called when the EFI DHCPv4 Protocol driver is in any state.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.
- @retval EFI_INVALID_PARAMETER This is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Stop (
- IN EFI_DHCP4_PROTOCOL *This
- )
- {
- DHCP_PROTOCOL *Instance;
- DHCP_SERVICE *DhcpSb;
- EFI_TPL OldTpl;
- //
- // First validate the parameters
- //
- if (This == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- Instance = DHCP_INSTANCE_FROM_THIS (This);
- if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- DhcpSb = Instance->Service;
- DhcpCleanLease (DhcpSb);
- DhcpSb->DhcpState = Dhcp4Stopped;
- DhcpSb->ServiceState = DHCP_UNCONFIGED;
- gBS->RestoreTPL (OldTpl);
- return EFI_SUCCESS;
- }
- /**
- Builds a DHCP packet, given the options to be appended or deleted or replaced.
- The Build() function is used to assemble a new packet from the original packet
- by replacing or deleting existing options or appending new options. This function
- does not change any state of the EFI DHCPv4 Protocol driver and can be used at
- any time.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] SeedPacket Initial packet to be used as a base for building new packet.
- @param[in] DeleteCount Number of opcodes in the DeleteList.
- @param[in] DeleteList List of opcodes to be deleted from the seed packet.
- Ignored if DeleteCount is zero.
- @param[in] AppendCount Number of entries in the OptionList.
- @param[in] AppendList Pointer to a DHCP option list to be appended to SeedPacket.
- If SeedPacket also contains options in this list, they are
- replaced by new options (except pad option). Ignored if
- AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION
- @param[out] NewPacket Pointer to storage for the pointer to the new allocated packet.
- Use the EFI Boot Service FreePool() on the resulting pointer
- when done with the packet.
- @retval EFI_SUCCESS The new packet was built.
- @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Build (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_PACKET *SeedPacket,
- IN UINT32 DeleteCount,
- IN UINT8 *DeleteList OPTIONAL,
- IN UINT32 AppendCount,
- IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
- OUT EFI_DHCP4_PACKET **NewPacket
- )
- {
- //
- // First validate the parameters
- //
- if ((This == NULL) || (NewPacket == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
- EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL)))
- {
- return EFI_INVALID_PARAMETER;
- }
- if (((DeleteCount == 0) && (AppendCount == 0)) ||
- ((DeleteCount != 0) && (DeleteList == NULL)) ||
- ((AppendCount != 0) && (AppendList == NULL)))
- {
- return EFI_INVALID_PARAMETER;
- }
- return DhcpBuild (
- SeedPacket,
- DeleteCount,
- DeleteList,
- AppendCount,
- AppendList,
- NewPacket
- );
- }
- /**
- Callback by UdpIoCreatePort() when creating UdpIo for this Dhcp4 instance.
- @param[in] UdpIo The UdpIo being created.
- @param[in] Context Dhcp4 instance.
- @retval EFI_SUCCESS UdpIo is configured successfully.
- @retval EFI_INVALID_PARAMETER Class E IP address is not supported or other parameters
- are not valid.
- @retval other Other error occurs.
- **/
- EFI_STATUS
- EFIAPI
- Dhcp4InstanceConfigUdpIo (
- IN UDP_IO *UdpIo,
- IN VOID *Context
- )
- {
- DHCP_PROTOCOL *Instance;
- DHCP_SERVICE *DhcpSb;
- EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
- EFI_UDP4_CONFIG_DATA UdpConfigData;
- IP4_ADDR ClientAddr;
- IP4_ADDR Ip;
- INTN Class;
- IP4_ADDR SubnetMask;
- Instance = (DHCP_PROTOCOL *)Context;
- DhcpSb = Instance->Service;
- Token = Instance->Token;
- ZeroMem (&UdpConfigData, sizeof (EFI_UDP4_CONFIG_DATA));
- UdpConfigData.AcceptBroadcast = TRUE;
- UdpConfigData.AllowDuplicatePort = TRUE;
- UdpConfigData.TimeToLive = 64;
- UdpConfigData.DoNotFragment = TRUE;
- ClientAddr = EFI_NTOHL (Token->Packet->Dhcp4.Header.ClientAddr);
- Ip = HTONL (ClientAddr);
- CopyMem (&UdpConfigData.StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
- if (DhcpSb->Netmask == 0) {
- //
- // The Dhcp4.TransmitReceive() API should be able to used at any time according to
- // UEFI spec, while in classless addressing network, the netmask must be explicitly
- // provided together with the station address.
- // If the DHCP instance haven't be configured with a valid netmask, we could only
- // compute it according to the classful addressing rule.
- //
- Class = NetGetIpClass (ClientAddr);
- //
- // Class E IP address is not supported here!
- //
- ASSERT (Class < IP4_ADDR_CLASSE);
- if (Class >= IP4_ADDR_CLASSE) {
- return EFI_INVALID_PARAMETER;
- }
- SubnetMask = gIp4AllMasks[Class << 3];
- } else {
- SubnetMask = DhcpSb->Netmask;
- }
- Ip = HTONL (SubnetMask);
- CopyMem (&UdpConfigData.SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
- if ((Token->ListenPointCount == 0) || (Token->ListenPoints[0].ListenPort == 0)) {
- UdpConfigData.StationPort = DHCP_CLIENT_PORT;
- } else {
- UdpConfigData.StationPort = Token->ListenPoints[0].ListenPort;
- }
- return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);
- }
- /**
- Create UdpIo for this Dhcp4 instance.
- @param Instance The Dhcp4 instance.
- @retval EFI_SUCCESS UdpIo is created successfully.
- @retval EFI_OUT_OF_RESOURCES Fails to create UdpIo because of limited
- resources or configuration failure.
- **/
- EFI_STATUS
- Dhcp4InstanceCreateUdpIo (
- IN OUT DHCP_PROTOCOL *Instance
- )
- {
- DHCP_SERVICE *DhcpSb;
- EFI_STATUS Status;
- VOID *Udp4;
- ASSERT (Instance->Token != NULL);
- DhcpSb = Instance->Service;
- Instance->UdpIo = UdpIoCreateIo (
- DhcpSb->Controller,
- DhcpSb->Image,
- Dhcp4InstanceConfigUdpIo,
- UDP_IO_UDP4_VERSION,
- Instance
- );
- if (Instance->UdpIo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- } else {
- Status = gBS->OpenProtocol (
- Instance->UdpIo->UdpHandle,
- &gEfiUdp4ProtocolGuid,
- (VOID **)&Udp4,
- Instance->Service->Image,
- Instance->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- if (EFI_ERROR (Status)) {
- UdpIoFreeIo (Instance->UdpIo);
- Instance->UdpIo = NULL;
- }
- return Status;
- }
- }
- /**
- Callback of Dhcp packet. Does nothing.
- @param Arg The context.
- **/
- VOID
- EFIAPI
- DhcpDummyExtFree (
- IN VOID *Arg
- )
- {
- }
- /**
- Callback of UdpIoRecvDatagram() that handles a Dhcp4 packet.
- Only BOOTP responses will be handled that correspond to the Xid of the request
- sent out. The packet will be queued to the response queue.
- @param UdpPacket The Dhcp4 packet.
- @param EndPoint Udp4 address pair.
- @param IoStatus Status of the input.
- @param Context Extra info for the input.
- **/
- VOID
- EFIAPI
- PxeDhcpInput (
- NET_BUF *UdpPacket,
- UDP_END_POINT *EndPoint,
- EFI_STATUS IoStatus,
- VOID *Context
- )
- {
- DHCP_PROTOCOL *Instance;
- EFI_DHCP4_HEADER *Head;
- NET_BUF *Wrap;
- EFI_DHCP4_PACKET *Packet;
- EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
- UINT32 Len;
- EFI_STATUS Status;
- Wrap = NULL;
- Instance = (DHCP_PROTOCOL *)Context;
- Token = Instance->Token;
- //
- // Don't restart receive if error occurs or DHCP is destroyed.
- //
- if (EFI_ERROR (IoStatus)) {
- return;
- }
- ASSERT (UdpPacket != NULL);
- //
- // Validate the packet received
- //
- if (UdpPacket->TotalSize < sizeof (EFI_DHCP4_HEADER)) {
- goto RESTART;
- }
- //
- // Copy the DHCP message to a continuous memory block, make the buffer size
- // of the EFI_DHCP4_PACKET a multiple of 4-byte.
- //
- Len = NET_ROUNDUP (sizeof (EFI_DHCP4_PACKET) + UdpPacket->TotalSize - sizeof (EFI_DHCP4_HEADER), 4);
- Wrap = NetbufAlloc (Len);
- if (Wrap == NULL) {
- goto RESTART;
- }
- Packet = (EFI_DHCP4_PACKET *)NetbufAllocSpace (Wrap, Len, NET_BUF_TAIL);
- ASSERT (Packet != NULL);
- Packet->Size = Len;
- Head = &Packet->Dhcp4.Header;
- Packet->Length = NetbufCopy (UdpPacket, 0, UdpPacket->TotalSize, (UINT8 *)Head);
- if (Packet->Length != UdpPacket->TotalSize) {
- goto RESTART;
- }
- //
- // Is this packet the answer to our packet?
- //
- if ((Head->OpCode != BOOTP_REPLY) ||
- (Head->Xid != Token->Packet->Dhcp4.Header.Xid) ||
- (CompareMem (&Token->Packet->Dhcp4.Header.ClientHwAddr[0], Head->ClientHwAddr, Head->HwAddrLen) != 0))
- {
- goto RESTART;
- }
- //
- // Validate the options and retrieve the interested options
- //
- if ((Packet->Length > sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)) &&
- (Packet->Dhcp4.Magik == DHCP_OPTION_MAGIC) &&
- EFI_ERROR (DhcpValidateOptions (Packet, NULL)))
- {
- goto RESTART;
- }
- //
- // Keep this packet in the ResponseQueue.
- //
- NET_GET_REF (Wrap);
- NetbufQueAppend (&Instance->ResponseQueue, Wrap);
- RESTART:
- NetbufFree (UdpPacket);
- if (Wrap != NULL) {
- NetbufFree (Wrap);
- }
- Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);
- if (EFI_ERROR (Status)) {
- PxeDhcpDone (Instance);
- }
- }
- /**
- Complete a Dhcp4 transaction and signal the upper layer.
- @param Instance Dhcp4 instance.
- **/
- VOID
- PxeDhcpDone (
- IN DHCP_PROTOCOL *Instance
- )
- {
- EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
- Token = Instance->Token;
- Token->ResponseCount = Instance->ResponseQueue.BufNum;
- if (Token->ResponseCount != 0) {
- Token->ResponseList = (EFI_DHCP4_PACKET *)AllocatePool (Instance->ResponseQueue.BufSize);
- if (Token->ResponseList == NULL) {
- Token->Status = EFI_OUT_OF_RESOURCES;
- goto SIGNAL_USER;
- }
- //
- // Copy the received DHCP responses.
- //
- NetbufQueCopy (&Instance->ResponseQueue, 0, Instance->ResponseQueue.BufSize, (UINT8 *)Token->ResponseList);
- Token->Status = EFI_SUCCESS;
- } else {
- Token->ResponseList = NULL;
- Token->Status = EFI_TIMEOUT;
- }
- SIGNAL_USER:
- //
- // Clean up the resources dedicated for this transmit receive transaction.
- //
- NetbufQueFlush (&Instance->ResponseQueue);
- UdpIoCleanIo (Instance->UdpIo);
- gBS->CloseProtocol (
- Instance->UdpIo->UdpHandle,
- &gEfiUdp4ProtocolGuid,
- Instance->Service->Image,
- Instance->Handle
- );
- UdpIoFreeIo (Instance->UdpIo);
- Instance->UdpIo = NULL;
- Instance->Token = NULL;
- if (Token->CompletionEvent != NULL) {
- gBS->SignalEvent (Token->CompletionEvent);
- }
- }
- /**
- Transmits a DHCP formatted packet and optionally waits for responses.
- The TransmitReceive() function is used to transmit a DHCP packet and optionally
- wait for the response from servers. This function does not change the state of
- the EFI DHCPv4 Protocol driver and thus can be used at any time.
- @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param[in] Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.
- @retval EFI_SUCCESS The packet was successfully queued for transmission.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call
- this function after collection process completes.
- @retval EFI_NO_MAPPING The default station address is not available yet.
- @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
- @retval Others Some other unexpected error occurred.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4TransmitReceive (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token
- )
- {
- DHCP_PROTOCOL *Instance;
- EFI_TPL OldTpl;
- EFI_STATUS Status;
- NET_FRAGMENT Frag;
- NET_BUF *Wrap;
- UDP_END_POINT EndPoint;
- IP4_ADDR Ip;
- DHCP_SERVICE *DhcpSb;
- EFI_IP_ADDRESS Gateway;
- IP4_ADDR ClientAddr;
- if ((This == NULL) || (Token == NULL) || (Token->Packet == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- Instance = DHCP_INSTANCE_FROM_THIS (This);
- DhcpSb = Instance->Service;
- if (Instance->Token != NULL) {
- //
- // The previous call to TransmitReceive is not finished.
- //
- return EFI_NOT_READY;
- }
- if ((Token->Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
- (NTOHL (Token->Packet->Dhcp4.Header.Xid) == Instance->Service->Xid) ||
- (Token->TimeoutValue == 0) ||
- ((Token->ListenPointCount != 0) && (Token->ListenPoints == NULL)) ||
- EFI_ERROR (DhcpValidateOptions (Token->Packet, NULL)) ||
- EFI_IP4_EQUAL (&Token->RemoteAddress, &mZeroIp4Addr)
- )
- {
- //
- // The DHCP packet isn't well-formed, the Transaction ID is already used,
- // the timeout value is zero, the ListenPoint is invalid, or the
- // RemoteAddress is zero.
- //
- return EFI_INVALID_PARAMETER;
- }
- ClientAddr = EFI_NTOHL (Token->Packet->Dhcp4.Header.ClientAddr);
- if (ClientAddr == 0) {
- return EFI_NO_MAPPING;
- }
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- //
- // Save the token and the timeout value.
- //
- Instance->Token = Token;
- Instance->Timeout = Token->TimeoutValue;
- //
- // Create a UDP IO for this transmit receive transaction.
- //
- Status = Dhcp4InstanceCreateUdpIo (Instance);
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Save the Client Address is sent out
- //
- CopyMem (
- &DhcpSb->ClientAddressSendOut[0],
- &Token->Packet->Dhcp4.Header.ClientHwAddr[0],
- Token->Packet->Dhcp4.Header.HwAddrLen
- );
- //
- // Wrap the DHCP packet into a net buffer.
- //
- Frag.Bulk = (UINT8 *)&Token->Packet->Dhcp4;
- Frag.Len = Token->Packet->Length;
- Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL);
- if (Wrap == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_ERROR;
- }
- //
- // Set the local address and local port to ZERO.
- //
- ZeroMem (&EndPoint, sizeof (UDP_END_POINT));
- //
- // Set the destination address and destination port.
- //
- CopyMem (&Ip, &Token->RemoteAddress, sizeof (EFI_IPv4_ADDRESS));
- EndPoint.RemoteAddr.Addr[0] = NTOHL (Ip);
- if (Token->RemotePort == 0) {
- EndPoint.RemotePort = DHCP_SERVER_PORT;
- } else {
- EndPoint.RemotePort = Token->RemotePort;
- }
- //
- // Get the gateway.
- //
- ZeroMem (&Gateway, sizeof (Gateway));
- if (!IP4_NET_EQUAL (ClientAddr, EndPoint.RemoteAddr.Addr[0], DhcpSb->Netmask)) {
- CopyMem (&Gateway.v4, &Token->GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
- Gateway.Addr[0] = NTOHL (Gateway.Addr[0]);
- }
- //
- // Transmit the DHCP packet.
- //
- Status = UdpIoSendDatagram (Instance->UdpIo, Wrap, &EndPoint, &Gateway, DhcpOnPacketSent, NULL);
- if (EFI_ERROR (Status)) {
- NetbufFree (Wrap);
- goto ON_ERROR;
- }
- //
- // Start to receive the DHCP response.
- //
- Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- ON_ERROR:
- if (EFI_ERROR (Status) && (Instance->UdpIo != NULL)) {
- UdpIoCleanIo (Instance->UdpIo);
- gBS->CloseProtocol (
- Instance->UdpIo->UdpHandle,
- &gEfiUdp4ProtocolGuid,
- Instance->Service->Image,
- Instance->Handle
- );
- UdpIoFreeIo (Instance->UdpIo);
- Instance->UdpIo = NULL;
- Instance->Token = NULL;
- }
- gBS->RestoreTPL (OldTpl);
- if (!EFI_ERROR (Status) && (Token->CompletionEvent == NULL)) {
- //
- // Keep polling until timeout if no error happens and the CompletionEvent
- // is NULL.
- //
- while (TRUE) {
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- //
- // Raise TPL to protect the UDPIO in instance, in case that DhcpOnTimerTick
- // free it when timeout.
- //
- if (Instance->Timeout > 0) {
- Instance->UdpIo->Protocol.Udp4->Poll (Instance->UdpIo->Protocol.Udp4);
- gBS->RestoreTPL (OldTpl);
- } else {
- gBS->RestoreTPL (OldTpl);
- break;
- }
- }
- }
- return Status;
- }
- /**
- Callback function for DhcpIterateOptions. This callback sets the
- EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point
- the individual DHCP option in the packet.
- @param[in] Tag The DHCP option type
- @param[in] Len Length of the DHCP option data
- @param[in] Data The DHCP option data
- @param[in] Context The context, to pass several parameters in.
- @retval EFI_SUCCESS It always returns EFI_SUCCESS
- **/
- EFI_STATUS
- Dhcp4ParseCheckOption (
- IN UINT8 Tag,
- IN UINT8 Len,
- IN UINT8 *Data,
- IN VOID *Context
- )
- {
- DHCP_PARSE_CONTEXT *Parse;
- Parse = (DHCP_PARSE_CONTEXT *)Context;
- Parse->Index++;
- if (Parse->Index <= Parse->OptionCount) {
- //
- // Use BASE_CR to get the memory position of EFI_DHCP4_PACKET_OPTION for
- // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only
- // pass in the point to option data.
- //
- Parse->Option[Parse->Index - 1] = BASE_CR (Data, EFI_DHCP4_PACKET_OPTION, Data);
- }
- return EFI_SUCCESS;
- }
- /**
- Parses the packed DHCP option data.
- The Parse() function is used to retrieve the option list from a DHCP packet.
- If *OptionCount isn't zero, and there is enough space for all the DHCP options
- in the Packet, each element of PacketOptionList is set to point to somewhere in
- the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,
- the caller should reassemble the parsed DHCP options to get the finial result.
- If *OptionCount is zero or there isn't enough space for all of them, the number
- of DHCP options in the Packet is returned in OptionCount.
- @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
- @param Packet Pointer to packet to be parsed.
- @param OptionCount On input, the number of entries in the PacketOptionList.
- On output, the number of entries that were written into the
- PacketOptionList.
- @param PacketOptionList List of packet option entries to be filled in. End option or pad
- options are not included.
- @retval EFI_SUCCESS The packet was successfully parsed.
- @retval EFI_INVALID_PARAMETER Some parameter is NULL.
- @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:
- 1) *OptionCount is smaller than the number of options that
- were found in the Packet.
- 2) PacketOptionList is NULL.
- **/
- EFI_STATUS
- EFIAPI
- EfiDhcp4Parse (
- IN EFI_DHCP4_PROTOCOL *This,
- IN EFI_DHCP4_PACKET *Packet,
- IN OUT UINT32 *OptionCount,
- OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL
- )
- {
- DHCP_PARSE_CONTEXT Context;
- EFI_STATUS Status;
- //
- // First validate the parameters
- //
- if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||
- (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
- EFI_ERROR (DhcpValidateOptions (Packet, NULL)))
- {
- return EFI_INVALID_PARAMETER;
- }
- if ((*OptionCount != 0) && (PacketOptionList == NULL)) {
- return EFI_BUFFER_TOO_SMALL;
- }
- ZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
- Context.Option = PacketOptionList;
- Context.OptionCount = *OptionCount;
- Context.Index = 0;
- Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- *OptionCount = Context.Index;
- if (Context.Index > Context.OptionCount) {
- return EFI_BUFFER_TOO_SMALL;
- }
- return EFI_SUCCESS;
- }
- /**
- Set the elapsed time based on the given instance and the pointer to the
- elapsed time option.
- @param[in] Elapsed The pointer to the position to append.
- @param[in] Instance The pointer to the Dhcp4 instance.
- **/
- VOID
- SetElapsedTime (
- IN UINT16 *Elapsed,
- IN DHCP_PROTOCOL *Instance
- )
- {
- WriteUnaligned16 (Elapsed, HTONS (Instance->ElaspedTime));
- }
|