iPXE
blocktrans.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /**
27  * @file
28  *
29  * Block device translator
30  *
31  */
32 
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <assert.h>
36 #include <ipxe/iobuf.h>
37 #include <ipxe/xfer.h>
38 #include <ipxe/blockdev.h>
39 #include <ipxe/blocktrans.h>
40 
41 /**
42  * Reallocate block device translator data buffer
43  *
44  * @v xferbuf Data transfer buffer
45  * @v len New length (or zero to free buffer)
46  * @ret rc Return status code
47  */
48 static int blktrans_xferbuf_realloc ( struct xfer_buffer *xferbuf,
49  size_t len ) {
50  struct block_translator *blktrans =
52 
53  /* Record length, if applicable */
54  if ( blktrans->buffer ) {
55 
56  /* We have a (non-reallocatable) data buffer */
57  return -ENOTSUP;
58 
59  } else {
60 
61  /* Record length (for block device capacity) */
62  xferbuf->len = len;
63  return 0;
64  }
65 }
66 
67 /**
68  * Write data to block device translator data buffer
69  *
70  * @v xferbuf Data transfer buffer
71  * @v offset Starting offset
72  * @v data Data to copy
73  * @v len Length of data
74  */
75 static void blktrans_xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
76  const void *data, size_t len ) {
77  struct block_translator *blktrans =
79 
80  /* Write data to buffer, if applicable */
81  if ( blktrans->buffer ) {
82 
83  /* Write data to buffer */
84  copy_to_user ( blktrans->buffer, offset, data, len );
85 
86  } else {
87 
88  /* Sanity check */
89  assert ( len == 0 );
90  }
91 }
92 
93 /**
94  * Read data from block device translator data buffer
95  *
96  * @v xferbuf Data transfer buffer
97  * @v offset Starting offset
98  * @v data Data to read
99  * @v len Length of data
100  */
101 static void blktrans_xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset,
102  void *data, size_t len ) {
103  struct block_translator *blktrans =
105 
106  /* Read data from buffer, if applicable */
107  if ( blktrans->buffer ) {
108 
109  /* Read data from buffer */
110  copy_from_user ( data, blktrans->buffer, offset, len );
111 
112  } else {
113 
114  /* Sanity check */
115  assert ( len == 0 );
116  }
117 }
118 
119 /** Block device translator data transfer buffer operations */
122  .write = blktrans_xferbuf_write,
123  .read = blktrans_xferbuf_read,
124 };
125 
126 /**
127  * Close block device translator
128  *
129  * @v blktrans Block device translator
130  * @v rc Reason for close
131  */
132 static void blktrans_close ( struct block_translator *blktrans, int rc ) {
133  struct block_device_capacity capacity;
134 
135  /* Report block device capacity, if applicable */
136  if ( ( rc == 0 ) && ( blktrans->blksize ) ) {
137 
138  /* Construct block device capacity */
139  capacity.blocks =
140  ( blktrans->xferbuf.len / blktrans->blksize );
141  capacity.blksize = blktrans->blksize;
142  capacity.max_count = -1U;
143 
144  /* Report block device capacity */
145  block_capacity ( &blktrans->block, &capacity );
146  }
147 
148  /* Shut down interfaces */
149  intf_shutdown ( &blktrans->xfer, rc );
150  intf_shutdown ( &blktrans->block, rc );
151 }
152 
153 /**
154  * Deliver data
155  *
156  * @v blktrans Block device translator
157  * @v iobuf I/O buffer
158  * @v meta Data transfer metadata
159  * @ret rc Return status code
160  */
161 static int blktrans_deliver ( struct block_translator *blktrans,
162  struct io_buffer *iobuf,
163  struct xfer_metadata *meta ) {
164  int rc;
165 
166  /* Deliver to buffer */
167  if ( ( rc = xferbuf_deliver ( &blktrans->xferbuf, iob_disown ( iobuf ),
168  meta ) ) != 0 ) {
169  DBGC ( blktrans, "BLKTRANS %p could not deliver: %s\n",
170  blktrans, strerror ( rc ) );
171  goto err;
172  }
173 
174  return 0;
175 
176  err:
177  blktrans_close ( blktrans, rc );
178  return rc;
179 }
180 
181 /**
182  * Get underlying data transfer buffer
183  *
184  * @v blktrans Block device translator
185  * @ret xferbuf Data transfer buffer
186  */
187 static struct xfer_buffer *
188 blktrans_buffer ( struct block_translator *blktrans ) {
189 
190  return &blktrans->xferbuf;
191 }
192 
193 /** Block device translator block device interface operations */
196 };
197 
198 /** Block device translator block device interface descriptor */
202 
203 /** Block device translator data transfer interface operations */
208 };
209 
210 /** Block device translator data transfer interface descriptor */
212  INTF_DESC_PASSTHRU ( struct block_translator, xfer,
214 
215 /**
216  * Insert block device translator
217  *
218  * @v block Block device interface
219  * @v buffer Data buffer (or UNULL)
220  * @v size Length of data buffer, or block size
221  * @ret rc Return status code
222  */
224  struct block_translator *blktrans;
225  int rc;
226 
227  /* Allocate and initialise structure */
228  blktrans = zalloc ( sizeof ( *blktrans ) );
229  if ( ! blktrans ) {
230  rc = -ENOMEM;
231  goto err_alloc;
232  }
233  ref_init ( &blktrans->refcnt, NULL );
234  intf_init ( &blktrans->block, &blktrans_block_desc, &blktrans->refcnt );
235  intf_init ( &blktrans->xfer, &blktrans_xfer_desc, &blktrans->refcnt );
237  blktrans->buffer = buffer;
238  if ( buffer ) {
239  blktrans->xferbuf.len = size;
240  } else {
241  blktrans->blksize = size;
242  }
243 
244  /* Attach to interfaces, mortalise self, and return */
245  intf_insert ( block, &blktrans->block, &blktrans->xfer );
246  ref_put ( &blktrans->refcnt );
247 
248  DBGC2 ( blktrans, "BLKTRANS %p created", blktrans );
249  if ( buffer ) {
250  DBGC2 ( blktrans, " for %#lx+%#zx",
251  user_to_phys ( buffer, 0 ), size );
252  }
253  DBGC2 ( blktrans, "\n" );
254  return 0;
255 
256  ref_put ( &blktrans->refcnt );
257  err_alloc:
258  return rc;
259 }
An object interface operation.
Definition: interface.h:17
struct refcnt refcnt
Reference count.
Definition: blocktrans.h:21
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
int xferbuf_deliver(struct xfer_buffer *xferbuf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Add received data to data transfer buffer.
Definition: xferbuf.c:152
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
unsigned int max_count
Maximum number of blocks per single transfer.
Definition: blockdev.h:24
static struct interface_descriptor blktrans_block_desc
Block device translator block device interface descriptor.
Definition: blocktrans.c:199
static void blktrans_close(struct block_translator *blktrans, int rc)
Close block device translator.
Definition: blocktrans.c:132
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
A data transfer buffer.
Definition: xferbuf.h:19
I/O buffers.
void block_capacity(struct interface *intf, struct block_device_capacity *capacity)
Report block device capacity.
Definition: blockdev.c:129
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
unsigned long user_to_phys(userptr_t userptr, off_t offset)
Convert user pointer to physical address.
#define DBGC(...)
Definition: compiler.h:505
Block device translator.
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
int block_translate(struct interface *block, userptr_t buffer, size_t size)
Insert block device translator.
Definition: blocktrans.c:223
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
Data transfer interfaces.
Data transfer buffer operations.
Definition: xferbuf.h:31
size_t len
Size of data.
Definition: xferbuf.h:23
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:212
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
An object interface.
Definition: interface.h:124
A block device translator.
Definition: blocktrans.h:19
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
uint64_t blocks
Total number of blocks.
Definition: blockdev.h:20
static int blktrans_xferbuf_realloc(struct xfer_buffer *xferbuf, size_t len)
Reallocate block device translator data buffer.
Definition: blocktrans.c:48
static struct xfer_buffer * blktrans_buffer(struct block_translator *blktrans)
Get underlying data transfer buffer.
Definition: blocktrans.c:188
struct interface xfer
Data transfer interface.
Definition: blocktrans.h:25
int meta(WINDOW *, bool)
An object interface descriptor.
Definition: interface.h:55
struct xfer_buffer_operations * op
Data transfer buffer operations.
Definition: xferbuf.h:27
Block devices.
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
static __always_inline void copy_to_user(userptr_t dest, off_t dest_off, const void *src, size_t len)
Copy data to user buffer.
Definition: uaccess.h:324
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
static struct interface_descriptor blktrans_xfer_desc
Block device translator data transfer interface descriptor.
Definition: blocktrans.c:211
static int blktrans_deliver(struct block_translator *blktrans, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver data.
Definition: blocktrans.c:161
static struct interface_operation blktrans_xfer_operations[]
Block device translator data transfer interface operations.
Definition: blocktrans.c:204
static struct interface_operation blktrans_block_operations[]
Block device translator block device interface operations.
Definition: blocktrans.c:194
void intf_insert(struct interface *intf, struct interface *upper, struct interface *lower)
Insert a filter interface.
Definition: interface.c:401
static void blktrans_xferbuf_read(struct xfer_buffer *xferbuf, size_t offset, void *data, size_t len)
Read data from block device translator data buffer.
Definition: blocktrans.c:101
uint32_t len
Length.
Definition: ena.h:14
Block device capacity.
Definition: blockdev.h:18
#define DBGC2(...)
Definition: compiler.h:522
uint8_t block[3][8]
DES-encrypted blocks.
Definition: mschapv2.h:12
int(* realloc)(struct xfer_buffer *xferbuf, size_t len)
Reallocate data buffer.
Definition: xferbuf.h:38
uint8_t size
Entry size (in 32-bit words)
Definition: ena.h:16
uint8_t data[48]
Additional event data.
Definition: ena.h:22
struct xfer_buffer xferbuf
Data transfer buffer.
Definition: blocktrans.h:28
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
Definition: interface.h:97
size_t blksize
Block size.
Definition: blocktrans.h:32
static struct xfer_buffer_operations blktrans_xferbuf_operations
Block device translator data transfer buffer operations.
Definition: blocktrans.c:120
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:203
static void blktrans_xferbuf_write(struct xfer_buffer *xferbuf, size_t offset, const void *data, size_t len)
Write data to block device translator data buffer.
Definition: blocktrans.c:75
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
userptr_t buffer
Data buffer.
Definition: blocktrans.h:30
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
size_t blksize
Block size.
Definition: blockdev.h:22
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
struct interface block
Block device interface.
Definition: blocktrans.h:23
A persistent I/O buffer.
Definition: iobuf.h:33