xref: /freebsd/sys/x86/x86/vmware_guestrpc.c (revision ecaab0fb)
1*ecaab0fbSStephen J. Kiernan /*-
2*ecaab0fbSStephen J. Kiernan  * SPDX-License-Identifier: BSD-2-Clause
3*ecaab0fbSStephen J. Kiernan  *
4*ecaab0fbSStephen J. Kiernan  * Copyright (c) 2013-2024, Juniper Networks, Inc.
5*ecaab0fbSStephen J. Kiernan  *
6*ecaab0fbSStephen J. Kiernan  * Redistribution and use in source and binary forms, with or without
7*ecaab0fbSStephen J. Kiernan  * modification, are permitted provided that the following conditions
8*ecaab0fbSStephen J. Kiernan  * are met:
9*ecaab0fbSStephen J. Kiernan  * 1. Redistributions of source code must retain the above copyright
10*ecaab0fbSStephen J. Kiernan  *    notice, this list of conditions and the following disclaimer.
11*ecaab0fbSStephen J. Kiernan  * 2. Redistributions in binary form must reproduce the above copyright
12*ecaab0fbSStephen J. Kiernan  *    notice, this list of conditions and the following disclaimer in the
13*ecaab0fbSStephen J. Kiernan  *    documentation and/or other materials provided with the distribution.
14*ecaab0fbSStephen J. Kiernan  *
15*ecaab0fbSStephen J. Kiernan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*ecaab0fbSStephen J. Kiernan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*ecaab0fbSStephen J. Kiernan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*ecaab0fbSStephen J. Kiernan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*ecaab0fbSStephen J. Kiernan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*ecaab0fbSStephen J. Kiernan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*ecaab0fbSStephen J. Kiernan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*ecaab0fbSStephen J. Kiernan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*ecaab0fbSStephen J. Kiernan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*ecaab0fbSStephen J. Kiernan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*ecaab0fbSStephen J. Kiernan  * SUCH DAMAGE.
26*ecaab0fbSStephen J. Kiernan  */
27*ecaab0fbSStephen J. Kiernan 
28*ecaab0fbSStephen J. Kiernan #include <sys/cdefs.h>
29*ecaab0fbSStephen J. Kiernan 
30*ecaab0fbSStephen J. Kiernan #include <sys/param.h>
31*ecaab0fbSStephen J. Kiernan #include <sys/systm.h>
32*ecaab0fbSStephen J. Kiernan #include <sys/conf.h>
33*ecaab0fbSStephen J. Kiernan #include <sys/kernel.h>
34*ecaab0fbSStephen J. Kiernan #include <sys/limits.h>
35*ecaab0fbSStephen J. Kiernan #include <sys/bus.h>
36*ecaab0fbSStephen J. Kiernan #include <sys/sbuf.h>
37*ecaab0fbSStephen J. Kiernan #include <sys/errno.h>
38*ecaab0fbSStephen J. Kiernan #include <sys/module.h>
39*ecaab0fbSStephen J. Kiernan 
40*ecaab0fbSStephen J. Kiernan #include <x86/vmware.h>
41*ecaab0fbSStephen J. Kiernan #include <x86/vmware_guestrpc.h>
42*ecaab0fbSStephen J. Kiernan 
43*ecaab0fbSStephen J. Kiernan /* GuestRPC Subcommands */
44*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_OPEN			0x00
45*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_SEND_LEN			0x01
46*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_SEND_DATA		0x02
47*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_RECV_LEN			0x03
48*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_RECV_DATA		0x04
49*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_FINISH_RECV		0x05
50*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_CLOSE			0x06
51*ecaab0fbSStephen J. Kiernan /* GuestRPC Parameters */
52*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_OPEN_MAGIC		0x49435052
53*ecaab0fbSStephen J. Kiernan /* GuestRPC Status */
54*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_FAILURE			0x00000000
55*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_OPEN_SUCCESS		0x00010000
56*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_SEND_LEN_SUCCESS		0x00810000
57*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_SEND_DATA_SUCCESS	0x00010000
58*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_RECV_LEN_SUCCESS		0x00830000
59*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_RECV_DATA_SUCCESS	0x00010000
60*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_FINISH_RECV_SUCCESS	0x00010000
61*ecaab0fbSStephen J. Kiernan #define		VMW_HVGUESTRPC_CLOSE_SUCCESS		0x00010000
62*ecaab0fbSStephen J. Kiernan 
63*ecaab0fbSStephen J. Kiernan #define	VMW_GUESTRPC_EBX(_p)	((_p)[1])
64*ecaab0fbSStephen J. Kiernan #define	VMW_GUESTRPC_EDXHI(_p)	((_p)[3] >> 16)
65*ecaab0fbSStephen J. Kiernan #define	VMW_GUESTRPC_STATUS(_p)	((_p)[2])
66*ecaab0fbSStephen J. Kiernan 
67*ecaab0fbSStephen J. Kiernan static __inline void
vmware_guestrpc(int chan,uint16_t subcmd,uint32_t param,u_int * p)68*ecaab0fbSStephen J. Kiernan vmware_guestrpc(int chan, uint16_t subcmd, uint32_t param, u_int *p)
69*ecaab0fbSStephen J. Kiernan {
70*ecaab0fbSStephen J. Kiernan 
71*ecaab0fbSStephen J. Kiernan #ifdef DEBUG_VMGUESTRPC
72*ecaab0fbSStephen J. Kiernan 	printf("%s(%d, %#x, %#x, %p)\n", __func__, chan, subcmd, param, p);
73*ecaab0fbSStephen J. Kiernan #endif
74*ecaab0fbSStephen J. Kiernan 	vmware_hvcall(chan, VMW_HVCMD_GUESTRPC | (subcmd << 16), param, p);
75*ecaab0fbSStephen J. Kiernan #ifdef DEBUG_VMGUESTRPC
76*ecaab0fbSStephen J. Kiernan 	printf("p[0] = %#x\n", p[0]);
77*ecaab0fbSStephen J. Kiernan 	printf("p[1] = %#x\n", p[1]);
78*ecaab0fbSStephen J. Kiernan 	printf("p[2] = %#x\n", p[2]);
79*ecaab0fbSStephen J. Kiernan 	printf("p[3] = %#x\n", p[3]);
80*ecaab0fbSStephen J. Kiernan #endif
81*ecaab0fbSStephen J. Kiernan }
82*ecaab0fbSStephen J. Kiernan 
83*ecaab0fbSStephen J. Kiernan /*
84*ecaab0fbSStephen J. Kiernan  * Start a GuestRPC request
85*ecaab0fbSStephen J. Kiernan  *
86*ecaab0fbSStephen J. Kiernan  * Channel number is returned in the EDXHI parameter.
87*ecaab0fbSStephen J. Kiernan  *
88*ecaab0fbSStephen J. Kiernan  * This channel number must be used in successive GuestRPC requests for
89*ecaab0fbSStephen J. Kiernan  * sending and receiving RPC data.
90*ecaab0fbSStephen J. Kiernan  */
91*ecaab0fbSStephen J. Kiernan static int
vmware_guestrpc_open(void)92*ecaab0fbSStephen J. Kiernan vmware_guestrpc_open(void)
93*ecaab0fbSStephen J. Kiernan {
94*ecaab0fbSStephen J. Kiernan 	u_int p[4];
95*ecaab0fbSStephen J. Kiernan 
96*ecaab0fbSStephen J. Kiernan 	vmware_guestrpc(0, VMW_HVGUESTRPC_OPEN, VMW_HVGUESTRPC_OPEN_MAGIC,
97*ecaab0fbSStephen J. Kiernan 	    p);
98*ecaab0fbSStephen J. Kiernan 	if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_OPEN_SUCCESS)
99*ecaab0fbSStephen J. Kiernan 		return (-1);
100*ecaab0fbSStephen J. Kiernan 
101*ecaab0fbSStephen J. Kiernan 	return (VMW_GUESTRPC_EDXHI(p));
102*ecaab0fbSStephen J. Kiernan }
103*ecaab0fbSStephen J. Kiernan 
104*ecaab0fbSStephen J. Kiernan /*
105*ecaab0fbSStephen J. Kiernan  * Send the length of the GuestRPC request
106*ecaab0fbSStephen J. Kiernan  *
107*ecaab0fbSStephen J. Kiernan  * In a GuestRPC request, the total length of the request must be sent
108*ecaab0fbSStephen J. Kiernan  * before any data can be sent.
109*ecaab0fbSStephen J. Kiernan  */
110*ecaab0fbSStephen J. Kiernan static int
vmware_guestrpc_send_len(int channel,size_t len)111*ecaab0fbSStephen J. Kiernan vmware_guestrpc_send_len(int channel, size_t len)
112*ecaab0fbSStephen J. Kiernan {
113*ecaab0fbSStephen J. Kiernan 	u_int p[4];
114*ecaab0fbSStephen J. Kiernan 
115*ecaab0fbSStephen J. Kiernan 	vmware_guestrpc(channel, VMW_HVGUESTRPC_SEND_LEN, len, p);
116*ecaab0fbSStephen J. Kiernan 	if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_SEND_LEN_SUCCESS)
117*ecaab0fbSStephen J. Kiernan 		return (-1);
118*ecaab0fbSStephen J. Kiernan 
119*ecaab0fbSStephen J. Kiernan 	return (0);
120*ecaab0fbSStephen J. Kiernan }
121*ecaab0fbSStephen J. Kiernan 
122*ecaab0fbSStephen J. Kiernan /*
123*ecaab0fbSStephen J. Kiernan  * Send the data for the GuestRPC request
124*ecaab0fbSStephen J. Kiernan  *
125*ecaab0fbSStephen J. Kiernan  * The total length of the GuestRPC request must be sent before any data.
126*ecaab0fbSStephen J. Kiernan  * Data is sent 32-bit values at a time and therefore may require multiple
127*ecaab0fbSStephen J. Kiernan  * calls to send all the data.
128*ecaab0fbSStephen J. Kiernan  */
129*ecaab0fbSStephen J. Kiernan static int
vmware_guestrpc_send_data(int channel,uint32_t data)130*ecaab0fbSStephen J. Kiernan vmware_guestrpc_send_data(int channel, uint32_t data)
131*ecaab0fbSStephen J. Kiernan {
132*ecaab0fbSStephen J. Kiernan 	u_int p[4];
133*ecaab0fbSStephen J. Kiernan 
134*ecaab0fbSStephen J. Kiernan 	vmware_guestrpc(channel, VMW_HVGUESTRPC_SEND_DATA, data, p);
135*ecaab0fbSStephen J. Kiernan 	if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_SEND_DATA_SUCCESS)
136*ecaab0fbSStephen J. Kiernan 		return (-1);
137*ecaab0fbSStephen J. Kiernan 
138*ecaab0fbSStephen J. Kiernan 	return (0);
139*ecaab0fbSStephen J. Kiernan }
140*ecaab0fbSStephen J. Kiernan 
141*ecaab0fbSStephen J. Kiernan /*
142*ecaab0fbSStephen J. Kiernan  * Receive the length of the GuestRPC reply.
143*ecaab0fbSStephen J. Kiernan  *
144*ecaab0fbSStephen J. Kiernan  * Length of the reply data is returned in the EBX parameter.
145*ecaab0fbSStephen J. Kiernan  * The reply identifier is returned in the EDXHI parameter.
146*ecaab0fbSStephen J. Kiernan  *
147*ecaab0fbSStephen J. Kiernan  * The reply identifier must be used as the GuestRPC parameter in calls
148*ecaab0fbSStephen J. Kiernan  * to vmware_guestrpc_recv_data()
149*ecaab0fbSStephen J. Kiernan  */
150*ecaab0fbSStephen J. Kiernan static int
vmware_guestrpc_recv_len(int channel,size_t * lenp)151*ecaab0fbSStephen J. Kiernan vmware_guestrpc_recv_len(int channel, size_t *lenp)
152*ecaab0fbSStephen J. Kiernan {
153*ecaab0fbSStephen J. Kiernan 	u_int p[4];
154*ecaab0fbSStephen J. Kiernan 
155*ecaab0fbSStephen J. Kiernan 	vmware_guestrpc(channel, VMW_HVGUESTRPC_RECV_LEN, 0, p);
156*ecaab0fbSStephen J. Kiernan 	if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_RECV_LEN_SUCCESS)
157*ecaab0fbSStephen J. Kiernan 		return (-1);
158*ecaab0fbSStephen J. Kiernan 
159*ecaab0fbSStephen J. Kiernan 	*lenp = VMW_GUESTRPC_EBX(p);
160*ecaab0fbSStephen J. Kiernan 	return (VMW_GUESTRPC_EDXHI(p));
161*ecaab0fbSStephen J. Kiernan }
162*ecaab0fbSStephen J. Kiernan 
163*ecaab0fbSStephen J. Kiernan /*
164*ecaab0fbSStephen J. Kiernan  * Receive the GuestRPC reply data.
165*ecaab0fbSStephen J. Kiernan  *
166*ecaab0fbSStephen J. Kiernan  * Data is received in 32-bit values at a time and therefore may
167*ecaab0fbSStephen J. Kiernan  * require multiple requests to get all the data.
168*ecaab0fbSStephen J. Kiernan  */
169*ecaab0fbSStephen J. Kiernan static int
vmware_guestrpc_recv_data(int channel,int id,uint32_t * datap)170*ecaab0fbSStephen J. Kiernan vmware_guestrpc_recv_data(int channel, int id, uint32_t *datap)
171*ecaab0fbSStephen J. Kiernan {
172*ecaab0fbSStephen J. Kiernan 	u_int p[4];
173*ecaab0fbSStephen J. Kiernan 
174*ecaab0fbSStephen J. Kiernan 	vmware_guestrpc(channel, VMW_HVGUESTRPC_RECV_DATA, id, p);
175*ecaab0fbSStephen J. Kiernan 	if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_RECV_DATA_SUCCESS)
176*ecaab0fbSStephen J. Kiernan 		return (-1);
177*ecaab0fbSStephen J. Kiernan 
178*ecaab0fbSStephen J. Kiernan 	*datap = VMW_GUESTRPC_EBX(p);
179*ecaab0fbSStephen J. Kiernan 	return (0);
180*ecaab0fbSStephen J. Kiernan }
181*ecaab0fbSStephen J. Kiernan 
182*ecaab0fbSStephen J. Kiernan /*
183*ecaab0fbSStephen J. Kiernan  * Close the GuestRPC channel.
184*ecaab0fbSStephen J. Kiernan  */
185*ecaab0fbSStephen J. Kiernan static int
vmware_guestrpc_close(int channel)186*ecaab0fbSStephen J. Kiernan vmware_guestrpc_close(int channel)
187*ecaab0fbSStephen J. Kiernan {
188*ecaab0fbSStephen J. Kiernan 	u_int p[4];
189*ecaab0fbSStephen J. Kiernan 
190*ecaab0fbSStephen J. Kiernan 	vmware_guestrpc(channel, VMW_HVGUESTRPC_CLOSE, 0, p);
191*ecaab0fbSStephen J. Kiernan 	if (VMW_GUESTRPC_STATUS(p) != VMW_HVGUESTRPC_CLOSE_SUCCESS)
192*ecaab0fbSStephen J. Kiernan 		return (-1);
193*ecaab0fbSStephen J. Kiernan 
194*ecaab0fbSStephen J. Kiernan 	return (0);
195*ecaab0fbSStephen J. Kiernan }
196*ecaab0fbSStephen J. Kiernan 
197*ecaab0fbSStephen J. Kiernan /*
198*ecaab0fbSStephen J. Kiernan  * Send a GuestRPC command.
199*ecaab0fbSStephen J. Kiernan  */
200*ecaab0fbSStephen J. Kiernan int
vmware_guestrpc_cmd(struct sbuf * sbufp)201*ecaab0fbSStephen J. Kiernan vmware_guestrpc_cmd(struct sbuf *sbufp)
202*ecaab0fbSStephen J. Kiernan {
203*ecaab0fbSStephen J. Kiernan 	char *buf;
204*ecaab0fbSStephen J. Kiernan 	size_t cnt, len;
205*ecaab0fbSStephen J. Kiernan 	int chan, id, status;
206*ecaab0fbSStephen J. Kiernan 	uint32_t data;
207*ecaab0fbSStephen J. Kiernan 
208*ecaab0fbSStephen J. Kiernan 	/* Make sure we are running under VMware hypervisor */
209*ecaab0fbSStephen J. Kiernan 	if (vm_guest != VM_GUEST_VMWARE)
210*ecaab0fbSStephen J. Kiernan 		return (ENXIO);
211*ecaab0fbSStephen J. Kiernan 
212*ecaab0fbSStephen J. Kiernan 	/* Open the GuestRPC channel */
213*ecaab0fbSStephen J. Kiernan 	chan = vmware_guestrpc_open();
214*ecaab0fbSStephen J. Kiernan 	if (chan == -1)
215*ecaab0fbSStephen J. Kiernan 		return (EIO);
216*ecaab0fbSStephen J. Kiernan 
217*ecaab0fbSStephen J. Kiernan 	/* Send the length */
218*ecaab0fbSStephen J. Kiernan 	buf = sbuf_data(sbufp);
219*ecaab0fbSStephen J. Kiernan 	len = sbuf_len(sbufp);
220*ecaab0fbSStephen J. Kiernan 	status = vmware_guestrpc_send_len(chan, len);
221*ecaab0fbSStephen J. Kiernan 	if (status == -1)
222*ecaab0fbSStephen J. Kiernan 		goto done;
223*ecaab0fbSStephen J. Kiernan 
224*ecaab0fbSStephen J. Kiernan 	/* Send the data */
225*ecaab0fbSStephen J. Kiernan 	while (len > 0) {
226*ecaab0fbSStephen J. Kiernan 		data = 0;
227*ecaab0fbSStephen J. Kiernan 		cnt = min(4, len);
228*ecaab0fbSStephen J. Kiernan 		memcpy(&data, buf, cnt);
229*ecaab0fbSStephen J. Kiernan 		status = vmware_guestrpc_send_data(chan, data);
230*ecaab0fbSStephen J. Kiernan 		if (status == -1)
231*ecaab0fbSStephen J. Kiernan 			goto done;
232*ecaab0fbSStephen J. Kiernan 		buf += cnt;
233*ecaab0fbSStephen J. Kiernan 		len -= cnt;
234*ecaab0fbSStephen J. Kiernan 	}
235*ecaab0fbSStephen J. Kiernan 
236*ecaab0fbSStephen J. Kiernan 	/* Receive the length of the reply data */
237*ecaab0fbSStephen J. Kiernan 	id = vmware_guestrpc_recv_len(chan, &len);
238*ecaab0fbSStephen J. Kiernan 	if (id == -1)
239*ecaab0fbSStephen J. Kiernan 		goto done;
240*ecaab0fbSStephen J. Kiernan 
241*ecaab0fbSStephen J. Kiernan 	/* Receive the reply data */
242*ecaab0fbSStephen J. Kiernan 	sbuf_clear(sbufp);
243*ecaab0fbSStephen J. Kiernan 	while (len > 0) {
244*ecaab0fbSStephen J. Kiernan 		status = vmware_guestrpc_recv_data(chan, id, &data);
245*ecaab0fbSStephen J. Kiernan 		if (status == -1)
246*ecaab0fbSStephen J. Kiernan 			goto done;
247*ecaab0fbSStephen J. Kiernan 		sbuf_bcat(sbufp, &data, 4);
248*ecaab0fbSStephen J. Kiernan 		len -= min(4, len);
249*ecaab0fbSStephen J. Kiernan 	}
250*ecaab0fbSStephen J. Kiernan 
251*ecaab0fbSStephen J. Kiernan done:
252*ecaab0fbSStephen J. Kiernan 	/* Close the GuestRPC channel */
253*ecaab0fbSStephen J. Kiernan 	vmware_guestrpc_close(chan);
254*ecaab0fbSStephen J. Kiernan 	return (status == -1 ? EIO : 0);
255*ecaab0fbSStephen J. Kiernan }
256*ecaab0fbSStephen J. Kiernan 
257*ecaab0fbSStephen J. Kiernan /*
258*ecaab0fbSStephen J. Kiernan  * Set guest information key/value pair
259*ecaab0fbSStephen J. Kiernan  */
260*ecaab0fbSStephen J. Kiernan int
vmware_guestrpc_set_guestinfo(const char * keyword,const char * val)261*ecaab0fbSStephen J. Kiernan vmware_guestrpc_set_guestinfo(const char *keyword, const char *val)
262*ecaab0fbSStephen J. Kiernan {
263*ecaab0fbSStephen J. Kiernan 	struct sbuf sb;
264*ecaab0fbSStephen J. Kiernan 	char *buf;
265*ecaab0fbSStephen J. Kiernan 	int error;
266*ecaab0fbSStephen J. Kiernan 
267*ecaab0fbSStephen J. Kiernan #ifdef DEBUG_VMGUESTRPC
268*ecaab0fbSStephen J. Kiernan 	printf("%s: %s=%s\n", __func__, keyword, val);
269*ecaab0fbSStephen J. Kiernan #endif
270*ecaab0fbSStephen J. Kiernan 
271*ecaab0fbSStephen J. Kiernan 	/* Send "info-set" GuestRPC command */
272*ecaab0fbSStephen J. Kiernan 	sbuf_new(&sb, NULL, 256, SBUF_AUTOEXTEND);
273*ecaab0fbSStephen J. Kiernan 	sbuf_printf(&sb, "info-set guestinfo.fbsd.%s %s", keyword, val);
274*ecaab0fbSStephen J. Kiernan 	sbuf_trim(&sb);
275*ecaab0fbSStephen J. Kiernan 	sbuf_finish(&sb);
276*ecaab0fbSStephen J. Kiernan 
277*ecaab0fbSStephen J. Kiernan 	error = vmware_guestrpc_cmd(&sb);
278*ecaab0fbSStephen J. Kiernan 	if (error)
279*ecaab0fbSStephen J. Kiernan 		return (error);
280*ecaab0fbSStephen J. Kiernan 
281*ecaab0fbSStephen J. Kiernan 	sbuf_finish(&sb);
282*ecaab0fbSStephen J. Kiernan 	buf = sbuf_data(&sb);
283*ecaab0fbSStephen J. Kiernan 
284*ecaab0fbSStephen J. Kiernan #ifdef DEBUG_VMGUESTRPC
285*ecaab0fbSStephen J. Kiernan 	printf("%s: result: %s\n", __func__, buf);
286*ecaab0fbSStephen J. Kiernan #endif
287*ecaab0fbSStephen J. Kiernan 
288*ecaab0fbSStephen J. Kiernan 	/* Buffer will contain 1 on sucess or 0 on failure */
289*ecaab0fbSStephen J. Kiernan 	return ((buf[0] == '0') ? EINVAL : 0);
290*ecaab0fbSStephen J. Kiernan }
291*ecaab0fbSStephen J. Kiernan 
292*ecaab0fbSStephen J. Kiernan /*
293*ecaab0fbSStephen J. Kiernan  * Get guest information key/value pair.
294*ecaab0fbSStephen J. Kiernan  */
295*ecaab0fbSStephen J. Kiernan int
vmware_guestrpc_get_guestinfo(const char * keyword,struct sbuf * sbufp)296*ecaab0fbSStephen J. Kiernan vmware_guestrpc_get_guestinfo(const char *keyword, struct sbuf *sbufp)
297*ecaab0fbSStephen J. Kiernan {
298*ecaab0fbSStephen J. Kiernan 	struct sbuf sb;
299*ecaab0fbSStephen J. Kiernan 	char *buf;
300*ecaab0fbSStephen J. Kiernan 	int error;
301*ecaab0fbSStephen J. Kiernan 
302*ecaab0fbSStephen J. Kiernan #ifdef DEBUG_VMGUESTRPC
303*ecaab0fbSStephen J. Kiernan 	printf("%s: %s\n", __func__, keyword);
304*ecaab0fbSStephen J. Kiernan #endif
305*ecaab0fbSStephen J. Kiernan 
306*ecaab0fbSStephen J. Kiernan 	/* Send "info-get" GuestRPC command */
307*ecaab0fbSStephen J. Kiernan 	sbuf_new(&sb, NULL, 256, SBUF_AUTOEXTEND);
308*ecaab0fbSStephen J. Kiernan 	sbuf_printf(&sb, "info-get guestinfo.fbsd.%s", keyword);
309*ecaab0fbSStephen J. Kiernan 	sbuf_trim(&sb);
310*ecaab0fbSStephen J. Kiernan 	sbuf_finish(&sb);
311*ecaab0fbSStephen J. Kiernan 
312*ecaab0fbSStephen J. Kiernan 	error = vmware_guestrpc_cmd(&sb);
313*ecaab0fbSStephen J. Kiernan 	if (error)
314*ecaab0fbSStephen J. Kiernan 		return (error);
315*ecaab0fbSStephen J. Kiernan 
316*ecaab0fbSStephen J. Kiernan 	sbuf_finish(&sb);
317*ecaab0fbSStephen J. Kiernan 	buf = sbuf_data(&sb);
318*ecaab0fbSStephen J. Kiernan 
319*ecaab0fbSStephen J. Kiernan #ifdef DEBUG_VMGUESTRPC
320*ecaab0fbSStephen J. Kiernan 	printf("%s: result: %s\n", __func__, buf);
321*ecaab0fbSStephen J. Kiernan #endif
322*ecaab0fbSStephen J. Kiernan 
323*ecaab0fbSStephen J. Kiernan 	/*
324*ecaab0fbSStephen J. Kiernan 	 * Buffer will contain "1 <value>" on success or
325*ecaab0fbSStephen J. Kiernan 	 * "0 No value found" on failure
326*ecaab0fbSStephen J. Kiernan 	 */
327*ecaab0fbSStephen J. Kiernan 	if (buf[0] == '0')
328*ecaab0fbSStephen J. Kiernan 		return (ENOENT);
329*ecaab0fbSStephen J. Kiernan 
330*ecaab0fbSStephen J. Kiernan 	/*
331*ecaab0fbSStephen J. Kiernan 	 * Add value from buffer to the sbuf
332*ecaab0fbSStephen J. Kiernan 	 */
333*ecaab0fbSStephen J. Kiernan 	sbuf_cat(sbufp, buf + 2);
334*ecaab0fbSStephen J. Kiernan 	return (0);
335*ecaab0fbSStephen J. Kiernan }
336*ecaab0fbSStephen J. Kiernan 
337*ecaab0fbSStephen J. Kiernan MODULE_VERSION(vmware_guestrpc, 1);
338