1
/*********************************************************
2
* Copyright (C) 2010 VMware, Inc. All rights reserved.
4
* This program is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU Lesser General Public License as published
6
* by the Free Software Foundation version 2.1 and no later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10
* or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public
11
* License for more details.
13
* You should have received a copy of the GNU Lesser General Public License
14
* along with this program; if not, write to the Free Software Foundation, Inc.,
15
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17
*********************************************************/
20
* hgfsServerPacketUtil.c --
22
* Utility functions for manipulating packet used by hgfs server code
29
#include "hgfsServer.h"
30
#include "hgfsServerInt.h"
33
#define LOGLEVEL_MODULE hgfs
34
#include "loglevel_user.h"
38
*-----------------------------------------------------------------------------
40
* HSPU_GetReplyPacket --
42
* Get a reply packet given an hgfs packet.
43
* Guest mappings may be established.
46
* Pointer to reply packet.
49
* Buffer may be allocated.
50
*-----------------------------------------------------------------------------
54
HSPU_GetReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
55
size_t *replyPacketSize, // IN/OUT: Size of reply Packet
56
HgfsSessionInfo *session) // IN: Session Info
59
if (packet->replyPacket) {
61
* When we are transferring packets over backdoor, reply packet
62
* is a static buffer. Backdoor should always return from here.
64
LOG(4, ("Exising reply packet %s %Zu %Zu\n", __FUNCTION__,
65
*replyPacketSize, packet->replyPacketSize));
67
* HgfsServer_ProcessPacket does not tell us the real size of packetOut.
68
* It assumes that size of reply packet can never be bigger than size of
69
* the outgoing packet. I changed it to HGFS_LARGE_PACKET_MAX.
71
ASSERT_DEVEL(*replyPacketSize <= packet->replyPacketSize);
72
} else if (session->channelCbTable && session->channelCbTable->getWriteVa) {
73
/* Can we write directly into guest memory ? */
74
if (packet->metaPacket) {
75
LOG(10, ("%s Using meta packet for reply packet\n", __FUNCTION__));
76
ASSERT_DEVEL(*replyPacketSize <= packet->metaPacketSize);
77
packet->replyPacket = packet->metaPacket;
78
packet->replyPacketSize = packet->metaPacketSize;
80
/* This should really never happen in existing scenarios */
82
LOG(10, ("%s Mapping meta packet for reply packet\n", __FUNCTION__));
83
packet->replyPacket = HSPU_GetBuf(packet, 0, &packet->metaPacket,
84
packet->metaPacketSize,
85
&packet->metaPacketIsAllocated,
89
* Really this can never happen, we would have caught bad physical address
90
* during getMetaPacket.
92
ASSERT(packet->replyPacket);
93
packet->replyPacketSize = packet->metaPacketSize;
96
/* For sockets channel we always need to allocate buffer */
97
LOG(10, ("%s Allocating reply packet\n", __FUNCTION__));
98
packet->replyPacket = Util_SafeMalloc(*replyPacketSize);
99
packet->replyPacketIsAllocated = TRUE;
100
packet->replyPacketSize = *replyPacketSize;
103
*replyPacketSize = packet->replyPacketSize;
104
return packet->replyPacket;
109
*-----------------------------------------------------------------------------
111
* HSPU_PutReplyPacket --
113
* Free buffer if reply packet was allocated.
120
*-----------------------------------------------------------------------------
124
HSPU_PutReplyPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
125
HgfsSessionInfo *session) // IN: Session Info
127
if (packet->replyPacketIsAllocated) {
128
LOG(10, ("%s Freeing reply packet", __FUNCTION__));
129
free(packet->replyPacket);
130
packet->replyPacketIsAllocated = FALSE;
131
packet->replyPacket = NULL;
132
packet->replyPacketSize = 0;
138
*-----------------------------------------------------------------------------
140
* HSPU_GetMetaPacket --
142
* Get a meta packet given an hgfs packet.
143
* Guest mappings will be established.
146
* Pointer to meta packet.
149
* Buffer may be allocated.
150
*-----------------------------------------------------------------------------
154
HSPU_GetMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
155
size_t *metaPacketSize, // OUT: Size of metaPacket
156
HgfsSessionInfo *session) // IN: Session Info
158
*metaPacketSize = packet->metaPacketSize;
159
return HSPU_GetBuf(packet, 0, &packet->metaPacket,
160
packet->metaPacketSize,
161
&packet->metaPacketIsAllocated,
162
HGFS_BUF_WRITEABLE, session);
167
*-----------------------------------------------------------------------------
169
* HSPU_GetDataPacketIov --
171
* Get a data packet in an iov form given an hgfs packet.
172
* Guest mappings will be established.
175
* Pointer to data packet iov.
178
* Buffer may be allocated.
179
*-----------------------------------------------------------------------------
183
HSPU_GetDataPacketIov(HgfsPacket *packet, // IN/OUT: Hgfs Packet
184
HgfsSessionInfo *session, // IN: Session Info
185
HgfsVaIov iov) // OUT: I/O vector
194
*-----------------------------------------------------------------------------
196
* HSPU_GetDataPacketBuf --
198
* Get a data packet given an hgfs packet.
199
* Guest mappings will be established.
202
* Pointer to data packet.
205
* Buffer may be allocated.
206
*-----------------------------------------------------------------------------
210
HSPU_GetDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
211
uint32 mappingType, // IN: Writeable/Readable
212
HgfsSessionInfo *session) // IN: Session Info
214
packet->dataMappingType = mappingType;
215
return HSPU_GetBuf(packet, packet->dataPacketIovIndex,
216
&packet->dataPacket, packet->dataPacketSize,
217
&packet->dataPacketIsAllocated, mappingType, session);
222
*-----------------------------------------------------------------------------
226
* Get a {meta, data} packet given an hgfs packet.
227
* Guest mappings will be established.
233
* Buffer may be allocated.
234
*-----------------------------------------------------------------------------
238
HSPU_GetBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
239
uint32 startIndex, // IN: start index of iov
240
void **buf, // OUT: Contigous buffer
241
size_t bufSize, // IN: Size of buffer
242
Bool *isAllocated, // OUT: Was buffer allocated ?
243
uint32 mappingType, // IN: Readable/Writeable ?
244
HgfsSessionInfo *session) // IN: Session Info
247
uint32 iovMapped = 0;
248
int32 size = bufSize;
250
void* (*func)(uint64, uint32, char **);
255
} else if (bufSize == 0) {
259
ASSERT_DEVEL(session->channelCbTable);
260
if (!session->channelCbTable) {
264
if (mappingType == HGFS_BUF_WRITEABLE) {
265
func = session->channelCbTable->getWriteVa;
267
ASSERT(mappingType == HGFS_BUF_READABLE);
268
func = session->channelCbTable->getReadVa;
276
/* Establish guest memory mappings */
277
for (iovCount = startIndex; iovCount < packet->iovCount && size > 0;
280
packet->iov[iovCount].token = NULL;
282
/* Debugging check: Iov in VMCI should never cross page boundary */
283
ASSERT_DEVEL(packet->iov[iovCount].len <=
284
(4096 - (packet->iov[iovCount].pa & 0xfff)));
286
packet->iov[iovCount].va = func(packet->iov[iovCount].pa,
287
packet->iov[iovCount].len,
288
&packet->iov[iovCount].token);
289
ASSERT_DEVEL(packet->iov[iovCount].va);
290
if (packet->iov[iovCount].va == NULL) {
291
/* Guest probably passed us bad physical address */
296
size -= packet->iov[iovCount].len;
300
/* Seems like more than one page was requested. */
301
uint32 copiedAmount = 0;
305
ASSERT_DEVEL(packet->iov[startIndex].len < bufSize);
306
*buf = Util_SafeMalloc(bufSize);
309
LOG(10, ("%s: Hgfs Allocating buffer \n", __FUNCTION__));
312
* Since we are allocating seperate buffer, it does not make sense
313
* to continue to hold on to mappings. Let's release it, we will
314
* reacquire mappings when we need in HSPU_CopyBufToIovec.
316
remainingSize = bufSize;
317
for (i = startIndex; i < packet->iovCount && remainingSize > 0; i++) {
318
copyAmount = remainingSize < packet->iov[i].len ?
319
remainingSize : packet->iov[i].len;
320
memcpy((char *)*buf + copiedAmount, packet->iov[i].va, copyAmount);
321
copiedAmount += copyAmount;
322
remainingSize -= copyAmount;
324
ASSERT_DEVEL(copiedAmount == bufSize);
326
/* We will continue to hold on to guest mappings */
327
*buf = packet->iov[startIndex].va;
332
for (i = 0; i < iovCount; i++) {
333
session->channelCbTable->putVa(&packet->iov[i].token);
334
packet->iov[i].va = NULL;
342
*-----------------------------------------------------------------------------
344
* HSPU_PutMetaPacket --
346
* Free meta packet buffer if allocated.
347
* Guest mappings will be released.
354
*-----------------------------------------------------------------------------
358
HSPU_PutMetaPacket(HgfsPacket *packet, // IN/OUT: Hgfs Packet
359
HgfsSessionInfo *session) // IN: Session Info
361
LOG(4, ("%s Hgfs Putting Meta packet\n", __FUNCTION__));
362
HSPU_PutBuf(packet, 0, &packet->metaPacket,
363
&packet->metaPacketSize,
364
&packet->metaPacketIsAllocated,
365
HGFS_BUF_WRITEABLE, session);
370
*-----------------------------------------------------------------------------
372
* HSPU_PutDataPacketIov --
374
* Free data packet Iov if allocated.
380
* Guest mappings will be released.
381
*-----------------------------------------------------------------------------
385
HSPU_PutDataPacketIov()
392
*-----------------------------------------------------------------------------
394
* HSPU_PutDataPacketBuf --
396
* Free data packet buffer if allocated.
397
* Guest mappings will be released.
404
*-----------------------------------------------------------------------------
408
HSPU_PutDataPacketBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
409
HgfsSessionInfo *session) // IN: Session Info
412
LOG(4, ("%s Hgfs Putting Data packet\n", __FUNCTION__));
413
HSPU_PutBuf(packet, packet->dataPacketIovIndex,
414
&packet->dataPacket, &packet->dataPacketSize,
415
&packet->dataPacketIsAllocated,
416
packet->dataMappingType, session);
421
*-----------------------------------------------------------------------------
425
* Free buffer if allocated and release guest mappings.
432
*-----------------------------------------------------------------------------
436
HSPU_PutBuf(HgfsPacket *packet, // IN/OUT: Hgfs Packet
437
uint32 startIndex, // IN: Start of iov
438
void **buf, // IN/OUT: Buffer to be freed
439
size_t *bufSize, // IN: Size of the buffer
440
Bool *isAllocated, // IN: Was buffer allocated ?
441
uint32 mappingType, // IN: Readable / Writeable ?
442
HgfsSessionInfo *session) // IN: Session info
448
if (!session->channelCbTable) {
452
if (!session->channelCbTable->putVa || *buf == NULL) {
457
if (mappingType == HGFS_BUF_WRITEABLE) {
458
HSPU_CopyBufToIovec(packet, startIndex, *buf, *bufSize, session);
460
LOG(10, ("%s: Hgfs Freeing buffer \n", __FUNCTION__));
462
*isAllocated = FALSE;
464
for (iovCount = startIndex;
465
iovCount < packet->iovCount && size > 0;
467
ASSERT_DEVEL(packet->iov[iovCount].token);
468
session->channelCbTable->putVa(&packet->iov[iovCount].token);
469
size -= packet->iov[iovCount].len;
471
LOG(10, ("%s: Hgfs bufSize = %d \n", __FUNCTION__, size));
480
*-----------------------------------------------------------------------------
482
* HSPU_CopyBufToMetaIovec --
484
* Write out buffer to data Iovec.
490
* @iov is populated with contents of @buf
491
*-----------------------------------------------------------------------------
495
HSPU_CopyBufToMetaIovec(HgfsPacket *packet, // IN/OUT: Hgfs packet
496
void *buf, // IN: Buffer to copy from
497
size_t bufSize, // IN: Size of buffer
498
HgfsSessionInfo *session)// IN: Session Info
500
HSPU_CopyBufToIovec(packet, 0, buf, bufSize, session);
505
*-----------------------------------------------------------------------------
507
* HSPU_CopyBufToDataIovec --
509
* Write out buffer to data Iovec.
515
* @iov is populated with contents of @buf
516
*-----------------------------------------------------------------------------
520
HSPU_CopyBufToDataIovec(HgfsPacket *packet, // IN: Hgfs packet
521
void *buf, // IN: Buffer to copy from
522
uint32 bufSize, // IN: Size of buffer
523
HgfsSessionInfo *session)
525
HSPU_CopyBufToIovec(packet, packet->dataPacketIovIndex, buf, bufSize,
531
*-----------------------------------------------------------------------------
533
* HSPU_CopyBufToDataIovec --
535
* Write out buffer to data Iovec.
541
* @iov is populated with contents of @buf
542
*-----------------------------------------------------------------------------
546
HSPU_CopyBufToIovec(HgfsPacket *packet, // IN/OUT: Hgfs Packet
547
uint32 startIndex, // IN: start index into iov
548
void *buf, // IN: Contigous Buffer
549
size_t bufSize, // IN: Size of buffer
550
HgfsSessionInfo *session) // IN: Session Info
553
size_t remainingSize = bufSize;
555
size_t copiedAmount = 0;
560
if (!session->channelCbTable) {
564
ASSERT_DEVEL(session->channelCbTable->getWriteVa);
565
if (!session->channelCbTable->getWriteVa) {
569
for (iovCount = startIndex; iovCount < packet->iovCount
570
&& remainingSize > 0; iovCount++) {
571
copyAmount = remainingSize < packet->iov[iovCount].len ?
572
remainingSize: packet->iov[iovCount].len;
574
packet->iov[iovCount].token = NULL;
576
/* Debugging check: Iov in VMCI should never cross page boundary */
577
ASSERT_DEVEL(packet->iov[iovCount].len <=
578
(4096 - (packet->iov[iovCount].pa & 0xfff)));
580
packet->iov[iovCount].va = session->channelCbTable->getWriteVa(packet->iov[iovCount].pa,
581
packet->iov[iovCount].len,
582
&packet->iov[iovCount].token);
583
ASSERT_DEVEL(packet->iov[iovCount].va);
584
if (packet->iov[iovCount].va != NULL) {
585
memcpy(packet->iov[iovCount].va, (char *)buf + copiedAmount, copyAmount);
586
session->channelCbTable->putVa(&packet->iov[iovCount].token);
587
remainingSize -= copyAmount;
588
copiedAmount += copyAmount;
594
ASSERT_DEVEL(remainingSize == 0);