xref: /plan9/sys/src/9/boot/usb.c (revision 217e9e83c7f9cc6fb27d97dda90c8339b6f98728)
1 /* usb support */
2 
3 #include <u.h>
4 #include <libc.h>
5 #include <auth.h>
6 #include <fcall.h>
7 #include "../boot/boot.h"
8 
9 #define PARTSRV "partfs.sdXX"
10 
11 enum {
12 	Dontpost,
13 	Post,
14 };
15 
16 static char usbdisk0[] = "/dev/sdU0.0";
17 static char sdxxctl[]  = "/dev/sdXX/ctl";
18 
19 /*
20  * run argv[0] (short name is name) and wait awhile for file to appear.
21  * file must be generated by running argv[0]; if it already exists, we're done.
22  */
23 static int
start(char * name,char ** argv,char * file)24 start(char *name, char **argv, char *file)
25 {
26 	int cnt;
27 
28 	if(access(file, AEXIST) >= 0)
29 		return 0;
30 	if(access(argv[0], AEXIST) < 0) {
31 		fprint(2, "no %s...", argv[0]);
32 		return -1;
33 	}
34 
35 	dprint("%s...", name);
36 	runv(argv);
37 	for(cnt = 10; cnt > 0 && access(file, AEXIST) < 0; cnt--)
38 		sleep(100);
39 	if (cnt <= 0) {
40 		dprint("no %s...", file);
41 		return -1;
42 	}
43 	return 0;
44 }
45 
46 int
chmod(char * file,int mode)47 chmod(char *file, int mode)
48 {
49 	Dir *dir;
50 
51 	dir = dirstat(file);
52 	if (dir == nil) {
53 		dprint("can't stat %s: %r\n", file);
54 		return -1;
55 	}
56 	dir->mode &= ~0777;
57 	dir->mode |= mode & 0777;
58 	dirwstat("/srv/" PARTSRV, dir);
59 	free(dir);
60 	return 0;
61 }
62 
63 /* start partfs on first usb disk, if any.  optionally post partfs in /srv. */
64 static int
startpartfs(int post)65 startpartfs(int post)
66 {
67 	int r, i;
68 	char *parts;
69 	char *partfsv[32];
70 
71 	if(access(usbdisk0, AEXIST) < 0)
72 		return -1;	/* can't run partfs until usbd is mounted */
73 
74 	if (post)
75 		remove("/srv/" PARTSRV);
76 
77 	i = 0;
78 	partfsv[i++] = "/boot/partfs";
79 	/*
80 	 * hack for booting from usb: if /env/sdB0part (from 9load) exists,
81 	 * pass it to partfs for sdXX.
82 	 */
83 	parts = getenv("sdB0part");
84 	if (parts != nil) {
85 		partfsv[i++] = "-p";
86 		partfsv[i++] = parts;
87 	}
88 	if (post) {
89 		partfsv[i++] = "-s";
90 		partfsv[i++] = PARTSRV;
91 	}
92 	partfsv[i++] = usbdisk0;
93 	partfsv[i] = nil;
94 	r = start("partfs", partfsv, sdxxctl);
95 
96 	if (post)
97 		chmod("/srv/" PARTSRV, 0666);
98 	return r;
99 }
100 
101 static int
mountusb(void)102 mountusb(void)
103 {
104 	int fd;
105 
106 	dprint("mount usbd...");
107 	fd = open("/srv/usb", ORDWR);
108 	if(fd < 0)
109 		warning("can't open /srv/usb");
110 	else if(mount(fd, -1, "/dev", MBEFORE, "") < 0) {
111 		warning("mount -a /srv/usb /dev");
112 		close(fd);
113 	} else
114 		return 0;		/* mount closed fd */
115 	return -1;
116 }
117 
118 int
mountusbparts(void)119 mountusbparts(void)
120 {
121 	mountusb();
122 	return startpartfs(Post);
123 }
124 
125 /*
126  *  start usbd, which mounts itself on /dev.
127  *  start partfs on first disk, if any, to permit nvram on usb.
128  */
129 void
usbinit(int post)130 usbinit(int post)
131 {
132 	int cnt;
133 	static char *usbdv[] = { "/boot/usbd", nil };
134 
135 	if(access("#u/usb/ctl", AEXIST) < 0 || bind("#u", "/dev", MAFTER) < 0)
136 		return;
137 	dprint("usbinit...");
138 	start("usbd", usbdv, "/srv/usb");
139 
140 	/* allow a little time for usbd's device discovery */
141 	for(cnt = 20; cnt > 0 && access(usbdisk0, AEXIST) < 0; cnt--)
142 		sleep(100);
143 	if(cnt > 0)
144 		startpartfs(post);
145 	else
146 		dprint("no usb disk...");
147 }
148