1 /* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */ 2 3 #include "inc.h" 4 5 #define CMD_XFER 0x1E /* vmware backdoor transfer command */ 6 7 enum { 8 XFER_OPEN, /* open transfer channel */ 9 XFER_SENDLEN, /* specify length of data to send */ 10 XFER_SEND, /* send data */ 11 XFER_RECVLEN, /* get length of data to receive */ 12 XFER_RECV, /* receive data */ 13 XFER_RECVACK, /* acknowledge receipt of data */ 14 XFER_CLOSE /* close transfer channel */ 15 }; 16 17 #define STATUS(p) (HIWORD((p)[2]) & 0xff) 18 19 /*===========================================================================* 20 * channel_open * 21 *===========================================================================*/ 22 int channel_open( 23 struct channel *ch, /* struct describing the new channel */ 24 u32_t type /* channel type: CH_IN or CH_OUT */ 25 ) 26 { 27 /* Open a new backdoor channel. Upon success, the given channel structure will 28 * be filled with information and can be used in subsequent channel calls. 29 * Return OK on success, or a negative error code on error. 30 */ 31 u32_t ptr[6]; 32 33 ptr[1] = type | 0x80000000; 34 ptr[2] = MAKELONG(CMD_XFER, XFER_OPEN); 35 36 backdoor(ptr); 37 38 if ((STATUS(ptr) & 1) == 0) return EIO; 39 40 ch->id = HIWORD(ptr[3]); 41 ch->cookie1 = ptr[4]; 42 ch->cookie2 = ptr[5]; 43 44 return OK; 45 } 46 47 /*===========================================================================* 48 * channel_close * 49 *===========================================================================*/ 50 void channel_close( 51 struct channel *ch /* backdoor channel to close */ 52 ) 53 { 54 /* Close a previously opened backdoor channel. 55 */ 56 u32_t ptr[6]; 57 58 ptr[2] = MAKELONG(CMD_XFER, XFER_CLOSE); 59 ptr[3] = MAKELONG(0, ch->id); 60 ptr[4] = ch->cookie1; 61 ptr[5] = ch->cookie2; 62 63 backdoor(ptr); 64 } 65 66 /*===========================================================================* 67 * channel_send * 68 *===========================================================================*/ 69 int channel_send( 70 struct channel *ch, /* backdoor channel to send to */ 71 char *buf, /* buffer to send data from */ 72 int len /* size of the data to send */ 73 ) 74 { 75 /* Receive data over a backdoor channel. Return OK on success, or a negative 76 * error code on error. 77 */ 78 u32_t ptr[7]; 79 80 ptr[1] = len; 81 ptr[2] = MAKELONG(CMD_XFER, XFER_SENDLEN); 82 ptr[3] = MAKELONG(0, ch->id); 83 ptr[4] = ch->cookie1; 84 ptr[5] = ch->cookie2; 85 86 backdoor(ptr); 87 88 if ((STATUS(ptr) & 1) == 0) return EIO; 89 90 if (len == 0) return OK; 91 92 ptr[1] = MAKELONG(0, 1); 93 ptr[2] = len; 94 ptr[3] = MAKELONG(0, ch->id); 95 ptr[4] = (u32_t)buf; 96 ptr[5] = ch->cookie2; 97 ptr[6] = ch->cookie1; 98 99 backdoor_out(ptr); 100 101 return OK; 102 } 103 104 /*===========================================================================* 105 * channel_recv * 106 *===========================================================================*/ 107 int channel_recv( 108 struct channel *ch, /* backdoor channel to receive from */ 109 char *buf, /* buffer to receive data into */ 110 int max /* size of the buffer */ 111 ) 112 { 113 /* Receive data on a backdoor channel. Return the number of bytes received, or 114 * a negative error code on error. 115 */ 116 u32_t ptr[7]; 117 int len; 118 119 ptr[2] = MAKELONG(CMD_XFER, XFER_RECVLEN); 120 ptr[3] = MAKELONG(0, ch->id); 121 ptr[4] = ch->cookie1; 122 ptr[5] = ch->cookie2; 123 124 backdoor(ptr); 125 126 if ((STATUS(ptr) & 0x81) == 0) return EIO; 127 128 if ((len = ptr[1]) == 0 || (STATUS(ptr) & 3) == 1) return 0; 129 130 if (len > max) return E2BIG; 131 132 ptr[1] = MAKELONG(0, 1); 133 ptr[2] = len; 134 ptr[3] = MAKELONG(0, ch->id); 135 ptr[4] = ch->cookie1; 136 ptr[5] = (u32_t)buf; 137 ptr[6] = ch->cookie2; 138 139 backdoor_in(ptr); 140 141 ptr[1] = 1; 142 ptr[2] = MAKELONG(CMD_XFER, XFER_RECVACK); 143 ptr[3] = MAKELONG(0, ch->id); 144 ptr[4] = ch->cookie1; 145 ptr[5] = ch->cookie2; 146 147 backdoor(ptr); 148 149 return len; 150 } 151