return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Get the file content from cached data.\r
-\r
- @param[in] Private The pointer to the driver's private data.\r
- @param[in] Uri Uri of the file to be retrieved from cache.\r
- @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return\r
- code of EFI_SUCCESS, the amount of data transferred to\r
- Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,\r
- the size of Buffer required to retrieve the requested file.\r
- @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL,\r
- then the size of the requested file is returned in\r
- BufferSize.\r
-\r
- @retval EFI_SUCCESS Successfully created.\r
- @retval Others Failed to create HttpIo.\r
-\r
-**/\r
-EFI_STATUS\r
-HttpBootGetFileFromCache (\r
- IN HTTP_BOOT_PRIVATE_DATA *Private,\r
- IN CHAR16 *Uri,\r
- IN OUT UINTN *BufferSize,\r
- OUT UINT8 *Buffer\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- LIST_ENTRY *Entry2;\r
- HTTP_BOOT_CACHE_CONTENT *Cache;\r
- HTTP_BOOT_ENTITY_DATA *EntityData;\r
- UINTN CopyedSize;\r
- \r
- if (Uri == NULL || BufferSize == 0 || Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- NET_LIST_FOR_EACH (Entry, &Private->CacheList) {\r
- Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link);\r
- //\r
- // Compare the URI to see whether we already have a cache for this file.\r
- //\r
- if ((Cache->RequestData != NULL) &&\r
- (Cache->RequestData->Url != NULL) &&\r
- (StrCmp (Uri, Cache->RequestData->Url) == 0)) \r
- {\r
- //\r
- // Hit cache, check buffer size.\r
- //\r
- if (*BufferSize < Cache->EntityLength) {\r
- *BufferSize = Cache->EntityLength;\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- //\r
- // Fill data to buffer.\r
- //\r
- CopyedSize = 0;\r
- NET_LIST_FOR_EACH (Entry2, &Cache->EntityDataList) {\r
- EntityData = NET_LIST_USER_STRUCT (Entry2, HTTP_BOOT_ENTITY_DATA, Link);\r
- if (*BufferSize > CopyedSize) {\r
- CopyMem (\r
- Buffer + CopyedSize,\r
- EntityData->DataStart,\r
- MIN (EntityData->DataLength, *BufferSize - CopyedSize)\r
- );\r
- CopyedSize += MIN (EntityData->DataLength, *BufferSize - CopyedSize);\r
- }\r
- }\r
- *BufferSize = CopyedSize;\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
/**\r
Release all the resource of a cache item.\r
\r
}\r
}\r
\r
+/**\r
+ Get the file content from cached data.\r
+\r
+ @param[in] Private The pointer to the driver's private data.\r
+ @param[in] Uri Uri of the file to be retrieved from cache.\r
+ @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return\r
+ code of EFI_SUCCESS, the amount of data transferred to\r
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,\r
+ the size of Buffer required to retrieve the requested file.\r
+ @param[out] Buffer The memory buffer to transfer the file to. IF Buffer is NULL,\r
+ then the size of the requested file is returned in\r
+ BufferSize.\r
+\r
+ @retval EFI_SUCCESS Successfully created.\r
+ @retval Others Failed to create HttpIo.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootGetFileFromCache (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN CHAR16 *Uri,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT UINT8 *Buffer\r
+ )\r
+{\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Entry2;\r
+ HTTP_BOOT_CACHE_CONTENT *Cache;\r
+ HTTP_BOOT_ENTITY_DATA *EntityData;\r
+ UINTN CopyedSize;\r
+ \r
+ if (Uri == NULL || BufferSize == 0 || Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Search file in the cache list, the cache entry will be released upon a successful\r
+ // match.\r
+ //\r
+ NET_LIST_FOR_EACH (Entry, &Private->CacheList) {\r
+ Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link);\r
+ //\r
+ // Compare the URI to see whether we already have a cache for this file.\r
+ //\r
+ if ((Cache->RequestData != NULL) &&\r
+ (Cache->RequestData->Url != NULL) &&\r
+ (StrCmp (Uri, Cache->RequestData->Url) == 0)) \r
+ {\r
+ //\r
+ // Hit cache, check buffer size.\r
+ //\r
+ if (*BufferSize < Cache->EntityLength) {\r
+ *BufferSize = Cache->EntityLength;\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ //\r
+ // Fill data to buffer.\r
+ //\r
+ CopyedSize = 0;\r
+ NET_LIST_FOR_EACH (Entry2, &Cache->EntityDataList) {\r
+ EntityData = NET_LIST_USER_STRUCT (Entry2, HTTP_BOOT_ENTITY_DATA, Link);\r
+ if (*BufferSize > CopyedSize) {\r
+ CopyMem (\r
+ Buffer + CopyedSize,\r
+ EntityData->DataStart,\r
+ MIN (EntityData->DataLength, *BufferSize - CopyedSize)\r
+ );\r
+ CopyedSize += MIN (EntityData->DataLength, *BufferSize - CopyedSize);\r
+ }\r
+ }\r
+ *BufferSize = CopyedSize;\r
+\r
+ //\r
+ // On success, free the cached data to release the memory resource.\r
+ //\r
+ RemoveEntryList (&Cache->Link);\r
+ HttpBootFreeCache (Cache);\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
/**\r
A callback function to intercept events during message parser.\r
\r
HTTP_BOOT_CACHE_CONTENT *Cache;\r
UINT8 *Block;\r
CHAR16 *Url;\r
+ BOOLEAN IdentityMode;\r
+ UINTN ReceivedSize;\r
\r
ASSERT (Private != NULL);\r
ASSERT (Private->HttpCreated);\r
//\r
Block = NULL;\r
if (!HeaderOnly) {\r
+ //\r
+ // 3.4.1, check whether we are in identity transfer-coding.\r
+ //\r
+ ContentLength = 0;\r
+ Status = HttpGetEntityLength (Parser, &ContentLength);\r
+ if (!EFI_ERROR (Status)) {\r
+ IdentityMode = TRUE;\r
+ } else {\r
+ IdentityMode = FALSE;\r
+ }\r
+\r
+ //\r
+ // 3.4.2, start the message-body download, the identity and chunked transfer-coding\r
+ // is handled in different path here.\r
+ //\r
ZeroMem (&ResponseBody, sizeof (HTTP_IO_RESOPNSE_DATA));\r
- while (!HttpIsMessageComplete (Parser)) {\r
+ if (IdentityMode) {\r
//\r
- // Allocate a block to hold the message-body, if caller doesn't provide\r
- // a buffer, the block will be cached and we will allocate a new one here.\r
+ // In identity transfer-coding there is no need to parse the message body,\r
+ // just download the message body to the user provided buffer directly.\r
//\r
- if (Block == NULL || Context.BufferSize == 0) {\r
- Block = AllocatePool (HTTP_BOOT_BLOCK_SIZE);\r
- if (Block == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
+ ReceivedSize = 0;\r
+ while (ReceivedSize < ContentLength) {\r
+ ResponseBody.Body = (CHAR8*) Buffer + ReceivedSize;\r
+ ResponseBody.BodyLength = *BufferSize - ReceivedSize;\r
+ Status = HttpIoRecvResponse (\r
+ &Private->HttpIo,\r
+ FALSE,\r
+ &ResponseBody\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
goto ERROR_6;\r
}\r
- Context.NewBlock = TRUE;\r
- Context.Block = Block;\r
- } else {\r
- Context.NewBlock = FALSE;\r
- }\r
-\r
- ResponseBody.Body = (CHAR8*) Block;\r
- ResponseBody.BodyLength = HTTP_BOOT_BLOCK_SIZE;\r
- Status = HttpIoRecvResponse (\r
- &Private->HttpIo,\r
- FALSE,\r
- &ResponseBody\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ERROR_6;\r
+ ReceivedSize += ResponseBody.BodyLength;\r
}\r
-\r
+ } else {\r
//\r
- // Parse the new received block of the message-body, the block will be saved in cache.\r
+ // In "chunked" transfer-coding mode, so we need to parse the received\r
+ // data to get the real entity content.\r
//\r
- Status = HttpParseMessageBody (\r
- Parser,\r
- ResponseBody.BodyLength,\r
- ResponseBody.Body\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ERROR_6;\r
+ Block = NULL;\r
+ while (!HttpIsMessageComplete (Parser)) {\r
+ //\r
+ // Allocate a buffer in Block to hold the message-body.\r
+ // If caller provides a buffer, this Block will be reused in every HttpIoRecvResponse().\r
+ // Otherwise a buffer, the buffer in Block will be cached and we should allocate a new before\r
+ // every HttpIoRecvResponse().\r
+ //\r
+ if (Block == NULL || Context.BufferSize == 0) {\r
+ Block = AllocatePool (HTTP_BOOT_BLOCK_SIZE);\r
+ if (Block == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ERROR_6;\r
+ }\r
+ Context.NewBlock = TRUE;\r
+ Context.Block = Block;\r
+ } else {\r
+ Context.NewBlock = FALSE;\r
+ }\r
+\r
+ ResponseBody.Body = (CHAR8*) Block;\r
+ ResponseBody.BodyLength = HTTP_BOOT_BLOCK_SIZE;\r
+ Status = HttpIoRecvResponse (\r
+ &Private->HttpIo,\r
+ FALSE,\r
+ &ResponseBody\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_6;\r
+ }\r
+\r
+ //\r
+ // Parse the new received block of the message-body, the block will be saved in cache.\r
+ //\r
+ Status = HttpParseMessageBody (\r
+ Parser,\r
+ ResponseBody.BodyLength,\r
+ ResponseBody.Body\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_6;\r
+ }\r
}\r
}\r
}\r
- \r
+\r
//\r
- // 3.5 Message-body receive & parse is completed, get the file size.\r
+ // 3.5 Message-body receive & parse is completed, we should be able to get the file size now.\r
//\r
Status = HttpGetEntityLength (Parser, &ContentLength);\r
if (EFI_ERROR (Status)) {\r