]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigImpl.c
f992cea07b80bc6a742f86d40dbf4543d9e019c3
[mirror_edk2.git] / MdeModulePkg / Universal / Network / VlanConfigDxe / VlanConfigImpl.c
1 /** @file
2 HII Config Access protocol implementation of VLAN configuration module.
3
4 Copyright (c) 2009 - 2011, 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 StrCpy (String, 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 StrCpy (String + 4 - DigitalCount, VlanIdStr);
423 String += 4;
424
425 StrCpy (String, 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
493 //
494 // Create child handle and install HII Config Access Protocol
495 //
496 ChildDevicePath = AppendDevicePathNode (
497 PrivateData->ParentDevicePath,
498 (CONST EFI_DEVICE_PATH_PROTOCOL *) &mHiiVendorDevicePathNode
499 );
500 if (ChildDevicePath == NULL) {
501 return EFI_OUT_OF_RESOURCES;
502 }
503 PrivateData->ChildDevicePath = ChildDevicePath;
504
505 DriverHandle = NULL;
506 ConfigAccess = &PrivateData->ConfigAccess;
507 Status = gBS->InstallMultipleProtocolInterfaces (
508 &DriverHandle,
509 &gEfiDevicePathProtocolGuid,
510 ChildDevicePath,
511 &gEfiHiiConfigAccessProtocolGuid,
512 ConfigAccess,
513 NULL
514 );
515 if (EFI_ERROR (Status)) {
516 return Status;
517 }
518 PrivateData->DriverHandle = DriverHandle;
519
520 //
521 // Publish the HII package list
522 //
523 HiiHandle = HiiAddPackages (
524 &gVlanConfigFormSetGuid,
525 DriverHandle,
526 VlanConfigDxeStrings,
527 VlanConfigBin,
528 NULL
529 );
530 if (HiiHandle == NULL) {
531 return EFI_OUT_OF_RESOURCES;
532 }
533 PrivateData->HiiHandle = HiiHandle;
534
535 //
536 // Update formset title help string.
537 //
538 MacString = NULL;
539 Status = NetLibGetMacString (PrivateData->ControllerHandle, PrivateData->ImageHandle, &MacString);
540 if (EFI_ERROR (Status)) {
541 return Status;
542 }
543 PrivateData->MacString = MacString;
544
545 StrCpy (Str, L"VLAN Configuration (MAC:");
546 StrnCat (Str, MacString, sizeof (EFI_MAC_ADDRESS) * 2);
547 StrCat (Str, L")");
548 HiiSetString (
549 HiiHandle,
550 STRING_TOKEN (STR_VLAN_FORM_SET_TITLE_HELP),
551 Str,
552 NULL
553 );
554
555 //
556 // Update form title help string.
557 //
558 HiiSetString (
559 HiiHandle,
560 STRING_TOKEN (STR_VLAN_FORM_HELP),
561 Str,
562 NULL
563 );
564
565 return EFI_SUCCESS;
566 }
567
568 /**
569 This function remove the VLAN configuration Form for a network device. The
570 child handle for HII Config Access protocol will be destroyed.
571
572 @param[in, out] PrivateData Points to VLAN configuration private data.
573
574 **/
575 VOID
576 UninstallVlanConfigForm (
577 IN OUT VLAN_CONFIG_PRIVATE_DATA *PrivateData
578 )
579 {
580 //
581 // Free MAC string
582 //
583 if (PrivateData->MacString != NULL) {
584 FreePool (PrivateData->MacString);
585 PrivateData->MacString = NULL;
586 }
587
588 //
589 // Uninstall HII package list
590 //
591 if (PrivateData->HiiHandle != NULL) {
592 HiiRemovePackages (PrivateData->HiiHandle);
593 PrivateData->HiiHandle = NULL;
594 }
595
596 //
597 // Uninstall HII Config Access Protocol
598 //
599 if (PrivateData->DriverHandle != NULL) {
600 gBS->UninstallMultipleProtocolInterfaces (
601 PrivateData->DriverHandle,
602 &gEfiDevicePathProtocolGuid,
603 PrivateData->ChildDevicePath,
604 &gEfiHiiConfigAccessProtocolGuid,
605 &PrivateData->ConfigAccess,
606 NULL
607 );
608 PrivateData->DriverHandle = NULL;
609
610 if (PrivateData->ChildDevicePath != NULL) {
611 FreePool (PrivateData->ChildDevicePath);
612 PrivateData->ChildDevicePath = NULL;
613 }
614 }
615 }