2 HII Config Access protocol implementation of VLAN configuration module.
4 Copyright (c) 2009 - 2018, 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
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.
16 #include "VlanConfigImpl.h"
18 CHAR16 mVlanStorageName
[] = L
"VlanNvData";
19 EFI_HII_CONFIG_ROUTING_PROTOCOL
*mHiiConfigRouting
= NULL
;
21 VLAN_CONFIG_PRIVATE_DATA mVlanConfigPrivateDateTemplate
= {
22 VLAN_CONFIG_PRIVATE_DATA_SIGNATURE
,
30 VENDOR_DEVICE_PATH mHiiVendorDevicePathNode
= {
35 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
36 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
39 VLAN_CONFIG_FORM_SET_GUID
43 This function allows a caller to extract the current configuration for one
44 or more named elements from the target driver.
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
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.
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
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
79 VLAN_CONFIGURATION Configuration
;
80 VLAN_CONFIG_PRIVATE_DATA
*PrivateData
;
81 EFI_STRING ConfigRequestHdr
;
82 EFI_STRING ConfigRequest
;
83 BOOLEAN AllocatedRequest
;
86 if (Progress
== NULL
|| Results
== NULL
) {
87 return EFI_INVALID_PARAMETER
;
91 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gVlanConfigFormSetGuid
, mVlanStorageName
)) {
95 ConfigRequestHdr
= NULL
;
97 AllocatedRequest
= FALSE
;
101 // Retrieve the pointer to the UEFI HII Config Routing Protocol
103 if (mHiiConfigRouting
== NULL
) {
104 gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**) &mHiiConfigRouting
);
106 ASSERT (mHiiConfigRouting
!= NULL
);
109 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
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
)) {
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
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
);
130 Status
= mHiiConfigRouting
->BlockToConfig (
133 (UINT8
*) &Configuration
,
139 // Free the allocated config request string.
141 if (AllocatedRequest
) {
142 FreePool (ConfigRequest
);
143 ConfigRequest
= NULL
;
146 // Set Progress string to the original request string.
148 if (Request
== NULL
) {
150 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
151 *Progress
= Request
+ StrLen (Request
);
159 This function processes the results of changes in configuration.
161 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
162 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
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.
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
179 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
180 IN CONST EFI_STRING Configuration
,
181 OUT EFI_STRING
*Progress
184 if (Configuration
== NULL
|| Progress
== NULL
) {
185 return EFI_INVALID_PARAMETER
;
188 *Progress
= Configuration
;
189 if (!HiiIsConfigHdrMatch (Configuration
, &gVlanConfigFormSetGuid
, mVlanStorageName
)) {
190 return EFI_NOT_FOUND
;
193 *Progress
= Configuration
+ StrLen (Configuration
);
198 This function processes the results of changes in configuration.
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
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
208 @param[out] ActionRequest On return, points to the action requested by the
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
222 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
223 IN EFI_BROWSER_ACTION Action
,
224 IN EFI_QUESTION_ID QuestionId
,
226 IN EFI_IFR_TYPE_VALUE
*Value
,
227 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
230 VLAN_CONFIG_PRIVATE_DATA
*PrivateData
;
231 VLAN_CONFIGURATION
*Configuration
;
232 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
234 EFI_HANDLE VlanHandle
;
236 PrivateData
= VLAN_CONFIG_PRIVATE_DATA_FROM_THIS (This
);
238 if ((Action
== EFI_BROWSER_ACTION_FORM_OPEN
) || (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
)) {
242 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) && (Action
!= EFI_BROWSER_ACTION_CHANGING
)) {
244 // All other action return unsupported.
246 return EFI_UNSUPPORTED
;
252 Configuration
= AllocateZeroPool (sizeof (VLAN_CONFIGURATION
));
253 ASSERT (Configuration
!= NULL
);
254 HiiGetBrowserData (&gVlanConfigFormSetGuid
, mVlanStorageName
, sizeof (VLAN_CONFIGURATION
), (UINT8
*) Configuration
);
256 VlanConfig
= PrivateData
->VlanConfig
;
258 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
259 switch (QuestionId
) {
260 case VLAN_ADD_QUESTION_ID
:
264 VlanConfig
->Set (VlanConfig
, Configuration
->VlanId
, Configuration
->Priority
);
265 VlanUpdateForm (PrivateData
);
268 // Connect the newly created VLAN device
270 VlanHandle
= NetLibGetVlanHandle (PrivateData
->ControllerHandle
, Configuration
->VlanId
);
271 if (VlanHandle
== NULL
) {
273 // There may be no child handle created for VLAN ID 0, connect the parent handle
275 VlanHandle
= PrivateData
->ControllerHandle
;
277 gBS
->ConnectController (VlanHandle
, NULL
, NULL
, TRUE
);
282 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
283 Configuration
->VlanId
= 0;
284 Configuration
->Priority
= 0;
287 case VLAN_REMOVE_QUESTION_ID
:
291 ASSERT (PrivateData
->NumberOfVlan
<= MAX_VLAN_NUMBER
);
292 for (Index
= 0; Index
< PrivateData
->NumberOfVlan
; Index
++) {
293 if (Configuration
->VlanList
[Index
] != 0) {
295 // Checkbox is selected, need remove this VLAN
297 VlanConfig
->Remove (VlanConfig
, PrivateData
->VlanId
[Index
]);
301 VlanUpdateForm (PrivateData
);
302 if (PrivateData
->NumberOfVlan
== 0) {
304 // No VLAN device now, connect the physical NIC handle.
305 // Note: PrivateData->NumberOfVlan has been updated by VlanUpdateForm()
307 gBS
->ConnectController (PrivateData
->ControllerHandle
, NULL
, NULL
, TRUE
);
310 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
311 ZeroMem (Configuration
->VlanList
, MAX_VLAN_NUMBER
);
317 } else if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
318 switch (QuestionId
) {
319 case VLAN_UPDATE_QUESTION_ID
:
321 // Update current VLAN list into Form.
323 VlanUpdateForm (PrivateData
);
331 HiiSetBrowserData (&gVlanConfigFormSetGuid
, mVlanStorageName
, sizeof (VLAN_CONFIGURATION
), (UINT8
*) Configuration
, NULL
);
332 FreePool (Configuration
);
338 This function update VLAN list in the VLAN configuration Form.
340 @param[in, out] PrivateData Points to VLAN configuration private data.
345 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
348 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
351 EFI_VLAN_FIND_DATA
*VlanData
;
352 VOID
*StartOpCodeHandle
;
353 EFI_IFR_GUID_LABEL
*StartLabel
;
354 VOID
*EndOpCodeHandle
;
355 EFI_IFR_GUID_LABEL
*EndLabel
;
360 EFI_STRING_ID StringId
;
363 // Find current VLAN configuration
367 VlanConfig
= PrivateData
->VlanConfig
;
368 VlanConfig
->Find (VlanConfig
, NULL
, &NumberOfVlan
, &VlanData
);
371 // Update VLAN configuration in PrivateData
373 if (NumberOfVlan
> MAX_VLAN_NUMBER
) {
374 NumberOfVlan
= MAX_VLAN_NUMBER
;
376 PrivateData
->NumberOfVlan
= NumberOfVlan
;
379 // Init OpCode Handle
381 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
382 ASSERT (StartOpCodeHandle
!= NULL
);
384 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
385 ASSERT (EndOpCodeHandle
!= NULL
);
388 // Create Hii Extend Label OpCode as the start opcode
390 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
394 sizeof (EFI_IFR_GUID_LABEL
)
396 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
397 StartLabel
->Number
= LABEL_VLAN_LIST
;
400 // Create Hii Extend Label OpCode as the end opcode
402 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
406 sizeof (EFI_IFR_GUID_LABEL
)
408 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
409 EndLabel
->Number
= LABEL_END
;
411 ZeroMem (PrivateData
->VlanId
, MAX_VLAN_NUMBER
);
412 for (Index
= 0; Index
< NumberOfVlan
; Index
++) {
415 StrCpyS (String
, (sizeof (VlanStr
) /sizeof (CHAR16
)), L
" VLAN ID:");
418 // Pad VlanId string up to 4 characters with space
420 UnicodeValueToStringS (VlanIdStr
, sizeof (VlanIdStr
), 0, VlanData
[Index
].VlanId
, 5);
421 DigitalCount
= StrnLenS (VlanIdStr
, ARRAY_SIZE (VlanIdStr
));
422 SetMem16 (String
, (4 - DigitalCount
) * sizeof (CHAR16
), L
' ');
423 StrCpyS (String
+ 4 - DigitalCount
, (sizeof (VlanStr
) /sizeof (CHAR16
)) - 10 - (4 - DigitalCount
), VlanIdStr
);
426 StrCpyS (String
, (sizeof (VlanStr
) /sizeof (CHAR16
)) - 10 - (4 - DigitalCount
) - 4, L
", Priority:");
428 UnicodeValueToStringS (
430 sizeof (VlanStr
) - ((UINTN
)String
- (UINTN
)VlanStr
),
432 VlanData
[Index
].Priority
,
435 String
+= StrnLenS (String
, ARRAY_SIZE (VlanStr
) - ((UINTN
)String
- (UINTN
)VlanStr
) / sizeof (CHAR16
));
438 StringId
= HiiSetString (PrivateData
->HiiHandle
, 0, VlanStr
, NULL
);
439 ASSERT (StringId
!= 0);
441 HiiCreateCheckBoxOpCode (
443 (EFI_QUESTION_ID
) (VLAN_LIST_VAR_OFFSET
+ Index
),
444 VLAN_CONFIGURATION_VARSTORE_ID
,
445 (UINT16
) (VLAN_LIST_VAR_OFFSET
+ Index
),
447 STRING_TOKEN (STR_VLAN_VLAN_LIST_HELP
),
454 // Save VLAN id to private data
456 PrivateData
->VlanId
[Index
] = VlanData
[Index
].VlanId
;
460 PrivateData
->HiiHandle
, // HII handle
461 &gVlanConfigFormSetGuid
, // Formset GUID
462 VLAN_CONFIGURATION_FORM_ID
, // Form ID
463 StartOpCodeHandle
, // Label for where to insert opcodes
464 EndOpCodeHandle
// Replace data
467 HiiFreeOpCodeHandle (StartOpCodeHandle
);
468 HiiFreeOpCodeHandle (EndOpCodeHandle
);
470 if (VlanData
!= NULL
) {
477 This function publish the VLAN configuration Form for a network device. The
478 HII Config Access protocol will be installed on a child handle of the network
481 @param[in, out] PrivateData Points to VLAN configuration private data.
483 @retval EFI_SUCCESS HII Form is installed for this network device.
484 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
485 @retval Others Other errors as indicated.
489 InstallVlanConfigForm (
490 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
494 EFI_HII_HANDLE HiiHandle
;
495 EFI_HANDLE DriverHandle
;
496 CHAR16 Str
[26 + sizeof (EFI_MAC_ADDRESS
) * 2 + 1];
498 EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
;
499 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
500 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
503 // Create child handle and install HII Config Access Protocol
505 ChildDevicePath
= AppendDevicePathNode (
506 PrivateData
->ParentDevicePath
,
507 (CONST EFI_DEVICE_PATH_PROTOCOL
*) &mHiiVendorDevicePathNode
509 if (ChildDevicePath
== NULL
) {
510 return EFI_OUT_OF_RESOURCES
;
512 PrivateData
->ChildDevicePath
= ChildDevicePath
;
515 ConfigAccess
= &PrivateData
->ConfigAccess
;
516 Status
= gBS
->InstallMultipleProtocolInterfaces (
518 &gEfiDevicePathProtocolGuid
,
520 &gEfiHiiConfigAccessProtocolGuid
,
524 if (EFI_ERROR (Status
)) {
527 PrivateData
->DriverHandle
= DriverHandle
;
530 // Establish the parent-child relationship between the new created
531 // child handle and the ControllerHandle.
533 Status
= gBS
->OpenProtocol (
534 PrivateData
->ControllerHandle
,
535 &gEfiVlanConfigProtocolGuid
,
536 (VOID
**)&VlanConfig
,
537 PrivateData
->ImageHandle
,
538 PrivateData
->DriverHandle
,
539 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
541 if (EFI_ERROR (Status
)) {
546 // Publish the HII package list
548 HiiHandle
= HiiAddPackages (
549 &gVlanConfigFormSetGuid
,
551 VlanConfigDxeStrings
,
555 if (HiiHandle
== NULL
) {
556 return EFI_OUT_OF_RESOURCES
;
558 PrivateData
->HiiHandle
= HiiHandle
;
561 // Update formset title help string.
564 Status
= NetLibGetMacString (PrivateData
->ControllerHandle
, PrivateData
->ImageHandle
, &MacString
);
565 if (EFI_ERROR (Status
)) {
568 PrivateData
->MacString
= MacString
;
570 StrCpyS (Str
, sizeof (Str
) / sizeof (CHAR16
), L
"VLAN Configuration (MAC:");
571 StrCatS (Str
, sizeof (Str
) / sizeof (CHAR16
), MacString
);
572 StrCatS (Str
, sizeof (Str
) / sizeof (CHAR16
), L
")");
575 STRING_TOKEN (STR_VLAN_FORM_SET_TITLE_HELP
),
581 // Update form title help string.
585 STRING_TOKEN (STR_VLAN_FORM_HELP
),
594 This function remove the VLAN configuration Form for a network device. The
595 child handle for HII Config Access protocol will be destroyed.
597 @param[in, out] PrivateData Points to VLAN configuration private data.
599 @retval EFI_SUCCESS HII Form has been uninstalled successfully.
600 @retval Others Other errors as indicated.
604 UninstallVlanConfigForm (
605 IN OUT VLAN_CONFIG_PRIVATE_DATA
*PrivateData
609 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
612 // End the parent-child relationship.
614 Status
= gBS
->CloseProtocol (
615 PrivateData
->ControllerHandle
,
616 &gEfiVlanConfigProtocolGuid
,
617 PrivateData
->ImageHandle
,
618 PrivateData
->DriverHandle
620 if (EFI_ERROR (Status
)) {
625 // Uninstall HII Config Access Protocol
627 if (PrivateData
->DriverHandle
!= NULL
) {
628 Status
= gBS
->UninstallMultipleProtocolInterfaces (
629 PrivateData
->DriverHandle
,
630 &gEfiDevicePathProtocolGuid
,
631 PrivateData
->ChildDevicePath
,
632 &gEfiHiiConfigAccessProtocolGuid
,
633 &PrivateData
->ConfigAccess
,
636 if (EFI_ERROR (Status
)) {
638 PrivateData
->ControllerHandle
,
639 &gEfiVlanConfigProtocolGuid
,
640 (VOID
**)&VlanConfig
,
641 PrivateData
->ImageHandle
,
642 PrivateData
->DriverHandle
,
643 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
647 PrivateData
->DriverHandle
= NULL
;
649 if (PrivateData
->ChildDevicePath
!= NULL
) {
650 FreePool (PrivateData
->ChildDevicePath
);
651 PrivateData
->ChildDevicePath
= NULL
;
658 if (PrivateData
->MacString
!= NULL
) {
659 FreePool (PrivateData
->MacString
);
660 PrivateData
->MacString
= NULL
;
664 // Uninstall HII package list
666 if (PrivateData
->HiiHandle
!= NULL
) {
667 HiiRemovePackages (PrivateData
->HiiHandle
);
668 PrivateData
->HiiHandle
= NULL
;