143 lines · 2.3 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <fis.h>#include "dat.h" typedef	struct	Dl	Dl;struct Dl {	char	*firmware;	uint	length;	uint	okfw;}; static	Sdisk	*disks;static	Dl	dl;static	Dtype	dtab[] = {	Tata,	"ata",	ataprobe,	atadl,	Tscsi,	"scsi",	scsiprobe,	nil,}; voideprint(Sdisk *d, char *s, ...){	char buf[256];	va_list arg; 	va_start(arg, s);	vseprint(buf, buf + sizeof buf, s, arg);	va_end(arg);	fprint(2, "%s: %s", d->name, buf);} voidfirmware(char *f){	int fd;	Dir *d; 	fd = open(f, OREAD);	if(fd == -1)		sysfatal("open: %r");	d = dirfstat(fd);	if(d == nil)		sysfatal("dirfstat: %r");	if(d->length/512 > 1ul<<16 || d->length&0x1ff)		sysfatal("firmware length: %llux", d->length);	dl.length = d->length;	free(d); 	dl.firmware = realloc(dl.firmware, dl.length);	if(readn(fd, dl.firmware, dl.length) != dl.length)		sysfatal("readn: %r");	dl.okfw = 1;} static intdiskopen(Sdisk *d){	char buf[128]; 	snprint(buf, sizeof buf, "%s/raw", d->path);	werrstr("");	return d->fd = open(buf, ORDWR);} static voiddiskclose(Sdisk *d){	close(d->fd);	d->fd = -1;} static intnewdisk(char *s){	char buf[128], *p;	int i;	Sdisk d; 	memset(&d, 0, sizeof d);	snprint(d.path, sizeof d.path, "%s", s);	if(p = strrchr(s, '/'))		p++;	else		p = s;	snprint(d.name, sizeof d.name, "%s", p);	snprint(buf, sizeof buf, "%s/raw", s);	if(diskopen(&d) == -1)		return -1;	for(i = 0; i < nelem(dtab); i++)		if(dtab[i].probe(&d) == 0){			d.t = dtab + i;			break;		}	diskclose(&d);	if(d.t != 0){		d.next = disks;		disks = malloc(sizeof d);		memmove(disks, &d, sizeof d);		return 0;	}	werrstr("unknown disk protocol");	return -1;} voidusage(void){	fprint(2, "usage: dlmicrocode -f fw disk ...\n");	exits("usage");} voidmain(int argc, char **argv){	int i;	Sdisk *d; 	ARGBEGIN{	case 'f':		firmware(EARGF(usage()));		break;	default:		usage();	}ARGEND 	if(dl.okfw != 1)		usage(); 	for(i = 0; i < argc; i++)		if(newdisk(argv[i]) != 0)			sysfatal("bad disk");		else if(disks->t->dlmc == nil)			sysfatal("no dlmc function"); 	for(d = disks; d != nil; d = d->next){		print("%s\n", d->path);		if(diskopen(d) == -1)			sysfatal("diskopen: %r");		if(d->t->dlmc(d, dl.firmware, dl.length) == -1)			sysfatal("disk bricked");		diskclose(d);	}}