Ip4Config2Impl.c 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143
  1. /** @file
  2. The implementation of EFI IPv4 Configuration II Protocol.
  3. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
  4. (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "Ip4Impl.h"
  8. LIST_ENTRY mIp4Config2InstanceList = { &mIp4Config2InstanceList, &mIp4Config2InstanceList };
  9. /**
  10. The event process routine when the DHCPv4 service binding protocol is installed
  11. in the system.
  12. @param[in] Event Not used.
  13. @param[in] Context Pointer to the IP4 config2 instance data.
  14. **/
  15. VOID
  16. EFIAPI
  17. Ip4Config2OnDhcp4SbInstalled (
  18. IN EFI_EVENT Event,
  19. IN VOID *Context
  20. );
  21. /**
  22. Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources.
  23. @param[in, out] Instance The buffer of IP4 config2 instance to be freed.
  24. @retval EFI_SUCCESS The child was successfully destroyed.
  25. @retval Others Failed to destroy the child.
  26. **/
  27. EFI_STATUS
  28. Ip4Config2DestroyDhcp4 (
  29. IN OUT IP4_CONFIG2_INSTANCE *Instance
  30. )
  31. {
  32. IP4_SERVICE *IpSb;
  33. EFI_STATUS Status;
  34. EFI_DHCP4_PROTOCOL *Dhcp4;
  35. Dhcp4 = Instance->Dhcp4;
  36. ASSERT (Dhcp4 != NULL);
  37. Dhcp4->Stop (Dhcp4);
  38. Dhcp4->Configure (Dhcp4, NULL);
  39. Instance->Dhcp4 = NULL;
  40. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  41. //
  42. // Close DHCPv4 protocol and destroy the child.
  43. //
  44. Status = gBS->CloseProtocol (
  45. Instance->Dhcp4Handle,
  46. &gEfiDhcp4ProtocolGuid,
  47. IpSb->Image,
  48. IpSb->Controller
  49. );
  50. if (EFI_ERROR (Status)) {
  51. return Status;
  52. }
  53. Status = NetLibDestroyServiceChild (
  54. IpSb->Controller,
  55. IpSb->Image,
  56. &gEfiDhcp4ServiceBindingProtocolGuid,
  57. Instance->Dhcp4Handle
  58. );
  59. Instance->Dhcp4Handle = NULL;
  60. return Status;
  61. }
  62. /**
  63. Update the current policy to NewPolicy. During the transition
  64. period, the default router list
  65. and address list in all interfaces will be released.
  66. @param[in] IpSb The IP4 service binding instance.
  67. @param[in] NewPolicy The new policy to be updated to.
  68. **/
  69. VOID
  70. Ip4Config2OnPolicyChanged (
  71. IN IP4_SERVICE *IpSb,
  72. IN EFI_IP4_CONFIG2_POLICY NewPolicy
  73. )
  74. {
  75. IP4_INTERFACE *IpIf;
  76. IP4_ROUTE_TABLE *RouteTable;
  77. //
  78. // Currently there are only two policies: static and dhcp. Regardless of
  79. // what transition is going on, i.e., static -> dhcp and dhcp ->
  80. // static, we have to free default router table and all addresses.
  81. //
  82. if (IpSb->DefaultInterface != NULL) {
  83. if (IpSb->DefaultRouteTable != NULL) {
  84. Ip4FreeRouteTable (IpSb->DefaultRouteTable);
  85. IpSb->DefaultRouteTable = NULL;
  86. }
  87. Ip4CancelReceive (IpSb->DefaultInterface);
  88. Ip4FreeInterface (IpSb->DefaultInterface, NULL);
  89. IpSb->DefaultInterface = NULL;
  90. }
  91. Ip4CleanAssembleTable (&IpSb->Assemble);
  92. //
  93. // Create new default interface and route table.
  94. //
  95. IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);
  96. if (IpIf == NULL) {
  97. return;
  98. }
  99. RouteTable = Ip4CreateRouteTable ();
  100. if (RouteTable == NULL) {
  101. Ip4FreeInterface (IpIf, NULL);
  102. return;
  103. }
  104. IpSb->DefaultInterface = IpIf;
  105. InsertHeadList (&IpSb->Interfaces, &IpIf->Link);
  106. IpSb->DefaultRouteTable = RouteTable;
  107. Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);
  108. if ((IpSb->State == IP4_SERVICE_CONFIGED) || (IpSb->State == IP4_SERVICE_STARTED)) {
  109. IpSb->State = IP4_SERVICE_UNSTARTED;
  110. }
  111. //
  112. // Start the dhcp configuration.
  113. //
  114. if (NewPolicy == Ip4Config2PolicyDhcp) {
  115. Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);
  116. }
  117. }
  118. /**
  119. Signal the registered event. It is the callback routine for NetMapIterate.
  120. @param[in] Map Points to the list of registered event.
  121. @param[in] Item The registered event.
  122. @param[in] Arg Not used.
  123. @retval EFI_SUCCESS The event was signaled successfully.
  124. **/
  125. EFI_STATUS
  126. EFIAPI
  127. Ip4Config2SignalEvent (
  128. IN NET_MAP *Map,
  129. IN NET_MAP_ITEM *Item,
  130. IN VOID *Arg
  131. )
  132. {
  133. gBS->SignalEvent ((EFI_EVENT)Item->Key);
  134. return EFI_SUCCESS;
  135. }
  136. /**
  137. Read the configuration data from variable storage according to the VarName and
  138. gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the
  139. data is corrupted, it clears the variable data to ZERO. Otherwise, it outputs the
  140. configuration data to IP4_CONFIG2_INSTANCE.
  141. @param[in] VarName The pointer to the variable name
  142. @param[in, out] Instance The pointer to the IP4 config2 instance data.
  143. @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
  144. @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
  145. @retval EFI_SUCCESS The configuration data was retrieved successfully.
  146. **/
  147. EFI_STATUS
  148. Ip4Config2ReadConfigData (
  149. IN CHAR16 *VarName,
  150. IN OUT IP4_CONFIG2_INSTANCE *Instance
  151. )
  152. {
  153. EFI_STATUS Status;
  154. UINTN VarSize;
  155. IP4_CONFIG2_VARIABLE *Variable;
  156. IP4_CONFIG2_DATA_ITEM *DataItem;
  157. UINTN Index;
  158. IP4_CONFIG2_DATA_RECORD DataRecord;
  159. CHAR8 *Data;
  160. //
  161. // Try to read the configuration variable.
  162. //
  163. VarSize = 0;
  164. Status = gRT->GetVariable (
  165. VarName,
  166. &gEfiIp4Config2ProtocolGuid,
  167. NULL,
  168. &VarSize,
  169. NULL
  170. );
  171. if (Status == EFI_BUFFER_TOO_SMALL) {
  172. //
  173. // Allocate buffer and read the config variable.
  174. //
  175. Variable = AllocatePool (VarSize);
  176. if (Variable == NULL) {
  177. return EFI_OUT_OF_RESOURCES;
  178. }
  179. Status = gRT->GetVariable (
  180. VarName,
  181. &gEfiIp4Config2ProtocolGuid,
  182. NULL,
  183. &VarSize,
  184. Variable
  185. );
  186. if (EFI_ERROR (Status) || ((UINT16)(~NetblockChecksum ((UINT8 *)Variable, (UINT32)VarSize)) != 0)) {
  187. //
  188. // GetVariable still error or the variable is corrupted.
  189. // Fall back to the default value.
  190. //
  191. FreePool (Variable);
  192. //
  193. // Remove the problematic variable and return EFI_NOT_FOUND, a new
  194. // variable will be set again.
  195. //
  196. gRT->SetVariable (
  197. VarName,
  198. &gEfiIp4Config2ProtocolGuid,
  199. IP4_CONFIG2_VARIABLE_ATTRIBUTE,
  200. 0,
  201. NULL
  202. );
  203. return EFI_NOT_FOUND;
  204. }
  205. for (Index = 0; Index < Variable->DataRecordCount; Index++) {
  206. CopyMem (&DataRecord, &Variable->DataRecord[Index], sizeof (DataRecord));
  207. DataItem = &Instance->DataItem[DataRecord.DataType];
  208. if (DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED) &&
  209. (DataItem->DataSize != DataRecord.DataSize)
  210. )
  211. {
  212. //
  213. // Perhaps a corrupted data record...
  214. //
  215. continue;
  216. }
  217. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {
  218. //
  219. // This data item has variable length data.
  220. //
  221. DataItem->Data.Ptr = AllocatePool (DataRecord.DataSize);
  222. if (DataItem->Data.Ptr == NULL) {
  223. //
  224. // no memory resource
  225. //
  226. continue;
  227. }
  228. }
  229. Data = (CHAR8 *)Variable + DataRecord.Offset;
  230. CopyMem (DataItem->Data.Ptr, Data, DataRecord.DataSize);
  231. DataItem->DataSize = DataRecord.DataSize;
  232. DataItem->Status = EFI_SUCCESS;
  233. }
  234. FreePool (Variable);
  235. return EFI_SUCCESS;
  236. }
  237. return Status;
  238. }
  239. /**
  240. Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage.
  241. @param[in] VarName The pointer to the variable name.
  242. @param[in] Instance The pointer to the IP4 config2 instance data.
  243. @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
  244. @retval EFI_SUCCESS The configuration data is written successfully.
  245. **/
  246. EFI_STATUS
  247. Ip4Config2WriteConfigData (
  248. IN CHAR16 *VarName,
  249. IN IP4_CONFIG2_INSTANCE *Instance
  250. )
  251. {
  252. UINTN Index;
  253. UINTN VarSize;
  254. IP4_CONFIG2_DATA_ITEM *DataItem;
  255. IP4_CONFIG2_VARIABLE *Variable;
  256. IP4_CONFIG2_DATA_RECORD *DataRecord;
  257. CHAR8 *Heap;
  258. EFI_STATUS Status;
  259. VarSize = sizeof (IP4_CONFIG2_VARIABLE) - sizeof (IP4_CONFIG2_DATA_RECORD);
  260. for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {
  261. DataItem = &Instance->DataItem[Index];
  262. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) {
  263. VarSize += sizeof (IP4_CONFIG2_DATA_RECORD) + DataItem->DataSize;
  264. }
  265. }
  266. Variable = AllocatePool (VarSize);
  267. if (Variable == NULL) {
  268. return EFI_OUT_OF_RESOURCES;
  269. }
  270. Heap = (CHAR8 *)Variable + VarSize;
  271. Variable->DataRecordCount = 0;
  272. for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {
  273. DataItem = &Instance->DataItem[Index];
  274. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) {
  275. Heap -= DataItem->DataSize;
  276. CopyMem (Heap, DataItem->Data.Ptr, DataItem->DataSize);
  277. DataRecord = &Variable->DataRecord[Variable->DataRecordCount];
  278. DataRecord->DataType = (EFI_IP4_CONFIG2_DATA_TYPE)Index;
  279. DataRecord->DataSize = (UINT32)DataItem->DataSize;
  280. DataRecord->Offset = (UINT16)(Heap - (CHAR8 *)Variable);
  281. Variable->DataRecordCount++;
  282. }
  283. }
  284. Variable->Checksum = 0;
  285. Variable->Checksum = (UINT16) ~NetblockChecksum ((UINT8 *)Variable, (UINT32)VarSize);
  286. Status = gRT->SetVariable (
  287. VarName,
  288. &gEfiIp4Config2ProtocolGuid,
  289. IP4_CONFIG2_VARIABLE_ATTRIBUTE,
  290. VarSize,
  291. Variable
  292. );
  293. FreePool (Variable);
  294. return Status;
  295. }
  296. /**
  297. Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData.
  298. The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the
  299. IP4 driver.
  300. @param[in] IpSb The IP4 service binding instance.
  301. @param[out] Table The built IP4 route table.
  302. @retval EFI_SUCCESS The route table is successfully build
  303. @retval EFI_NOT_FOUND Failed to allocate the memory for the route table.
  304. **/
  305. EFI_STATUS
  306. Ip4Config2BuildDefaultRouteTable (
  307. IN IP4_SERVICE *IpSb,
  308. OUT EFI_IP4_ROUTE_TABLE *Table
  309. )
  310. {
  311. LIST_ENTRY *Entry;
  312. IP4_ROUTE_ENTRY *RtEntry;
  313. UINT32 Count;
  314. INT32 Index;
  315. if (IpSb->DefaultRouteTable == NULL) {
  316. return EFI_NOT_FOUND;
  317. }
  318. Count = IpSb->DefaultRouteTable->TotalNum;
  319. if (Count == 0) {
  320. return EFI_NOT_FOUND;
  321. }
  322. //
  323. // Copy the route entry to EFI route table. Keep the order of
  324. // route entry copied from most specific to default route. That
  325. // is, interlevel the route entry from the instance's route area
  326. // and those from the default route table's route area.
  327. //
  328. Count = 0;
  329. for (Index = IP4_MASK_MAX; Index >= 0; Index--) {
  330. NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) {
  331. RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);
  332. EFI_IP4 (Table[Count].SubnetAddress) = HTONL (RtEntry->Dest & RtEntry->Netmask);
  333. EFI_IP4 (Table[Count].SubnetMask) = HTONL (RtEntry->Netmask);
  334. EFI_IP4 (Table[Count].GatewayAddress) = HTONL (RtEntry->NextHop);
  335. Count++;
  336. }
  337. }
  338. return EFI_SUCCESS;
  339. }
  340. /**
  341. The event process routine when the DHCPv4 service binding protocol is installed
  342. in the system.
  343. @param[in] Event Not used.
  344. @param[in] Context The pointer to the IP4 config2 instance data.
  345. **/
  346. VOID
  347. EFIAPI
  348. Ip4Config2OnDhcp4SbInstalled (
  349. IN EFI_EVENT Event,
  350. IN VOID *Context
  351. )
  352. {
  353. IP4_CONFIG2_INSTANCE *Instance;
  354. Instance = (IP4_CONFIG2_INSTANCE *)Context;
  355. if ((Instance->Dhcp4Handle != NULL) || (Instance->Policy != Ip4Config2PolicyDhcp)) {
  356. //
  357. // The DHCP4 child is already created or the policy is no longer DHCP.
  358. //
  359. return;
  360. }
  361. Ip4StartAutoConfig (Instance);
  362. }
  363. /**
  364. Set the station address and subnetmask for the default interface.
  365. @param[in] IpSb The pointer to the IP4 service binding instance.
  366. @param[in] StationAddress Ip address to be set.
  367. @param[in] SubnetMask Subnet to be set.
  368. @retval EFI_SUCCESS Set default address successful.
  369. @retval Others Some errors occur in setting.
  370. **/
  371. EFI_STATUS
  372. Ip4Config2SetDefaultAddr (
  373. IN IP4_SERVICE *IpSb,
  374. IN IP4_ADDR StationAddress,
  375. IN IP4_ADDR SubnetMask
  376. )
  377. {
  378. EFI_STATUS Status;
  379. IP4_INTERFACE *IpIf;
  380. IP4_PROTOCOL *Ip4Instance;
  381. EFI_ARP_PROTOCOL *Arp;
  382. LIST_ENTRY *Entry;
  383. IP4_ADDR Subnet;
  384. IP4_ROUTE_TABLE *RouteTable;
  385. IpIf = IpSb->DefaultInterface;
  386. ASSERT (IpIf != NULL);
  387. if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) {
  388. IpSb->State = IP4_SERVICE_CONFIGED;
  389. return EFI_SUCCESS;
  390. }
  391. if (IpSb->Reconfig) {
  392. //
  393. // The default address is changed, free the previous interface first.
  394. //
  395. if (IpSb->DefaultRouteTable != NULL) {
  396. Ip4FreeRouteTable (IpSb->DefaultRouteTable);
  397. IpSb->DefaultRouteTable = NULL;
  398. }
  399. Ip4CancelReceive (IpSb->DefaultInterface);
  400. Ip4FreeInterface (IpSb->DefaultInterface, NULL);
  401. IpSb->DefaultInterface = NULL;
  402. //
  403. // Create new default interface and route table.
  404. //
  405. IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);
  406. if (IpIf == NULL) {
  407. return EFI_OUT_OF_RESOURCES;
  408. }
  409. RouteTable = Ip4CreateRouteTable ();
  410. if (RouteTable == NULL) {
  411. Ip4FreeInterface (IpIf, NULL);
  412. return EFI_OUT_OF_RESOURCES;
  413. }
  414. IpSb->DefaultInterface = IpIf;
  415. InsertHeadList (&IpSb->Interfaces, &IpIf->Link);
  416. IpSb->DefaultRouteTable = RouteTable;
  417. Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);
  418. }
  419. if (IpSb->State == IP4_SERVICE_CONFIGED) {
  420. IpSb->State = IP4_SERVICE_UNSTARTED;
  421. }
  422. Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);
  423. if (EFI_ERROR (Status)) {
  424. return Status;
  425. }
  426. if (IpIf->Arp != NULL) {
  427. //
  428. // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,
  429. // but some IP children may have referenced the default interface before it is configured,
  430. // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.
  431. //
  432. Arp = NULL;
  433. NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
  434. Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE);
  435. Status = gBS->OpenProtocol (
  436. IpIf->ArpHandle,
  437. &gEfiArpProtocolGuid,
  438. (VOID **)&Arp,
  439. gIp4DriverBinding.DriverBindingHandle,
  440. Ip4Instance->Handle,
  441. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  442. );
  443. if (EFI_ERROR (Status)) {
  444. return Status;
  445. }
  446. }
  447. }
  448. //
  449. // Add a route for the connected network.
  450. //
  451. Subnet = StationAddress & SubnetMask;
  452. Ip4AddRoute (
  453. IpSb->DefaultRouteTable,
  454. Subnet,
  455. SubnetMask,
  456. IP4_ALLZERO_ADDRESS
  457. );
  458. IpSb->State = IP4_SERVICE_CONFIGED;
  459. IpSb->Reconfig = FALSE;
  460. return EFI_SUCCESS;
  461. }
  462. /**
  463. Set the station address, subnetmask and gateway address for the default interface.
  464. @param[in] Instance The pointer to the IP4 config2 instance data.
  465. @param[in] StationAddress Ip address to be set.
  466. @param[in] SubnetMask Subnet to be set.
  467. @param[in] GatewayAddress Gateway to be set.
  468. @retval EFI_SUCCESS Set default If successful.
  469. @retval Others Errors occur as indicated.
  470. **/
  471. EFI_STATUS
  472. Ip4Config2SetDefaultIf (
  473. IN IP4_CONFIG2_INSTANCE *Instance,
  474. IN IP4_ADDR StationAddress,
  475. IN IP4_ADDR SubnetMask,
  476. IN IP4_ADDR GatewayAddress
  477. )
  478. {
  479. EFI_STATUS Status;
  480. IP4_SERVICE *IpSb;
  481. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  482. //
  483. // Check whether the StationAddress/SubnetMask pair is valid.
  484. //
  485. if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {
  486. return EFI_INVALID_PARAMETER;
  487. }
  488. Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);
  489. if (EFI_ERROR (Status)) {
  490. return Status;
  491. }
  492. //
  493. // Create a route if there is a default router.
  494. //
  495. if (GatewayAddress != IP4_ALLZERO_ADDRESS) {
  496. Ip4AddRoute (
  497. IpSb->DefaultRouteTable,
  498. IP4_ALLZERO_ADDRESS,
  499. IP4_ALLZERO_ADDRESS,
  500. GatewayAddress
  501. );
  502. }
  503. return EFI_SUCCESS;
  504. }
  505. /**
  506. Release all the DHCP related resources.
  507. @param Instance The IP4 config2 instance.
  508. @return None
  509. **/
  510. VOID
  511. Ip4Config2CleanDhcp4 (
  512. IN IP4_CONFIG2_INSTANCE *Instance
  513. )
  514. {
  515. IP4_SERVICE *IpSb;
  516. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  517. if (Instance->Dhcp4 != NULL) {
  518. Instance->Dhcp4->Stop (Instance->Dhcp4);
  519. gBS->CloseProtocol (
  520. Instance->Dhcp4Handle,
  521. &gEfiDhcp4ProtocolGuid,
  522. IpSb->Image,
  523. IpSb->Controller
  524. );
  525. Instance->Dhcp4 = NULL;
  526. }
  527. if (Instance->Dhcp4Handle != NULL) {
  528. NetLibDestroyServiceChild (
  529. IpSb->Controller,
  530. IpSb->Image,
  531. &gEfiDhcp4ServiceBindingProtocolGuid,
  532. Instance->Dhcp4Handle
  533. );
  534. Instance->Dhcp4Handle = NULL;
  535. }
  536. if (Instance->Dhcp4Event != NULL) {
  537. gBS->CloseEvent (Instance->Dhcp4Event);
  538. Instance->Dhcp4Event = NULL;
  539. }
  540. }
  541. /**
  542. This worker function sets the DNS server list for the EFI IPv4 network
  543. stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
  544. manages. The DNS server addresses must be unicast IPv4 addresses.
  545. @param[in] Instance The pointer to the IP4 config2 instance data.
  546. @param[in] DataSize The size of the buffer pointed to by Data in bytes.
  547. @param[in] Data The data buffer to set, points to an array of
  548. EFI_IPv4_ADDRESS instances.
  549. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  550. @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
  551. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
  552. @retval EFI_ABORTED The DNS server addresses to be set equal the current
  553. configuration.
  554. @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
  555. network stack was set.
  556. **/
  557. EFI_STATUS
  558. Ip4Config2SetDnsServerWorker (
  559. IN IP4_CONFIG2_INSTANCE *Instance,
  560. IN UINTN DataSize,
  561. IN VOID *Data
  562. )
  563. {
  564. UINTN OldIndex;
  565. UINTN NewIndex;
  566. EFI_IPv4_ADDRESS *OldDns;
  567. EFI_IPv4_ADDRESS *NewDns;
  568. UINTN OldDnsCount;
  569. UINTN NewDnsCount;
  570. IP4_CONFIG2_DATA_ITEM *Item;
  571. BOOLEAN OneAdded;
  572. VOID *Tmp;
  573. IP4_ADDR DnsAddress;
  574. if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {
  575. return EFI_BAD_BUFFER_SIZE;
  576. }
  577. Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
  578. NewDns = (EFI_IPv4_ADDRESS *)Data;
  579. OldDns = Item->Data.DnsServers;
  580. NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
  581. OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);
  582. OneAdded = FALSE;
  583. if (NewDnsCount != OldDnsCount) {
  584. Tmp = AllocatePool (DataSize);
  585. if (Tmp == NULL) {
  586. return EFI_OUT_OF_RESOURCES;
  587. }
  588. } else {
  589. Tmp = NULL;
  590. }
  591. for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {
  592. CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));
  593. if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress))) {
  594. //
  595. // The dns server address must be unicast.
  596. //
  597. if (Tmp != NULL) {
  598. FreePool (Tmp);
  599. }
  600. return EFI_INVALID_PARAMETER;
  601. }
  602. if (OneAdded) {
  603. //
  604. // If any address in the new setting is not in the old settings, skip the
  605. // comparision below.
  606. //
  607. continue;
  608. }
  609. for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {
  610. if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {
  611. //
  612. // If found break out.
  613. //
  614. break;
  615. }
  616. }
  617. if (OldIndex == OldDnsCount) {
  618. OneAdded = TRUE;
  619. }
  620. }
  621. if (!OneAdded && (DataSize == Item->DataSize)) {
  622. //
  623. // No new item is added and the size is the same.
  624. //
  625. Item->Status = EFI_SUCCESS;
  626. return EFI_ABORTED;
  627. } else {
  628. if (Tmp != NULL) {
  629. if (Item->Data.Ptr != NULL) {
  630. FreePool (Item->Data.Ptr);
  631. }
  632. Item->Data.Ptr = Tmp;
  633. }
  634. CopyMem (Item->Data.Ptr, Data, DataSize);
  635. Item->DataSize = DataSize;
  636. Item->Status = EFI_SUCCESS;
  637. return EFI_SUCCESS;
  638. }
  639. }
  640. /**
  641. Callback function when DHCP process finished. It will save the
  642. retrieved IP configure parameter from DHCP to the NVRam.
  643. @param Event The callback event
  644. @param Context Opaque context to the callback
  645. @return None
  646. **/
  647. VOID
  648. EFIAPI
  649. Ip4Config2OnDhcp4Complete (
  650. IN EFI_EVENT Event,
  651. IN VOID *Context
  652. )
  653. {
  654. IP4_CONFIG2_INSTANCE *Instance;
  655. EFI_DHCP4_MODE_DATA Dhcp4Mode;
  656. EFI_STATUS Status;
  657. IP4_ADDR StationAddress;
  658. IP4_ADDR SubnetMask;
  659. IP4_ADDR GatewayAddress;
  660. UINT32 Index;
  661. UINT32 OptionCount;
  662. EFI_DHCP4_PACKET_OPTION **OptionList;
  663. Instance = (IP4_CONFIG2_INSTANCE *)Context;
  664. ASSERT (Instance->Dhcp4 != NULL);
  665. //
  666. // Get the DHCP retrieved parameters
  667. //
  668. Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);
  669. if (EFI_ERROR (Status)) {
  670. goto Exit;
  671. }
  672. if (Dhcp4Mode.State == Dhcp4Bound) {
  673. StationAddress = EFI_NTOHL (Dhcp4Mode.ClientAddress);
  674. SubnetMask = EFI_NTOHL (Dhcp4Mode.SubnetMask);
  675. GatewayAddress = EFI_NTOHL (Dhcp4Mode.RouterAddress);
  676. Status = Ip4Config2SetDefaultIf (Instance, StationAddress, SubnetMask, GatewayAddress);
  677. if (EFI_ERROR (Status)) {
  678. goto Exit;
  679. }
  680. //
  681. // Parse the ACK to get required DNS server information.
  682. //
  683. OptionCount = 0;
  684. OptionList = NULL;
  685. Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);
  686. if (Status != EFI_BUFFER_TOO_SMALL) {
  687. goto Exit;
  688. }
  689. OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
  690. if (OptionList == NULL) {
  691. goto Exit;
  692. }
  693. Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);
  694. if (EFI_ERROR (Status)) {
  695. FreePool (OptionList);
  696. goto Exit;
  697. }
  698. for (Index = 0; Index < OptionCount; Index++) {
  699. //
  700. // Look for DNS Server opcode (6).
  701. //
  702. if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {
  703. if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {
  704. break;
  705. }
  706. Ip4Config2SetDnsServerWorker (Instance, OptionList[Index]->Length, &OptionList[Index]->Data[0]);
  707. break;
  708. }
  709. }
  710. FreePool (OptionList);
  711. Instance->DhcpSuccess = TRUE;
  712. }
  713. Exit:
  714. Ip4Config2CleanDhcp4 (Instance);
  715. DispatchDpc ();
  716. }
  717. /**
  718. Start the DHCP configuration for this IP service instance.
  719. It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the
  720. DHCP configuration.
  721. @param[in] Instance The IP4 config2 instance to configure
  722. @retval EFI_SUCCESS The auto configuration is successfully started
  723. @retval Others Failed to start auto configuration.
  724. **/
  725. EFI_STATUS
  726. Ip4StartAutoConfig (
  727. IN IP4_CONFIG2_INSTANCE *Instance
  728. )
  729. {
  730. IP4_SERVICE *IpSb;
  731. EFI_DHCP4_PROTOCOL *Dhcp4;
  732. EFI_DHCP4_MODE_DATA Dhcp4Mode;
  733. EFI_DHCP4_PACKET_OPTION *OptionList[1];
  734. IP4_CONFIG2_DHCP4_OPTION ParaList;
  735. EFI_STATUS Status;
  736. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  737. if (IpSb->State > IP4_SERVICE_UNSTARTED) {
  738. return EFI_SUCCESS;
  739. }
  740. //
  741. // A host must not invoke DHCP configuration if it is already
  742. // participating in the DHCP configuration process.
  743. //
  744. if (Instance->Dhcp4Handle != NULL) {
  745. return EFI_SUCCESS;
  746. }
  747. Status = NetLibCreateServiceChild (
  748. IpSb->Controller,
  749. IpSb->Image,
  750. &gEfiDhcp4ServiceBindingProtocolGuid,
  751. &Instance->Dhcp4Handle
  752. );
  753. if (Status == EFI_UNSUPPORTED) {
  754. //
  755. // No DHCPv4 Service Binding protocol, register a notify.
  756. //
  757. if (Instance->Dhcp4SbNotifyEvent == NULL) {
  758. Instance->Dhcp4SbNotifyEvent = EfiCreateProtocolNotifyEvent (
  759. &gEfiDhcp4ServiceBindingProtocolGuid,
  760. TPL_CALLBACK,
  761. Ip4Config2OnDhcp4SbInstalled,
  762. (VOID *)Instance,
  763. &Instance->Registration
  764. );
  765. }
  766. }
  767. if (EFI_ERROR (Status)) {
  768. return Status;
  769. }
  770. if (Instance->Dhcp4SbNotifyEvent != NULL) {
  771. gBS->CloseEvent (Instance->Dhcp4SbNotifyEvent);
  772. }
  773. Status = gBS->OpenProtocol (
  774. Instance->Dhcp4Handle,
  775. &gEfiDhcp4ProtocolGuid,
  776. (VOID **)&Instance->Dhcp4,
  777. IpSb->Image,
  778. IpSb->Controller,
  779. EFI_OPEN_PROTOCOL_BY_DRIVER
  780. );
  781. if (EFI_ERROR (Status)) {
  782. NetLibDestroyServiceChild (
  783. IpSb->Controller,
  784. IpSb->Image,
  785. &gEfiDhcp4ServiceBindingProtocolGuid,
  786. Instance->Dhcp4Handle
  787. );
  788. Instance->Dhcp4Handle = NULL;
  789. return Status;
  790. }
  791. //
  792. // Check the current DHCP status, if the DHCP process has
  793. // already finished, return now.
  794. //
  795. Dhcp4 = Instance->Dhcp4;
  796. Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
  797. if (Dhcp4Mode.State == Dhcp4Bound) {
  798. Ip4Config2OnDhcp4Complete (NULL, Instance);
  799. return EFI_SUCCESS;
  800. }
  801. //
  802. // Try to start the DHCP process. Use most of the current
  803. // DHCP configuration to avoid problems if some DHCP client
  804. // yields the control of this DHCP service to us.
  805. //
  806. ParaList.Head.OpCode = DHCP4_TAG_PARA_LIST;
  807. ParaList.Head.Length = 3;
  808. ParaList.Head.Data[0] = DHCP4_TAG_NETMASK;
  809. ParaList.Route = DHCP4_TAG_ROUTER;
  810. ParaList.Dns = DHCP4_TAG_DNS_SERVER;
  811. OptionList[0] = &ParaList.Head;
  812. Dhcp4Mode.ConfigData.OptionCount = 1;
  813. Dhcp4Mode.ConfigData.OptionList = OptionList;
  814. Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);
  815. if (EFI_ERROR (Status)) {
  816. gBS->CloseProtocol (
  817. Instance->Dhcp4Handle,
  818. &gEfiDhcp4ProtocolGuid,
  819. IpSb->Image,
  820. IpSb->Controller
  821. );
  822. NetLibDestroyServiceChild (
  823. IpSb->Controller,
  824. IpSb->Image,
  825. &gEfiDhcp4ServiceBindingProtocolGuid,
  826. Instance->Dhcp4Handle
  827. );
  828. Instance->Dhcp4 = NULL;
  829. Instance->Dhcp4Handle = NULL;
  830. return Status;
  831. }
  832. //
  833. // Start the DHCP process
  834. //
  835. Status = gBS->CreateEvent (
  836. EVT_NOTIFY_SIGNAL,
  837. TPL_CALLBACK,
  838. Ip4Config2OnDhcp4Complete,
  839. Instance,
  840. &Instance->Dhcp4Event
  841. );
  842. if (EFI_ERROR (Status)) {
  843. Ip4Config2DestroyDhcp4 (Instance);
  844. return Status;
  845. }
  846. Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);
  847. if (EFI_ERROR (Status)) {
  848. Ip4Config2DestroyDhcp4 (Instance);
  849. gBS->CloseEvent (Instance->Dhcp4Event);
  850. Instance->Dhcp4Event = NULL;
  851. return Status;
  852. }
  853. IpSb->State = IP4_SERVICE_STARTED;
  854. DispatchDpc ();
  855. return EFI_SUCCESS;
  856. }
  857. /**
  858. The work function is to get the interface information of the communication
  859. device this IP4_CONFIG2_INSTANCE manages.
  860. @param[in] Instance Pointer to the IP4 config2 instance data.
  861. @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
  862. bytes, the size of buffer required to store the specified
  863. configuration data.
  864. @param[in] Data The data buffer in which the configuration data is returned.
  865. Ignored if DataSize is ZERO.
  866. @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
  867. configuration data, and the required size is
  868. returned in DataSize.
  869. @retval EFI_SUCCESS The specified configuration data was obtained.
  870. **/
  871. EFI_STATUS
  872. Ip4Config2GetIfInfo (
  873. IN IP4_CONFIG2_INSTANCE *Instance,
  874. IN OUT UINTN *DataSize,
  875. IN VOID *Data OPTIONAL
  876. )
  877. {
  878. IP4_SERVICE *IpSb;
  879. UINTN Length;
  880. IP4_CONFIG2_DATA_ITEM *Item;
  881. EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
  882. IP4_ADDR Address;
  883. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  884. Length = sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO);
  885. if (IpSb->DefaultRouteTable != NULL) {
  886. Length += IpSb->DefaultRouteTable->TotalNum * sizeof (EFI_IP4_ROUTE_TABLE);
  887. }
  888. if (*DataSize < Length) {
  889. *DataSize = Length;
  890. return EFI_BUFFER_TOO_SMALL;
  891. }
  892. //
  893. // Copy the fixed size part of the interface info.
  894. //
  895. Item = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo];
  896. IfInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *)Data;
  897. CopyMem (IfInfo, Item->Data.Ptr, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO));
  898. //
  899. // Update the address info.
  900. //
  901. if (IpSb->DefaultInterface != NULL) {
  902. Address = HTONL (IpSb->DefaultInterface->Ip);
  903. CopyMem (&IfInfo->StationAddress, &Address, sizeof (EFI_IPv4_ADDRESS));
  904. Address = HTONL (IpSb->DefaultInterface->SubnetMask);
  905. CopyMem (&IfInfo->SubnetMask, &Address, sizeof (EFI_IPv4_ADDRESS));
  906. }
  907. if (IpSb->DefaultRouteTable != NULL) {
  908. IfInfo->RouteTableSize = IpSb->DefaultRouteTable->TotalNum;
  909. IfInfo->RouteTable = (EFI_IP4_ROUTE_TABLE *)((UINT8 *)Data + sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO));
  910. Ip4Config2BuildDefaultRouteTable (IpSb, IfInfo->RouteTable);
  911. }
  912. return EFI_SUCCESS;
  913. }
  914. /**
  915. The work function is to set the general configuration policy for the EFI IPv4 network
  916. stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE.
  917. The policy will affect other configuration settings.
  918. @param[in] Instance Pointer to the IP4 config2 instance data.
  919. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  920. @param[in] Data The data buffer to set.
  921. @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
  922. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  923. @retval EFI_ABORTED The new policy equals the current policy.
  924. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  925. network stack was set.
  926. **/
  927. EFI_STATUS
  928. Ip4Config2SetPolicy (
  929. IN IP4_CONFIG2_INSTANCE *Instance,
  930. IN UINTN DataSize,
  931. IN VOID *Data
  932. )
  933. {
  934. EFI_IP4_CONFIG2_POLICY NewPolicy;
  935. IP4_CONFIG2_DATA_ITEM *DataItem;
  936. IP4_SERVICE *IpSb;
  937. if (DataSize != sizeof (EFI_IP4_CONFIG2_POLICY)) {
  938. return EFI_BAD_BUFFER_SIZE;
  939. }
  940. NewPolicy = *((EFI_IP4_CONFIG2_POLICY *)Data);
  941. if (NewPolicy >= Ip4Config2PolicyMax) {
  942. return EFI_INVALID_PARAMETER;
  943. }
  944. if (NewPolicy == Instance->Policy) {
  945. if ((NewPolicy != Ip4Config2PolicyDhcp) || Instance->DhcpSuccess) {
  946. return EFI_ABORTED;
  947. }
  948. } else {
  949. //
  950. // The policy is changed. Clean the ManualAddress, Gateway and DnsServers,
  951. // shrink the variable data size, and fire up all the related events.
  952. //
  953. DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
  954. if (DataItem->Data.Ptr != NULL) {
  955. FreePool (DataItem->Data.Ptr);
  956. }
  957. DataItem->Data.Ptr = NULL;
  958. DataItem->DataSize = 0;
  959. DataItem->Status = EFI_NOT_FOUND;
  960. NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);
  961. DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];
  962. if (DataItem->Data.Ptr != NULL) {
  963. FreePool (DataItem->Data.Ptr);
  964. }
  965. DataItem->Data.Ptr = NULL;
  966. DataItem->DataSize = 0;
  967. DataItem->Status = EFI_NOT_FOUND;
  968. NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);
  969. DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
  970. if (DataItem->Data.Ptr != NULL) {
  971. FreePool (DataItem->Data.Ptr);
  972. }
  973. DataItem->Data.Ptr = NULL;
  974. DataItem->DataSize = 0;
  975. DataItem->Status = EFI_NOT_FOUND;
  976. NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);
  977. if (NewPolicy == Ip4Config2PolicyDhcp) {
  978. SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_VOLATILE);
  979. } else {
  980. //
  981. // The policy is changed from dhcp to static. Stop the DHCPv4 process
  982. // and destroy the DHCPv4 child.
  983. //
  984. if (Instance->Dhcp4Handle != NULL) {
  985. Ip4Config2DestroyDhcp4 (Instance);
  986. }
  987. //
  988. // Close the event.
  989. //
  990. if (Instance->Dhcp4Event != NULL) {
  991. gBS->CloseEvent (Instance->Dhcp4Event);
  992. Instance->Dhcp4Event = NULL;
  993. }
  994. }
  995. }
  996. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  997. Ip4Config2OnPolicyChanged (IpSb, NewPolicy);
  998. Instance->Policy = NewPolicy;
  999. return EFI_SUCCESS;
  1000. }
  1001. /**
  1002. The work function is to set the station addresses manually for the EFI IPv4
  1003. network stack. It is only configurable when the policy is Ip4Config2PolicyStatic.
  1004. @param[in] Instance Pointer to the IP4 config2 instance data.
  1005. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  1006. @param[in] Data The data buffer to set.
  1007. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  1008. @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
  1009. under the current policy.
  1010. @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
  1011. @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
  1012. @retval EFI_NOT_READY An asynchronous process is invoked to set the specified
  1013. configuration data, and the process is not finished.
  1014. @retval EFI_ABORTED The manual addresses to be set equal current
  1015. configuration.
  1016. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  1017. network stack was set.
  1018. **/
  1019. EFI_STATUS
  1020. Ip4Config2SetManualAddress (
  1021. IN IP4_CONFIG2_INSTANCE *Instance,
  1022. IN UINTN DataSize,
  1023. IN VOID *Data
  1024. )
  1025. {
  1026. EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress;
  1027. IP4_CONFIG2_DATA_ITEM *DataItem;
  1028. EFI_STATUS Status;
  1029. IP4_ADDR StationAddress;
  1030. IP4_ADDR SubnetMask;
  1031. VOID *Ptr;
  1032. IP4_SERVICE *IpSb;
  1033. IP4_INTERFACE *IpIf;
  1034. IP4_ROUTE_TABLE *RouteTable;
  1035. DataItem = NULL;
  1036. Status = EFI_SUCCESS;
  1037. Ptr = NULL;
  1038. IpIf = NULL;
  1039. RouteTable = NULL;
  1040. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  1041. ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);
  1042. if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0)) {
  1043. return EFI_BAD_BUFFER_SIZE;
  1044. }
  1045. if (Instance->Policy != Ip4Config2PolicyStatic) {
  1046. return EFI_WRITE_PROTECTED;
  1047. }
  1048. DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
  1049. if ((Data != NULL) && (DataSize != 0)) {
  1050. NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *)Data);
  1051. StationAddress = EFI_NTOHL (NewAddress.Address);
  1052. SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);
  1053. //
  1054. // Check whether the StationAddress/SubnetMask pair is valid.
  1055. //
  1056. if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {
  1057. return EFI_INVALID_PARAMETER;
  1058. }
  1059. //
  1060. // Store the new data, and init the DataItem status to EFI_NOT_READY because
  1061. // we may have an asynchronous configuration process.
  1062. //
  1063. Ptr = AllocateCopyPool (DataSize, Data);
  1064. if (Ptr == NULL) {
  1065. return EFI_OUT_OF_RESOURCES;
  1066. }
  1067. if (DataItem->Data.Ptr != NULL) {
  1068. FreePool (DataItem->Data.Ptr);
  1069. }
  1070. DataItem->Data.Ptr = Ptr;
  1071. DataItem->DataSize = DataSize;
  1072. DataItem->Status = EFI_NOT_READY;
  1073. IpSb->Reconfig = TRUE;
  1074. Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);
  1075. DataItem->Status = Status;
  1076. if (EFI_ERROR (DataItem->Status) && (DataItem->Status != EFI_NOT_READY)) {
  1077. if (Ptr != NULL) {
  1078. FreePool (Ptr);
  1079. }
  1080. DataItem->Data.Ptr = NULL;
  1081. }
  1082. } else {
  1083. //
  1084. // DataSize is 0 and Data is NULL, clean up the manual address.
  1085. //
  1086. if (DataItem->Data.Ptr != NULL) {
  1087. FreePool (DataItem->Data.Ptr);
  1088. }
  1089. DataItem->Data.Ptr = NULL;
  1090. DataItem->DataSize = 0;
  1091. DataItem->Status = EFI_NOT_FOUND;
  1092. //
  1093. // Free the default router table and Interface, clean up the assemble table.
  1094. //
  1095. if (IpSb->DefaultInterface != NULL) {
  1096. if (IpSb->DefaultRouteTable != NULL) {
  1097. Ip4FreeRouteTable (IpSb->DefaultRouteTable);
  1098. IpSb->DefaultRouteTable = NULL;
  1099. }
  1100. Ip4CancelReceive (IpSb->DefaultInterface);
  1101. Ip4FreeInterface (IpSb->DefaultInterface, NULL);
  1102. IpSb->DefaultInterface = NULL;
  1103. }
  1104. Ip4CleanAssembleTable (&IpSb->Assemble);
  1105. //
  1106. // Create new default interface and route table.
  1107. //
  1108. IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);
  1109. if (IpIf == NULL) {
  1110. return EFI_OUT_OF_RESOURCES;
  1111. }
  1112. RouteTable = Ip4CreateRouteTable ();
  1113. if (RouteTable == NULL) {
  1114. Ip4FreeInterface (IpIf, NULL);
  1115. return EFI_OUT_OF_RESOURCES;
  1116. }
  1117. IpSb->DefaultInterface = IpIf;
  1118. InsertHeadList (&IpSb->Interfaces, &IpIf->Link);
  1119. IpSb->DefaultRouteTable = RouteTable;
  1120. Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);
  1121. //
  1122. // Reset the State to unstarted.
  1123. //
  1124. if ((IpSb->State == IP4_SERVICE_CONFIGED) || (IpSb->State == IP4_SERVICE_STARTED)) {
  1125. IpSb->State = IP4_SERVICE_UNSTARTED;
  1126. }
  1127. }
  1128. return Status;
  1129. }
  1130. /**
  1131. The work function is to set the gateway addresses manually for the EFI IPv4
  1132. network stack that is running on the communication device that this EFI IPv4
  1133. Configuration Protocol manages. It is not configurable when the policy is
  1134. Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses.
  1135. @param[in] Instance The pointer to the IP4 config2 instance data.
  1136. @param[in] DataSize The size of the buffer pointed to by Data in bytes.
  1137. @param[in] Data The data buffer to set. This points to an array of
  1138. EFI_IPv6_ADDRESS instances.
  1139. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  1140. @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
  1141. under the current policy.
  1142. @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
  1143. @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
  1144. @retval EFI_ABORTED The manual gateway addresses to be set equal the
  1145. current configuration.
  1146. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  1147. network stack was set.
  1148. **/
  1149. EFI_STATUS
  1150. Ip4Config2SetGateway (
  1151. IN IP4_CONFIG2_INSTANCE *Instance,
  1152. IN UINTN DataSize,
  1153. IN VOID *Data
  1154. )
  1155. {
  1156. IP4_SERVICE *IpSb;
  1157. IP4_CONFIG2_DATA_ITEM *DataItem;
  1158. IP4_ADDR Gateway;
  1159. UINTN Index1;
  1160. UINTN Index2;
  1161. EFI_IPv4_ADDRESS *OldGateway;
  1162. EFI_IPv4_ADDRESS *NewGateway;
  1163. UINTN OldGatewayCount;
  1164. UINTN NewGatewayCount;
  1165. BOOLEAN OneRemoved;
  1166. BOOLEAN OneAdded;
  1167. VOID *Tmp;
  1168. OldGateway = NULL;
  1169. NewGateway = NULL;
  1170. OneRemoved = FALSE;
  1171. OneAdded = FALSE;
  1172. Tmp = NULL;
  1173. if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv4_ADDRESS) != 0)) {
  1174. return EFI_BAD_BUFFER_SIZE;
  1175. }
  1176. if (Instance->Policy != Ip4Config2PolicyStatic) {
  1177. return EFI_WRITE_PROTECTED;
  1178. }
  1179. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  1180. DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];
  1181. OldGateway = DataItem->Data.Gateway;
  1182. OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);
  1183. for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {
  1184. //
  1185. // Remove the old route entry.
  1186. //
  1187. CopyMem (&Gateway, OldGateway + Index1, sizeof (IP4_ADDR));
  1188. Ip4DelRoute (
  1189. IpSb->DefaultRouteTable,
  1190. IP4_ALLZERO_ADDRESS,
  1191. IP4_ALLZERO_ADDRESS,
  1192. NTOHL (Gateway)
  1193. );
  1194. OneRemoved = TRUE;
  1195. }
  1196. if ((Data != NULL) && (DataSize != 0)) {
  1197. NewGateway = (EFI_IPv4_ADDRESS *)Data;
  1198. NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
  1199. for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
  1200. CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
  1201. if ((IpSb->DefaultInterface->SubnetMask != 0) &&
  1202. !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask))
  1203. {
  1204. return EFI_INVALID_PARAMETER;
  1205. }
  1206. for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {
  1207. if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) {
  1208. return EFI_INVALID_PARAMETER;
  1209. }
  1210. }
  1211. }
  1212. if (NewGatewayCount != OldGatewayCount) {
  1213. Tmp = AllocatePool (DataSize);
  1214. if (Tmp == NULL) {
  1215. return EFI_OUT_OF_RESOURCES;
  1216. }
  1217. } else {
  1218. Tmp = NULL;
  1219. }
  1220. for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
  1221. //
  1222. // Add the new route entry.
  1223. //
  1224. CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
  1225. Ip4AddRoute (
  1226. IpSb->DefaultRouteTable,
  1227. IP4_ALLZERO_ADDRESS,
  1228. IP4_ALLZERO_ADDRESS,
  1229. NTOHL (Gateway)
  1230. );
  1231. OneAdded = TRUE;
  1232. }
  1233. if (!OneRemoved && !OneAdded) {
  1234. DataItem->Status = EFI_SUCCESS;
  1235. return EFI_ABORTED;
  1236. } else {
  1237. if (Tmp != NULL) {
  1238. if (DataItem->Data.Ptr != NULL) {
  1239. FreePool (DataItem->Data.Ptr);
  1240. }
  1241. DataItem->Data.Ptr = Tmp;
  1242. }
  1243. CopyMem (DataItem->Data.Ptr, Data, DataSize);
  1244. DataItem->DataSize = DataSize;
  1245. DataItem->Status = EFI_SUCCESS;
  1246. }
  1247. } else {
  1248. //
  1249. // DataSize is 0 and Data is NULL, clean up the Gateway address.
  1250. //
  1251. if (DataItem->Data.Ptr != NULL) {
  1252. FreePool (DataItem->Data.Ptr);
  1253. }
  1254. DataItem->Data.Ptr = NULL;
  1255. DataItem->DataSize = 0;
  1256. DataItem->Status = EFI_NOT_FOUND;
  1257. }
  1258. return EFI_SUCCESS;
  1259. }
  1260. /**
  1261. The work function is to set the DNS server list for the EFI IPv4 network
  1262. stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL
  1263. manages. It is not configurable when the policy is Ip4Config2PolicyDhcp.
  1264. The DNS server addresses must be unicast IPv4 addresses.
  1265. @param[in] Instance The pointer to the IP4 config2 instance data.
  1266. @param[in] DataSize The size of the buffer pointed to by Data in bytes.
  1267. @param[in] Data The data buffer to set, points to an array of
  1268. EFI_IPv4_ADDRESS instances.
  1269. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
  1270. @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
  1271. under the current policy.
  1272. @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
  1273. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
  1274. @retval EFI_ABORTED The DNS server addresses to be set equal the current
  1275. configuration.
  1276. @retval EFI_SUCCESS The specified configuration data for the EFI IPv4
  1277. network stack was set.
  1278. **/
  1279. EFI_STATUS
  1280. Ip4Config2SetDnsServer (
  1281. IN IP4_CONFIG2_INSTANCE *Instance,
  1282. IN UINTN DataSize,
  1283. IN VOID *Data
  1284. )
  1285. {
  1286. EFI_STATUS Status;
  1287. IP4_CONFIG2_DATA_ITEM *Item;
  1288. Status = EFI_SUCCESS;
  1289. Item = NULL;
  1290. if (Instance->Policy != Ip4Config2PolicyStatic) {
  1291. return EFI_WRITE_PROTECTED;
  1292. }
  1293. Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
  1294. if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) {
  1295. REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE);
  1296. }
  1297. if ((Data != NULL) && (DataSize != 0)) {
  1298. Status = Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);
  1299. } else {
  1300. //
  1301. // DataSize is 0 and Data is NULL, clean up the DnsServer address.
  1302. //
  1303. if (Item->Data.Ptr != NULL) {
  1304. FreePool (Item->Data.Ptr);
  1305. }
  1306. Item->Data.Ptr = NULL;
  1307. Item->DataSize = 0;
  1308. Item->Status = EFI_NOT_FOUND;
  1309. }
  1310. return Status;
  1311. }
  1312. /**
  1313. Generate the operational state of the interface this IP4 config2 instance manages
  1314. and output in EFI_IP4_CONFIG2_INTERFACE_INFO.
  1315. @param[in] IpSb The pointer to the IP4 service binding instance.
  1316. @param[out] IfInfo The pointer to the IP4 config2 interface information structure.
  1317. **/
  1318. VOID
  1319. Ip4Config2InitIfInfo (
  1320. IN IP4_SERVICE *IpSb,
  1321. OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo
  1322. )
  1323. {
  1324. UnicodeSPrint (
  1325. IfInfo->Name,
  1326. EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE,
  1327. L"eth%d",
  1328. IpSb->Ip4Config2Instance.IfIndex
  1329. );
  1330. IfInfo->IfType = IpSb->SnpMode.IfType;
  1331. IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;
  1332. CopyMem (&IfInfo->HwAddress, &IpSb->SnpMode.CurrentAddress, IfInfo->HwAddressSize);
  1333. }
  1334. /**
  1335. Set the configuration for the EFI IPv4 network stack running on the communication
  1336. device this EFI_IP4_CONFIG2_PROTOCOL instance manages.
  1337. This function is used to set the configuration data of type DataType for the EFI
  1338. IPv4 network stack that is running on the communication device that this EFI IPv4
  1339. Configuration Protocol instance manages.
  1340. DataSize is used to calculate the count of structure instances in the Data for
  1341. a DataType in which multiple structure instances are allowed.
  1342. This function is always non-blocking. When setting some type of configuration data,
  1343. an asynchronous process is invoked to check the correctness of the data, such as
  1344. performing Duplicate Address Detection on the manually set local IPv4 addresses.
  1345. EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
  1346. is invoked, and the process is not finished yet. The caller wanting to get the result
  1347. of the asynchronous process is required to call RegisterDataNotify() to register an
  1348. event on the specified configuration data. Once the event is signaled, the caller
  1349. can call GetData() to obtain the configuration data and know the result.
  1350. For other types of configuration data that do not require an asynchronous configuration
  1351. process, the result of the operation is immediately returned.
  1352. @param[in] This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
  1353. @param[in] DataType The type of data to set.
  1354. @param[in] DataSize Size of the buffer pointed to by Data in bytes.
  1355. @param[in] Data The data buffer to set. The type of the data buffer is
  1356. associated with the DataType.
  1357. @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
  1358. network stack was set successfully.
  1359. @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
  1360. - This is NULL.
  1361. - One or more fields in Data and DataSize do not match the
  1362. requirement of the data type indicated by DataType.
  1363. @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
  1364. configuration data cannot be set under the current policy.
  1365. @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
  1366. data is already in process.
  1367. @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
  1368. configuration data, and the process is not finished yet.
  1369. @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
  1370. indicated by DataType.
  1371. @retval EFI_UNSUPPORTED This DataType is not supported.
  1372. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  1373. @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
  1374. **/
  1375. EFI_STATUS
  1376. EFIAPI
  1377. EfiIp4Config2SetData (
  1378. IN EFI_IP4_CONFIG2_PROTOCOL *This,
  1379. IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
  1380. IN UINTN DataSize,
  1381. IN VOID *Data
  1382. )
  1383. {
  1384. EFI_TPL OldTpl;
  1385. EFI_STATUS Status;
  1386. IP4_CONFIG2_INSTANCE *Instance;
  1387. IP4_SERVICE *IpSb;
  1388. if ((This == NULL) || ((Data == NULL) && (DataSize != 0)) || ((Data != NULL) && (DataSize == 0))) {
  1389. return EFI_INVALID_PARAMETER;
  1390. }
  1391. if (DataType >= Ip4Config2DataTypeMaximum) {
  1392. return EFI_UNSUPPORTED;
  1393. }
  1394. Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
  1395. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  1396. NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
  1397. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1398. Status = Instance->DataItem[DataType].Status;
  1399. if (Status != EFI_NOT_READY) {
  1400. if (Instance->DataItem[DataType].SetData == NULL) {
  1401. //
  1402. // This type of data is readonly.
  1403. //
  1404. Status = EFI_WRITE_PROTECTED;
  1405. } else {
  1406. Status = Instance->DataItem[DataType].SetData (Instance, DataSize, Data);
  1407. if (!EFI_ERROR (Status)) {
  1408. //
  1409. // Fire up the events registered with this type of data.
  1410. //
  1411. NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL);
  1412. Ip4Config2WriteConfigData (IpSb->MacString, Instance);
  1413. } else if (Status == EFI_ABORTED) {
  1414. //
  1415. // The SetData is aborted because the data to set is the same with
  1416. // the one maintained.
  1417. //
  1418. Status = EFI_SUCCESS;
  1419. NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL);
  1420. }
  1421. }
  1422. } else {
  1423. //
  1424. // Another asynchronous process is on the way.
  1425. //
  1426. Status = EFI_ACCESS_DENIED;
  1427. }
  1428. gBS->RestoreTPL (OldTpl);
  1429. return Status;
  1430. }
  1431. /**
  1432. Get the configuration data for the EFI IPv4 network stack running on the communication
  1433. device that this EFI_IP4_CONFIG2_PROTOCOL instance manages.
  1434. This function returns the configuration data of type DataType for the EFI IPv4 network
  1435. stack running on the communication device that this EFI IPv4 Configuration Protocol instance
  1436. manages.
  1437. The caller is responsible for allocating the buffer used to return the specified
  1438. configuration data. The required size will be returned to the caller if the size of
  1439. the buffer is too small.
  1440. EFI_NOT_READY is returned if the specified configuration data is not ready due to an
  1441. asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
  1442. to register an event on the specified configuration data. Once the asynchronous configuration
  1443. process is finished, the event will be signaled, and a subsequent GetData() call will return
  1444. the specified configuration data.
  1445. @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
  1446. @param[in] DataType The type of data to get.
  1447. @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
  1448. size of buffer required to store the specified configuration data.
  1449. @param[in] Data The data buffer in which the configuration data is returned. The
  1450. type of the data buffer is associated with the DataType.
  1451. This is an optional parameter that may be NULL.
  1452. @retval EFI_SUCCESS The specified configuration data was obtained successfully.
  1453. @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
  1454. - This is NULL.
  1455. - DataSize is NULL.
  1456. - Data is NULL if *DataSize is not zero.
  1457. @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
  1458. and the required size is returned in DataSize.
  1459. @retval EFI_NOT_READY The specified configuration data is not ready due to an
  1460. asynchronous configuration process already in progress.
  1461. @retval EFI_NOT_FOUND The specified configuration data is not found.
  1462. **/
  1463. EFI_STATUS
  1464. EFIAPI
  1465. EfiIp4Config2GetData (
  1466. IN EFI_IP4_CONFIG2_PROTOCOL *This,
  1467. IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
  1468. IN OUT UINTN *DataSize,
  1469. IN VOID *Data OPTIONAL
  1470. )
  1471. {
  1472. EFI_TPL OldTpl;
  1473. EFI_STATUS Status;
  1474. IP4_CONFIG2_INSTANCE *Instance;
  1475. IP4_CONFIG2_DATA_ITEM *DataItem;
  1476. if ((This == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) {
  1477. return EFI_INVALID_PARAMETER;
  1478. }
  1479. if (DataType >= Ip4Config2DataTypeMaximum) {
  1480. return EFI_NOT_FOUND;
  1481. }
  1482. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1483. Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
  1484. DataItem = &Instance->DataItem[DataType];
  1485. Status = Instance->DataItem[DataType].Status;
  1486. if (!EFI_ERROR (Status)) {
  1487. if (DataItem->GetData != NULL) {
  1488. Status = DataItem->GetData (Instance, DataSize, Data);
  1489. } else if (*DataSize < Instance->DataItem[DataType].DataSize) {
  1490. //
  1491. // Update the buffer length.
  1492. //
  1493. *DataSize = Instance->DataItem[DataType].DataSize;
  1494. Status = EFI_BUFFER_TOO_SMALL;
  1495. } else {
  1496. *DataSize = Instance->DataItem[DataType].DataSize;
  1497. CopyMem (Data, Instance->DataItem[DataType].Data.Ptr, *DataSize);
  1498. }
  1499. }
  1500. gBS->RestoreTPL (OldTpl);
  1501. return Status;
  1502. }
  1503. /**
  1504. Register an event that is signaled whenever a configuration process on the specified
  1505. configuration data is done.
  1506. This function registers an event that is to be signaled whenever a configuration
  1507. process on the specified configuration data is performed. An event can be registered
  1508. for a different DataType simultaneously. The caller is responsible for determining
  1509. which type of configuration data causes the signaling of the event in such an event.
  1510. @param[in] This Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
  1511. @param[in] DataType The type of data to unregister the event for.
  1512. @param[in] Event The event to register.
  1513. @retval EFI_SUCCESS The notification event for the specified configuration data is
  1514. registered.
  1515. @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
  1516. @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
  1517. supported.
  1518. @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
  1519. @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
  1520. **/
  1521. EFI_STATUS
  1522. EFIAPI
  1523. EfiIp4Config2RegisterDataNotify (
  1524. IN EFI_IP4_CONFIG2_PROTOCOL *This,
  1525. IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
  1526. IN EFI_EVENT Event
  1527. )
  1528. {
  1529. EFI_TPL OldTpl;
  1530. EFI_STATUS Status;
  1531. IP4_CONFIG2_INSTANCE *Instance;
  1532. NET_MAP *EventMap;
  1533. NET_MAP_ITEM *Item;
  1534. if ((This == NULL) || (Event == NULL)) {
  1535. return EFI_INVALID_PARAMETER;
  1536. }
  1537. if (DataType >= Ip4Config2DataTypeMaximum) {
  1538. return EFI_UNSUPPORTED;
  1539. }
  1540. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1541. Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
  1542. EventMap = &Instance->DataItem[DataType].EventMap;
  1543. //
  1544. // Check whether this event is already registered for this DataType.
  1545. //
  1546. Item = NetMapFindKey (EventMap, Event);
  1547. if (Item == NULL) {
  1548. Status = NetMapInsertTail (EventMap, Event, NULL);
  1549. if (EFI_ERROR (Status)) {
  1550. Status = EFI_OUT_OF_RESOURCES;
  1551. }
  1552. } else {
  1553. Status = EFI_ACCESS_DENIED;
  1554. }
  1555. gBS->RestoreTPL (OldTpl);
  1556. return Status;
  1557. }
  1558. /**
  1559. Remove a previously registered event for the specified configuration data.
  1560. @param This The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.
  1561. @param DataType The type of data to remove from the previously
  1562. registered event.
  1563. @param Event The event to be unregistered.
  1564. @retval EFI_SUCCESS The event registered for the specified
  1565. configuration data was removed.
  1566. @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
  1567. @retval EFI_NOT_FOUND The Event has not been registered for the
  1568. specified DataType.
  1569. **/
  1570. EFI_STATUS
  1571. EFIAPI
  1572. EfiIp4Config2UnregisterDataNotify (
  1573. IN EFI_IP4_CONFIG2_PROTOCOL *This,
  1574. IN EFI_IP4_CONFIG2_DATA_TYPE DataType,
  1575. IN EFI_EVENT Event
  1576. )
  1577. {
  1578. EFI_TPL OldTpl;
  1579. EFI_STATUS Status;
  1580. IP4_CONFIG2_INSTANCE *Instance;
  1581. NET_MAP_ITEM *Item;
  1582. if ((This == NULL) || (Event == NULL)) {
  1583. return EFI_INVALID_PARAMETER;
  1584. }
  1585. if (DataType >= Ip4Config2DataTypeMaximum) {
  1586. return EFI_NOT_FOUND;
  1587. }
  1588. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1589. Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);
  1590. Item = NetMapFindKey (&Instance->DataItem[DataType].EventMap, Event);
  1591. if (Item != NULL) {
  1592. NetMapRemoveItem (&Instance->DataItem[DataType].EventMap, Item, NULL);
  1593. Status = EFI_SUCCESS;
  1594. } else {
  1595. Status = EFI_NOT_FOUND;
  1596. }
  1597. gBS->RestoreTPL (OldTpl);
  1598. return Status;
  1599. }
  1600. /**
  1601. Initialize an IP4_CONFIG2_INSTANCE.
  1602. @param[out] Instance The buffer of IP4_CONFIG2_INSTANCE to be initialized.
  1603. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
  1604. @retval EFI_SUCCESS The IP4_CONFIG2_INSTANCE initialized successfully.
  1605. **/
  1606. EFI_STATUS
  1607. Ip4Config2InitInstance (
  1608. OUT IP4_CONFIG2_INSTANCE *Instance
  1609. )
  1610. {
  1611. IP4_SERVICE *IpSb;
  1612. IP4_CONFIG2_INSTANCE *TmpInstance;
  1613. LIST_ENTRY *Entry;
  1614. EFI_STATUS Status;
  1615. UINTN Index;
  1616. UINT16 IfIndex;
  1617. IP4_CONFIG2_DATA_ITEM *DataItem;
  1618. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  1619. Instance->Signature = IP4_CONFIG2_INSTANCE_SIGNATURE;
  1620. //
  1621. // Determine the index of this interface.
  1622. //
  1623. IfIndex = 0;
  1624. NET_LIST_FOR_EACH (Entry, &mIp4Config2InstanceList) {
  1625. TmpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_CONFIG2_INSTANCE, Link, IP4_CONFIG2_INSTANCE_SIGNATURE);
  1626. if (TmpInstance->IfIndex > IfIndex) {
  1627. //
  1628. // There is a sequence hole because some interface is down.
  1629. //
  1630. break;
  1631. }
  1632. IfIndex++;
  1633. }
  1634. Instance->IfIndex = IfIndex;
  1635. NetListInsertBefore (Entry, &Instance->Link);
  1636. for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {
  1637. //
  1638. // Initialize the event map for each data item.
  1639. //
  1640. NetMapInit (&Instance->DataItem[Index].EventMap);
  1641. }
  1642. //
  1643. // Initialize each data type: associate storage and set data size for the
  1644. // fixed size data types, hook the SetData function, set the data attribute.
  1645. //
  1646. DataItem = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo];
  1647. DataItem->GetData = Ip4Config2GetIfInfo;
  1648. DataItem->Data.Ptr = &Instance->InterfaceInfo;
  1649. DataItem->DataSize = sizeof (Instance->InterfaceInfo);
  1650. SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED | DATA_ATTRIB_VOLATILE);
  1651. Ip4Config2InitIfInfo (IpSb, &Instance->InterfaceInfo);
  1652. DataItem = &Instance->DataItem[Ip4Config2DataTypePolicy];
  1653. DataItem->SetData = Ip4Config2SetPolicy;
  1654. DataItem->Data.Ptr = &Instance->Policy;
  1655. DataItem->DataSize = sizeof (Instance->Policy);
  1656. Instance->Policy = Ip4Config2PolicyStatic;
  1657. SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);
  1658. DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
  1659. DataItem->SetData = Ip4Config2SetManualAddress;
  1660. DataItem->Status = EFI_NOT_FOUND;
  1661. DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];
  1662. DataItem->SetData = Ip4Config2SetGateway;
  1663. DataItem->Status = EFI_NOT_FOUND;
  1664. DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];
  1665. DataItem->SetData = Ip4Config2SetDnsServer;
  1666. DataItem->Status = EFI_NOT_FOUND;
  1667. Instance->Configured = TRUE;
  1668. //
  1669. // Try to read the config data from NV variable.
  1670. // If not found, write initialized config data into NV variable
  1671. // as a default config data.
  1672. //
  1673. Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance);
  1674. if (Status == EFI_NOT_FOUND) {
  1675. Status = Ip4Config2WriteConfigData (IpSb->MacString, Instance);
  1676. }
  1677. if (EFI_ERROR (Status)) {
  1678. return Status;
  1679. }
  1680. Instance->Ip4Config2.SetData = EfiIp4Config2SetData;
  1681. Instance->Ip4Config2.GetData = EfiIp4Config2GetData;
  1682. Instance->Ip4Config2.RegisterDataNotify = EfiIp4Config2RegisterDataNotify;
  1683. Instance->Ip4Config2.UnregisterDataNotify = EfiIp4Config2UnregisterDataNotify;
  1684. //
  1685. // Publish the IP4 configuration form
  1686. //
  1687. return Ip4Config2FormInit (Instance);
  1688. }
  1689. /**
  1690. Release an IP4_CONFIG2_INSTANCE.
  1691. @param[in, out] Instance The buffer of IP4_CONFIG2_INSTANCE to be freed.
  1692. **/
  1693. VOID
  1694. Ip4Config2CleanInstance (
  1695. IN OUT IP4_CONFIG2_INSTANCE *Instance
  1696. )
  1697. {
  1698. UINTN Index;
  1699. IP4_CONFIG2_DATA_ITEM *DataItem;
  1700. if (Instance->DeclineAddress != NULL) {
  1701. FreePool (Instance->DeclineAddress);
  1702. }
  1703. if (!Instance->Configured) {
  1704. return;
  1705. }
  1706. if (Instance->Dhcp4Handle != NULL) {
  1707. Ip4Config2DestroyDhcp4 (Instance);
  1708. }
  1709. //
  1710. // Close the event.
  1711. //
  1712. if (Instance->Dhcp4Event != NULL) {
  1713. gBS->CloseEvent (Instance->Dhcp4Event);
  1714. Instance->Dhcp4Event = NULL;
  1715. }
  1716. for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {
  1717. DataItem = &Instance->DataItem[Index];
  1718. if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {
  1719. if (DataItem->Data.Ptr != NULL) {
  1720. FreePool (DataItem->Data.Ptr);
  1721. }
  1722. DataItem->Data.Ptr = NULL;
  1723. DataItem->DataSize = 0;
  1724. }
  1725. NetMapClean (&Instance->DataItem[Index].EventMap);
  1726. }
  1727. Ip4Config2FormUnload (Instance);
  1728. RemoveEntryList (&Instance->Link);
  1729. }
  1730. /**
  1731. The event handle for IP4 auto reconfiguration. The original default
  1732. interface and route table will be removed as the default.
  1733. @param[in] Context The IP4 service binding instance.
  1734. **/
  1735. VOID
  1736. EFIAPI
  1737. Ip4AutoReconfigCallBackDpc (
  1738. IN VOID *Context
  1739. )
  1740. {
  1741. IP4_SERVICE *IpSb;
  1742. IpSb = (IP4_SERVICE *)Context;
  1743. NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
  1744. if (IpSb->State > IP4_SERVICE_UNSTARTED) {
  1745. IpSb->State = IP4_SERVICE_UNSTARTED;
  1746. }
  1747. IpSb->Reconfig = TRUE;
  1748. Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);
  1749. return;
  1750. }
  1751. /**
  1752. Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.
  1753. @param Event The event that is signalled.
  1754. @param Context The IP4 service binding instance.
  1755. **/
  1756. VOID
  1757. EFIAPI
  1758. Ip4AutoReconfigCallBack (
  1759. IN EFI_EVENT Event,
  1760. IN VOID *Context
  1761. )
  1762. {
  1763. //
  1764. // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK
  1765. //
  1766. QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context);
  1767. }