]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - VBLADE/vblade-master/aoe.c
1 // aoe.c: the ATA over Ethernet virtual EtherDrive (R) blade
11 #include <netinet/in.h>
21 uchar masks
[Nmasks
*Alen
];
29 int bufcnt
= Bufcount
;
35 typedef unsigned long long u64_t
;
36 typedef unsigned int u32_t
;
39 typedef struct ventoy_img_chunk
41 u32_t img_start_sector
; // sector size: 2KB
42 u32_t img_end_sector
; // included
44 u64_t disk_start_sector
; // in disk_sector_size
45 u64_t disk_end_sector
; // included
48 typedef struct ventoy_disk_map
50 u64_t img_start_sector
;
52 u64_t disk_start_sector
;
53 u64_t disk_end_sector
;
57 static int verbose
= 0;
58 static u64_t g_iso_file_size
= 0;
59 static int g_img_map_num
= 0;
60 static ventoy_disk_map
*g_img_map
= NULL
;
62 static ventoy_disk_map
* vtoydm_get_img_map_data(const char *img_map_file
, int *plen
)
69 ventoy_img_chunk
*chunk
= NULL
;
70 ventoy_disk_map
*map
= NULL
;
72 fp
= fopen(img_map_file
, "rb");
75 fprintf(stderr
, "Failed to open file %s\n", img_map_file
);
79 fseek(fp
, 0, SEEK_END
);
81 fseek(fp
, 0, SEEK_SET
);
83 chunk
= (ventoy_img_chunk
*)malloc(len
);
86 fprintf(stderr
, "Failed to malloc memory len:%d\n", len
);
90 if (fread(chunk
, 1, len
, fp
) != len
)
92 fprintf(stderr
, "Failed to read file\n");
96 if (len
% sizeof(ventoy_img_chunk
))
98 fprintf(stderr
, "image map file size %d is not aligned with %d\n",
99 len
, (int)sizeof(ventoy_img_chunk
));
103 map
= (ventoy_disk_map
*)malloc((len
/ sizeof(ventoy_img_chunk
)) * sizeof(ventoy_disk_map
));
106 fprintf(stderr
, "Failed to malloc memory\n");
110 for (i
= 0; i
< len
/ sizeof(ventoy_img_chunk
); i
++)
112 sector_num
= chunk
[i
].img_end_sector
- chunk
[i
].img_start_sector
+ 1;
113 g_iso_file_size
+= sector_num
* 2048;
115 map
[i
].img_start_sector
= chunk
[i
].img_start_sector
<< 2;
116 map
[i
].img_end_sector
= (chunk
[i
].img_end_sector
<< 2) + 3;
117 map
[i
].disk_start_sector
= chunk
[i
].disk_start_sector
;
118 map
[i
].disk_end_sector
= chunk
[i
].disk_end_sector
;
135 static void parse_img_chunk(const char *img_map_file
)
139 g_img_map
= vtoydm_get_img_map_data(img_map_file
, &len
);
142 g_img_map_num
= len
/ sizeof(ventoy_img_chunk
);
146 static u64_t
get_disk_sector(u64_t lba
)
149 ventoy_disk_map
*cur
= g_img_map
;
151 for (i
= 0; i
< g_img_map_num
; i
++, cur
++)
153 if (lba
>= cur
->img_start_sector
&& lba
<= cur
->img_end_sector
)
155 return (lba
- cur
->img_start_sector
) + cur
->disk_start_sector
;
162 int getsec(int fd
, uchar
*place
, vlong lba
, int nsec
)
170 last_sector
= get_disk_sector((u64_t
)lba
);
172 for (i
= 1; i
< nsec
; i
++)
174 sector
= get_disk_sector((u64_t
)(lba
+ i
));
175 if (sector
== (last_sector
+ count
))
181 lseek(fd
, last_sector
* 512, SEEK_SET
);
182 read(fd
, place
, count
* 512);
184 last_sector
= sector
;
189 lseek(fd
, last_sector
* 512, SEEK_SET
);
190 read(fd
, place
, count
* 512);
195 int putsec(int fd
, uchar
*place
, vlong lba
, int nsec
)
202 aoead(int fd
) // advertise the virtual blade
209 memset(p
, 0, sizeof *p
);
210 memset(p
->h
.dst
, 0xff, 6);
211 memmove(p
->h
.src
, mac
, 6);
212 p
->h
.type
= htons(0x88a2);
214 p
->h
.maj
= htons(shelf
);
217 p
->bufcnt
= htons(bufcnt
);
218 p
->scnt
= maxscnt
= (getmtu(sfd
, ifname
) - sizeof (Ata
)) / 512;
219 p
->firmware
= htons(FWV
);
220 p
->vercmd
= 0x10 | Qread
;
221 memcpy(p
->data
, config
, nconfig
);
222 p
->len
= htons(nconfig
);
224 if (putpkt(fd
, buf
, sizeof *p
- sizeof p
->data
+ nconfig
) == -1) {
225 perror("putpkt aoe id");
228 for (i
=0; i
<nmasks
; i
++) {
229 memcpy(p
->h
.dst
, &masks
[i
*Alen
], Alen
);
230 if (putpkt(fd
, buf
, sizeof *p
- sizeof p
->data
+ nconfig
) == -1)
231 perror("putpkt aoe id");
238 uchar
*b
= (uchar
*)"\377\377\377\377\377\377";
240 return memcmp(ea
, b
, 6) == 0;
250 for (i
= 0; i
< 6; i
++)
251 v
|= (vlong
)(*p
++) << i
* 8;
256 aoeata(Ata
*p
, int pktlen
) // do ATA reqeust
262 r
.lba
= getlba(p
->lba
);
263 r
.sectors
= p
->sectors
;
267 if (!rrok(p
->h
.src
)) {
272 if (atacmd(&r
, (uchar
*)(p
+1), maxscnt
*512, pktlen
- sizeof(*p
)) < 0) {
277 if (!(p
->aflag
& Write
))
278 if ((n
= p
->sectors
)) {
280 len
= sizeof (Ata
) + (n
*512);
282 p
->sectors
= r
.sectors
;
288 #define QCMD(x) ((x)->vercmd & 0xf)
290 // yes, this makes unnecessary copies.
293 confcmd(Conf
*p
, int payload
) // process conf request
298 if (QCMD(p
) != Qread
)
299 if (len
> Nconfig
|| len
> payload
)
300 return 0; // if you can't play nice ...
309 if (memcmp(config
, p
->data
, len
))
316 if (nconfig
!= len
|| memcmp(config
, p
->data
, len
)) {
318 p
->h
.error
= ConfigErr
;
324 memcpy(config
, p
->data
, nconfig
);
330 memmove(p
->data
, config
, nconfig
);
331 p
->len
= htons(nconfig
);
332 p
->bufcnt
= htons(bufcnt
);
333 p
->scnt
= maxscnt
= (getmtu(sfd
, ifname
) - sizeof (Ata
)) / 512;
334 p
->firmware
= htons(FWV
);
335 p
->vercmd
= 0x10 | QCMD(p
); // aoe v.1
336 return nconfig
+ sizeof *p
- sizeof p
->data
;
340 aoesrr(Aoesrr
*sh
, int len
)
345 e
= (uchar
*) sh
+ len
;
346 m
= (uchar
*) sh
+ Nsrrhdr
;
349 e
: sh
->h
.error
= BadArg
;
350 sh
->h
.flags
|= Error
;
353 if (!rrok(sh
->h
.src
)) {
355 sh
->h
.flags
|= Error
;
382 if (!memcmp(p
, ea
, 6))
384 if (nmasks
>= Nmasks
)
399 if (!memcmp(p
, ea
, 6)) {
400 memmove(p
, p
+6, e
-p
-6);
407 aoemask(Aoemask
*mh
, int len
)
409 Mdir
*md
, *mdi
, *mde
;
413 md
= mdi
= (Mdir
*) ((uchar
*)mh
+ Nmaskhdr
);
416 mde
= md
+ mh
->nmacs
;
417 for (; md
<mde
; md
++) {
423 if (addmask(md
->mac
))
426 mh
->nmacs
= md
- mdi
;
431 mh
->merror
= MEbaddir
;
432 mh
->nmacs
= md
- mdi
;
436 // success. fall thru to return list
439 for (i
=0; i
<nmasks
; i
++) {
440 md
->res
= md
->cmd
= 0;
441 memmove(md
->mac
, &masks
[i
*6], 6);
446 n
= sizeof *md
* nmasks
;
449 mh
->h
.flags
|= Error
;
450 mh
->h
.error
= BadArg
;
452 e
: return n
+ Nmaskhdr
;
456 doaoe(Aoehdr
*p
, int n
)
464 len
= aoeata((Ata
*)p
, n
);
469 len
= confcmd((Conf
*)p
, n
);
474 len
= aoemask((Aoemask
*)p
, n
);
479 len
= aoesrr((Aoesrr
*)p
, n
);
489 memmove(p
->dst
, p
->src
, 6);
490 memmove(p
->src
, mac
, 6);
491 p
->maj
= htons(shelf
);
494 if (putpkt(sfd
, (uchar
*) p
, len
) == -1) {
495 perror("write to network");
507 enum { bufsz
= 1<<16, };
509 if ((pagesz
= sysconf(_SC_PAGESIZE
)) < 0) {
513 if ((buf
= malloc(bufsz
+ pagesz
)) == NULL
) {
517 n
= (size_t) buf
+ sizeof(Ata
);
518 if (n
& (pagesz
- 1))
519 buf
+= pagesz
- (n
& (pagesz
- 1));
524 n
= getpkt(sfd
, buf
, bufsz
);
526 perror("read network");
529 if (n
< sizeof(Aoehdr
))
532 if (ntohs(p
->type
) != 0x88a2)
537 if (sh
!= shelf
&& sh
!= (ushort
)~0)
539 if (p
->min
!= slot
&& p
->min
!= (uchar
)~0)
541 if (nmasks
&& !maskok(p
->src
))
550 fprintf(stderr
, "usage: %s [-b bufcnt] [-o offset] [-l length] [-d ] [-s] [-r] [ -m mac[,mac...] ] shelf slot netif filename\n",
555 /* parseether from plan 9 */
557 parseether(uchar
*to
, char *from
)
564 for(i
= 0; i
< 6; i
++){
572 to
[i
] = strtoul(nip
, 0, 16);
589 n
= parseether(&masks
[nmasks
*Alen
], ml
);
591 fprintf(stderr
, "ignoring mask %s, parseether failure\n", ml
);
602 for (i
=0; !ok
&& i
<nmasks
; i
++)
603 ok
= memcmp(ea
, &masks
[i
*Alen
], Alen
) == 0;
614 for (i
=0; !ok
&& i
<nsrr
; i
++)
615 ok
= memcmp(ea
, &srr
[i
*Alen
], Alen
) == 0;
620 setserial(int sh
, int sl
)
625 gethostname(h
, sizeof h
);
626 snprintf(serial
, Nserial
, "%d.%d:%.*s", sh
, sl
, (int) sizeof h
, h
);
630 main(int argc
, char **argv
)
632 int ch
, omode
= 0, readonly
= 0;
635 char filepath
[300] = {0};
637 /* Avoid to be killed by systemd */
638 if (access("/etc/initrd-release", F_OK
) >= 0)
647 while ((ch
= getopt(argc
, argv
, "b:dsrm:f:tv::o:l:")) != -1) {
650 bufcnt
= atoi(optarg
);
672 strncpy(filepath
, optarg
, sizeof(filepath
) - 1);
675 offset
= strtoll(optarg
, &end
, 0);
676 if (end
== optarg
|| offset
< 0)
680 length
= strtoll(optarg
, &end
, 0);
681 if (end
== optarg
|| length
< 1)
691 if (argc
!= 4 || bufcnt
<= 0)
693 omode
|= readonly
? O_RDONLY
: O_RDWR
;
694 parse_img_chunk(filepath
);
695 bfd
= open(argv
[3], omode
);
700 shelf
= atoi(argv
[0]);
701 slot
= atoi(argv
[1]);
702 setserial(shelf
, slot
);
703 size
= g_iso_file_size
; //getsize(bfd);
705 if (size
<= offset
) {
708 "Offset %lld too large for %lld-sector export\n",
712 fputs("0-sector file size is too small\n", stderr
);
718 fprintf(stderr
, "Length %llu too big - exceeds size of file!\n", offset
);
724 sfd
= dial(ifname
, bufcnt
);
727 getea(sfd
, ifname
, mac
);
730 printf("pid %ld: e%d.%d, %lld sectors %s\n",
731 (long) getpid(), shelf
, slot
, size
,
732 readonly
? "O_RDONLY" : "O_RDWR");