1 /* netrpc.c - server to perform lv1 and device ops via network requests
3 Copyright (C) 2010-2011 Hector Martin "marcan" <hector@marcansoft.com>
5 This code is licensed to you under the terms of the GNU GPL, version 2;
6 see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
23 extern volatile u64 _thread1_release
;
24 extern volatile u64 _thread1_vector
;
49 typedef s64 (*rpc_callfn
) (u64
,u64
,u64
,u64
,u64
,u64
,u64
,u64
);
76 struct rpc_vec vector
;
86 } __attribute__((packed
));
88 static struct udp_pcb
*pcb
;
94 static struct pbuf
*outbuf
;
98 static void sendbuf(int len
, struct ip_addr
*addr
, u16_t port
)
100 outbuf
->tot_len
= len
;
103 err_t err
= udp_sendto(pcb
, outbuf
, addr
, port
);
104 // reclaim the header space used by udp_send
105 pbuf_header(outbuf
, -(outbuf
->len
- len
));
106 outbuf
->tot_len
= BUFSIZE
;
107 outbuf
->len
= BUFSIZE
;
109 printf("netrpc: udp_sendto() returned %d\n", err
);
112 void memcpy64(u64
*dst
, u64
*src
, s32 size
)
120 void memcpy32(u32
*dst
, u32
*src
, s32 size
)
128 void memcpy16(u16
*dst
, u16
*src
, s32 size
)
136 void memset64(u64
*dst
, u64 val
, s32 size
)
144 void memset32(u32
*dst
, u32 val
, s32 size
)
152 void memset16(u16
*dst
, u16 val
, s32 size
)
160 void memcpy_align(void *dst
, void *src
, u32 size
)
162 u64 t
= ((u64
)dst
)|((u64
)src
)|size
;
165 memcpy64(dst
, src
, size
);
166 } else if ((t
&3) == 0) {
167 memcpy32(dst
, src
, size
);
168 } else if ((t
&1) == 0) {
169 memcpy16(dst
, src
, size
);
171 memcpy(dst
, src
, size
);
175 void memset_align(void *dst
, u64 val
, u32 size
)
177 u64 t
= ((u64
)dst
)|size
;
180 memset64(dst
, val
, size
);
181 } else if ((t
&3) == 0) {
182 memset32(dst
, val
, size
);
183 } else if ((t
&1) == 0) {
184 memset16(dst
, val
, size
);
186 memset(dst
, val
, size
);
190 static u8 tmpbuf
[XFERSIZE
] __attribute__((aligned(64)));
192 static u64
*vector
[3] = {NULL
,NULL
,NULL
};
194 static void netrpc_vector(void *vec0
, void *vec1
, void *copy_dst
, void *copy_src
, u32 copy_size
)
198 mm_shutdown_highmem();
201 printf("netrpc: Relocating vectors...\n");
202 memcpy(copy_dst
, copy_src
, copy_size
);
203 sync_before_exec(copy_dst
, copy_size
);
205 printf("netrpc: Letting thread1 run loose...\n");
206 _thread1_vector
= (u64
)vec1
;
207 _thread1_release
= 1;
209 printf("netrpc: Taking the plunge...\n");
211 ((void (*)(void))vector
)();
215 static void netrpc_recv(void *arg
, struct udp_pcb
*upcb
, struct pbuf
*p
, struct ip_addr
*addr
, u16_t port
)
217 if (p
->tot_len
> BUFSIZE
) {
218 printf("netrpc: max buffer size exceeded (%d)\n", p
->tot_len
);
222 u8
*buf
= outbuf
->payload
;
223 pbuf_copy_partial(p
, buf
, BUFSIZE
, 0);
225 struct rpc_header
*hdr
= (void*)buf
;
232 struct rpc_vec vector
;
236 hdr
->reply
.retcode
= 0;
237 sendbuf(REPLY_SIZE
, addr
, port
);
240 if (hdr
->memop
.size
> XFERSIZE
) {
241 printf("netrpc: READMEM size > %d (%d)\n", XFERSIZE
, hdr
->memop
.size
);
242 hdr
->reply
.retcode
= -1;
243 sendbuf(REPLY_SIZE
, addr
, port
);
246 size
= hdr
->memop
.size
;
247 memcpy_align(tmpbuf
, hdr
->memop
.addr
, size
);
248 memcpy(hdr
->reply
.retdata
, tmpbuf
, size
);
249 hdr
->reply
.retcode
= 0;
250 sendbuf(REPLY_SIZE
+ size
, addr
, port
);
253 if (hdr
->memop
.size
> XFERSIZE
) {
254 printf("netrpc: WRITEMEM size > %d (%d)\n", XFERSIZE
, hdr
->memop
.size
);
255 hdr
->reply
.retcode
= -1;
256 sendbuf(REPLY_SIZE
, addr
, port
);
259 memcpy(tmpbuf
, hdr
->memop
.data
, hdr
->memop
.size
);
260 memcpy_align(hdr
->memop
.addr
, tmpbuf
, hdr
->memop
.size
);
261 hdr
->reply
.retcode
= 0;
262 sendbuf(REPLY_SIZE
, addr
, port
);
265 memcpy(&val
, hdr
->memop
.data
, sizeof(u64
));
266 memset_align(hdr
->memop
.addr
, val
, hdr
->memop
.size
);
267 hdr
->reply
.retcode
= 0;
268 sendbuf(REPLY_SIZE
, addr
, port
);
271 if (hdr
->hvcall
.numout
> 7) {
272 printf("netrpc: HVCALL numout > 7 (%d)\n", hdr
->hvcall
.numout
);
273 hdr
->reply
.retcode
= -100;
274 sendbuf(REPLY_SIZE
, addr
, port
);
277 if (hdr
->hvcall
.numin
> 8) {
278 printf("netrpc: HVCALL numin > 8 (%d)\n", hdr
->hvcall
.numin
);
279 hdr
->reply
.retcode
= -100;
280 sendbuf(REPLY_SIZE
, addr
, port
);
283 numout
= hdr
->hvcall
.numout
;
284 memcpy(regs
, hdr
->hvcall
.regs
, hdr
->hvcall
.numin
*8);
285 regs
[8] = hdr
->hvcall
.code
;
287 hdr
->reply
.retcode
= regs
[0];
288 memcpy(hdr
->reply
.retdata
, ®s
[1], numout
*8);
289 sendbuf(REPLY_SIZE
+numout
*8, addr
, port
);
292 hdr
->reply
.retcode
= mm_addmmio(hdr
->addmmio
.start
, hdr
->addmmio
.size
);
293 sendbuf(REPLY_SIZE
, addr
, port
);
296 hdr
->reply
.retcode
= mm_delmmio(hdr
->addmmio
.start
);
297 sendbuf(REPLY_SIZE
, addr
, port
);
300 hdr
->reply
.retcode
= mm_clrmmio();
301 sendbuf(REPLY_SIZE
, addr
, port
);
304 vector
= hdr
->vector
;
305 printf("netrpc: vector called (%p,%p %p,%p,0x%x)...\n", vector
.vec0
, vector
.vec1
, vector
.copy_dst
, vector
.copy_src
, vector
.copy_size
);
306 hdr
->reply
.retcode
= 0;
307 sendbuf(REPLY_SIZE
, addr
, port
);
308 netrpc_vector(vector
.vec0
, vector
.vec1
, vector
.copy_dst
, vector
.copy_src
, vector
.copy_size
);
311 sync_before_exec(hdr
->sync
.addr
, hdr
->sync
.size
);
312 hdr
->reply
.retcode
= 0;
313 sendbuf(REPLY_SIZE
, addr
, port
);
316 hdr
->reply
.retcode
= hdr
->call
.addr(hdr
->call
.args
[0], hdr
->call
.args
[1],
317 hdr
->call
.args
[2], hdr
->call
.args
[3],
318 hdr
->call
.args
[4], hdr
->call
.args
[5],
319 hdr
->call
.args
[6], hdr
->call
.args
[7]);
320 sendbuf(REPLY_SIZE
, addr
, port
);
323 printf("netrpc: Unknown RPC command 0x%x\n", hdr
->cmd
);
324 hdr
->reply
.retcode
= -1;
325 sendbuf(REPLY_SIZE
, addr
, port
);
331 void netrpc_init(void)
335 fatal("netrpc: Could not allocate PCB for netrpc");
336 outbuf
= pbuf_alloc(PBUF_TRANSPORT
, BUFSIZE
, PBUF_RAM
);
338 fatal("netrpc: Could not allocate buffer");
340 udp_bind(pcb
, IP_ADDR_ANY
, PORT
);
341 udp_recv(pcb
, netrpc_recv
, NULL
);
342 printf("netrpc: initialized\n");
344 void netrpc_shutdown(void)
346 printf("netrpc: shutting down\n");
353 printf("netrpc: shutdown complete\n");