add license headers
[archipelago] / xseg / sys / kernel / segtool.c
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 #define _GNU_SOURCE
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdint.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/ioctl.h>
42 #include <sys/mman.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <string.h>
46
47 #include "segdev.h"
48
49 int help(void)
50 {
51         printf("segtool [<command> <arg>]* \n"
52                 "commands:\n"
53                 "    create <size_in_bytes>\n"
54                 "    destroy\n"
55                 "    info\n"
56                 "    map <offset> <size_in_bytes>\n"
57                 "    unmap <size_in_bytes>\n"
58                 "    dump <offset> <size_in_bytes>\n"
59                 "    load <offset>\n"
60                 "    fill <offset> <size_in_bytes> <char_in_hex>\n"
61                 "    mark\n"
62                 "    checkmark\n"
63                 "    wait\n"
64         );
65         return 1;
66 }
67
68 #define ALLOC_MIN 4096
69 #define ALLOC_MAX 1048576
70
71 void inputbuf(FILE *fp, char **retbuf, uint64_t *retsize)
72 {
73         static uint64_t alloc_size;
74         static char *buf;
75         uint64_t size = 0;
76         char *p;
77         size_t r;
78
79         if (alloc_size < ALLOC_MIN)
80                 alloc_size = ALLOC_MIN;
81
82         if (alloc_size > ALLOC_MAX)
83                 alloc_size = ALLOC_MAX;
84
85         p = realloc(buf, alloc_size);
86         if (!p) {
87                 if (buf)
88                         free(buf);
89                 buf = NULL;
90                 goto out;
91         }
92
93         buf = p;
94
95         while (!feof(fp)) {
96                 r = fread(buf + size, 1, alloc_size - size, fp);
97                 if (!r)
98                         break;
99                 size += r;
100                 if (size >= alloc_size) {
101                         p = realloc(buf, alloc_size * 2);
102                         if (!p) {
103                                 if (buf)
104                                         free(buf);
105                                 buf = NULL;
106                                 size = 0;
107                                 goto out;
108                         }
109                         buf = p;
110                         alloc_size *= 2;
111                 }
112         }
113
114 out:
115         *retbuf = buf;
116         *retsize = size;
117 }
118
119 static int opendev(void)
120 {
121         int fd = open("/dev/segdev", O_RDWR);
122         if (fd < 0)
123                 perror("/dev/segdev");
124         return fd;
125 }
126
127 static char *segment;
128 static unsigned long mapped_size;
129
130 int cmd_create(uint64_t size)
131 {
132         int r, fd = opendev();
133         if (fd < 0)
134                 return fd;
135
136         r = ioctl(fd, SEGDEV_IOC_CREATESEG, size);
137         if (r < 0)
138                 perror("CREATESEG");
139
140         close(fd);
141         return 0;
142 }
143
144 int cmd_destroy(void)
145 {
146         int r, fd = opendev();
147         if (fd < 0)
148                 return fd;
149
150         r = ioctl(fd, SEGDEV_IOC_DESTROYSEG, 0);
151         if (r < 0)
152                 perror("DESTROYSEG");
153
154         close(fd);
155         return 0;
156 }
157
158 int cmd_info(void)
159 {
160         long r, fd = opendev();
161         if (fd < 0)
162                 return fd;
163
164         r = ioctl(fd, SEGDEV_IOC_SEGSIZE, 0);
165         if (r < 0)
166                 perror("SEGSIZE");
167         else
168                 printf("Segment size: %lu bytes\n", r);
169         close(fd);
170         return 0;
171 }
172
173 int cmd_map(uint64_t offset, uint64_t size)
174 {
175         char *seg;
176         long r = -1, fd = opendev();
177         if (fd < 0)
178                 goto out;
179
180         r = 0;
181         if (segment)
182                 goto out;
183
184         if (!size) {
185                 r = ioctl(fd, SEGDEV_IOC_SEGSIZE, 0);
186                 if (r < 0) {
187                         perror("SEGSIZE");
188                         goto out;
189                 }
190                 size = r - offset;
191         }
192
193         if (offset + size > r) {
194                 printf("segment size would be exceeded\n");
195                 goto out;
196         }
197
198         r = -1;
199         //seg = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
200         seg = mmap( (void*) 0x37fd0000, size,
201                         PROT_READ | PROT_WRITE,
202                         MAP_SHARED | MAP_FIXED,
203                         fd, offset);
204         if (seg == MAP_FAILED) {
205                 perror("mmap");
206                 goto out;
207         }
208
209         segment = seg;
210         mapped_size = size;
211 out:
212         close(fd);
213         return r;
214 }
215
216 int cmd_unmap(uint64_t size)
217 {
218         long r = -1, fd = opendev();
219         if (fd < 0)
220                 goto out;
221
222         r = 0;
223         if (!segment)
224                 goto out;
225
226         if (!size)
227                 size = mapped_size;
228
229         r = munmap(segment, size);
230         if (r < 0)
231                 perror("munmap");
232         else {
233                 segment = NULL;
234                 mapped_size = 0;
235         }
236
237 out:
238         close(fd);
239         return r;
240 }
241
242 int cmd_wait(void)
243 {
244         int c, fd = open("/dev/tty", O_RDONLY);
245         c = read(fd, &c, 1);
246         close(fd);
247         return 0;
248 }
249
250 int cmd_dump(uint64_t offset, uint64_t size)
251 {
252         long r = -1, fd = opendev();
253         if (fd < 0)
254                 goto out;
255
256         if (!segment) {
257                 printf("segment not mapped\n");
258                 goto out;
259         }
260
261         if (!size)
262                 size = mapped_size - offset;
263
264         if (offset + size > mapped_size) {
265                 printf("mapped segment size would be exceeded\n");
266                 goto out;
267         }
268
269         for (r = offset; r < offset + size; r++)
270                 if (fputc(segment[r], stdout) == EOF)
271                         break;
272
273         fflush(stdout);
274         r = 0;
275 out:
276         close(fd);
277         return r;
278 }
279
280 int cmd_load(uint64_t offset)
281 {
282         long r = -1, fd = opendev();
283         unsigned long pos;
284
285         if (fd < 0)
286                 goto out;
287
288         if (!segment) {
289                 printf("segment not mapped\n");
290                 goto out;
291         }
292
293         for (pos = offset; pos < mapped_size; pos++) {
294                 int c = fgetc(stdin);
295                 if (c == EOF)
296                         break;
297                 segment[pos] = c;
298         }
299 out:
300         close(fd);
301         return r;
302 }
303
304 int cmd_fill(uint64_t offset, uint64_t size, int fill)
305 {
306         long r = -1, fd = opendev();
307         uint64_t misscount = 0;
308
309         if (fd < 0)
310                 goto out;
311
312         if (!segment) {
313                 printf("segment not mapped\n");
314                 goto out;
315         }
316
317         if (size == 0)
318                 size = mapped_size - offset;
319
320         if (offset + size > mapped_size) {
321                 printf("mapped segment size would be exceeded\n");
322                 goto out;
323         }
324
325         memset(segment + offset, fill, size);
326         for (size += offset; offset < size; offset++)
327                 if (segment[offset] != (char)fill)
328                         misscount ++;
329
330         if (misscount)
331                 printf("fill misscount(!) %lu\n", misscount);
332 out:
333         close(fd);
334         return r;
335 }
336
337 int cmd_mark(void)
338 {
339         unsigned long i, count;
340         unsigned long *longs;
341
342         if (!segment) {
343                 printf("segment not mapped\n");
344                 return -1;
345         }
346
347         longs = (void *)segment;
348         count = mapped_size / sizeof(long);
349         for (i = 0; i < count; i++)
350                 longs[i] = i;
351
352         return 0;
353 }
354
355 int cmd_checkmark(void)
356 {
357         unsigned long i, count;
358         unsigned long *longs;
359
360         if (!segment) {
361                 printf("segment not mapped\n");
362                 return -1;
363         }
364
365         longs = (void *)segment;
366         count = mapped_size / sizeof(long);
367         for (i = 0; i < count; i++)
368                 if (longs[i] != i)
369                         printf("%lu != %lu\n", i, longs[i]);
370         return 0;
371 }
372
373 int main(int argc, char **argv) {
374
375         int i, ret = 0;
376
377         if (argc < 2)
378                 return help();
379
380         for (i = 1; i < argc; i++) {
381
382                 if (!strcmp(argv[i], "info")) {
383                         ret = cmd_info();
384                         continue;
385                 }
386
387                 if (!strcmp(argv[i], "create") && (i + 1 < argc)) {
388                         ret = cmd_create(atol(argv[i+1]));
389                         i += 1;
390                         continue;
391                 }
392
393                 if (!strcmp(argv[i], "destroy")) {
394                         ret = cmd_destroy();
395                         continue;
396                 }
397
398                 if (!strcmp(argv[i], "wait")) {
399                         ret = cmd_wait();
400                         continue;
401                 }
402
403                 if (!strcmp(argv[i], "mark")) {
404                         ret = cmd_mark();
405                         continue;
406                 }
407
408                 if (!strcmp(argv[i], "checkmark")) {
409                         ret = cmd_checkmark();
410                         continue;
411                 }
412
413                 if (!strcmp(argv[i], "map") && (i + 2 < argc)) {
414                         ret = cmd_map(atol(argv[i+1]), atol(argv[i+2]));
415                         i += 2;
416                         continue;
417                 }
418
419                 if (!strcmp(argv[i], "unmap") && (i + 1 < argc)) {
420                         ret = cmd_unmap(atol(argv[i+1]));
421                         i += 1;
422                         continue;
423                 }
424
425                 if (!strcmp(argv[i], "fill") && (i + 3 < argc)) {
426                         ret = cmd_fill( atol(argv[i+1]),
427                                         atol(argv[i+2]),
428                                         strtoul(argv[i+3], NULL, 16));
429                         i += 3;
430                         continue;
431                 }
432
433                 if (!strcmp(argv[i], "dump") && (i + 2 < argc)) {
434                         ret = cmd_dump(atol(argv[i+1]), atol(argv[i+2]));
435                         i += 2;
436                         continue;
437                 }
438
439                 if (!strcmp(argv[i], "load") && (i + 1 < argc)) {
440                         ret = cmd_load(atol(argv[i+1]));
441                         i += 1;
442                         continue;
443                 }
444
445                 return help();
446         }
447
448         return ret;
449 }