[ipxe-devel] [PATCH 2/2 v2] [http] Support booting images larger than 2GB over http on 32-bit builds

Johannes Thoma johannes at johannesthoma.com
Mon Feb 11 16:15:08 UTC 2019


The start member of http_request_range has been widened to
64 bit.

The len parameter of the blktrans_xferbuf_realloc has been
widened (which records the length of the image) plus all
intermediate functions that lead to the call.

Tested with an 32GB Windows 7 64-bit image: it boots until
it fails to find the root device (which is expected)
---
 src/core/blocktrans.c         | 12 ++++++------
 src/core/xfer.c               |  4 ++--
 src/core/xferbuf.c            | 29 +++++++++++++++--------------
 src/include/ipxe/blocktrans.h |  2 +-
 src/include/ipxe/http.h       |  4 ++--
 src/include/ipxe/xfer.h       |  4 ++--
 src/include/ipxe/xferbuf.h    | 14 +++++++-------
 src/interface/efi/efi_pxe.c   |  4 ++--
 src/net/tcp/httpcore.c        |  6 +++---
 9 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/src/core/blocktrans.c b/src/core/blocktrans.c
index 3f32f9cf..880dd9e5 100644
--- a/src/core/blocktrans.c
+++ b/src/core/blocktrans.c
@@ -46,7 +46,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  * @ret rc		Return status code
  */
 static int blktrans_xferbuf_realloc ( struct xfer_buffer *xferbuf,
-				      size_t len ) {
+				      uint64_t len ) {
 	struct block_translator *blktrans =
 		container_of ( xferbuf, struct block_translator, xferbuf );
 
@@ -72,7 +72,7 @@ static int blktrans_xferbuf_realloc ( struct xfer_buffer *xferbuf,
  * @v data		Data to copy
  * @v len		Length of data
  */
-static void blktrans_xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
+static void blktrans_xferbuf_write ( struct xfer_buffer *xferbuf, uint64_t offset,
 				     const void *data, size_t len ) {
 	struct block_translator *blktrans =
 		container_of ( xferbuf, struct block_translator, xferbuf );
@@ -98,8 +98,8 @@ static void blktrans_xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
  * @v data		Data to read
  * @v len		Length of data
  */
-static void blktrans_xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset,
-				    void *data, size_t len ) {
+static void blktrans_xferbuf_read ( struct xfer_buffer *xferbuf,
+				    uint64_t offset, void *data, size_t len ) {
 	struct block_translator *blktrans =
 		container_of ( xferbuf, struct block_translator, xferbuf );
 
@@ -220,7 +220,7 @@ static struct interface_descriptor blktrans_xfer_desc =
  * @v size		Length of data buffer, or block size
  * @ret rc		Return status code
  */
-int block_translate ( struct interface *block, userptr_t buffer, size_t size ) {
+int block_translate ( struct interface *block, userptr_t buffer, uint64_t size ) {
 	struct block_translator *blktrans;
 	int rc;
 
@@ -249,7 +249,7 @@ int block_translate ( struct interface *block, userptr_t buffer, size_t size ) {
 
 	DBGC2 ( blktrans, "BLKTRANS %p created", blktrans );
 	if ( buffer ) {
-		DBGC2 ( blktrans, " for %#lx+%#zx",
+		DBGC2 ( blktrans, " for %#lx+%#llx",
 			user_to_phys ( buffer, 0 ), size );
 	}
 	DBGC2 ( blktrans, "\n" );
diff --git a/src/core/xfer.c b/src/core/xfer.c
index 0faf3292..765b5ed0 100644
--- a/src/core/xfer.c
+++ b/src/core/xfer.c
@@ -347,14 +347,14 @@ int xfer_printf ( struct interface *intf, const char *format, ... ) {
  * @v offset		Offset to new position
  * @ret rc		Return status code
  */
-int xfer_seek ( struct interface *intf, off_t offset ) {
+int xfer_seek ( struct interface *intf, int64_t offset ) {
 	struct io_buffer *iobuf;
 	struct xfer_metadata meta = {
 		.flags = XFER_FL_ABS_OFFSET,
 		.offset = offset,
 	};
 
-	DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " seek to %ld\n",
+	DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " seek to %lld\n",
 	       INTF_DBG ( intf ), offset );
 
 	/* Allocate and send a zero-length data buffer */
diff --git a/src/core/xferbuf.c b/src/core/xferbuf.c
index 24011855..cdd0f909 100644
--- a/src/core/xferbuf.c
+++ b/src/core/xferbuf.c
@@ -69,7 +69,7 @@ void xferbuf_free ( struct xfer_buffer *xferbuf ) {
  * @v len		Required minimum size
  * @ret rc		Return status code
  */
-static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) {
+static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, uint64_t len ) {
 	int rc;
 
 	/* If buffer is already large enough, do nothing */
@@ -79,7 +79,7 @@ static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) {
 	/* Extend buffer */
 	if ( ( rc = xferbuf->op->realloc ( xferbuf, len ) ) != 0 ) {
 		DBGC ( xferbuf, "XFERBUF %p could not extend buffer to "
-		       "%zd bytes: %s\n", xferbuf, len, strerror ( rc ) );
+		       "%lld bytes: %s\n", xferbuf, len, strerror ( rc ) );
 		return rc;
 	}
 	xferbuf->len = len;
@@ -95,9 +95,9 @@ static int xferbuf_ensure_size ( struct xfer_buffer *xferbuf, size_t len ) {
  * @v data		Data to write
  * @v len		Length of data
  */
-int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
+int xferbuf_write ( struct xfer_buffer *xferbuf, uint64_t offset,
 		    const void *data, size_t len ) {
-	size_t max_len;
+	uint64_t max_len;
 	int rc;
 
 	/* Check for overflow */
@@ -125,7 +125,7 @@ int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
  * @v data		Data to write
  * @v len		Length of data
  */
-int xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset,
+int xferbuf_read ( struct xfer_buffer *xferbuf, uint64_t offset,
 		   void *data, size_t len ) {
 
 	/* Check that read is within buffer range */
@@ -152,7 +152,7 @@ int xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset,
 int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf,
 		      struct xfer_metadata *meta ) {
 	size_t len = iob_len ( iobuf );
-	size_t pos;
+	uint64_t pos;
 	int rc;
 
 	/* Start profiling */
@@ -184,7 +184,7 @@ int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf,
  * @v len		New length (or zero to free buffer)
  * @ret rc		Return status code
  */
-static int xferbuf_malloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
+static int xferbuf_malloc_realloc ( struct xfer_buffer *xferbuf, uint64_t len ) {
 	void *new_data;
 
 	new_data = realloc ( xferbuf->data, len );
@@ -202,7 +202,7 @@ static int xferbuf_malloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
  * @v data		Data to copy
  * @v len		Length of data
  */
-static void xferbuf_malloc_write ( struct xfer_buffer *xferbuf, size_t offset,
+static void xferbuf_malloc_write ( struct xfer_buffer *xferbuf, uint64_t offset,
 				   const void *data, size_t len ) {
 
 	memcpy ( ( xferbuf->data + offset ), data, len );
@@ -216,7 +216,7 @@ static void xferbuf_malloc_write ( struct xfer_buffer *xferbuf, size_t offset,
  * @v data		Data to read
  * @v len		Length of data
  */
-static void xferbuf_malloc_read ( struct xfer_buffer *xferbuf, size_t offset,
+static void xferbuf_malloc_read ( struct xfer_buffer *xferbuf, uint64_t offset,
 				  void *data, size_t len ) {
 
 	memcpy ( data, ( xferbuf->data + offset ), len );
@@ -236,7 +236,7 @@ struct xfer_buffer_operations xferbuf_malloc_operations = {
  * @v len		New length (or zero to free buffer)
  * @ret rc		Return status code
  */
-static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
+static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, uint64_t len ) {
 	userptr_t *udata = xferbuf->data;
 	userptr_t new_udata;
 
@@ -255,8 +255,9 @@ static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) {
  * @v data		Data to copy
  * @v len		Length of data
  */
-static void xferbuf_umalloc_write ( struct xfer_buffer *xferbuf, size_t offset,
-				    const void *data, size_t len ) {
+static void xferbuf_umalloc_write ( struct xfer_buffer *xferbuf,
+				    uint64_t offset, const void *data,
+				    size_t len ) {
 	userptr_t *udata = xferbuf->data;
 
 	copy_to_user ( *udata, offset, data, len );
@@ -270,8 +271,8 @@ static void xferbuf_umalloc_write ( struct xfer_buffer *xferbuf, size_t offset,
  * @v data		Data to read
  * @v len		Length of data
  */
-static void xferbuf_umalloc_read ( struct xfer_buffer *xferbuf, size_t offset,
-				   void *data, size_t len ) {
+static void xferbuf_umalloc_read ( struct xfer_buffer *xferbuf,
+				   uint64_t offset, void *data, size_t len ) {
 	userptr_t *udata = xferbuf->data;
 
 	copy_from_user ( data, *udata, offset, len );
diff --git a/src/include/ipxe/blocktrans.h b/src/include/ipxe/blocktrans.h
index fee71b96..0c5682e9 100644
--- a/src/include/ipxe/blocktrans.h
+++ b/src/include/ipxe/blocktrans.h
@@ -33,6 +33,6 @@ struct block_translator {
 };
 
 extern int block_translate ( struct interface *block,
-			     userptr_t buffer, size_t size );
+			     userptr_t buffer, uint64_t size );
 
 #endif /* _IPXE_BLOCKTRANS_H */
diff --git a/src/include/ipxe/http.h b/src/include/ipxe/http.h
index 0893c953..6d479a6b 100644
--- a/src/include/ipxe/http.h
+++ b/src/include/ipxe/http.h
@@ -136,7 +136,7 @@ extern struct http_method http_post;
 /** HTTP request range descriptor */
 struct http_request_range {
 	/** Range start */
-	size_t start;
+	uint64_t start;
 	/** Range length, or zero for no range request */
 	size_t len;
 };
@@ -262,7 +262,7 @@ struct http_response_transfer {
 /** HTTP response content descriptor */
 struct http_response_content {
 	/** Content length (may be zero) */
-	size_t len;
+	uint64_t len;
 	/** Content encoding */
 	struct http_content_encoding *encoding;
 };
diff --git a/src/include/ipxe/xfer.h b/src/include/ipxe/xfer.h
index 3a35fa92..c8a64471 100644
--- a/src/include/ipxe/xfer.h
+++ b/src/include/ipxe/xfer.h
@@ -34,7 +34,7 @@ struct xfer_metadata {
 	 * relative offset of zero, i.e. no offset from the current
 	 * position.)
 	 */
-	off_t offset;
+	int64_t offset;
 	/** Source socket address, or NULL */
 	struct sockaddr *src;
 	/** Destination socket address, or NULL */
@@ -102,7 +102,7 @@ extern int xfer_vprintf ( struct interface *intf,
 			  const char *format, va_list args );
 extern int __attribute__ (( format ( printf, 2, 3 ) ))
 xfer_printf ( struct interface *intf, const char *format, ... );
-extern int xfer_seek ( struct interface *intf, off_t offset );
+extern int xfer_seek ( struct interface *intf, int64_t offset );
 extern int xfer_check_order ( struct xfer_metadata *meta, size_t *pos,
 			      size_t len );
 
diff --git a/src/include/ipxe/xferbuf.h b/src/include/ipxe/xferbuf.h
index cb0b1a0e..e5bf0133 100644
--- a/src/include/ipxe/xferbuf.h
+++ b/src/include/ipxe/xferbuf.h
@@ -20,9 +20,9 @@ struct xfer_buffer {
 	/** Data */
 	void *data;
 	/** Size of data */
-	size_t len;
+	uint64_t len;
 	/** Current offset within data */
-	size_t pos;
+	uint64_t pos;
 	/** Data transfer buffer operations */
 	struct xfer_buffer_operations *op;
 };
@@ -35,7 +35,7 @@ struct xfer_buffer_operations {
 	 * @v len		New length (or zero to free buffer)
 	 * @ret rc		Return status code
 	 */
-	int ( * realloc ) ( struct xfer_buffer *xferbuf, size_t len );
+	int ( * realloc ) ( struct xfer_buffer *xferbuf, uint64_t len );
 	/** Write data to buffer
 	 *
 	 * @v xferbuf		Data transfer buffer
@@ -47,7 +47,7 @@ struct xfer_buffer_operations {
 	 * memcpy()-like operation: the caller is responsible for
 	 * ensuring that the write does not exceed the buffer length.
 	 */
-	void ( * write ) ( struct xfer_buffer *xferbuf, size_t offset,
+	void ( * write ) ( struct xfer_buffer *xferbuf, uint64_t offset,
 			   const void *data, size_t len );
 	/** Read data from buffer
 	 *
@@ -60,7 +60,7 @@ struct xfer_buffer_operations {
 	 * memcpy()-like operation: the caller is responsible for
 	 * ensuring that the read does not exceed the buffer length.
 	 */
-	void ( * read ) ( struct xfer_buffer *xferbuf, size_t offset,
+	void ( * read ) ( struct xfer_buffer *xferbuf, uint64_t offset,
 			  void *data, size_t len );
 };
 
@@ -90,9 +90,9 @@ xferbuf_umalloc_init ( struct xfer_buffer *xferbuf, userptr_t *data ) {
 }
 
 extern void xferbuf_free ( struct xfer_buffer *xferbuf );
-extern int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
+extern int xferbuf_write ( struct xfer_buffer *xferbuf, uint64_t offset,
 			   const void *data, size_t len );
-extern int xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset,
+extern int xferbuf_read ( struct xfer_buffer *xferbuf, uint64_t offset,
 			  void *data, size_t len );
 extern int xferbuf_deliver ( struct xfer_buffer *xferbuf,
 			     struct io_buffer *iobuf,
diff --git a/src/interface/efi/efi_pxe.c b/src/interface/efi/efi_pxe.c
index a1f81df5..e7be1558 100644
--- a/src/interface/efi/efi_pxe.c
+++ b/src/interface/efi/efi_pxe.c
@@ -317,7 +317,7 @@ static int efi_pxe_ip_filter ( struct efi_pxe *pxe, EFI_IP_ADDRESS *ip ) {
  * @ret rc		Return status code
  */
 static int efi_pxe_buf_realloc ( struct xfer_buffer *xferbuf __unused,
-				 size_t len __unused ) {
+				 uint64_t len __unused ) {
 
 	/* Can never reallocate: return EFI_BUFFER_TOO_SMALL */
 	return -ERANGE;
@@ -331,7 +331,7 @@ static int efi_pxe_buf_realloc ( struct xfer_buffer *xferbuf __unused,
  * @v data		Data to copy
  * @v len		Length of data
  */
-static void efi_pxe_buf_write ( struct xfer_buffer *xferbuf, size_t offset,
+static void efi_pxe_buf_write ( struct xfer_buffer *xferbuf, uint64_t offset,
 				const void *data, size_t len ) {
 
 	/* Copy data to buffer */
diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c
index f755fb72..cbd507b5 100644
--- a/src/net/tcp/httpcore.c
+++ b/src/net/tcp/httpcore.c
@@ -591,7 +591,7 @@ int http_open ( struct interface *xfer, struct http_method *method,
 	struct uri request_host;
 	size_t request_uri_len;
 	size_t request_host_len;
-	size_t content_len;
+	uint64_t content_len;
 	char *request_uri_string;
 	char *request_host_string;
 	void *content_data;
@@ -936,7 +936,7 @@ static int http_format_range ( struct http_transaction *http,
 
 	/* Construct range, if applicable */
 	if ( http->request.range.len ) {
-		return snprintf ( buf, len, "bytes=%zd-%zd",
+		return snprintf ( buf, len, "bytes=%lld-%lld",
 				  http->request.range.start,
 				  ( http->request.range.start +
 				    http->request.range.len - 1 ) );
@@ -1345,7 +1345,7 @@ static int http_parse_content_length ( struct http_transaction *http,
 	char *endp;
 
 	/* Parse length */
-	http->response.content.len = strtoul ( line, &endp, 10 );
+	http->response.content.len = strtoull ( line, &endp, 10 );
 	if ( *endp != '\0' ) {
 		DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
 		       http, line );
-- 
2.17.0




More information about the ipxe-devel mailing list