1 /** @file 2 HII Config Access protocol implementation of VLAN configuration module. 3 4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions 7 of the BSD License which accompanies this distribution. The full 8 text of the license may be found at<BR> 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "VlanConfigImpl.h" 17 18 CHAR16 mVlanStorageName[] = L"VlanNvData"; 19 EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL; 20 21 VLAN_CONFIG_PRIVATE_DATA mVlanConfigPrivateDateTemplate = { 22 VLAN_CONFIG_PRIVATE_DATA_SIGNATURE, 23 { 24 VlanExtractConfig, 25 VlanRouteConfig, 26 VlanCallback 27 } 28 }; 29 30 VENDOR_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 **/ 68 EFI_STATUS 69 EFIAPI 70 VlanExtractConfig ( 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 **/ 176 EFI_STATUS 177 EFIAPI 178 VlanRouteConfig ( 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 **/ 219 EFI_STATUS 220 EFIAPI 221 VlanCallback ( 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 **/ 343 VOID 344 VlanUpdateForm ( 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 **/ 480 EFI_STATUS 481 InstallVlanConfigForm ( 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 **/ 595 EFI_STATUS 596 UninstallVlanConfigForm ( 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