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