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
VlanExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)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
VlanRouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)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
VlanCallback(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN EFI_BROWSER_ACTION Action,IN EFI_QUESTION_ID QuestionId,IN UINT8 Type,IN EFI_IFR_TYPE_VALUE * Value,OUT EFI_BROWSER_ACTION_REQUEST * ActionRequest)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
VlanUpdateForm(IN OUT VLAN_CONFIG_PRIVATE_DATA * PrivateData)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
InstallVlanConfigForm(IN OUT VLAN_CONFIG_PRIVATE_DATA * PrivateData)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
UninstallVlanConfigForm(IN OUT VLAN_CONFIG_PRIVATE_DATA * PrivateData)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