]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/xen/dpart.c
bcm: flush out early boot messages on uart and screen initialization
[plan9front.git] / sys / src / 9 / xen / dpart.c
1 #include <u.h>
2 #include <libc.h>
3 #include <disk.h>
4
5 typedef void Fs;
6 #include "/sys/src/boot/pc/dosfs.h"
7
8 enum {
9         Npart = 32
10 };
11
12 #define GSHORT(p)               (((p)[1]<<8)|(p)[0])
13 #define GLONG(p)                        ((GSHORT(p+2)<<16)|GSHORT(p))
14
15 int
16 readdisk(Disk *d, void *buf, vlong off, int len)
17 {
18         if(seek(d->fd, off, 0) == -1
19         || read(d->fd, buf, len) != len)
20                 return -1;
21         return 0;
22 }
23
24 void
25 addpart(Disk *d, char *name, ulong s, ulong e)
26 {
27         print("%s: part %s %lud %lud\n", d->prefix, name, s, e);
28         fprint(d->ctlfd, "part %s %lud %lud\n", name, s, e);
29 }
30
31 int
32 isdos(int t)
33 {
34         return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X;
35 }
36
37 int
38 isextend(int t)
39 {
40         return t==EXTEND || t==EXTHUGE || t==LEXTEND;
41 }
42
43
44
45 /* build a cdboot partition if there is an embedded boot floppy image */
46 int
47 cdpart(Disk *d)
48 {
49         uchar buf[2048];
50         ulong a, n;
51         uchar *p;
52
53         if(readdisk(d, buf, 17*2048, 2048) == -1
54         || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0)
55                 return 0;
56
57         p = buf + 0x47;
58         a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
59         
60         if(readdisk(d, buf, a*2048, 2048) == -1
61         || memcmp((char*)buf, "\x01\x00\x00\x00", 4) != 0
62         || memcmp((char*)buf+30, "\x55\xAA", 2) != 0
63         || buf[0x20] != 0x88)
64                 return 0;
65
66         p = buf+0x28;
67         a = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
68
69         switch(buf[0x21]) {
70         case 1: n = 1200*1024; break;
71         case 2: n = 1440*1024; break;
72         case 3: n = 2880*1024; break;
73         default: return 0;
74         }
75
76         a = a * (uvlong)2048 / d->secsize;
77         n /= d->secsize;
78         addpart(d, "cdboot", a, a+n);
79         return 1;
80 }
81
82 int
83 p9part(Disk *d, char *name, ulong pstart)
84 {
85         char partbuf[512];
86         char *field[4], *line[Npart+1], *name2;
87         ulong start, end;
88         int i, n;
89
90         name2 = smprint("%s%s", d->prefix, name);
91         d = opendisk(name2, 1, 0);
92         if(!d) {
93                 fprint(2, "%s: %r\n", name2);
94                 free(name2);
95                 return 0;
96         }
97         free(name2);
98
99         if(readdisk(d, partbuf, 512, sizeof partbuf) == -1)
100                 return 0;
101         partbuf[sizeof partbuf - 1] = '\0';
102         if(strncmp(partbuf, "part ", 5) != 0
103         || (n = getfields(partbuf, line, Npart+1, 0, "\n")) == 0)
104                 return 0;
105         for(i = 0; i < n; i++) {
106                 if(strncmp(line[i], "part ", 5) != 0)
107                         break;
108                 if(getfields(line[i], field, 4, 0, " ") != 4)
109                         break;
110                 start = strtoul(field[2], 0, 0);
111                 end = strtoul(field[3], 0, 0);
112                 if(start >= end)
113                         break;
114                 addpart(d, field[1], pstart+start, pstart+end);
115         }
116         return 0;
117 }
118
119 int
120 mbrpart(Disk *d)
121 {
122         uchar mbrbuf[512];
123         char name[10];
124         Dospart *dp;
125         ulong taboffset, start, end;
126         ulong firstxpart, nxtxpart;
127         int i, nplan9, havedos;
128
129 #define readmbr()       \
130         if(readdisk(d, mbrbuf, (uvlong)taboffset*512, sizeof mbrbuf) == -1      \
131         || mbrbuf[0x1FE] != 0x55 || mbrbuf[0x1FF] != 0xAA)      \
132                 return 0
133
134         if(d->secsize > 512)
135                 return 0;
136         dp = (Dospart*)&mbrbuf[0x1BE];
137         taboffset = 0;
138
139         if(1) {
140                 /* get the MBR (allowing for DMDDO) */
141                 readmbr();
142                 for(i = 0; i < 4; i++) {
143                         if(dp[i].type == DMDDO) {
144                                 taboffset = 63;
145                                 readmbr();
146                                 i = -1;         /* start over */
147                         }
148                 }
149         }
150
151         /*
152          * Read the partitions, first from the MBR and then
153          * from successive extended partition tables.
154          */
155         nplan9 = 0;
156         havedos = 0;
157         firstxpart = 0;
158         for(;;) {
159                 readmbr();
160                 nxtxpart = 0;
161                 for(i = 0; i < 4; i++) {
162                         /* partition offsets are relative to taboffset */
163                         start = taboffset+GLONG(dp[i].start);
164                         end = start+GLONG(dp[i].len);
165                         if(dp[i].type == PLAN9) {
166                                 if(nplan9 == 0)
167                                         strcpy(name, "plan9");
168                                 else
169                                         sprint(name, "plan9.%d", nplan9);
170                                 addpart(d, name, start, end);
171                                 p9part(d, name, start);
172                                 nplan9++;
173                         }
174
175                         if(!havedos && isdos(dp[i].type)) {
176                                 havedos = 1;
177                                 addpart(d, "dos", start, end);
178                         }
179
180                         /* nxtxpart is relative to firstxpart (or 0), not taboffset */
181                         if(isextend(dp[i].type))
182                                 nxtxpart = start-taboffset+firstxpart;
183                 }
184                 if(!nxtxpart)
185                         break;
186                 if(!firstxpart)
187                         firstxpart = nxtxpart;
188                 taboffset = nxtxpart;
189         }
190         return nplan9 + havedos;
191 }
192
193 void
194 partall(void)
195 {
196         Disk *d;
197         Dir *ent;
198         char *name;
199         int fd, i, n;
200
201         fd = open("#S", OREAD);
202         if(fd == -1) {
203                 fprint(2, "No disk\n");
204                 return;
205         }
206
207         while((n = dirread(fd, &ent)) > 0) {
208                 for(i = 0; i < n; i++) {
209                         if(ent[i].mode & DMDIR) {
210                                 name = smprint("#S/%s/data", ent[i].name);
211                                 d = opendisk(name, 1, 0);
212                                 if(!d) {
213                                         fprint(2, "%s: %r\n", name);
214                                         continue;
215                                 }
216                                 // XXX not safe yet: if(!mbrpart(d) && !cdpart(d) && !p9part(d, "data", 0))
217                                 if(!mbrpart(d) && !cdpart(d))
218                                         fprint(2, "%s: no partitions\n", name);
219                                 close(d->fd);
220                         }
221                 }
222         }
223         close(fd);                              
224 }
225
226
227 void
228 main(int argc, char **argv)
229 {
230         USED(argc, argv);
231
232         fmtinstall('r', errfmt);
233
234         bind("#c", "/dev", MBEFORE);
235         open("/dev/cons", OREAD);
236         open("/dev/cons", OWRITE);
237         open("/dev/cons", OWRITE);
238
239         partall();
240
241         close(0);
242         close(1);
243         close(2);
244
245         exec("/boot/boot2", argv);
246         
247         exits(0);
248 }