2 HII Config Access protocol implementation of VLAN configuration module.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "VlanConfigImpl.h"
11 CHAR16 mVlanStorageName
[] = L
"VlanNvData";
12 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
= NULL
;
14 VLAN_CONFIG_PRIVATE_DATA mVlanConfigPrivateDateTemplate
= {
15 VLAN_CONFIG_PRIVATE_DATA_SIGNATURE
,
23 VENDOR_DEVICE_PATH mHiiVendorDevicePathNode
= {
28 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
29 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
32 VLAN_CONFIG_FORM_SET_GUID
36 This function allows a caller to extract the current configuration for one
37 or more named elements from the target driver.
39 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
40 @param[in] Request A null-terminated Unicode string in
41 <ConfigRequest> format.
42 @param[out] Progress On return, points to a character in the Request
43 string. Points to the string's null terminator if
44 request was successful. Points to the most recent
45 '&' before the first failing name/value pair (or
46 the beginning of the string if the failure is in
47 the first name/value pair) if the request was not
49 @param[out] Results A null-terminated Unicode string in
50 <ConfigAltResp> format which has all values filled
51 in for the names in the Request string. String to
52 be allocated by the called function.
54 @retval EFI_SUCCESS The Results is filled with the requested values.
55 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
56 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
57 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
64 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
65 IN CONST EFI_STRING Request
,
66 OUT EFI_STRING
*Progress
,
67 OUT EFI_STRING
*Results
72 VLAN_CONFIGURATION Configuration
;
73 VLAN_CONFIG_PRIVATE_DATA
*PrivateData
;
74 EFI_STRING ConfigRequestHdr
;
75 EFI_STRING ConfigRequest
;
76 BOOLEAN AllocatedRequest
;
79 if (Progress
== NULL
|| Results
== NULL
) {
80 return EFI_INVALID_PARAMETER
;
84 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gVlanConfigFormSetGuid
, mVlanStorageName
)) {
88 ConfigRequestHdr
= NULL
;
90 AllocatedRequest
= FALSE
;
94 // Retrieve the pointer to the UEFI HII Config Routing Protocol
96 if (mHiiConfigRouting
== NULL
) {
97 gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &mHiiConfigRouting
);
99 ASSERT (mHiiConfigRouting
!= NULL
);
102 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
104 PrivateData
= VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This
);
105 ZeroMem (&Configuration
, sizeof (VLAN_CONFIGURATION
));
106 BufferSize
= sizeof (Configuration
);
107 ConfigRequest
= Request
;
108 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
110 // Request has no request element, construct full request string.
111 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
112 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
114 ConfigRequestHdr
= HiiConstructConfigHdr (&gVlanConfigFormSetGuid
, mVlanStorageName
, PrivateData
->DriverHandle
);
115 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
116 ConfigRequest
= AllocateZeroPool (Size
);
117 ASSERT (ConfigRequest
!= NULL
);
118 AllocatedRequest
= TRUE
;
119 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
120 FreePool (ConfigRequestHdr
);
123 Status
= mHiiConfigRouting
->BlockToConfig (
126 (UINT8
*) &Configuration
,
132 // Free the allocated config request string.
134 if (AllocatedRequest
) {
135 FreePool (ConfigRequest
);
136 ConfigRequest
= NULL
;
139 // Set Progress string to the original request string.
141 if (Request
== NULL
) {
143 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
144 *Progress
= Request
+ StrLen (Request
);
152 This function processes the results of changes in configuration.
154 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
155 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
157 @param[out] Progress A pointer to a string filled in with the offset of
158 the most recent '&' before the first failing
159 name/value pair (or the beginning of the string if
160 the failure is in the first name/value pair) or
161 the terminating NULL if all was successful.
163 @retval EFI_SUCCESS The Results is processed successfully.
164 @retval EFI_INVALID_PARAMETER Configuration is NULL.
165 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
172 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
173 IN CONST EFI_STRING Configuration
,
174 OUT EFI_STRING
*Progress
177 if (Configuration
== NULL
|| Progress
== NULL
) {
178 return EFI_INVALID_PARAMETER
;
181 *Progress
= Configuration
;
182 if (!HiiIsConfigHdrMatch (Configuration
, &gVlanConfigFormSetGuid
, mVlanStorageName
)) {
183 return EFI_NOT_FOUND
;
186 *Progress
= Configuration
+ StrLen (Configuration
);
191 This function processes the results of changes in configuration.
193 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
194 @param[in] Action Specifies the type of action taken by the browser.
195 @param[in] QuestionId A unique value which is sent to the original
196 exporting driver so that it can identify the type
198 @param[in] Type The type of value for the question.
199 @param[in] Value A pointer to the data being sent to the original
201 @param[out] ActionRequest On return, points to the action requested by the
204 @retval EFI_SUCCESS The callback successfully handled the action.
205 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
206 variable and its data.
207 @retval EFI_DEVICE_ERROR The variable could not be saved.
208 @retval EFI_UNSUPPORTED The specified Action is not supported by the
215 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
216 IN EFI_BROWSER_ACTION Action
,
217 IN EFI_QUESTION_ID QuestionId
,
219 IN EFI_IFR_TYPE_VALUE
*Value
,
220 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
223 VLAN_CONFIG_PRIVATE_DATA
*PrivateData
;
224 VLAN_CONFIGURATION
*Configuration
;
225 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
227 EFI_HANDLE VlanHandle
;
229 PrivateData
= VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This
);
231 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
235 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) && (Action
!= EFI_BROWSER_ACTION_CHANGING
)) {
237 // All other action return unsupported.
239 return EFI_UNSUPPORTED
;
245 Configuration
= AllocateZeroPool (sizeof (VLAN_CONFIGURATION
));
246 ASSERT (Configuration
!= NULL
);
247 HiiGetBrowserData (&gVlanConfigFormSetGuid
, mVlanStorageName
, sizeof (VLAN_CONFIGURATION
), (UINT8
*) Configuration
);
249 VlanConfig
= PrivateData
->VlanConfig
;
251 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
252 switch (QuestionId
) {
253 case VLAN_ADD_QUESTION_ID
:
257 VlanConfig
->Set (VlanConfig
, Configuration
->VlanId
, Configuration
->Priority
);
258 VlanUpdateForm (PrivateData
);
261 // Connect the newly created VLAN device
263 VlanHandle
= NetLibGetVlanHandle (PrivateData
->ControllerHandle
, Configuration
->VlanId
);
264 if (VlanHandle
== NULL
) {
266 // There may be no child handle created for VLAN ID 0, connect the parent handle
268 VlanHandle
= PrivateData
->ControllerHandle
;
270 gBS
->ConnectController (VlanHandle
, NULL
, NULL
, TRUE
);
275 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
276 Configuration
->VlanId
= 0;
277 Configuration
->Priority
= 0;
280 case VLAN_REMOVE_QUESTION_ID
:
284 ASSERT (PrivateData
->NumberOfVlan
<= MAX_VLAN_NUMBER
);
285 for (Index
= 0; Index
< PrivateData
->NumberOfVlan
; Index
++) {
286 if (Configuration
->VlanList
[Index
] != 0) {
288 // Checkbox is selected, need remove this VLAN
290 VlanConfig
->Remove (VlanConfig
, PrivateData
->VlanId
[Index
]);
294 VlanUpdateForm (PrivateData
);
295 if (PrivateData
->NumberOfVlan
== 0) {
297 // No VLAN device now, connect the physical NIC handle.
298 // Note: PrivateData->NumberOfVlan has been updated by VlanUpdateForm()
300 gBS
->ConnectController (PrivateData
->ControllerHandle
, NULL
, NULL
, TRUE
);
303 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
304 ZeroMem (Configuration
->VlanList
, MAX_VLAN_NUMBER
);
310 } else if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
311 switch (QuestionId
) {
312 case VLAN_UPDATE_QUESTION_ID
:
314 // Update current VLAN list into Form.
316 VlanUpdateForm (PrivateData
);
324 HiiSetBrowserData (&gVlanConfigFormSetGuid
, mVlanStorageName
, sizeof (VLAN_CONFIGURATION
), (UINT8
*) Configuration
, NULL
);
325 FreePool (Configuration
);
331 This function update VLAN list in the VLAN configuration Form.
333 @param[in, out] PrivateData Points to VLAN configuration private data.
338 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
341 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
344 EFI_VLAN_FIND_DATA
*VlanData
;
345 VOID
*StartOpCodeHandle
;
346 EFI_IFR_GUID_LABEL
*StartLabel
;
347 VOID
*EndOpCodeHandle
;
348 EFI_IFR_GUID_LABEL
*EndLabel
;
353 EFI_STRING_ID StringId
;
356 // Find current VLAN configuration
360 VlanConfig
= PrivateData
->VlanConfig
;
361 VlanConfig
->Find (VlanConfig
, NULL
, &NumberOfVlan
, &VlanData
);
364 // Update VLAN configuration in PrivateData
366 if (NumberOfVlan
> MAX_VLAN_NUMBER
) {
367 NumberOfVlan
= MAX_VLAN_NUMBER
;
369 PrivateData
->NumberOfVlan
= NumberOfVlan
;
372 // Init OpCode Handle
374 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
375 ASSERT (StartOpCodeHandle
!= NULL
);
377 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
378 ASSERT (EndOpCodeHandle
!= NULL
);
381 // Create Hii Extend Label OpCode as the start opcode
383 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
387 sizeof (EFI_IFR_GUID_LABEL
)
389 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
390 StartLabel
->Number
= LABEL_VLAN_LIST
;
393 // Create Hii Extend Label OpCode as the end opcode
395 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
399 sizeof (EFI_IFR_GUID_LABEL
)
401 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
402 EndLabel
->Number
= LABEL_END
;
404 ZeroMem (PrivateData
->VlanId
, MAX_VLAN_NUMBER
);
405 for (Index
= 0; Index
< NumberOfVlan
; Index
++) {
408 StrCpyS (String
, (sizeof (VlanStr
) /sizeof (CHAR16
)), L
" VLAN ID:");
411 // Pad VlanId string up to 4 characters with space
413 UnicodeValueToStringS (VlanIdStr
, sizeof (VlanIdStr
), 0, VlanData
[Index
].VlanId
, 5);
414 DigitalCount
= StrnLenS (VlanIdStr
, ARRAY_SIZE (VlanIdStr
));
415 SetMem16 (String
, (4 - DigitalCount
) * sizeof (CHAR16
), L
' ');
416 StrCpyS (String
+ 4 - DigitalCount
, (sizeof (VlanStr
) /sizeof (CHAR16
)) - 10 - (4 - DigitalCount
), VlanIdStr
);
419 StrCpyS (String
, (sizeof (VlanStr
) /sizeof (CHAR16
)) - 10 - (4 - DigitalCount
) - 4, L
", Priority:");
421 UnicodeValueToStringS (
423 sizeof (VlanStr
) - ((UINTN
)String
- (UINTN
)VlanStr
),
425 VlanData
[Index
].Priority
,
428 String
+= StrnLenS (String
, ARRAY_SIZE (VlanStr
) - ((UINTN
)String
- (UINTN
)VlanStr
) / sizeof (CHAR16
));
431 StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, VlanStr
, NULL
);
432 ASSERT (StringId
!= 0);
434 HiiCreateCheckBoxOpCode (
436 (EFI_QUESTION_ID
) (VLAN_LIST_VAR_OFFSET
+ Index
),
437 VLAN_CONFIGURATION_VARSTORE_ID
,
438 (UINT16
) (VLAN_LIST_VAR_OFFSET
+ Index
),
440 STRING_TOKEN (STR_VLAN_VLAN_LIST_HELP
),
447 // Save VLAN id to private data
449 PrivateData
->VlanId
[Index
] = VlanData
[Index
].VlanId
;
453 PrivateData
->HiiHandle
, // HII handle
454 &gVlanConfigFormSetGuid
, // Formset GUID
455 VLAN_CONFIGURATION_FORM_ID
, // Form ID
456 StartOpCodeHandle
, // Label for where to insert opcodes
457 EndOpCodeHandle
// Replace data
460 HiiFreeOpCodeHandle (StartOpCodeHandle
);
461 HiiFreeOpCodeHandle (EndOpCodeHandle
);
463 if (VlanData
!= NULL
) {
470 This function publish the VLAN configuration Form for a network device. The
471 HII Config Access protocol will be installed on a child handle of the network
474 @param[in, out] PrivateData Points to VLAN configuration private data.
476 @retval EFI_SUCCESS HII Form is installed for this network device.
477 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
478 @retval Others Other errors as indicated.
482 InstallVlanConfigForm (
483 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
487 EFI_HII_HANDLE HiiHandle
;
488 EFI_HANDLE DriverHandle
;
489 CHAR16 Str
[26 + sizeof (EFI_MAC_ADDRESS
) * 2 + 1];
491 EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
;
492 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
493 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
496 // Create child handle and install HII Config Access Protocol
498 ChildDevicePath
= AppendDevicePathNode (
499 PrivateData
->ParentDevicePath
,
500 (CONST EFI_DEVICE_PATH_PROTOCOL
*) &mHiiVendorDevicePathNode
502 if (ChildDevicePath
== NULL
) {
503 return EFI_OUT_OF_RESOURCES
;
505 PrivateData
->ChildDevicePath
= ChildDevicePath
;
508 ConfigAccess
= &PrivateData
->ConfigAccess
;
509 Status
= gBS
->InstallMultipleProtocolInterfaces (
511 &gEfiDevicePathProtocolGuid
,
513 &gEfiHiiConfigAccessProtocolGuid
,
517 if (EFI_ERROR (Status
)) {
520 PrivateData
->DriverHandle
= DriverHandle
;
523 // Establish the parent-child relationship between the new created
524 // child handle and the ControllerHandle.
526 Status
= gBS
->OpenProtocol (
527 PrivateData
->ControllerHandle
,
528 &gEfiVlanConfigProtocolGuid
,
529 (VOID
**)&VlanConfig
,
530 PrivateData
->ImageHandle
,
531 PrivateData
->DriverHandle
,
532 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
534 if (EFI_ERROR (Status
)) {
539 // Publish the HII package list
541 HiiHandle
= HiiAddPackages (
542 &gVlanConfigFormSetGuid
,
544 VlanConfigDxeStrings
,
548 if (HiiHandle
== NULL
) {
549 return EFI_OUT_OF_RESOURCES
;
551 PrivateData
->HiiHandle
= HiiHandle
;
554 // Update formset title help string.
557 Status
= NetLibGetMacString (PrivateData
->ControllerHandle
, PrivateData
->ImageHandle
, &MacString
);
558 if (EFI_ERROR (Status
)) {
561 PrivateData
->MacString
= MacString
;
563 StrCpyS (Str
, sizeof (Str
) / sizeof (CHAR16
), L
"VLAN Configuration (MAC:");
564 StrCatS (Str
, sizeof (Str
) / sizeof (CHAR16
), MacString
);
565 StrCatS (Str
, sizeof (Str
) / sizeof (CHAR16
), L
")");
568 STRING_TOKEN (STR_VLAN_FORM_SET_TITLE_HELP
),
574 // Update form title help string.
578 STRING_TOKEN (STR_VLAN_FORM_HELP
),
587 This function remove the VLAN configuration Form for a network device. The
588 child handle for HII Config Access protocol will be destroyed.
590 @param[in, out] PrivateData Points to VLAN configuration private data.
592 @retval EFI_SUCCESS HII Form has been uninstalled successfully.
593 @retval Others Other errors as indicated.
597 UninstallVlanConfigForm (
598 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
602 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
605 // End the parent-child relationship.
607 Status
= gBS
->CloseProtocol (
608 PrivateData
->ControllerHandle
,
609 &gEfiVlanConfigProtocolGuid
,
610 PrivateData
->ImageHandle
,
611 PrivateData
->DriverHandle
613 if (EFI_ERROR (Status
)) {
618 // Uninstall HII Config Access Protocol
620 if (PrivateData
->DriverHandle
!= NULL
) {
621 Status
= gBS
->UninstallMultipleProtocolInterfaces (
622 PrivateData
->DriverHandle
,
623 &gEfiDevicePathProtocolGuid
,
624 PrivateData
->ChildDevicePath
,
625 &gEfiHiiConfigAccessProtocolGuid
,
626 &PrivateData
->ConfigAccess
,
629 if (EFI_ERROR (Status
)) {
631 PrivateData
->ControllerHandle
,
632 &gEfiVlanConfigProtocolGuid
,
633 (VOID
**)&VlanConfig
,
634 PrivateData
->ImageHandle
,
635 PrivateData
->DriverHandle
,
636 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
640 PrivateData
->DriverHandle
= NULL
;
642 if (PrivateData
->ChildDevicePath
!= NULL
) {
643 FreePool (PrivateData
->ChildDevicePath
);
644 PrivateData
->ChildDevicePath
= NULL
;
651 if (PrivateData
->MacString
!= NULL
) {
652 FreePool (PrivateData
->MacString
);
653 PrivateData
->MacString
= NULL
;
657 // Uninstall HII package list
659 if (PrivateData
->HiiHandle
!= NULL
) {
660 HiiRemovePackages (PrivateData
->HiiHandle
);
661 PrivateData
->HiiHandle
= NULL
;