iPXE
|
00001 #ifndef _IPXE_IOBUF_H 00002 #define _IPXE_IOBUF_H 00003 00004 /** @file 00005 * 00006 * I/O buffers 00007 * 00008 */ 00009 00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); 00011 00012 #include <stdint.h> 00013 #include <assert.h> 00014 #include <ipxe/list.h> 00015 00016 /** 00017 * Minimum I/O buffer length 00018 * 00019 * alloc_iob() will round up the allocated length to this size if 00020 * necessary. This is used on behalf of hardware that is not capable 00021 * of auto-padding. 00022 */ 00023 #define IOB_ZLEN 128 00024 00025 /** 00026 * A persistent I/O buffer 00027 * 00028 * This data structure encapsulates a long-lived I/O buffer. The 00029 * buffer may be passed between multiple owners, queued for possible 00030 * retransmission, etc. 00031 */ 00032 struct io_buffer { 00033 /** List of which this buffer is a member 00034 * 00035 * The list must belong to the current owner of the buffer. 00036 * Different owners may maintain different lists (e.g. a 00037 * retransmission list for TCP). 00038 */ 00039 struct list_head list; 00040 00041 /** Start of the buffer */ 00042 void *head; 00043 /** Start of data */ 00044 void *data; 00045 /** End of data */ 00046 void *tail; 00047 /** End of the buffer */ 00048 void *end; 00049 }; 00050 00051 /** 00052 * Reserve space at start of I/O buffer 00053 * 00054 * @v iobuf I/O buffer 00055 * @v len Length to reserve 00056 * @ret data Pointer to new start of buffer 00057 */ 00058 static inline void * iob_reserve ( struct io_buffer *iobuf, size_t len ) { 00059 iobuf->data += len; 00060 iobuf->tail += len; 00061 return iobuf->data; 00062 } 00063 #define iob_reserve( iobuf, len ) ( { \ 00064 void *__result; \ 00065 __result = iob_reserve ( (iobuf), (len) ); \ 00066 assert ( (iobuf)->tail <= (iobuf)->end ); \ 00067 __result; } ) 00068 00069 /** 00070 * Add data to start of I/O buffer 00071 * 00072 * @v iobuf I/O buffer 00073 * @v len Length to add 00074 * @ret data Pointer to new start of buffer 00075 */ 00076 static inline void * iob_push ( struct io_buffer *iobuf, size_t len ) { 00077 iobuf->data -= len; 00078 return iobuf->data; 00079 } 00080 #define iob_push( iobuf, len ) ( { \ 00081 void *__result; \ 00082 __result = iob_push ( (iobuf), (len) ); \ 00083 assert ( (iobuf)->data >= (iobuf)->head ); \ 00084 __result; } ) 00085 00086 /** 00087 * Remove data from start of I/O buffer 00088 * 00089 * @v iobuf I/O buffer 00090 * @v len Length to remove 00091 * @ret data Pointer to new start of buffer 00092 */ 00093 static inline void * iob_pull ( struct io_buffer *iobuf, size_t len ) { 00094 iobuf->data += len; 00095 assert ( iobuf->data <= iobuf->tail ); 00096 return iobuf->data; 00097 } 00098 #define iob_pull( iobuf, len ) ( { \ 00099 void *__result; \ 00100 __result = iob_pull ( (iobuf), (len) ); \ 00101 assert ( (iobuf)->data <= (iobuf)->tail ); \ 00102 __result; } ) 00103 00104 /** 00105 * Add data to end of I/O buffer 00106 * 00107 * @v iobuf I/O buffer 00108 * @v len Length to add 00109 * @ret data Pointer to newly added space 00110 */ 00111 static inline void * iob_put ( struct io_buffer *iobuf, size_t len ) { 00112 void *old_tail = iobuf->tail; 00113 iobuf->tail += len; 00114 return old_tail; 00115 } 00116 #define iob_put( iobuf, len ) ( { \ 00117 void *__result; \ 00118 __result = iob_put ( (iobuf), (len) ); \ 00119 assert ( (iobuf)->tail <= (iobuf)->end ); \ 00120 __result; } ) 00121 00122 /** 00123 * Remove data from end of I/O buffer 00124 * 00125 * @v iobuf I/O buffer 00126 * @v len Length to remove 00127 */ 00128 static inline void iob_unput ( struct io_buffer *iobuf, size_t len ) { 00129 iobuf->tail -= len; 00130 } 00131 #define iob_unput( iobuf, len ) do { \ 00132 iob_unput ( (iobuf), (len) ); \ 00133 assert ( (iobuf)->tail >= (iobuf)->data ); \ 00134 } while ( 0 ) 00135 00136 /** 00137 * Empty an I/O buffer 00138 * 00139 * @v iobuf I/O buffer 00140 */ 00141 static inline void iob_empty ( struct io_buffer *iobuf ) { 00142 iobuf->tail = iobuf->data; 00143 } 00144 00145 /** 00146 * Calculate length of data in an I/O buffer 00147 * 00148 * @v iobuf I/O buffer 00149 * @ret len Length of data in buffer 00150 */ 00151 static inline size_t iob_len ( struct io_buffer *iobuf ) { 00152 return ( iobuf->tail - iobuf->data ); 00153 } 00154 00155 /** 00156 * Calculate available space at start of an I/O buffer 00157 * 00158 * @v iobuf I/O buffer 00159 * @ret len Length of data available at start of buffer 00160 */ 00161 static inline size_t iob_headroom ( struct io_buffer *iobuf ) { 00162 return ( iobuf->data - iobuf->head ); 00163 } 00164 00165 /** 00166 * Calculate available space at end of an I/O buffer 00167 * 00168 * @v iobuf I/O buffer 00169 * @ret len Length of data available at end of buffer 00170 */ 00171 static inline size_t iob_tailroom ( struct io_buffer *iobuf ) { 00172 return ( iobuf->end - iobuf->tail ); 00173 } 00174 00175 /** 00176 * Create a temporary I/O buffer 00177 * 00178 * @v iobuf I/O buffer 00179 * @v data Data buffer 00180 * @v len Length of data 00181 * @v max_len Length of buffer 00182 * 00183 * It is sometimes useful to use the iob_xxx() methods on temporary 00184 * data buffers. 00185 */ 00186 static inline void iob_populate ( struct io_buffer *iobuf, 00187 void *data, size_t len, size_t max_len ) { 00188 iobuf->head = iobuf->data = data; 00189 iobuf->tail = ( data + len ); 00190 iobuf->end = ( data + max_len ); 00191 } 00192 00193 /** 00194 * Disown an I/O buffer 00195 * 00196 * @v iobuf I/O buffer 00197 * 00198 * There are many functions that take ownership of the I/O buffer they 00199 * are passed as a parameter. The caller should not retain a pointer 00200 * to the I/O buffer. Use iob_disown() to automatically nullify the 00201 * caller's pointer, e.g.: 00202 * 00203 * xfer_deliver_iob ( xfer, iob_disown ( iobuf ) ); 00204 * 00205 * This will ensure that iobuf is set to NULL for any code after the 00206 * call to xfer_deliver_iob(). 00207 */ 00208 #define iob_disown( iobuf ) ( { \ 00209 struct io_buffer *__iobuf = (iobuf); \ 00210 (iobuf) = NULL; \ 00211 __iobuf; } ) 00212 00213 extern struct io_buffer * __malloc alloc_iob_raw ( size_t len, size_t align, 00214 size_t offset ); 00215 extern struct io_buffer * __malloc alloc_iob ( size_t len ); 00216 extern void free_iob ( struct io_buffer *iobuf ); 00217 extern void iob_pad ( struct io_buffer *iobuf, size_t min_len ); 00218 extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ); 00219 extern struct io_buffer * iob_concatenate ( struct list_head *list ); 00220 extern struct io_buffer * iob_split ( struct io_buffer *iobuf, size_t len ); 00221 00222 #endif /* _IPXE_IOBUF_H */