Ip4Config2Nv.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. /** @file
  2. Helper functions for configuring or getting the parameters relating to Ip4.
  3. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Ip4Impl.h"
  7. CHAR16 mIp4Config2StorageName[] = L"IP4_CONFIG2_IFR_NVDATA";
  8. /**
  9. Calculate the prefix length of the IPv4 subnet mask.
  10. @param[in] SubnetMask The IPv4 subnet mask.
  11. @return The prefix length of the subnet mask.
  12. @retval 0 Other errors as indicated.
  13. **/
  14. UINT8
  15. GetSubnetMaskPrefixLength (
  16. IN EFI_IPv4_ADDRESS *SubnetMask
  17. )
  18. {
  19. UINT8 Len;
  20. UINT32 ReverseMask;
  21. //
  22. // The SubnetMask is in network byte order.
  23. //
  24. ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);
  25. //
  26. // Reverse it.
  27. //
  28. ReverseMask = ~ReverseMask;
  29. if ((ReverseMask & (ReverseMask + 1)) != 0) {
  30. return 0;
  31. }
  32. Len = 0;
  33. while (ReverseMask != 0) {
  34. ReverseMask = ReverseMask >> 1;
  35. Len++;
  36. }
  37. return (UINT8)(32 - Len);
  38. }
  39. /**
  40. Convert the decimal dotted IPv4 address into the binary IPv4 address.
  41. @param[in] Str The UNICODE string.
  42. @param[out] Ip The storage to return the IPv4 address.
  43. @retval EFI_SUCCESS The binary IP address is returned in Ip.
  44. @retval EFI_INVALID_PARAMETER The IP string is malformatted.
  45. **/
  46. EFI_STATUS
  47. Ip4Config2StrToIp (
  48. IN CHAR16 *Str,
  49. OUT EFI_IPv4_ADDRESS *Ip
  50. )
  51. {
  52. UINTN Index;
  53. UINTN Number;
  54. Index = 0;
  55. while (*Str != L'\0') {
  56. if (Index > 3) {
  57. return EFI_INVALID_PARAMETER;
  58. }
  59. Number = 0;
  60. while ((*Str >= L'0') && (*Str <= L'9')) {
  61. Number = Number * 10 + (*Str - L'0');
  62. Str++;
  63. }
  64. if (Number > 0xFF) {
  65. return EFI_INVALID_PARAMETER;
  66. }
  67. Ip->Addr[Index] = (UINT8)Number;
  68. if ((*Str != L'\0') && (*Str != L'.')) {
  69. //
  70. // The current character should be either the NULL terminator or
  71. // the dot delimiter.
  72. //
  73. return EFI_INVALID_PARAMETER;
  74. }
  75. if (*Str == L'.') {
  76. //
  77. // Skip the delimiter.
  78. //
  79. Str++;
  80. }
  81. Index++;
  82. }
  83. if (Index != 4) {
  84. return EFI_INVALID_PARAMETER;
  85. }
  86. return EFI_SUCCESS;
  87. }
  88. /**
  89. Convert the decimal dotted IPv4 addresses separated by space into the binary IPv4 address list.
  90. @param[in] Str The UNICODE string contains IPv4 addresses.
  91. @param[out] PtrIpList The storage to return the IPv4 address list.
  92. @param[out] IpCount The size of the IPv4 address list.
  93. @retval EFI_SUCCESS The binary IP address list is returned in PtrIpList.
  94. @retval EFI_OUT_OF_RESOURCES Error occurs in allocating memory.
  95. @retval EFI_INVALID_PARAMETER The IP string is malformatted.
  96. **/
  97. EFI_STATUS
  98. Ip4Config2StrToIpList (
  99. IN CHAR16 *Str,
  100. OUT EFI_IPv4_ADDRESS **PtrIpList,
  101. OUT UINTN *IpCount
  102. )
  103. {
  104. UINTN BeginIndex;
  105. UINTN EndIndex;
  106. UINTN Index;
  107. UINTN IpIndex;
  108. CHAR16 *StrTemp;
  109. BOOLEAN SpaceTag;
  110. BeginIndex = 0;
  111. EndIndex = BeginIndex;
  112. Index = 0;
  113. IpIndex = 0;
  114. StrTemp = NULL;
  115. SpaceTag = TRUE;
  116. *PtrIpList = NULL;
  117. *IpCount = 0;
  118. if (Str == NULL) {
  119. return EFI_SUCCESS;
  120. }
  121. //
  122. // Get the number of Ip.
  123. //
  124. while (*(Str + Index) != L'\0') {
  125. if (*(Str + Index) == L' ') {
  126. SpaceTag = TRUE;
  127. } else {
  128. if (SpaceTag) {
  129. (*IpCount)++;
  130. SpaceTag = FALSE;
  131. }
  132. }
  133. Index++;
  134. }
  135. if (*IpCount == 0) {
  136. return EFI_SUCCESS;
  137. }
  138. //
  139. // Allocate buffer for IpList.
  140. //
  141. *PtrIpList = AllocateZeroPool (*IpCount * sizeof (EFI_IPv4_ADDRESS));
  142. if (*PtrIpList == NULL) {
  143. return EFI_OUT_OF_RESOURCES;
  144. }
  145. //
  146. // Get IpList from Str.
  147. //
  148. Index = 0;
  149. while (*(Str + Index) != L'\0') {
  150. if (*(Str + Index) == L' ') {
  151. if (!SpaceTag) {
  152. StrTemp = AllocateZeroPool ((EndIndex - BeginIndex + 1) * sizeof (CHAR16));
  153. if (StrTemp == NULL) {
  154. FreePool (*PtrIpList);
  155. *PtrIpList = NULL;
  156. *IpCount = 0;
  157. return EFI_OUT_OF_RESOURCES;
  158. }
  159. CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof (CHAR16));
  160. *(StrTemp + (EndIndex - BeginIndex)) = L'\0';
  161. if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {
  162. FreePool (StrTemp);
  163. FreePool (*PtrIpList);
  164. *PtrIpList = NULL;
  165. *IpCount = 0;
  166. return EFI_INVALID_PARAMETER;
  167. }
  168. BeginIndex = EndIndex;
  169. IpIndex++;
  170. FreePool (StrTemp);
  171. }
  172. BeginIndex++;
  173. EndIndex++;
  174. SpaceTag = TRUE;
  175. } else {
  176. EndIndex++;
  177. SpaceTag = FALSE;
  178. }
  179. Index++;
  180. if (*(Str + Index) == L'\0') {
  181. if (!SpaceTag) {
  182. StrTemp = AllocateZeroPool ((EndIndex - BeginIndex + 1) * sizeof (CHAR16));
  183. if (StrTemp == NULL) {
  184. FreePool (*PtrIpList);
  185. *PtrIpList = NULL;
  186. *IpCount = 0;
  187. return EFI_OUT_OF_RESOURCES;
  188. }
  189. CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof (CHAR16));
  190. *(StrTemp + (EndIndex - BeginIndex)) = L'\0';
  191. if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {
  192. FreePool (StrTemp);
  193. FreePool (*PtrIpList);
  194. *PtrIpList = NULL;
  195. *IpCount = 0;
  196. return EFI_INVALID_PARAMETER;
  197. }
  198. FreePool (StrTemp);
  199. }
  200. }
  201. }
  202. return EFI_SUCCESS;
  203. }
  204. /**
  205. Convert the IPv4 address into a dotted string.
  206. @param[in] Ip The IPv4 address.
  207. @param[out] Str The dotted IP string.
  208. **/
  209. VOID
  210. Ip4Config2IpToStr (
  211. IN EFI_IPv4_ADDRESS *Ip,
  212. OUT CHAR16 *Str
  213. )
  214. {
  215. UnicodeSPrint (
  216. Str,
  217. 2 * IP4_STR_MAX_SIZE,
  218. L"%d.%d.%d.%d",
  219. Ip->Addr[0],
  220. Ip->Addr[1],
  221. Ip->Addr[2],
  222. Ip->Addr[3]
  223. );
  224. }
  225. /**
  226. Convert the IPv4 address list into string consists of several decimal
  227. dotted IPv4 addresses separated by space.
  228. @param[in] Ip The IPv4 address list.
  229. @param[in] IpCount The size of IPv4 address list.
  230. @param[out] Str The string contains several decimal dotted
  231. IPv4 addresses separated by space.
  232. @retval EFI_SUCCESS Operation is success.
  233. @retval EFI_OUT_OF_RESOURCES Error occurs in allocating memory.
  234. **/
  235. EFI_STATUS
  236. Ip4Config2IpListToStr (
  237. IN EFI_IPv4_ADDRESS *Ip,
  238. IN UINTN IpCount,
  239. OUT CHAR16 *Str
  240. )
  241. {
  242. UINTN Index;
  243. UINTN TemIndex;
  244. UINTN StrIndex;
  245. CHAR16 *TempStr;
  246. EFI_IPv4_ADDRESS *TempIp;
  247. Index = 0;
  248. TemIndex = 0;
  249. StrIndex = 0;
  250. TempStr = NULL;
  251. TempIp = NULL;
  252. for (Index = 0; Index < IpCount; Index++) {
  253. TempIp = Ip + Index;
  254. if (TempStr == NULL) {
  255. TempStr = AllocateZeroPool (2 * IP4_STR_MAX_SIZE);
  256. if (TempStr == NULL) {
  257. return EFI_OUT_OF_RESOURCES;
  258. }
  259. }
  260. UnicodeSPrint (
  261. TempStr,
  262. 2 * IP4_STR_MAX_SIZE,
  263. L"%d.%d.%d.%d",
  264. TempIp->Addr[0],
  265. TempIp->Addr[1],
  266. TempIp->Addr[2],
  267. TempIp->Addr[3]
  268. );
  269. for (TemIndex = 0; TemIndex < IP4_STR_MAX_SIZE; TemIndex++) {
  270. if (*(TempStr + TemIndex) == L'\0') {
  271. if (Index == IpCount - 1) {
  272. Str[StrIndex++] = L'\0';
  273. } else {
  274. Str[StrIndex++] = L' ';
  275. }
  276. break;
  277. } else {
  278. Str[StrIndex++] = *(TempStr + TemIndex);
  279. }
  280. }
  281. }
  282. if (TempStr != NULL) {
  283. FreePool (TempStr);
  284. }
  285. return EFI_SUCCESS;
  286. }
  287. /**
  288. The notify function of create event when performing a manual configuration.
  289. @param[in] Event The pointer of Event.
  290. @param[in] Context The pointer of Context.
  291. **/
  292. VOID
  293. EFIAPI
  294. Ip4Config2ManualAddressNotify (
  295. IN EFI_EVENT Event,
  296. IN VOID *Context
  297. )
  298. {
  299. *((BOOLEAN *)Context) = TRUE;
  300. }
  301. /**
  302. Convert the network configuration data into the IFR data.
  303. @param[in] Instance The IP4 config2 instance.
  304. @param[in, out] IfrNvData The IFR nv data.
  305. @retval EFI_SUCCESS The configure parameter to IFR data was
  306. set successfully.
  307. @retval EFI_INVALID_PARAMETER Source instance or target IFR data is not available.
  308. @retval Others Other errors as indicated.
  309. **/
  310. EFI_STATUS
  311. Ip4Config2ConvertConfigNvDataToIfrNvData (
  312. IN IP4_CONFIG2_INSTANCE *Instance,
  313. IN OUT IP4_CONFIG2_IFR_NVDATA *IfrNvData
  314. )
  315. {
  316. IP4_SERVICE *IpSb;
  317. EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
  318. EFI_IP4_CONFIG2_INTERFACE_INFO *Ip4Info;
  319. EFI_IP4_CONFIG2_POLICY Policy;
  320. UINTN DataSize;
  321. UINTN GatewaySize;
  322. EFI_IPv4_ADDRESS GatewayAddress;
  323. EFI_STATUS Status;
  324. UINTN DnsSize;
  325. UINTN DnsCount;
  326. EFI_IPv4_ADDRESS *DnsAddress;
  327. Status = EFI_SUCCESS;
  328. Ip4Config2 = &Instance->Ip4Config2;
  329. Ip4Info = NULL;
  330. DnsAddress = NULL;
  331. GatewaySize = sizeof (EFI_IPv4_ADDRESS);
  332. if ((IfrNvData == NULL) || (Instance == NULL)) {
  333. return EFI_INVALID_PARAMETER;
  334. }
  335. NET_CHECK_SIGNATURE (Instance, IP4_CONFIG2_INSTANCE_SIGNATURE);
  336. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  337. if (IpSb->DefaultInterface->Configured) {
  338. IfrNvData->Configure = 1;
  339. } else {
  340. IfrNvData->Configure = 0;
  341. goto Exit;
  342. }
  343. //
  344. // Get the Policy info.
  345. //
  346. DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
  347. Status = Ip4Config2->GetData (
  348. Ip4Config2,
  349. Ip4Config2DataTypePolicy,
  350. &DataSize,
  351. &Policy
  352. );
  353. if (EFI_ERROR (Status)) {
  354. goto Exit;
  355. }
  356. if (Policy == Ip4Config2PolicyStatic) {
  357. IfrNvData->DhcpEnable = FALSE;
  358. } else if (Policy == Ip4Config2PolicyDhcp) {
  359. IfrNvData->DhcpEnable = TRUE;
  360. goto Exit;
  361. }
  362. //
  363. // Get the interface info.
  364. //
  365. DataSize = 0;
  366. Status = Ip4Config2->GetData (
  367. Ip4Config2,
  368. Ip4Config2DataTypeInterfaceInfo,
  369. &DataSize,
  370. NULL
  371. );
  372. if (Status != EFI_BUFFER_TOO_SMALL) {
  373. return Status;
  374. }
  375. Ip4Info = AllocateZeroPool (DataSize);
  376. if (Ip4Info == NULL) {
  377. Status = EFI_OUT_OF_RESOURCES;
  378. return Status;
  379. }
  380. Status = Ip4Config2->GetData (
  381. Ip4Config2,
  382. Ip4Config2DataTypeInterfaceInfo,
  383. &DataSize,
  384. Ip4Info
  385. );
  386. if (EFI_ERROR (Status)) {
  387. goto Exit;
  388. }
  389. //
  390. // Get the Gateway info.
  391. //
  392. Status = Ip4Config2->GetData (
  393. Ip4Config2,
  394. Ip4Config2DataTypeGateway,
  395. &GatewaySize,
  396. &GatewayAddress
  397. );
  398. if (EFI_ERROR (Status)) {
  399. goto Exit;
  400. }
  401. //
  402. // Get the Dns info.
  403. //
  404. DnsSize = 0;
  405. Status = Ip4Config2->GetData (
  406. Ip4Config2,
  407. Ip4Config2DataTypeDnsServer,
  408. &DnsSize,
  409. NULL
  410. );
  411. if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
  412. goto Exit;
  413. }
  414. DnsCount = (UINT32)(DnsSize / sizeof (EFI_IPv4_ADDRESS));
  415. if (DnsSize > 0) {
  416. DnsAddress = AllocateZeroPool (DnsSize);
  417. if (DnsAddress == NULL) {
  418. Status = EFI_OUT_OF_RESOURCES;
  419. goto Exit;
  420. }
  421. Status = Ip4Config2->GetData (
  422. Ip4Config2,
  423. Ip4Config2DataTypeDnsServer,
  424. &DnsSize,
  425. DnsAddress
  426. );
  427. if (EFI_ERROR (Status)) {
  428. goto Exit;
  429. }
  430. }
  431. Ip4Config2IpToStr (&Ip4Info->StationAddress, IfrNvData->StationAddress);
  432. Ip4Config2IpToStr (&Ip4Info->SubnetMask, IfrNvData->SubnetMask);
  433. Ip4Config2IpToStr (&GatewayAddress, IfrNvData->GatewayAddress);
  434. Status = Ip4Config2IpListToStr (DnsAddress, DnsCount, IfrNvData->DnsAddress);
  435. Exit:
  436. if (DnsAddress != NULL) {
  437. FreePool (DnsAddress);
  438. }
  439. if (Ip4Info != NULL) {
  440. FreePool (Ip4Info);
  441. }
  442. return Status;
  443. }
  444. /**
  445. Convert the IFR data into the network configuration data and set the IP
  446. configure parameters for the NIC.
  447. @param[in] IfrFormNvData The IFR NV data.
  448. @param[in, out] Instance The IP4 config2 instance.
  449. @retval EFI_SUCCESS The configure parameter for this NIC was
  450. set successfully.
  451. @retval EFI_INVALID_PARAMETER The address information for setting is invalid.
  452. @retval Others Other errors as indicated.
  453. **/
  454. EFI_STATUS
  455. Ip4Config2ConvertIfrNvDataToConfigNvData (
  456. IN IP4_CONFIG2_IFR_NVDATA *IfrFormNvData,
  457. IN OUT IP4_CONFIG2_INSTANCE *Instance
  458. )
  459. {
  460. EFI_STATUS Status;
  461. EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
  462. IP4_CONFIG2_NVDATA *Ip4NvData;
  463. EFI_IP_ADDRESS StationAddress;
  464. EFI_IP_ADDRESS SubnetMask;
  465. EFI_IP_ADDRESS Gateway;
  466. IP4_ADDR Ip;
  467. EFI_IPv4_ADDRESS *DnsAddress;
  468. UINTN DnsCount;
  469. UINTN Index;
  470. EFI_EVENT TimeoutEvent;
  471. EFI_EVENT SetAddressEvent;
  472. BOOLEAN IsAddressOk;
  473. UINTN DataSize;
  474. EFI_INPUT_KEY Key;
  475. Status = EFI_SUCCESS;
  476. Ip4Cfg2 = &Instance->Ip4Config2;
  477. Ip4NvData = &Instance->Ip4NvData;
  478. DnsCount = 0;
  479. DnsAddress = NULL;
  480. TimeoutEvent = NULL;
  481. SetAddressEvent = NULL;
  482. if ((Instance == NULL) || (IfrFormNvData == NULL)) {
  483. return EFI_INVALID_PARAMETER;
  484. }
  485. if (IfrFormNvData->Configure != TRUE) {
  486. return EFI_SUCCESS;
  487. }
  488. if (IfrFormNvData->DhcpEnable == TRUE) {
  489. Ip4NvData->Policy = Ip4Config2PolicyDhcp;
  490. Status = Ip4Cfg2->SetData (
  491. Ip4Cfg2,
  492. Ip4Config2DataTypePolicy,
  493. sizeof (EFI_IP4_CONFIG2_POLICY),
  494. &Ip4NvData->Policy
  495. );
  496. if (EFI_ERROR (Status)) {
  497. return Status;
  498. }
  499. } else {
  500. //
  501. // Get Ip4NvData from IfrFormNvData if it is valid.
  502. //
  503. Ip4NvData->Policy = Ip4Config2PolicyStatic;
  504. Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
  505. if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
  506. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
  507. return EFI_INVALID_PARAMETER;
  508. }
  509. Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);
  510. if (EFI_ERROR (Status) ||
  511. ((SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) ||
  512. !Ip4StationAddressValid (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0])))
  513. {
  514. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
  515. return EFI_INVALID_PARAMETER;
  516. }
  517. Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
  518. if (EFI_ERROR (Status) ||
  519. ((Gateway.Addr[0] != 0) && (SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (SubnetMask.Addr[0]))))
  520. {
  521. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
  522. return EFI_INVALID_PARAMETER;
  523. }
  524. Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);
  525. if (!EFI_ERROR (Status) && (DnsCount > 0)) {
  526. for (Index = 0; Index < DnsCount; Index++) {
  527. CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));
  528. if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
  529. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
  530. FreePool (DnsAddress);
  531. return EFI_INVALID_PARAMETER;
  532. }
  533. }
  534. } else {
  535. if (EFI_ERROR (Status)) {
  536. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
  537. }
  538. }
  539. if (Ip4NvData->ManualAddress != NULL) {
  540. FreePool (Ip4NvData->ManualAddress);
  541. }
  542. Ip4NvData->ManualAddressCount = 1;
  543. Ip4NvData->ManualAddress = AllocateZeroPool (sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS));
  544. if (Ip4NvData->ManualAddress == NULL) {
  545. if (DnsAddress != NULL) {
  546. FreePool (DnsAddress);
  547. }
  548. return EFI_OUT_OF_RESOURCES;
  549. }
  550. CopyMem (&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof (EFI_IPv4_ADDRESS));
  551. CopyMem (&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
  552. if (Ip4NvData->GatewayAddress != NULL) {
  553. FreePool (Ip4NvData->GatewayAddress);
  554. }
  555. Ip4NvData->GatewayAddressCount = 1;
  556. Ip4NvData->GatewayAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
  557. if (Ip4NvData->GatewayAddress == NULL) {
  558. if (DnsAddress != NULL) {
  559. FreePool (DnsAddress);
  560. }
  561. return EFI_OUT_OF_RESOURCES;
  562. }
  563. CopyMem (Ip4NvData->GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
  564. if (Ip4NvData->DnsAddress != NULL) {
  565. FreePool (Ip4NvData->DnsAddress);
  566. }
  567. Ip4NvData->DnsAddressCount = (UINT32)DnsCount;
  568. Ip4NvData->DnsAddress = DnsAddress;
  569. //
  570. // Setting Ip4NvData.
  571. //
  572. Status = Ip4Cfg2->SetData (
  573. Ip4Cfg2,
  574. Ip4Config2DataTypePolicy,
  575. sizeof (EFI_IP4_CONFIG2_POLICY),
  576. &Ip4NvData->Policy
  577. );
  578. if (EFI_ERROR (Status)) {
  579. return Status;
  580. }
  581. //
  582. // Create events & timers for asynchronous settings.
  583. //
  584. Status = gBS->CreateEvent (
  585. EVT_TIMER,
  586. TPL_CALLBACK,
  587. NULL,
  588. NULL,
  589. &TimeoutEvent
  590. );
  591. if (EFI_ERROR (Status)) {
  592. return EFI_OUT_OF_RESOURCES;
  593. }
  594. Status = gBS->CreateEvent (
  595. EVT_NOTIFY_SIGNAL,
  596. TPL_NOTIFY,
  597. Ip4Config2ManualAddressNotify,
  598. &IsAddressOk,
  599. &SetAddressEvent
  600. );
  601. if (EFI_ERROR (Status)) {
  602. goto Exit;
  603. }
  604. IsAddressOk = FALSE;
  605. Status = Ip4Cfg2->RegisterDataNotify (
  606. Ip4Cfg2,
  607. Ip4Config2DataTypeManualAddress,
  608. SetAddressEvent
  609. );
  610. if (EFI_ERROR (Status)) {
  611. goto Exit;
  612. }
  613. //
  614. // Set ManualAddress.
  615. //
  616. DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
  617. Status = Ip4Cfg2->SetData (
  618. Ip4Cfg2,
  619. Ip4Config2DataTypeManualAddress,
  620. DataSize,
  621. (VOID *)Ip4NvData->ManualAddress
  622. );
  623. if (Status == EFI_NOT_READY) {
  624. gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);
  625. while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
  626. if (IsAddressOk) {
  627. Status = EFI_SUCCESS;
  628. break;
  629. }
  630. }
  631. }
  632. Ip4Cfg2->UnregisterDataNotify (
  633. Ip4Cfg2,
  634. Ip4Config2DataTypeManualAddress,
  635. SetAddressEvent
  636. );
  637. if (EFI_ERROR (Status)) {
  638. goto Exit;
  639. }
  640. //
  641. // Set gateway.
  642. //
  643. DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS);
  644. Status = Ip4Cfg2->SetData (
  645. Ip4Cfg2,
  646. Ip4Config2DataTypeGateway,
  647. DataSize,
  648. Ip4NvData->GatewayAddress
  649. );
  650. if (EFI_ERROR (Status)) {
  651. goto Exit;
  652. }
  653. //
  654. // Set DNS addresses.
  655. //
  656. if ((Ip4NvData->DnsAddressCount > 0) && (Ip4NvData->DnsAddress != NULL)) {
  657. DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS);
  658. Status = Ip4Cfg2->SetData (
  659. Ip4Cfg2,
  660. Ip4Config2DataTypeDnsServer,
  661. DataSize,
  662. Ip4NvData->DnsAddress
  663. );
  664. if (EFI_ERROR (Status)) {
  665. goto Exit;
  666. }
  667. }
  668. }
  669. Exit:
  670. if (SetAddressEvent != NULL) {
  671. gBS->CloseEvent (SetAddressEvent);
  672. }
  673. if (TimeoutEvent != NULL) {
  674. gBS->CloseEvent (TimeoutEvent);
  675. }
  676. return Status;
  677. }
  678. /**
  679. This function allows the caller to request the current
  680. configuration for one or more named elements. The resulting
  681. string is in <ConfigAltResp> format. Any and all alternative
  682. configuration strings shall also be appended to the end of the
  683. current configuration string. If they are, they must appear
  684. after the current configuration. They must contain the same
  685. routing (GUID, NAME, PATH) as the current configuration string.
  686. They must have an additional description indicating the type of
  687. alternative configuration the string represents,
  688. "ALTCFG=<StringToken>". That <StringToken> (when
  689. converted from Hex UNICODE to binary) is a reference to a
  690. string in the associated string pack.
  691. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  692. @param[in] Request A null-terminated Unicode string in
  693. <ConfigRequest> format. Note that this
  694. includes the routing information as well as
  695. the configurable name / value pairs. It is
  696. invalid for this string to be in
  697. <MultiConfigRequest> format.
  698. @param[out] Progress On return, points to a character in the
  699. Request string. Points to the string's null
  700. terminator if request was successful. Points
  701. to the most recent "&" before the first
  702. failing name / value pair (or the beginning
  703. of the string if the failure is in the first
  704. name / value pair) if the request was not
  705. successful.
  706. @param[out] Results A null-terminated Unicode string in
  707. <ConfigAltResp> format which has all values
  708. filled in for the names in the Request string.
  709. String to be allocated by the called function.
  710. @retval EFI_SUCCESS The Results string is filled with the
  711. values corresponding to all requested
  712. names.
  713. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
  714. parts of the results that must be
  715. stored awaiting possible future
  716. protocols.
  717. @retval EFI_NOT_FOUND Routing data doesn't match any
  718. known driver. Progress set to the
  719. first character in the routing header.
  720. Note: There is no requirement that the
  721. driver validate the routing data. It
  722. must skip the <ConfigHdr> in order to
  723. process the names.
  724. @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
  725. to most recent & before the
  726. error or the beginning of the
  727. string.
  728. @retval EFI_INVALID_PARAMETER Unknown name. Progress points
  729. to the & before the name in
  730. question.Currently not implemented.
  731. **/
  732. EFI_STATUS
  733. EFIAPI
  734. Ip4FormExtractConfig (
  735. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  736. IN CONST EFI_STRING Request,
  737. OUT EFI_STRING *Progress,
  738. OUT EFI_STRING *Results
  739. )
  740. {
  741. EFI_STATUS Status;
  742. IP4_CONFIG2_INSTANCE *Ip4Config2Instance;
  743. IP4_FORM_CALLBACK_INFO *Private;
  744. IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
  745. EFI_STRING ConfigRequestHdr;
  746. EFI_STRING ConfigRequest;
  747. BOOLEAN AllocatedRequest;
  748. EFI_STRING FormResult;
  749. UINTN Size;
  750. UINTN BufferSize;
  751. if ((Progress == NULL) || (Results == NULL)) {
  752. return EFI_INVALID_PARAMETER;
  753. }
  754. Status = EFI_SUCCESS;
  755. IfrFormNvData = NULL;
  756. ConfigRequest = NULL;
  757. FormResult = NULL;
  758. Size = 0;
  759. AllocatedRequest = FALSE;
  760. ConfigRequest = Request;
  761. Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
  762. Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
  763. BufferSize = sizeof (IP4_CONFIG2_IFR_NVDATA);
  764. *Progress = Request;
  765. //
  766. // Check Request data in <ConfigHdr>.
  767. //
  768. if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
  769. IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
  770. if (IfrFormNvData == NULL) {
  771. return EFI_OUT_OF_RESOURCES;
  772. }
  773. Ip4Config2ConvertConfigNvDataToIfrNvData (Ip4Config2Instance, IfrFormNvData);
  774. if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
  775. //
  776. // Request has no request element, construct full request string.
  777. // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
  778. // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
  779. //
  780. ConfigRequestHdr = HiiConstructConfigHdr (&gIp4Config2NvDataGuid, mIp4Config2StorageName, Private->ChildHandle);
  781. Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
  782. ConfigRequest = AllocateZeroPool (Size);
  783. if (ConfigRequest == NULL) {
  784. Status = EFI_OUT_OF_RESOURCES;
  785. goto Failure;
  786. }
  787. AllocatedRequest = TRUE;
  788. UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
  789. FreePool (ConfigRequestHdr);
  790. }
  791. //
  792. // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
  793. //
  794. Status = gHiiConfigRouting->BlockToConfig (
  795. gHiiConfigRouting,
  796. ConfigRequest,
  797. (UINT8 *)IfrFormNvData,
  798. BufferSize,
  799. &FormResult,
  800. Progress
  801. );
  802. FreePool (IfrFormNvData);
  803. //
  804. // Free the allocated config request string.
  805. //
  806. if (AllocatedRequest) {
  807. FreePool (ConfigRequest);
  808. ConfigRequest = NULL;
  809. }
  810. if (EFI_ERROR (Status)) {
  811. goto Failure;
  812. }
  813. }
  814. if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
  815. *Results = FormResult;
  816. } else {
  817. return EFI_NOT_FOUND;
  818. }
  819. Failure:
  820. //
  821. // Set Progress string to the original request string.
  822. //
  823. if (Request == NULL) {
  824. *Progress = NULL;
  825. } else if (StrStr (Request, L"OFFSET") == NULL) {
  826. *Progress = Request + StrLen (Request);
  827. }
  828. return Status;
  829. }
  830. /**
  831. This function applies changes in a driver's configuration.
  832. Input is a Configuration, which has the routing data for this
  833. driver followed by name / value configuration pairs. The driver
  834. must apply those pairs to its configurable storage. If the
  835. driver's configuration is stored in a linear block of data
  836. and the driver's name / value pairs are in <BlockConfig>
  837. format, it may use the ConfigToBlock helper function (above) to
  838. simplify the job. Currently not implemented.
  839. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  840. @param[in] Configuration A null-terminated Unicode string in
  841. <ConfigString> format.
  842. @param[out] Progress A pointer to a string filled in with the
  843. offset of the most recent '&' before the
  844. first failing name / value pair (or the
  845. beginning of the string if the failure
  846. is in the first name / value pair) or
  847. the terminating NULL if all was
  848. successful.
  849. @retval EFI_SUCCESS The results have been distributed or are
  850. awaiting distribution.
  851. @retval EFI_OUT_OF_MEMORY Not enough memory to store the
  852. parts of the results that must be
  853. stored awaiting possible future
  854. protocols.
  855. @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
  856. Results parameter would result
  857. in this type of error.
  858. @retval EFI_NOT_FOUND Target for the specified routing data
  859. was not found.
  860. **/
  861. EFI_STATUS
  862. EFIAPI
  863. Ip4FormRouteConfig (
  864. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  865. IN CONST EFI_STRING Configuration,
  866. OUT EFI_STRING *Progress
  867. )
  868. {
  869. EFI_STATUS Status;
  870. UINTN BufferSize;
  871. IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
  872. IP4_CONFIG2_INSTANCE *Ip4Config2Instance;
  873. IP4_FORM_CALLBACK_INFO *Private;
  874. Status = EFI_SUCCESS;
  875. IfrFormNvData = NULL;
  876. if ((Configuration == NULL) || (Progress == NULL)) {
  877. return EFI_INVALID_PARAMETER;
  878. }
  879. *Progress = Configuration;
  880. Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
  881. Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
  882. //
  883. // Check Routing data in <ConfigHdr>.
  884. //
  885. if (HiiIsConfigHdrMatch (Configuration, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {
  886. //
  887. // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
  888. //
  889. IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
  890. if (IfrFormNvData == NULL) {
  891. return EFI_OUT_OF_RESOURCES;
  892. }
  893. BufferSize = 0;
  894. Status = gHiiConfigRouting->ConfigToBlock (
  895. gHiiConfigRouting,
  896. Configuration,
  897. (UINT8 *)IfrFormNvData,
  898. &BufferSize,
  899. Progress
  900. );
  901. if (Status != EFI_BUFFER_TOO_SMALL) {
  902. return Status;
  903. }
  904. Status = gHiiConfigRouting->ConfigToBlock (
  905. gHiiConfigRouting,
  906. Configuration,
  907. (UINT8 *)IfrFormNvData,
  908. &BufferSize,
  909. Progress
  910. );
  911. if (!EFI_ERROR (Status)) {
  912. Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Ip4Config2Instance);
  913. }
  914. FreePool (IfrFormNvData);
  915. } else {
  916. return EFI_NOT_FOUND;
  917. }
  918. return Status;
  919. }
  920. /**
  921. This function is called to provide results data to the driver.
  922. This data consists of a unique key that is used to identify
  923. which data is either being passed back or being asked for.
  924. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  925. @param[in] Action Specifies the type of action taken by the browser.
  926. @param[in] QuestionId A unique value which is sent to the original
  927. exporting driver so that it can identify the type
  928. of data to expect. The format of the data tends to
  929. vary based on the opcode that enerated the callback.
  930. @param[in] Type The type of value for the question.
  931. @param[in] Value A pointer to the data being sent to the original
  932. exporting driver.
  933. @param[out] ActionRequest On return, points to the action requested by the
  934. callback function.
  935. @retval EFI_SUCCESS The callback successfully handled the action.
  936. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
  937. variable and its data.
  938. @retval EFI_DEVICE_ERROR The variable could not be saved.
  939. @retval EFI_UNSUPPORTED The specified Action is not supported by the
  940. callback. Currently not implemented.
  941. @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
  942. @retval Others Other errors as indicated.
  943. **/
  944. EFI_STATUS
  945. EFIAPI
  946. Ip4FormCallback (
  947. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  948. IN EFI_BROWSER_ACTION Action,
  949. IN EFI_QUESTION_ID QuestionId,
  950. IN UINT8 Type,
  951. IN EFI_IFR_TYPE_VALUE *Value,
  952. OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
  953. )
  954. {
  955. EFI_STATUS Status;
  956. IP4_CONFIG2_INSTANCE *Instance;
  957. IP4_CONFIG2_IFR_NVDATA *IfrFormNvData;
  958. IP4_FORM_CALLBACK_INFO *Private;
  959. EFI_IP_ADDRESS StationAddress;
  960. EFI_IP_ADDRESS SubnetMask;
  961. EFI_IP_ADDRESS Gateway;
  962. IP4_ADDR Ip;
  963. EFI_IPv4_ADDRESS *DnsAddress;
  964. UINTN DnsCount;
  965. UINTN Index;
  966. EFI_INPUT_KEY Key;
  967. IfrFormNvData = NULL;
  968. DnsCount = 0;
  969. DnsAddress = NULL;
  970. if (Action == EFI_BROWSER_ACTION_CHANGED) {
  971. Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
  972. Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private);
  973. IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));
  974. if (IfrFormNvData == NULL) {
  975. return EFI_OUT_OF_RESOURCES;
  976. }
  977. //
  978. // Retrieve uncommitted data from Browser
  979. //
  980. if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *)IfrFormNvData)) {
  981. FreePool (IfrFormNvData);
  982. return EFI_NOT_FOUND;
  983. }
  984. Status = EFI_SUCCESS;
  985. switch (QuestionId) {
  986. case KEY_LOCAL_IP:
  987. Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);
  988. if (EFI_ERROR (Status) || IP4_IS_UNSPECIFIED (NTOHL (StationAddress.Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (StationAddress.Addr[0]))) {
  989. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
  990. Status = EFI_INVALID_PARAMETER;
  991. }
  992. break;
  993. case KEY_SUBNET_MASK:
  994. Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
  995. if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
  996. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
  997. Status = EFI_INVALID_PARAMETER;
  998. }
  999. break;
  1000. case KEY_GATE_WAY:
  1001. Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
  1002. if (EFI_ERROR (Status) || IP4_IS_LOCAL_BROADCAST (NTOHL (Gateway.Addr[0]))) {
  1003. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
  1004. Status = EFI_INVALID_PARAMETER;
  1005. }
  1006. break;
  1007. case KEY_DNS:
  1008. Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);
  1009. if (!EFI_ERROR (Status) && (DnsCount > 0)) {
  1010. for (Index = 0; Index < DnsCount; Index++) {
  1011. CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));
  1012. if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
  1013. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
  1014. Status = EFI_INVALID_PARAMETER;
  1015. break;
  1016. }
  1017. }
  1018. } else {
  1019. if (EFI_ERROR (Status)) {
  1020. CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);
  1021. }
  1022. }
  1023. if (DnsAddress != NULL) {
  1024. FreePool (DnsAddress);
  1025. }
  1026. break;
  1027. case KEY_SAVE_CHANGES:
  1028. Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance);
  1029. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
  1030. break;
  1031. default:
  1032. break;
  1033. }
  1034. FreePool (IfrFormNvData);
  1035. return Status;
  1036. }
  1037. //
  1038. // All other action return unsupported.
  1039. //
  1040. return EFI_UNSUPPORTED;
  1041. }
  1042. /**
  1043. Install HII Config Access protocol for network device and allocate resource.
  1044. @param[in, out] Instance The IP4 config2 Instance.
  1045. @retval EFI_SUCCESS The HII Config Access protocol is installed.
  1046. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  1047. @retval Others Other errors as indicated.
  1048. **/
  1049. EFI_STATUS
  1050. Ip4Config2FormInit (
  1051. IN OUT IP4_CONFIG2_INSTANCE *Instance
  1052. )
  1053. {
  1054. EFI_STATUS Status;
  1055. IP4_SERVICE *IpSb;
  1056. IP4_FORM_CALLBACK_INFO *CallbackInfo;
  1057. EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
  1058. VENDOR_DEVICE_PATH VendorDeviceNode;
  1059. EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
  1060. CHAR16 *MacString;
  1061. CHAR16 MenuString[128];
  1062. CHAR16 PortString[128];
  1063. CHAR16 *OldMenuString;
  1064. EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
  1065. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  1066. ASSERT (IpSb != NULL);
  1067. CallbackInfo = &Instance->CallbackInfo;
  1068. CallbackInfo->Signature = IP4_FORM_CALLBACK_INFO_SIGNATURE;
  1069. Status = gBS->HandleProtocol (
  1070. IpSb->Controller,
  1071. &gEfiDevicePathProtocolGuid,
  1072. (VOID **)&ParentDevicePath
  1073. );
  1074. if (EFI_ERROR (Status)) {
  1075. return Status;
  1076. }
  1077. //
  1078. // Construct device path node for EFI HII Config Access protocol,
  1079. // which consists of controller physical device path and one hardware
  1080. // vendor guid node.
  1081. //
  1082. ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
  1083. VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
  1084. VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
  1085. CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);
  1086. SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
  1087. CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
  1088. ParentDevicePath,
  1089. (EFI_DEVICE_PATH_PROTOCOL *)&VendorDeviceNode
  1090. );
  1091. if (CallbackInfo->HiiVendorDevicePath == NULL) {
  1092. Status = EFI_OUT_OF_RESOURCES;
  1093. goto Error;
  1094. }
  1095. ConfigAccess = &CallbackInfo->HiiConfigAccessProtocol;
  1096. ConfigAccess->ExtractConfig = Ip4FormExtractConfig;
  1097. ConfigAccess->RouteConfig = Ip4FormRouteConfig;
  1098. ConfigAccess->Callback = Ip4FormCallback;
  1099. //
  1100. // Install Device Path Protocol and Config Access protocol on new handle
  1101. //
  1102. Status = gBS->InstallMultipleProtocolInterfaces (
  1103. &CallbackInfo->ChildHandle,
  1104. &gEfiDevicePathProtocolGuid,
  1105. CallbackInfo->HiiVendorDevicePath,
  1106. &gEfiHiiConfigAccessProtocolGuid,
  1107. ConfigAccess,
  1108. NULL
  1109. );
  1110. if (!EFI_ERROR (Status)) {
  1111. //
  1112. // Open the Parent Handle for the child
  1113. //
  1114. Status = gBS->OpenProtocol (
  1115. IpSb->Controller,
  1116. &gEfiManagedNetworkServiceBindingProtocolGuid,
  1117. (VOID **)&MnpSb,
  1118. IpSb->Image,
  1119. CallbackInfo->ChildHandle,
  1120. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  1121. );
  1122. }
  1123. if (EFI_ERROR (Status)) {
  1124. goto Error;
  1125. }
  1126. //
  1127. // Publish our HII data
  1128. //
  1129. CallbackInfo->RegisteredHandle = HiiAddPackages (
  1130. &gIp4Config2NvDataGuid,
  1131. CallbackInfo->ChildHandle,
  1132. Ip4DxeStrings,
  1133. Ip4Config2Bin,
  1134. NULL
  1135. );
  1136. if (CallbackInfo->RegisteredHandle == NULL) {
  1137. Status = EFI_OUT_OF_RESOURCES;
  1138. goto Error;
  1139. }
  1140. //
  1141. // Append MAC string in the menu help string and tile help string
  1142. //
  1143. Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);
  1144. if (!EFI_ERROR (Status)) {
  1145. OldMenuString = HiiGetString (
  1146. CallbackInfo->RegisteredHandle,
  1147. STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP),
  1148. NULL
  1149. );
  1150. UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
  1151. HiiSetString (
  1152. CallbackInfo->RegisteredHandle,
  1153. STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP),
  1154. MenuString,
  1155. NULL
  1156. );
  1157. UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
  1158. HiiSetString (
  1159. CallbackInfo->RegisteredHandle,
  1160. STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP),
  1161. PortString,
  1162. NULL
  1163. );
  1164. FreePool (MacString);
  1165. FreePool (OldMenuString);
  1166. return EFI_SUCCESS;
  1167. }
  1168. Error:
  1169. Ip4Config2FormUnload (Instance);
  1170. return Status;
  1171. }
  1172. /**
  1173. Uninstall the HII Config Access protocol for network devices and free up the resources.
  1174. @param[in, out] Instance The IP4 config2 instance to unload a form.
  1175. **/
  1176. VOID
  1177. Ip4Config2FormUnload (
  1178. IN OUT IP4_CONFIG2_INSTANCE *Instance
  1179. )
  1180. {
  1181. IP4_SERVICE *IpSb;
  1182. IP4_FORM_CALLBACK_INFO *CallbackInfo;
  1183. IP4_CONFIG2_NVDATA *Ip4NvData;
  1184. IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
  1185. ASSERT (IpSb != NULL);
  1186. CallbackInfo = &Instance->CallbackInfo;
  1187. if (CallbackInfo->ChildHandle != NULL) {
  1188. //
  1189. // Close the child handle
  1190. //
  1191. gBS->CloseProtocol (
  1192. IpSb->Controller,
  1193. &gEfiManagedNetworkServiceBindingProtocolGuid,
  1194. IpSb->Image,
  1195. CallbackInfo->ChildHandle
  1196. );
  1197. //
  1198. // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
  1199. //
  1200. gBS->UninstallMultipleProtocolInterfaces (
  1201. CallbackInfo->ChildHandle,
  1202. &gEfiDevicePathProtocolGuid,
  1203. CallbackInfo->HiiVendorDevicePath,
  1204. &gEfiHiiConfigAccessProtocolGuid,
  1205. &CallbackInfo->HiiConfigAccessProtocol,
  1206. NULL
  1207. );
  1208. }
  1209. if (CallbackInfo->HiiVendorDevicePath != NULL) {
  1210. FreePool (CallbackInfo->HiiVendorDevicePath);
  1211. }
  1212. if (CallbackInfo->RegisteredHandle != NULL) {
  1213. //
  1214. // Remove HII package list
  1215. //
  1216. HiiRemovePackages (CallbackInfo->RegisteredHandle);
  1217. }
  1218. Ip4NvData = &Instance->Ip4NvData;
  1219. if (Ip4NvData->ManualAddress != NULL) {
  1220. FreePool (Ip4NvData->ManualAddress);
  1221. }
  1222. if (Ip4NvData->GatewayAddress != NULL) {
  1223. FreePool (Ip4NvData->GatewayAddress);
  1224. }
  1225. if (Ip4NvData->DnsAddress != NULL) {
  1226. FreePool (Ip4NvData->DnsAddress);
  1227. }
  1228. Ip4NvData->ManualAddressCount = 0;
  1229. Ip4NvData->GatewayAddressCount = 0;
  1230. Ip4NvData->DnsAddressCount = 0;
  1231. }