1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27#include <string.h>
28#include <stdio.h>
29#include <stdarg.h>
30#include <ctype.h>
31#include <assert.h>
32
33#include "vchost.h"
34
35#include "interface/vcos/vcos.h"
36#include "interface/vchi/vchi.h"
37#include "interface/vchi/common/endian.h"
38
39#include "vc_vchi_filesys.h"
40#include "interface/vmcs_host/vc_vchi_fileservice_defs.h"
41
42/******************************************************************************
43Global data.
44******************************************************************************/
45
46/******************************************************************************
47Local types and defines.
48******************************************************************************/
49typedef enum {
50 VC_SECTOR_IO_NONE,
51 VC_SECTOR_IO_READING,
52 VC_SECTOR_IO_WRITING
53} VC_SECTOR_IO_T;
54
55typedef struct {
56
57 VCHI_SERVICE_HANDLE_T open_handle;
58
59 int32_t num_connections;
60
61 //Host->2727
62 FILESERV_MSG_T fileserv_msg;
63
64 //2727->Host XXX
65 FILESERV_MSG_T vc_msg;
66
67 VCOS_THREAD_T filesys_thread;
68
69 // used to signal response has arrived
70 VCOS_EVENT_T response_event;
71
72 //we lock each vc_filesys function call
73 VCOS_MUTEX_T filesys_lock;
74
75 //used to signal msg arrivals
76 VCOS_EVENT_T filesys_msg_avail;
77
78 // Outstanding transaction's ID
79 volatile uint32_t cur_xid;
80
81 // Copy of the header code from responses
82 int32_t resp_code;
83 int32_t err_no;
84
85 char *bulk_buffer;
86 int32_t initialised;
87
88} FILESYS_SERVICE_T;
89
90static FILESYS_SERVICE_T vc_filesys_client;
91
92
93/******************************************************************************
94Static functions.
95******************************************************************************/
96
97//Lock the host state
98static __inline int32_t lock_obtain (void) {
99 int ret = -1;
100 if(vc_filesys_client.initialised && vcos_mutex_lock(&vc_filesys_client.filesys_lock) == VCOS_SUCCESS) {
101 vchi_service_use(vc_filesys_client.open_handle);
102 ret = 0;
103 }
104 return ret;
105}
106
107//Unlock the host state
108static __inline void lock_release (void) {
109 vcos_assert(vc_filesys_client.initialised);
110 vchi_service_release(vc_filesys_client.open_handle);
111 vcos_mutex_unlock(&vc_filesys_client.filesys_lock);
112}
113
114// File Service VCHI functions
115
116static int vchi_msg_stub(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len );
117
118static int vchi_msg_stub_noblock(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len);
119
120static int vc_fs_message_handler( FILESERV_MSG_T* msg, uint32_t nbytes );
121
122static void *filesys_task_func(void *arg);
123
124static void filesys_callback( void *callback_param, VCHI_CALLBACK_REASON_T reason, void *msg_handle );
125
126
127
128#ifdef PRINTF
129#ifdef WIN32
130#define printf tprintf
131#endif
132static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
133 struct file_service_msg_body const * body);
134#endif
135static int fs_host_direntbytestream_create(struct dirent *d, void *buffer);
136static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer);
137
138/*---------------------------------------------------------------------------*/
139
140/******************************************************************************
141NAME
142 vc_filesys_init
143
144SYNOPSIS
145 vc_filesys_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections ) {
146
147FUNCTION
148 Initialise the file system for use. A negative return value
149 indicates failure (which may mean it has not been started on VideoCore).
150
151RETURNS
152 int
153******************************************************************************/
154int vc_vchi_filesys_init (VCHI_INSTANCE_T initialise_instance, VCHI_CONNECTION_T **connections, uint32_t num_connections )
155{
156 int32_t success = 0;
157 SERVICE_CREATION_T filesys_parameters;
158 VCOS_THREAD_ATTR_T attrs;
159 VCOS_STATUS_T status;
160
161 // record the number of connections
162 memset( &vc_filesys_client, 0, sizeof(FILESYS_SERVICE_T) );
163 vc_filesys_client.num_connections = num_connections;
164
165 if(!vcos_verify(vc_filesys_client.num_connections < 2))
166 return -1;
167
168 status = vcos_mutex_create(&vc_filesys_client.filesys_lock, "HFilesys");
169 vcos_assert(status == VCOS_SUCCESS);
170
171 status = vcos_event_create(&vc_filesys_client.filesys_msg_avail, "HFilesys");
172 vcos_assert(status == VCOS_SUCCESS);
173
174 //create sema used to signal cmd response has arrived
175 status = vcos_event_create(&vc_filesys_client.response_event, "HFilesys");
176 vcos_assert(status == VCOS_SUCCESS);
177
178 vc_filesys_client.bulk_buffer = vcos_malloc_aligned(FILESERV_MAX_BULK, 16, "HFilesys bulk_recv");
179 vc_filesys_client.cur_xid = 0;
180
181 memset(&filesys_parameters, 0, sizeof(filesys_parameters));
182 filesys_parameters.service_id = FILESERV_4CC; // 4cc service code
183 filesys_parameters.connection = connections[0]; // passed in fn ptrs
184 filesys_parameters.rx_fifo_size = 0; // rx fifo size (unused)
185 filesys_parameters.tx_fifo_size = 0; // tx fifo size (unused)
186 filesys_parameters.callback = &filesys_callback;
187 filesys_parameters.callback_param = &vc_filesys_client.filesys_msg_avail;
188 filesys_parameters.want_unaligned_bulk_rx = 0;
189 filesys_parameters.want_unaligned_bulk_tx = 0;
190 filesys_parameters.want_crc = 0;
191 filesys_parameters.version.version = VC_FILESERV_VER;
192 filesys_parameters.version.version_min = VC_FILESERV_VER;
193
194 success = vchi_service_open( initialise_instance, &filesys_parameters, &vc_filesys_client.open_handle );
195 vcos_assert( success == 0 );
196
197 vcos_thread_attr_init(&attrs);
198 vcos_thread_attr_setstacksize(&attrs, 4000);
199 vcos_thread_attr_settimeslice(&attrs, 1);
200
201 vc_filesys_client.initialised = 1;
202
203 status = vcos_thread_create(&vc_filesys_client.filesys_thread, "HFilesys", &attrs, filesys_task_func, NULL);
204 vcos_assert(status == VCOS_SUCCESS);
205
206 /* Not using service immediately - release videocore */
207 vchi_service_release(vc_filesys_client.open_handle);
208
209 return (int)success;
210}
211
212static void *filesys_task_func(void *arg)
213{
214 int32_t success;
215 uint32_t msg_len;
216
217 (void)arg;
218
219 vc_hostfs_init();
220
221 while(1) {
222 // wait for the semaphore to say that there is a message
223 if (vcos_event_wait(&vc_filesys_client.filesys_msg_avail) != VCOS_SUCCESS || vc_filesys_client.initialised == 0)
224 break;
225
226 vchi_service_use(vc_filesys_client.open_handle);
227 // read the message - should we really "peek" this
228 while (1) {
229 success = vchi_msg_dequeue(vc_filesys_client.open_handle, &vc_filesys_client.vc_msg,
230 sizeof(vc_filesys_client.vc_msg), &msg_len, VCHI_FLAGS_NONE);
231 if (!success)
232 break;
233
234 /* coverity[tainted_string_argument] */
235 success = (int32_t) vc_fs_message_handler(&vc_filesys_client.vc_msg, msg_len);
236 (void)success;
237 }
238 vchi_service_release(vc_filesys_client.open_handle);
239 }
240
241 return 0;
242}
243
244
245/******************************************************************************
246NAME
247 filesys_callback
248
249SYNOPSIS
250 void filesys_callback( void *callback_param,
251 const VCHI_CALLBACK_REASON_T reason,
252 const void *msg_handle )
253
254FUNCTION
255 VCHI callback
256
257RETURNS
258 int
259******************************************************************************/
260static void filesys_callback( void *callback_param,
261 const VCHI_CALLBACK_REASON_T reason,
262 void *msg_handle )
263{
264 (void)msg_handle;
265
266 switch( reason ) {
267
268 case VCHI_CALLBACK_MSG_AVAILABLE:
269 {
270 VCOS_EVENT_T *event = (VCOS_EVENT_T *) callback_param;
271 if(event)
272 vcos_event_signal(event);
273 }
274 break;
275
276 case VCHI_CALLBACK_BULK_RECEIVED:
277 break;
278 case VCHI_CALLBACK_BULK_SENT:
279 break;
280
281 default:
282 return;
283 }
284}
285
286/******************************************************************************
287NAME
288 vc_filesys_stop
289
290SYNOPSIS
291 void vc_filesys_stop()
292
293FUNCTION
294 This tells us that the file system service has stopped, thereby preventing
295 any of the functions from doing anything.
296
297RETURNS
298 void
299******************************************************************************/
300
301void vc_filesys_stop ()
302{
303 int32_t result;
304 void *dummy;
305
306 if(lock_obtain() != 0)
307 return;
308
309 result = vchi_service_close(vc_filesys_client.open_handle);
310 vcos_assert(result == 0);
311
312 vc_filesys_client.initialised = 0;
313
314 vcos_event_signal(&vc_filesys_client.filesys_msg_avail);
315 vcos_thread_join(&vc_filesys_client.filesys_thread, &dummy);
316
317 vcos_event_delete(&vc_filesys_client.filesys_msg_avail);
318 vcos_event_delete(&vc_filesys_client.response_event);
319 vcos_mutex_delete(&vc_filesys_client.filesys_lock);
320
321 if(vc_filesys_client.bulk_buffer)
322 vcos_free(vc_filesys_client.bulk_buffer);
323}
324
325/******************************************************************************
326NAME
327 vc_filesys_single_param
328
329SYNOPSIS
330 int vc_filesys_single_param(uint32_t param, uint32_t fn)
331
332FUNCTION
333 Utility function for implementing filesys methods
334
335RETURNS
336 void
337******************************************************************************/
338static int vc_filesys_single_param(uint32_t param, uint32_t fn)
339{
340 int success = -1;
341
342 if(lock_obtain() == 0)
343 {
344 vc_filesys_client.fileserv_msg.params[0] = param;
345 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, fn, 4) == FILESERV_RESP_OK)
346 success = 0;
347
348 lock_release();
349 }
350
351 return success;
352}
353
354/******************************************************************************
355NAME
356 vc_filesys_single_string
357
358SYNOPSIS
359 int vc_filesys_single_string(uint32_t param, const char *str, uint32_t fn, int return_param)
360
361FUNCTION
362 Utility function for implementing filesys methods
363
364RETURNS
365 void
366******************************************************************************/
367static int vc_filesys_single_string(uint32_t param, const char *str, uint32_t fn, int return_param)
368{
369 int ret = -1;
370 int len = strlen(str);
371
372 if(len < FILESERV_MAX_DATA && lock_obtain() == 0)
373 {
374 vc_filesys_client.fileserv_msg.params[0] = param;
375 /* coverity[buffer_size_warning] - the length of str has already been checked */
376 strncpy((char*)vc_filesys_client.fileserv_msg.data, str, FILESERV_MAX_DATA);
377
378 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, fn, len+1+16) == FILESERV_RESP_OK)
379 {
380 if(return_param)
381 ret = (int) vc_filesys_client.fileserv_msg.params[0];
382 else
383 ret = 0;
384 }
385
386 lock_release();
387 }
388
389 return ret;
390}
391
392/* Standard UNIX low-level library functions (declared in unistd.h) */
393/******************************************************************************
394NAME
395 vc_filesys_close
396
397SYNOPSIS
398 int vc_filesys_close(int fildes)
399
400FUNCTION
401 Deallocates the file descriptor to a file.
402
403RETURNS
404 Successful completion: 0
405 Otherwise: -1
406******************************************************************************/
407
408int vc_filesys_close(int fildes)
409{
410 return vc_filesys_single_param((uint32_t) fildes, VC_FILESYS_CLOSE);
411}
412
413
414/******************************************************************************
415NAME
416 vc_filesys_lseek
417
418SYNOPSIS
419 long vc_filesys_lseek(int fildes, long offset, int whence)
420
421FUNCTION
422 Sets the file pointer associated with the open file specified by fildes.
423
424RETURNS
425 Successful completion: offset
426 Otherwise: -1
427******************************************************************************/
428
429long vc_filesys_lseek(int fildes, long offset, int whence)
430{
431 long set = -1;
432
433 if(lock_obtain() == 0)
434 {
435 vc_filesys_client.fileserv_msg.params[0] = (uint32_t) fildes;
436 vc_filesys_client.fileserv_msg.params[1] = (uint32_t) offset;
437 vc_filesys_client.fileserv_msg.params[2] = (uint32_t) whence;
438
439 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_LSEEK, 12) == FILESERV_RESP_OK)
440 set = (long) vc_filesys_client.fileserv_msg.params[0];
441
442 lock_release();
443 }
444
445 return set;
446}
447
448/******************************************************************************
449NAME
450 vc_filesys_lseek64
451
452SYNOPSIS
453 int64_t vc_filesys_lseek64(int fildes, int64_t offset, int whence)
454
455FUNCTION
456 Sets the file pointer associated with the open file specified by fildes.
457
458RETURNS
459 Successful completion: file pointer value
460 Otherwise: -1
461******************************************************************************/
462
463int64_t vc_filesys_lseek64(int fildes, int64_t offset, int whence)
464{
465 int64_t set = -1;
466
467 if(lock_obtain() == 0)
468 {
469 vc_filesys_client.fileserv_msg.params[0] = (uint32_t) fildes;
470 vc_filesys_client.fileserv_msg.params[1] = (uint32_t) offset; // LSB
471 vc_filesys_client.fileserv_msg.params[2] = (uint32_t)(offset >> 32); // MSB
472 vc_filesys_client.fileserv_msg.params[3] = (uint32_t) whence;
473
474 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_LSEEK64, 16) == FILESERV_RESP_OK)
475 {
476 set = vc_filesys_client.fileserv_msg.params[0];
477 set += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
478 }
479
480 lock_release();
481 }
482
483 return set;
484}
485
486/******************************************************************************
487NAME
488 vc_filesys_mount
489
490SYNOPSIS
491 int vc_filesys_mount(const char *device, const char *mountpoint, const char *options)
492
493FUNCTION
494 Mounts a filesystem at a given location
495
496RETURNS
497 Successful completion: 0
498******************************************************************************/
499
500int vc_filesys_mount(const char *device, const char *mountpoint, const char *options)
501{
502 int set = -1, len;
503 int a = strlen(device);
504 int b = strlen(mountpoint);
505 int c = strlen(options);
506
507 if(a + b + c + 3 < FILESERV_MAX_DATA && lock_obtain() == 0)
508 {
509 char *str = (char *) vc_filesys_client.fileserv_msg.data;
510
511 memcpy(str, device, a);
512 str[a] = 0;
513 memcpy(str+a+1, mountpoint, b);
514 str[a+1+b] = 0;
515 memcpy(str+a+b+2, options, c);
516 str[a+b+c+2] = 0;
517 len = a + b + c + 3 + (int)(((FILESERV_MSG_T *)0)->data);
518 len = ((len + (VCHI_BULK_GRANULARITY-1)) & ~(VCHI_BULK_GRANULARITY-1)) + VCHI_BULK_GRANULARITY;
519
520 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_MOUNT, len) == FILESERV_RESP_OK)
521 set = (int) vc_filesys_client.fileserv_msg.params[0];
522
523 lock_release();
524 }
525
526 return set;
527}
528
529/******************************************************************************
530NAME
531 vc_filesys_umount
532
533SYNOPSIS
534 int vc_filesys_mount(const char *mountpoint)
535
536FUNCTION
537 Un-mounts a removable device from the location that it has been mounted
538 to earlier in the session
539
540RETURNS
541 Successful completion: 0
542******************************************************************************/
543
544int vc_filesys_umount(const char *mountpoint)
545{
546 return vc_filesys_single_string(0, mountpoint, VC_FILESYS_UMOUNT, 1);
547}
548
549/******************************************************************************
550NAME
551 vc_filesys_open
552
553SYNOPSIS
554 int vc_filesys_open(const char *path, int vc_oflag)
555
556FUNCTION
557 Establishes a connection between a file and a file descriptor.
558
559RETURNS
560 Successful completion: file descriptor
561 Otherwise: -1
562******************************************************************************/
563
564int vc_filesys_open(const char *path, int vc_oflag)
565{
566 return vc_filesys_single_string((uint32_t) vc_oflag, path, VC_FILESYS_OPEN, 1);
567}
568
569
570/******************************************************************************
571NAME
572 vc_filesys_read
573
574SYNOPSIS
575 int vc_filesys_read(int fildes, void *buf, unsigned int nbyte)
576
577FUNCTION
578 Attempts to read nbyte bytes from the file associated with the file
579 descriptor, fildes, into the buffer pointed to by buf.
580
581RETURNS
582 Successful completion: number of bytes read
583 Otherwise: -1
584******************************************************************************/
585
586/******************************************************************************
587
588FUNCTION
589
590
591RETURNS
592 Successful completion: the number of bytes received
593 Otherwise negative error code
594******************************************************************************/
595static int vc_vchi_msg_bulk_read(FILESERV_MSG_T* msg, uint16_t cmd_id, uint32_t transfer_len, uint8_t* recv_addr )
596{
597 uint32_t i;
598 int msg_len;
599 uint32_t host_align_bytes;
600 uint32_t num_bytes_read;
601 int32_t success;
602
603 //this is current file_io_buffer size so assuming never more than this
604 //otherwise we will split the read into chunks
605 if(!vcos_verify(transfer_len <= FILESERV_MAX_BULK))
606 return -1;
607
608 //number of bytes required to align recv_addr
609 host_align_bytes = VCHI_BULK_ALIGN_NBYTES(recv_addr);
610
611 i = vc_filesys_client.cur_xid + 1;
612 i &= 0x7fffffffUL;
613 vc_filesys_client.cur_xid = i;
614
615 msg->xid = vc_filesys_client.cur_xid;
616
617 //fill in cmd id: VC_FILESYS_READ etc
618 msg->cmd_code = cmd_id;
619
620 msg->params[2] = transfer_len;
621
622 msg->params[3] = host_align_bytes;
623
624 //24 comes from the static size of FILESERV_MSG_T
625 msg_len = 24;
626
627 if(vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ) != 0)
628 return -1;
629
630 //wait to receive response
631 if(vcos_event_wait(&vc_filesys_client.response_event) != VCOS_SUCCESS || msg->cmd_code == FILESERV_RESP_ERROR)
632 return -1;
633
634 //total bytes read
635 num_bytes_read = msg->params[0];
636
637 if(!vcos_verify(num_bytes_read <= FILESERV_MAX_BULK))
638 return -1;
639
640 //everything is in msg->data
641 if(msg->cmd_code == FILESERV_RESP_OK) {
642 if(!vcos_verify(num_bytes_read <= FILESERV_MAX_DATA))
643 return -1;
644
645 memcpy(recv_addr, msg->data, num_bytes_read);
646 return (int) num_bytes_read;
647 }
648
649// Make this code conditional to stop Coverity complaining about dead code
650#if VCHI_BULK_ALIGN > 1
651 //copy host_align_bytes bytes to recv_addr, now ready for bulk
652 if(host_align_bytes) {
653 memcpy(recv_addr, msg->data, host_align_bytes);
654 recv_addr += host_align_bytes;
655 transfer_len -= host_align_bytes;
656 }
657#endif
658
659 //receive bulk from host
660 if(msg->cmd_code == FILESERV_BULK_WRITE){
661 //number of end bytes
662 uint32_t end_bytes = msg->params[1];
663 //calculate what portion of read transfer by bulk
664 uint32_t bulk_bytes = (num_bytes_read-host_align_bytes-end_bytes);
665
666 success = vchi_bulk_queue_receive(vc_filesys_client.open_handle,
667 recv_addr,
668 bulk_bytes,
669 VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
670 NULL );
671 if(!vcos_verify(success == 0))
672 return -1;
673
674 recv_addr+=bulk_bytes;
675
676 //copy any left over end bytes from original msg
677 if(end_bytes)
678 memcpy(recv_addr, &msg->data[host_align_bytes], end_bytes);
679 }
680 else {
681 return -1;
682 }
683
684 return (int) num_bytes_read;
685}
686
687
688int vc_filesys_read(int fildes, void *buf, unsigned int nbyte)
689{
690 int bulk_bytes = 0;
691 int actual_read = 0;
692 int total_byte = 0;
693 uint8_t* ptr = (uint8_t*)buf;
694
695 if (nbyte == 0) {
696 return 0;
697 }
698
699 if(lock_obtain() == 0)
700 {
701 do {
702 bulk_bytes = nbyte > FILESERV_MAX_BULK ? FILESERV_MAX_BULK : nbyte;
703
704 //we overwrite the response here so fill in data again
705 vc_filesys_client.fileserv_msg.params[0] = (uint32_t)fildes;
706 vc_filesys_client.fileserv_msg.params[1] = 0xffffffffU; // offset: use -1 to indicate no offset
707
708 actual_read = vc_vchi_msg_bulk_read(&vc_filesys_client.fileserv_msg , VC_FILESYS_READ, (uint32_t)bulk_bytes, (uint8_t*)ptr);
709
710 if(bulk_bytes != actual_read) {
711 if(actual_read < 0)
712 total_byte = -1;
713 else
714 total_byte += actual_read;
715 //exit loop
716 break;
717 }
718
719 ptr+=bulk_bytes;
720 nbyte -= actual_read;
721 total_byte += actual_read;
722 }while(nbyte > 0);
723
724 lock_release();
725 }
726
727 return total_byte;
728}
729
730/******************************************************************************
731NAME
732 vc_filesys_write
733
734SYNOPSIS
735 int vc_filesys_write(int fildes, const void *buf, unsigned int nbyte)
736
737FUNCTION
738 Attempts to write nbyte bytes from the buffer pointed to by buf to file
739 associated with the file descriptor, fildes.
740
741RETURNS
742 Successful completion: number of bytes written
743 Otherwise: -1
744******************************************************************************/
745
746/******************************************************************************
747
748FUNCTION
749
750
751RETURNS
752 Successful completion: the number of bytes received
753 Otherwise negative error code
754******************************************************************************/
755static int vc_vchi_msg_bulk_write(FILESERV_MSG_T* msg, uint16_t cmd_id, uint32_t transfer_len, uint8_t* send_addr )
756{
757 uint32_t i;
758 int msg_len;
759 uint32_t align_bytes = 0;
760 uint32_t bulk_end_bytes = 0;
761 uint32_t bulk_bytes = 0;
762 int num_bytes_written = -1;
763
764 //this is current file_io_buffer size so assuming never more than this
765 //otherwise we will split the read into chunks
766 if(!vcos_verify(transfer_len <= FILESERV_MAX_BULK))
767 return -1;
768
769 i = vc_filesys_client.cur_xid + 1;
770 i &= 0x7fffffffUL;
771 vc_filesys_client.cur_xid = i;
772
773 msg->xid = vc_filesys_client.cur_xid;
774
775 //fill in cmd id VC_FILESYS_OPEN etc
776 msg->cmd_code = cmd_id;
777
778 msg->params[2] = transfer_len;
779
780 //24 comes from the static size of FILESERV_MSG_T
781 msg_len = 24;
782
783 //put it all in one msg
784 if(transfer_len <= FILESERV_MAX_DATA) {
785 memcpy(msg->data, send_addr, transfer_len);
786 msg->params[3] = 0;
787 msg_len += transfer_len;
788 //send request to write to host
789 if(vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ) != 0)
790 return -1;
791
792 // wait to receive response
793 if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS &&
794 msg->cmd_code != FILESERV_RESP_ERROR && msg->params[0] == transfer_len)
795 {
796 //vc_fs_message_handler copies resp into outgoing msg struct
797 num_bytes_written = (int)msg->params[0];
798 }
799 }
800 else {
801 //required to make send_addr for bulk
802 align_bytes = VCHI_BULK_ALIGN_NBYTES(send_addr);
803
804// Make this code conditional to stop Coverity complaining about dead code
805#if VCHI_BULK_ALIGN > 1
806 //copy vc_align bytes to msg->data, send_addr ready for bulk
807 if(align_bytes) {
808 msg->params[3] = align_bytes;
809 memcpy(msg->data, send_addr, align_bytes);
810 transfer_len -= align_bytes;
811 send_addr += align_bytes;
812 msg_len += align_bytes;
813 }
814 else
815#endif
816 msg->params[3] = 0;
817
818 // need to ensure we have the appropriate alignment
819 bulk_bytes = (transfer_len)&(~(VCHI_BULK_GRANULARITY-1));
820
821 bulk_end_bytes = transfer_len-bulk_bytes;
822
823 if(bulk_end_bytes) {
824 memcpy(msg->data+align_bytes, send_addr+bulk_bytes, bulk_end_bytes);
825 msg_len += bulk_end_bytes;
826 }
827
828 //send request to write to host
829 if(vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL ) != 0)
830 return -1;
831
832 //send bulk VCHI_FLAGS_BLOCK_UNTIL_QUEUED is ok because we wait for response msg with actual length written
833 if(vchi_bulk_queue_transmit( vc_filesys_client.open_handle,
834 send_addr,
835 bulk_bytes,
836 VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
837 NULL ) != 0)
838 return -1;
839
840 // wait to receive response sent by filsys_task_func
841 if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS && msg->cmd_code == FILESERV_BULK_READ)
842 num_bytes_written = (int)msg->params[0];
843 }
844
845 return num_bytes_written;
846}
847
848
849int vc_filesys_write(int fildes, const void *buf, unsigned int nbyte)
850{
851 int num_wrt = 0;
852 int bulk_bytes = 0;
853 int actual_written = 0;
854 uint8_t *ptr = (uint8_t*) buf;
855
856 if (nbyte == 0) {
857 return 0;
858 }
859
860 if(lock_obtain() == 0)
861 {
862 //will split the read into 4K chunks based on vc fwrite buffer size array size
863 //we will make this more dynamic later
864 do {
865 bulk_bytes = nbyte > FILESERV_MAX_BULK ? FILESERV_MAX_BULK : nbyte;
866
867 //we overwrite the response here so fill in data again
868 vc_filesys_client.fileserv_msg.params[0] = (uint32_t)fildes;
869 vc_filesys_client.fileserv_msg.params[1] = 0xffffffffU; // offset: use -1 to indicate no offset
870
871 actual_written = vc_vchi_msg_bulk_write(&vc_filesys_client.fileserv_msg , VC_FILESYS_WRITE, (uint32_t)bulk_bytes, (uint8_t*)ptr);
872
873 if(bulk_bytes != actual_written) {
874 if(actual_written < 0)
875 num_wrt = -1;
876 else
877 num_wrt += actual_written;
878 break;
879 }
880
881 ptr+=bulk_bytes;
882 nbyte -= actual_written;
883 num_wrt += actual_written;
884 }while(nbyte > 0);
885
886 lock_release();
887 }
888
889 return num_wrt;
890}
891
892
893/* Directory management functions */
894
895/******************************************************************************
896NAME
897 vc_filesys_closedir
898
899SYNOPSIS
900 int vc_filesys_closedir(void *dhandle)
901
902FUNCTION
903 Ends a directory list iteration.
904
905RETURNS
906 Successful completion: 0
907 Otherwise: -1
908******************************************************************************/
909
910int vc_filesys_closedir(void *dhandle)
911{
912 return vc_filesys_single_param((uint32_t)dhandle, VC_FILESYS_CLOSEDIR);
913}
914
915
916/******************************************************************************
917NAME
918 vc_filesys_format
919
920SYNOPSIS
921 int vc_filesys_format(const char *path)
922
923FUNCTION
924 Formats the physical file system that contains path.
925
926RETURNS
927 Successful completion: 0
928 Otherwise: -1
929******************************************************************************/
930
931int vc_filesys_format(const char *path)
932{
933 return vc_filesys_single_string(0, path, VC_FILESYS_FORMAT, 0);
934}
935
936
937/******************************************************************************
938NAME
939 vc_filesys_freespace
940
941SYNOPSIS
942 int vc_filesys_freespace(const char *path)
943
944FUNCTION
945 Returns the amount of free space on the physical file system that contains
946 path.
947
948RETURNS
949 Successful completion: free space
950 Otherwise: -1
951******************************************************************************/
952
953int vc_filesys_freespace(const char *path)
954{
955 return vc_filesys_single_string(0, path, VC_FILESYS_FREESPACE, 1);
956}
957
958
959/******************************************************************************
960NAME
961 vc_filesys_freespace64
962
963SYNOPSIS
964 int64_t vc_filesys_freespace64(const char *path)
965
966FUNCTION
967 Returns the amount of free space on the physical file system that contains
968 path.
969
970RETURNS
971 Successful completion: free space
972 Otherwise: -1
973******************************************************************************/
974
975int64_t vc_filesys_freespace64(const char *path)
976{
977 int64_t freespace = -1LL;
978
979 if(lock_obtain() == 0)
980 {
981 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
982
983 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_FREESPACE64,
984 (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK)
985 {
986 freespace = vc_filesys_client.fileserv_msg.params[0];
987 freespace += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
988 }
989
990 lock_release();
991 }
992
993 return freespace;
994}
995
996
997/******************************************************************************
998NAME
999 vc_filesys_get_attr
1000
1001SYNOPSIS
1002 int vc_filesys_get_attr(const char *path, fattributes_t *attr)
1003
1004FUNCTION
1005 Gets the file/directory attributes.
1006
1007RETURNS
1008 Successful completion: 0
1009 Otherwise: -1
1010******************************************************************************/
1011
1012int vc_filesys_get_attr(const char *path, fattributes_t *attr)
1013{
1014 int success = -1;
1015
1016 if(lock_obtain() == 0)
1017 {
1018 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1019
1020 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_GET_ATTR,
1021 (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK)
1022 {
1023 success = 0;
1024 *attr = (fattributes_t) vc_filesys_client.fileserv_msg.params[0];
1025 }
1026
1027 lock_release();
1028 }
1029
1030 return success;
1031}
1032
1033
1034/******************************************************************************
1035NAME
1036 vc_filesys_fstat
1037
1038SYNOPSIS
1039 int64_t vc_filesys_fstat(int fildes, FSTAT_T *buf)
1040
1041FUNCTION
1042 Returns the file stat info structure for the specified file.
1043 This structure includes date and size info.
1044
1045RETURNS
1046 Successful completion: 0
1047 Otherwise: -1
1048******************************************************************************/
1049
1050int vc_filesys_fstat(int fildes, FSTAT_T *buf)
1051{
1052 int success = -1;
1053
1054 if (buf != NULL && lock_obtain() == 0)
1055 {
1056 vc_filesys_client.fileserv_msg.params[0] = (uint32_t) fildes;
1057 if ( vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_FSTAT, 4) == FILESERV_RESP_OK )
1058 {
1059 buf->st_size = (int64_t)vc_filesys_client.fileserv_msg.params[0]; // LSB
1060 buf->st_size |= (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32; // MSB
1061 buf->st_modtime = (uint32_t)vc_filesys_client.fileserv_msg.params[2];
1062 // there's room for expansion here to pass across more elements of the structure if required...
1063 success = 0;
1064 }
1065
1066 lock_release();
1067 }
1068
1069 return success;
1070}
1071
1072
1073/******************************************************************************
1074NAME
1075 vc_filesys_mkdir
1076
1077SYNOPSIS
1078 int vc_filesys_mkdir(const char *path)
1079
1080FUNCTION
1081 Creates a new directory named by the pathname pointed to by path.
1082
1083RETURNS
1084 Successful completion: 0
1085 Otherwise: -1
1086******************************************************************************/
1087
1088int vc_filesys_mkdir(const char *path)
1089{
1090 return vc_filesys_single_string(0, path, VC_FILESYS_MKDIR, 0);
1091}
1092
1093
1094/******************************************************************************
1095NAME
1096 vc_filesys_opendir
1097
1098SYNOPSIS
1099 void *vc_filesys_opendir(const char *dirname)
1100
1101FUNCTION
1102 Starts a directory list iteration.
1103
1104RETURNS
1105 Successful completion: dhandle (pointer)
1106 Otherwise: NULL
1107******************************************************************************/
1108
1109void *vc_filesys_opendir(const char *dirname)
1110{
1111 return (void *) vc_filesys_single_string(0, dirname, VC_FILESYS_OPENDIR, 1);
1112}
1113
1114
1115/******************************************************************************
1116NAME
1117 vc_filesys_dirsize
1118
1119SYNOPSIS
1120 int vc_filesys_dirsize(const char *path)
1121
1122FUNCTION
1123 Look through the specified directory tree and sum the file sizes.
1124
1125RETURNS
1126 Successful completion: 0
1127 Otherwise: -1
1128******************************************************************************/
1129
1130int64_t vc_filesys_dirsize(const char *path, uint32_t *num_files, uint32_t *num_dirs)
1131{
1132 int64_t ret = -1;
1133
1134 if(lock_obtain() == 0)
1135 {
1136 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1137
1138 // FIXME: Should probably use a non-blocking call here since it may take a
1139 // long time to do the operation...
1140 if ( vchi_msg_stub(&vc_filesys_client.fileserv_msg,
1141 VC_FILESYS_DIRSIZE,
1142 (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK )
1143 {
1144 ret = vc_filesys_client.fileserv_msg.params[0];
1145 ret += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
1146 if (num_files)
1147 *num_files = vc_filesys_client.fileserv_msg.params[2];
1148 if (num_dirs)
1149 *num_dirs = vc_filesys_client.fileserv_msg.params[3];
1150 }
1151
1152 lock_release();
1153 }
1154
1155 return ret;
1156}
1157
1158
1159/******************************************************************************
1160NAME
1161 vc_filesys_readdir_r
1162
1163SYNOPSIS
1164 struct dirent *vc_filesys_readdir_r(void *dhandle, struct dirent *result)
1165
1166FUNCTION
1167 Fills in the passed result structure with details of the directory entry
1168 at the current psition in the directory stream specified by the argument
1169 dhandle, and positions the directory stream at the next entry.
1170
1171RETURNS
1172 Successful completion: result
1173 End of directory stream: NULL
1174******************************************************************************/
1175
1176struct dirent *vc_filesys_readdir_r(void *dhandle, struct dirent *result)
1177{
1178 struct dirent *ret = NULL;
1179
1180 if(lock_obtain() == 0)
1181 {
1182 vc_filesys_client.fileserv_msg.params[0] = (uint32_t)dhandle;
1183 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_READDIR, 4) == FILESERV_RESP_OK)
1184 {
1185 fs_host_direntbytestream_interp(result, (void *)vc_filesys_client.fileserv_msg.data);
1186 ret = result;
1187 }
1188
1189 lock_release();
1190 }
1191
1192 return ret;
1193}
1194
1195
1196/******************************************************************************
1197NAME
1198 vc_filesys_remove
1199
1200SYNOPSIS
1201 int vc_filesys_remove(const char *path)
1202
1203FUNCTION
1204 Removes a file or a directory. A directory must be empty before it can be
1205 deleted.
1206
1207RETURNS
1208 Successful completion: 0
1209 Otherwise: -1
1210******************************************************************************/
1211
1212int vc_filesys_remove(const char *path)
1213{
1214 return vc_filesys_single_string(0, path, VC_FILESYS_REMOVE, 0);
1215}
1216
1217
1218/******************************************************************************
1219NAME
1220 vc_filesys_rename
1221
1222SYNOPSIS
1223 int vc_filesys_rename(const char *oldfile, const char *newfile)
1224
1225FUNCTION
1226 Changes the name of a file. The old and new pathnames must be on the same
1227 physical file system.
1228
1229RETURNS
1230 Successful completion: 0
1231 Otherwise: -1
1232******************************************************************************/
1233
1234int vc_filesys_rename(const char *oldfile, const char *newfile)
1235{
1236 int a, b, success = -1;
1237
1238 // Ensure the pathnames aren't too long
1239 if ((a = strlen(oldfile)) < FS_MAX_PATH && (b = strlen(newfile)) < FS_MAX_PATH && lock_obtain() == 0)
1240 {
1241 strncpy((char *)vc_filesys_client.fileserv_msg.data, oldfile, FS_MAX_PATH);
1242 strncpy((char *)&vc_filesys_client.fileserv_msg.data[a+1], newfile, FS_MAX_PATH);
1243
1244 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_RENAME, 16+a+1+b+1) == FILESERV_RESP_OK)
1245 success = 0;
1246
1247 lock_release();
1248 }
1249
1250 return success;
1251}
1252
1253
1254/******************************************************************************
1255NAME
1256 vc_filesys_reset
1257
1258SYNOPSIS
1259 int vc_filesys_reset()
1260
1261FUNCTION
1262 Send a vc_FILESYS_RESET command. This will return immediately.
1263
1264RETURNS
1265 Successful completion: FILESERV_RESP_OK
1266 Otherwise: -
1267******************************************************************************/
1268
1269int vc_filesys_reset()
1270{
1271 return vc_filesys_single_param(0, VC_FILESYS_RESET);
1272}
1273
1274
1275/******************************************************************************
1276NAME
1277 vc_filesys_set_attr
1278
1279SYNOPSIS
1280 int vc_filesys_set_attr(const char *path, fattributes_t attr)
1281
1282FUNCTION
1283 Sets file/directory attributes.
1284
1285RETURNS
1286 Successful completion: 0
1287 Otherwise: -1
1288******************************************************************************/
1289
1290int vc_filesys_set_attr(const char *path, fattributes_t attr)
1291{
1292 return vc_filesys_single_string((uint32_t) attr, path, VC_FILESYS_SET_ATTR, 0);
1293}
1294
1295
1296/******************************************************************************
1297NAME
1298 vc_filesys_setend
1299
1300SYNOPSIS
1301 int vc_filesys_setend(int fildes)
1302
1303FUNCTION
1304 Truncates file at current position.
1305
1306RETURNS
1307 Successful completion: 0
1308 Otherwise: -1
1309******************************************************************************/
1310
1311int vc_filesys_setend(int fildes)
1312{
1313 return vc_filesys_single_param((uint32_t) fildes, VC_FILESYS_SETEND);
1314}
1315
1316
1317
1318/******************************************************************************
1319NAME
1320 vc_filesys_scandisk
1321
1322SYNOPSIS
1323 void vc_filesys_scandisk(const char *path)
1324
1325FUNCTION
1326 Truncates file at current position.
1327
1328RETURNS
1329 -
1330******************************************************************************/
1331
1332void vc_filesys_scandisk(const char *path)
1333{
1334 vc_filesys_single_string(0, path, VC_FILESYS_SCANDISK, 0);
1335 return;
1336}
1337
1338/******************************************************************************
1339NAME
1340 vc_filesys_chkdsk
1341
1342SYNOPSIS
1343 int vc_filesys_chkdsk(const char *path, int fix_errors)
1344
1345FUNCTION
1346 Truncates file at current position.
1347
1348RETURNS
1349 -
1350******************************************************************************/
1351
1352int vc_filesys_chkdsk(const char *path, int fix_errors)
1353{
1354 return vc_filesys_single_string(fix_errors, path, VC_FILESYS_CHKDSK, 1);
1355}
1356
1357/******************************************************************************
1358NAME
1359 vc_filesys_size
1360
1361SYNOPSIS
1362 int vc_filesys_size(const char *path)
1363
1364FUNCTION
1365 return size of file
1366
1367RETURNS
1368 -
1369******************************************************************************/
1370
1371int vc_filesys_size(const char *path)
1372{
1373 int fd;
1374 int end_pos = 0;
1375 int success = -1;
1376 if((fd = vc_filesys_open(path, VC_O_RDONLY)) == 0)
1377 {
1378 end_pos = vc_filesys_lseek(fd, 0, SEEK_END);
1379 success = vc_filesys_close(fd);
1380 (void)success;
1381 }
1382
1383 return end_pos;
1384}
1385/******************************************************************************
1386NAME
1387 vc_filesys_totalspace
1388
1389SYNOPSIS
1390 int vc_filesys_totalspace(const char *path)
1391
1392FUNCTION
1393 Returns the total amount of space on the physical file system that contains
1394 path.
1395
1396RETURNS
1397 Successful completion: total space
1398 Otherwise: -1
1399******************************************************************************/
1400
1401int vc_filesys_totalspace(const char *path)
1402{
1403 return vc_filesys_single_string(0, path, VC_FILESYS_TOTALSPACE, 1);
1404}
1405
1406
1407/******************************************************************************
1408NAME
1409 vc_filesys_totalspace64
1410
1411SYNOPSIS
1412 int64_t vc_filesys_totalspace64(const char *path)
1413
1414FUNCTION
1415 Returns the total amount of space on the physical file system that contains
1416 path.
1417
1418RETURNS
1419 Successful completion: total space
1420 Otherwise: -1
1421******************************************************************************/
1422
1423int64_t vc_filesys_totalspace64(const char *path)
1424{
1425 int64_t totalspace = -1LL;
1426
1427 if(lock_obtain() == 0)
1428 {
1429 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1430
1431 if (vchi_msg_stub(&vc_filesys_client.fileserv_msg, VC_FILESYS_TOTALSPACE64,
1432 (int)(16+strlen((char *)vc_filesys_client.fileserv_msg.data)+1)) == FILESERV_RESP_OK)
1433 {
1434 totalspace = vc_filesys_client.fileserv_msg.params[0];
1435 totalspace += (int64_t)vc_filesys_client.fileserv_msg.params[1] << 32;
1436 }
1437
1438 lock_release();
1439 }
1440
1441 return totalspace;
1442}
1443
1444
1445/******************************************************************************
1446NAME
1447 vc_filesys_diskwritable
1448
1449SYNOPSIS
1450 int vc_filesys_diskwritable(const char *path)
1451
1452FUNCTION
1453 Return whether the named disk is writable.
1454
1455RETURNS
1456 Successful completion: 1 (disk writable) or 0 (disk not writable)
1457 Otherwise: -1
1458******************************************************************************/
1459
1460int vc_filesys_diskwritable(const char *path)
1461{
1462 return vc_filesys_single_string(0, path, VC_FILESYS_DISKWRITABLE, 1);
1463}
1464
1465/******************************************************************************
1466NAME
1467 vc_filesys_fstype
1468
1469SYNOPSIS
1470 int vc_filesys_fstype(const char *path)
1471
1472FUNCTION
1473 Return the filesystem type of the named disk.
1474
1475RETURNS
1476 Successful completion: disk type (see vc_fileservice_defs.h)
1477 Otherwise: -1
1478******************************************************************************/
1479
1480int vc_filesys_fstype(const char *path)
1481{
1482 return vc_filesys_single_string(0, path, VC_FILESYS_FSTYPE, 1);
1483}
1484
1485/******************************************************************************
1486NAME
1487 vc_filesys_open_disk_raw
1488
1489SYNOPSIS
1490 int vc_filesys_open_disk_raw(const char *path)
1491
1492FUNCTION
1493 Open disk for access in raw mode.
1494
1495RETURNS
1496 Successful completion: 0
1497 Otherwise: -1
1498******************************************************************************/
1499
1500int vc_filesys_open_disk_raw(const char *path)
1501{
1502 return vc_filesys_single_string(0, path, VC_FILESYS_OPEN_DISK_RAW, 1);
1503}
1504
1505/******************************************************************************
1506NAME
1507 vc_filesys_close_disk_raw
1508
1509SYNOPSIS
1510 int vc_filesys_close_disk_raw(const char *path)
1511
1512FUNCTION
1513 Close disk from access in raw mode.
1514
1515RETURNS
1516 Successful completion: 0
1517 Otherwise: -1
1518******************************************************************************/
1519
1520int vc_filesys_close_disk_raw(const char *path)
1521{
1522 return vc_filesys_single_string(0, path, VC_FILESYS_CLOSE_DISK_RAW, 1);
1523}
1524
1525
1526/******************************************************************************
1527NAME
1528 vc_filesys_open_disk
1529
1530SYNOPSIS
1531 int vc_filesys_open_disk(const char *path)
1532
1533FUNCTION
1534 Open disk for normal access.
1535
1536RETURNS
1537 Successful completion: 0
1538 Otherwise: -1
1539******************************************************************************/
1540
1541int vc_filesys_open_disk(const char *path)
1542{
1543 return vc_filesys_single_string(0, path, VC_FILESYS_OPEN_DISK, 1);
1544}
1545
1546/******************************************************************************
1547NAME
1548 vc_filesys_close_disk
1549
1550SYNOPSIS
1551 int vc_filesys_close_disk(const char *path)
1552
1553FUNCTION
1554 Close disk from normal access.
1555
1556RETURNS
1557 Successful completion: 0
1558 Otherwise: -1
1559******************************************************************************/
1560
1561int vc_filesys_close_disk(const char *path)
1562{
1563 return vc_filesys_single_string(0, path, VC_FILESYS_CLOSE_DISK, 1);
1564}
1565
1566/******************************************************************************
1567NAME
1568 vc_filesys_numsectors
1569
1570SYNOPSIS
1571 int vc_filesys_numsectors(const char *path)
1572
1573FUNCTION
1574 Return number of sectors on disk
1575
1576RETURNS
1577 Successful completion: greater than 0
1578 Otherwise: -1
1579******************************************************************************/
1580
1581int vc_filesys_numsectors(const char *path)
1582{
1583 return vc_filesys_single_string(0, path, VC_FILESYS_NUMSECTORS, 1);
1584}
1585
1586/******************************************************************************
1587NAME
1588 vc_filesys_read_sectors
1589
1590SYNOPSIS
1591 int vc_filesys_read_sectors(const char *path, uint32_t sector_num, char *buffer, uint32_t num_sectors)
1592
1593FUNCTION
1594 Start streaming sectors from 2727
1595
1596RETURNS
1597 Successful completion: 0
1598 Otherwise: -1
1599******************************************************************************/
1600int vc_filesys_read_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_read)
1601{
1602#if VCHI_BULK_ALIGN > 1
1603 uint32_t align_bytes = 0;
1604#endif
1605 char* bulk_addr = sectors;
1606 int len;
1607 int ret = -1;
1608
1609 if((len = (int)strlen(path)) < FS_MAX_PATH && lock_obtain() == 0)
1610 {
1611 strncpy((char *)vc_filesys_client.fileserv_msg.data, path, FS_MAX_PATH);
1612 vc_filesys_client.fileserv_msg.params[0] = sector_num;
1613 vc_filesys_client.fileserv_msg.params[1] = num_sectors;
1614
1615#if VCHI_BULK_ALIGN > 1
1616 //required to make buffer aligned for bulk
1617 align_bytes = VCHI_BULK_ALIGN_NBYTES(sectors);
1618#endif
1619 //note for read we are currently doing memcpy on host to tell 2727 align is 0
1620 vc_filesys_client.fileserv_msg.params[2] = 0;
1621
1622 //we send read request
1623 if (vchi_msg_stub_noblock(&vc_filesys_client.fileserv_msg, VC_FILESYS_READ_SECTORS, 16+len+1) == 0)
1624 {
1625 while(num_sectors)
1626 {
1627 uint32_t bulk_sectors = (num_sectors > FILESERV_MAX_BULK_SECTOR) ? (uint32_t)FILESERV_MAX_BULK_SECTOR : num_sectors;
1628 if(vchi_bulk_queue_receive( vc_filesys_client.open_handle,
1629#if VCHI_BULK_ALIGN > 1
1630 align_bytes ? vc_filesys_client.bulk_buffer : bulk_addr,
1631#else
1632 bulk_addr,
1633#endif
1634 (bulk_sectors*FILESERV_SECTOR_LENGTH), VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE, NULL) != 0)
1635 break;
1636
1637#if VCHI_BULK_ALIGN > 1
1638 if(align_bytes) {
1639 //this is bad but will do for now..
1640 memcpy( bulk_addr, vc_filesys_client.bulk_buffer, (bulk_sectors*FILESERV_SECTOR_LENGTH));
1641 }
1642#endif
1643 bulk_addr += (bulk_sectors*FILESERV_SECTOR_LENGTH);
1644 num_sectors -= bulk_sectors;
1645 }
1646
1647 // now wait to receive resp from original msg...
1648 if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS && vc_filesys_client.fileserv_msg.cmd_code == FILESERV_RESP_OK)
1649 {
1650 *sectors_read = vc_filesys_client.fileserv_msg.params[0];
1651 ret = 0;
1652 }
1653 else
1654 {
1655 //error code in [0]
1656 *sectors_read = vc_filesys_client.fileserv_msg.params[1];
1657 ret = vc_filesys_client.fileserv_msg.params[0];
1658 }
1659 }
1660
1661 lock_release();
1662 }
1663
1664 return ret;
1665}
1666
1667/******************************************************************************
1668NAME
1669 vc_filesys_write_sectors
1670
1671SYNOPSIS
1672 int vc_filesys_write_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_written)
1673
1674FUNCTION
1675 Start streaming sectors to 2727
1676
1677RETURNS
1678 Successful completion: 0
1679 Otherwise: -error code
1680******************************************************************************/
1681int vc_filesys_write_sectors(const char *path, uint32_t sector_num, char *sectors, uint32_t num_sectors, uint32_t *sectors_written)
1682{
1683 uint32_t align_bytes = 0;
1684 char* bulk_addr = sectors;
1685 int len;
1686 int ret = -1;
1687
1688 len = (int) strlen(path);
1689 if((len = (int) strlen(path)) < FS_MAX_PATH && lock_obtain() == 0)
1690 {
1691 vc_filesys_client.fileserv_msg.params[0] = sector_num;
1692 vc_filesys_client.fileserv_msg.params[1] = num_sectors;
1693
1694 //required to make buffer aligned for bulk
1695 align_bytes = ((unsigned long)sectors & (VCHI_BULK_ALIGN-1));
1696 vc_filesys_client.fileserv_msg.params[2] = align_bytes;
1697
1698 //copy path at end of any alignbytes
1699 strncpy(((char *)vc_filesys_client.fileserv_msg.data), path, FS_MAX_PATH);
1700
1701 //we send write request
1702 if (vchi_msg_stub_noblock(&vc_filesys_client.fileserv_msg, VC_FILESYS_WRITE_SECTORS, 16+len+1) == 0)
1703 {
1704 if(align_bytes) {
1705 //note we are cheating and going backward to make addr aligned and sending more data...
1706 bulk_addr -= align_bytes;
1707 }
1708
1709 while(num_sectors) {
1710 uint32_t bulk_sectors = (num_sectors > FILESERV_MAX_BULK_SECTOR) ? (uint32_t)FILESERV_MAX_BULK_SECTOR : num_sectors;
1711 //we send some extra data at the start
1712 if(vchi_bulk_queue_transmit( vc_filesys_client.open_handle, bulk_addr,
1713 VCHI_BULK_ROUND_UP((bulk_sectors*FILESERV_SECTOR_LENGTH)+align_bytes),
1714 VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, NULL) != 0)
1715 break;
1716
1717 //go to next ALIGNED address
1718 bulk_addr += FILESERV_MAX_BULK;
1719 num_sectors -= bulk_sectors;
1720 }
1721
1722 // now wait to receive resp from original msg...
1723 if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS && vc_filesys_client.fileserv_msg.cmd_code == FILESERV_RESP_OK)
1724 {
1725 *sectors_written = vc_filesys_client.fileserv_msg.params[0];
1726 ret = 0;
1727 }
1728 else
1729 {
1730 //error code in [0]
1731 *sectors_written = vc_filesys_client.fileserv_msg.params[1];
1732 ret = vc_filesys_client.fileserv_msg.params[0];
1733 }
1734 }
1735
1736 lock_release();
1737 }
1738
1739 return ret;
1740}
1741
1742/******************************************************************************
1743NAME
1744 vc_filesys_errno
1745
1746SYNOPSIS
1747 int vc_filesys_errno(void)
1748
1749FUNCTION
1750 Returns the error code of the last file system error that occurred.
1751
1752RETURNS
1753 Error code
1754******************************************************************************/
1755
1756int vc_filesys_errno(void)
1757{
1758 return (int) vc_filesys_client.err_no;
1759}
1760
1761
1762/* File Service Message FIFO functions */
1763
1764/******************************************************************************
1765NAME
1766 vchi_msg_stub
1767
1768SYNOPSIS
1769 static int vc_fs_stub(int verb, int ext_len)
1770
1771FUNCTION
1772 Generates a request and sends it to the co-processor. It then suspends
1773 until it receives a reply from the host. The calling task must hold
1774 the filesys_lock.
1775
1776RETURNS
1777 Successful completion: Response code of reply
1778 Otherwise: -
1779******************************************************************************/
1780static int vchi_msg_stub(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len )
1781{
1782 int ret = -1;
1783 vchi_msg_stub_noblock(msg, cmd_id, msg_len);
1784
1785 // wait to receive response
1786 if(vcos_event_wait(&vc_filesys_client.response_event) == VCOS_SUCCESS)
1787 ret = (int) msg->cmd_code;
1788
1789 return ret;
1790}
1791
1792static int vchi_msg_stub_noblock(FILESERV_MSG_T* msg, uint16_t cmd_id, int msg_len)
1793{
1794 uint32_t i;
1795
1796 if(!vcos_verify(msg_len <= VCHI_MAX_MSG_SIZE))
1797 return -1;
1798
1799 //will get changed by response from command
1800 vc_filesys_client.resp_code = FILESERV_RESP_ERROR;
1801
1802 //the top bit is used for host/vc
1803 i = vc_filesys_client.cur_xid + 1;
1804 i &= 0x7fffffffUL;
1805 vc_filesys_client.cur_xid = i;
1806
1807 //fill in transaction id, used for response identification
1808 vchi_writebuf_uint32( &(msg->xid), vc_filesys_client.cur_xid );
1809
1810 //fill in cmd id VC_FILESYS_OPEN etc
1811 vchi_writebuf_uint32( &(msg->cmd_code), cmd_id );
1812
1813 //we always have cmd_id, xid
1814 msg_len += 8;
1815
1816 //return response code
1817 return (int) vchi_msg_queue( vc_filesys_client.open_handle, msg, (uint32_t)msg_len, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
1818}
1819
1820static int vc_send_response( FILESERV_MSG_T* msg, uint32_t retval, uint32_t nbytes )
1821{
1822 int success = -1;
1823 //convert all to over the wire values
1824 vchi_writebuf_uint32(&msg->cmd_code, retval);
1825 vchi_writebuf_uint32(&msg->xid, msg->xid);
1826 vchi_writebuf_uint32(&msg->params[0], msg->params[0]);
1827 vchi_writebuf_uint32(&msg->params[1], msg->params[1]);
1828 vchi_writebuf_uint32(&msg->params[2], msg->params[2]);
1829 vchi_writebuf_uint32(&msg->params[3], msg->params[3]);
1830
1831 //start with 8 because always xid and retval
1832 nbytes += 8;
1833
1834 if(vcos_verify(nbytes <= VCHI_MAX_MSG_SIZE))
1835 success = (int) vchi_msg_queue( vc_filesys_client.open_handle, msg, nbytes, VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL );
1836
1837 return success;
1838}
1839
1840/******************************************************************************
1841NAME
1842 vc_fs_message_handler
1843
1844SYNOPSIS
1845 static int vc_fs_message_handler()
1846
1847FUNCTION
1848 Handle messages from the co-processor.
1849
1850RETURNS
1851 0 - No message found.
1852 1 - Request received and actioned.
1853 2 - Reply received.
1854******************************************************************************/
1855
1856static int vc_fs_message_handler( FILESERV_MSG_T* msg, uint32_t nbytes )
1857{
1858 int rr = 0;
1859 uint32_t xid = vchi_readbuf_uint32(&msg->xid);
1860
1861 if (xid == vc_filesys_client.cur_xid) {
1862
1863 //memcpy reply to msg should really peek before
1864 vc_filesys_client.fileserv_msg.xid = xid;
1865 vc_filesys_client.fileserv_msg.cmd_code = vchi_readbuf_uint32(&msg->cmd_code);
1866 vc_filesys_client.fileserv_msg.params[0] = vchi_readbuf_uint32(&msg->params[0]);
1867 vc_filesys_client.fileserv_msg.params[1] = vchi_readbuf_uint32(&msg->params[1]);
1868 vc_filesys_client.fileserv_msg.params[2] = vchi_readbuf_uint32(&msg->params[2]);
1869 vc_filesys_client.fileserv_msg.params[3] = vchi_readbuf_uint32(&msg->params[3]);
1870
1871 //copy any data, 24 is size of header
1872 if(nbytes >24)
1873 memcpy(&vc_filesys_client.fileserv_msg.data, msg->data, (nbytes-24));
1874
1875 vc_filesys_client.resp_code = (int32_t)vc_filesys_client.fileserv_msg.cmd_code;
1876
1877 if (vc_filesys_client.resp_code == FILESERV_RESP_ERROR) {
1878 vc_filesys_client.err_no = (int32_t)vc_filesys_client.fileserv_msg.params[0];
1879 }
1880
1881 // signal vchi_msg_stub which will be waiting for response
1882 vcos_event_signal(&vc_filesys_client.response_event);
1883
1884 rr = 2;
1885 }
1886 else if ((xid & 0x80000000UL) == 0x80000000UL) {
1887 /* Process new requests from the co-processor */
1888
1889 uint32_t retval = FILESERV_RESP_OK;
1890
1891 //this is the number of uint32_t param[] + data that we send back to VC in bytes
1892
1893 uint32_t rlen = 0;
1894 int i;
1895
1896 switch (msg->cmd_code) {
1897
1898 case VC_FILESYS_CLOSE:
1899
1900 i = vc_hostfs_close((int)msg->params[0]);
1901 if (i != 0) {
1902 retval = FILESERV_RESP_ERROR;
1903 }
1904 rlen = 0;
1905 break;
1906
1907 case VC_FILESYS_CLOSEDIR:
1908
1909 i = vc_hostfs_closedir((void *)msg->params[0]);
1910 if (i != 0) {
1911 retval = FILESERV_RESP_ERROR;
1912 }
1913 rlen = 0;
1914 break;
1915
1916 case VC_FILESYS_FORMAT:
1917
1918 i = vc_hostfs_format((const char *)msg->data);
1919 if (i != 0) {
1920 retval = FILESERV_RESP_ERROR;
1921 }
1922 rlen = 0;
1923 break;
1924
1925 case VC_FILESYS_FREESPACE:
1926
1927 i = vc_hostfs_freespace((const char *)msg->data);
1928 if (i < 0) {
1929 retval = FILESERV_RESP_ERROR;
1930 rlen = 0;
1931 } else {
1932 msg->params[0] = (uint32_t)i;
1933 rlen = 4;
1934 }
1935 break;
1936
1937 case VC_FILESYS_FREESPACE64:
1938 {
1939 int64_t freespace;
1940 freespace = vc_hostfs_freespace64((const char *)msg->data);
1941 if (freespace < (int64_t)0) {
1942 retval = FILESERV_RESP_ERROR;
1943 rlen = 0;
1944 } else {
1945 msg->params[0] = (uint32_t)freespace;
1946 msg->params[1] = (uint32_t)(freespace>>32);
1947 rlen = 8;
1948 }
1949 }
1950 break;
1951
1952 case VC_FILESYS_GET_ATTR:
1953 {
1954 fattributes_t attr;
1955
1956 i = vc_hostfs_get_attr((const char *)msg->data,
1957 &attr);
1958 if (i != 0) {
1959 retval = FILESERV_RESP_ERROR;
1960 rlen = 0;
1961 } else {
1962 msg->params[0] = (uint32_t) attr;
1963 rlen = 4;
1964 }
1965 }
1966 break;
1967 case VC_FILESYS_LSEEK:
1968
1969 i = vc_hostfs_lseek( (int)msg->params[0],
1970 (int)msg->params[1],
1971 (int)msg->params[2]);
1972 if (i < 0) {
1973 retval = FILESERV_RESP_ERROR;
1974 rlen = 0;
1975 } else {
1976 msg->params[0] = (uint32_t) i;
1977 rlen = 4;
1978 }
1979 break;
1980
1981 case VC_FILESYS_LSEEK64:
1982 {
1983 int64_t offset;
1984 offset = (((int64_t) msg->params[2]) << 32) + msg->params[1];
1985
1986 offset = vc_hostfs_lseek64( (int)msg->params[0], offset, (int)msg->params[3]);
1987 if (offset < (int64_t)0) {
1988 retval = FILESERV_RESP_ERROR;
1989 rlen = 0;
1990 } else {
1991 msg->params[0] = (uint32_t)offset;
1992 msg->params[1] = (uint32_t)(offset>>32);
1993 rlen = 8;
1994 }
1995 }
1996 break;
1997
1998 case VC_FILESYS_MKDIR:
1999
2000 i = vc_hostfs_mkdir((const char *)msg->data);
2001 if (i != 0) {
2002 retval = FILESERV_RESP_ERROR;
2003 }
2004 rlen = 0;
2005 break;
2006
2007 case VC_FILESYS_OPEN:
2008
2009 i = vc_hostfs_open((const char *)msg->data,
2010 (int) msg->params[0]);
2011 if (i < 0) {
2012 retval = FILESERV_RESP_ERROR;
2013 } else {
2014 msg->params[0] = (uint32_t) i;
2015 }
2016 rlen = 4;
2017 break;
2018
2019 case VC_FILESYS_OPENDIR:
2020
2021 msg->params[0] = (uint32_t)vc_hostfs_opendir(
2022 (const char *)msg->data);
2023 if ((void *)msg->params[0] == NULL) {
2024 retval = FILESERV_RESP_ERROR;
2025 }
2026 rlen = 4;
2027 break;
2028
2029 case VC_FILESYS_READ:
2030 {
2031 uint32_t fd = msg->params[0];
2032 uint32_t offset = msg->params[1];
2033 int total_bytes = (int)msg->params[2];
2034 uint32_t nalign_bytes = msg->params[3];
2035
2036 i = 0;
2037
2038 if(!vcos_verify(((int)vc_filesys_client.bulk_buffer & (VCHI_BULK_ALIGN-1)) == 0 &&
2039 total_bytes <= FILESERV_MAX_BULK))
2040 {
2041 retval = FILESERV_RESP_ERROR;
2042 rlen = 4;
2043 break;
2044 }
2045
2046 rlen = 0;
2047
2048 //perform any seeking
2049 if ( (uint32_t)0xffffffffUL != offset)
2050 {
2051 i = vc_hostfs_lseek( (int)fd,
2052 (long int) offset,
2053 VC_FILESYS_SEEK_SET);
2054 if ( 0 > i)
2055 {
2056 retval = FILESERV_RESP_ERROR;
2057 rlen = 4;
2058 break;
2059 }
2060 }
2061
2062
2063 //put it all in one msg
2064 if(total_bytes <= FILESERV_MAX_DATA) {
2065 i = vc_hostfs_read( (int)fd,
2066 msg->data,
2067 (unsigned int) total_bytes);
2068
2069 if(i < 0) {
2070 retval = FILESERV_RESP_ERROR;
2071 msg->params[0] = 0;
2072 }
2073 else {
2074 retval = FILESERV_RESP_OK;
2075 //send back length of read
2076 msg->params[0] = (uint32_t) i;
2077 }
2078
2079 msg->params[1] = 0;
2080 rlen = 16 + (uint32_t) i;
2081 }
2082 //bulk transfer required
2083 else {
2084 uint32_t end_bytes = 0;
2085 retval = FILESERV_BULK_WRITE;
2086
2087 //we send the bytes required for HOST buffer align
2088 if(nalign_bytes) {
2089 i = vc_hostfs_read( (int)fd,
2090 msg->data,
2091 (unsigned int)nalign_bytes);
2092 if(i < 0) {
2093 retval = FILESERV_RESP_ERROR;
2094 rlen = 16;
2095 break;
2096 }
2097 else if(i != (int)nalign_bytes) {
2098 //all data will be in one msg
2099 retval = FILESERV_RESP_OK;
2100 msg->params[0] = (uint32_t) i;
2101 msg->params[1] = 0;
2102 rlen = 16 + (uint32_t) i;
2103 //send response
2104 break;
2105 }
2106
2107 total_bytes -= i;
2108 rlen += (uint32_t) i;
2109 }
2110
2111 //bulk bytes
2112 i = vc_hostfs_read((int)fd, vc_filesys_client.bulk_buffer, (unsigned int)total_bytes);
2113
2114 if(i < 0) {
2115 retval = FILESERV_RESP_ERROR;
2116 rlen = 16;
2117 break;
2118 }
2119 else if((i+nalign_bytes) <= FILESERV_MAX_DATA) {
2120 retval = FILESERV_RESP_OK;
2121 memcpy(&msg->data[nalign_bytes], &vc_filesys_client.bulk_buffer[0], (size_t) i);
2122 //read size
2123 msg->params[0] = (i + nalign_bytes);
2124 msg->params[1] = 0;
2125 rlen = i + nalign_bytes + 16;
2126 break;
2127 }
2128
2129 //copy end unaligned length bytes into msg->data
2130 end_bytes = (uint32_t) (i & (VCHI_BULK_GRANULARITY-1));
2131 if(end_bytes) {
2132 int end_index = i - (int) end_bytes;
2133 memcpy(&msg->data[nalign_bytes], &vc_filesys_client.bulk_buffer[end_index], end_bytes);
2134 rlen += end_bytes;
2135 }
2136
2137 //send back total bytes
2138 msg->params[0] = (uint32_t)(i + nalign_bytes);
2139 //number of end bytes
2140 msg->params[1] = end_bytes;
2141 //number of bulk bytes
2142 msg->params[2] = (uint32_t)(i - end_bytes);
2143 //16 for param len
2144 rlen += 16;
2145
2146 //queue bulk to be sent
2147 if(vchi_bulk_queue_transmit( vc_filesys_client.open_handle,
2148 vc_filesys_client.bulk_buffer,
2149 msg->params[2],
2150 VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
2151 NULL ) != 0)
2152 {
2153 retval = FILESERV_RESP_ERROR;
2154 rlen = 4;
2155 break;
2156 }
2157 }
2158 }
2159 //send response
2160 break;
2161
2162 case VC_FILESYS_READDIR:
2163 {
2164 struct dirent result;
2165 if (vc_hostfs_readdir_r((void *)msg->params[0],
2166 &result) == NULL) {
2167 retval = FILESERV_RESP_ERROR;
2168 rlen = 4;
2169 } else {
2170 rlen = (uint32_t) (16+fs_host_direntbytestream_create(&result,
2171 (void *)msg->data));
2172 }
2173 }
2174 break;
2175
2176 case VC_FILESYS_REMOVE:
2177
2178 i = vc_hostfs_remove((const char *)msg->data);
2179 if (i != 0) {
2180 retval = FILESERV_RESP_ERROR;
2181 }
2182 rlen = 0;
2183 break;
2184
2185 case VC_FILESYS_RENAME:
2186
2187 i = (int) strlen((char *)msg->data);
2188 if (vc_hostfs_rename((const char *)msg->data,
2189 (const char *)&msg->data[i+1])
2190 != 0) {
2191 retval = FILESERV_RESP_ERROR;
2192 }
2193 rlen = 0;
2194 break;
2195
2196 case VC_FILESYS_SETEND:
2197
2198 i = vc_hostfs_setend( (int)msg->params[0] );
2199 if (i != 0) {
2200 retval = FILESERV_RESP_ERROR;
2201 }
2202 rlen = 0;
2203 break;
2204
2205 case VC_FILESYS_SET_ATTR:
2206
2207 i = vc_hostfs_set_attr((const char *)msg->data,
2208 (fattributes_t)msg->params[0]);
2209 if (i != 0) {
2210 retval = FILESERV_RESP_ERROR;
2211 }
2212 rlen = 0;
2213 break;
2214
2215 case VC_FILESYS_TOTALSPACE:
2216
2217 i = vc_hostfs_totalspace((const char *)msg->data);
2218 if (i < 0) {
2219 retval = FILESERV_RESP_ERROR;
2220 rlen = 0;
2221 } else {
2222 msg->params[0] = (uint32_t) i;
2223 rlen = 4;
2224 }
2225 break;
2226
2227 case VC_FILESYS_TOTALSPACE64:
2228 {
2229 int64_t totalspace;
2230 totalspace = vc_hostfs_totalspace64((const char *)msg->data);
2231 if (totalspace < (int64_t)0) {
2232 retval = FILESERV_RESP_ERROR;
2233 rlen = 0;
2234 } else {
2235 msg->params[0] = (uint32_t)totalspace;
2236 msg->params[1] = (uint32_t)(totalspace>>32);
2237 rlen = 8;
2238 }
2239 }
2240 break;
2241#if 0 // I don't think host systems are ready for these yet
2242 case VC_FILESYS_SCANDISK:
2243
2244 vc_hostfs_scandisk((const char *)msg->data);
2245 rlen = 0;
2246 break;
2247
2248 case VC_FILESYS_CHKDSK:
2249
2250 i = vc_hostfs_chkdsk((const char *)msg->data, msg->params[0]);
2251 if (i < 0) {
2252 retval = FILESERV_RESP_ERROR;
2253 rlen = 0;
2254 } else {
2255 msg->params[0] = (uint32_t)i;
2256 rlen = 4;
2257 }
2258 break;
2259#endif
2260 case VC_FILESYS_WRITE:
2261 {
2262 uint32_t fd = msg->params[0];
2263 // uint32_t offset = msg->params[1];
2264 int total_bytes = (int)msg->params[2];
2265 uint32_t nalign_bytes = msg->params[3];
2266 retval = FILESERV_RESP_OK;
2267 i = 0;
2268
2269 //everything in one msg
2270 if(total_bytes <= FILESERV_MAX_DATA)
2271 {
2272 i = vc_hostfs_write( (int)fd,
2273 msg->data,
2274 (unsigned int) total_bytes);
2275 if (i < 0) {
2276 retval = FILESERV_RESP_ERROR;
2277 } else {
2278 msg->params[0] = (uint32_t) i;
2279 }
2280 rlen = 4;
2281 //send response
2282 break;
2283 }
2284 else
2285 {
2286 uint32_t end_bytes;
2287 uint32_t bulk_bytes;
2288 uint32_t total_bytes_written = 0;
2289 i = 0;
2290 //one return param
2291 rlen = 4;
2292 retval = FILESERV_BULK_READ;
2293
2294 //write bytes required for VC buffer align
2295 if(nalign_bytes) {
2296 i = vc_hostfs_write( (int)fd,
2297 msg->data,
2298 (unsigned int)nalign_bytes);
2299 if(i < 0) {
2300 retval = FILESERV_RESP_ERROR;
2301 msg->params[0] = 0;
2302 //break from switch and send reply
2303 break;
2304 }
2305 total_bytes_written += i;
2306 total_bytes -= nalign_bytes;
2307 }
2308
2309 //calculate bytes that wil lbe sent by bulk
2310 bulk_bytes = (uint32_t)((total_bytes)&(~(VCHI_BULK_ALIGN-1)));
2311
2312 end_bytes = total_bytes-bulk_bytes;
2313
2314
2315
2316 if(vchi_bulk_queue_receive(vc_filesys_client.open_handle,
2317 vc_filesys_client.bulk_buffer,
2318 bulk_bytes,
2319 VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE,
2320 NULL) != 0 ||
2321 (i = vc_hostfs_write( (int)fd,
2322 vc_filesys_client.bulk_buffer,
2323 (unsigned int) bulk_bytes)) < 0)
2324 {
2325 retval = FILESERV_RESP_ERROR;
2326 msg->params[0] = 0;
2327 break;
2328 }
2329
2330 total_bytes_written += i;
2331
2332 if(end_bytes) {
2333 i = vc_hostfs_write( (int)fd,
2334 msg->data+nalign_bytes,
2335 (unsigned int)end_bytes);
2336
2337 total_bytes_written += i;
2338 }
2339
2340 if(i < 0) {
2341 retval = FILESERV_RESP_ERROR;
2342 msg->params[0] = 0;
2343 break;
2344 }
2345
2346 msg->params[0] = total_bytes_written;
2347
2348 }
2349 }
2350 break;
2351
2352 default:
2353 rlen = 4;
2354 retval = FILESERV_RESP_ERROR;
2355 break;
2356 }
2357
2358 //convert all to over the wire values and send
2359 vc_send_response( msg, retval, rlen );
2360
2361 rr = 1;
2362
2363 } else {
2364 /* A message has been left in the fifo and the host side has been reset.
2365 The message needs to be flushed. It would be better to do this by resetting
2366 the fifos. */
2367 }
2368
2369 return rr;
2370}
2371
2372
2373/******************************************************************************
2374NAME
2375 showmsg
2376
2377SYNOPSIS
2378 static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
2379 struct file_service_msg_body const * body)
2380
2381FUNCTION
2382 De-bug tool: prints out fifo message.
2383
2384RETURNS
2385 void
2386******************************************************************************/
2387
2388#ifdef PRINTF
2389static void showmsg(VC_MSGFIFO_CMD_HEADER_T const * head,
2390 struct file_service_msg_body const * body)
2391{
2392 unsigned int ael = (head->ext_length + 15) & ~15;
2393 printf("Sync=%08x XID=%08x Code=%08x Extlen=%08x (%d bytes follow)\n",
2394 head->sync, head->xid, head->cmd_code, head->ext_length, ael);
2395 if (ael) {
2396 unsigned int i;
2397 printf("Content:");
2398 for (i = 0; i < 4 && i*4 < head->ext_length; ++i) printf(" %08x", body->params[i]);
2399 //for(i = 0; i+16 < head->ext_length; ++i) printf(" %02x", body->data[i]);
2400 if (head->ext_length > 16) printf(" plus %d bytes\n", head->ext_length);
2401 }
2402 printf("\n");
2403}
2404#endif
2405
2406
2407/******************************************************************************
2408NAME
2409 fs_host_direntbytestream_create
2410
2411SYNOPSIS
2412 static int fs_host_direntbytestream_create(struct dirent *d, void *buffer)
2413
2414FUNCTION
2415 Turns a variable of type struct dirent into a compiler independent byte
2416 stream, which is stored in buffer.
2417
2418RETURNS
2419 Successful completion: The length of the byte stream
2420 Otherwise: -1
2421******************************************************************************/
2422static void write_bytestream(void *a, char *b, int n)
2423{
2424 int i;
2425 for (i=0;i<n;i++) {
2426 b[i] = ((char *)a)[i];
2427 }
2428 for (;i<4;i++) {
2429 b[i] = 0;
2430 }
2431}
2432
2433static int fs_host_direntbytestream_create(struct dirent *d, void *buffer)
2434{
2435 char *buf = (char*)buffer;
2436
2437 // Write d_name (D_NAME_MAX_SIZE chars)
2438 memcpy(buf, &d->d_name, D_NAME_MAX_SIZE);
2439 buf += D_NAME_MAX_SIZE;
2440
2441 // Write d_size (unsigned int)
2442 write_bytestream((void *)&d->d_size, buf, (int)sizeof(d->d_size));
2443 buf += 4;
2444
2445 // Write d_attrib (int)
2446 write_bytestream((void *)&d->d_attrib, buf, (int)sizeof(d->d_attrib));
2447 buf += 4;
2448
2449 // Write d_modtime (time_t)
2450 write_bytestream((void *)&d->d_modtime, buf, (int)sizeof(d->d_modtime));
2451 buf += 4;
2452
2453 return (int)(buf-(char *)buffer);
2454}
2455
2456
2457/******************************************************************************
2458NAME
2459 fs_host_direntbytestream_interp
2460
2461SYNOPSIS
2462 static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer)
2463
2464FUNCTION
2465 Turns a compiler independent byte stream back into a struct of type dirent.
2466
2467RETURNS
2468 Successful completion: 0
2469 Otherwise: -1
2470******************************************************************************/
2471static void read_bytestream(void *a, char *b, int n)
2472{
2473 int i;
2474 for (i=0;i<n;i++) {
2475 ((char *)a)[i] = b[i];
2476 }
2477}
2478
2479static void fs_host_direntbytestream_interp(struct dirent *d, void *buffer)
2480{
2481 char *buf = (char*)buffer;
2482
2483 // Read d_name (D_NAME_MAX_SIZE chars)
2484 memcpy(&d->d_name, buf, D_NAME_MAX_SIZE);
2485 buf += D_NAME_MAX_SIZE;
2486
2487 // Read d_size (unsigned int)
2488 read_bytestream((void *)&d->d_size, buf, (int)sizeof(d->d_size));
2489 d->d_size = VC_VTOH32(d->d_size);
2490 buf += 4;
2491
2492 // Read d_attrib (int)
2493 read_bytestream((void *)&d->d_attrib, buf, (int)sizeof(d->d_attrib));
2494 d->d_attrib = VC_VTOH32(d->d_attrib);
2495 buf += 4;
2496
2497 // Read d_modtime (time_t)
2498 read_bytestream((void *)&d->d_modtime, buf, (int)sizeof(d->d_modtime));
2499 d->d_modtime = VC_VTOH32(d->d_modtime);
2500
2501 return;
2502}
2503
2504
2505
2506void vc_filesys_sendreset(void)
2507{
2508 //TODO
2509}
2510