VlanConfigImpl.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /** @file
  2. HII Config Access protocol implementation of VLAN configuration module.
  3. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "VlanConfigImpl.h"
  7. CHAR16 mVlanStorageName[] = L"VlanNvData";
  8. EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL;
  9. VLAN_CONFIG_PRIVATE_DATA mVlanConfigPrivateDateTemplate = {
  10. VLAN_CONFIG_PRIVATE_DATA_SIGNATURE,
  11. {
  12. VlanExtractConfig,
  13. VlanRouteConfig,
  14. VlanCallback
  15. }
  16. };
  17. VENDOR_DEVICE_PATH mHiiVendorDevicePathNode = {
  18. {
  19. HARDWARE_DEVICE_PATH,
  20. HW_VENDOR_DP,
  21. {
  22. (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
  23. (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
  24. }
  25. },
  26. VLAN_CONFIG_FORM_SET_GUID
  27. };
  28. /**
  29. This function allows a caller to extract the current configuration for one
  30. or more named elements from the target driver.
  31. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  32. @param[in] Request A null-terminated Unicode string in
  33. <ConfigRequest> format.
  34. @param[out] Progress On return, points to a character in the Request
  35. string. Points to the string's null terminator if
  36. request was successful. Points to the most recent
  37. '&' before the first failing name/value pair (or
  38. the beginning of the string if the failure is in
  39. the first name/value pair) if the request was not
  40. successful.
  41. @param[out] Results A null-terminated Unicode string in
  42. <ConfigAltResp> format which has all values filled
  43. in for the names in the Request string. String to
  44. be allocated by the called function.
  45. @retval EFI_SUCCESS The Results is filled with the requested values.
  46. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
  47. @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
  48. @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
  49. driver.
  50. **/
  51. EFI_STATUS
  52. EFIAPI
  53. VlanExtractConfig (
  54. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  55. IN CONST EFI_STRING Request,
  56. OUT EFI_STRING *Progress,
  57. OUT EFI_STRING *Results
  58. )
  59. {
  60. EFI_STATUS Status;
  61. UINTN BufferSize;
  62. VLAN_CONFIGURATION Configuration;
  63. VLAN_CONFIG_PRIVATE_DATA *PrivateData;
  64. EFI_STRING ConfigRequestHdr;
  65. EFI_STRING ConfigRequest;
  66. BOOLEAN AllocatedRequest;
  67. UINTN Size;
  68. if ((Progress == NULL) || (Results == NULL)) {
  69. return EFI_INVALID_PARAMETER;
  70. }
  71. *Progress = Request;
  72. if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gVlanConfigFormSetGuid, mVlanStorageName)) {
  73. return EFI_NOT_FOUND;
  74. }
  75. ConfigRequestHdr = NULL;
  76. ConfigRequest = NULL;
  77. AllocatedRequest = FALSE;
  78. Size = 0;
  79. //
  80. // Retrieve the pointer to the UEFI HII Config Routing Protocol
  81. //
  82. if (mHiiConfigRouting == NULL) {
  83. gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&mHiiConfigRouting);
  84. }
  85. ASSERT (mHiiConfigRouting != NULL);
  86. //
  87. // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
  88. //
  89. PrivateData = VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This);
  90. ZeroMem (&Configuration, sizeof (VLAN_CONFIGURATION));
  91. BufferSize = sizeof (Configuration);
  92. ConfigRequest = Request;
  93. if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
  94. //
  95. // Request has no request element, construct full request string.
  96. // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
  97. // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
  98. //
  99. ConfigRequestHdr = HiiConstructConfigHdr (&gVlanConfigFormSetGuid, mVlanStorageName, PrivateData->DriverHandle);
  100. Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
  101. ConfigRequest = AllocateZeroPool (Size);
  102. ASSERT (ConfigRequest != NULL);
  103. AllocatedRequest = TRUE;
  104. UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
  105. FreePool (ConfigRequestHdr);
  106. }
  107. Status = mHiiConfigRouting->BlockToConfig (
  108. mHiiConfigRouting,
  109. ConfigRequest,
  110. (UINT8 *)&Configuration,
  111. BufferSize,
  112. Results,
  113. Progress
  114. );
  115. //
  116. // Free the allocated config request string.
  117. //
  118. if (AllocatedRequest) {
  119. FreePool (ConfigRequest);
  120. ConfigRequest = NULL;
  121. }
  122. //
  123. // Set Progress string to the original request string.
  124. //
  125. if (Request == NULL) {
  126. *Progress = NULL;
  127. } else if (StrStr (Request, L"OFFSET") == NULL) {
  128. *Progress = Request + StrLen (Request);
  129. }
  130. return Status;
  131. }
  132. /**
  133. This function processes the results of changes in configuration.
  134. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  135. @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
  136. format.
  137. @param[out] Progress A pointer to a string filled in with the offset of
  138. the most recent '&' before the first failing
  139. name/value pair (or the beginning of the string if
  140. the failure is in the first name/value pair) or
  141. the terminating NULL if all was successful.
  142. @retval EFI_SUCCESS The Results is processed successfully.
  143. @retval EFI_INVALID_PARAMETER Configuration is NULL.
  144. @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
  145. driver.
  146. **/
  147. EFI_STATUS
  148. EFIAPI
  149. VlanRouteConfig (
  150. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  151. IN CONST EFI_STRING Configuration,
  152. OUT EFI_STRING *Progress
  153. )
  154. {
  155. if ((Configuration == NULL) || (Progress == NULL)) {
  156. return EFI_INVALID_PARAMETER;
  157. }
  158. *Progress = Configuration;
  159. if (!HiiIsConfigHdrMatch (Configuration, &gVlanConfigFormSetGuid, mVlanStorageName)) {
  160. return EFI_NOT_FOUND;
  161. }
  162. *Progress = Configuration + StrLen (Configuration);
  163. return EFI_SUCCESS;
  164. }
  165. /**
  166. This function processes the results of changes in configuration.
  167. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  168. @param[in] Action Specifies the type of action taken by the browser.
  169. @param[in] QuestionId A unique value which is sent to the original
  170. exporting driver so that it can identify the type
  171. of data to expect.
  172. @param[in] Type The type of value for the question.
  173. @param[in] Value A pointer to the data being sent to the original
  174. exporting driver.
  175. @param[out] ActionRequest On return, points to the action requested by the
  176. callback function.
  177. @retval EFI_SUCCESS The callback successfully handled the action.
  178. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
  179. variable and its data.
  180. @retval EFI_DEVICE_ERROR The variable could not be saved.
  181. @retval EFI_UNSUPPORTED The specified Action is not supported by the
  182. callback.
  183. **/
  184. EFI_STATUS
  185. EFIAPI
  186. VlanCallback (
  187. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  188. IN EFI_BROWSER_ACTION Action,
  189. IN EFI_QUESTION_ID QuestionId,
  190. IN UINT8 Type,
  191. IN EFI_IFR_TYPE_VALUE *Value,
  192. OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
  193. )
  194. {
  195. VLAN_CONFIG_PRIVATE_DATA *PrivateData;
  196. VLAN_CONFIGURATION *Configuration;
  197. EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
  198. UINTN Index;
  199. EFI_HANDLE VlanHandle;
  200. PrivateData = VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This);
  201. if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
  202. return EFI_SUCCESS;
  203. }
  204. if ((Action != EFI_BROWSER_ACTION_CHANGED) && (Action != EFI_BROWSER_ACTION_CHANGING)) {
  205. //
  206. // All other action return unsupported.
  207. //
  208. return EFI_UNSUPPORTED;
  209. }
  210. //
  211. // Get Browser data
  212. //
  213. Configuration = AllocateZeroPool (sizeof (VLAN_CONFIGURATION));
  214. ASSERT (Configuration != NULL);
  215. HiiGetBrowserData (&gVlanConfigFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *)Configuration);
  216. VlanConfig = PrivateData->VlanConfig;
  217. if (Action == EFI_BROWSER_ACTION_CHANGED) {
  218. switch (QuestionId) {
  219. case VLAN_ADD_QUESTION_ID:
  220. //
  221. // Add a VLAN
  222. //
  223. VlanConfig->Set (VlanConfig, Configuration->VlanId, Configuration->Priority);
  224. VlanUpdateForm (PrivateData);
  225. //
  226. // Connect the newly created VLAN device
  227. //
  228. VlanHandle = NetLibGetVlanHandle (PrivateData->ControllerHandle, Configuration->VlanId);
  229. if (VlanHandle == NULL) {
  230. //
  231. // There may be no child handle created for VLAN ID 0, connect the parent handle
  232. //
  233. VlanHandle = PrivateData->ControllerHandle;
  234. }
  235. gBS->ConnectController (VlanHandle, NULL, NULL, TRUE);
  236. //
  237. // Clear UI data
  238. //
  239. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
  240. Configuration->VlanId = 0;
  241. Configuration->Priority = 0;
  242. break;
  243. case VLAN_REMOVE_QUESTION_ID:
  244. //
  245. // Remove VLAN
  246. //
  247. ASSERT (PrivateData->NumberOfVlan <= MAX_VLAN_NUMBER);
  248. for (Index = 0; Index < PrivateData->NumberOfVlan; Index++) {
  249. if (Configuration->VlanList[Index] != 0) {
  250. //
  251. // Checkbox is selected, need remove this VLAN
  252. //
  253. VlanConfig->Remove (VlanConfig, PrivateData->VlanId[Index]);
  254. }
  255. }
  256. VlanUpdateForm (PrivateData);
  257. if (PrivateData->NumberOfVlan == 0) {
  258. //
  259. // No VLAN device now, connect the physical NIC handle.
  260. // Note: PrivateData->NumberOfVlan has been updated by VlanUpdateForm()
  261. //
  262. gBS->ConnectController (PrivateData->ControllerHandle, NULL, NULL, TRUE);
  263. }
  264. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
  265. ZeroMem (Configuration->VlanList, MAX_VLAN_NUMBER);
  266. break;
  267. default:
  268. break;
  269. }
  270. } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
  271. switch (QuestionId) {
  272. case VLAN_UPDATE_QUESTION_ID:
  273. //
  274. // Update current VLAN list into Form.
  275. //
  276. VlanUpdateForm (PrivateData);
  277. break;
  278. default:
  279. break;
  280. }
  281. }
  282. HiiSetBrowserData (&gVlanConfigFormSetGuid, mVlanStorageName, sizeof (VLAN_CONFIGURATION), (UINT8 *)Configuration, NULL);
  283. FreePool (Configuration);
  284. return EFI_SUCCESS;
  285. }
  286. /**
  287. This function update VLAN list in the VLAN configuration Form.
  288. @param[in, out] PrivateData Points to VLAN configuration private data.
  289. **/
  290. VOID
  291. VlanUpdateForm (
  292. IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData
  293. )
  294. {
  295. EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
  296. UINT16 NumberOfVlan;
  297. UINTN Index;
  298. EFI_VLAN_FIND_DATA *VlanData;
  299. VOID *StartOpCodeHandle;
  300. EFI_IFR_GUID_LABEL *StartLabel;
  301. VOID *EndOpCodeHandle;
  302. EFI_IFR_GUID_LABEL *EndLabel;
  303. CHAR16 *String;
  304. CHAR16 VlanStr[30];
  305. CHAR16 VlanIdStr[6];
  306. UINTN DigitalCount;
  307. EFI_STRING_ID StringId;
  308. //
  309. // Find current VLAN configuration
  310. //
  311. VlanData = NULL;
  312. NumberOfVlan = 0;
  313. VlanConfig = PrivateData->VlanConfig;
  314. VlanConfig->Find (VlanConfig, NULL, &NumberOfVlan, &VlanData);
  315. //
  316. // Update VLAN configuration in PrivateData
  317. //
  318. if (NumberOfVlan > MAX_VLAN_NUMBER) {
  319. NumberOfVlan = MAX_VLAN_NUMBER;
  320. }
  321. PrivateData->NumberOfVlan = NumberOfVlan;
  322. //
  323. // Init OpCode Handle
  324. //
  325. StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  326. ASSERT (StartOpCodeHandle != NULL);
  327. EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  328. ASSERT (EndOpCodeHandle != NULL);
  329. //
  330. // Create Hii Extend Label OpCode as the start opcode
  331. //
  332. StartLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
  333. StartOpCodeHandle,
  334. &gEfiIfrTianoGuid,
  335. NULL,
  336. sizeof (EFI_IFR_GUID_LABEL)
  337. );
  338. StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  339. StartLabel->Number = LABEL_VLAN_LIST;
  340. //
  341. // Create Hii Extend Label OpCode as the end opcode
  342. //
  343. EndLabel = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode (
  344. EndOpCodeHandle,
  345. &gEfiIfrTianoGuid,
  346. NULL,
  347. sizeof (EFI_IFR_GUID_LABEL)
  348. );
  349. EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  350. EndLabel->Number = LABEL_END;
  351. ZeroMem (PrivateData->VlanId, MAX_VLAN_NUMBER);
  352. for (Index = 0; Index < NumberOfVlan; Index++) {
  353. String = VlanStr;
  354. StrCpyS (String, (sizeof (VlanStr) /sizeof (CHAR16)), L" VLAN ID:");
  355. String += 10;
  356. //
  357. // Pad VlanId string up to 4 characters with space
  358. //
  359. UnicodeValueToStringS (VlanIdStr, sizeof (VlanIdStr), 0, VlanData[Index].VlanId, 5);
  360. DigitalCount = StrnLenS (VlanIdStr, ARRAY_SIZE (VlanIdStr));
  361. SetMem16 (String, (4 - DigitalCount) * sizeof (CHAR16), L' ');
  362. StrCpyS (String + 4 - DigitalCount, (sizeof (VlanStr) /sizeof (CHAR16)) - 10 - (4 - DigitalCount), VlanIdStr);
  363. String += 4;
  364. StrCpyS (String, (sizeof (VlanStr) /sizeof (CHAR16)) - 10 - (4 - DigitalCount) - 4, L", Priority:");
  365. String += 11;
  366. UnicodeValueToStringS (
  367. String,
  368. sizeof (VlanStr) - ((UINTN)String - (UINTN)VlanStr),
  369. 0,
  370. VlanData[Index].Priority,
  371. 4
  372. );
  373. String += StrnLenS (String, ARRAY_SIZE (VlanStr) - ((UINTN)String - (UINTN)VlanStr) / sizeof (CHAR16));
  374. *String = 0;
  375. StringId = HiiSetString (PrivateData->HiiHandle, 0, VlanStr, NULL);
  376. ASSERT (StringId != 0);
  377. HiiCreateCheckBoxOpCode (
  378. StartOpCodeHandle,
  379. (EFI_QUESTION_ID)(VLAN_LIST_VAR_OFFSET + Index),
  380. VLAN_CONFIGURATION_VARSTORE_ID,
  381. (UINT16)(VLAN_LIST_VAR_OFFSET + Index),
  382. StringId,
  383. STRING_TOKEN (STR_VLAN_VLAN_LIST_HELP),
  384. 0,
  385. 0,
  386. NULL
  387. );
  388. //
  389. // Save VLAN id to private data
  390. //
  391. PrivateData->VlanId[Index] = VlanData[Index].VlanId;
  392. }
  393. HiiUpdateForm (
  394. PrivateData->HiiHandle, // HII handle
  395. &gVlanConfigFormSetGuid, // Formset GUID
  396. VLAN_CONFIGURATION_FORM_ID, // Form ID
  397. StartOpCodeHandle, // Label for where to insert opcodes
  398. EndOpCodeHandle // Replace data
  399. );
  400. HiiFreeOpCodeHandle (StartOpCodeHandle);
  401. HiiFreeOpCodeHandle (EndOpCodeHandle);
  402. if (VlanData != NULL) {
  403. FreePool (VlanData);
  404. }
  405. }
  406. /**
  407. This function publish the VLAN configuration Form for a network device. The
  408. HII Config Access protocol will be installed on a child handle of the network
  409. device.
  410. @param[in, out] PrivateData Points to VLAN configuration private data.
  411. @retval EFI_SUCCESS HII Form is installed for this network device.
  412. @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
  413. @retval Others Other errors as indicated.
  414. **/
  415. EFI_STATUS
  416. InstallVlanConfigForm (
  417. IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData
  418. )
  419. {
  420. EFI_STATUS Status;
  421. EFI_HII_HANDLE HiiHandle;
  422. EFI_HANDLE DriverHandle;
  423. CHAR16 Str[26 + sizeof (EFI_MAC_ADDRESS) * 2 + 1];
  424. CHAR16 *MacString;
  425. EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath;
  426. EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
  427. EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
  428. //
  429. // Create child handle and install HII Config Access Protocol
  430. //
  431. ChildDevicePath = AppendDevicePathNode (
  432. PrivateData->ParentDevicePath,
  433. (CONST EFI_DEVICE_PATH_PROTOCOL *)&mHiiVendorDevicePathNode
  434. );
  435. if (ChildDevicePath == NULL) {
  436. return EFI_OUT_OF_RESOURCES;
  437. }
  438. PrivateData->ChildDevicePath = ChildDevicePath;
  439. DriverHandle = NULL;
  440. ConfigAccess = &PrivateData->ConfigAccess;
  441. Status = gBS->InstallMultipleProtocolInterfaces (
  442. &DriverHandle,
  443. &gEfiDevicePathProtocolGuid,
  444. ChildDevicePath,
  445. &gEfiHiiConfigAccessProtocolGuid,
  446. ConfigAccess,
  447. NULL
  448. );
  449. if (EFI_ERROR (Status)) {
  450. return Status;
  451. }
  452. PrivateData->DriverHandle = DriverHandle;
  453. //
  454. // Establish the parent-child relationship between the new created
  455. // child handle and the ControllerHandle.
  456. //
  457. Status = gBS->OpenProtocol (
  458. PrivateData->ControllerHandle,
  459. &gEfiVlanConfigProtocolGuid,
  460. (VOID **)&VlanConfig,
  461. PrivateData->ImageHandle,
  462. PrivateData->DriverHandle,
  463. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  464. );
  465. if (EFI_ERROR (Status)) {
  466. return Status;
  467. }
  468. //
  469. // Publish the HII package list
  470. //
  471. HiiHandle = HiiAddPackages (
  472. &gVlanConfigFormSetGuid,
  473. DriverHandle,
  474. VlanConfigDxeStrings,
  475. VlanConfigBin,
  476. NULL
  477. );
  478. if (HiiHandle == NULL) {
  479. return EFI_OUT_OF_RESOURCES;
  480. }
  481. PrivateData->HiiHandle = HiiHandle;
  482. //
  483. // Update formset title help string.
  484. //
  485. MacString = NULL;
  486. Status = NetLibGetMacString (PrivateData->ControllerHandle, PrivateData->ImageHandle, &MacString);
  487. if (EFI_ERROR (Status)) {
  488. return Status;
  489. }
  490. PrivateData->MacString = MacString;
  491. StrCpyS (Str, sizeof (Str) / sizeof (CHAR16), L"VLAN Configuration (MAC:");
  492. StrCatS (Str, sizeof (Str) / sizeof (CHAR16), MacString);
  493. StrCatS (Str, sizeof (Str) / sizeof (CHAR16), L")");
  494. HiiSetString (
  495. HiiHandle,
  496. STRING_TOKEN (STR_VLAN_FORM_SET_TITLE_HELP),
  497. Str,
  498. NULL
  499. );
  500. //
  501. // Update form title help string.
  502. //
  503. HiiSetString (
  504. HiiHandle,
  505. STRING_TOKEN (STR_VLAN_FORM_HELP),
  506. Str,
  507. NULL
  508. );
  509. return EFI_SUCCESS;
  510. }
  511. /**
  512. This function remove the VLAN configuration Form for a network device. The
  513. child handle for HII Config Access protocol will be destroyed.
  514. @param[in, out] PrivateData Points to VLAN configuration private data.
  515. @retval EFI_SUCCESS HII Form has been uninstalled successfully.
  516. @retval Others Other errors as indicated.
  517. **/
  518. EFI_STATUS
  519. UninstallVlanConfigForm (
  520. IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData
  521. )
  522. {
  523. EFI_STATUS Status;
  524. EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
  525. //
  526. // End the parent-child relationship.
  527. //
  528. Status = gBS->CloseProtocol (
  529. PrivateData->ControllerHandle,
  530. &gEfiVlanConfigProtocolGuid,
  531. PrivateData->ImageHandle,
  532. PrivateData->DriverHandle
  533. );
  534. if (EFI_ERROR (Status)) {
  535. return Status;
  536. }
  537. //
  538. // Uninstall HII Config Access Protocol
  539. //
  540. if (PrivateData->DriverHandle != NULL) {
  541. Status = gBS->UninstallMultipleProtocolInterfaces (
  542. PrivateData->DriverHandle,
  543. &gEfiDevicePathProtocolGuid,
  544. PrivateData->ChildDevicePath,
  545. &gEfiHiiConfigAccessProtocolGuid,
  546. &PrivateData->ConfigAccess,
  547. NULL
  548. );
  549. if (EFI_ERROR (Status)) {
  550. gBS->OpenProtocol (
  551. PrivateData->ControllerHandle,
  552. &gEfiVlanConfigProtocolGuid,
  553. (VOID **)&VlanConfig,
  554. PrivateData->ImageHandle,
  555. PrivateData->DriverHandle,
  556. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  557. );
  558. return Status;
  559. }
  560. PrivateData->DriverHandle = NULL;
  561. if (PrivateData->ChildDevicePath != NULL) {
  562. FreePool (PrivateData->ChildDevicePath);
  563. PrivateData->ChildDevicePath = NULL;
  564. }
  565. }
  566. //
  567. // Free MAC string
  568. //
  569. if (PrivateData->MacString != NULL) {
  570. FreePool (PrivateData->MacString);
  571. PrivateData->MacString = NULL;
  572. }
  573. //
  574. // Uninstall HII package list
  575. //
  576. if (PrivateData->HiiHandle != NULL) {
  577. HiiRemovePackages (PrivateData->HiiHandle);
  578. PrivateData->HiiHandle = NULL;
  579. }
  580. return EFI_SUCCESS;
  581. }