1 // SPDX-License-Identifier: MIT 2 /* Copyright (C) 2006-2017 Oracle Corporation */ 3 4 #include <linux/vbox_err.h> 5 #include "vbox_drv.h" 6 #include "vboxvideo_guest.h" 7 #include "vboxvideo_vbe.h" 8 #include "hgsmi_channels.h" 9 #include "hgsmi_ch_setup.h" 10 11 /** 12 * hgsmi_report_flags_location - Inform the host of the location of 13 * the host flags in VRAM via an HGSMI cmd. 14 * Return: 0 or negative errno value. 15 * @ctx: The context of the guest heap to use. 16 * @location: The offset chosen for the flags within guest VRAM. 17 */ 18 int hgsmi_report_flags_location(struct gen_pool *ctx, u32 location) 19 { 20 struct hgsmi_buffer_location *p; 21 22 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_HGSMI, 23 HGSMI_CC_HOST_FLAGS_LOCATION); 24 if (!p) 25 return -ENOMEM; 26 27 p->buf_location = location; 28 p->buf_len = sizeof(struct hgsmi_host_flags); 29 30 hgsmi_buffer_submit(ctx, p); 31 hgsmi_buffer_free(ctx, p); 32 33 return 0; 34 } 35 36 /** 37 * hgsmi_send_caps_info - Notify the host of HGSMI-related guest capabilities 38 * via an HGSMI command. 39 * Return: 0 or negative errno value. 40 * @ctx: The context of the guest heap to use. 41 * @caps: The capabilities to report, see vbva_caps. 42 */ 43 int hgsmi_send_caps_info(struct gen_pool *ctx, u32 caps) 44 { 45 struct vbva_caps *p; 46 47 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, VBVA_INFO_CAPS); 48 if (!p) 49 return -ENOMEM; 50 51 p->rc = VERR_NOT_IMPLEMENTED; 52 p->caps = caps; 53 54 hgsmi_buffer_submit(ctx, p); 55 56 WARN_ON_ONCE(p->rc < 0); 57 58 hgsmi_buffer_free(ctx, p); 59 60 return 0; 61 } 62 63 int hgsmi_test_query_conf(struct gen_pool *ctx) 64 { 65 u32 value = 0; 66 int ret; 67 68 ret = hgsmi_query_conf(ctx, U32_MAX, &value); 69 if (ret) 70 return ret; 71 72 return value == U32_MAX ? 0 : -EIO; 73 } 74 75 /** 76 * hgsmi_query_conf - Query the host for an HGSMI configuration 77 * parameter via an HGSMI command. 78 * Return: 0 or negative errno value. 79 * @ctx: The context containing the heap used. 80 * @index: The index of the parameter to query. 81 * @value_ret: Where to store the value of the parameter on success. 82 */ 83 int hgsmi_query_conf(struct gen_pool *ctx, u32 index, u32 *value_ret) 84 { 85 struct vbva_conf32 *p; 86 87 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, 88 VBVA_QUERY_CONF32); 89 if (!p) 90 return -ENOMEM; 91 92 p->index = index; 93 p->value = U32_MAX; 94 95 hgsmi_buffer_submit(ctx, p); 96 97 *value_ret = p->value; 98 99 hgsmi_buffer_free(ctx, p); 100 101 return 0; 102 } 103 104 /** 105 * hgsmi_update_pointer_shape - Pass the host a new mouse pointer shape 106 * via an HGSMI command. 107 * Return: 0 or negative errno value. 108 * @ctx: The context containing the heap to be used. 109 * @flags: Cursor flags. 110 * @hot_x: Horizontal position of the hot spot. 111 * @hot_y: Vertical position of the hot spot. 112 * @width: Width in pixels of the cursor. 113 * @height: Height in pixels of the cursor. 114 * @pixels: Pixel data, @see VMMDevReqMousePointer for the format. 115 * @len: Size in bytes of the pixel data. 116 */ 117 int hgsmi_update_pointer_shape(struct gen_pool *ctx, u32 flags, 118 u32 hot_x, u32 hot_y, u32 width, u32 height, 119 u8 *pixels, u32 len) 120 { 121 struct vbva_mouse_pointer_shape *p; 122 u32 pixel_len = 0; 123 int rc; 124 125 if (flags & VBOX_MOUSE_POINTER_SHAPE) { 126 /* 127 * Size of the pointer data: 128 * sizeof (AND mask) + sizeof (XOR_MASK) 129 */ 130 pixel_len = ((((width + 7) / 8) * height + 3) & ~3) + 131 width * 4 * height; 132 if (pixel_len > len) 133 return -EINVAL; 134 135 /* 136 * If shape is supplied, then always create the pointer visible. 137 * See comments in 'vboxUpdatePointerShape' 138 */ 139 flags |= VBOX_MOUSE_POINTER_VISIBLE; 140 } 141 142 /* 143 * The 4 extra bytes come from switching struct vbva_mouse_pointer_shape 144 * from having a 4 bytes fixed array at the end to using a proper VLA 145 * at the end. These 4 extra bytes were not subtracted from sizeof(*p) 146 * before the switch to the VLA, so this way the behavior is unchanged. 147 * Chances are these 4 extra bytes are not necessary but they are kept 148 * to avoid regressions. 149 */ 150 p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len + 4, HGSMI_CH_VBVA, 151 VBVA_MOUSE_POINTER_SHAPE); 152 if (!p) 153 return -ENOMEM; 154 155 p->result = VINF_SUCCESS; 156 p->flags = flags; 157 p->hot_X = hot_x; 158 p->hot_y = hot_y; 159 p->width = width; 160 p->height = height; 161 if (pixel_len) 162 memcpy(p->data, pixels, pixel_len); 163 164 hgsmi_buffer_submit(ctx, p); 165 166 switch (p->result) { 167 case VINF_SUCCESS: 168 rc = 0; 169 break; 170 case VERR_NO_MEMORY: 171 rc = -ENOMEM; 172 break; 173 case VERR_NOT_SUPPORTED: 174 rc = -EBUSY; 175 break; 176 default: 177 rc = -EINVAL; 178 } 179 180 hgsmi_buffer_free(ctx, p); 181 182 return rc; 183 } 184 185 /** 186 * hgsmi_cursor_position - Report the guest cursor position. The host may 187 * wish to use this information to re-position its 188 * own cursor (though this is currently unlikely). 189 * The current host cursor position is returned. 190 * Return: 0 or negative errno value. 191 * @ctx: The context containing the heap used. 192 * @report_position: Are we reporting a position? 193 * @x: Guest cursor X position. 194 * @y: Guest cursor Y position. 195 * @x_host: Host cursor X position is stored here. Optional. 196 * @y_host: Host cursor Y position is stored here. Optional. 197 */ 198 int hgsmi_cursor_position(struct gen_pool *ctx, bool report_position, 199 u32 x, u32 y, u32 *x_host, u32 *y_host) 200 { 201 struct vbva_cursor_position *p; 202 203 p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA, 204 VBVA_CURSOR_POSITION); 205 if (!p) 206 return -ENOMEM; 207 208 p->report_position = report_position; 209 p->x = x; 210 p->y = y; 211 212 hgsmi_buffer_submit(ctx, p); 213 214 *x_host = p->x; 215 *y_host = p->y; 216 217 hgsmi_buffer_free(ctx, p); 218 219 return 0; 220 } 221