xref: /plan9-contrib/sys/src/9k/boot/usb.c (revision 9737c4be2bb3615215e2d82cc9d998b5b1e5e6a1)
1532111f7SDavid du Colombier /* usb support */
2532111f7SDavid du Colombier 
3532111f7SDavid du Colombier #include <u.h>
4532111f7SDavid du Colombier #include <libc.h>
5532111f7SDavid du Colombier #include <auth.h>
6532111f7SDavid du Colombier #include <fcall.h>
7532111f7SDavid du Colombier #include "../boot/boot.h"
8532111f7SDavid du Colombier 
9532111f7SDavid du Colombier #define PARTSRV "partfs.sdXX"
10532111f7SDavid du Colombier 
11532111f7SDavid du Colombier enum {
12532111f7SDavid du Colombier 	Dontpost,
13532111f7SDavid du Colombier 	Post,
14532111f7SDavid du Colombier };
15532111f7SDavid du Colombier 
16532111f7SDavid du Colombier static char usbdisk0[] = "/dev/sdU0.0";
17532111f7SDavid du Colombier static char sdxxctl[]  = "/dev/sdXX/ctl";
18532111f7SDavid du Colombier 
19532111f7SDavid du Colombier /*
20532111f7SDavid du Colombier  * run argv[0] (short name is name) and wait awhile for file to appear.
21532111f7SDavid du Colombier  * file must be generated by running argv[0]; if it already exists, we're done.
22532111f7SDavid du Colombier  */
23532111f7SDavid du Colombier static int
start(char * name,char ** argv,char * file)24532111f7SDavid du Colombier start(char *name, char **argv, char *file)
25532111f7SDavid du Colombier {
26532111f7SDavid du Colombier 	int cnt;
27532111f7SDavid du Colombier 
28532111f7SDavid du Colombier 	if(access(file, AEXIST) >= 0)
29532111f7SDavid du Colombier 		return 0;
30532111f7SDavid du Colombier 	if(access(argv[0], AEXIST) < 0) {
31532111f7SDavid du Colombier 		fprint(2, "no %s...", argv[0]);
32532111f7SDavid du Colombier 		return -1;
33532111f7SDavid du Colombier 	}
34532111f7SDavid du Colombier 
35532111f7SDavid du Colombier 	dprint("%s...", name);
36532111f7SDavid du Colombier 	runv(argv);
37532111f7SDavid du Colombier 	for(cnt = 10; cnt > 0 && access(file, AEXIST) < 0; cnt--)
38532111f7SDavid du Colombier 		sleep(100);
39532111f7SDavid du Colombier 	if (cnt <= 0) {
40532111f7SDavid du Colombier 		dprint("no %s...", file);
41532111f7SDavid du Colombier 		return -1;
42532111f7SDavid du Colombier 	}
43532111f7SDavid du Colombier 	return 0;
44532111f7SDavid du Colombier }
45532111f7SDavid du Colombier 
46532111f7SDavid du Colombier int
chmod(char * file,int mode)47532111f7SDavid du Colombier chmod(char *file, int mode)
48532111f7SDavid du Colombier {
49532111f7SDavid du Colombier 	Dir *dir;
50532111f7SDavid du Colombier 
51532111f7SDavid du Colombier 	dir = dirstat(file);
52532111f7SDavid du Colombier 	if (dir == nil) {
53532111f7SDavid du Colombier 		dprint("can't stat %s: %r\n", file);
54532111f7SDavid du Colombier 		return -1;
55532111f7SDavid du Colombier 	}
56532111f7SDavid du Colombier 	dir->mode &= ~0777;
57532111f7SDavid du Colombier 	dir->mode |= mode & 0777;
58532111f7SDavid du Colombier 	dirwstat("/srv/" PARTSRV, dir);
59532111f7SDavid du Colombier 	free(dir);
60532111f7SDavid du Colombier 	return 0;
61532111f7SDavid du Colombier }
62532111f7SDavid du Colombier 
63532111f7SDavid du Colombier /* start partfs on first usb disk, if any.  optionally post partfs in /srv. */
64532111f7SDavid du Colombier static int
startpartfs(int post)65532111f7SDavid du Colombier startpartfs(int post)
66532111f7SDavid du Colombier {
67532111f7SDavid du Colombier 	int r, i;
68532111f7SDavid du Colombier 	char *parts;
69532111f7SDavid du Colombier 	char *partfsv[32];
70532111f7SDavid du Colombier 
71532111f7SDavid du Colombier 	if(access(usbdisk0, AEXIST) < 0)
72532111f7SDavid du Colombier 		return -1;	/* can't run partfs until usbd is mounted */
73532111f7SDavid du Colombier 
74532111f7SDavid du Colombier 	if (post)
75532111f7SDavid du Colombier 		remove("/srv/" PARTSRV);
76532111f7SDavid du Colombier 
77532111f7SDavid du Colombier 	i = 0;
78532111f7SDavid du Colombier 	partfsv[i++] = "/boot/partfs";
79532111f7SDavid du Colombier 	/*
80532111f7SDavid du Colombier 	 * hack for booting from usb: if /env/sdB0part (from 9load) exists,
81532111f7SDavid du Colombier 	 * pass it to partfs for sdXX.
82532111f7SDavid du Colombier 	 */
83532111f7SDavid du Colombier 	parts = getenv("sdB0part");
84532111f7SDavid du Colombier 	if (parts != nil) {
85532111f7SDavid du Colombier 		partfsv[i++] = "-p";
86532111f7SDavid du Colombier 		partfsv[i++] = parts;
87532111f7SDavid du Colombier 	}
88532111f7SDavid du Colombier 	if (post) {
89532111f7SDavid du Colombier 		partfsv[i++] = "-s";
90532111f7SDavid du Colombier 		partfsv[i++] = PARTSRV;
91532111f7SDavid du Colombier 	}
92532111f7SDavid du Colombier 	partfsv[i++] = usbdisk0;
93532111f7SDavid du Colombier 	partfsv[i] = nil;
94532111f7SDavid du Colombier 	r = start("partfs", partfsv, sdxxctl);
95532111f7SDavid du Colombier 
96532111f7SDavid du Colombier 	if (post)
97532111f7SDavid du Colombier 		chmod("/srv/" PARTSRV, 0666);
98532111f7SDavid du Colombier 	return r;
99532111f7SDavid du Colombier }
100532111f7SDavid du Colombier 
101532111f7SDavid du Colombier static int
mountusb(void)102532111f7SDavid du Colombier mountusb(void)
103532111f7SDavid du Colombier {
104532111f7SDavid du Colombier 	int fd;
105532111f7SDavid du Colombier 
106532111f7SDavid du Colombier 	dprint("mount usbd...");
107532111f7SDavid du Colombier 	fd = open("/srv/usb", ORDWR);
108532111f7SDavid du Colombier 	if(fd < 0)
109*9737c4beSDavid du Colombier 		dprint("can't open /srv/usb");
110532111f7SDavid du Colombier 	else if(mount(fd, -1, "/dev", MBEFORE, "") < 0) {
111532111f7SDavid du Colombier 		warning("mount -a /srv/usb /dev");
112532111f7SDavid du Colombier 		close(fd);
113532111f7SDavid du Colombier 	} else
114532111f7SDavid du Colombier 		return 0;		/* mount closed fd */
115532111f7SDavid du Colombier 	return -1;
116532111f7SDavid du Colombier }
117532111f7SDavid du Colombier 
118532111f7SDavid du Colombier int
mountusbparts(void)119532111f7SDavid du Colombier mountusbparts(void)
120532111f7SDavid du Colombier {
121532111f7SDavid du Colombier 	mountusb();
122532111f7SDavid du Colombier 	return startpartfs(Post);
123532111f7SDavid du Colombier }
124532111f7SDavid du Colombier 
125532111f7SDavid du Colombier /*
126532111f7SDavid du Colombier  *  start usbd, which mounts itself on /dev.
127532111f7SDavid du Colombier  *  start partfs on first disk, if any, to permit nvram on usb.
128532111f7SDavid du Colombier  */
129532111f7SDavid du Colombier void
usbinit(int post)130532111f7SDavid du Colombier usbinit(int post)
131532111f7SDavid du Colombier {
132532111f7SDavid du Colombier 	int cnt;
133532111f7SDavid du Colombier 	static char *usbdv[] = { "/boot/usbd", nil };
134532111f7SDavid du Colombier 
135532111f7SDavid du Colombier 	if(access("#u/usb/ctl", AEXIST) < 0 || bind("#u", "/dev", MAFTER) < 0)
136532111f7SDavid du Colombier 		return;
137532111f7SDavid du Colombier 	dprint("usbinit...");
138532111f7SDavid du Colombier 	start("usbd", usbdv, "/srv/usb");
139532111f7SDavid du Colombier 
140532111f7SDavid du Colombier 	/* allow a little time for usbd's device discovery */
141532111f7SDavid du Colombier 	for(cnt = 20; cnt > 0 && access(usbdisk0, AEXIST) < 0; cnt--)
142532111f7SDavid du Colombier 		sleep(100);
143532111f7SDavid du Colombier 	if(cnt > 0)
144532111f7SDavid du Colombier 		startpartfs(post);
145532111f7SDavid du Colombier 	else
146532111f7SDavid du Colombier 		dprint("no usb disk...");
147532111f7SDavid du Colombier }
148