]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpBootDxe/HttpBootSupport.c
NetworkPkg: Add PCD to enable the HTTP connections switch
[mirror_edk2.git] / NetworkPkg / HttpBootDxe / HttpBootSupport.c
CommitLineData
d933e70a
JW
1/** @file\r
2 Support functions implementation for UEFI HTTP boot driver.\r
3\r
221463c2 4Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
f58554fc
GB
5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
6This program and the accompanying materials are licensed and made available under\r
7the terms and conditions of the BSD License that accompanies this distribution.\r
d933e70a
JW
8The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php. \r
10 \r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "HttpBootDxe.h"\r
17\r
18\r
19/**\r
20 Get the Nic handle using any child handle in the IPv4 stack.\r
21\r
22 @param[in] ControllerHandle Pointer to child handle over IPv4.\r
23\r
24 @return NicHandle The pointer to the Nic handle.\r
25 @return NULL Can't find the Nic handle.\r
26\r
27**/\r
28EFI_HANDLE\r
29HttpBootGetNicByIp4Children (\r
30 IN EFI_HANDLE ControllerHandle\r
31 )\r
32{\r
33 EFI_HANDLE NicHandle;\r
34\r
35 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);\r
36 if (NicHandle == NULL) {\r
37 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
38 if (NicHandle == NULL) {\r
39 return NULL;\r
40 }\r
41 }\r
42\r
43 return NicHandle;\r
44}\r
45\r
b659408b
ZL
46/**\r
47 Get the Nic handle using any child handle in the IPv6 stack.\r
48\r
49 @param[in] ControllerHandle Pointer to child handle over IPv6.\r
50\r
51 @return NicHandle The pointer to the Nic handle.\r
52 @return NULL Can't find the Nic handle.\r
53\r
54**/\r
55EFI_HANDLE\r
56HttpBootGetNicByIp6Children (\r
57 IN EFI_HANDLE ControllerHandle\r
58 )\r
59{\r
60 EFI_HANDLE NicHandle;\r
61 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);\r
62 if (NicHandle == NULL) {\r
63 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
64 if (NicHandle == NULL) {\r
65 return NULL;\r
66 }\r
67 }\r
68\r
69 return NicHandle;\r
70}\r
d933e70a
JW
71\r
72/**\r
73 This function is to convert UINTN to ASCII string with the required formatting.\r
74\r
75 @param[in] Number Numeric value to be converted.\r
76 @param[in] Buffer The pointer to the buffer for ASCII string.\r
77 @param[in] Length The length of the required format.\r
78\r
79**/\r
80VOID\r
81HttpBootUintnToAscDecWithFormat (\r
82 IN UINTN Number,\r
83 IN UINT8 *Buffer,\r
84 IN INTN Length\r
85 )\r
86{\r
87 UINTN Remainder;\r
88\r
413535bb 89 for (; Length > 0; Length--) {\r
d933e70a
JW
90 Remainder = Number % 10;\r
91 Number /= 10;\r
413535bb 92 Buffer[Length - 1] = (UINT8) ('0' + Remainder);\r
d933e70a
JW
93 }\r
94}\r
95\r
96/**\r
97 This function is to display the IPv4 address.\r
98\r
99 @param[in] Ip The pointer to the IPv4 address.\r
100\r
101**/\r
102VOID\r
103HttpBootShowIp4Addr (\r
104 IN EFI_IPv4_ADDRESS *Ip\r
105 )\r
106{\r
107 UINTN Index;\r
108\r
109 for (Index = 0; Index < 4; Index++) {\r
110 AsciiPrint ("%d", Ip->Addr[Index]);\r
111 if (Index < 3) {\r
112 AsciiPrint (".");\r
113 }\r
114 }\r
115}\r
116\r
b659408b
ZL
117/**\r
118 This function is to display the IPv6 address.\r
119\r
120 @param[in] Ip The pointer to the IPv6 address.\r
121\r
122**/\r
123VOID\r
124HttpBootShowIp6Addr (\r
125 IN EFI_IPv6_ADDRESS *Ip\r
126 )\r
127{\r
128 UINTN Index;\r
129\r
130 for (Index = 0; Index < 16; Index++) {\r
131\r
132 if (Ip->Addr[Index] != 0) {\r
133 AsciiPrint ("%x", Ip->Addr[Index]);\r
134 }\r
135 Index++;\r
136 if (Index > 15) {\r
137 return;\r
138 }\r
139 if (((Ip->Addr[Index] & 0xf0) == 0) && (Ip->Addr[Index - 1] != 0)) {\r
140 AsciiPrint ("0");\r
141 }\r
142 AsciiPrint ("%x", Ip->Addr[Index]);\r
143 if (Index < 15) {\r
144 AsciiPrint (":");\r
145 }\r
146 }\r
147}\r
148\r
62cae351
ZL
149/**\r
150 This function is to display the HTTP error status.\r
151\r
152 @param[in] StatusCode The status code value in HTTP message.\r
153\r
154**/\r
155VOID\r
156HttpBootPrintErrorMessage (\r
157 EFI_HTTP_STATUS_CODE StatusCode\r
158 )\r
159{\r
160 AsciiPrint ("\n");\r
161\r
162 switch (StatusCode) {\r
163 case HTTP_STATUS_300_MULTIPLE_CHIOCES:\r
164 AsciiPrint ("\n Redirection: 300 Multiple Choices");\r
165 break; \r
166 \r
167 case HTTP_STATUS_301_MOVED_PERMANENTLY:\r
168 AsciiPrint ("\n Redirection: 301 Moved Permanently");\r
169 break; \r
170 \r
171 case HTTP_STATUS_302_FOUND:\r
172 AsciiPrint ("\n Redirection: 302 Found");\r
173 break; \r
174 \r
175 case HTTP_STATUS_303_SEE_OTHER:\r
176 AsciiPrint ("\n Redirection: 303 See Other");\r
177 break; \r
178\r
179 case HTTP_STATUS_304_NOT_MODIFIED:\r
180 AsciiPrint ("\n Redirection: 304 Not Modified");\r
181 break; \r
182\r
183 case HTTP_STATUS_305_USE_PROXY:\r
184 AsciiPrint ("\n Redirection: 305 Use Proxy");\r
185 break; \r
186\r
187 case HTTP_STATUS_307_TEMPORARY_REDIRECT:\r
188 AsciiPrint ("\n Redirection: 307 Temporary Redirect");\r
189 break; \r
190\r
191 case HTTP_STATUS_400_BAD_REQUEST:\r
192 AsciiPrint ("\n Client Error: 400 Bad Request");\r
193 break;\r
194 \r
195 case HTTP_STATUS_401_UNAUTHORIZED:\r
196 AsciiPrint ("\n Client Error: 401 Unauthorized");\r
197 break;\r
198 \r
199 case HTTP_STATUS_402_PAYMENT_REQUIRED:\r
200 AsciiPrint ("\n Client Error: 402 Payment Required");\r
201 break;\r
202\r
203 case HTTP_STATUS_403_FORBIDDEN:\r
204 AsciiPrint ("\n Client Error: 403 Forbidden");\r
205 break;\r
206\r
207 case HTTP_STATUS_404_NOT_FOUND:\r
208 AsciiPrint ("\n Client Error: 404 Not Found");\r
209 break;\r
210\r
211 case HTTP_STATUS_405_METHOD_NOT_ALLOWED:\r
212 AsciiPrint ("\n Client Error: 405 Method Not Allowed");\r
213 break;\r
214\r
215 case HTTP_STATUS_406_NOT_ACCEPTABLE:\r
216 AsciiPrint ("\n Client Error: 406 Not Acceptable");\r
217 break;\r
218\r
219 case HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED:\r
220 AsciiPrint ("\n Client Error: 407 Proxy Authentication Required");\r
221 break;\r
222\r
223 case HTTP_STATUS_408_REQUEST_TIME_OUT:\r
224 AsciiPrint ("\n Client Error: 408 Request Timeout");\r
225 break;\r
226\r
227 case HTTP_STATUS_409_CONFLICT:\r
228 AsciiPrint ("\n Client Error: 409 Conflict");\r
229 break;\r
230\r
231 case HTTP_STATUS_410_GONE:\r
232 AsciiPrint ("\n Client Error: 410 Gone");\r
233 break;\r
234\r
235 case HTTP_STATUS_411_LENGTH_REQUIRED:\r
236 AsciiPrint ("\n Client Error: 411 Length Required");\r
237 break;\r
238\r
239 case HTTP_STATUS_412_PRECONDITION_FAILED:\r
240 AsciiPrint ("\n Client Error: 412 Precondition Failed");\r
241 break;\r
242\r
243 case HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE:\r
244 AsciiPrint ("\n Client Error: 413 Request Entity Too Large");\r
245 break;\r
246\r
247 case HTTP_STATUS_414_REQUEST_URI_TOO_LARGE:\r
248 AsciiPrint ("\n Client Error: 414 Request URI Too Long");\r
249 break;\r
250\r
251 case HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE:\r
252 AsciiPrint ("\n Client Error: 415 Unsupported Media Type");\r
253 break;\r
254\r
255 case HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED:\r
256 AsciiPrint ("\n Client Error: 416 Requested Range Not Satisfiable");\r
257 break;\r
258\r
259 case HTTP_STATUS_417_EXPECTATION_FAILED:\r
260 AsciiPrint ("\n Client Error: 417 Expectation Failed");\r
261 break;\r
262\r
263 case HTTP_STATUS_500_INTERNAL_SERVER_ERROR:\r
264 AsciiPrint ("\n Server Error: 500 Internal Server Error");\r
265 break;\r
266\r
267 case HTTP_STATUS_501_NOT_IMPLEMENTED:\r
268 AsciiPrint ("\n Server Error: 501 Not Implemented");\r
269 break;\r
270\r
271 case HTTP_STATUS_502_BAD_GATEWAY:\r
272 AsciiPrint ("\n Server Error: 502 Bad Gateway");\r
273 break;\r
274\r
275 case HTTP_STATUS_503_SERVICE_UNAVAILABLE:\r
276 AsciiPrint ("\n Server Error: 503 Service Unavailable");\r
277 break;\r
278\r
279 case HTTP_STATUS_504_GATEWAY_TIME_OUT:\r
280 AsciiPrint ("\n Server Error: 504 Gateway Timeout");\r
281 break;\r
282\r
283 case HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED:\r
284 AsciiPrint ("\n Server Error: 505 HTTP Version Not Supported");\r
285 break;\r
286\r
287 default: ;\r
288 \r
289 }\r
290}\r
291\r
b659408b
ZL
292/**\r
293 Notify the callback function when an event is triggered.\r
294\r
295 @param[in] Event The triggered event.\r
296 @param[in] Context The opaque parameter to the function.\r
297\r
298**/\r
299VOID\r
300EFIAPI\r
301HttpBootCommonNotify (\r
302 IN EFI_EVENT Event,\r
303 IN VOID *Context\r
304 )\r
305{\r
306 *((BOOLEAN *) Context) = TRUE;\r
307}\r
308\r
309/**\r
310 Retrieve the host address using the EFI_DNS6_PROTOCOL.\r
311\r
312 @param[in] Private The pointer to the driver's private data.\r
313 @param[in] HostName Pointer to buffer containing hostname.\r
314 @param[out] IpAddress On output, pointer to buffer containing IPv6 address.\r
315\r
316 @retval EFI_SUCCESS Operation succeeded.\r
317 @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
318 @retval Others Other errors as indicated. \r
319**/\r
320EFI_STATUS\r
321HttpBootDns (\r
322 IN HTTP_BOOT_PRIVATE_DATA *Private,\r
323 IN CHAR16 *HostName,\r
324 OUT EFI_IPv6_ADDRESS *IpAddress \r
325 )\r
326{\r
327 EFI_STATUS Status;\r
328 EFI_DNS6_PROTOCOL *Dns6;\r
329 EFI_DNS6_CONFIG_DATA Dns6ConfigData;\r
330 EFI_DNS6_COMPLETION_TOKEN Token;\r
331 EFI_HANDLE Dns6Handle;\r
332 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
333 EFI_IPv6_ADDRESS *DnsServerList;\r
334 UINTN DnsServerListCount;\r
335 UINTN DataSize;\r
336 BOOLEAN IsDone; \r
337 \r
338 DnsServerList = NULL;\r
339 DnsServerListCount = 0;\r
340 Dns6 = NULL;\r
341 Dns6Handle = NULL;\r
342 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));\r
343 \r
344 //\r
345 // Get DNS server list from EFI IPv6 Configuration protocol.\r
346 //\r
347 Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);\r
348 if (!EFI_ERROR (Status)) {\r
349 //\r
350 // Get the required size.\r
351 //\r
352 DataSize = 0;\r
353 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);\r
354 if (Status == EFI_BUFFER_TOO_SMALL) {\r
355 DnsServerList = AllocatePool (DataSize);\r
356 if (DnsServerList == NULL) {\r
357 return EFI_OUT_OF_RESOURCES;\r
358 } \r
359\r
360 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);\r
361 if (EFI_ERROR (Status)) {\r
362 FreePool (DnsServerList);\r
363 DnsServerList = NULL;\r
364 } else {\r
365 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
366 }\r
367 }\r
368 }\r
369 //\r
370 // Create a DNSv6 child instance and get the protocol.\r
371 //\r
372 Status = NetLibCreateServiceChild (\r
373 Private->Controller,\r
75372581 374 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
375 &gEfiDns6ServiceBindingProtocolGuid,\r
376 &Dns6Handle\r
377 );\r
378 if (EFI_ERROR (Status)) {\r
379 goto Exit;\r
380 } \r
381 \r
382 Status = gBS->OpenProtocol (\r
383 Dns6Handle,\r
384 &gEfiDns6ProtocolGuid,\r
385 (VOID **) &Dns6,\r
75372581 386 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
387 Private->Controller,\r
388 EFI_OPEN_PROTOCOL_BY_DRIVER\r
389 );\r
390 if (EFI_ERROR (Status)) {\r
391 goto Exit;\r
392 }\r
393\r
394 //\r
395 // Configure DNS6 instance for the DNS server address and protocol.\r
396 //\r
397 ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));\r
398 Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;\r
399 Dns6ConfigData.DnsServerList = DnsServerList;\r
400 Dns6ConfigData.EnableDnsCache = TRUE;\r
401 Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;\r
402 IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6);\r
403 Status = Dns6->Configure (\r
404 Dns6,\r
405 &Dns6ConfigData\r
406 );\r
407 if (EFI_ERROR (Status)) {\r
408 goto Exit;\r
409 }\r
410 \r
411 Token.Status = EFI_NOT_READY;\r
412 IsDone = FALSE;\r
413 //\r
414 // Create event to set the IsDone flag when name resolution is finished.\r
415 //\r
416 Status = gBS->CreateEvent (\r
417 EVT_NOTIFY_SIGNAL,\r
418 TPL_NOTIFY,\r
419 HttpBootCommonNotify,\r
420 &IsDone,\r
421 &Token.Event\r
422 );\r
423 if (EFI_ERROR (Status)) {\r
424 goto Exit;\r
425 }\r
426\r
427 //\r
428 // Start asynchronous name resolution.\r
429 //\r
430 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);\r
431 if (EFI_ERROR (Status)) {\r
432 goto Exit;\r
433 }\r
434\r
435 while (!IsDone) {\r
436 Dns6->Poll (Dns6);\r
437 }\r
438 \r
439 //\r
440 // Name resolution is done, check result.\r
441 //\r
442 Status = Token.Status; \r
443 if (!EFI_ERROR (Status)) {\r
444 if (Token.RspData.H2AData == NULL) {\r
445 Status = EFI_DEVICE_ERROR;\r
446 goto Exit;\r
447 }\r
448 if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {\r
449 Status = EFI_DEVICE_ERROR;\r
450 goto Exit;\r
451 }\r
452 //\r
453 // We just return the first IPv6 address from DNS protocol.\r
454 //\r
455 IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
456 Status = EFI_SUCCESS;\r
457 }\r
458Exit:\r
459\r
460 if (Token.Event != NULL) {\r
461 gBS->CloseEvent (Token.Event);\r
462 }\r
463 if (Token.RspData.H2AData != NULL) {\r
464 if (Token.RspData.H2AData->IpList != NULL) {\r
465 FreePool (Token.RspData.H2AData->IpList);\r
466 }\r
467 FreePool (Token.RspData.H2AData);\r
468 }\r
469\r
470 if (Dns6 != NULL) {\r
471 Dns6->Configure (Dns6, NULL);\r
472 \r
473 gBS->CloseProtocol (\r
474 Dns6Handle,\r
475 &gEfiDns6ProtocolGuid,\r
75372581 476 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
477 Private->Controller\r
478 );\r
479 }\r
480\r
481 if (Dns6Handle != NULL) {\r
482 NetLibDestroyServiceChild (\r
483 Private->Controller,\r
75372581 484 Private->Ip6Nic->ImageHandle,\r
b659408b
ZL
485 &gEfiDns6ServiceBindingProtocolGuid,\r
486 Dns6Handle\r
487 );\r
488 }\r
489\r
490 if (DnsServerList != NULL) {\r
491 FreePool (DnsServerList);\r
492 }\r
493 \r
494 return Status; \r
495}\r
d933e70a
JW
496/**\r
497 Create a HTTP_IO_HEADER to hold the HTTP header items.\r
498\r
499 @param[in] MaxHeaderCount The maximun number of HTTP header in this holder.\r
500\r
501 @return A pointer of the HTTP header holder or NULL if failed.\r
502 \r
503**/\r
504HTTP_IO_HEADER *\r
505HttpBootCreateHeader (\r
506 UINTN MaxHeaderCount\r
b659408b 507 )\r
d933e70a
JW
508{\r
509 HTTP_IO_HEADER *HttpIoHeader;\r
510\r
511 if (MaxHeaderCount == 0) {\r
512 return NULL;\r
513 }\r
514\r
515 HttpIoHeader = AllocateZeroPool (sizeof (HTTP_IO_HEADER) + MaxHeaderCount * sizeof (EFI_HTTP_HEADER));\r
516 if (HttpIoHeader == NULL) {\r
517 return NULL;\r
518 }\r
519\r
520 HttpIoHeader->MaxHeaderCount = MaxHeaderCount;\r
521 HttpIoHeader->Headers = (EFI_HTTP_HEADER *) (HttpIoHeader + 1);\r
522\r
523 return HttpIoHeader;\r
524}\r
525\r
526/**\r
527 Destroy the HTTP_IO_HEADER and release the resouces. \r
528\r
529 @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.\r
530\r
531**/\r
532VOID\r
533HttpBootFreeHeader (\r
534 IN HTTP_IO_HEADER *HttpIoHeader\r
535 )\r
536{\r
537 UINTN Index;\r
538 \r
539 if (HttpIoHeader != NULL) {\r
540 if (HttpIoHeader->HeaderCount != 0) {\r
541 for (Index = 0; Index < HttpIoHeader->HeaderCount; Index++) {\r
542 FreePool (HttpIoHeader->Headers[Index].FieldName);\r
543 FreePool (HttpIoHeader->Headers[Index].FieldValue);\r
544 }\r
545 }\r
546 FreePool (HttpIoHeader);\r
547 }\r
548}\r
549\r
d933e70a
JW
550/**\r
551 Set or update a HTTP header with the field name and corresponding value.\r
552\r
553 @param[in] HttpIoHeader Point to the HTTP header holder.\r
f58554fc 554 @param[in] FieldName Null terminated string which describes a field name.\r
d933e70a
JW
555 @param[in] FieldValue Null terminated string which describes the corresponding field value.\r
556\r
557 @retval EFI_SUCCESS The HTTP header has been set or updated.\r
558 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
559 @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.\r
560 @retval Other Unexpected error happened.\r
561 \r
562**/\r
563EFI_STATUS\r
564HttpBootSetHeader (\r
565 IN HTTP_IO_HEADER *HttpIoHeader,\r
566 IN CHAR8 *FieldName,\r
567 IN CHAR8 *FieldValue\r
568 )\r
569{\r
570 EFI_HTTP_HEADER *Header;\r
571 UINTN StrSize;\r
572 CHAR8 *NewFieldValue;\r
573 \r
574 if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) {\r
575 return EFI_INVALID_PARAMETER;\r
576 }\r
577\r
f58554fc 578 Header = HttpFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName);\r
d933e70a
JW
579 if (Header == NULL) {\r
580 //\r
581 // Add a new header.\r
582 //\r
583 if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) {\r
584 return EFI_OUT_OF_RESOURCES;\r
585 }\r
586 Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount];\r
587\r
588 StrSize = AsciiStrSize (FieldName);\r
589 Header->FieldName = AllocatePool (StrSize);\r
590 if (Header->FieldName == NULL) {\r
591 return EFI_OUT_OF_RESOURCES;\r
592 }\r
593 CopyMem (Header->FieldName, FieldName, StrSize);\r
594 Header->FieldName[StrSize -1] = '\0';\r
595\r
596 StrSize = AsciiStrSize (FieldValue);\r
597 Header->FieldValue = AllocatePool (StrSize);\r
598 if (Header->FieldValue == NULL) {\r
599 FreePool (Header->FieldName);\r
600 return EFI_OUT_OF_RESOURCES;\r
601 }\r
602 CopyMem (Header->FieldValue, FieldValue, StrSize);\r
603 Header->FieldValue[StrSize -1] = '\0';\r
604\r
605 HttpIoHeader->HeaderCount++;\r
606 } else {\r
607 //\r
608 // Update an existing one.\r
609 //\r
610 StrSize = AsciiStrSize (FieldValue);\r
611 NewFieldValue = AllocatePool (StrSize);\r
612 if (NewFieldValue == NULL) {\r
613 return EFI_OUT_OF_RESOURCES;\r
614 }\r
615 CopyMem (NewFieldValue, FieldValue, StrSize);\r
616 NewFieldValue[StrSize -1] = '\0';\r
617 \r
618 if (Header->FieldValue != NULL) {\r
619 FreePool (Header->FieldValue);\r
620 }\r
621 Header->FieldValue = NewFieldValue;\r
622 }\r
623\r
624 return EFI_SUCCESS;\r
625}\r
626\r
d933e70a
JW
627/**\r
628 Create a HTTP_IO to access the HTTP service. It will create and configure\r
629 a HTTP child handle.\r
630\r
631 @param[in] Image The handle of the driver image.\r
632 @param[in] Controller The handle of the controller.\r
633 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
634 @param[in] ConfigData The HTTP_IO configuration data.\r
635 @param[out] HttpIo The HTTP_IO.\r
636 \r
637 @retval EFI_SUCCESS The HTTP_IO is created and configured.\r
638 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
639 @retval EFI_UNSUPPORTED One or more of the control options are not\r
640 supported in the implementation.\r
641 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
642 @retval Others Failed to create the HTTP_IO or configure it.\r
643\r
644**/\r
645EFI_STATUS\r
646HttpIoCreateIo (\r
647 IN EFI_HANDLE Image,\r
648 IN EFI_HANDLE Controller,\r
649 IN UINT8 IpVersion,\r
650 IN HTTP_IO_CONFIG_DATA *ConfigData,\r
651 OUT HTTP_IO *HttpIo\r
652 )\r
653{\r
654 EFI_STATUS Status;\r
655 EFI_HTTP_CONFIG_DATA HttpConfigData;\r
656 EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;\r
b659408b 657 EFI_HTTPv6_ACCESS_POINT Http6AccessPoint;\r
d933e70a
JW
658 EFI_HTTP_PROTOCOL *Http;\r
659 EFI_EVENT Event;\r
660 \r
661 if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) {\r
662 return EFI_INVALID_PARAMETER;\r
663 }\r
664\r
665 if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {\r
666 return EFI_UNSUPPORTED;\r
667 }\r
668\r
669 ZeroMem (HttpIo, sizeof (HTTP_IO));\r
670 \r
671 //\r
672 // Create the HTTP child instance and get the HTTP protocol.\r
673 // \r
674 Status = NetLibCreateServiceChild (\r
675 Controller,\r
676 Image,\r
677 &gEfiHttpServiceBindingProtocolGuid,\r
678 &HttpIo->Handle\r
679 );\r
680 if (EFI_ERROR (Status)) {\r
681 return Status;\r
682 }\r
683\r
684 Status = gBS->OpenProtocol (\r
685 HttpIo->Handle,\r
686 &gEfiHttpProtocolGuid,\r
687 (VOID **) &Http,\r
688 Image,\r
689 Controller,\r
690 EFI_OPEN_PROTOCOL_BY_DRIVER\r
691 );\r
692 if (EFI_ERROR (Status) || (Http == NULL)) {\r
693 goto ON_ERROR;\r
694 }\r
695\r
696 //\r
697 // Init the configuration data and configure the HTTP child.\r
698 //\r
699 HttpIo->Image = Image;\r
700 HttpIo->Controller = Controller;\r
701 HttpIo->IpVersion = IpVersion;\r
702 HttpIo->Http = Http;\r
703\r
704 ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));\r
705 HttpConfigData.HttpVersion = HttpVersion11;\r
706 HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut;\r
707 if (HttpIo->IpVersion == IP_VERSION_4) {\r
708 HttpConfigData.LocalAddressIsIPv6 = FALSE;\r
709 \r
710 Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;\r
711 Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort;\r
712 IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);\r
713 IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);\r
714 HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint; \r
715 } else {\r
b659408b
ZL
716 HttpConfigData.LocalAddressIsIPv6 = TRUE;\r
717 Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort;\r
718 IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);\r
719 HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;\r
d933e70a
JW
720 }\r
721 \r
722 Status = Http->Configure (Http, &HttpConfigData);\r
723 if (EFI_ERROR (Status)) {\r
724 goto ON_ERROR;\r
725 }\r
726\r
727 //\r
728 // Create events for variuos asynchronous operations.\r
729 //\r
730 Status = gBS->CreateEvent (\r
731 EVT_NOTIFY_SIGNAL,\r
732 TPL_NOTIFY,\r
b659408b 733 HttpBootCommonNotify,\r
d933e70a
JW
734 &HttpIo->IsTxDone,\r
735 &Event\r
736 );\r
737 if (EFI_ERROR (Status)) {\r
738 goto ON_ERROR;\r
739 }\r
740 HttpIo->ReqToken.Event = Event;\r
741 HttpIo->ReqToken.Message = &HttpIo->ReqMessage;\r
742\r
743 Status = gBS->CreateEvent (\r
744 EVT_NOTIFY_SIGNAL,\r
745 TPL_NOTIFY,\r
b659408b 746 HttpBootCommonNotify,\r
d933e70a
JW
747 &HttpIo->IsRxDone,\r
748 &Event\r
749 );\r
750 if (EFI_ERROR (Status)) {\r
751 goto ON_ERROR;\r
752 }\r
753 HttpIo->RspToken.Event = Event;\r
754 HttpIo->RspToken.Message = &HttpIo->RspMessage;\r
755\r
7570696c
JW
756 //\r
757 // Create TimeoutEvent for response\r
758 //\r
759 Status = gBS->CreateEvent (\r
760 EVT_TIMER,\r
761 TPL_CALLBACK,\r
762 NULL,\r
763 NULL,\r
764 &Event\r
765 );\r
766 if (EFI_ERROR (Status)) {\r
767 goto ON_ERROR;\r
768 }\r
769 HttpIo->TimeoutEvent = Event;\r
770\r
d933e70a
JW
771 return EFI_SUCCESS;\r
772 \r
773ON_ERROR:\r
774 HttpIoDestroyIo (HttpIo);\r
775\r
776 return Status;\r
777}\r
778\r
779/**\r
780 Destroy the HTTP_IO and release the resouces. \r
781\r
782 @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.\r
783\r
784**/\r
785VOID\r
786HttpIoDestroyIo (\r
787 IN HTTP_IO *HttpIo\r
788 )\r
789{\r
790 EFI_HTTP_PROTOCOL *Http;\r
791 EFI_EVENT Event;\r
792\r
793 if (HttpIo == NULL) {\r
794 return;\r
795 }\r
796\r
797 Event = HttpIo->ReqToken.Event;\r
798 if (Event != NULL) {\r
799 gBS->CloseEvent (Event);\r
800 }\r
801\r
802 Event = HttpIo->RspToken.Event;\r
803 if (Event != NULL) {\r
804 gBS->CloseEvent (Event);\r
805 }\r
7570696c
JW
806\r
807 Event = HttpIo->TimeoutEvent;\r
808 if (Event != NULL) {\r
809 gBS->CloseEvent (Event);\r
810 }\r
d933e70a
JW
811 \r
812 Http = HttpIo->Http;\r
813 if (Http != NULL) {\r
814 Http->Configure (Http, NULL);\r
815 gBS->CloseProtocol (\r
816 HttpIo->Handle,\r
817 &gEfiHttpProtocolGuid,\r
818 HttpIo->Image,\r
819 HttpIo->Controller\r
820 );\r
821 }\r
822\r
823 NetLibDestroyServiceChild (\r
824 HttpIo->Controller,\r
825 HttpIo->Image,\r
826 &gEfiHttpServiceBindingProtocolGuid,\r
827 HttpIo->Handle\r
828 );\r
829}\r
830\r
831/**\r
832 Synchronously send a HTTP REQUEST message to the server.\r
833 \r
834 @param[in] HttpIo The HttpIo wrapping the HTTP service.\r
835 @param[in] Request A pointer to storage such data as URL and HTTP method.\r
836 @param[in] HeaderCount Number of HTTP header structures in Headers list. \r
837 @param[in] Headers Array containing list of HTTP headers.\r
838 @param[in] BodyLength Length in bytes of the HTTP body.\r
839 @param[in] Body Body associated with the HTTP request. \r
840 \r
841 @retval EFI_SUCCESS The HTTP request is trasmitted.\r
842 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
843 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
844 @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
845 @retval Others Other errors as indicated.\r
846\r
847**/\r
848EFI_STATUS\r
849HttpIoSendRequest (\r
850 IN HTTP_IO *HttpIo,\r
851 IN EFI_HTTP_REQUEST_DATA *Request,\r
852 IN UINTN HeaderCount,\r
853 IN EFI_HTTP_HEADER *Headers,\r
854 IN UINTN BodyLength,\r
855 IN VOID *Body\r
856 )\r
857{\r
858 EFI_STATUS Status;\r
859 EFI_HTTP_PROTOCOL *Http;\r
860\r
861 if (HttpIo == NULL || HttpIo->Http == NULL) {\r
862 return EFI_INVALID_PARAMETER;\r
863 }\r
864\r
865 HttpIo->ReqToken.Status = EFI_NOT_READY;\r
866 HttpIo->ReqToken.Message->Data.Request = Request;\r
867 HttpIo->ReqToken.Message->HeaderCount = HeaderCount;\r
868 HttpIo->ReqToken.Message->Headers = Headers;\r
869 HttpIo->ReqToken.Message->BodyLength = BodyLength;\r
870 HttpIo->ReqToken.Message->Body = Body;\r
871\r
872 //\r
873 // Queue the request token to HTTP instances.\r
874 //\r
875 Http = HttpIo->Http;\r
876 HttpIo->IsTxDone = FALSE;\r
877 Status = Http->Request (\r
878 Http,\r
879 &HttpIo->ReqToken\r
880 );\r
881 if (EFI_ERROR (Status)) {\r
882 return Status;\r
883 }\r
884\r
885 //\r
886 // Poll the network until transmit finish.\r
887 //\r
888 while (!HttpIo->IsTxDone) {\r
889 Http->Poll (Http);\r
890 }\r
891\r
892 return HttpIo->ReqToken.Status;\r
893}\r
894\r
895/**\r
896 Synchronously receive a HTTP RESPONSE message from the server.\r
897 \r
898 @param[in] HttpIo The HttpIo wrapping the HTTP service.\r
899 @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).\r
900 FALSE to continue receive the previous response message.\r
901 @param[out] ResponseData Point to a wrapper of the received response data.\r
902 \r
ef422fc5 903 @retval EFI_SUCCESS The HTTP response is received.\r
d933e70a
JW
904 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
905 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
906 @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.\r
907 @retval Others Other errors as indicated.\r
908\r
909**/\r
910EFI_STATUS\r
911HttpIoRecvResponse (\r
912 IN HTTP_IO *HttpIo,\r
913 IN BOOLEAN RecvMsgHeader,\r
ef422fc5 914 OUT HTTP_IO_RESPONSE_DATA *ResponseData\r
d933e70a
JW
915 )\r
916{\r
917 EFI_STATUS Status;\r
918 EFI_HTTP_PROTOCOL *Http;\r
919\r
920 if (HttpIo == NULL || HttpIo->Http == NULL || ResponseData == NULL) {\r
921 return EFI_INVALID_PARAMETER;\r
922 }\r
923\r
7570696c
JW
924 //\r
925 // Start the timer, and wait Timeout seconds to receive the header packet.\r
926 //\r
927 Status = gBS->SetTimer (HttpIo->TimeoutEvent, TimerRelative, HTTP_BOOT_RESPONSE_TIMEOUT * TICKS_PER_MS);\r
928 if (EFI_ERROR (Status)) {\r
929 return Status;\r
930 }\r
931\r
d933e70a
JW
932 //\r
933 // Queue the response token to HTTP instances.\r
934 //\r
935 HttpIo->RspToken.Status = EFI_NOT_READY;\r
936 if (RecvMsgHeader) {\r
937 HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;\r
938 } else {\r
939 HttpIo->RspToken.Message->Data.Response = NULL;\r
940 }\r
941 HttpIo->RspToken.Message->HeaderCount = 0;\r
942 HttpIo->RspToken.Message->Headers = NULL;\r
943 HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength;\r
944 HttpIo->RspToken.Message->Body = ResponseData->Body;\r
945\r
946 Http = HttpIo->Http;\r
947 HttpIo->IsRxDone = FALSE;\r
948 Status = Http->Response (\r
949 Http,\r
950 &HttpIo->RspToken\r
951 );\r
952 \r
953 if (EFI_ERROR (Status)) {\r
7570696c 954 gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);\r
d933e70a
JW
955 return Status;\r
956 }\r
957\r
958 //\r
62cae351 959 // Poll the network until receive finish.\r
d933e70a 960 //\r
7570696c 961 while (!HttpIo->IsRxDone && ((HttpIo->TimeoutEvent == NULL) || EFI_ERROR (gBS->CheckEvent (HttpIo->TimeoutEvent)))) {\r
d933e70a
JW
962 Http->Poll (Http);\r
963 }\r
964\r
7570696c
JW
965 gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);\r
966\r
967 if (!HttpIo->IsRxDone) {\r
968 //\r
969 // Timeout occurs, cancel the response token.\r
970 //\r
971 Http->Cancel (Http, &HttpIo->RspToken);\r
972 \r
973 Status = EFI_TIMEOUT;\r
974 \r
975 return Status;\r
976 } else {\r
977 HttpIo->IsRxDone = FALSE;\r
978 }\r
979\r
d933e70a
JW
980 //\r
981 // Store the received data into the wrapper.\r
982 //\r
072289f4
ZL
983 ResponseData->Status = HttpIo->RspToken.Status;\r
984 ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;\r
985 ResponseData->Headers = HttpIo->RspToken.Message->Headers;\r
986 ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength;\r
d933e70a
JW
987\r
988 return Status;\r
989}\r
fa848a40 990\r
221463c2
JW
991/**\r
992 This function checks the HTTP(S) URI scheme.\r
993\r
994 @param[in] Uri The pointer to the URI string.\r
995 \r
996 @retval EFI_SUCCESS The URI scheme is valid.\r
997 @retval EFI_INVALID_PARAMETER The URI scheme is not HTTP or HTTPS.\r
998 @retval EFI_ACCESS_DENIED HTTP is disabled and the URI is HTTP.\r
999\r
1000**/\r
1001EFI_STATUS\r
1002HttpBootCheckUriScheme (\r
1003 IN CHAR8 *Uri\r
1004 )\r
1005{\r
1006 UINTN Index;\r
1007 EFI_STATUS Status;\r
1008\r
1009 Status = EFI_SUCCESS;\r
1010\r
1011 //\r
1012 // Convert the scheme to all lower case.\r
1013 //\r
1014 for (Index = 0; Index < AsciiStrLen (Uri); Index++) {\r
1015 if (Uri[Index] == ':') {\r
1016 break;\r
1017 }\r
1018 if (Uri[Index] >= 'A' && Uri[Index] <= 'Z') {\r
1019 Uri[Index] -= (CHAR8)('A' - 'a');\r
1020 }\r
1021 }\r
1022\r
1023 //\r
1024 // Return EFI_INVALID_PARAMETER if the URI is not HTTP or HTTPS.\r
1025 //\r
1026 if ((AsciiStrnCmp (Uri, "http://", 7) != 0) && (AsciiStrnCmp (Uri, "https://", 8) != 0)) {\r
1027 DEBUG ((EFI_D_ERROR, "HttpBootCheckUriScheme: Invalid Uri.\n"));\r
1028 return EFI_INVALID_PARAMETER;\r
1029 }\r
1030 \r
1031 //\r
1032 // HTTP is disabled, return EFI_ACCESS_DENIED if the URI is HTTP.\r
1033 //\r
1034 if (!PcdGetBool (PcdAllowHttpConnections) && (AsciiStrnCmp (Uri, "http://", 7) == 0)) {\r
1035 DEBUG ((EFI_D_ERROR, "HttpBootCheckUriScheme: HTTP is disabled.\n"));\r
1036 return EFI_ACCESS_DENIED;\r
1037 }\r
1038\r
1039 return Status;\r
1040}\r
1041\r
fa848a40
FS
1042/**\r
1043 Get the URI address string from the input device path.\r
1044\r
1045 Caller need to free the buffer in the UriAddress pointer.\r
1046 \r
1047 @param[in] FilePath Pointer to the device path which contains a URI device path node.\r
73617fa6 1048 @param[out] UriAddress The URI address string extract from the device path.\r
fa848a40
FS
1049 \r
1050 @retval EFI_SUCCESS The URI string is returned.\r
1051 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
1052\r
1053**/\r
1054EFI_STATUS\r
1055HttpBootParseFilePath (\r
1056 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
1057 OUT CHAR8 **UriAddress\r
1058 )\r
1059{\r
1060 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1061 URI_DEVICE_PATH *UriDevicePath;\r
1062 CHAR8 *Uri;\r
1063 UINTN UriStrLength;\r
1064\r
1065 if (FilePath == NULL) {\r
1066 return EFI_INVALID_PARAMETER;\r
1067 }\r
1068\r
1069 *UriAddress = NULL;\r
1070\r
1071 //\r
1072 // Extract the URI address from the FilePath\r
1073 //\r
1074 TempDevicePath = FilePath;\r
1075 while (!IsDevicePathEnd (TempDevicePath)) {\r
1076 if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&\r
1077 (DevicePathSubType (TempDevicePath) == MSG_URI_DP)) {\r
1078 UriDevicePath = (URI_DEVICE_PATH*) TempDevicePath;\r
1079 //\r
1080 // UEFI Spec doesn't require the URI to be a NULL-terminated string\r
1081 // So we allocate a new buffer and always append a '\0' to it.\r
1082 //\r
1083 UriStrLength = DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
1084 if (UriStrLength == 0) {\r
1085 //\r
1086 // return a NULL UriAddress if it's a empty URI device path node.\r
1087 //\r
1088 break;\r
1089 }\r
1090 Uri = AllocatePool (UriStrLength + 1);\r
1091 if (Uri == NULL) {\r
1092 return EFI_OUT_OF_RESOURCES;\r
1093 }\r
1094 CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL));\r
1095 Uri[DevicePathNodeLength (UriDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL)] = '\0';\r
1096\r
1097 *UriAddress = Uri;\r
1098 }\r
1099 TempDevicePath = NextDevicePathNode (TempDevicePath);\r
1100 }\r
1101\r
1102 return EFI_SUCCESS;\r
1103}\r
587d204c
FS
1104\r
1105/**\r
1106 This function returns the image type according to server replied HTTP message\r
1107 and also the image's URI info.\r
1108\r
1109 @param[in] Uri The pointer to the image's URI string.\r
1110 @param[in] UriParser URI Parse result returned by NetHttpParseUrl(). \r
1111 @param[in] HeaderCount Number of HTTP header structures in Headers list. \r
1112 @param[in] Headers Array containing list of HTTP headers.\r
1113 @param[out] ImageType The image type of the downloaded file.\r
1114 \r
1115 @retval EFI_SUCCESS The image type is returned in ImageType.\r
1116 @retval EFI_INVALID_PARAMETER ImageType, Uri or UriParser is NULL.\r
1117 @retval EFI_INVALID_PARAMETER HeaderCount is not zero, and Headers is NULL.\r
1118 @retval EFI_NOT_FOUND Failed to identify the image type.\r
1119 @retval Others Unexpect error happened.\r
1120\r
1121**/\r
1122EFI_STATUS\r
1123HttpBootCheckImageType (\r
1124 IN CHAR8 *Uri,\r
1125 IN VOID *UriParser,\r
1126 IN UINTN HeaderCount,\r
1127 IN EFI_HTTP_HEADER *Headers,\r
1128 OUT HTTP_BOOT_IMAGE_TYPE *ImageType\r
1129 )\r
1130{\r
1131 EFI_STATUS Status;\r
1132 EFI_HTTP_HEADER *Header;\r
1133 CHAR8 *FilePath;\r
1134 CHAR8 *FilePost;\r
1135\r
1136 if (Uri == NULL || UriParser == NULL || ImageType == NULL) {\r
1137 return EFI_INVALID_PARAMETER;\r
1138 }\r
1139\r
1140 if (HeaderCount != 0 && Headers == NULL) {\r
1141 return EFI_INVALID_PARAMETER;\r
1142 }\r
1143\r
1144 //\r
1145 // Determine the image type by the HTTP Content-Type header field first.\r
1146 // "application/efi" -> EFI Image\r
1147 //\r
1148 Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_CONTENT_TYPE);\r
1149 if (Header != NULL) {\r
1150 if (AsciiStriCmp (Header->FieldValue, HTTP_CONTENT_TYPE_APP_EFI) == 0) {\r
1151 *ImageType = ImageTypeEfi;\r
1152 return EFI_SUCCESS;\r
1153 }\r
1154 }\r
1155\r
1156 //\r
1157 // Determine the image type by file extension:\r
1158 // *.efi -> EFI Image\r
1159 // *.iso -> CD/DVD Image\r
1160 // *.img -> Virtual Disk Image\r
1161 //\r
1162 Status = HttpUrlGetPath (\r
1163 Uri,\r
1164 UriParser,\r
1165 &FilePath\r
1166 );\r
1167 if (EFI_ERROR (Status)) {\r
1168 return Status;\r
1169 }\r
1170\r
1171 FilePost = FilePath + AsciiStrLen (FilePath) - 4;\r
1172 if (AsciiStrCmp (FilePost, ".efi") == 0) {\r
1173 *ImageType = ImageTypeEfi;\r
1174 } else if (AsciiStrCmp (FilePost, ".iso") == 0) {\r
1175 *ImageType = ImageTypeVirtualCd;\r
1176 } else if (AsciiStrCmp (FilePost, ".img") == 0) {\r
1177 *ImageType = ImageTypeVirtualDisk;\r
1178 } else {\r
1179 *ImageType = ImageTypeMax;\r
1180 }\r
1181\r
1182 FreePool (FilePath);\r
1183\r
1184 return (*ImageType < ImageTypeMax) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
1185}\r
1186\r
1187/**\r
1188 This function register the RAM disk info to the system.\r
1189 \r
1190 @param[in] Private The pointer to the driver's private data.\r
1191 @param[in] BufferSize The size of Buffer in bytes.\r
1192 @param[in] Buffer The base address of the RAM disk.\r
1193 @param[in] ImageType The image type of the file in Buffer.\r
1194\r
1195 @retval EFI_SUCCESS The RAM disk has been registered.\r
1196 @retval EFI_NOT_FOUND No RAM disk protocol instances were found.\r
1197 @retval EFI_UNSUPPORTED The ImageType is not supported.\r
1198 @retval Others Unexpected error happened.\r
1199\r
1200**/\r
1201EFI_STATUS\r
1202HttpBootRegisterRamDisk (\r
1203 IN HTTP_BOOT_PRIVATE_DATA *Private,\r
1204 IN UINTN BufferSize,\r
1205 IN VOID *Buffer,\r
1206 IN HTTP_BOOT_IMAGE_TYPE ImageType\r
1207 )\r
1208{\r
1209 EFI_RAM_DISK_PROTOCOL *RamDisk;\r
1210 EFI_STATUS Status;\r
1211 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1212 EFI_GUID *RamDiskType;\r
1213 \r
1214 ASSERT (Private != NULL);\r
1215 ASSERT (Buffer != NULL);\r
1216 ASSERT (BufferSize != 0);\r
1217\r
1218 Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID**) &RamDisk);\r
1219 if (EFI_ERROR (Status)) {\r
1220 DEBUG ((EFI_D_ERROR, "HTTP Boot: Couldn't find the RAM Disk protocol - %r\n", Status));\r
1221 return Status;\r
1222 }\r
1223\r
1224 if (ImageType == ImageTypeVirtualCd) {\r
1225 RamDiskType = &gEfiVirtualCdGuid;\r
1226 } else if (ImageType == ImageTypeVirtualDisk) {\r
1227 RamDiskType = &gEfiVirtualDiskGuid;\r
1228 } else {\r
1229 return EFI_UNSUPPORTED;\r
1230 }\r
1231 \r
1232 Status = RamDisk->Register (\r
1233 (UINTN)Buffer,\r
1234 (UINT64)BufferSize,\r
1235 RamDiskType,\r
1236 Private->UsingIpv6 ? Private->Ip6Nic->DevicePath : Private->Ip4Nic->DevicePath,\r
1237 &DevicePath\r
1238 );\r
1239 if (EFI_ERROR (Status)) {\r
1240 DEBUG ((EFI_D_ERROR, "HTTP Boot: Failed to register RAM Disk - %r\n", Status));\r
1241 }\r
1242\r
1243 return Status;\r
1244}\r
1245\r