alder_lake_bios/Insyde/InsydeNetworkPkg/Application/RestTest/RestTest.c

1548 lines
45 KiB
C

/** @file
REST test application sample code
;******************************************************************************
;* Copyright (c) 2021, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "RestTest.h"
#include <Protocol/Dns4.h>
#include <Protocol/Dns6.h>
BOOLEAN mDebugMode = 1;
REST_HTTP_CACHE *HttpCacheTags;
UINTN HttpCacheTagsCnt;
HTML_DISPLAY_LINES *mHtmlDisplayData;
UINTN MaxRows;
UINTN MaxColumns;
UINTN InputTextLength;
SHELL_PARAM_ITEM mNetworkCheckList[] = {
{
L"--device", // Device select
TypeValue,
},
{
L"--get", // Get file from http URL
TypeValue
},
{
L"--upload", // Put file to http URL
TypeValue
},
{
L"--file", // Dest/Source file name of get and post
TypeValue
},
{
L"--chatroom", // chat room demo
TypeValue
},
{
L"--name", // name in chat room
TypeValue
},
{
L"--debug",
TypeFlag
},
{
L"--IPv4",
TypeFlag
},
{
L"--IPv6",
TypeFlag
},
{
NULL,
TypeMax
},
};
UINT8 *HttpErrorString [] = {
"HTTP_STATUS_UNSUPPORTED_STATUS",
"HTTP_STATUS_100_CONTINUE",
"HTTP_STATUS_101_SWITCHING_PROTOCOLS",
"HTTP_STATUS_200_OK",
"HTTP_STATUS_201_CREATED",
"HTTP_STATUS_202_ACCEPTED",
"HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION",
"HTTP_STATUS_204_NO_CONTENT",
"HTTP_STATUS_205_RESET_CONTENT",
"HTTP_STATUS_206_PARTIAL_CONTENT",
"HTTP_STATUS_300_MULTIPLE_CHIOCES",
"HTTP_STATUS_301_MOVED_PERMANENTLY",
"HTTP_STATUS_302_FOUND",
"HTTP_STATUS_303_SEE_OTHER",
"HTTP_STATUS_304_NOT_MODIFIED",
"HTTP_STATUS_305_USE_PROXY",
"HTTP_STATUS_307_TEMPORARY_REDIRECT",
"HTTP_STATUS_400_BAD_REQUEST",
"HTTP_STATUS_401_UNAUTHORIZED",
"HTTP_STATUS_402_PAYMENT_REQUIRED",
"HTTP_STATUS_403_FORBIDDEN",
"HTTP_STATUS_404_NOT_FOUND",
"HTTP_STATUS_405_METHOD_NOT_ALLOWED",
"HTTP_STATUS_406_NOT_ACCEPTABLE",
"HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED",
"HTTP_STATUS_408_REQUEST_TIME_OUT",
"HTTP_STATUS_409_CONFLICT",
"HTTP_STATUS_410_GONE",
"HTTP_STATUS_411_LENGTH_REQUIRED",
"HTTP_STATUS_412_PRECONDITION_FAILED",
"HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE",
"HTTP_STATUS_414_REQUEST_URI_TOO_LARGE",
"HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE",
"HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED",
"HTTP_STATUS_417_EXPECTATION_FAILED",
"HTTP_STATUS_500_INTERNAL_SERVER_ERROR",
"HTTP_STATUS_501_NOT_IMPLEMENTED",
"HTTP_STATUS_502_BAD_GATEWAY",
"HTTP_STATUS_503_SERVICE_UNAVAILABLE",
"HTTP_STATUS_504_GATEWAY_TIME_OUT",
"HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED"
};
UINT16 *
SplitSlash (
IN UINT16 *FileName
)
{
UINTN FileNameLength;
UINTN Index;
UINT16 *TmpFileName;
FileNameLength = StrLen (FileName);
TmpFileName = NULL;
for (Index = 0; Index < FileNameLength; Index++) {
if ((FileName[Index] == '\\') && Index + 1 < FileNameLength) {
TmpFileName = &(FileName[Index+1]);
}
}
if (TmpFileName == NULL) {
return FileName;
}
return TmpFileName;
}
UINTN
EFIAPI
AsciiValueToString (
OUT CHAR8 *Buffer,
IN UINTN Flags,
IN INT64 Value,
IN UINTN Width
);
EFI_STATUS
RestGetFile (
EFI_REST_PROTOCOL *Rest,
UINT16 *URL,
UINTN *HeaderLen,
EFI_HTTP_HEADER **Headers,
UINTN *ContentLength,
VOID **Content
);
EFI_STATUS
DisplayHttpHeaders (
EFI_HTTP_HEADER *Headers,
UINTN HeaderCnt
)
{
UINTN Index;
AsciiPrint ("\nHTTP HEADERS :\n");
for (Index = 0; Index < HeaderCnt; Index++) {
AsciiPrint ("%a : %a\n", Headers[Index].FieldName, Headers[Index].FieldValue);
}
AsciiPrint ("HTTP CONTENTS :\n");
return EFI_SUCCESS;
}
EFI_STATUS
FileFineNameFromURL (
IN CHAR16 *String,
IN UINTN StringLength,
OUT CHAR16 **FileName
)
{
CHAR16 *TmpString;
UINTN Index;
TmpString = String;
for (Index = 0; Index < StringLength; Index++) {
if (String[Index] == L'/') {
TmpString = String + Index + 1;
}
}
*FileName = TmpString;
return EFI_SUCCESS;
}
CHAR8 *
AsciiStrnSplit (
OUT CHAR8 *OriginalStr,
IN UINTN StringLength,
IN CHAR8 *StringEnds
)
{
CHAR8 *TmpCharPtr;
CHAR8 *TmpEndCharPtr;
BOOLEAN StringEndFound;
StringEndFound = FALSE;
TmpCharPtr = OriginalStr;
while (!StringEndFound) {
if (*TmpCharPtr == 0) {
break;
}
if ((UINTN)(TmpCharPtr - OriginalStr) > (UINTN) OriginalStr) {
break;
}
TmpEndCharPtr = StringEnds;
for (;*TmpEndCharPtr != 0; TmpEndCharPtr++) {
if (*TmpEndCharPtr == *TmpCharPtr) {
/// String end
StringEndFound = TRUE;
break;
}
}
if (StringEndFound) {
break;
}
TmpCharPtr++;
}
return TmpCharPtr;
}
VOID
HtmlParserDestroy (
IN OUT HTML_DISPLAY_LINES *HtmlDisplayData
)
{
if (HtmlDisplayData != NULL) {
if (HtmlDisplayData->Lines != 0) {
FreePool (HtmlDisplayData->Lines);
}
FreePool (HtmlDisplayData);
}
}
EFI_STATUS
HtmlParserInitialize (
IN OUT HTML_DISPLAY_LINES **HtmlDisplayData,
IN BOOLEAN Extend
)
{
EFI_STATUS Status;
UINTN LinesCntStep;
HTML_DISPLAY_LINES *TmpHtmlData;
Status = EFI_SUCCESS;
LinesCntStep = 100;
if (*HtmlDisplayData == NULL) {
TmpHtmlData = AllocateZeroPool (sizeof (HTML_DISPLAY_LINES));
if (TmpHtmlData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
*HtmlDisplayData = TmpHtmlData;
} else {
TmpHtmlData = *HtmlDisplayData;
}
if (TmpHtmlData->AllocatedCnt == 0) {
TmpHtmlData->Lines = AllocateZeroPool (sizeof (CHAR8 *) * LinesCntStep);
} else {
TmpHtmlData->Lines = ReallocatePool (
sizeof (CHAR8 *) * (TmpHtmlData->AllocatedCnt),
sizeof (CHAR8 *) * (TmpHtmlData->AllocatedCnt + LinesCntStep),
TmpHtmlData->Lines
);
}
if (TmpHtmlData->Lines == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
TmpHtmlData->AllocatedCnt += LinesCntStep;
EXIT:
if (EFI_ERROR (Status)) {
HtmlParserDestroy (TmpHtmlData);
}
return Status;
}
EFI_STATUS
HtmlParserAddLine (
IN OUT HTML_DISPLAY_LINES *HtmlDisplayData,
IN CHAR8 *Line
)
{
HtmlDisplayData->Lines[HtmlDisplayData->LinesCnt] = Line;
HtmlDisplayData->LinesCnt++;
if (HtmlDisplayData->LinesCnt == HtmlDisplayData->AllocatedCnt) {
return HtmlParserInitialize (&mHtmlDisplayData, TRUE);
}
return EFI_SUCCESS;
}
VOID
DisplayHtml (
HTML_DISPLAY_LINES *HtmlDataCache,
UINTN TextWindowRows,
UINTN StartLine
)
{
UINTN Index;
for (Index = StartLine; Index < HtmlDataCache->LinesCnt; Index++) {
AsciiPrint ("%a\n", HtmlDataCache->Lines[Index]);
TextWindowRows--;
if (TextWindowRows == 0) {
break;
}
}
return;
}
VOID
DisplayHelp (
INT32 Col,
INT32 Row,
UINTN StartLine,
UINTN TextWindowsRows
)
{
gST->ConOut->SetCursorPosition (gST->ConOut, Col, Row);
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_YELLOW, EFI_BLUE));
AsciiPrint ("[PGUP][PGDOWN] Scroll text window [ESC] Exit chat room [ENTRY] Send/Refreash message%*a", MaxColumns - gST->ConOut->Mode->CursorColumn, "");
gST->ConOut->SetCursorPosition (gST->ConOut, MaxColumns - 12, Row);
AsciiPrint ("%3d-%3d:%4d", StartLine, StartLine + TextWindowsRows, mHtmlDisplayData->LinesCnt);
}
/// This function for demo, only parsing one of table column.
CHAR8 *
RestParsingHtmlTable (
IN HTML_DISPLAY_LINES *HtmlParser,
IN CHAR8 *HtmlContent,
IN UINTN HtmlLength
)
{
EFI_STATUS Status;
BOOLEAN Parsing;
CHAR8 *NextString;
CHAR8 *ContentPtr;
UINTN RemainingLength;
BOOLEAN InTag;
BOOLEAN IsFinishTag;
BOOLEAN IsData;
UINT8 SectionStack[100];
UINTN StackPtr;
CHAR8 *DataString;
CHAR8 *TagStartPosition;
HTML_STACK TagType;
Parsing = TRUE;
InTag = TRUE;
IsData = FALSE;
IsFinishTag = FALSE;
DataString = NULL;
TagStartPosition = NULL;
ZeroMem (SectionStack, sizeof (UINT8) * 100);
StackPtr = 0;
TagType = HtmlStackNull;
ContentPtr = HtmlContent;
RemainingLength = HtmlLength;
Status = EFI_SUCCESS;
while (Parsing) {
if (AsciiStrnCmp ((ContentPtr), HTML_TABLE, AsciiStrLen (HTML_TABLE)) == 0) {
TagType = HtmlTable;
} else if (AsciiStrnCmp ((ContentPtr), HTML_TABLE_TR, AsciiStrLen (HTML_TABLE_TR)) == 0) {
TagType = HtmlTableTr;
} else if (AsciiStrnCmp ((ContentPtr), HTML_TABLE_TD, AsciiStrLen (HTML_TABLE_TD)) == 0) {
TagType = HtmlTableTd;
}
NextString = AsciiStrnSplit (ContentPtr, HtmlLength, "<>/");
HtmlLength -= (UINTN)(NextString - ContentPtr);
ContentPtr = NextString;
if (*NextString == '<') {
InTag = TRUE;
TagStartPosition = ContentPtr;
ContentPtr++;
} else if (*NextString == '>') {
if (IsFinishTag) {
if (TagType == SectionStack[StackPtr-1]) {
StackPtr--;
SectionStack[StackPtr] = 0;
}
if (TagType == HtmlTableTd) {
*TagStartPosition = 0;
Status = HtmlParserAddLine (HtmlParser, DataString);
} else if (TagType == HtmlTable) {
break;
}
IsData = FALSE;
IsFinishTag = FALSE;
} else {
SectionStack[StackPtr] = TagType;
StackPtr++;
if (TagType == HtmlTableTr) {
/// New line
} else if (TagType == HtmlTableTd) {
IsData = TRUE;
DataString = ContentPtr + 1;
}
}
InTag = FALSE;
ContentPtr++;
}
if (InTag) {
if (*NextString == '/') {
IsFinishTag = TRUE;
ContentPtr++;
}
}
}
return ContentPtr+1;
}
EFI_STATUS
ParsingHtml (
UINT8 *Content,
UINTN ContentLength
)
{
EFI_STATUS Status;
UINTN Index;
BOOLEAN InHtml;
BOOLEAN InHeader;
BOOLEAN InBody;
BOOLEAN InPre;
BOOLEAN InTable;
BOOLEAN InTag;
BOOLEAN IsFinishTag;
CHAR8 **TempContentLines;
UINTN TempContentCnt;
CHAR8 *NextString;
Status = HtmlParserInitialize (&mHtmlDisplayData, FALSE);
if (EFI_ERROR (Status)) {
return Status;
}
InHtml = FALSE;
InHeader = FALSE;
InBody = FALSE;
InPre = FALSE;
InTag = FALSE;
IsFinishTag = FALSE;
TempContentCnt = 0;
TempContentLines = NULL;
for (Index = 0; Index < ContentLength; Index++) {
if (AsciiStrnCmp ((Content + Index), HTML_HTML, AsciiStrLen (HTML_HTML)) == 0) {
if (InTag) {
if (IsFinishTag) {
InHtml = FALSE;
} else {
InHtml = TRUE;
}
}
Index += AsciiStrLen (HTML_HTML);
} else if (AsciiStrnCmp ((Content + Index), HTML_HEADER, AsciiStrLen (HTML_HEADER)) == 0) {
if (InTag) {
if (IsFinishTag) {
InHeader = FALSE;
} else {
InHeader = TRUE;
}
}
Index += AsciiStrLen (HTML_HEADER);
} else if (AsciiStrnCmp ((Content + Index), HTML_BODY, AsciiStrLen (HTML_BODY)) == 0) {
if (InTag) {
if (IsFinishTag) {
InBody = FALSE;
} else {
InBody = TRUE;
}
}
Index += AsciiStrLen (HTML_BODY);
} else if (AsciiStrnCmp ((Content + Index), HTML_PRE, AsciiStrLen (HTML_PRE)) == 0) {
if (InTag) {
if (IsFinishTag) {
InPre = FALSE;
} else {
InPre = TRUE;
}
}
Index += AsciiStrLen (HTML_BODY);
} else if (AsciiStrnCmp ((Content + Index), HTML_TABLE, AsciiStrLen (HTML_TABLE)) == 0) {
if (InTag) {
if (IsFinishTag) {
InTable = FALSE;
} else {
/// ptr will be pointer to "table ..... >"
InTable = TRUE;
NextString = RestParsingHtmlTable (mHtmlDisplayData, Content + Index, ContentLength - Index);
Index = NextString - Content;
}
}
}
switch (Content[Index]) {
case HTML_TAG_START:
InTag = TRUE;
IsFinishTag = FALSE;
break;
case HTML_TAG_END:
InTag = FALSE;
IsFinishTag = FALSE;
break;
case HTML_SECTION_END:
IsFinishTag = TRUE;
break;
case 0x0a:
case 0x0d:
if (InBody && InPre) {
AsciiPrint ("\n");
}
break;
default:
if (InBody) {
if (InPre) {
NextString = AsciiStrnSplit (Content + Index, ContentLength - Index, "\r\n<");
Index = NextString - (Content + Index);
}
}
}
}
return EFI_SUCCESS;
}
EFI_STATUS
ReadString (
IN INT32 InputTextColumnPosX,
IN INT32 InputTextColumnPosY,
IN CHAR16 *HintString,
IN UINTN StringBufLen,
OUT CHAR8 *StringPtr,
OUT UINTN *StringLen
)
{
EFI_STATUS Status;
EFI_INPUT_KEY Key;
UINTN Offset;
BOOLEAN IsGettingString;
UINTN HintStringLen;
HintStringLen = StrLen (HintString) + 3;
gST->ConOut->SetCursorPosition (gST->ConOut, InputTextColumnPosX, InputTextColumnPosY);
AsciiPrint ("%s : %*a", HintString, MaxColumns - HintStringLen - 1, "");
Offset = 0;
IsGettingString = TRUE;
Status = EFI_NOT_READY;
while(IsGettingString) {
gST->ConOut->SetCursorPosition (gST->ConOut, InputTextColumnPosX + HintStringLen + AsciiStrLen (StringPtr), InputTextColumnPosY);
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if (EFI_ERROR(Status)) {
if (Status == EFI_NOT_READY) {
continue;
} else {
break;
}
}
if (Key.ScanCode == 0x00) {
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
Status = EFI_SUCCESS;
IsGettingString = FALSE;
break;
}
switch (Key.UnicodeChar) {
case CHAR_BACKSPACE:
if (Offset != 0) {
Offset -= 1;
StringPtr[Offset] = 0;
}
break;
default:
if (Offset < (StringBufLen - 1)) {
StringPtr[Offset] = (CHAR8) Key.UnicodeChar;
Offset += 1;
StringPtr[Offset] = 0;
}
}
} else if (Key.ScanCode == SCAN_ESC) {
IsGettingString = FALSE;
Status = EFI_NOT_READY;
continue;
} else if (Key.ScanCode == SCAN_PAGE_UP) {
IsGettingString = FALSE;
Status = REST_TEST_PAGE_UP;
} else if (Key.ScanCode == SCAN_PAGE_DOWN) {
IsGettingString = FALSE;
Status = REST_TEST_PAGE_DOWN;
}
gST->ConOut->SetCursorPosition (gST->ConOut, InputTextColumnPosX, InputTextColumnPosY);
AsciiPrint ("%s : %a", HintString, StringPtr);
AsciiPrint ("%*a", MaxColumns - HintStringLen - AsciiStrLen (StringPtr) - 1, "");
}
if (Offset != 0) {
*StringLen = Offset;
}
return Status;
}
EFI_STATUS
RestEtagToIndex (
IN CHAR16 *URL,
IN CHAR8 *AsciiURL,
IN OUT CHAR8 *Etag,
OUT UINTN *Index OPTIONAL
)
{
EFI_STATUS Status;
UINTN InternalIndex;
//
// Compare Etag with cache.
//
Status = EFI_NOT_FOUND;
for (InternalIndex = 0; InternalIndex < HttpCacheTagsCnt; Index++) {
if (AsciiURL != NULL) {
if (AsciiStrCmp (HttpCacheTags[InternalIndex].AsciiURL, AsciiURL) != 0) {
continue;
}
} else if (URL != NULL) {
if (StrCmp (HttpCacheTags[InternalIndex].URL, URL) != 0) {
continue;
}
}
if (AsciiStrCmp (HttpCacheTags[InternalIndex].Etag, Etag) == 0) {
/// Found
Status = EFI_SUCCESS;
break;
}
/// Content update
Status = EFI_MEDIA_CHANGED;
break;
}
if (Status != EFI_NOT_FOUND) {
if (Index != NULL) {
*Index = InternalIndex;
}
}
return Status;
}
EFI_STATUS
RestStoreCacheByEtag (
IN CHAR16 *URL OPTIONAL,
IN CHAR8 *AsciiURL OPTIONAL,
IN EFI_HTTP_HEADER *Headers,
IN UINTN HeaderCnt,
IN UINT8 *Content,
IN UINTN ContentLength
)
{
EFI_STATUS Status;
UINTN Index;
CHAR8 *Etag;
//
// Find Etag from HTTP headers.
//
Status = EFI_NOT_FOUND;
Etag = NULL;
for (Index = 0; Index < HeaderCnt; Index++) {
if (AsciiStrCmp (Headers[Index].FieldName, HTTP_CACHE_INDEX) != 0) {
continue;
}
Etag = Headers[Index].FieldValue;
}
Status = RestEtagToIndex (URL, AsciiURL, Etag, &Index);
if (Status == EFI_MEDIA_CHANGED) {
FreePool (HttpCacheTags[Index].Etag);
FreePool (HttpCacheTags[Index].Content);
FreePool (HttpCacheTags[Index].Headers);
HttpCacheTags[Index].Etag = Etag;
HttpCacheTags[Index].Content = Content;
HttpCacheTags[Index].ContentLength = ContentLength;
HttpCacheTags[Index].Headers = Headers;
HttpCacheTags[Index].HeaderCnt = HeaderCnt;
} else if (Status == EFI_NOT_FOUND) {
HttpCacheTags = ReallocatePool (
sizeof (REST_HTTP_CACHE) * HttpCacheTagsCnt,
sizeof (REST_HTTP_CACHE) * (HttpCacheTagsCnt + 1),
HttpCacheTags
);
if (HttpCacheTags == NULL) {
Status = EFI_OUT_OF_RESOURCES;
return Status;
}
HttpCacheTags[HttpCacheTagsCnt].AsciiURL = AsciiURL;
HttpCacheTags[HttpCacheTagsCnt].URL = URL;
HttpCacheTags[HttpCacheTagsCnt].Etag = Etag;
HttpCacheTags[HttpCacheTagsCnt].Content = Content;
HttpCacheTags[HttpCacheTagsCnt].ContentLength = ContentLength;
HttpCacheTags[HttpCacheTagsCnt].Headers = Headers;
HttpCacheTags[HttpCacheTagsCnt].HeaderCnt = HeaderCnt;
HttpCacheTagsCnt++;
Status = EFI_SUCCESS;
}
return Status;
}
/// Get HTTP header to compare Etag
EFI_STATUS
RestCheckCacheByEtag (
EFI_REST_PROTOCOL *Rest,
UINT16 *URL,
CHAR8 *Etag,
UINTN CacheIndex
)
{
EFI_STATUS Status;
EFI_HTTP_MESSAGE HttpRequest;
EFI_HTTP_MESSAGE HttpResponse;
EFI_HTTP_REQUEST_DATA RequestData;
EFI_HTTP_RESPONSE_DATA ResponseData;
EFI_HTTP_HEADER RequestHeader[1];
//
// Prepare HTTP request data.
//
RequestData.Method = HttpMethodGet;
RequestData.Url = URL;
RequestHeader[0].FieldName = HTTP_TRY_CACHE;
RequestHeader[0].FieldValue = Etag;
HttpRequest.Data.Request = &RequestData;
HttpRequest.HeaderCount = 1;
HttpRequest.Headers = RequestHeader;
HttpRequest.BodyLength = 0;
HttpRequest.Body = 0;
//
// Prepare HTTP response data.
//
ZeroMem (&HttpResponse, sizeof (EFI_HTTP_MESSAGE));
HttpResponse.Data.Response = &ResponseData;
Status = Rest->SendReceive (
Rest,
&HttpRequest,
&HttpResponse
);
if (HttpResponse.Data.Response->StatusCode == HTTP_STATUS_200_OK) {
//
// Update data to cache.
//
Status = RestStoreCacheByEtag (URL, NULL, HttpResponse.Headers, HttpResponse.HeaderCount, HttpResponse.Body, HttpResponse.BodyLength);
} else if (HttpResponse.Data.Response->StatusCode == HTTP_STATUS_304_NOT_MODIFIED) {
//
// Keep using data from cache.
//
Status = EFI_SUCCESS;
}
return Status;
}
/// Using WebkitFormBoundary
EFI_STATUS
RestPostFile (
EFI_REST_PROTOCOL *Rest,
UINT16 *URL,
CHAR16 *FileName,
UINTN FileLength,
UINT8 *FileContent
)
{
EFI_STATUS Status;
EFI_HTTP_MESSAGE HttpRequest;
EFI_HTTP_MESSAGE HttpResponse;
EFI_HTTP_REQUEST_DATA RequestData;
EFI_HTTP_RESPONSE_DATA ResponseData;
CHAR8 BodyLength[100];
CHAR8 *AsciiFileName;
EFI_HTTP_HEADER RequestHeaders[2];
UINTN PostContentLen;
UINT8 *PostContent;
UINT8 *HeaderPtr;
AsciiFileName = AllocateZeroPool (sizeof (CHAR8) * (StrLen (FileName) + 1));
if (AsciiFileName == NULL) {
return EFI_OUT_OF_RESOURCES;
}
UnicodeStrToAsciiStrS (FileName, AsciiFileName, sizeof (AsciiFileName));
//
// Prepare HTTP request data.
//
RequestData.Method = HttpMethodPost;
RequestData.Url = URL;
//
// Parsing POST data
//
PostContentLen = 0;
PostContentLen += AsciiStrLen (HTTP_END_BOUNDARY); // start with --
PostContentLen += AsciiStrLen (HTTP_DEFAULT_BOUNDARY); // boundary
PostContentLen += 2; // 0a0d
PostContentLen += AsciiStrLen (HTTP_POST_CONTENT_DISPOSITION);
PostContentLen += AsciiStrLen (AsciiFileName);
PostContentLen += 1; // "
PostContentLen += 2; // 0a0d
PostContentLen += AsciiStrLen (HTTP_POST_CONTENT_TYPE);
PostContentLen += 2; // 0a0d
PostContentLen += 2; // 0a0d
/// File Start
PostContentLen += FileLength;
/// File End
PostContentLen += 2; // 0a0d
PostContentLen += AsciiStrLen (HTTP_END_BOUNDARY);
PostContentLen += AsciiStrLen (HTTP_DEFAULT_BOUNDARY);
PostContentLen += AsciiStrLen (HTTP_END_BOUNDARY);
PostContentLen += 2; // 0a0d
PostContent = AllocateZeroPool (PostContentLen);
if (PostContent == NULL) {
return EFI_OUT_OF_RESOURCES;
}
HeaderPtr = PostContent;
//
// Fill POST data
//
PostContent = AsciiStrCatS (PostContent, PostContentLen, HTTP_END_BOUNDARY); // start with --
PostContent += AsciiStrLen (HTTP_END_BOUNDARY);
PostContent = AsciiStrCatS (PostContent, PostContentLen, HTTP_DEFAULT_BOUNDARY);
PostContent += AsciiStrLen (HTTP_DEFAULT_BOUNDARY);
PostContent[0] = 0x0d;
PostContent[1] = 0x0a;
PostContent += 2;
PostContent = AsciiStrCatS (PostContent, PostContentLen, HTTP_POST_CONTENT_DISPOSITION);
PostContent += AsciiStrLen (HTTP_POST_CONTENT_DISPOSITION);
PostContent = AsciiStrCatS (PostContent, PostContentLen, AsciiFileName);
PostContent += AsciiStrLen (AsciiFileName);
PostContent[0] = '\"';
PostContent[1] = 0x0d;
PostContent[2] = 0x0a;
PostContent += 3;
PostContent = AsciiStrCatS (PostContent, PostContentLen, HTTP_POST_CONTENT_TYPE);
PostContent += AsciiStrLen (HTTP_POST_CONTENT_TYPE);
PostContent[0] = 0x0d;
PostContent[1] = 0x0a;
PostContent += 2;
PostContent[0] = 0x0d;
PostContent[1] = 0x0a;
PostContent += 2;
/// File Start
CopyMem (PostContent, FileContent, FileLength);
PostContent += FileLength;
/// File End
PostContent[0] = 0x0d;
PostContent[1] = 0x0a;
PostContent += 2;
PostContent = AsciiStrCatS (PostContent, PostContentLen, HTTP_END_BOUNDARY);
PostContent += AsciiStrLen (HTTP_END_BOUNDARY);
PostContent = AsciiStrCatS (PostContent, PostContentLen, HTTP_DEFAULT_BOUNDARY);
PostContent += AsciiStrLen (HTTP_DEFAULT_BOUNDARY);
PostContent = AsciiStrCatS (PostContent, PostContentLen, HTTP_END_BOUNDARY);
PostContent += AsciiStrLen (HTTP_END_BOUNDARY);
PostContent[0] = 0x0d;
PostContent[1] = 0x0a;
PostContent += 2;
PostContent = HeaderPtr;
AsciiValueToString (BodyLength, 0, (INT64) PostContentLen, 20);
RequestHeaders[0].FieldName = HTTP_HEADER_CONTENT_LENGTH;
RequestHeaders[0].FieldValue = BodyLength;
RequestHeaders[1].FieldName = HTTP_HEADER_CONTENT_TYPE;
RequestHeaders[1].FieldValue = HTTP_CONTENT_TYPE_FILE HTTP_DEFAULT_BOUNDARY;
HttpRequest.Data.Request = &RequestData;
HttpRequest.HeaderCount = 2;
HttpRequest.Headers = RequestHeaders;
HttpRequest.BodyLength = PostContentLen;
HttpRequest.Body = PostContent;
ZeroMem (&HttpResponse, sizeof (EFI_HTTP_MESSAGE));
HttpResponse.Data.Response = &ResponseData;
Status = Rest->SendReceive (
Rest,
&HttpRequest,
&HttpResponse
);
if (HeaderPtr != NULL) {
FreePool (HeaderPtr);
}
if (AsciiFileName != NULL) {
FreePool (AsciiFileName);
}
return Status;
}
EFI_STATUS
RestPostString (
EFI_REST_PROTOCOL *Rest,
UINT16 *URL,
EFI_HTTP_HEADER *PostData,
UINTN PostDataCnt
)
{
EFI_STATUS Status;
EFI_HTTP_MESSAGE HttpRequest;
EFI_HTTP_MESSAGE HttpResponse;
EFI_HTTP_REQUEST_DATA RequestData;
EFI_HTTP_RESPONSE_DATA ResponseData;
UINTN Index;
CHAR8 **PostStrings;
UINTN PostStringLen;
CHAR8 *PostString;
UINTN TotalPostStringLen;
CHAR8 BodyLength[100];
EFI_HTTP_HEADER RequestHeaders[2];
//
// Prepare HTTP request data.
//
RequestData.Method = HttpMethodPost;
RequestData.Url = URL;
//
// Parsing POST data
//
PostStringLen = 0;
TotalPostStringLen = 0;
PostString = NULL;
PostStrings = AllocateZeroPool (sizeof (CHAR8 *) * PostDataCnt);
if (PostStrings == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
for (Index = 0; Index < PostDataCnt; Index++) {
PostStringLen = AsciiStrLen (PostData[Index].FieldName);
PostStringLen += AsciiStrLen (PostData[Index].FieldValue);
PostString = AllocateZeroPool (PostStringLen + 1);
if (TotalPostStringLen != 0) {
// Add '&' length
TotalPostStringLen ++;
}
TotalPostStringLen += PostStringLen;
if (PostString == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
PostString = AsciiStrCatS (PostString, PostStringLen + 1, PostData[Index].FieldName);
PostString = AsciiStrCatS (PostString, PostStringLen + 1, PostData[Index].FieldValue);
PostStrings[Index] = PostString;
}
PostString = AllocateZeroPool (TotalPostStringLen + 1);
if (PostString == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
for (Index = 0; Index < PostDataCnt; Index++) {
if (Index != 0) {
PostString = AsciiStrCatS (PostString, TotalPostStringLen + 1, "&");
}
PostString = AsciiStrCatS (PostString, TotalPostStringLen + 1, PostStrings[Index]);
}
AsciiValueToString (BodyLength, 0, (INT64) TotalPostStringLen, 20);
RequestHeaders[0].FieldName = HTTP_HEADER_CONTENT_LENGTH;
RequestHeaders[0].FieldValue = BodyLength;
RequestHeaders[1].FieldName = HTTP_HEADER_CONTENT_TYPE;
RequestHeaders[1].FieldValue = HTTP_CONTENT_TYPE_POST;
HttpRequest.Data.Request = &RequestData;
HttpRequest.HeaderCount = 2;
HttpRequest.Headers = RequestHeaders;
HttpRequest.BodyLength = TotalPostStringLen;
HttpRequest.Body = PostString;
ZeroMem (&HttpResponse, sizeof (EFI_HTTP_MESSAGE));
HttpResponse.Data.Response = &ResponseData;
Status = Rest->SendReceive (
Rest,
&HttpRequest,
&HttpResponse
);
EXIT:
if (PostString != NULL) {
FreePool (PostString);
}
if (PostStrings != NULL) {
for (Index = 0; Index < PostDataCnt; Index++) {
FreePool (PostStrings[Index]);
}
}
return Status;
}
#define INPUT_PAGE_UP_DOWN_STEP 5
EFI_STATUS
RestChatRoom (
EFI_REST_PROTOCOL *Rest,
UINT16 *URL,
CHAR16 *Name
)
{
EFI_STATUS Status;
UINT8 *Content;
UINTN ContentLength;
EFI_HTTP_HEADER *Headers;
UINTN HeaderCnt;
CHAR8 *InputString;
UINTN StringLen;
UINTN TextWindowsRows;
EFI_HTTP_HEADER PostData[2];
INT32 OriginalAttributes;
UINTN StartLine;
BOOLEAN IsUpdateHttp;
CHAR8 *AsciiName;
//
// Clean screen and get max columns and rows.
//
gST->ConOut->ClearScreen (gST->ConOut);
OriginalAttributes = gST->ConOut->Mode->Attribute;
Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &MaxColumns, &MaxRows);
if (EFI_ERROR (Status)) {
MaxColumns = 25;
MaxRows = 80;
}
AsciiName = AllocateZeroPool (sizeof (CHAR8) * (StrLen (Name) + 1));
if (AsciiName == NULL) {
return EFI_OUT_OF_RESOURCES;
}
UnicodeStrToAsciiStrS (Name, AsciiName, sizeof (AsciiName));
PostData[0].FieldName = CHAT_ROOM_POST_STRING;
PostData[0].FieldValue = NULL;
PostData[1].FieldName = CHAT_ROOM_POST_NAME;
PostData[1].FieldValue = AsciiName;
if (mDebugMode) {
MaxRows -= 1;
}
InputTextLength = MaxColumns - StrLen (Name) - 4;
InputString = AllocateZeroPool (InputTextLength);
if (InputString == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// HTTP cache initialize
//
HeaderCnt = 0;
Headers = NULL;
ContentLength = 0;
Content = NULL;
StartLine = 0;
IsUpdateHttp = TRUE;
mHtmlDisplayData = NULL;
ZeroMem (InputString, InputTextLength);
while (TRUE) {
if (IsUpdateHttp) {
IsUpdateHttp = FALSE;
Content = NULL;
ContentLength = 0;
Status = RestGetFile (Rest, URL, &HeaderCnt, &Headers, &ContentLength, &Content);
if (EFI_ERROR (Status)) {
if (Status != EFI_MEDIA_CHANGED) {
return Status;
}
}
}
gST->ConOut->ClearScreen (gST->ConOut);
gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
if (mDebugMode) {
DisplayHttpHeaders (Headers, HeaderCnt);
}
TextWindowsRows = MaxRows - gST->ConOut->Mode->CursorRow - 2;
if (((mHtmlDisplayData == NULL) && (Status == EFI_SUCCESS)) || (Status == EFI_MEDIA_CHANGED)){
if (Status == EFI_MEDIA_CHANGED) {
/// Clean cache
HtmlParserDestroy (mHtmlDisplayData);
mHtmlDisplayData = NULL;
}
Status = ParsingHtml (Content, ContentLength);
if (mHtmlDisplayData->LinesCnt > TextWindowsRows) {
StartLine = mHtmlDisplayData->LinesCnt - TextWindowsRows;
}
}
DisplayHtml (mHtmlDisplayData, TextWindowsRows, StartLine);
DisplayHelp (0, (INT32) MaxRows - 2, StartLine, TextWindowsRows);
StringLen = 0;
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_WHITE, EFI_BLUE));
Status = ReadString (0, (INT32) MaxRows - 1, Name, InputTextLength, InputString, &StringLen);
gST->ConOut->SetAttribute (gST->ConOut, OriginalAttributes);
//
// Scroll
//
if (Status == REST_TEST_PAGE_DOWN) {
if (mHtmlDisplayData->LinesCnt > (StartLine + TextWindowsRows + INPUT_PAGE_UP_DOWN_STEP)) {
StartLine += INPUT_PAGE_UP_DOWN_STEP;
} else if (mHtmlDisplayData->LinesCnt < TextWindowsRows) {
StartLine = 0;
} else {
StartLine = mHtmlDisplayData->LinesCnt - TextWindowsRows;
}
continue;
} else if (Status == REST_TEST_PAGE_UP) {
if (StartLine < INPUT_PAGE_UP_DOWN_STEP) {
StartLine = 0;
} else {
StartLine -= INPUT_PAGE_UP_DOWN_STEP;
}
continue;
}
if (EFI_ERROR (Status)) {
break;
}
IsUpdateHttp = TRUE;
if (StringLen == 0) {
continue;
}
PostData[0].FieldValue = InputString;
Status = RestPostString (Rest, URL, PostData, 2);
ZeroMem (InputString, InputTextLength);
// ShellPrintEx (MaxColumns, 0, L"%s", InputString);
}
gST->ConOut->ClearScreen (gST->ConOut);
gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
return Status;
}
EFI_STATUS
RestGetFile (
EFI_REST_PROTOCOL *Rest,
UINT16 *URL,
UINTN *HeaderLen,
EFI_HTTP_HEADER **Headers,
UINTN *ContentLength,
VOID **Content
)
{
EFI_STATUS Status;
EFI_HTTP_MESSAGE HttpRequest;
EFI_HTTP_MESSAGE HttpResponse;
EFI_HTTP_RESPONSE_DATA ResponseData;
EFI_HTTP_REQUEST_DATA RequestData;
UINTN Index;
CHAR8 *AsciiURL;
CHAR8 *Etag;
AsciiURL = AllocateZeroPool (sizeof (CHAR8) * (StrLen (URL) + 1));
if (AsciiURL == NULL) {
return EFI_OUT_OF_RESOURCES;
}
UnicodeStrToAsciiStrS (URL, AsciiURL, sizeof (AsciiURL));
Etag = NULL;
for (Index = 0; Index < HttpCacheTagsCnt; Index++) {
if (AsciiStrCmp (AsciiURL, HttpCacheTags[Index].AsciiURL) != 0) {
continue;
}
Etag = HttpCacheTags[Index].Etag;
break;
}
if (Etag != NULL) {
Status = RestCheckCacheByEtag (Rest, URL, Etag, Index);
if (!EFI_ERROR (Status) || Status == EFI_MEDIA_CHANGED) {
*ContentLength = HttpCacheTags[Index].ContentLength;
*Content = HttpCacheTags[Index].Content;
*HeaderLen = HttpCacheTags[Index].HeaderCnt;
*Headers = HttpCacheTags[Index].Headers;
/// AsciiURL has already saved in cache
FreePool (AsciiURL);
return Status;
}
}
//
// Prepare HTTP request data.
//
RequestData.Method = HttpMethodGet;
RequestData.Url = URL;
HttpRequest.Data.Request = &RequestData;
HttpRequest.HeaderCount = 0;
HttpRequest.Headers = NULL;
HttpRequest.BodyLength = 0;
HttpRequest.Body = 0;
ZeroMem (&HttpResponse, sizeof (EFI_HTTP_MESSAGE));
ResponseData.StatusCode = HTTP_STATUS_400_BAD_REQUEST;
HttpResponse.Data.Response = &ResponseData;
Status = Rest->SendReceive (
Rest,
&HttpRequest,
&HttpResponse
);
if (!EFI_ERROR (Status)) {
*ContentLength = HttpResponse.BodyLength;
*Content = HttpResponse.Body;
*HeaderLen = HttpResponse.HeaderCount;
*Headers = HttpResponse.Headers;
Status = RestStoreCacheByEtag (URL, AsciiURL, *Headers, *HeaderLen, *Content, *ContentLength);
} else {
AsciiPrint ("%a\n", HttpErrorString[HttpResponse.Data.Response->StatusCode]);
for (Index = 0; Index < HttpResponse.HeaderCount; Index++) {
AsciiPrint (" %a : %a\n", HttpResponse.Headers[Index].FieldName, HttpResponse.Headers[Index].FieldValue);
}
}
return Status;
}
EFI_STATUS
RestTestSetRestPolicy (
IN BOOLEAN IsIpv6
)
{
VOID *IsIPv6Ptr;
IsIPv6Ptr = PcdGetExPtr (&gInsydeTokenSpaceGuid, PcdH2ORestIPv6DnsPolicy);
if (IsIPv6Ptr == NULL) {
return EFI_NOT_FOUND;
}
PcdSetExBoolS (&gInsydeTokenSpaceGuid, PcdH2ORestIPv6DnsPolicy, IsIpv6);
return EFI_SUCCESS;
}
/**
The application entry point
@param[in] ImageHandle Common header of ImageHandle
@param[in] SystemTable Common header of SystemTable
@retval EFI_SUCCESS Application process success
@retval other Wrong status.
**/
EFI_STATUS
EFIAPI
RestTestEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_REST_PROTOCOL *Rest;
LIST_ENTRY *ParamPackage;
CHAR16 *ValueStr;
CHAR16 *Name;
CHAR16 *FileName;
EFI_HANDLE *RestHandles;
UINTN RestHandlesCnt;
UINTN DeviceId;
VOID *TestProtocol;
BOOLEAN IsIPv6;
// UINTN DeviceList[16];
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleNetworkProtocolGuid,
NULL,
&RestHandlesCnt,
&RestHandles
);
if (EFI_ERROR (Status)) {
Print (L"REST protocol not ready\n");
return Status;
}
Name = NULL;
FileName = NULL;
ShellInitialize ();
ParamPackage = NULL;
Status = ShellCommandLineParseEx (mNetworkCheckList, &ParamPackage, NULL, TRUE, FALSE);
if (EFI_ERROR (Status)) {
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
HttpCacheTags = NULL;
HttpCacheTagsCnt = 0;
mDebugMode = ShellCommandLineGetFlag (ParamPackage, L"--debug");
//
// select device by user
//
if (ShellCommandLineGetFlag (ParamPackage, L"--device")) {
ValueStr = (CHAR16 *) ShellCommandLineGetValue (ParamPackage, L"--device");
if (ValueStr == NULL) {
Status = EFI_INVALID_PARAMETER;
AsciiPrint (HELP_STRING);
goto ERROR;
}
DeviceId = StrDecimalToUintn (ValueStr);
if (DeviceId >= RestHandlesCnt) {
AsciiPrint (HELP_STRING);
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
Status = gBS->HandleProtocol (
*(RestHandles + DeviceId),
&gEfiRestProtocolGuid,
&Rest
);
if (EFI_ERROR (Status)) {
AsciiPrint (HELP_STRING);
goto ERROR;
}
Status = gBS->HandleProtocol (
*(RestHandles + DeviceId),
&gEfiDns4ServiceBindingProtocolGuid,
&TestProtocol
);
if (EFI_ERROR (Status)) {
Print (L"DNS IPv4 is not supported\n");
}
Status = gBS->HandleProtocol (
*(RestHandles + DeviceId),
&gEfiDns4ServiceBindingProtocolGuid,
&TestProtocol
);
if (EFI_ERROR (Status)) {
Print (L"DNS IPv6 is not supported\n");
}
} else {
Status = EFI_INVALID_PARAMETER;
AsciiPrint (HELP_STRING);
goto ERROR;
}
if (Rest == NULL) {
Status = EFI_INVALID_PARAMETER;
AsciiPrint (HELP_STRING);
goto ERROR;
}
//
// Setting REST policy, IPv4 or IPv6.
//
IsIPv6 = FALSE;
if (ShellCommandLineGetFlag (ParamPackage, L"--IPv6")) {
IsIPv6 = TRUE;
}
Status = RestTestSetRestPolicy (IsIPv6);
if (EFI_ERROR (Status)) {
AsciiPrint ("REST policy PCD is not found.\n");
IsIPv6 = FALSE;
}
AsciiPrint ("REST do HTTP %a\n", (IsIPv6) ? "IPv6" : "IPv4");
Name = NULL;
if (ShellCommandLineGetFlag (ParamPackage, L"--name")) {
Name = (CHAR16 *) ShellCommandLineGetValue (ParamPackage, L"--name");
if (Name == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
} else {
Name = L"CLIENT12345";
}
FileName = NULL;
if (ShellCommandLineGetFlag (ParamPackage, L"--file")) {
FileName = (CHAR16 *) ShellCommandLineGetValue (ParamPackage, L"--file");
if (FileName == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
}
if (ShellCommandLineGetFlag (ParamPackage, L"--chatroom")) {
ValueStr = (CHAR16 *) ShellCommandLineGetValue (ParamPackage, L"--chatroom");
if (ValueStr == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
Status = RestChatRoom (Rest, ValueStr, Name);
} else if (ShellCommandLineGetFlag (ParamPackage, L"--get")) {
UINT8 *Content;
UINTN ContentLength;
EFI_HTTP_HEADER *Headers;
UINTN HeadersCnt;
UINTN Index;
SHELL_FILE_HANDLE FileHandle;
// EFI_FILE_INFO *FileInfo;
ValueStr = (CHAR16 *) ShellCommandLineGetValue (ParamPackage, L"--get");
if (ValueStr == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
if (FileName == NULL) {
/// Try to get last filename from URL.
Status = FileFineNameFromURL (ValueStr, StrLen (ValueStr), &FileName);
if (EFI_ERROR (Status)) {
AsciiPrint ("Cannot identifier file name!!\n");
goto ERROR;
}
}
Status = RestGetFile (Rest, ValueStr, &HeadersCnt, &Headers, &ContentLength, &Content);
if (EFI_ERROR (Status)) {
AsciiPrint ("GET file failed %08x\n", Status);
goto ERROR;
}
AsciiPrint ("HeadersCnt : %d\n", HeadersCnt);
for (Index = 0; Index < HeadersCnt; Index++) {
AsciiPrint (" %a : %a\n", Headers[Index].FieldName, Headers[Index].FieldValue);
}
AsciiPrint ("ContentLength : %d\n", ContentLength);
AsciiPrint ("Content : %08x\n", Content);
FileHandle = NULL;
Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ + EFI_FILE_MODE_WRITE + EFI_FILE_MODE_CREATE, 0);
if (EFI_ERROR (Status)) {
AsciiPrint ("File open failed %08x", Status);
goto ERROR;
}
AsciiPrint ("Save to FILE NAME : %s\n", FileName);
Status = ShellWriteFile (FileHandle, &ContentLength, (VOID *)(UINTN) Content);
if (EFI_ERROR (Status)) {
AsciiPrint ("File open failed %08x", Status);
}
ShellCloseFile (&FileHandle);
AsciiPrint ("FILE write %d bytes\n", ContentLength);
} else if (ShellCommandLineGetFlag (ParamPackage, L"--upload")) {
UINT8 *Content;
UINTN ContentLength;
SHELL_FILE_HANDLE FileHandle;
EFI_FILE_INFO *FileInfo;
if (FileName == NULL) {
AsciiPrint ("Must input file name by --file [FileName]");
}
ValueStr = (CHAR16 *) ShellCommandLineGetValue (ParamPackage, L"--upload");
if (ValueStr == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
FileHandle = NULL;
Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR (Status)) {
AsciiPrint ("File open failed %08x", Status);
}
Content = NULL;
ContentLength = 0;
FileInfo = ShellGetFileInfo (FileHandle);
if (FileInfo == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ERROR;
}
ContentLength = (UINTN) FileInfo->FileSize;
Content = AllocateZeroPool (ContentLength);
if (Content == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ERROR;
}
Status = ShellReadFile (FileHandle, &ContentLength, Content);
if (EFI_ERROR (Status)) {
AsciiPrint ("File read failed %08x", Status);
}
FileName = SplitSlash (FileName);
ShellCloseFile (&FileHandle);
Status = RestPostFile (Rest, ValueStr, FileName, ContentLength, Content);
} else {
AsciiPrint (HELP_STRING);
}
if (EFI_ERROR (Status)) {
// Print (L"REST response error : %r\n", Status);
}
ERROR:
if (HttpCacheTags != NULL) {
UINTN Index;
for (Index = 0; Index < HttpCacheTagsCnt; Index++) {
if (HttpCacheTags[Index].URL != NULL) {
FreePool (HttpCacheTags[Index].URL);
}
if (HttpCacheTags[Index].Etag != NULL) {
FreePool (HttpCacheTags[Index].Etag);
}
if (HttpCacheTags[Index].Content != NULL) {
FreePool (HttpCacheTags[Index].Content);
}
}
FreePool (HttpCacheTags);
}
if (ParamPackage != NULL) {
gBS->FreePool (ParamPackage);
}
return Status;
}