TianoCore EDK2 master
Loading...
Searching...
No Matches
Http.c
Go to the documentation of this file.
1
12#include "Http.h"
13
14#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32
15
16//
17// Constant strings and definitions related to the message
18// indicating the amount of progress in the dowloading of a HTTP file.
19//
20
21//
22// Number of steps in the progression slider.
23//
24#define HTTP_PROGRESS_SLIDER_STEPS \
25 ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 3)
26
27//
28// Size in number of characters plus one (final zero) of the message to
29// indicate the progress of an HTTP download. The format is "[(progress slider:
30// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There
31// are thus the number of characters in HTTP_PROGR_FRAME[] plus 11 characters
32// (2 // spaces, "Kb" and seven characters for the number of KBytes).
33//
34#define HTTP_PROGRESS_MESSAGE_SIZE \
35 ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12)
36
37//
38// Buffer size. Note that larger buffer does not mean better speed.
39//
40#define DEFAULT_BUF_SIZE SIZE_32KB
41#define MAX_BUF_SIZE SIZE_4MB
42
43#define MIN_PARAM_COUNT 2
44#define MAX_PARAM_COUNT 4
45#define NEED_REDIRECTION(Code) \
46 (((Code >= HTTP_STATUS_300_MULTIPLE_CHOICES) \
47 && (Code <= HTTP_STATUS_307_TEMPORARY_REDIRECT)) \
48 || (Code == HTTP_STATUS_308_PERMANENT_REDIRECT))
49
50#define CLOSE_HTTP_HANDLE(ControllerHandle, HttpChildHandle) \
51 do { \
52 if (HttpChildHandle) { \
53 CloseProtocolAndDestroyServiceChild ( \
54 ControllerHandle, \
55 &gEfiHttpServiceBindingProtocolGuid, \
56 &gEfiHttpProtocolGuid, \
57 HttpChildHandle \
58 ); \
59 HttpChildHandle = NULL; \
60 } \
61 } while (0)
62
63typedef enum {
64 HdrHost,
65 HdrConn,
66 HdrAgent,
67 HdrMax
68} HDR_TYPE;
69
70#define USER_AGENT_HDR "Mozilla/5.0 (EDK2; Linux) Gecko/20100101 Firefox/79.0"
71
72#define TIMER_MAX_TIMEOUT_S 10
73
74//
75// File name to use when Uri ends with "/".
76//
77#define DEFAULT_HTML_FILE L"index.html"
78#define DEFAULT_HTTP_PROTO L"http"
79
80//
81// String to delete the HTTP progress message to be able to update it :
82// (HTTP_PROGRESS_MESSAGE_SIZE-1) '\b'.
83//
84#define HTTP_PROGRESS_DEL \
85 L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\
86\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
87
88#define HTTP_KB L"\b\b\b\b\b\b\b\b\b\b"
89//
90// Frame for the progression slider.
91//
92#define HTTP_PROGR_FRAME L"[ ]"
93
94//
95// Improve readability by using these macros.
96//
97#define PRINT_HII(token, ...) \
98 ShellPrintHiiEx (\
99 -1, -1, NULL, token, mHttpHiiHandle, __VA_ARGS__)
100
101#define PRINT_HII_APP(token, value) \
102 PRINT_HII (token, HTTP_APP_NAME, value)
103
104//
105// TimeBaseLib.h constants.
106// These will be removed once the library gets fixed.
107//
108
109//
110// Define EPOCH (1970-JANUARY-01) in the Julian Date representation.
111//
112#define EPOCH_JULIAN_DATE 2440588
113
114//
115// Seconds per unit.
116//
117#define SEC_PER_MIN ((UINTN) 60)
118#define SEC_PER_HOUR ((UINTN) 3600)
119#define SEC_PER_DAY ((UINTN) 86400)
120
121//
122// String descriptions for server errors.
123//
124STATIC CONST CHAR16 *ErrStatusDesc[] =
125{
126 L"400 Bad Request",
127 L"401 Unauthorized",
128 L"402 Payment required",
129 L"403 Forbidden",
130 L"404 Not Found",
131 L"405 Method not allowed",
132 L"406 Not acceptable",
133 L"407 Proxy authentication required",
134 L"408 Request time out",
135 L"409 Conflict",
136 L"410 Gone",
137 L"411 Length required",
138 L"412 Precondition failed",
139 L"413 Request entity too large",
140 L"414 Request URI to large",
141 L"415 Unsupported media type",
142 L"416 Requested range not satisfied",
143 L"417 Expectation failed",
144 L"500 Internal server error",
145 L"501 Not implemented",
146 L"502 Bad gateway",
147 L"503 Service unavailable",
148 L"504 Gateway timeout",
149 L"505 HTTP version not supported"
150};
151
152STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
153 { L"-i", TypeValue },
154 { L"-k", TypeFlag },
155 { L"-l", TypeValue },
156 { L"-m", TypeFlag },
157 { L"-s", TypeValue },
158 { L"-t", TypeValue },
159 { NULL, TypeMax }
160};
161
162//
163// Local File Handle.
164//
165STATIC SHELL_FILE_HANDLE mFileHandle = NULL;
166
167//
168// Path of the local file, Unicode encoded.
169//
170STATIC CONST CHAR16 *mLocalFilePath;
171
172STATIC BOOLEAN gRequestCallbackComplete = FALSE;
173STATIC BOOLEAN gResponseCallbackComplete = FALSE;
174
175STATIC BOOLEAN gHttpError;
176
177EFI_HII_HANDLE mHttpHiiHandle;
178
179//
180// Functions declarations.
181//
182
192STATIC
193BOOLEAN
195 IN CONST CHAR16 *ValueStr,
196 OUT UINT16 *Value
197 );
198
217STATIC
220 IN EFI_HANDLE ControllerHandle,
221 IN UINTN NicNumber,
222 OUT CHAR16 *NicName
223 );
224
244STATIC
247 IN EFI_HANDLE ControllerHandle,
248 IN EFI_GUID *ServiceBindingProtocolGuid,
249 IN EFI_GUID *ProtocolGuid,
250 OUT EFI_HANDLE *ChildHandle,
251 OUT VOID **Interface
252 );
253
266STATIC
267VOID
269 IN EFI_HANDLE ControllerHandle,
270 IN EFI_GUID *ServiceBindingProtocolGuid,
271 IN EFI_GUID *ProtocolGuid,
272 IN EFI_HANDLE ChildHandle
273 );
274
286STATIC
289 IN HTTP_DOWNLOAD_CONTEXT *Context,
290 IN EFI_HANDLE ControllerHandle,
291 IN CHAR16 *NicName
292 );
293
302STATIC
305 IN CHAR16 *String
306 )
307{
308 CHAR16 *Str;
309 UINTN Len;
310
311 ASSERT (String != NULL);
312
313 if (String == NULL) {
314 return EFI_INVALID_PARAMETER;
315 }
316
317 Str = String;
318
319 //
320 // Remove any whitespace at the beginning of the Str.
321 //
322 while (*Str == L' ' || *Str == L'\t') {
323 Str++;
324 }
325
326 //
327 // Remove any whitespace at the end of the Str.
328 //
329 do {
330 Len = StrLen (Str);
331 if (!Len || ((Str[Len - 1] != L' ') && (Str[Len - 1] != '\t'))) {
332 break;
333 }
334
335 Str[Len - 1] = CHAR_NULL;
336 } while (Len);
337
338 CopyMem (String, Str, StrSize (Str));
339
340 return EFI_SUCCESS;
341}
342
343//
344// Callbacks for request and response.
345// We just acknowledge that operation has completed here.
346//
347
354STATIC
355VOID
356EFIAPI
358 IN EFI_EVENT Event,
359 IN VOID *Context
360 )
361{
362 gRequestCallbackComplete = TRUE;
363}
364
370STATIC
371VOID
372EFIAPI
374 IN EFI_EVENT Event,
375 IN VOID *Context
376 )
377{
378 gResponseCallbackComplete = TRUE;
379}
380
381//
382// Set of functions from TimeBaseLib.
383// This will be removed once TimeBaseLib is enabled for ShellPkg.
384//
385
393STATIC
394UINTN
396 IN EFI_TIME *Time
397 )
398{
399 UINTN a;
400 UINTN y;
401 UINTN m;
402 //
403 // Absolute Julian Date representation of the supplied Time.
404 //
405 UINTN JulianDate;
406 //
407 // Number of days elapsed since EPOCH_JULIAN_DAY.
408 //
409 UINTN EpochDays;
410
411 a = (14 - Time->Month) / 12;
412 y = Time->Year + 4800 - a;
413 m = Time->Month + (12 * a) - 3;
414
415 JulianDate = Time->Day + ((153 * m + 2) / 5) + (365 * y) + (y / 4) -
416 (y / 100) + (y / 400) - 32045;
417
418 ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
419 EpochDays = JulianDate - EPOCH_JULIAN_DATE;
420
421 return EpochDays;
422}
423
430STATIC
431UINTN
432EFIAPI
434 IN EFI_TIME *Time
435 )
436{
437 //
438 // Number of days elapsed since EPOCH_JULIAN_DAY.
439 //
440 UINTN EpochDays;
441 UINTN EpochSeconds;
442
443 EpochDays = EfiGetEpochDays (Time);
444
445 EpochSeconds = (EpochDays * SEC_PER_DAY) +
446 ((UINTN)Time->Hour * SEC_PER_HOUR) +
447 (Time->Minute * SEC_PER_MIN) + Time->Second;
448
449 return EpochSeconds;
450}
451
470 IN EFI_HANDLE ImageHandle,
471 IN EFI_SYSTEM_TABLE *SystemTable
472 )
473{
474 EFI_STATUS Status;
475 LIST_ENTRY *CheckPackage;
476 UINTN ParamCount;
477 UINTN HandleCount;
478 UINTN NicNumber;
479 UINTN InitialSize;
480 UINTN ParamOffset;
481 UINTN StartSize;
482 CHAR16 *ProblemParam;
483 CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
484 CHAR16 *Walker1;
485 CHAR16 *VStr;
486 CONST CHAR16 *UserNicName;
487 CONST CHAR16 *ValueStr;
488 CONST CHAR16 *RemoteFilePath;
489 CONST CHAR16 *Walker;
491 EFI_HANDLE *Handles;
492 EFI_HANDLE ControllerHandle;
493 HTTP_DOWNLOAD_CONTEXT Context;
494 BOOLEAN NicFound;
495
496 ProblemParam = NULL;
497 RemoteFilePath = NULL;
498 NicFound = FALSE;
499 Handles = NULL;
500
501 //
502 // Initialize the Shell library (we must be in non-auto-init...).
503 //
504 ParamOffset = 0;
505 gHttpError = FALSE;
506
507 Status = ShellInitialize ();
508 if (EFI_ERROR (Status)) {
509 ASSERT_EFI_ERROR (Status);
510 return SHELL_ABORTED;
511 }
512
513 ZeroMem (&Context, sizeof (Context));
514
515 //
516 // Parse the command line.
517 //
518 Status = ShellCommandLineParse (
519 ParamList,
520 &CheckPackage,
521 &ProblemParam,
522 TRUE
523 );
524 if (EFI_ERROR (Status)) {
525 if ( (Status == EFI_VOLUME_CORRUPTED)
526 && (ProblemParam != NULL))
527 {
528 PRINT_HII_APP (STRING_TOKEN (STR_GEN_PROBLEM), ProblemParam);
529 SHELL_FREE_NON_NULL (ProblemParam);
530 } else {
531 ASSERT (FALSE);
532 }
533
534 goto Error;
535 }
536
537 //
538 // Check the number of parameters.
539 //
540 Status = EFI_INVALID_PARAMETER;
541
542 ParamCount = ShellCommandLineGetCount (CheckPackage);
543 if (ParamCount > MAX_PARAM_COUNT) {
544 PRINT_HII_APP (STRING_TOKEN (STR_GEN_TOO_MANY), NULL);
545 goto Error;
546 }
547
548 if (ParamCount < MIN_PARAM_COUNT) {
549 PRINT_HII_APP (STRING_TOKEN (STR_GEN_TOO_FEW), NULL);
550 goto Error;
551 }
552
553 ZeroMem (&Context.HttpConfigData, sizeof (Context.HttpConfigData));
554 ZeroMem (&IPv4Node, sizeof (IPv4Node));
555 IPv4Node.UseDefaultAddress = TRUE;
556
557 Context.HttpConfigData.HttpVersion = HttpVersion11;
558 Context.HttpConfigData.AccessPoint.IPv4Node = &IPv4Node;
559
560 //
561 // Get the host address (not necessarily IPv4 format).
562 //
563 ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
564 if (!ValueStr) {
565 PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
566 goto Error;
567 } else {
568 StartSize = 0;
569 TrimSpaces ((CHAR16 *)ValueStr);
570 if (!StrStr (ValueStr, L"://")) {
571 Context.ServerAddrAndProto = StrnCatGrow (
572 &Context.ServerAddrAndProto,
573 &StartSize,
574 DEFAULT_HTTP_PROTO,
575 StrLen (DEFAULT_HTTP_PROTO)
576 );
577 Context.ServerAddrAndProto = StrnCatGrow (
578 &Context.ServerAddrAndProto,
579 &StartSize,
580 L"://",
581 StrLen (L"://")
582 );
583 VStr = (CHAR16 *)ValueStr;
584 } else {
585 VStr = StrStr (ValueStr, L"://") + StrLen (L"://");
586 }
587
588 for (Walker1 = VStr; *Walker1; Walker1++) {
589 if (*Walker1 == L'/') {
590 break;
591 }
592 }
593
594 if (*Walker1 == L'/') {
595 ParamOffset = 1;
596 RemoteFilePath = Walker1;
597 }
598
599 Context.ServerAddrAndProto = StrnCatGrow (
600 &Context.ServerAddrAndProto,
601 &StartSize,
602 ValueStr,
603 StrLen (ValueStr) - StrLen (Walker1)
604 );
605 if (!Context.ServerAddrAndProto) {
606 Status = EFI_OUT_OF_RESOURCES;
607 goto Error;
608 }
609 }
610
611 if (!RemoteFilePath) {
612 RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
613 if (!RemoteFilePath) {
614 //
615 // If no path given, assume just "/".
616 //
617 RemoteFilePath = L"/";
618 }
619 }
620
621 TrimSpaces ((CHAR16 *)RemoteFilePath);
622
623 if (ParamCount == MAX_PARAM_COUNT - ParamOffset) {
624 mLocalFilePath = ShellCommandLineGetRawValue (
625 CheckPackage,
626 MAX_PARAM_COUNT - 1 - ParamOffset
627 );
628 } else {
629 Walker = RemoteFilePath + StrLen (RemoteFilePath);
630 while ((--Walker) >= RemoteFilePath) {
631 if ((*Walker == L'\\') ||
632 (*Walker == L'/'))
633 {
634 break;
635 }
636 }
637
638 mLocalFilePath = Walker + 1;
639 }
640
641 if (!StrLen (mLocalFilePath)) {
642 mLocalFilePath = DEFAULT_HTML_FILE;
643 }
644
645 InitialSize = 0;
646 Context.Uri = StrnCatGrow (
647 &Context.Uri,
648 &InitialSize,
649 RemoteFilePath,
650 StrLen (RemoteFilePath)
651 );
652 if (!Context.Uri) {
653 Status = EFI_OUT_OF_RESOURCES;
654 goto Error;
655 }
656
657 //
658 // Get the name of the Network Interface Card to be used if any.
659 //
660 UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");
661
662 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
663 if ( (ValueStr != NULL)
664 && (!StringToUint16 (
665 ValueStr,
666 &Context.HttpConfigData.AccessPoint.IPv4Node->LocalPort
667 )
668 ))
669 {
670 goto Error;
671 }
672
673 Context.BufferSize = DEFAULT_BUF_SIZE;
674
675 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");
676 if (ValueStr != NULL) {
677 Context.BufferSize = ShellStrToUintn (ValueStr);
678 if (!Context.BufferSize || (Context.BufferSize > MAX_BUF_SIZE)) {
679 PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
680 goto Error;
681 }
682 }
683
684 ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
685 if (ValueStr != NULL) {
686 Context.HttpConfigData.TimeOutMillisec = (UINT32)ShellStrToUintn (ValueStr);
687 }
688
689 //
690 // Locate all HTTP Service Binding protocols.
691 //
692 Status = gBS->LocateHandleBuffer (
694 &gEfiManagedNetworkServiceBindingProtocolGuid,
695 NULL,
696 &HandleCount,
697 &Handles
698 );
699 if (EFI_ERROR (Status) || (HandleCount == 0)) {
700 PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NO_NIC), NULL);
701 if (!EFI_ERROR (Status)) {
702 Status = EFI_NOT_FOUND;
703 }
704
705 goto Error;
706 }
707
708 Status = EFI_NOT_FOUND;
709
710 Context.Flags = 0;
711 if (ShellCommandLineGetFlag (CheckPackage, L"-m")) {
712 Context.Flags |= DL_FLAG_TIME;
713 }
714
715 if (ShellCommandLineGetFlag (CheckPackage, L"-k")) {
716 Context.Flags |= DL_FLAG_KEEP_BAD;
717 }
718
719 for (NicNumber = 0;
720 (NicNumber < HandleCount) && (Status != EFI_SUCCESS);
721 NicNumber++)
722 {
723 ControllerHandle = Handles[NicNumber];
724
725 Status = GetNicName (ControllerHandle, NicNumber, NicName);
726 if (EFI_ERROR (Status)) {
727 PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NIC_NAME), NicNumber, Status);
728 continue;
729 }
730
731 if (UserNicName != NULL) {
732 if (StrCmp (NicName, UserNicName) != 0) {
733 Status = EFI_NOT_FOUND;
734 continue;
735 }
736
737 NicFound = TRUE;
738 }
739
740 Status = DownloadFile (&Context, ControllerHandle, NicName);
741 PRINT_HII (STRING_TOKEN (STR_GEN_CRLF), NULL);
742
743 if (EFI_ERROR (Status)) {
744 PRINT_HII (
745 STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD),
746 RemoteFilePath,
747 NicName,
748 Status
749 );
750 //
751 // If a user aborted the operation,
752 // do not try another controller.
753 //
754 if (Status == EFI_ABORTED) {
755 goto Error;
756 }
757 }
758
759 if (gHttpError) {
760 //
761 // This is not related to connection, so no need to repeat with
762 // another interface.
763 //
764 break;
765 }
766 }
767
768 if ((UserNicName != NULL) && (!NicFound)) {
769 PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND), UserNicName);
770 }
771
772Error:
773 ShellCommandLineFreeVarList (CheckPackage);
774 SHELL_FREE_NON_NULL (Handles);
775 SHELL_FREE_NON_NULL (Context.ServerAddrAndProto);
776 SHELL_FREE_NON_NULL (Context.Uri);
777
778 return Status & ~MAX_BIT;
779}
780
790STATIC
791BOOLEAN
793 IN CONST CHAR16 *ValueStr,
794 OUT UINT16 *Value
795 )
796{
797 UINTN Val;
798
799 Val = ShellStrToUintn (ValueStr);
800 if (Val > MAX_UINT16) {
801 PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
802 return FALSE;
803 }
804
805 *Value = (UINT16)Val;
806 return TRUE;
807}
808
827STATIC
830 IN EFI_HANDLE ControllerHandle,
831 IN UINTN NicNumber,
832 OUT CHAR16 *NicName
833 )
834{
835 EFI_STATUS Status;
836 EFI_HANDLE MnpHandle;
839
841 ControllerHandle,
842 &gEfiManagedNetworkServiceBindingProtocolGuid,
843 &gEfiManagedNetworkProtocolGuid,
844 &MnpHandle,
845 (VOID **)&Mnp
846 );
847 if (EFI_ERROR (Status)) {
848 goto Error;
849 }
850
851 Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
852 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
853 goto Error;
854 }
855
857 NicName,
858 IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,
859 SnpMode.IfType == NET_IFTYPE_ETHERNET ? L"eth%d" : L"unk%d",
860 NicNumber
861 );
862
863 Status = EFI_SUCCESS;
864
865Error:
866
867 if (MnpHandle != NULL) {
869 ControllerHandle,
870 &gEfiManagedNetworkServiceBindingProtocolGuid,
871 &gEfiManagedNetworkProtocolGuid,
872 MnpHandle
873 );
874 }
875
876 return Status;
877}
878
898STATIC
901 IN EFI_HANDLE ControllerHandle,
902 IN EFI_GUID *ServiceBindingProtocolGuid,
903 IN EFI_GUID *ProtocolGuid,
904 OUT EFI_HANDLE *ChildHandle,
905 OUT VOID **Interface
906 )
907{
908 EFI_STATUS Status;
909
910 *ChildHandle = NULL;
911 Status = NetLibCreateServiceChild (
912 ControllerHandle,
914 ServiceBindingProtocolGuid,
915 ChildHandle
916 );
917 if (!EFI_ERROR (Status)) {
918 Status = gBS->OpenProtocol (
919 *ChildHandle,
920 ProtocolGuid,
921 Interface,
923 ControllerHandle,
924 EFI_OPEN_PROTOCOL_GET_PROTOCOL
925 );
926 if (EFI_ERROR (Status)) {
928 ControllerHandle,
930 ServiceBindingProtocolGuid,
931 *ChildHandle
932 );
933 *ChildHandle = NULL;
934 }
935 }
936
937 return Status;
938}
939
951STATIC
952VOID
954 IN EFI_HANDLE ControllerHandle,
955 IN EFI_GUID *ServiceBindingProtocolGuid,
956 IN EFI_GUID *ProtocolGuid,
957 IN EFI_HANDLE ChildHandle
958 )
959{
960 gBS->CloseProtocol (
961 ChildHandle,
962 ProtocolGuid,
964 ControllerHandle
965 );
966
968 ControllerHandle,
970 ServiceBindingProtocolGuid,
971 ChildHandle
972 );
973}
974
987STATIC
990 IN HTTP_DOWNLOAD_CONTEXT *Context,
991 IN OUT BOOLEAN *CallBackComplete
992 )
993{
994 EFI_STATUS Status;
995 EFI_EVENT WaitEvt;
996
997 Status = EFI_SUCCESS;
998
999 //
1000 // Use a timer to measure timeout. Cannot use Stall here!
1001 //
1002 Status = gBS->CreateEvent (
1003 EVT_TIMER,
1004 TPL_CALLBACK,
1005 NULL,
1006 NULL,
1007 &WaitEvt
1008 );
1009 ASSERT_EFI_ERROR (Status);
1010
1011 if (!EFI_ERROR (Status)) {
1012 Status = gBS->SetTimer (
1013 WaitEvt,
1015 EFI_TIMER_PERIOD_SECONDS (TIMER_MAX_TIMEOUT_S)
1016 );
1017
1018 ASSERT_EFI_ERROR (Status);
1019 }
1020
1021 while ( !*CallBackComplete
1022 && (!EFI_ERROR (Status))
1023 && EFI_ERROR (gBS->CheckEvent (WaitEvt)))
1024 {
1025 Status = Context->Http->Poll (Context->Http);
1026 if ( !Context->ContentDownloaded
1027 && (CallBackComplete == &gResponseCallbackComplete))
1028 {
1029 //
1030 // An HTTP server may just send a response redirection header.
1031 // In this case, don't wait for the event as
1032 // it might never happen and we waste 10s waiting.
1033 // Note that at this point Response may not has been populated,
1034 // so it needs to be checked first.
1035 //
1036 if ( Context->ResponseToken.Message
1037 && Context->ResponseToken.Message->Data.Response
1038 && (NEED_REDIRECTION (
1039 Context->ResponseToken.Message->Data.Response->StatusCode
1040 )
1041 ))
1042 {
1043 break;
1044 }
1045 }
1046 }
1047
1048 gBS->SetTimer (WaitEvt, TimerCancel, 0);
1049 gBS->CloseEvent (WaitEvt);
1050
1051 if (*CallBackComplete) {
1052 return EFI_SUCCESS;
1053 }
1054
1055 if (!EFI_ERROR (Status)) {
1056 Status = EFI_TIMEOUT;
1057 }
1058
1059 return Status;
1060}
1061
1076STATIC
1079 IN HTTP_DOWNLOAD_CONTEXT *Context,
1080 IN CHAR16 *DownloadUrl
1081 )
1082{
1083 EFI_HTTP_REQUEST_DATA RequestData;
1084 EFI_HTTP_HEADER RequestHeader[HdrMax];
1085 EFI_HTTP_MESSAGE RequestMessage;
1086 EFI_STATUS Status;
1087 CHAR16 *Host;
1088 UINTN StringSize;
1089
1090 ZeroMem (&RequestData, sizeof (RequestData));
1091 ZeroMem (&RequestHeader, sizeof (RequestHeader));
1092 ZeroMem (&RequestMessage, sizeof (RequestMessage));
1093 ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken));
1094
1095 RequestHeader[HdrHost].FieldName = "Host";
1096 RequestHeader[HdrConn].FieldName = "Connection";
1097 RequestHeader[HdrAgent].FieldName = "User-Agent";
1098
1099 Host = (CHAR16 *)Context->ServerAddrAndProto;
1100 while (*Host != CHAR_NULL && *Host != L'/') {
1101 Host++;
1102 }
1103
1104 if (*Host == CHAR_NULL) {
1105 return EFI_INVALID_PARAMETER;
1106 }
1107
1108 //
1109 // Get the next slash.
1110 //
1111 Host++;
1112 //
1113 // And now the host name.
1114 //
1115 Host++;
1116
1117 StringSize = StrLen (Host) + 1;
1118 RequestHeader[HdrHost].FieldValue = AllocatePool (StringSize);
1119 if (!RequestHeader[HdrHost].FieldValue) {
1120 return EFI_OUT_OF_RESOURCES;
1121 }
1122
1124 Host,
1125 RequestHeader[HdrHost].FieldValue,
1126 StringSize
1127 );
1128
1129 RequestHeader[HdrConn].FieldValue = "close";
1130 RequestHeader[HdrAgent].FieldValue = USER_AGENT_HDR;
1131 RequestMessage.HeaderCount = HdrMax;
1132
1133 RequestData.Method = HttpMethodGet;
1134 RequestData.Url = DownloadUrl;
1135
1136 RequestMessage.Data.Request = &RequestData;
1137 RequestMessage.Headers = RequestHeader;
1138 RequestMessage.BodyLength = 0;
1139 RequestMessage.Body = NULL;
1140 Context->RequestToken.Event = NULL;
1141
1142 //
1143 // Completion callback event to be set when Request completes.
1144 //
1145 Status = gBS->CreateEvent (
1146 EVT_NOTIFY_SIGNAL,
1147 TPL_CALLBACK,
1149 Context,
1150 &Context->RequestToken.Event
1151 );
1152 ASSERT_EFI_ERROR (Status);
1153
1154 Context->RequestToken.Status = EFI_SUCCESS;
1155 Context->RequestToken.Message = &RequestMessage;
1156 gRequestCallbackComplete = FALSE;
1157 Status = Context->Http->Request (Context->Http, &Context->RequestToken);
1158 if (EFI_ERROR (Status)) {
1159 goto Error;
1160 }
1161
1162 Status = WaitForCompletion (Context, &gRequestCallbackComplete);
1163 if (EFI_ERROR (Status)) {
1164 Context->Http->Cancel (Context->Http, &Context->RequestToken);
1165 }
1166
1167Error:
1168 SHELL_FREE_NON_NULL (RequestHeader[HdrHost].FieldValue);
1169 if (Context->RequestToken.Event) {
1170 gBS->CloseEvent (Context->RequestToken.Event);
1171 ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken));
1172 }
1173
1174 return Status;
1175}
1176
1188STATIC
1190EFIAPI
1192 IN HTTP_DOWNLOAD_CONTEXT *Context,
1193 IN UINTN DownloadLen,
1194 IN CHAR8 *Buffer
1195 )
1196{
1197 CHAR16 Progress[HTTP_PROGRESS_MESSAGE_SIZE];
1198 UINTN NbOfKb;
1199 UINTN Index;
1200 UINTN LastStep;
1201 UINTN Step;
1202 EFI_STATUS Status;
1203
1204 LastStep = 0;
1205 Step = 0;
1206
1207 ShellSetFilePosition (mFileHandle, Context->LastReportedNbOfBytes);
1208 Status = ShellWriteFile (mFileHandle, &DownloadLen, Buffer);
1209 if (EFI_ERROR (Status)) {
1210 if (Context->ContentDownloaded > 0) {
1211 PRINT_HII (STRING_TOKEN (STR_GEN_CRLF), NULL);
1212 }
1213
1214 PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_WRITE), mLocalFilePath, Status);
1215 return Status;
1216 }
1217
1218 if (Context->ContentDownloaded == 0) {
1219 ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME);
1220 }
1221
1222 Context->ContentDownloaded += DownloadLen;
1223 NbOfKb = Context->ContentDownloaded >> 10;
1224
1225 Progress[0] = L'\0';
1226 if (Context->ContentLength) {
1227 LastStep = (Context->LastReportedNbOfBytes * HTTP_PROGRESS_SLIDER_STEPS) /
1228 Context->ContentLength;
1229 Step = (Context->ContentDownloaded * HTTP_PROGRESS_SLIDER_STEPS) /
1230 Context->ContentLength;
1231 }
1232
1233 Context->LastReportedNbOfBytes = Context->ContentDownloaded;
1234
1235 if (Step <= LastStep) {
1236 if (!Context->ContentLength) {
1237 //
1238 // Update downloaded size, there is no length info available.
1239 //
1240 ShellPrintEx (-1, -1, L"%s", HTTP_KB);
1241 ShellPrintEx (-1, -1, L"%7d Kb", NbOfKb);
1242 }
1243
1244 return EFI_SUCCESS;
1245 }
1246
1247 ShellPrintEx (-1, -1, L"%s", HTTP_PROGRESS_DEL);
1248
1249 Status = StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE, HTTP_PROGR_FRAME);
1250 if (EFI_ERROR (Status)) {
1251 return Status;
1252 }
1253
1254 for (Index = 1; Index < Step; Index++) {
1255 Progress[Index] = L'=';
1256 }
1257
1258 if (Step) {
1259 Progress[Step] = L'>';
1260 }
1261
1263 Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1,
1264 sizeof (Progress) - sizeof (HTTP_PROGR_FRAME),
1265 L" %7d Kb",
1266 NbOfKb
1267 );
1268
1269 ShellPrintEx (-1, -1, L"%s", Progress);
1270
1271 return EFI_SUCCESS;
1272}
1273
1286STATIC
1289 IN CHAR8 *Location,
1290 IN HTTP_DOWNLOAD_CONTEXT *Context,
1291 IN CHAR16 *DownloadUrl
1292 )
1293{
1294 EFI_STATUS Status;
1295 UINTN StringSize;
1296 UINTN FirstStep;
1297 UINTN Idx;
1298 UINTN Step;
1299 CHAR8 *Walker;
1300 CHAR16 *Temp;
1301 CHAR8 *Tmp;
1302 CHAR16 *Url;
1303 BOOLEAN IsAbEmptyUrl;
1304
1305 Tmp = NULL;
1306 Url = NULL;
1307 IsAbEmptyUrl = FALSE;
1308 FirstStep = 0;
1309
1310 StringSize = (AsciiStrSize (Location) * sizeof (CHAR16));
1311 Url = AllocateZeroPool (StringSize);
1312 if (!Url) {
1313 return EFI_OUT_OF_RESOURCES;
1314 }
1315
1316 Status = AsciiStrToUnicodeStrS (
1317 (CONST CHAR8 *)Location,
1318 Url,
1319 StringSize
1320 );
1321
1322 if (EFI_ERROR (Status)) {
1323 goto Error;
1324 }
1325
1326 //
1327 // If an HTTP server redirects to the same location more than once,
1328 // then stop attempts and tell it is not reachable.
1329 //
1330 if (!StrCmp (Url, DownloadUrl)) {
1331 Status = EFI_NO_MAPPING;
1332 goto Error;
1333 }
1334
1335 if (AsciiStrLen (Location) > 2) {
1336 //
1337 // Some servers return 'Location: //server/resource'
1338 //
1339 IsAbEmptyUrl = (Location[0] == '/') && (Location[1] == '/');
1340 if (IsAbEmptyUrl) {
1341 //
1342 // Skip first "//"
1343 //
1344 Location += 2;
1345 FirstStep = 1;
1346 }
1347 }
1348
1349 if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) {
1350 Idx = 0;
1351 Walker = Location;
1352
1353 for (Step = FirstStep; Step < 2; Step++) {
1354 for ( ; *Walker != '/' && *Walker != '\0'; Walker++) {
1355 Idx++;
1356 }
1357
1358 if (!Step) {
1359 //
1360 // Skip "//"
1361 //
1362 Idx += 2;
1363 Walker += 2;
1364 }
1365 }
1366
1367 Tmp = AllocateZeroPool (Idx + 1);
1368 if (!Tmp) {
1369 Status = EFI_OUT_OF_RESOURCES;
1370 goto Error;
1371 }
1372
1373 CopyMem (Tmp, Location, Idx);
1374
1375 //
1376 // Location now points to Uri
1377 //
1378 Location += Idx;
1379 StringSize = (Idx + 1) * sizeof (CHAR16);
1380
1381 SHELL_FREE_NON_NULL (Context->ServerAddrAndProto);
1382
1383 Temp = AllocateZeroPool (StringSize);
1384 if (!Temp) {
1385 Status = EFI_OUT_OF_RESOURCES;
1386 goto Error;
1387 }
1388
1389 Status = AsciiStrToUnicodeStrS (
1390 (CONST CHAR8 *)Tmp,
1391 Temp,
1392 StringSize
1393 );
1394 if (EFI_ERROR (Status)) {
1395 SHELL_FREE_NON_NULL (Temp);
1396 goto Error;
1397 }
1398
1399 Idx = 0;
1400 if (IsAbEmptyUrl) {
1401 Context->ServerAddrAndProto = StrnCatGrow (
1402 &Context->ServerAddrAndProto,
1403 &Idx,
1404 L"http://",
1405 StrLen (L"http://")
1406 );
1407 }
1408
1409 Context->ServerAddrAndProto = StrnCatGrow (
1410 &Context->ServerAddrAndProto,
1411 &Idx,
1412 Temp,
1413 StrLen (Temp)
1414 );
1415 SHELL_FREE_NON_NULL (Temp);
1416 if (!Context->ServerAddrAndProto) {
1417 Status = EFI_OUT_OF_RESOURCES;
1418 goto Error;
1419 }
1420 }
1421
1422 SHELL_FREE_NON_NULL (Context->Uri);
1423
1424 StringSize = AsciiStrSize (Location) * sizeof (CHAR16);
1425 Context->Uri = AllocateZeroPool (StringSize);
1426 if (!Context->Uri) {
1427 Status = EFI_OUT_OF_RESOURCES;
1428 goto Error;
1429 }
1430
1431 //
1432 // Now make changes to the Uri part.
1433 //
1434 Status = AsciiStrToUnicodeStrS (
1435 (CONST CHAR8 *)Location,
1436 Context->Uri,
1437 StringSize
1438 );
1439Error:
1440 SHELL_FREE_NON_NULL (Tmp);
1441 SHELL_FREE_NON_NULL (Url);
1442
1443 return Status;
1444}
1445
1459STATIC
1461EFIAPI
1463 IN HTTP_BODY_PARSE_EVENT EventType,
1464 IN CHAR8 *Data,
1465 IN UINTN Length,
1466 IN VOID *Context
1467 )
1468{
1469 if ( (Data == NULL)
1470 || (EventType == BodyParseEventOnComplete)
1471 || (Context == NULL))
1472 {
1473 return EFI_SUCCESS;
1474 }
1475
1476 return SavePortion (Context, Length, Data);
1477}
1478
1497STATIC
1500 IN HTTP_DOWNLOAD_CONTEXT *Context,
1501 IN CHAR16 *DownloadUrl
1502 )
1503{
1504 EFI_HTTP_RESPONSE_DATA ResponseData;
1505 EFI_HTTP_MESSAGE ResponseMessage;
1506 EFI_HTTP_HEADER *Header;
1507 EFI_STATUS Status;
1508 VOID *MsgParser;
1509 EFI_TIME StartTime;
1510 EFI_TIME EndTime;
1511 CONST CHAR16 *Desc;
1512 UINTN ElapsedSeconds;
1513 BOOLEAN IsTrunked;
1514 BOOLEAN CanMeasureTime;
1515
1516 ZeroMem (&ResponseData, sizeof (ResponseData));
1517 ZeroMem (&ResponseMessage, sizeof (ResponseMessage));
1518 ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken));
1519 IsTrunked = FALSE;
1520
1521 ResponseMessage.Body = Context->Buffer;
1522 Context->ResponseToken.Status = EFI_SUCCESS;
1523 Context->ResponseToken.Message = &ResponseMessage;
1524 Context->ContentLength = 0;
1525 Context->Status = REQ_OK;
1526 Status = EFI_SUCCESS;
1527 MsgParser = NULL;
1528 ResponseData.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;
1529 ResponseMessage.Data.Response = &ResponseData;
1530 Context->ResponseToken.Event = NULL;
1531 CanMeasureTime = FALSE;
1532 if (Context->Flags & DL_FLAG_TIME) {
1533 ZeroMem (&StartTime, sizeof (StartTime));
1534 CanMeasureTime = !EFI_ERROR (gRT->GetTime (&StartTime, NULL));
1535 }
1536
1537 do {
1538 SHELL_FREE_NON_NULL (ResponseMessage.Headers);
1539 ResponseMessage.HeaderCount = 0;
1540 gResponseCallbackComplete = FALSE;
1541 ResponseMessage.BodyLength = Context->BufferSize;
1542
1544 Status = EFI_ABORTED;
1545 break;
1546 }
1547
1548 if (!Context->ContentDownloaded && !Context->ResponseToken.Event) {
1549 Status = gBS->CreateEvent (
1550 EVT_NOTIFY_SIGNAL,
1551 TPL_CALLBACK,
1553 Context,
1554 &Context->ResponseToken.Event
1555 );
1556 ASSERT_EFI_ERROR (Status);
1557 } else {
1558 ResponseMessage.Data.Response = NULL;
1559 }
1560
1561 if (EFI_ERROR (Status)) {
1562 break;
1563 }
1564
1565 Status = Context->Http->Response (Context->Http, &Context->ResponseToken);
1566 if (EFI_ERROR (Status)) {
1567 break;
1568 }
1569
1570 Status = WaitForCompletion (Context, &gResponseCallbackComplete);
1571 if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) {
1572 Status = EFI_SUCCESS;
1573 }
1574
1575 if (EFI_ERROR (Status)) {
1576 Context->Http->Cancel (Context->Http, &Context->ResponseToken);
1577 break;
1578 }
1579
1580 if (!Context->ContentDownloaded) {
1581 if (NEED_REDIRECTION (ResponseData.StatusCode)) {
1582 //
1583 // Need to repeat the request with new Location (server redirected).
1584 //
1585 Context->Status = REQ_NEED_REPEAT;
1586
1587 Header = HttpFindHeader (
1588 ResponseMessage.HeaderCount,
1589 ResponseMessage.Headers,
1590 "Location"
1591 );
1592 if (Header) {
1593 Status = SetHostURI (Header->FieldValue, Context, DownloadUrl);
1594 if (Status == EFI_NO_MAPPING) {
1595 PRINT_HII (
1596 STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),
1597 Context->ServerAddrAndProto,
1598 L"Recursive HTTP server relocation",
1599 Context->Uri
1600 );
1601 }
1602 } else {
1603 //
1604 // Bad reply from the server. Server must specify the location.
1605 // Indicate that resource was not found, and no body collected.
1606 //
1607 Status = EFI_NOT_FOUND;
1608 }
1609
1610 Context->Http->Cancel (Context->Http, &Context->ResponseToken);
1611 break;
1612 }
1613
1614 //
1615 // Init message-body parser by header information.
1616 //
1617 if (!MsgParser) {
1618 Status = HttpInitMsgParser (
1619 ResponseMessage.Data.Request->Method,
1620 ResponseData.StatusCode,
1621 ResponseMessage.HeaderCount,
1622 ResponseMessage.Headers,
1623 ParseMsg,
1624 Context,
1625 &MsgParser
1626 );
1627 if (EFI_ERROR (Status)) {
1628 break;
1629 }
1630 }
1631
1632 //
1633 // If it is a trunked message, rely on the parser.
1634 //
1635 Header = HttpFindHeader (
1636 ResponseMessage.HeaderCount,
1637 ResponseMessage.Headers,
1638 "Transfer-Encoding"
1639 );
1640 IsTrunked = (Header && !AsciiStrCmp (Header->FieldValue, "chunked"));
1641
1642 HttpGetEntityLength (MsgParser, &Context->ContentLength);
1643
1644 if ( (ResponseData.StatusCode >= HTTP_STATUS_400_BAD_REQUEST)
1645 && (ResponseData.StatusCode != HTTP_STATUS_308_PERMANENT_REDIRECT))
1646 {
1647 //
1648 // Server reported an error via Response code.
1649 // Collect the body if any.
1650 //
1651 if (!gHttpError) {
1652 gHttpError = TRUE;
1653
1654 Desc = ErrStatusDesc[ResponseData.StatusCode -
1655 HTTP_STATUS_400_BAD_REQUEST];
1656 PRINT_HII (
1657 STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),
1658 Context->ServerAddrAndProto,
1659 Desc,
1660 Context->Uri
1661 );
1662
1663 //
1664 // This gives an RFC HTTP error.
1665 //
1666 Context->Status = ShellStrToUintn (Desc);
1667 Status = ENCODE_ERROR (Context->Status);
1668 }
1669 }
1670 }
1671
1672 //
1673 // Do NOT try to parse an empty body.
1674 //
1675 if (ResponseMessage.BodyLength || IsTrunked) {
1676 Status = HttpParseMessageBody (
1677 MsgParser,
1678 ResponseMessage.BodyLength,
1679 ResponseMessage.Body
1680 );
1681 }
1682 } while ( !HttpIsMessageComplete (MsgParser)
1683 && !EFI_ERROR (Status)
1684 && ResponseMessage.BodyLength);
1685
1686 if ( (Context->Status != REQ_NEED_REPEAT)
1687 && (Status == EFI_SUCCESS)
1688 && CanMeasureTime)
1689 {
1690 if (!EFI_ERROR (gRT->GetTime (&EndTime, NULL))) {
1691 ElapsedSeconds = EfiTimeToEpoch (&EndTime) - EfiTimeToEpoch (&StartTime);
1692 Print (
1693 L",%a%Lus\n",
1694 ElapsedSeconds ? " " : " < ",
1695 ElapsedSeconds > 1 ? (UINT64)ElapsedSeconds : 1
1696 );
1697 }
1698 }
1699
1700 SHELL_FREE_NON_NULL (MsgParser);
1701 if (Context->ResponseToken.Event) {
1702 gBS->CloseEvent (Context->ResponseToken.Event);
1703 ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken));
1704 }
1705
1706 return Status;
1707}
1708
1725STATIC
1728 IN HTTP_DOWNLOAD_CONTEXT *Context,
1729 IN EFI_HANDLE ControllerHandle,
1730 IN CHAR16 *NicName
1731 )
1732{
1733 EFI_STATUS Status;
1734 CHAR16 *DownloadUrl;
1735 UINTN UrlSize;
1736 EFI_HANDLE HttpChildHandle;
1737
1738 ASSERT (Context);
1739 if (Context == NULL) {
1740 return EFI_INVALID_PARAMETER;
1741 }
1742
1743 DownloadUrl = NULL;
1744 HttpChildHandle = NULL;
1745
1746 Context->Buffer = AllocatePool (Context->BufferSize);
1747 if (Context->Buffer == NULL) {
1748 Status = EFI_OUT_OF_RESOURCES;
1749 goto ON_EXIT;
1750 }
1751
1752 //
1753 // Open the file.
1754 //
1755 if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {
1756 ShellDeleteFileByName (mLocalFilePath);
1757 }
1758
1759 Status = ShellOpenFileByName (
1760 mLocalFilePath,
1761 &mFileHandle,
1762 EFI_FILE_MODE_CREATE |
1763 EFI_FILE_MODE_WRITE |
1764 EFI_FILE_MODE_READ,
1765 0
1766 );
1767 if (EFI_ERROR (Status)) {
1768 PRINT_HII_APP (STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), mLocalFilePath);
1769 goto ON_EXIT;
1770 }
1771
1772 do {
1773 SHELL_FREE_NON_NULL (DownloadUrl);
1774
1775 CLOSE_HTTP_HANDLE (ControllerHandle, HttpChildHandle);
1776
1778 ControllerHandle,
1779 &gEfiHttpServiceBindingProtocolGuid,
1780 &gEfiHttpProtocolGuid,
1781 &HttpChildHandle,
1782 (VOID **)&Context->Http
1783 );
1784
1785 if (EFI_ERROR (Status)) {
1786 PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL), NicName, Status);
1787 goto ON_EXIT;
1788 }
1789
1790 Status = Context->Http->Configure (Context->Http, &Context->HttpConfigData);
1791 if (EFI_ERROR (Status)) {
1792 PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_CONFIGURE), NicName, Status);
1793 goto ON_EXIT;
1794 }
1795
1796 UrlSize = 0;
1797 DownloadUrl = StrnCatGrow (
1798 &DownloadUrl,
1799 &UrlSize,
1800 Context->ServerAddrAndProto,
1801 StrLen (Context->ServerAddrAndProto)
1802 );
1803 if (Context->Uri[0] != L'/') {
1804 DownloadUrl = StrnCatGrow (
1805 &DownloadUrl,
1806 &UrlSize,
1807 L"/",
1808 StrLen (Context->ServerAddrAndProto)
1809 );
1810 }
1811
1812 DownloadUrl = StrnCatGrow (
1813 &DownloadUrl,
1814 &UrlSize,
1815 Context->Uri,
1816 StrLen (Context->Uri)
1817 );
1818 if (DownloadUrl == NULL) {
1819 Status = EFI_OUT_OF_RESOURCES;
1820 goto ON_EXIT;
1821 }
1822
1823 PRINT_HII (STRING_TOKEN (STR_HTTP_DOWNLOADING), DownloadUrl);
1824
1825 Status = SendRequest (Context, DownloadUrl);
1826 if (Status) {
1827 goto ON_EXIT;
1828 }
1829
1830 Status = GetResponse (Context, DownloadUrl);
1831
1832 if (Status) {
1833 goto ON_EXIT;
1834 }
1835 } while (Context->Status == REQ_NEED_REPEAT);
1836
1837 if (Context->Status) {
1838 Status = ENCODE_ERROR (Context->Status);
1839 }
1840
1841ON_EXIT:
1842 //
1843 // Close the file.
1844 //
1845 if (mFileHandle != NULL) {
1846 if (EFI_ERROR (Status) && !(Context->Flags & DL_FLAG_KEEP_BAD)) {
1847 ShellDeleteFile (&mFileHandle);
1848 } else {
1849 ShellCloseFile (&mFileHandle);
1850 }
1851 }
1852
1853 SHELL_FREE_NON_NULL (DownloadUrl);
1854 SHELL_FREE_NON_NULL (Context->Buffer);
1855
1856 CLOSE_HTTP_HANDLE (ControllerHandle, HttpChildHandle);
1857
1858 return Status;
1859}
1860
1870 IN EFI_HANDLE ImageHandle
1871 )
1872{
1873 EFI_STATUS Status;
1874 EFI_HII_PACKAGE_LIST_HEADER *PackageList;
1875 EFI_HII_HANDLE HiiHandle;
1876
1877 //
1878 // Retrieve HII package list from ImageHandle.
1879 //
1880 Status = gBS->OpenProtocol (
1881 ImageHandle,
1882 &gEfiHiiPackageListProtocolGuid,
1883 (VOID **)&PackageList,
1884 ImageHandle,
1885 NULL,
1886 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1887 );
1888 ASSERT_EFI_ERROR (Status);
1889 if (EFI_ERROR (Status)) {
1890 return NULL;
1891 }
1892
1893 //
1894 // Publish HII package list to HII Database.
1895 //
1896 Status = gHiiDatabase->NewPackageList (
1898 PackageList,
1899 NULL,
1900 &HiiHandle
1901 );
1902 ASSERT_EFI_ERROR (Status);
1903 if (EFI_ERROR (Status)) {
1904 return NULL;
1905 }
1906
1907 return HiiHandle;
1908}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
RETURN_STATUS EFIAPI UnicodeStrToAsciiStrS(IN CONST CHAR16 *Source, OUT CHAR8 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2650
RETURN_STATUS EFIAPI AsciiStrToUnicodeStrS(IN CONST CHAR8 *Source, OUT CHAR16 *Destination, IN UINTN DestMax)
Definition: SafeString.c:2873
UINTN EFIAPI AsciiStrSize(IN CONST CHAR8 *String)
Definition: String.c:681
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
CHAR8 *EFIAPI AsciiStrStr(IN CONST CHAR8 *String, IN CONST CHAR8 *SearchString)
Definition: String.c:931
CHAR16 *EFIAPI StrStr(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString)
Definition: String.c:224
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
STATIC VOID CloseProtocolAndDestroyServiceChild(IN EFI_HANDLE ControllerHandle, IN EFI_GUID *ServiceBindingProtocolGuid, IN EFI_GUID *ProtocolGuid, IN EFI_HANDLE ChildHandle)
Definition: Http.c:953
STATIC UINTN EFIAPI EfiTimeToEpoch(IN EFI_TIME *Time)
Definition: Http.c:433
STATIC BOOLEAN StringToUint16(IN CONST CHAR16 *ValueStr, OUT UINT16 *Value)
Definition: Http.c:792
STATIC EFI_STATUS DownloadFile(IN HTTP_DOWNLOAD_CONTEXT *Context, IN EFI_HANDLE ControllerHandle, IN CHAR16 *NicName)
Definition: Http.c:1727
STATIC EFI_STATUS GetResponse(IN HTTP_DOWNLOAD_CONTEXT *Context, IN CHAR16 *DownloadUrl)
Definition: Http.c:1499
STATIC EFI_STATUS WaitForCompletion(IN HTTP_DOWNLOAD_CONTEXT *Context, IN OUT BOOLEAN *CallBackComplete)
Definition: Http.c:989
STATIC EFI_STATUS SendRequest(IN HTTP_DOWNLOAD_CONTEXT *Context, IN CHAR16 *DownloadUrl)
Definition: Http.c:1078
STATIC EFI_STATUS CreateServiceChildAndOpenProtocol(IN EFI_HANDLE ControllerHandle, IN EFI_GUID *ServiceBindingProtocolGuid, IN EFI_GUID *ProtocolGuid, OUT EFI_HANDLE *ChildHandle, OUT VOID **Interface)
Definition: Http.c:900
STATIC VOID EFIAPI ResponseCallback(IN EFI_EVENT Event, IN VOID *Context)
Definition: Http.c:373
STATIC EFI_STATUS GetNicName(IN EFI_HANDLE ControllerHandle, IN UINTN NicNumber, OUT CHAR16 *NicName)
Definition: Http.c:829
STATIC EFI_STATUS TrimSpaces(IN CHAR16 *String)
Definition: Http.c:304
STATIC EFI_STATUS SetHostURI(IN CHAR8 *Location, IN HTTP_DOWNLOAD_CONTEXT *Context, IN CHAR16 *DownloadUrl)
Definition: Http.c:1288
EFI_HII_HANDLE InitializeHiiPackage(IN EFI_HANDLE ImageHandle)
Definition: Http.c:1869
STATIC UINTN EfiGetEpochDays(IN EFI_TIME *Time)
Definition: Http.c:395
STATIC VOID EFIAPI RequestCallback(IN EFI_EVENT Event, IN VOID *Context)
Definition: Http.c:357
STATIC EFI_STATUS EFIAPI ParseMsg(IN HTTP_BODY_PARSE_EVENT EventType, IN CHAR8 *Data, IN UINTN Length, IN VOID *Context)
Definition: Http.c:1462
SHELL_STATUS RunHttp(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Http.c:469
STATIC EFI_STATUS EFIAPI SavePortion(IN HTTP_DOWNLOAD_CONTEXT *Context, IN UINTN DownloadLen, IN CHAR8 *Buffer)
Definition: Http.c:1191
EFI_STATUS EFIAPI HttpInitMsgParser(IN EFI_HTTP_METHOD Method, IN EFI_HTTP_STATUS_CODE StatusCode, IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, IN HTTP_BODY_PARSER_CALLBACK Callback, IN VOID *Context, OUT VOID **MsgParser)
Definition: DxeHttpLib.c:1050
EFI_HTTP_HEADER *EFIAPI HttpFindHeader(IN UINTN HeaderCount, IN EFI_HTTP_HEADER *Headers, IN CHAR8 *FieldName)
Definition: DxeHttpLib.c:855
EFI_STATUS EFIAPI HttpParseMessageBody(IN OUT VOID *MsgParser, IN UINTN BodyLength, IN CHAR8 *Body)
Definition: DxeHttpLib.c:1131
EFI_STATUS EFIAPI HttpGetEntityLength(IN VOID *MsgParser, OUT UINTN *ContentLength)
Definition: DxeHttpLib.c:1445
BOOLEAN EFIAPI HttpIsMessageComplete(IN VOID *MsgParser)
Definition: DxeHttpLib.c:1411
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
Definition: PrintLib.c:408
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ENCODE_ERROR(StatusCode)
Definition: Base.h:1037
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
SHELL_STATUS
Definition: Shell.h:21
@ SHELL_ABORTED
Definition: Shell.h:128
EFI_STATUS EFIAPI NetLibCreateServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN OUT EFI_HANDLE *ChildHandle)
Definition: DxeNetLib.c:1967
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
Definition: DxeNetLib.c:2020
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
CONST CHAR16 *EFIAPI ShellCommandLineGetValue(IN CONST LIST_ENTRY *CheckPackage, IN CHAR16 *KeyString)
EFI_STATUS EFIAPI ShellDeleteFile(IN SHELL_FILE_HANDLE *FileHandle)
Definition: UefiShellLib.c:992
UINTN EFIAPI ShellStrToUintn(IN CONST CHAR16 *String)
BOOLEAN EFIAPI ShellGetExecutionBreakFlag(VOID)
EFI_STATUS EFIAPI ShellDeleteFileByName(IN CONST CHAR16 *FileName)
#define ShellCommandLineParse(CheckList, CheckPackage, ProblemParam, AutoPageBreak)
Make it easy to upgrade from older versions of the shell library.
Definition: ShellLib.h:755
BOOLEAN EFIAPI ShellCommandLineGetFlag(IN CONST LIST_ENTRY *CONST CheckPackage, IN CONST CHAR16 *CONST KeyString)
@ TypeValue
A flag that has some data following it with a space (IE "-a 1").
Definition: ShellLib.h:700
@ TypeFlag
A flag that is present or not present only (IE "-a").
Definition: ShellLib.h:699
EFI_STATUS EFIAPI ShellOpenFileByName(IN CONST CHAR16 *FileName, OUT SHELL_FILE_HANDLE *FileHandle, IN UINT64 OpenMode, IN UINT64 Attributes)
Definition: UefiShellLib.c:720
CHAR16 *EFIAPI StrnCatGrow(IN OUT CHAR16 **Destination, IN OUT UINTN *CurrentSize, IN CONST CHAR16 *Source, IN UINTN Count)
EFI_STATUS EFIAPI ShellFileExists(IN CONST CHAR16 *Name)
VOID EFIAPI ShellCommandLineFreeVarList(IN LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellInitialize(VOID)
Definition: UefiShellLib.c:532
EFI_STATUS EFIAPI ShellSetFilePosition(IN SHELL_FILE_HANDLE FileHandle, IN UINT64 Position)
EFI_STATUS EFIAPI ShellPrintEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR16 *Format,...)
CONST CHAR16 *EFIAPI ShellCommandLineGetRawValue(IN CONST LIST_ENTRY *CONST CheckPackage, IN UINTN Position)
UINTN EFIAPI ShellCommandLineGetCount(IN CONST LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellWriteFile(IN SHELL_FILE_HANDLE FileHandle, IN OUT UINTN *BufferSize, IN VOID *Buffer)
Definition: UefiShellLib.c:947
EFI_STATUS EFIAPI ShellCloseFile(IN SHELL_FILE_HANDLE *FileHandle)
Definition: UefiShellLib.c:969
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
EFI_HII_DATABASE_PROTOCOL * gHiiDatabase
#define STRING_TOKEN(t)
VOID * EFI_HII_HANDLE
#define EFI_TIMER_PERIOD_SECONDS(Seconds)
Definition: UefiLib.h:98
UINTN EFIAPI Print(IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:113
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerRelative
Definition: UefiSpec.h:539
@ ByProtocol
Definition: UefiSpec.h:1518
EFI_HTTP_VERSION HttpVersion
Definition: Http.h:154
EFI_HTTPv4_ACCESS_POINT * IPv4Node
Definition: Http.h:171
UINT32 TimeOutMillisec
Definition: Http.h:158
CHAR8 * FieldValue
Definition: Http.h:220
CHAR8 * FieldName
Definition: Http.h:215
UINTN BodyLength
Definition: Http.h:257
EFI_HTTP_HEADER * Headers
Definition: Http.h:253
union EFI_HTTP_MESSAGE::@577 Data
UINTN HeaderCount
Definition: Http.h:246
VOID * Body
Definition: Http.h:262
EFI_HTTP_RESPONSE_DATA * Response
Definition: Http.h:240
EFI_HTTP_REQUEST_DATA * Request
Definition: Http.h:235
CHAR16 * Url
Definition: Http.h:194
EFI_HTTP_METHOD Method
Definition: Http.h:187
EFI_HTTP_STATUS_CODE StatusCode
Definition: Http.h:204
BOOLEAN UseDefaultAddress
Definition: Http.h:114
Definition: Base.h:213