char-ringbuf.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * QEMU System Emulator
  3. *
  4. * Copyright (c) 2003-2008 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "chardev/char.h"
  26. #include "qmp-commands.h"
  27. #include "qemu/base64.h"
  28. /* Ring buffer chardev */
  29. typedef struct {
  30. Chardev parent;
  31. size_t size;
  32. size_t prod;
  33. size_t cons;
  34. uint8_t *cbuf;
  35. } RingBufChardev;
  36. #define RINGBUF_CHARDEV(obj) \
  37. OBJECT_CHECK(RingBufChardev, (obj), TYPE_CHARDEV_RINGBUF)
  38. static size_t ringbuf_count(const Chardev *chr)
  39. {
  40. const RingBufChardev *d = RINGBUF_CHARDEV(chr);
  41. return d->prod - d->cons;
  42. }
  43. static int ringbuf_chr_write(Chardev *chr, const uint8_t *buf, int len)
  44. {
  45. RingBufChardev *d = RINGBUF_CHARDEV(chr);
  46. int i;
  47. if (!buf || (len < 0)) {
  48. return -1;
  49. }
  50. for (i = 0; i < len; i++) {
  51. d->cbuf[d->prod++ & (d->size - 1)] = buf[i];
  52. if (d->prod - d->cons > d->size) {
  53. d->cons = d->prod - d->size;
  54. }
  55. }
  56. return len;
  57. }
  58. static int ringbuf_chr_read(Chardev *chr, uint8_t *buf, int len)
  59. {
  60. RingBufChardev *d = RINGBUF_CHARDEV(chr);
  61. int i;
  62. qemu_mutex_lock(&chr->chr_write_lock);
  63. for (i = 0; i < len && d->cons != d->prod; i++) {
  64. buf[i] = d->cbuf[d->cons++ & (d->size - 1)];
  65. }
  66. qemu_mutex_unlock(&chr->chr_write_lock);
  67. return i;
  68. }
  69. static void char_ringbuf_finalize(Object *obj)
  70. {
  71. RingBufChardev *d = RINGBUF_CHARDEV(obj);
  72. g_free(d->cbuf);
  73. }
  74. static void qemu_chr_open_ringbuf(Chardev *chr,
  75. ChardevBackend *backend,
  76. bool *be_opened,
  77. Error **errp)
  78. {
  79. ChardevRingbuf *opts = backend->u.ringbuf.data;
  80. RingBufChardev *d = RINGBUF_CHARDEV(chr);
  81. d->size = opts->has_size ? opts->size : 65536;
  82. /* The size must be power of 2 */
  83. if (d->size & (d->size - 1)) {
  84. error_setg(errp, "size of ringbuf chardev must be power of two");
  85. return;
  86. }
  87. d->prod = 0;
  88. d->cons = 0;
  89. d->cbuf = g_malloc0(d->size);
  90. }
  91. void qmp_ringbuf_write(const char *device, const char *data,
  92. bool has_format, enum DataFormat format,
  93. Error **errp)
  94. {
  95. Chardev *chr;
  96. const uint8_t *write_data;
  97. int ret;
  98. gsize write_count;
  99. chr = qemu_chr_find(device);
  100. if (!chr) {
  101. error_setg(errp, "Device '%s' not found", device);
  102. return;
  103. }
  104. if (!CHARDEV_IS_RINGBUF(chr)) {
  105. error_setg(errp, "%s is not a ringbuf device", device);
  106. return;
  107. }
  108. if (has_format && (format == DATA_FORMAT_BASE64)) {
  109. write_data = qbase64_decode(data, -1,
  110. &write_count,
  111. errp);
  112. if (!write_data) {
  113. return;
  114. }
  115. } else {
  116. write_data = (uint8_t *)data;
  117. write_count = strlen(data);
  118. }
  119. ret = ringbuf_chr_write(chr, write_data, write_count);
  120. if (write_data != (uint8_t *)data) {
  121. g_free((void *)write_data);
  122. }
  123. if (ret < 0) {
  124. error_setg(errp, "Failed to write to device %s", device);
  125. return;
  126. }
  127. }
  128. char *qmp_ringbuf_read(const char *device, int64_t size,
  129. bool has_format, enum DataFormat format,
  130. Error **errp)
  131. {
  132. Chardev *chr;
  133. uint8_t *read_data;
  134. size_t count;
  135. char *data;
  136. chr = qemu_chr_find(device);
  137. if (!chr) {
  138. error_setg(errp, "Device '%s' not found", device);
  139. return NULL;
  140. }
  141. if (!CHARDEV_IS_RINGBUF(chr)) {
  142. error_setg(errp, "%s is not a ringbuf device", device);
  143. return NULL;
  144. }
  145. if (size <= 0) {
  146. error_setg(errp, "size must be greater than zero");
  147. return NULL;
  148. }
  149. count = ringbuf_count(chr);
  150. size = size > count ? count : size;
  151. read_data = g_malloc(size + 1);
  152. ringbuf_chr_read(chr, read_data, size);
  153. if (has_format && (format == DATA_FORMAT_BASE64)) {
  154. data = g_base64_encode(read_data, size);
  155. g_free(read_data);
  156. } else {
  157. /*
  158. * FIXME should read only complete, valid UTF-8 characters up
  159. * to @size bytes. Invalid sequences should be replaced by a
  160. * suitable replacement character. Except when (and only
  161. * when) ring buffer lost characters since last read, initial
  162. * continuation characters should be dropped.
  163. */
  164. read_data[size] = 0;
  165. data = (char *)read_data;
  166. }
  167. return data;
  168. }
  169. static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
  170. Error **errp)
  171. {
  172. int val;
  173. ChardevRingbuf *ringbuf;
  174. backend->type = CHARDEV_BACKEND_KIND_RINGBUF;
  175. ringbuf = backend->u.ringbuf.data = g_new0(ChardevRingbuf, 1);
  176. qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));
  177. val = qemu_opt_get_size(opts, "size", 0);
  178. if (val != 0) {
  179. ringbuf->has_size = true;
  180. ringbuf->size = val;
  181. }
  182. }
  183. static void char_ringbuf_class_init(ObjectClass *oc, void *data)
  184. {
  185. ChardevClass *cc = CHARDEV_CLASS(oc);
  186. cc->parse = qemu_chr_parse_ringbuf;
  187. cc->open = qemu_chr_open_ringbuf;
  188. cc->chr_write = ringbuf_chr_write;
  189. }
  190. static const TypeInfo char_ringbuf_type_info = {
  191. .name = TYPE_CHARDEV_RINGBUF,
  192. .parent = TYPE_CHARDEV,
  193. .class_init = char_ringbuf_class_init,
  194. .instance_size = sizeof(RingBufChardev),
  195. .instance_finalize = char_ringbuf_finalize,
  196. };
  197. /* Bug-compatibility: */
  198. static const TypeInfo char_memory_type_info = {
  199. .name = TYPE_CHARDEV_MEMORY,
  200. .parent = TYPE_CHARDEV_RINGBUF,
  201. };
  202. static void register_types(void)
  203. {
  204. type_register_static(&char_ringbuf_type_info);
  205. type_register_static(&char_memory_type_info);
  206. }
  207. type_init(register_types);