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