1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
|
#ifndef _IPXE_RNDIS_H
#define _IPXE_RNDIS_H
/** @file
*
* Remote Network Driver Interface Specification
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h>
#include <ipxe/netdevice.h>
#include <ipxe/iobuf.h>
/** Maximum time to wait for a transaction to complete
*
* This is a policy decision.
*/
#define RNDIS_MAX_WAIT_MS 1000
/** RNDIS message header */
struct rndis_header {
/** Message type */
uint32_t type;
/** Message length */
uint32_t len;
} __attribute__ (( packed ));
/** RNDIS initialise message */
#define RNDIS_INITIALIZE_MSG 0x00000002UL
/** RNDIS initialise message */
struct rndis_initialize_message {
/** Request ID */
uint32_t id;
/** Major version */
uint32_t major;
/** Minor version */
uint32_t minor;
/** Maximum transfer size */
uint32_t mtu;
} __attribute__ (( packed ));
/** RNDIS initialise completion */
#define RNDIS_INITIALISE_CMPLT 0x80000002UL
/** RNDIS initialise completion */
struct rndis_initialise_completion {
/** Request ID */
uint32_t id;
/** Status */
uint32_t status;
/** Major version */
uint32_t major;
/** Minor version */
uint32_t minor;
/** Device flags */
uint32_t flags;
/** Medium */
uint32_t medium;
/** Maximum packets per transfer */
uint32_t max_pkts;
/** Maximum transfer size */
uint32_t mtu;
/** Packet alignment factor */
uint32_t align;
/** Reserved */
uint32_t reserved;
} __attribute__ (( packed ));
/** RNDIS halt message */
#define RNIS_HALT_MSG 0x00000003UL
/** RNDIS halt message */
struct rndis_halt_message {
/** Request ID */
uint32_t id;
} __attribute__ (( packed ));
/** RNDIS query OID message */
#define RNDIS_QUERY_MSG 0x00000004UL
/** RNDIS set OID message */
#define RNDIS_SET_MSG 0x00000005UL
/** RNDIS query or set OID message */
struct rndis_oid_message {
/** Request ID */
uint32_t id;
/** Object ID */
uint32_t oid;
/** Information buffer length */
uint32_t len;
/** Information buffer offset */
uint32_t offset;
/** Reserved */
uint32_t reserved;
} __attribute__ (( packed ));
/** RNDIS query OID completion */
#define RNDIS_QUERY_CMPLT 0x80000004UL
/** RNDIS query OID completion */
struct rndis_query_completion {
/** Request ID */
uint32_t id;
/** Status */
uint32_t status;
/** Information buffer length */
uint32_t len;
/** Information buffer offset */
uint32_t offset;
} __attribute__ (( packed ));
/** RNDIS set OID completion */
#define RNDIS_SET_CMPLT 0x80000005UL
/** RNDIS set OID completion */
struct rndis_set_completion {
/** Request ID */
uint32_t id;
/** Status */
uint32_t status;
} __attribute__ (( packed ));
/** RNDIS reset message */
#define RNDIS_RESET_MSG 0x00000006UL
/** RNDIS reset message */
struct rndis_reset_message {
/** Reserved */
uint32_t reserved;
} __attribute__ (( packed ));
/** RNDIS reset completion */
#define RNDIS_RESET_CMPLT 0x80000006UL
/** RNDIS reset completion */
struct rndis_reset_completion {
/** Status */
uint32_t status;
/** Addressing reset */
uint32_t addr;
} __attribute__ (( packed ));
/** RNDIS indicate status message */
#define RNDIS_INDICATE_STATUS_MSG 0x00000007UL
/** RNDIS diagnostic information */
struct rndis_diagnostic_info {
/** Status */
uint32_t status;
/** Error offset */
uint32_t offset;
} __attribute__ (( packed ));
/** RNDIS indicate status message */
struct rndis_indicate_status_message {
/** Status */
uint32_t status;
/** Status buffer length */
uint32_t len;
/** Status buffer offset */
uint32_t offset;
/** Diagnostic information (optional) */
struct rndis_diagnostic_info diag[0];
} __attribute__ (( packed ));
/** RNDIS status codes */
enum rndis_status {
/** Device is connected to a network medium */
RNDIS_STATUS_MEDIA_CONNECT = 0x4001000bUL,
/** Device is disconnected from the medium */
RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000cUL,
};
/** RNDIS keepalive message */
#define RNDIS_KEEPALIVE_MSG 0x00000008UL
/** RNDIS keepalive message */
struct rndis_keepalive_message {
/** Request ID */
uint32_t id;
} __attribute__ (( packed ));
/** RNDIS keepalive completion */
#define RNDIS_KEEPALIVE_CMPLT 0x80000008UL
/** RNDIS keepalive completion */
struct rndis_keepalive_completion {
/** Request ID */
uint32_t id;
/** Status */
uint32_t status;
} __attribute__ (( packed ));
/** RNDIS packet message */
#define RNDIS_PACKET_MSG 0x00000001UL
/** RNDIS packet field */
struct rndis_packet_field {
/** Offset */
uint32_t offset;
/** Length */
uint32_t len;
} __attribute__ (( packed ));
/** RNDIS packet message */
struct rndis_packet_message {
/** Data */
struct rndis_packet_field data;
/** Out-of-band data records */
struct rndis_packet_field oob;
/** Number of out-of-band data records */
uint32_t oob_count;
/** Per-packet information record */
struct rndis_packet_field ppi;
/** Reserved */
uint32_t reserved;
} __attribute__ (( packed ));
/** RNDIS packet record */
struct rndis_packet_record {
/** Length */
uint32_t len;
/** Type */
uint32_t type;
/** Offset */
uint32_t offset;
} __attribute__ (( packed ));
/** OID for packet filter */
#define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010eUL
/** Packet filter bits */
enum rndis_packet_filter {
/** Unicast packets */
RNDIS_FILTER_UNICAST = 0x00000001UL,
/** Multicast packets */
RNDIS_FILTER_MULTICAST = 0x00000002UL,
/** All multicast packets */
RNDIS_FILTER_ALL_MULTICAST = 0x00000004UL,
/** Broadcast packets */
RNDIS_FILTER_BROADCAST = 0x00000008UL,
/** All packets */
RNDIS_FILTER_PROMISCUOUS = 0x00000020UL
};
/** OID for media status */
#define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL
/** OID for permanent MAC address */
#define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101UL
/** OID for current MAC address */
#define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102UL
struct rndis_device;
/** RNDIS device operations */
struct rndis_operations {
/**
* Open RNDIS device
*
* @v rndis RNDIS device
* @ret rc Return status code
*/
int ( * open ) ( struct rndis_device *rndis );
/**
* Close RNDIS device
*
* @v rndis RNDIS device
*/
void ( * close ) ( struct rndis_device *rndis );
/**
* Transmit packet
*
* @v rndis RNDIS device
* @v iobuf I/O buffer
* @ret rc Return status code
*
* If this method returns success then the RNDIS device must
* eventually report completion via rndis_tx_complete().
*/
int ( * transmit ) ( struct rndis_device *rndis,
struct io_buffer *iobuf );
/**
* Poll for completed and received packets
*
* @v rndis RNDIS device
*/
void ( * poll ) ( struct rndis_device *rndis );
};
/** An RNDIS device */
struct rndis_device {
/** Network device */
struct net_device *netdev;
/** Device name */
const char *name;
/** RNDIS operations */
struct rndis_operations *op;
/** Driver private data */
void *priv;
/** Request ID for current blocking request */
unsigned int wait_id;
/** Return status code for current blocking request */
int wait_rc;
};
/**
* Initialise an RNDIS device
*
* @v rndis RNDIS device
* @v op RNDIS device operations
*/
static inline void rndis_init ( struct rndis_device *rndis,
struct rndis_operations *op ) {
rndis->op = op;
}
extern void rndis_tx_complete_err ( struct rndis_device *rndis,
struct io_buffer *iobuf, int rc );
extern int rndis_tx_defer ( struct rndis_device *rndis,
struct io_buffer *iobuf );
extern void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf );
extern struct rndis_device * alloc_rndis ( size_t priv_len );
extern int register_rndis ( struct rndis_device *rndis );
extern void unregister_rndis ( struct rndis_device *rndis );
extern void free_rndis ( struct rndis_device *rndis );
/**
* Complete message transmission
*
* @v rndis RNDIS device
* @v iobuf I/O buffer
*/
static inline void rndis_tx_complete ( struct rndis_device *rndis,
struct io_buffer *iobuf ) {
rndis_tx_complete_err ( rndis, iobuf, 0 );
}
#endif /* _IPXE_RNDIS_H */
|