xref: /plan9/sys/src/9/boot/usb.c (revision 217e9e83c7f9cc6fb27d97dda90c8339b6f98728)
163c59e25SDavid du Colombier /* usb support */
263c59e25SDavid du Colombier 
363c59e25SDavid du Colombier #include <u.h>
463c59e25SDavid du Colombier #include <libc.h>
563c59e25SDavid du Colombier #include <auth.h>
663c59e25SDavid du Colombier #include <fcall.h>
763c59e25SDavid du Colombier #include "../boot/boot.h"
863c59e25SDavid du Colombier 
963c59e25SDavid du Colombier #define PARTSRV "partfs.sdXX"
1063c59e25SDavid du Colombier 
1163c59e25SDavid du Colombier enum {
1263c59e25SDavid du Colombier 	Dontpost,
1363c59e25SDavid du Colombier 	Post,
1463c59e25SDavid du Colombier };
1563c59e25SDavid du Colombier 
1663c59e25SDavid du Colombier static char usbdisk0[] = "/dev/sdU0.0";
1763c59e25SDavid du Colombier static char sdxxctl[]  = "/dev/sdXX/ctl";
1863c59e25SDavid du Colombier 
1963c59e25SDavid du Colombier /*
2063c59e25SDavid du Colombier  * run argv[0] (short name is name) and wait awhile for file to appear.
2163c59e25SDavid du Colombier  * file must be generated by running argv[0]; if it already exists, we're done.
2263c59e25SDavid du Colombier  */
2363c59e25SDavid du Colombier static int
start(char * name,char ** argv,char * file)2463c59e25SDavid du Colombier start(char *name, char **argv, char *file)
2563c59e25SDavid du Colombier {
2663c59e25SDavid du Colombier 	int cnt;
2763c59e25SDavid du Colombier 
2863c59e25SDavid du Colombier 	if(access(file, AEXIST) >= 0)
2963c59e25SDavid du Colombier 		return 0;
3063c59e25SDavid du Colombier 	if(access(argv[0], AEXIST) < 0) {
3163c59e25SDavid du Colombier 		fprint(2, "no %s...", argv[0]);
3263c59e25SDavid du Colombier 		return -1;
3363c59e25SDavid du Colombier 	}
3463c59e25SDavid du Colombier 
35*217e9e83SDavid du Colombier 	dprint("%s...", name);
3663c59e25SDavid du Colombier 	runv(argv);
3763c59e25SDavid du Colombier 	for(cnt = 10; cnt > 0 && access(file, AEXIST) < 0; cnt--)
3863c59e25SDavid du Colombier 		sleep(100);
3963c59e25SDavid du Colombier 	if (cnt <= 0) {
40*217e9e83SDavid du Colombier 		dprint("no %s...", file);
4163c59e25SDavid du Colombier 		return -1;
4263c59e25SDavid du Colombier 	}
4363c59e25SDavid du Colombier 	return 0;
4463c59e25SDavid du Colombier }
4563c59e25SDavid du Colombier 
4663c59e25SDavid du Colombier int
chmod(char * file,int mode)4763c59e25SDavid du Colombier chmod(char *file, int mode)
4863c59e25SDavid du Colombier {
4963c59e25SDavid du Colombier 	Dir *dir;
5063c59e25SDavid du Colombier 
5163c59e25SDavid du Colombier 	dir = dirstat(file);
5263c59e25SDavid du Colombier 	if (dir == nil) {
53*217e9e83SDavid du Colombier 		dprint("can't stat %s: %r\n", file);
5463c59e25SDavid du Colombier 		return -1;
5563c59e25SDavid du Colombier 	}
5663c59e25SDavid du Colombier 	dir->mode &= ~0777;
5763c59e25SDavid du Colombier 	dir->mode |= mode & 0777;
5863c59e25SDavid du Colombier 	dirwstat("/srv/" PARTSRV, dir);
5963c59e25SDavid du Colombier 	free(dir);
6063c59e25SDavid du Colombier 	return 0;
6163c59e25SDavid du Colombier }
6263c59e25SDavid du Colombier 
6328684b1dSDavid du Colombier /* start partfs on first usb disk, if any.  optionally post partfs in /srv. */
6463c59e25SDavid du Colombier static int
startpartfs(int post)6563c59e25SDavid du Colombier startpartfs(int post)
6663c59e25SDavid du Colombier {
6763c59e25SDavid du Colombier 	int r, i;
6863c59e25SDavid du Colombier 	char *parts;
6963c59e25SDavid du Colombier 	char *partfsv[32];
7063c59e25SDavid du Colombier 
7163c59e25SDavid du Colombier 	if(access(usbdisk0, AEXIST) < 0)
7263c59e25SDavid du Colombier 		return -1;	/* can't run partfs until usbd is mounted */
7363c59e25SDavid du Colombier 
7463c59e25SDavid du Colombier 	if (post)
7563c59e25SDavid du Colombier 		remove("/srv/" PARTSRV);
7663c59e25SDavid du Colombier 
7763c59e25SDavid du Colombier 	i = 0;
7863c59e25SDavid du Colombier 	partfsv[i++] = "/boot/partfs";
7963c59e25SDavid du Colombier 	/*
8063c59e25SDavid du Colombier 	 * hack for booting from usb: if /env/sdB0part (from 9load) exists,
8163c59e25SDavid du Colombier 	 * pass it to partfs for sdXX.
8263c59e25SDavid du Colombier 	 */
8363c59e25SDavid du Colombier 	parts = getenv("sdB0part");
8463c59e25SDavid du Colombier 	if (parts != nil) {
8563c59e25SDavid du Colombier 		partfsv[i++] = "-p";
8663c59e25SDavid du Colombier 		partfsv[i++] = parts;
8763c59e25SDavid du Colombier 	}
8863c59e25SDavid du Colombier 	if (post) {
8963c59e25SDavid du Colombier 		partfsv[i++] = "-s";
9063c59e25SDavid du Colombier 		partfsv[i++] = PARTSRV;
9163c59e25SDavid du Colombier 	}
9263c59e25SDavid du Colombier 	partfsv[i++] = usbdisk0;
9363c59e25SDavid du Colombier 	partfsv[i] = nil;
9463c59e25SDavid du Colombier 	r = start("partfs", partfsv, sdxxctl);
9563c59e25SDavid du Colombier 
9663c59e25SDavid du Colombier 	if (post)
9763c59e25SDavid du Colombier 		chmod("/srv/" PARTSRV, 0666);
9863c59e25SDavid du Colombier 	return r;
9963c59e25SDavid du Colombier }
10063c59e25SDavid du Colombier 
10163c59e25SDavid du Colombier static int
mountusb(void)10263c59e25SDavid du Colombier mountusb(void)
10363c59e25SDavid du Colombier {
10463c59e25SDavid du Colombier 	int fd;
10563c59e25SDavid du Colombier 
106*217e9e83SDavid du Colombier 	dprint("mount usbd...");
10763c59e25SDavid du Colombier 	fd = open("/srv/usb", ORDWR);
10863c59e25SDavid du Colombier 	if(fd < 0)
10963c59e25SDavid du Colombier 		warning("can't open /srv/usb");
11063c59e25SDavid du Colombier 	else if(mount(fd, -1, "/dev", MBEFORE, "") < 0) {
11163c59e25SDavid du Colombier 		warning("mount -a /srv/usb /dev");
11263c59e25SDavid du Colombier 		close(fd);
11363c59e25SDavid du Colombier 	} else
11463c59e25SDavid du Colombier 		return 0;		/* mount closed fd */
11563c59e25SDavid du Colombier 	return -1;
11663c59e25SDavid du Colombier }
11763c59e25SDavid du Colombier 
11863c59e25SDavid du Colombier int
mountusbparts(void)11963c59e25SDavid du Colombier mountusbparts(void)
12063c59e25SDavid du Colombier {
12163c59e25SDavid du Colombier 	mountusb();
12263c59e25SDavid du Colombier 	return startpartfs(Post);
12363c59e25SDavid du Colombier }
12463c59e25SDavid du Colombier 
12528684b1dSDavid du Colombier /*
12628684b1dSDavid du Colombier  *  start usbd, which mounts itself on /dev.
12728684b1dSDavid du Colombier  *  start partfs on first disk, if any, to permit nvram on usb.
12828684b1dSDavid du Colombier  */
12963c59e25SDavid du Colombier void
usbinit(int post)13063c59e25SDavid du Colombier usbinit(int post)
13163c59e25SDavid du Colombier {
13263c59e25SDavid du Colombier 	int cnt;
13363c59e25SDavid du Colombier 	static char *usbdv[] = { "/boot/usbd", nil };
13463c59e25SDavid du Colombier 
1359607627cSDavid du Colombier 	if(access("#u/usb/ctl", AEXIST) < 0 || bind("#u", "/dev", MAFTER) < 0)
13663c59e25SDavid du Colombier 		return;
137*217e9e83SDavid du Colombier 	dprint("usbinit...");
13863c59e25SDavid du Colombier 	start("usbd", usbdv, "/srv/usb");
13963c59e25SDavid du Colombier 
14063c59e25SDavid du Colombier 	/* allow a little time for usbd's device discovery */
14163c59e25SDavid du Colombier 	for(cnt = 20; cnt > 0 && access(usbdisk0, AEXIST) < 0; cnt--)
14263c59e25SDavid du Colombier 		sleep(100);
14363c59e25SDavid du Colombier 	if(cnt > 0)
14463c59e25SDavid du Colombier 		startpartfs(post);
145*217e9e83SDavid du Colombier 	else
146*217e9e83SDavid du Colombier 		dprint("no usb disk...");
14763c59e25SDavid du Colombier }
148