]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/HttpBootDxe/HttpBootSupport.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / HttpBootDxe / HttpBootSupport.c
1 /** @file
2 Support functions implementation for UEFI HTTP boot driver.
3
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 - 2020 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "HttpBootDxe.h"
11
12 /**
13 Get the Nic handle using any child handle in the IPv4 stack.
14
15 @param[in] ControllerHandle Pointer to child handle over IPv4.
16
17 @return NicHandle The pointer to the Nic handle.
18 @return NULL Can't find the Nic handle.
19
20 **/
21 EFI_HANDLE
22 HttpBootGetNicByIp4Children (
23 IN EFI_HANDLE ControllerHandle
24 )
25 {
26 EFI_HANDLE NicHandle;
27
28 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);
29 if (NicHandle == NULL) {
30 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
31 if (NicHandle == NULL) {
32 return NULL;
33 }
34 }
35
36 return NicHandle;
37 }
38
39 /**
40 Get the Nic handle using any child handle in the IPv6 stack.
41
42 @param[in] ControllerHandle Pointer to child handle over IPv6.
43
44 @return NicHandle The pointer to the Nic handle.
45 @return NULL Can't find the Nic handle.
46
47 **/
48 EFI_HANDLE
49 HttpBootGetNicByIp6Children (
50 IN EFI_HANDLE ControllerHandle
51 )
52 {
53 EFI_HANDLE NicHandle;
54
55 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);
56 if (NicHandle == NULL) {
57 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
58 if (NicHandle == NULL) {
59 return NULL;
60 }
61 }
62
63 return NicHandle;
64 }
65
66 /**
67 This function is to convert UINTN to ASCII string with the required formatting.
68
69 @param[in] Number Numeric value to be converted.
70 @param[in] Buffer The pointer to the buffer for ASCII string.
71 @param[in] Length The length of the required format.
72
73 **/
74 VOID
75 HttpBootUintnToAscDecWithFormat (
76 IN UINTN Number,
77 IN UINT8 *Buffer,
78 IN INTN Length
79 )
80 {
81 UINTN Remainder;
82
83 for ( ; Length > 0; Length--) {
84 Remainder = Number % 10;
85 Number /= 10;
86 Buffer[Length - 1] = (UINT8)('0' + Remainder);
87 }
88 }
89
90 /**
91 This function is to display the IPv4 address.
92
93 @param[in] Ip The pointer to the IPv4 address.
94
95 **/
96 VOID
97 HttpBootShowIp4Addr (
98 IN EFI_IPv4_ADDRESS *Ip
99 )
100 {
101 UINTN Index;
102
103 for (Index = 0; Index < 4; Index++) {
104 AsciiPrint ("%d", Ip->Addr[Index]);
105 if (Index < 3) {
106 AsciiPrint (".");
107 }
108 }
109 }
110
111 /**
112 This function is to display the IPv6 address.
113
114 @param[in] Ip The pointer to the IPv6 address.
115
116 **/
117 VOID
118 HttpBootShowIp6Addr (
119 IN EFI_IPv6_ADDRESS *Ip
120 )
121 {
122 UINTN Index;
123
124 for (Index = 0; Index < 16; Index++) {
125 if (Ip->Addr[Index] != 0) {
126 AsciiPrint ("%x", Ip->Addr[Index]);
127 }
128
129 Index++;
130 if (Index > 15) {
131 return;
132 }
133
134 if (((Ip->Addr[Index] & 0xf0) == 0) && (Ip->Addr[Index - 1] != 0)) {
135 AsciiPrint ("0");
136 }
137
138 AsciiPrint ("%x", Ip->Addr[Index]);
139 if (Index < 15) {
140 AsciiPrint (":");
141 }
142 }
143 }
144
145 /**
146 This function is to display the HTTP error status.
147
148 @param[in] StatusCode The status code value in HTTP message.
149
150 **/
151 VOID
152 HttpBootPrintErrorMessage (
153 EFI_HTTP_STATUS_CODE StatusCode
154 )
155 {
156 AsciiPrint ("\n");
157
158 switch (StatusCode) {
159 case HTTP_STATUS_300_MULTIPLE_CHOICES:
160 AsciiPrint ("\n Redirection: 300 Multiple Choices");
161 break;
162
163 case HTTP_STATUS_301_MOVED_PERMANENTLY:
164 AsciiPrint ("\n Redirection: 301 Moved Permanently");
165 break;
166
167 case HTTP_STATUS_302_FOUND:
168 AsciiPrint ("\n Redirection: 302 Found");
169 break;
170
171 case HTTP_STATUS_303_SEE_OTHER:
172 AsciiPrint ("\n Redirection: 303 See Other");
173 break;
174
175 case HTTP_STATUS_304_NOT_MODIFIED:
176 AsciiPrint ("\n Redirection: 304 Not Modified");
177 break;
178
179 case HTTP_STATUS_305_USE_PROXY:
180 AsciiPrint ("\n Redirection: 305 Use Proxy");
181 break;
182
183 case HTTP_STATUS_307_TEMPORARY_REDIRECT:
184 AsciiPrint ("\n Redirection: 307 Temporary Redirect");
185 break;
186
187 case HTTP_STATUS_308_PERMANENT_REDIRECT:
188 AsciiPrint ("\n Redirection: 308 Permanent Redirect");
189 break;
190
191 case HTTP_STATUS_400_BAD_REQUEST:
192 AsciiPrint ("\n Client Error: 400 Bad Request");
193 break;
194
195 case HTTP_STATUS_401_UNAUTHORIZED:
196 AsciiPrint ("\n Client Error: 401 Unauthorized");
197 break;
198
199 case HTTP_STATUS_402_PAYMENT_REQUIRED:
200 AsciiPrint ("\n Client Error: 402 Payment Required");
201 break;
202
203 case HTTP_STATUS_403_FORBIDDEN:
204 AsciiPrint ("\n Client Error: 403 Forbidden");
205 break;
206
207 case HTTP_STATUS_404_NOT_FOUND:
208 AsciiPrint ("\n Client Error: 404 Not Found");
209 break;
210
211 case HTTP_STATUS_405_METHOD_NOT_ALLOWED:
212 AsciiPrint ("\n Client Error: 405 Method Not Allowed");
213 break;
214
215 case HTTP_STATUS_406_NOT_ACCEPTABLE:
216 AsciiPrint ("\n Client Error: 406 Not Acceptable");
217 break;
218
219 case HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED:
220 AsciiPrint ("\n Client Error: 407 Proxy Authentication Required");
221 break;
222
223 case HTTP_STATUS_408_REQUEST_TIME_OUT:
224 AsciiPrint ("\n Client Error: 408 Request Timeout");
225 break;
226
227 case HTTP_STATUS_409_CONFLICT:
228 AsciiPrint ("\n Client Error: 409 Conflict");
229 break;
230
231 case HTTP_STATUS_410_GONE:
232 AsciiPrint ("\n Client Error: 410 Gone");
233 break;
234
235 case HTTP_STATUS_411_LENGTH_REQUIRED:
236 AsciiPrint ("\n Client Error: 411 Length Required");
237 break;
238
239 case HTTP_STATUS_412_PRECONDITION_FAILED:
240 AsciiPrint ("\n Client Error: 412 Precondition Failed");
241 break;
242
243 case HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE:
244 AsciiPrint ("\n Client Error: 413 Request Entity Too Large");
245 break;
246
247 case HTTP_STATUS_414_REQUEST_URI_TOO_LARGE:
248 AsciiPrint ("\n Client Error: 414 Request URI Too Long");
249 break;
250
251 case HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE:
252 AsciiPrint ("\n Client Error: 415 Unsupported Media Type");
253 break;
254
255 case HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED:
256 AsciiPrint ("\n Client Error: 416 Requested Range Not Satisfiable");
257 break;
258
259 case HTTP_STATUS_417_EXPECTATION_FAILED:
260 AsciiPrint ("\n Client Error: 417 Expectation Failed");
261 break;
262
263 case HTTP_STATUS_500_INTERNAL_SERVER_ERROR:
264 AsciiPrint ("\n Server Error: 500 Internal Server Error");
265 break;
266
267 case HTTP_STATUS_501_NOT_IMPLEMENTED:
268 AsciiPrint ("\n Server Error: 501 Not Implemented");
269 break;
270
271 case HTTP_STATUS_502_BAD_GATEWAY:
272 AsciiPrint ("\n Server Error: 502 Bad Gateway");
273 break;
274
275 case HTTP_STATUS_503_SERVICE_UNAVAILABLE:
276 AsciiPrint ("\n Server Error: 503 Service Unavailable");
277 break;
278
279 case HTTP_STATUS_504_GATEWAY_TIME_OUT:
280 AsciiPrint ("\n Server Error: 504 Gateway Timeout");
281 break;
282
283 case HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED:
284 AsciiPrint ("\n Server Error: 505 HTTP Version Not Supported");
285 break;
286
287 default:;
288 }
289 }
290
291 /**
292 Notify the callback function when an event is triggered.
293
294 @param[in] Event The triggered event.
295 @param[in] Context The opaque parameter to the function.
296
297 **/
298 VOID
299 EFIAPI
300 HttpBootCommonNotify (
301 IN EFI_EVENT Event,
302 IN VOID *Context
303 )
304 {
305 *((BOOLEAN *)Context) = TRUE;
306 }
307
308 /**
309 Retrieve the host address using the EFI_DNS6_PROTOCOL.
310
311 @param[in] Private The pointer to the driver's private data.
312 @param[in] HostName Pointer to buffer containing hostname.
313 @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
314
315 @retval EFI_SUCCESS Operation succeeded.
316 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
317 @retval Others Other errors as indicated.
318 **/
319 EFI_STATUS
320 HttpBootDns (
321 IN HTTP_BOOT_PRIVATE_DATA *Private,
322 IN CHAR16 *HostName,
323 OUT EFI_IPv6_ADDRESS *IpAddress
324 )
325 {
326 EFI_STATUS Status;
327 EFI_DNS6_PROTOCOL *Dns6;
328 EFI_DNS6_CONFIG_DATA Dns6ConfigData;
329 EFI_DNS6_COMPLETION_TOKEN Token;
330 EFI_HANDLE Dns6Handle;
331 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
332 EFI_IPv6_ADDRESS *DnsServerList;
333 UINTN DnsServerListCount;
334 UINTN DataSize;
335 BOOLEAN IsDone;
336
337 DnsServerList = NULL;
338 DnsServerListCount = 0;
339 Dns6 = NULL;
340 Dns6Handle = NULL;
341 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
342
343 //
344 // Get DNS server list from EFI IPv6 Configuration protocol.
345 //
346 Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **)&Ip6Config);
347 if (!EFI_ERROR (Status)) {
348 //
349 // Get the required size.
350 //
351 DataSize = 0;
352 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
353 if (Status == EFI_BUFFER_TOO_SMALL) {
354 DnsServerList = AllocatePool (DataSize);
355 if (DnsServerList == NULL) {
356 return EFI_OUT_OF_RESOURCES;
357 }
358
359 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
360 if (EFI_ERROR (Status)) {
361 FreePool (DnsServerList);
362 DnsServerList = NULL;
363 } else {
364 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
365 }
366 }
367 }
368
369 //
370 // Create a DNSv6 child instance and get the protocol.
371 //
372 Status = NetLibCreateServiceChild (
373 Private->Controller,
374 Private->Ip6Nic->ImageHandle,
375 &gEfiDns6ServiceBindingProtocolGuid,
376 &Dns6Handle
377 );
378 if (EFI_ERROR (Status)) {
379 goto Exit;
380 }
381
382 Status = gBS->OpenProtocol (
383 Dns6Handle,
384 &gEfiDns6ProtocolGuid,
385 (VOID **)&Dns6,
386 Private->Ip6Nic->ImageHandle,
387 Private->Controller,
388 EFI_OPEN_PROTOCOL_BY_DRIVER
389 );
390 if (EFI_ERROR (Status)) {
391 goto Exit;
392 }
393
394 //
395 // Configure DNS6 instance for the DNS server address and protocol.
396 //
397 ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
398 Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
399 Dns6ConfigData.DnsServerList = DnsServerList;
400 Dns6ConfigData.EnableDnsCache = TRUE;
401 Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
402 IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &Private->StationIp.v6);
403 Status = Dns6->Configure (
404 Dns6,
405 &Dns6ConfigData
406 );
407 if (EFI_ERROR (Status)) {
408 goto Exit;
409 }
410
411 Token.Status = EFI_NOT_READY;
412 IsDone = FALSE;
413 //
414 // Create event to set the IsDone flag when name resolution is finished.
415 //
416 Status = gBS->CreateEvent (
417 EVT_NOTIFY_SIGNAL,
418 TPL_NOTIFY,
419 HttpBootCommonNotify,
420 &IsDone,
421 &Token.Event
422 );
423 if (EFI_ERROR (Status)) {
424 goto Exit;
425 }
426
427 //
428 // Start asynchronous name resolution.
429 //
430 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
431 if (EFI_ERROR (Status)) {
432 goto Exit;
433 }
434
435 while (!IsDone) {
436 Dns6->Poll (Dns6);
437 }
438
439 //
440 // Name resolution is done, check result.
441 //
442 Status = Token.Status;
443 if (!EFI_ERROR (Status)) {
444 if (Token.RspData.H2AData == NULL) {
445 Status = EFI_DEVICE_ERROR;
446 goto Exit;
447 }
448
449 if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
450 Status = EFI_DEVICE_ERROR;
451 goto Exit;
452 }
453
454 //
455 // We just return the first IPv6 address from DNS protocol.
456 //
457 IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
458 Status = EFI_SUCCESS;
459 }
460
461 Exit:
462
463 if (Token.Event != NULL) {
464 gBS->CloseEvent (Token.Event);
465 }
466
467 if (Token.RspData.H2AData != NULL) {
468 if (Token.RspData.H2AData->IpList != NULL) {
469 FreePool (Token.RspData.H2AData->IpList);
470 }
471
472 FreePool (Token.RspData.H2AData);
473 }
474
475 if (Dns6 != NULL) {
476 Dns6->Configure (Dns6, NULL);
477
478 gBS->CloseProtocol (
479 Dns6Handle,
480 &gEfiDns6ProtocolGuid,
481 Private->Ip6Nic->ImageHandle,
482 Private->Controller
483 );
484 }
485
486 if (Dns6Handle != NULL) {
487 NetLibDestroyServiceChild (
488 Private->Controller,
489 Private->Ip6Nic->ImageHandle,
490 &gEfiDns6ServiceBindingProtocolGuid,
491 Dns6Handle
492 );
493 }
494
495 if (DnsServerList != NULL) {
496 FreePool (DnsServerList);
497 }
498
499 return Status;
500 }
501
502 /**
503 This function checks the HTTP(S) URI scheme.
504
505 @param[in] Uri The pointer to the URI string.
506
507 @retval EFI_SUCCESS The URI scheme is valid.
508 @retval EFI_INVALID_PARAMETER The URI scheme is not HTTP or HTTPS.
509 @retval EFI_ACCESS_DENIED HTTP is disabled and the URI is HTTP.
510
511 **/
512 EFI_STATUS
513 HttpBootCheckUriScheme (
514 IN CHAR8 *Uri
515 )
516 {
517 UINTN Index;
518 EFI_STATUS Status;
519
520 Status = EFI_SUCCESS;
521
522 //
523 // Convert the scheme to all lower case.
524 //
525 for (Index = 0; Index < AsciiStrLen (Uri); Index++) {
526 if (Uri[Index] == ':') {
527 break;
528 }
529
530 if ((Uri[Index] >= 'A') && (Uri[Index] <= 'Z')) {
531 Uri[Index] -= (CHAR8)('A' - 'a');
532 }
533 }
534
535 //
536 // Return EFI_INVALID_PARAMETER if the URI is not HTTP or HTTPS.
537 //
538 if ((AsciiStrnCmp (Uri, "http://", 7) != 0) && (AsciiStrnCmp (Uri, "https://", 8) != 0)) {
539 DEBUG ((DEBUG_ERROR, "HttpBootCheckUriScheme: Invalid Uri.\n"));
540 return EFI_INVALID_PARAMETER;
541 }
542
543 //
544 // HTTP is disabled, return EFI_ACCESS_DENIED if the URI is HTTP.
545 //
546 if (!PcdGetBool (PcdAllowHttpConnections) && (AsciiStrnCmp (Uri, "http://", 7) == 0)) {
547 DEBUG ((DEBUG_ERROR, "HttpBootCheckUriScheme: HTTP is disabled.\n"));
548 return EFI_ACCESS_DENIED;
549 }
550
551 return Status;
552 }
553
554 /**
555 Get the URI address string from the input device path.
556
557 Caller need to free the buffer in the UriAddress pointer.
558
559 @param[in] FilePath Pointer to the device path which contains a URI device path node.
560 @param[out] UriAddress The URI address string extract from the device path.
561
562 @retval EFI_SUCCESS The URI string is returned.
563 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
564
565 **/
566 EFI_STATUS
567 HttpBootParseFilePath (
568 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
569 OUT CHAR8 **UriAddress
570 )
571 {
572 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
573 URI_DEVICE_PATH *UriDevicePath;
574 CHAR8 *Uri;
575 UINTN UriStrLength;
576
577 if (FilePath == NULL) {
578 return EFI_INVALID_PARAMETER;
579 }
580
581 *UriAddress = NULL;
582
583 //
584 // Extract the URI address from the FilePath
585 //
586 TempDevicePath = FilePath;
587 while (!IsDevicePathEnd (TempDevicePath)) {
588 if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&
589 (DevicePathSubType (TempDevicePath) == MSG_URI_DP))
590 {
591 UriDevicePath = (URI_DEVICE_PATH *)TempDevicePath;
592 //
593 // UEFI Spec doesn't require the URI to be a NULL-terminated string
594 // So we allocate a new buffer and always append a '\0' to it.
595 //
596 UriStrLength = DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
597 if (UriStrLength == 0) {
598 //
599 // return a NULL UriAddress if it's a empty URI device path node.
600 //
601 break;
602 }
603
604 Uri = AllocatePool (UriStrLength + 1);
605 if (Uri == NULL) {
606 return EFI_OUT_OF_RESOURCES;
607 }
608
609 CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL));
610 Uri[DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL)] = '\0';
611
612 *UriAddress = Uri;
613 }
614
615 TempDevicePath = NextDevicePathNode (TempDevicePath);
616 }
617
618 return EFI_SUCCESS;
619 }
620
621 /**
622 This function returns the image type according to server replied HTTP message
623 and also the image's URI info.
624
625 @param[in] Uri The pointer to the image's URI string.
626 @param[in] UriParser URI Parse result returned by NetHttpParseUrl().
627 @param[in] HeaderCount Number of HTTP header structures in Headers list.
628 @param[in] Headers Array containing list of HTTP headers.
629 @param[out] ImageType The image type of the downloaded file.
630
631 @retval EFI_SUCCESS The image type is returned in ImageType.
632 @retval EFI_INVALID_PARAMETER ImageType, Uri or UriParser is NULL.
633 @retval EFI_INVALID_PARAMETER HeaderCount is not zero, and Headers is NULL.
634 @retval EFI_NOT_FOUND Failed to identify the image type.
635 @retval Others Unexpected error happened.
636
637 **/
638 EFI_STATUS
639 HttpBootCheckImageType (
640 IN CHAR8 *Uri,
641 IN VOID *UriParser,
642 IN UINTN HeaderCount,
643 IN EFI_HTTP_HEADER *Headers,
644 OUT HTTP_BOOT_IMAGE_TYPE *ImageType
645 )
646 {
647 EFI_STATUS Status;
648 EFI_HTTP_HEADER *Header;
649 CHAR8 *FilePath;
650 CHAR8 *FilePost;
651
652 if ((Uri == NULL) || (UriParser == NULL) || (ImageType == NULL)) {
653 return EFI_INVALID_PARAMETER;
654 }
655
656 if ((HeaderCount != 0) && (Headers == NULL)) {
657 return EFI_INVALID_PARAMETER;
658 }
659
660 //
661 // Determine the image type by the HTTP Content-Type header field first.
662 // "application/efi" -> EFI Image
663 // "application/vnd.efi-iso" -> CD/DVD Image
664 // "application/vnd.efi-img" -> Virtual Disk Image
665 //
666 Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_CONTENT_TYPE);
667 if (Header != NULL) {
668 if (AsciiStriCmp (Header->FieldValue, HTTP_CONTENT_TYPE_APP_EFI) == 0) {
669 *ImageType = ImageTypeEfi;
670 return EFI_SUCCESS;
671 } else if (AsciiStriCmp (Header->FieldValue, HTTP_CONTENT_TYPE_APP_ISO) == 0) {
672 *ImageType = ImageTypeVirtualCd;
673 return EFI_SUCCESS;
674 } else if (AsciiStriCmp (Header->FieldValue, HTTP_CONTENT_TYPE_APP_IMG) == 0) {
675 *ImageType = ImageTypeVirtualDisk;
676 return EFI_SUCCESS;
677 }
678 }
679
680 //
681 // Determine the image type by file extension:
682 // *.efi -> EFI Image
683 // *.iso -> CD/DVD Image
684 // *.img -> Virtual Disk Image
685 //
686 Status = HttpUrlGetPath (
687 Uri,
688 UriParser,
689 &FilePath
690 );
691 if (EFI_ERROR (Status)) {
692 return Status;
693 }
694
695 FilePost = FilePath + AsciiStrLen (FilePath) - 4;
696 if (AsciiStriCmp (FilePost, ".efi") == 0) {
697 *ImageType = ImageTypeEfi;
698 } else if (AsciiStriCmp (FilePost, ".iso") == 0) {
699 *ImageType = ImageTypeVirtualCd;
700 } else if (AsciiStriCmp (FilePost, ".img") == 0) {
701 *ImageType = ImageTypeVirtualDisk;
702 } else {
703 *ImageType = ImageTypeMax;
704 }
705
706 FreePool (FilePath);
707
708 return (*ImageType < ImageTypeMax) ? EFI_SUCCESS : EFI_NOT_FOUND;
709 }
710
711 /**
712 This function register the RAM disk info to the system.
713
714 @param[in] Private The pointer to the driver's private data.
715 @param[in] BufferSize The size of Buffer in bytes.
716 @param[in] Buffer The base address of the RAM disk.
717 @param[in] ImageType The image type of the file in Buffer.
718
719 @retval EFI_SUCCESS The RAM disk has been registered.
720 @retval EFI_NOT_FOUND No RAM disk protocol instances were found.
721 @retval EFI_UNSUPPORTED The ImageType is not supported.
722 @retval Others Unexpected error happened.
723
724 **/
725 EFI_STATUS
726 HttpBootRegisterRamDisk (
727 IN HTTP_BOOT_PRIVATE_DATA *Private,
728 IN UINTN BufferSize,
729 IN VOID *Buffer,
730 IN HTTP_BOOT_IMAGE_TYPE ImageType
731 )
732 {
733 EFI_RAM_DISK_PROTOCOL *RamDisk;
734 EFI_STATUS Status;
735 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
736 EFI_GUID *RamDiskType;
737
738 ASSERT (Private != NULL);
739 ASSERT (Buffer != NULL);
740 ASSERT (BufferSize != 0);
741
742 Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID **)&RamDisk);
743 if (EFI_ERROR (Status)) {
744 DEBUG ((DEBUG_ERROR, "HTTP Boot: Couldn't find the RAM Disk protocol - %r\n", Status));
745 return Status;
746 }
747
748 if (ImageType == ImageTypeVirtualCd) {
749 RamDiskType = &gEfiVirtualCdGuid;
750 } else if (ImageType == ImageTypeVirtualDisk) {
751 RamDiskType = &gEfiVirtualDiskGuid;
752 } else {
753 return EFI_UNSUPPORTED;
754 }
755
756 Status = RamDisk->Register (
757 (UINTN)Buffer,
758 (UINT64)BufferSize,
759 RamDiskType,
760 Private->UsingIpv6 ? Private->Ip6Nic->DevicePath : Private->Ip4Nic->DevicePath,
761 &DevicePath
762 );
763 if (EFI_ERROR (Status)) {
764 DEBUG ((DEBUG_ERROR, "HTTP Boot: Failed to register RAM Disk - %r\n", Status));
765 }
766
767 return Status;
768 }
769
770 /**
771 Indicate if the HTTP status code indicates a redirection.
772
773 @param[in] StatusCode HTTP status code from server.
774
775 @return TRUE if it's redirection.
776
777 **/
778 BOOLEAN
779 HttpBootIsHttpRedirectStatusCode (
780 IN EFI_HTTP_STATUS_CODE StatusCode
781 )
782 {
783 if ((StatusCode == HTTP_STATUS_301_MOVED_PERMANENTLY) ||
784 (StatusCode == HTTP_STATUS_302_FOUND) ||
785 (StatusCode == HTTP_STATUS_307_TEMPORARY_REDIRECT) ||
786 (StatusCode == HTTP_STATUS_308_PERMANENT_REDIRECT))
787 {
788 return TRUE;
789 }
790
791 return FALSE;
792 }