]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpBootDxe/HttpBootConfig.c
NetworkPkg: Fix HII related problem in HTTP boot driver.
[mirror_edk2.git] / NetworkPkg / HttpBootDxe / HttpBootConfig.c
CommitLineData
fa848a40
FS
1/** @file\r
2 Helper functions for configuring or getting the parameters relating to HTTP Boot.\r
3\r
4Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "HttpBootDxe.h"\r
16\r
17CHAR16 mHttpBootConfigStorageName[] = L"HTTP_BOOT_CONFIG_IFR_NVDATA";\r
18\r
19/**\r
20 Add new boot option for HTTP boot.\r
21\r
22 @param[in] Private Pointer to the driver private data.\r
23 @param[in] UsingIpv6 Set to TRUE if creating boot option for IPv6.\r
24 @param[in] Description The description text of the boot option.\r
25 @param[in] Uri The URI string of the boot file.\r
26 \r
27 @retval EFI_SUCCESS The boot option is created successfully.\r
28 @retval Others Failed to create new boot option.\r
29\r
30**/\r
31EFI_STATUS\r
32HttpBootAddBootOption (\r
33 IN HTTP_BOOT_PRIVATE_DATA *Private,\r
34 IN BOOLEAN UsingIpv6,\r
35 IN CHAR16 *Description,\r
36 IN CHAR16 *Uri\r
37 )\r
38{\r
39 EFI_DEV_PATH *Node;\r
40 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
41 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
42 UINTN Length;\r
43 CHAR8 AsciiUri[URI_STR_MAX_SIZE];\r
44 CHAR16 *CurrentOrder;\r
45 EFI_STATUS Status;\r
46 UINTN OrderCount;\r
47 UINTN TargetLocation;\r
48 BOOLEAN Found;\r
49 UINT8 *TempByteBuffer;\r
50 UINT8 *TempByteStart;\r
51 UINTN DescSize;\r
52 UINTN FilePathSize;\r
53 CHAR16 OptionStr[10];\r
54 UINT16 *NewOrder;\r
55 UINTN Index;\r
56\r
57 NewOrder = NULL;\r
58 TempByteStart = NULL;\r
59 NewDevicePath = NULL;\r
60 NewOrder = NULL;\r
61 Node = NULL;\r
62 TmpDevicePath = NULL;\r
63 CurrentOrder = NULL;\r
64\r
65 if (StrLen (Description) == 0) {\r
66 return EFI_INVALID_PARAMETER;\r
67 }\r
68\r
69 //\r
70 // Convert the scheme to all lower case.\r
71 //\r
72 for (Index = 0; Index < StrLen (Uri); Index++) {\r
73 if (Uri[Index] == L':') {\r
74 break;\r
75 }\r
76 if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') {\r
77 Uri[Index] -= (CHAR16)(L'A' - L'a');\r
78 }\r
79 }\r
80\r
81 //\r
82 // Only accept http and https URI.\r
83 //\r
84 if ((StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 7) != 0)) {\r
85 return EFI_INVALID_PARAMETER;\r
86 }\r
87 \r
88 //\r
89 // Create a new device path by appending the IP node and URI node to\r
90 // the driver's parent device path\r
91 //\r
92 if (!UsingIpv6) {\r
93 Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));\r
94 if (Node == NULL) {\r
95 Status = EFI_OUT_OF_RESOURCES;\r
96 goto ON_EXIT;\r
97 }\r
98 Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH;\r
99 Node->Ipv4.Header.SubType = MSG_IPv4_DP;\r
100 SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));\r
101 } else {\r
102 Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));\r
103 if (Node == NULL) {\r
104 Status = EFI_OUT_OF_RESOURCES;\r
105 goto ON_EXIT;\r
106 }\r
107 Node->Ipv6.Header.Type = MESSAGING_DEVICE_PATH;\r
108 Node->Ipv6.Header.SubType = MSG_IPv6_DP;\r
109 SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH));\r
110 }\r
111 TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
112 FreePool (Node);\r
113 if (TmpDevicePath == NULL) {\r
114 return EFI_OUT_OF_RESOURCES;\r
115 }\r
116 //\r
117 // Update the URI node with the input boot file URI.\r
118 //\r
119 UnicodeStrToAsciiStr (Uri, AsciiUri);\r
120 Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri);\r
121 Node = AllocatePool (Length);\r
122 if (Node == NULL) {\r
123 Status = EFI_OUT_OF_RESOURCES;\r
124 FreePool (TmpDevicePath);\r
125 goto ON_EXIT;\r
126 }\r
127 Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
128 Node->DevPath.SubType = MSG_URI_DP;\r
129 SetDevicePathNodeLength (Node, Length);\r
130 CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), AsciiUri, AsciiStrSize (AsciiUri));\r
131 NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
132 FreePool (Node);\r
133 FreePool (TmpDevicePath);\r
134 if (NewDevicePath == NULL) {\r
135 Status = EFI_OUT_OF_RESOURCES;\r
136 goto ON_EXIT;\r
137 }\r
138\r
139 //\r
140 // Get current "BootOrder" variable and find a free target.\r
141 //\r
142 Length = 0;\r
143 Status = GetVariable2 (\r
144 L"BootOrder",\r
145 &gEfiGlobalVariableGuid,\r
8244e197 146 (VOID **)&CurrentOrder,\r
fa848a40
FS
147 &Length \r
148 );\r
149 if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
150 goto ON_EXIT;\r
151 }\r
152 OrderCount = Length / sizeof (UINT16);\r
153 Found = FALSE;\r
154 for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {\r
155 Found = TRUE;\r
156 for (Index = 0; Index < OrderCount; Index++) {\r
157 if (CurrentOrder[Index] == TargetLocation) {\r
158 Found = FALSE;\r
159 break;\r
160 }\r
161 }\r
162 if (Found) {\r
163 break;\r
164 }\r
165 }\r
166\r
167 if (TargetLocation == 0xFFFF) {\r
168 DEBUG ((EFI_D_ERROR, "Could not find unused target index.\n"));\r
169 Status = EFI_OUT_OF_RESOURCES;\r
170 goto ON_EXIT;\r
171 } else {\r
172 DEBUG ((EFI_D_INFO, "TargetIndex = %04x.\n", TargetLocation));\r
173 }\r
174 \r
175 //\r
176 // Construct and set the "Boot####" variable\r
177 //\r
178 DescSize = StrSize(Description);\r
179 FilePathSize = GetDevicePathSize (NewDevicePath);\r
180 TempByteBuffer = AllocateZeroPool(sizeof(EFI_LOAD_OPTION) + DescSize + FilePathSize);\r
181 if (TempByteBuffer == NULL) {\r
182 Status = EFI_OUT_OF_RESOURCES;\r
183 goto ON_EXIT;\r
184 }\r
185\r
186 TempByteStart = TempByteBuffer;\r
187 *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes\r
188 TempByteBuffer += sizeof (UINT32);\r
189\r
190 *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength\r
191 TempByteBuffer += sizeof (UINT16);\r
192\r
193 CopyMem (TempByteBuffer, Description, DescSize);\r
194 TempByteBuffer += DescSize;\r
195 CopyMem (TempByteBuffer, NewDevicePath, FilePathSize);\r
196\r
197 UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", L"Boot", TargetLocation);\r
198 Status = gRT->SetVariable (\r
199 OptionStr,\r
200 &gEfiGlobalVariableGuid,\r
201 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
202 sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,\r
203 TempByteStart\r
204 );\r
205 if (EFI_ERROR (Status)) {\r
206 goto ON_EXIT;\r
207 }\r
208\r
209 //\r
210 // Insert into the order list and set "BootOrder" variable\r
211 //\r
212 NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (UINT16));\r
213 if (NewOrder == NULL) {\r
214 Status = EFI_OUT_OF_RESOURCES;\r
215 goto ON_EXIT;\r
216 }\r
217 CopyMem(NewOrder, CurrentOrder, OrderCount * sizeof(UINT16));\r
218 NewOrder[OrderCount] = (UINT16) TargetLocation;\r
219 Status = gRT->SetVariable (\r
220 L"BootOrder",\r
221 &gEfiGlobalVariableGuid,\r
222 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
223 ((OrderCount + 1) * sizeof (UINT16)),\r
224 NewOrder\r
225 );\r
226 \r
227\r
228ON_EXIT:\r
229\r
230 if (CurrentOrder != NULL) {\r
231 FreePool (CurrentOrder);\r
232 }\r
233 if (NewOrder != NULL) {\r
234 FreePool (NewOrder);\r
235 }\r
236 if (TempByteStart != NULL) {\r
237 FreePool (TempByteStart);\r
238 }\r
239 if (NewDevicePath != NULL) {\r
240 FreePool (NewDevicePath);\r
241 }\r
242\r
243 return Status;\r
244}\r
245\r
246/**\r
247 \r
248 This function allows the caller to request the current\r
249 configuration for one or more named elements. The resulting\r
250 string is in <ConfigAltResp> format. Also, any and all alternative\r
251 configuration strings shall be appended to the end of the\r
252 current configuration string. If they are, they must appear\r
253 after the current configuration. They must contain the same\r
254 routing (GUID, NAME, PATH) as the current configuration string.\r
255 They must have an additional description indicating the type of\r
256 alternative configuration the string represents,\r
257 "ALTCFG=<StringToken>". That <StringToken> (when\r
258 converted from Hex UNICODE to binary) is a reference to a\r
259 string in the associated string pack.\r
260\r
261 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
262\r
263 @param[in] Request A null-terminated Unicode string in\r
264 <ConfigRequest> format. Note that this\r
265 includes the routing information as well as\r
266 the configurable name / value pairs. It is\r
267 invalid for this string to be in\r
268 <MultiConfigRequest> format.\r
269\r
270 @param[out] Progress On return, points to a character in the\r
271 Request string. Points to the string's null\r
272 terminator if request was successful. Points\r
273 to the most recent "&" before the first\r
274 failing name / value pair (or the beginning\r
275 of the string if the failure is in the first\r
276 name / value pair) if the request was not successful. \r
277\r
278 @param[out] Results A null-terminated Unicode string in\r
279 <ConfigAltResp> format which has all values\r
280 filled in for the names in the Request string.\r
281 String to be allocated by the called function.\r
282\r
283 @retval EFI_SUCCESS The Results string is filled with the\r
284 values corresponding to all requested\r
285 names.\r
286\r
287 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
288 parts of the results that must be\r
289 stored awaiting possible future\r
290 protocols.\r
291\r
292 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
293 for the Request parameter\r
294 would result in this type of\r
295 error. In this case, the\r
296 Progress parameter would be\r
297 set to NULL. \r
298\r
299 @retval EFI_NOT_FOUND Routing data doesn't match any\r
300 known driver. Progress set to the\r
301 first character in the routing header.\r
302 Note: There is no requirement that the\r
303 driver validate the routing data. It\r
304 must skip the <ConfigHdr> in order to\r
305 process the names.\r
306\r
307 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
308 to most recent "&" before the\r
309 error or the beginning of the\r
310 string.\r
311\r
312 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
313 to the & before the name in\r
314 question.\r
315\r
316**/\r
317EFI_STATUS\r
318EFIAPI\r
319HttpBootFormExtractConfig (\r
320 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
321 IN CONST EFI_STRING Request,\r
322 OUT EFI_STRING *Progress,\r
323 OUT EFI_STRING *Results\r
324 )\r
325{\r
326 EFI_STATUS Status;\r
327 UINTN BufferSize;\r
328 HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
329 EFI_STRING ConfigRequestHdr;\r
330 EFI_STRING ConfigRequest;\r
331 BOOLEAN AllocatedRequest;\r
332 UINTN Size;\r
333\r
334 if (Progress == NULL || Results == NULL) {\r
335 return EFI_INVALID_PARAMETER;\r
336 }\r
337\r
338 *Progress = Request;\r
339 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gHttpBootConfigGuid, mHttpBootConfigStorageName)) {\r
340 return EFI_NOT_FOUND;\r
341 }\r
342 \r
343 ConfigRequestHdr = NULL;\r
344 ConfigRequest = NULL;\r
345 AllocatedRequest = FALSE;\r
346 Size = 0;\r
347\r
348 CallbackInfo = HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);\r
349 //\r
350 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
351 //\r
352 BufferSize = sizeof (HTTP_BOOT_CONFIG_IFR_NVDATA);\r
353 ZeroMem (&CallbackInfo->HttpBootNvData, BufferSize);\r
a5acc842 354 StrCpyS (CallbackInfo->HttpBootNvData.Description, DESCRIPTION_STR_MAX_SIZE / sizeof (CHAR16), HTTP_BOOT_DEFAULT_DESCRIPTION_STR);\r
fa848a40
FS
355\r
356 ConfigRequest = Request;\r
357 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
358 //\r
359 // Request has no request element, construct full request string.\r
360 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
361 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
362 //\r
363 ConfigRequestHdr = HiiConstructConfigHdr (&gHttpBootConfigGuid, mHttpBootConfigStorageName, CallbackInfo->ChildHandle);\r
364 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
365 ConfigRequest = AllocateZeroPool (Size);\r
366 ASSERT (ConfigRequest != NULL);\r
367 AllocatedRequest = TRUE;\r
368 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
369 FreePool (ConfigRequestHdr);\r
370 }\r
371\r
372 Status = gHiiConfigRouting->BlockToConfig (\r
373 gHiiConfigRouting,\r
374 ConfigRequest,\r
375 (UINT8 *) &CallbackInfo->HttpBootNvData,\r
376 BufferSize,\r
377 Results,\r
378 Progress\r
379 );\r
fa848a40
FS
380 \r
381 //\r
382 // Free the allocated config request string.\r
383 //\r
384 if (AllocatedRequest) {\r
385 FreePool (ConfigRequest);\r
386 ConfigRequest = NULL;\r
387 }\r
388 //\r
389 // Set Progress string to the original request string.\r
390 //\r
391 if (Request == NULL) {\r
392 *Progress = NULL;\r
393 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
394 *Progress = Request + StrLen (Request);\r
395 }\r
396\r
397 return Status;\r
398}\r
399\r
400/**\r
401 \r
402 This function applies changes in a driver's configuration.\r
403 Input is a Configuration, which has the routing data for this\r
404 driver followed by name / value configuration pairs. The driver\r
405 must apply those pairs to its configurable storage. If the\r
406 driver's configuration is stored in a linear block of data\r
407 and the driver's name / value pairs are in <BlockConfig>\r
408 format, it may use the ConfigToBlock helper function (above) to\r
409 simplify the job.\r
410\r
411 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
412\r
413 @param[in] Configuration A null-terminated Unicode string in\r
414 <ConfigString> format. \r
415 \r
416 @param[out] Progress A pointer to a string filled in with the\r
417 offset of the most recent '&' before the\r
418 first failing name / value pair (or the\r
419 beginning of the string if the failure\r
420 is in the first name / value pair) or\r
421 the terminating NULL if all was\r
422 successful.\r
423\r
424 @retval EFI_SUCCESS The results have been distributed or are\r
425 awaiting distribution.\r
426 \r
427 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
428 parts of the results that must be\r
429 stored awaiting possible future\r
430 protocols.\r
431 \r
432 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
433 Results parameter would result\r
434 in this type of error.\r
435 \r
436 @retval EFI_NOT_FOUND Target for the specified routing data\r
437 was not found.\r
438\r
439**/\r
440EFI_STATUS\r
441EFIAPI\r
442HttpBootFormRouteConfig (\r
443 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
444 IN CONST EFI_STRING Configuration,\r
445 OUT EFI_STRING *Progress\r
446 )\r
447{\r
448 EFI_STATUS Status;\r
449 UINTN BufferSize;\r
450 HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
451 HTTP_BOOT_PRIVATE_DATA *Private;\r
452\r
453 if (Progress == NULL) {\r
454 return EFI_INVALID_PARAMETER;\r
455 }\r
456 *Progress = Configuration;\r
457\r
458 if (Configuration == NULL) {\r
459 return EFI_INVALID_PARAMETER;\r
460 }\r
461\r
462 //\r
463 // Check routing data in <ConfigHdr>.\r
464 // Note: there is no name for Name/Value storage, only GUID will be checked\r
465 //\r
466 if (!HiiIsConfigHdrMatch (Configuration, &gHttpBootConfigGuid, mHttpBootConfigStorageName)) {\r
467 return EFI_NOT_FOUND;\r
468 }\r
469\r
470 CallbackInfo = HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);\r
471 Private = HTTP_BOOT_PRIVATE_DATA_FROM_CALLBACK_INFO (CallbackInfo);\r
472 \r
473 BufferSize = sizeof (HTTP_BOOT_CONFIG_IFR_NVDATA);\r
474 ZeroMem (&CallbackInfo->HttpBootNvData, BufferSize);\r
475\r
476 Status = gHiiConfigRouting->ConfigToBlock (\r
477 gHiiConfigRouting,\r
478 Configuration,\r
479 (UINT8 *) &CallbackInfo->HttpBootNvData,\r
480 &BufferSize,\r
481 Progress\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 return Status;\r
485 }\r
486\r
487 //\r
488 // Create a new boot option according to the configuration data.\r
489 //\r
a5acc842
FS
490 HttpBootAddBootOption (\r
491 Private,\r
492 (CallbackInfo->HttpBootNvData.IpVersion == HTTP_BOOT_IP_VERSION_6) ? TRUE : FALSE,\r
493 CallbackInfo->HttpBootNvData.Description,\r
494 CallbackInfo->HttpBootNvData.Uri\r
495 );\r
fa848a40 496 \r
a5acc842 497 return EFI_SUCCESS;\r
fa848a40
FS
498}\r
499\r
500/**\r
501 \r
502 This function is called to provide results data to the driver.\r
503 This data consists of a unique key that is used to identify\r
504 which data is either being passed back or being asked for.\r
505\r
506 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
507 @param[in] Action Specifies the type of action taken by the browser.\r
508 @param[in] QuestionId A unique value which is sent to the original\r
509 exporting driver so that it can identify the type\r
510 of data to expect. The format of the data tends to \r
511 vary based on the opcode that generated the callback.\r
512 @param[in] Type The type of value for the question.\r
513 @param[in, out] Value A pointer to the data being sent to the original\r
514 exporting driver.\r
515 @param[out] ActionRequest On return, points to the action requested by the\r
516 callback function.\r
517\r
518 @retval EFI_SUCCESS The callback successfully handled the action.\r
519 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
520 variable and its data.\r
521 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
522 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
523 callback.\r
524**/\r
525EFI_STATUS\r
526EFIAPI\r
527HttpBootFormCallback (\r
528 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
529 IN EFI_BROWSER_ACTION Action,\r
530 IN EFI_QUESTION_ID QuestionId,\r
531 IN UINT8 Type,\r
532 IN OUT EFI_IFR_TYPE_VALUE *Value,\r
533 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
534 )\r
535{\r
a5acc842
FS
536 EFI_INPUT_KEY Key;\r
537 UINTN Index;\r
538 CHAR16 *Uri;\r
539 HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
540 \r
541 if (This == NULL || Value == NULL) {\r
542 return EFI_INVALID_PARAMETER;\r
543 }\r
544\r
545 CallbackInfo = HTTP_BOOT_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);\r
546 \r
547 if (Action != EFI_BROWSER_ACTION_CHANGING) {\r
548 return EFI_UNSUPPORTED;\r
549 }\r
550 \r
551 switch (QuestionId) {\r
552 case KEY_INITIATOR_URI:\r
553 //\r
554 // Get user input URI string\r
555 //\r
556 Uri = HiiGetString (CallbackInfo->RegisteredHandle, Value->string, NULL);\r
557\r
558 //\r
559 // Convert the scheme to all lower case.\r
560 //\r
561 for (Index = 0; Index < StrLen (Uri); Index++) {\r
562 if (Uri[Index] == L':') {\r
563 break;\r
564 }\r
565 if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') {\r
566 Uri[Index] -= (CHAR16)(L'A' - L'a');\r
567 }\r
568 }\r
569\r
570 //\r
571 // Set the converted URI string back\r
572 //\r
573 HiiSetString (CallbackInfo->RegisteredHandle, Value->string, Uri, NULL);\r
574\r
575 //\r
576 // We only accept http and https, pop up a message box for unsupported URI.\r
577 //\r
578 if ((StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 7) != 0)) {\r
579 CreatePopUp (\r
580 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
581 &Key,\r
582 L"ERROR: Unsupported URI!",\r
583 L"Only supports HTTP and HTTPS",\r
584 NULL\r
585 );\r
586 }\r
587\r
588 FreePool (Uri);\r
589 break;\r
590\r
591 default:\r
592 break;\r
593 }\r
594\r
595 return EFI_SUCCESS;\r
fa848a40
FS
596}\r
597\r
598/**\r
599 Initialize the configuration form.\r
600\r
601 @param[in] Private Pointer to the driver private data.\r
602\r
603 @retval EFI_SUCCESS The configuration form is initialized.\r
604 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
605\r
606**/\r
607EFI_STATUS\r
608HttpBootConfigFormInit (\r
609 IN HTTP_BOOT_PRIVATE_DATA *Private\r
610 )\r
611{\r
612 EFI_STATUS Status;\r
613 HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
614 VENDOR_DEVICE_PATH VendorDeviceNode;\r
fa848a40
FS
615 CHAR16 *MacString;\r
616 CHAR16 *OldMenuString;\r
617 CHAR16 MenuString[128];\r
618\r
619 CallbackInfo = &Private->CallbackInfo;\r
620\r
621 if (CallbackInfo->Initilized) {\r
622 return EFI_SUCCESS;\r
623 }\r
624 \r
625 CallbackInfo->Signature = HTTP_BOOT_FORM_CALLBACK_INFO_SIGNATURE;\r
626\r
627 //\r
628 // Construct device path node for EFI HII Config Access protocol,\r
629 // which consists of controller physical device path and one hardware\r
630 // vendor guid node.\r
631 //\r
632 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));\r
633 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;\r
634 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;\r
635 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);\r
636 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));\r
637 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (\r
638 Private->ParentDevicePath,\r
639 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode\r
640 );\r
641 if (CallbackInfo->HiiVendorDevicePath == NULL) {\r
642 Status = EFI_OUT_OF_RESOURCES;\r
643 goto Error;\r
644 }\r
645\r
646 CallbackInfo->ConfigAccess.ExtractConfig = HttpBootFormExtractConfig;\r
647 CallbackInfo->ConfigAccess.RouteConfig = HttpBootFormRouteConfig;\r
648 CallbackInfo->ConfigAccess.Callback = HttpBootFormCallback;\r
649 \r
650 //\r
651 // Install Device Path Protocol and Config Access protocol to driver handle.\r
652 //\r
653 Status = gBS->InstallMultipleProtocolInterfaces (\r
654 &CallbackInfo->ChildHandle,\r
655 &gEfiDevicePathProtocolGuid,\r
656 CallbackInfo->HiiVendorDevicePath,\r
657 &gEfiHiiConfigAccessProtocolGuid,\r
658 &CallbackInfo->ConfigAccess,\r
659 NULL\r
660 );\r
fa848a40
FS
661 if (EFI_ERROR (Status)) {\r
662 goto Error;\r
663 }\r
664\r
665 //\r
666 // Publish our HII data.\r
667 //\r
668 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
669 &gHttpBootConfigGuid,\r
670 CallbackInfo->ChildHandle,\r
671 HttpBootDxeStrings,\r
672 HttpBootConfigVfrBin,\r
673 NULL\r
674 );\r
675 if (CallbackInfo->RegisteredHandle == NULL) {\r
676 Status = EFI_OUT_OF_RESOURCES;\r
677 goto Error;\r
678 }\r
679\r
680 //\r
681 // Append MAC string in the menu help string\r
682 //\r
75372581 683 Status = NetLibGetMacString (Private->Controller, NULL, &MacString);\r
fa848a40
FS
684 if (!EFI_ERROR (Status)) {\r
685 OldMenuString = HiiGetString (\r
686 CallbackInfo->RegisteredHandle, \r
687 STRING_TOKEN (STR_HTTP_BOOT_CONFIG_FORM_HELP), \r
688 NULL\r
689 );\r
690 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);\r
691 HiiSetString (\r
692 CallbackInfo->RegisteredHandle, \r
693 STRING_TOKEN (STR_HTTP_BOOT_CONFIG_FORM_HELP), \r
694 MenuString, \r
695 NULL\r
696 );\r
697 \r
698 FreePool (MacString);\r
699 FreePool (OldMenuString);\r
700\r
75372581 701 CallbackInfo->Initilized = TRUE;\r
fa848a40
FS
702 return EFI_SUCCESS;\r
703 }\r
704 \r
705Error:\r
706\r
707 HttpBootConfigFormUnload (Private);\r
708 return Status;\r
709}\r
710\r
711/**\r
712 Unload the configuration form, this includes: delete all the configuration\r
713 entries, uninstall the form callback protocol, and free the resources used.\r
75372581 714 The form will only be unload completely when both IP4 and IP6 stack are stopped.\r
fa848a40
FS
715\r
716 @param[in] Private Pointer to the driver private data.\r
717\r
718 @retval EFI_SUCCESS The configuration form is unloaded.\r
719 @retval Others Failed to unload the form.\r
720\r
721**/\r
722EFI_STATUS\r
723HttpBootConfigFormUnload (\r
724 IN HTTP_BOOT_PRIVATE_DATA *Private\r
725 )\r
726{\r
727 HTTP_BOOT_FORM_CALLBACK_INFO *CallbackInfo;\r
728\r
75372581 729 if (Private->Ip4Nic != NULL || Private->Ip6Nic != NULL) {\r
fa848a40 730 //\r
75372581 731 // Only unload the configuration form when both IP4 and IP6 stack are stopped.\r
fa848a40 732 //\r
75372581
FS
733 return EFI_SUCCESS;\r
734 }\r
735\r
736 CallbackInfo = &Private->CallbackInfo;\r
737 if (CallbackInfo->ChildHandle != NULL) {\r
fa848a40
FS
738 //\r
739 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
740 //\r
741 gBS->UninstallMultipleProtocolInterfaces (\r
742 CallbackInfo->ChildHandle,\r
743 &gEfiDevicePathProtocolGuid,\r
744 CallbackInfo->HiiVendorDevicePath,\r
745 &gEfiHiiConfigAccessProtocolGuid,\r
746 &CallbackInfo->ConfigAccess,\r
747 NULL\r
748 );\r
749 CallbackInfo->ChildHandle = NULL;\r
750 }\r
751\r
752 if (CallbackInfo->HiiVendorDevicePath != NULL) {\r
753 FreePool (CallbackInfo->HiiVendorDevicePath);\r
754 CallbackInfo->HiiVendorDevicePath = NULL;\r
755 }\r
756\r
757 if (CallbackInfo->RegisteredHandle != NULL) {\r
758 //\r
759 // Remove HII package list\r
760 //\r
761 HiiRemovePackages (CallbackInfo->RegisteredHandle);\r
762 CallbackInfo->RegisteredHandle = NULL;\r
763 }\r
764\r
765 return EFI_SUCCESS;\r
766}\r