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
);
100 ASSERT (mHiiConfigRouting
!= NULL
);
103 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
105 PrivateData
= VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This
);
106 ZeroMem (&Configuration
, sizeof (VLAN_CONFIGURATION
));
107 BufferSize
= sizeof (Configuration
);
108 ConfigRequest
= Request
;
109 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
111 // Request has no request element, construct full request string.
112 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
113 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
115 ConfigRequestHdr
= HiiConstructConfigHdr (&gVlanConfigFormSetGuid
, mVlanStorageName
, PrivateData
->DriverHandle
);
116 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
117 ConfigRequest
= AllocateZeroPool (Size
);
118 ASSERT (ConfigRequest
!= NULL
);
119 AllocatedRequest
= TRUE
;
120 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
121 FreePool (ConfigRequestHdr
);
124 Status
= mHiiConfigRouting
->BlockToConfig (
127 (UINT8
*)&Configuration
,
133 // Free the allocated config request string.
135 if (AllocatedRequest
) {
136 FreePool (ConfigRequest
);
137 ConfigRequest
= NULL
;
141 // Set Progress string to the original request string.
143 if (Request
== NULL
) {
145 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
146 *Progress
= Request
+ StrLen (Request
);
153 This function processes the results of changes in configuration.
155 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
156 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
158 @param[out] Progress A pointer to a string filled in with the offset of
159 the most recent '&' before the first failing
160 name/value pair (or the beginning of the string if
161 the failure is in the first name/value pair) or
162 the terminating NULL if all was successful.
164 @retval EFI_SUCCESS The Results is processed successfully.
165 @retval EFI_INVALID_PARAMETER Configuration is NULL.
166 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
173 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
174 IN CONST EFI_STRING Configuration
,
175 OUT EFI_STRING
*Progress
178 if ((Configuration
== NULL
) || (Progress
== NULL
)) {
179 return EFI_INVALID_PARAMETER
;
182 *Progress
= Configuration
;
183 if (!HiiIsConfigHdrMatch (Configuration
, &gVlanConfigFormSetGuid
, mVlanStorageName
)) {
184 return EFI_NOT_FOUND
;
187 *Progress
= Configuration
+ StrLen (Configuration
);
192 This function processes the results of changes in configuration.
194 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
195 @param[in] Action Specifies the type of action taken by the browser.
196 @param[in] QuestionId A unique value which is sent to the original
197 exporting driver so that it can identify the type
199 @param[in] Type The type of value for the question.
200 @param[in] Value A pointer to the data being sent to the original
202 @param[out] ActionRequest On return, points to the action requested by the
205 @retval EFI_SUCCESS The callback successfully handled the action.
206 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
207 variable and its data.
208 @retval EFI_DEVICE_ERROR The variable could not be saved.
209 @retval EFI_UNSUPPORTED The specified Action is not supported by the
216 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
217 IN EFI_BROWSER_ACTION Action
,
218 IN EFI_QUESTION_ID QuestionId
,
220 IN EFI_IFR_TYPE_VALUE
*Value
,
221 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
224 VLAN_CONFIG_PRIVATE_DATA
*PrivateData
;
225 VLAN_CONFIGURATION
*Configuration
;
226 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
228 EFI_HANDLE VlanHandle
;
230 PrivateData
= VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This
);
232 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
236 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) && (Action
!= EFI_BROWSER_ACTION_CHANGING
)) {
238 // All other action return unsupported.
240 return EFI_UNSUPPORTED
;
246 Configuration
= AllocateZeroPool (sizeof (VLAN_CONFIGURATION
));
247 ASSERT (Configuration
!= NULL
);
248 HiiGetBrowserData (&gVlanConfigFormSetGuid
, mVlanStorageName
, sizeof (VLAN_CONFIGURATION
), (UINT8
*)Configuration
);
250 VlanConfig
= PrivateData
->VlanConfig
;
252 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
253 switch (QuestionId
) {
254 case VLAN_ADD_QUESTION_ID
:
258 VlanConfig
->Set (VlanConfig
, Configuration
->VlanId
, Configuration
->Priority
);
259 VlanUpdateForm (PrivateData
);
262 // Connect the newly created VLAN device
264 VlanHandle
= NetLibGetVlanHandle (PrivateData
->ControllerHandle
, Configuration
->VlanId
);
265 if (VlanHandle
== NULL
) {
267 // There may be no child handle created for VLAN ID 0, connect the parent handle
269 VlanHandle
= PrivateData
->ControllerHandle
;
272 gBS
->ConnectController (VlanHandle
, NULL
, NULL
, TRUE
);
277 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
278 Configuration
->VlanId
= 0;
279 Configuration
->Priority
= 0;
282 case VLAN_REMOVE_QUESTION_ID
:
286 ASSERT (PrivateData
->NumberOfVlan
<= MAX_VLAN_NUMBER
);
287 for (Index
= 0; Index
< PrivateData
->NumberOfVlan
; Index
++) {
288 if (Configuration
->VlanList
[Index
] != 0) {
290 // Checkbox is selected, need remove this VLAN
292 VlanConfig
->Remove (VlanConfig
, PrivateData
->VlanId
[Index
]);
296 VlanUpdateForm (PrivateData
);
297 if (PrivateData
->NumberOfVlan
== 0) {
299 // No VLAN device now, connect the physical NIC handle.
300 // Note: PrivateData->NumberOfVlan has been updated by VlanUpdateForm()
302 gBS
->ConnectController (PrivateData
->ControllerHandle
, NULL
, NULL
, TRUE
);
305 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
306 ZeroMem (Configuration
->VlanList
, MAX_VLAN_NUMBER
);
312 } else if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
313 switch (QuestionId
) {
314 case VLAN_UPDATE_QUESTION_ID
:
316 // Update current VLAN list into Form.
318 VlanUpdateForm (PrivateData
);
326 HiiSetBrowserData (&gVlanConfigFormSetGuid
, mVlanStorageName
, sizeof (VLAN_CONFIGURATION
), (UINT8
*)Configuration
, NULL
);
327 FreePool (Configuration
);
332 This function update VLAN list in the VLAN configuration Form.
334 @param[in, out] PrivateData Points to VLAN configuration private data.
339 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
342 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
345 EFI_VLAN_FIND_DATA
*VlanData
;
346 VOID
*StartOpCodeHandle
;
347 EFI_IFR_GUID_LABEL
*StartLabel
;
348 VOID
*EndOpCodeHandle
;
349 EFI_IFR_GUID_LABEL
*EndLabel
;
354 EFI_STRING_ID StringId
;
357 // Find current VLAN configuration
361 VlanConfig
= PrivateData
->VlanConfig
;
362 VlanConfig
->Find (VlanConfig
, NULL
, &NumberOfVlan
, &VlanData
);
365 // Update VLAN configuration in PrivateData
367 if (NumberOfVlan
> MAX_VLAN_NUMBER
) {
368 NumberOfVlan
= MAX_VLAN_NUMBER
;
371 PrivateData
->NumberOfVlan
= NumberOfVlan
;
374 // Init OpCode Handle
376 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
377 ASSERT (StartOpCodeHandle
!= NULL
);
379 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
380 ASSERT (EndOpCodeHandle
!= NULL
);
383 // Create Hii Extend Label OpCode as the start opcode
385 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
389 sizeof (EFI_IFR_GUID_LABEL
)
391 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
392 StartLabel
->Number
= LABEL_VLAN_LIST
;
395 // Create Hii Extend Label OpCode as the end opcode
397 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (
401 sizeof (EFI_IFR_GUID_LABEL
)
403 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
404 EndLabel
->Number
= LABEL_END
;
406 ZeroMem (PrivateData
->VlanId
, MAX_VLAN_NUMBER
);
407 for (Index
= 0; Index
< NumberOfVlan
; Index
++) {
410 StrCpyS (String
, (sizeof (VlanStr
) /sizeof (CHAR16
)), L
" VLAN ID:");
413 // Pad VlanId string up to 4 characters with space
415 UnicodeValueToStringS (VlanIdStr
, sizeof (VlanIdStr
), 0, VlanData
[Index
].VlanId
, 5);
416 DigitalCount
= StrnLenS (VlanIdStr
, ARRAY_SIZE (VlanIdStr
));
417 SetMem16 (String
, (4 - DigitalCount
) * sizeof (CHAR16
), L
' ');
418 StrCpyS (String
+ 4 - DigitalCount
, (sizeof (VlanStr
) /sizeof (CHAR16
)) - 10 - (4 - DigitalCount
), VlanIdStr
);
421 StrCpyS (String
, (sizeof (VlanStr
) /sizeof (CHAR16
)) - 10 - (4 - DigitalCount
) - 4, L
", Priority:");
423 UnicodeValueToStringS (
425 sizeof (VlanStr
) - ((UINTN
)String
- (UINTN
)VlanStr
),
427 VlanData
[Index
].Priority
,
430 String
+= StrnLenS (String
, ARRAY_SIZE (VlanStr
) - ((UINTN
)String
- (UINTN
)VlanStr
) / sizeof (CHAR16
));
433 StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, VlanStr
, NULL
);
434 ASSERT (StringId
!= 0);
436 HiiCreateCheckBoxOpCode (
438 (EFI_QUESTION_ID
)(VLAN_LIST_VAR_OFFSET
+ Index
),
439 VLAN_CONFIGURATION_VARSTORE_ID
,
440 (UINT16
)(VLAN_LIST_VAR_OFFSET
+ Index
),
442 STRING_TOKEN (STR_VLAN_VLAN_LIST_HELP
),
449 // Save VLAN id to private data
451 PrivateData
->VlanId
[Index
] = VlanData
[Index
].VlanId
;
455 PrivateData
->HiiHandle
, // HII handle
456 &gVlanConfigFormSetGuid
, // Formset GUID
457 VLAN_CONFIGURATION_FORM_ID
, // Form ID
458 StartOpCodeHandle
, // Label for where to insert opcodes
459 EndOpCodeHandle
// Replace data
462 HiiFreeOpCodeHandle (StartOpCodeHandle
);
463 HiiFreeOpCodeHandle (EndOpCodeHandle
);
465 if (VlanData
!= NULL
) {
471 This function publish the VLAN configuration Form for a network device. The
472 HII Config Access protocol will be installed on a child handle of the network
475 @param[in, out] PrivateData Points to VLAN configuration private data.
477 @retval EFI_SUCCESS HII Form is installed for this network device.
478 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
479 @retval Others Other errors as indicated.
483 InstallVlanConfigForm (
484 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
488 EFI_HII_HANDLE HiiHandle
;
489 EFI_HANDLE DriverHandle
;
490 CHAR16 Str
[26 + sizeof (EFI_MAC_ADDRESS
) * 2 + 1];
492 EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
;
493 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
494 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
497 // Create child handle and install HII Config Access Protocol
499 ChildDevicePath
= AppendDevicePathNode (
500 PrivateData
->ParentDevicePath
,
501 (CONST EFI_DEVICE_PATH_PROTOCOL
*)&mHiiVendorDevicePathNode
503 if (ChildDevicePath
== NULL
) {
504 return EFI_OUT_OF_RESOURCES
;
507 PrivateData
->ChildDevicePath
= ChildDevicePath
;
510 ConfigAccess
= &PrivateData
->ConfigAccess
;
511 Status
= gBS
->InstallMultipleProtocolInterfaces (
513 &gEfiDevicePathProtocolGuid
,
515 &gEfiHiiConfigAccessProtocolGuid
,
519 if (EFI_ERROR (Status
)) {
523 PrivateData
->DriverHandle
= DriverHandle
;
526 // Establish the parent-child relationship between the new created
527 // child handle and the ControllerHandle.
529 Status
= gBS
->OpenProtocol (
530 PrivateData
->ControllerHandle
,
531 &gEfiVlanConfigProtocolGuid
,
532 (VOID
**)&VlanConfig
,
533 PrivateData
->ImageHandle
,
534 PrivateData
->DriverHandle
,
535 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
537 if (EFI_ERROR (Status
)) {
542 // Publish the HII package list
544 HiiHandle
= HiiAddPackages (
545 &gVlanConfigFormSetGuid
,
547 VlanConfigDxeStrings
,
551 if (HiiHandle
== NULL
) {
552 return EFI_OUT_OF_RESOURCES
;
555 PrivateData
->HiiHandle
= HiiHandle
;
558 // Update formset title help string.
561 Status
= NetLibGetMacString (PrivateData
->ControllerHandle
, PrivateData
->ImageHandle
, &MacString
);
562 if (EFI_ERROR (Status
)) {
566 PrivateData
->MacString
= MacString
;
568 StrCpyS (Str
, sizeof (Str
) / sizeof (CHAR16
), L
"VLAN Configuration (MAC:");
569 StrCatS (Str
, sizeof (Str
) / sizeof (CHAR16
), MacString
);
570 StrCatS (Str
, sizeof (Str
) / sizeof (CHAR16
), L
")");
573 STRING_TOKEN (STR_VLAN_FORM_SET_TITLE_HELP
),
579 // Update form title help string.
583 STRING_TOKEN (STR_VLAN_FORM_HELP
),
592 This function remove the VLAN configuration Form for a network device. The
593 child handle for HII Config Access protocol will be destroyed.
595 @param[in, out] PrivateData Points to VLAN configuration private data.
597 @retval EFI_SUCCESS HII Form has been uninstalled successfully.
598 @retval Others Other errors as indicated.
602 UninstallVlanConfigForm (
603 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
607 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
610 // End the parent-child relationship.
612 Status
= gBS
->CloseProtocol (
613 PrivateData
->ControllerHandle
,
614 &gEfiVlanConfigProtocolGuid
,
615 PrivateData
->ImageHandle
,
616 PrivateData
->DriverHandle
618 if (EFI_ERROR (Status
)) {
623 // Uninstall HII Config Access Protocol
625 if (PrivateData
->DriverHandle
!= NULL
) {
626 Status
= gBS
->UninstallMultipleProtocolInterfaces (
627 PrivateData
->DriverHandle
,
628 &gEfiDevicePathProtocolGuid
,
629 PrivateData
->ChildDevicePath
,
630 &gEfiHiiConfigAccessProtocolGuid
,
631 &PrivateData
->ConfigAccess
,
634 if (EFI_ERROR (Status
)) {
636 PrivateData
->ControllerHandle
,
637 &gEfiVlanConfigProtocolGuid
,
638 (VOID
**)&VlanConfig
,
639 PrivateData
->ImageHandle
,
640 PrivateData
->DriverHandle
,
641 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
646 PrivateData
->DriverHandle
= NULL
;
648 if (PrivateData
->ChildDevicePath
!= NULL
) {
649 FreePool (PrivateData
->ChildDevicePath
);
650 PrivateData
->ChildDevicePath
= NULL
;
657 if (PrivateData
->MacString
!= NULL
) {
658 FreePool (PrivateData
->MacString
);
659 PrivateData
->MacString
= NULL
;
663 // Uninstall HII package list
665 if (PrivateData
->HiiHandle
!= NULL
) {
666 HiiRemovePackages (PrivateData
->HiiHandle
);
667 PrivateData
->HiiHandle
= NULL
;