iPXE
guestrpc.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012 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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * VMware GuestRPC mechanism
29 *
30 */
31
32#include <stdint.h>
33#include <string.h>
34#include <errno.h>
35#include <assert.h>
36#include <ipxe/vmware.h>
37#include <ipxe/guestrpc.h>
38
39/* Disambiguate the various error causes */
40#define EPROTO_OPEN __einfo_error ( EINFO_EPROTO_OPEN )
41#define EINFO_EPROTO_OPEN \
42 __einfo_uniqify ( EINFO_EPROTO, 0x00, "GuestRPC open failed" )
43#define EPROTO_COMMAND_LEN __einfo_error ( EINFO_EPROTO_COMMAND_LEN )
44#define EINFO_EPROTO_COMMAND_LEN \
45 __einfo_uniqify ( EINFO_EPROTO, 0x01, "GuestRPC command length failed" )
46#define EPROTO_COMMAND_DATA __einfo_error ( EINFO_EPROTO_COMMAND_DATA )
47#define EINFO_EPROTO_COMMAND_DATA \
48 __einfo_uniqify ( EINFO_EPROTO, 0x02, "GuestRPC command data failed" )
49#define EPROTO_REPLY_LEN __einfo_error ( EINFO_EPROTO_REPLY_LEN )
50#define EINFO_EPROTO_REPLY_LEN \
51 __einfo_uniqify ( EINFO_EPROTO, 0x03, "GuestRPC reply length failed" )
52#define EPROTO_REPLY_DATA __einfo_error ( EINFO_EPROTO_REPLY_DATA )
53#define EINFO_EPROTO_REPLY_DATA \
54 __einfo_uniqify ( EINFO_EPROTO, 0x04, "GuestRPC reply data failed" )
55#define EPROTO_REPLY_FINISH __einfo_error ( EINFO_EPROTO_REPLY_FINISH )
56#define EINFO_EPROTO_REPLY_FINISH \
57 __einfo_uniqify ( EINFO_EPROTO, 0x05, "GuestRPC reply finish failed" )
58#define EPROTO_CLOSE __einfo_error ( EINFO_EPROTO_CLOSE )
59#define EINFO_EPROTO_CLOSE \
60 __einfo_uniqify ( EINFO_EPROTO, 0x06, "GuestRPC close failed" )
61
62/**
63 * Open GuestRPC channel
64 *
65 * @ret channel Channel number, or negative error
66 */
67int guestrpc_open ( void ) {
69 uint32_t discard_b;
71
72 /* Issue GuestRPC command */
73 status = vmware_cmd_guestrpc ( 0, GUESTRPC_OPEN, GUESTRPC_MAGIC,
74 &channel, &discard_b );
76 DBGC ( GUESTRPC_MAGIC, "GuestRPC open failed: status %08x\n",
77 status );
78 return -EPROTO_OPEN;
79 }
80
81 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d opened\n", channel );
82 return channel;
83}
84
85/**
86 * Send GuestRPC command length
87 *
88 * @v channel Channel number
89 * @v len Command length
90 * @ret rc Return status code
91 */
92static int guestrpc_command_len ( int channel, size_t len ) {
93 uint16_t discard_d;
94 uint32_t discard_b;
96
97 /* Issue GuestRPC command */
98 status = vmware_cmd_guestrpc ( channel, GUESTRPC_COMMAND_LEN, len,
99 &discard_d, &discard_b );
101 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d send command "
102 "length %zd failed: status %08x\n",
103 channel, len, status );
104 return -EPROTO_COMMAND_LEN;
105 }
106
107 return 0;
108}
109
110/**
111 * Send GuestRPC command data
112 *
113 * @v channel Channel number
114 * @v data Command data
115 * @ret rc Return status code
116 */
118 uint16_t discard_d;
119 uint32_t discard_b;
121
122 /* Issue GuestRPC command */
123 status = vmware_cmd_guestrpc ( channel, GUESTRPC_COMMAND_DATA, data,
124 &discard_d, &discard_b );
126 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d send command "
127 "data %08x failed: status %08x\n",
128 channel, data, status );
129 return -EPROTO_COMMAND_DATA;
130 }
131
132 return 0;
133}
134
135/**
136 * Receive GuestRPC reply length
137 *
138 * @v channel Channel number
139 * @ret reply_id Reply ID
140 * @ret len Reply length, or negative error
141 */
142static int guestrpc_reply_len ( int channel, uint16_t *reply_id ) {
145
146 /* Issue GuestRPC command */
147 status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_LEN, 0,
148 reply_id, &len );
150 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d receive reply "
151 "length failed: status %08x\n", channel, status );
152 return -EPROTO_REPLY_LEN;
153 }
154
155 return len;
156}
157
158/**
159 * Receive GuestRPC reply data
160 *
161 * @v channel Channel number
162 * @v reply_id Reply ID
163 * @ret data Reply data
164 * @ret rc Return status code
165 */
166static int guestrpc_reply_data ( int channel, uint16_t reply_id,
167 uint32_t *data ) {
168 uint16_t discard_d;
170
171 /* Issue GuestRPC command */
172 status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_DATA, reply_id,
173 &discard_d, data );
175 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d receive reply "
176 "%d data failed: status %08x\n",
177 channel, reply_id, status );
178 return -EPROTO_REPLY_DATA;
179 }
180
181 return 0;
182}
183
184/**
185 * Finish receiving GuestRPC reply
186 *
187 * @v channel Channel number
188 * @v reply_id Reply ID
189 * @ret rc Return status code
190 */
191static int guestrpc_reply_finish ( int channel, uint16_t reply_id ) {
192 uint16_t discard_d;
193 uint32_t discard_b;
195
196 /* Issue GuestRPC command */
197 status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_FINISH, reply_id,
198 &discard_d, &discard_b );
200 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d finish reply %d "
201 "failed: status %08x\n", channel, reply_id, status );
202 return -EPROTO_REPLY_FINISH;
203 }
204
205 return 0;
206}
207
208/**
209 * Close GuestRPC channel
210 *
211 * @v channel Channel number
212 */
214 uint16_t discard_d;
215 uint32_t discard_b;
217
218 /* Issue GuestRPC command */
219 status = vmware_cmd_guestrpc ( channel, GUESTRPC_CLOSE, 0,
220 &discard_d, &discard_b );
222 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d close failed: "
223 "status %08x\n", channel, status );
224 return;
225 }
226
227 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d closed\n", channel );
228}
229
230/**
231 * Issue GuestRPC command
232 *
233 * @v channel Channel number
234 * @v command Command
235 * @v reply Reply buffer
236 * @v reply_len Length of reply buffer
237 * @ret len Length of reply, or negative error
238 *
239 * The actual length of the reply will be returned even if the buffer
240 * was too small.
241 */
242int guestrpc_command ( int channel, const char *command, char *reply,
243 size_t reply_len ) {
244 const uint8_t *command_bytes = ( ( const void * ) command );
245 uint8_t *reply_bytes = ( ( void * ) reply );
246 size_t command_len = strlen ( command );
247 int orig_reply_len = reply_len;
249 uint8_t *status_bytes = ( ( void * ) &status );
250 size_t status_len = sizeof ( status );
252 uint16_t reply_id;
253 int len;
254 int remaining;
255 unsigned int i;
256 int rc;
257
258 DBGC2 ( GUESTRPC_MAGIC, "GuestRPC channel %d issuing command:\n",
259 channel );
261
262 /* Sanity check */
263 assert ( ( reply != NULL ) || ( reply_len == 0 ) );
264
265 /* Send command length */
266 if ( ( rc = guestrpc_command_len ( channel, command_len ) ) < 0 )
267 return rc;
268
269 /* Send command data */
270 while ( command_len ) {
271 data = 0;
272 for ( i = sizeof ( data ) ; i ; i-- ) {
273 if ( command_len ) {
274 data = ( ( data & ~0xff ) |
275 *(command_bytes++) );
276 command_len--;
277 }
278 data = ( ( data << 24 ) | ( data >> 8 ) );
279 }
280 if ( ( rc = guestrpc_command_data ( channel, data ) ) < 0 )
281 return rc;
282 }
283
284 /* Receive reply length */
285 if ( ( len = guestrpc_reply_len ( channel, &reply_id ) ) < 0 ) {
286 rc = len;
287 return rc;
288 }
289
290 /* Receive reply */
291 for ( remaining = len ; remaining > 0 ; remaining -= sizeof ( data ) ) {
292 if ( ( rc = guestrpc_reply_data ( channel, reply_id,
293 &data ) ) < 0 ) {
294 return rc;
295 }
296 for ( i = sizeof ( data ) ; i ; i-- ) {
297 if ( status_len ) {
298 *(status_bytes++) = ( data & 0xff );
299 status_len--;
300 len--;
301 } else if ( reply_len ) {
302 *(reply_bytes++) = ( data & 0xff );
303 reply_len--;
304 }
305 data = ( ( data << 24 ) | ( data >> 8 ) );
306 }
307 }
308
309 /* Finish receiving RPC reply */
310 if ( ( rc = guestrpc_reply_finish ( channel, reply_id ) ) < 0 )
311 return rc;
312
313 DBGC2 ( GUESTRPC_MAGIC, "GuestRPC channel %d received reply (id %d, "
314 "length %d):\n", channel, reply_id, len );
315 DBGC2_HDA ( GUESTRPC_MAGIC, 0, &status, sizeof ( status ) );
316 DBGC2_HDA ( GUESTRPC_MAGIC, sizeof ( status ), reply,
317 ( ( len < orig_reply_len ) ? len : orig_reply_len ) );
318
319 /* Check reply status */
320 if ( status != GUESTRPC_SUCCESS ) {
321 DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d command failed "
322 "(status %04x, reply id %d, reply length %d):\n",
323 channel, status, reply_id, len );
325 DBGC_HDA ( GUESTRPC_MAGIC, 0, &status, sizeof ( status ) );
326 DBGC_HDA ( GUESTRPC_MAGIC, sizeof ( status ), reply,
327 ( ( len < orig_reply_len ) ? len : orig_reply_len ));
328 return -EIO;
329 }
330
331 return len;
332}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t status
Status.
Definition ena.h:5
Error codes.
#define DBGC2(...)
Definition compiler.h:522
#define DBGC2_HDA(...)
Definition compiler.h:523
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EIO
Input/output error.
Definition errno.h:434
device command_len
Definition threewire.h:60
static int guestrpc_reply_data(int channel, uint16_t reply_id, uint32_t *data)
Receive GuestRPC reply data.
Definition guestrpc.c:166
#define EPROTO_COMMAND_DATA
Definition guestrpc.c:46
#define EPROTO_REPLY_FINISH
Definition guestrpc.c:55
#define EPROTO_COMMAND_LEN
Definition guestrpc.c:43
#define EPROTO_REPLY_DATA
Definition guestrpc.c:52
static int guestrpc_command_data(int channel, uint32_t data)
Send GuestRPC command data.
Definition guestrpc.c:117
static int guestrpc_command_len(int channel, size_t len)
Send GuestRPC command length.
Definition guestrpc.c:92
int guestrpc_open(void)
Open GuestRPC channel.
Definition guestrpc.c:67
#define EPROTO_OPEN
Definition guestrpc.c:40
static int guestrpc_reply_finish(int channel, uint16_t reply_id)
Finish receiving GuestRPC reply.
Definition guestrpc.c:191
#define EPROTO_REPLY_LEN
Definition guestrpc.c:49
static int guestrpc_reply_len(int channel, uint16_t *reply_id)
Receive GuestRPC reply length.
Definition guestrpc.c:142
void guestrpc_close(int channel)
Close GuestRPC channel.
Definition guestrpc.c:213
int guestrpc_command(int channel, const char *command, char *reply, size_t reply_len)
Issue GuestRPC command.
Definition guestrpc.c:242
VMware GuestRPC mechanism.
#define GUESTRPC_COMMAND_LEN
Send RPC command length.
Definition guestrpc.h:25
#define GUESTRPC_MAGIC
GuestRPC magic number.
Definition guestrpc.h:16
#define GUESTRPC_SUCCESS
RPC command success status.
Definition guestrpc.h:61
#define GUESTRPC_OPEN
Open RPC channel.
Definition guestrpc.h:19
#define GUESTRPC_REPLY_DATA_SUCCESS
Receive RPC reply data success status.
Definition guestrpc.h:46
#define GUESTRPC_CLOSE_SUCCESS
Close RPC channel success status.
Definition guestrpc.h:58
#define GUESTRPC_COMMAND_DATA
Send RPC command data.
Definition guestrpc.h:31
#define GUESTRPC_REPLY_DATA
Receive RPC reply data.
Definition guestrpc.h:43
#define GUESTRPC_OPEN_SUCCESS
Open RPC channel success status.
Definition guestrpc.h:22
#define GUESTRPC_CLOSE
Close RPC channel.
Definition guestrpc.h:55
#define GUESTRPC_REPLY_FINISH
Finish receiving RPC reply.
Definition guestrpc.h:49
#define GUESTRPC_COMMAND_LEN_SUCCESS
Send RPC command length success status.
Definition guestrpc.h:28
#define GUESTRPC_REPLY_LEN_SUCCESS
Receive RPC reply length success status.
Definition guestrpc.h:40
#define GUESTRPC_REPLY_FINISH_SUCCESS
Finish receiving RPC reply success status.
Definition guestrpc.h:52
#define GUESTRPC_COMMAND_DATA_SUCCESS
Send RPC command data success status.
Definition guestrpc.h:34
#define GUESTRPC_REPLY_LEN
Receive RPC reply length.
Definition guestrpc.h:37
String functions.
uint32_t channel
RNDIS channel.
Definition netvsc.h:3
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
A command-line command.
Definition command.h:10
VMware backdoor mechanism.