1 /*
2 * Copyright (C) 2006-2017 Oracle Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "vbox_drv.h"
24 #include "vbox_err.h"
25 #include "vboxvideo_guest.h"
26 #include "vboxvideo_vbe.h"
27 #include "hgsmi_channels.h"
28 #include "hgsmi_ch_setup.h"
29
30 /**
31 * Inform the host of the location of the host flags in VRAM via an HGSMI cmd.
32 * @param ctx the context of the guest heap to use.
33 * @param location the offset chosen for the flags within guest VRAM.
34 * @returns 0 on success, -errno on failure
35 */
hgsmi_report_flags_location(struct gen_pool * ctx,u32 location)36 int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location)
37 {
38 struct hgsmi_buffer_location *p;
39
40 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI,
41 HGSMI_CC_HOST_FLAGS_LOCATION);
42 if (!p)
43 return -ENOMEM;
44
45 p->buf_location = location;
46 p->buf_len = sizeof(struct hgsmi_host_flags);
47
48 hgsmi_buffer_submit(ctx, p);
49 hgsmi_buffer_free(ctx, p);
50
51 return 0;
52 }
53
54 /**
55 * Notify the host of HGSMI-related guest capabilities via an HGSMI command.
56 * @param ctx the context of the guest heap to use.
57 * @param caps the capabilities to report, see vbva_caps.
58 * @returns 0 on success, -errno on failure
59 */
hgsmi_send_caps_info(struct gen_pool * ctx,u32 caps)60 int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps)
61 {
62 struct vbva_caps *p;
63
64 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS);
65 if (!p)
66 return -ENOMEM;
67
68 p->rc = VERR_NOT_IMPLEMENTED;
69 p->caps = caps;
70
71 hgsmi_buffer_submit(ctx, p);
72
73 WARN_ON_ONCE(RT_FAILURE(p->rc));
74
75 hgsmi_buffer_free(ctx, p);
76
77 return 0;
78 }
79
hgsmi_test_query_conf(struct gen_pool * ctx)80 int hgsmi_test_query_conf(struct gen_pool *ctx)
81 {
82 u32 value = 0;
83 int ret;
84
85 ret = hgsmi_query_conf(ctx, U32_MAX, &value);
86 if (ret)
87 return ret;
88
89 return value == U32_MAX ? 0 : -EIO;
90 }
91
92 /**
93 * Query the host for an HGSMI configuration parameter via an HGSMI command.
94 * @param ctx the context containing the heap used
95 * @param index the index of the parameter to query,
96 * @see vbva_conf32::index
97 * @param value_ret where to store the value of the parameter on success
98 * @returns 0 on success, -errno on failure
99 */
hgsmi_query_conf(struct gen_pool * ctx,u32 index,u32 * value_ret)100 int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret)
101 {
102 struct vbva_conf32 *p;
103
104 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
105 VBVA_QUERY_CONF32);
106 if (!p)
107 return -ENOMEM;
108
109 p->index = index;
110 p->value = U32_MAX;
111
112 hgsmi_buffer_submit(ctx, p);
113
114 *value_ret = p->value;
115
116 hgsmi_buffer_free(ctx, p);
117
118 return 0;
119 }
120
121 /**
122 * Pass the host a new mouse pointer shape via an HGSMI command.
123 *
124 * @param ctx the context containing the heap to be used
125 * @param flags cursor flags, @see VMMDevReqMousePointer::flags
126 * @param hot_x horizontal position of the hot spot
127 * @param hot_y vertical position of the hot spot
128 * @param width width in pixels of the cursor
129 * @param height height in pixels of the cursor
130 * @param pixels pixel data, @see VMMDevReqMousePointer for the format
131 * @param len size in bytes of the pixel data
132 * @returns 0 on success, -errno on failure
133 */
hgsmi_update_pointer_shape(struct gen_pool * ctx,u32 flags,u32 hot_x,u32 hot_y,u32 width,u32 height,u8 * pixels,u32 len)134 int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags,
135 u32 hot_x, u32 hot_y, u32 width, u32 height,
136 u8 *pixels, u32 len)
137 {
138 struct vbva_mouse_pointer_shape *p;
139 u32 pixel_len = 0;
140 int rc;
141
142 if (flags & VBOX_MOUSE_POINTER_SHAPE) {
143 /*
144 * Size of the pointer data:
145 * sizeof (AND mask) + sizeof (XOR_MASK)
146 */
147 pixel_len = ((((width + 7) / 8) * height + 3) & ~3) +
148 width * 4 * height;
149 if (pixel_len > len)
150 return -EINVAL;
151
152 /*
153 * If shape is supplied, then always create the pointer visible.
154 * See comments in 'vboxUpdatePointerShape'
155 */
156 flags |= VBOX_MOUSE_POINTER_VISIBLE;
157 }
158
159 p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
160 VBVA_MOUSE_POINTER_SHAPE);
161 if (!p)
162 return -ENOMEM;
163
164 p->result = VINF_SUCCESS;
165 p->flags = flags;
166 p->hot_X = hot_x;
167 p->hot_y = hot_y;
168 p->width = width;
169 p->height = height;
170 if (pixel_len)
171 memcpy(p->data, pixels, pixel_len);
172
173 hgsmi_buffer_submit(ctx, p);
174
175 switch (p->result) {
176 case VINF_SUCCESS:
177 rc = 0;
178 break;
179 case VERR_NO_MEMORY:
180 rc = -ENOMEM;
181 break;
182 case VERR_NOT_SUPPORTED:
183 rc = -EBUSY;
184 break;
185 default:
186 rc = -EINVAL;
187 }
188
189 hgsmi_buffer_free(ctx, p);
190
191 return rc;
192 }
193
194 /**
195 * Report the guest cursor position. The host may wish to use this information
196 * to re-position its own cursor (though this is currently unlikely). The
197 * current host cursor position is returned.
198 * @param ctx The context containing the heap used.
199 * @param report_position Are we reporting a position?
200 * @param x Guest cursor X position.
201 * @param y Guest cursor Y position.
202 * @param x_host Host cursor X position is stored here. Optional.
203 * @param y_host Host cursor Y position is stored here. Optional.
204 * @returns 0 on success, -errno on failure
205 */
hgsmi_cursor_position(struct gen_pool * ctx,bool report_position,u32 x,u32 y,u32 * x_host,u32 * y_host)206 int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position,
207 u32 x, u32 y, u32 *x_host, u32 *y_host)
208 {
209 struct vbva_cursor_position *p;
210
211 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
212 VBVA_CURSOR_POSITION);
213 if (!p)
214 return -ENOMEM;
215
216 p->report_position = report_position;
217 p->x = x;
218 p->y = y;
219
220 hgsmi_buffer_submit(ctx, p);
221
222 *x_host = p->x;
223 *y_host = p->y;
224
225 hgsmi_buffer_free(ctx, p);
226
227 return 0;
228 }
229
230 /**
231 * @todo Mouse pointer position to be read from VMMDev memory, address of the
232 * memory region can be queried from VMMDev via an IOCTL. This VMMDev memory
233 * region will contain host information which is needed by the guest.
234 *
235 * Reading will not cause a switch to the host.
236 *
237 * Have to take into account:
238 * * synchronization: host must write to the memory only from EMT,
239 * large structures must be read under flag, which tells the host
240 * that the guest is currently reading the memory (OWNER flag?).
241 * * guest writes: may be allocate a page for the host info and make
242 * the page readonly for the guest.
243 * * the information should be available only for additions drivers.
244 * * VMMDev additions driver will inform the host which version of the info
245 * it expects, host must support all versions.
246 */
247