]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libdisk/open_disk.c
This commit was generated by cvs2svn to compensate for changes in r165071,
[FreeBSD/FreeBSD.git] / lib / libdisk / open_disk.c
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  */
9
10 #include <sys/cdefs.h>
11 __FBSDID("$FreeBSD$");
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <string.h>
18 #include <inttypes.h>
19 #include <err.h>
20 #include <sys/sysctl.h>
21 #include <sys/stdint.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/ioctl.h>
25 #include <sys/disklabel.h>
26 #include <sys/gpt.h>
27 #include <paths.h>
28 #include "libdisk.h"
29
30 #include <ctype.h>
31 #include <errno.h>
32 #include <assert.h>
33
34 #ifdef DEBUG
35 #define DPRINT(x)       warn x
36 #define DPRINTX(x)      warnx x
37 #else
38 #define DPRINT(x)
39 #define DPRINTX(x)
40 #endif
41
42 struct disk *
43 Int_Open_Disk(const char *name, char *conftxt)
44 {
45         struct disk *d;
46         int i;
47         char *p, *q, *r, *a, *b, *n, *t, *sn;
48         daddr_t o, len, off;
49         u_int l, s, ty, sc, hd, alt;
50         daddr_t lo[10];
51
52         for (p = conftxt; p != NULL && *p; p = strchr(p, '\n')) {
53                 if (*p == '\n')
54                         p++;
55                 a = strsep(&p, " ");
56                 if (strcmp(a, "0"))
57                         continue;
58
59                 a = strsep(&p, " ");
60                 if (strcmp(a, "DISK"))
61                         continue;
62
63                 a = strsep(&p, " ");
64                 if (strcmp(a, name))
65                         continue;
66                 break;
67         }
68
69         q = strchr(p, '\n');
70         if (q != NULL)
71                 *q++ = '\0';
72
73         d = (struct disk *)calloc(sizeof *d, 1);
74         if(d == NULL)
75                 return NULL;
76
77         d->name = strdup(name);
78
79         a = strsep(&p, " ");    /* length in bytes */
80         len = strtoimax(a, &r, 0);
81         if (*r) {
82                 printf("BARF %d <%d>\n", __LINE__, *r);
83                 exit (0);
84         }
85
86         a = strsep(&p, " ");    /* sectorsize */
87         s = strtoul(a, &r, 0);
88         if (*r) {
89                 printf("BARF %d <%d>\n", __LINE__, *r);
90                 exit (0);
91         }
92
93         if (s == 0)
94                 return (NULL);
95         d->sector_size = s;
96         len /= s;       /* media size in number of sectors. */
97
98         if (Add_Chunk(d, 0, len, name, whole, 0, 0, "-")) {
99                 DPRINT(("Failed to add 'whole' chunk"));
100         }
101
102         for (;;) {
103                 a = strsep(&p, " ");
104                 if (a == NULL)
105                         break;
106                 b = strsep(&p, " ");
107                 o = strtoimax(b, &r, 0);
108                 if (*r) {
109                         printf("BARF %d <%d>\n", __LINE__, *r);
110                         exit (0);
111                 }
112                 if (!strcmp(a, "hd"))
113                         d->bios_hd = o;
114                 else if (!strcmp(a, "sc"))
115                         d->bios_sect = o;
116                 else
117                         printf("HUH ? <%s> <%s>\n", a, b);
118         }
119
120         /*
121          * Calculate the number of cylinders this disk must have. If we have
122          * an obvious insanity, we set the number of cylinders to zero.
123          */
124         o = d->bios_hd * d->bios_sect;
125         d->bios_cyl = (o != 0) ? len / o : 0;
126
127         p = q;
128         lo[0] = 0;
129
130         for (; p != NULL && *p; p = q) {
131                 sn = NULL;
132                 q = strchr(p, '\n');
133                 if (q != NULL)
134                         *q++ = '\0';
135                 a = strsep(&p, " ");    /* Index */
136                 if (!strcmp(a, "0"))
137                         break;
138                 l = strtoimax(a, &r, 0);
139                 if (*r) {
140                         printf("BARF %d <%d>\n", __LINE__, *r);
141                         exit (0);
142                 }
143                 t = strsep(&p, " ");    /* Type {SUN, BSD, MBR, PC98, GPT} */
144                 n = strsep(&p, " ");    /* name */
145                 a = strsep(&p, " ");    /* len */
146                 len = strtoimax(a, &r, 0);
147                 if (*r) {
148                         printf("BARF %d <%d>\n", __LINE__, *r);
149                         exit (0);
150                 }
151                 a = strsep(&p, " ");    /* secsize */
152                 s = strtoimax(a, &r, 0);
153                 if (*r) {
154                         printf("BARF %d <%d>\n", __LINE__, *r);
155                         exit (0);
156                 }
157                 for (;;) {
158                         a = strsep(&p, " ");
159                         if (a == NULL)
160                                 break;
161                         /* XXX: Slice name may include a space. */
162                         if (!strcmp(a, "sn")) {
163                                 sn = p;
164                                 break;
165                         }
166                         b = strsep(&p, " ");
167                         o = strtoimax(b, &r, 0);
168                         /* APPLE have ty as a string */
169                         if ((*r) && (strcmp(t, "APPLE") && strcmp(t, "GPT"))) {
170                                 printf("BARF %d <%d>\n", __LINE__, *r);
171                                 exit (0);
172                         }
173                         if (!strcmp(a, "o"))
174                                 off = o;
175                         else if (!strcmp(a, "i"))
176                                 i = o;
177                         else if (!strcmp(a, "ty"))
178                                 ty = o;
179                         else if (!strcmp(a, "sc"))
180                                 sc = o;
181                         else if (!strcmp(a, "hd"))
182                                 hd = o;
183                         else if (!strcmp(a, "alt"))
184                                 alt = o;
185                 }
186
187                 /* PLATFORM POLICY BEGIN ----------------------------------- */
188                 if (platform == p_sparc64 && !strcmp(t, "SUN") && i == 2)
189                         continue;
190                 if (platform == p_sparc64 && !strcmp(t, "SUN") &&
191                     d->chunks->part->part == NULL) {
192                         d->bios_hd = hd;
193                         d->bios_sect = sc;
194                         o = d->chunks->size / (hd * sc);
195                         o *= (hd * sc);
196                         o -= alt * hd * sc;
197                         if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) {
198                                 DPRINT(("Failed to add 'freebsd' chunk"));
199                         }
200                 }
201                 if (platform == p_alpha && !strcmp(t, "BSD") &&
202                     d->chunks->part->part == NULL) {
203                         if (Add_Chunk(d, 0, d->chunks->size, name, freebsd,
204                                       0, 0, "-")) {
205                                 DPRINT(("Failed to add 'freebsd' chunk"));
206                         }
207                 }
208                 if (!strcmp(t, "BSD") && i == RAW_PART)
209                         continue;
210                 /* PLATFORM POLICY END ------------------------------------- */
211
212                 off /= s;
213                 len /= s;
214                 off += lo[l - 1];
215                 lo[l] = off;
216                 if (!strcmp(t, "SUN"))
217                         i = Add_Chunk(d, off, len, n, part, 0, 0, 0);
218                 else if (!strncmp(t, "MBR", 3)) {
219                         switch (ty) {
220                         case 0xa5:
221                                 i = Add_Chunk(d, off, len, n, freebsd, ty, 0, 0);
222                                 break;
223                         case 0x01:
224                         case 0x04:
225                         case 0x06:
226                         case 0x0b:
227                         case 0x0c:
228                         case 0x0e:
229                                 i = Add_Chunk(d, off, len, n, fat, ty, 0, 0);
230                                 break;
231                         case 0xef:      /* EFI */
232                                 i = Add_Chunk(d, off, len, n, efi, ty, 0, 0);
233                                 break;
234                         default:
235                                 i = Add_Chunk(d, off, len, n, mbr, ty, 0, 0);
236                                 break;
237                         }
238                 } else if (!strcmp(t, "BSD"))
239                         i = Add_Chunk(d, off, len, n, part, ty, 0, 0);
240                 else if (!strcmp(t, "PC98")) {
241                         switch (ty & 0x7f) {
242                         case 0x14:
243                                 i = Add_Chunk(d, off, len, n, freebsd, ty, 0,
244                                               sn);
245                                 break;
246                         case 0x20:
247                         case 0x21:
248                         case 0x22:
249                         case 0x23:
250                         case 0x24:
251                                 i = Add_Chunk(d, off, len, n, fat, ty, 0, sn);
252                                 break;
253                         default:
254                                 i = Add_Chunk(d, off, len, n, pc98, ty, 0, sn);
255                                 break;
256                         }
257                 } else if (!strcmp(t, "GPT"))
258                         i = Add_Chunk(d, off, len, n, gpt, 0, 0, b);
259                 else if (!strcmp(t, "APPLE"))
260                         i = Add_Chunk(d, off, len, n, apple, 0, 0, sn);
261                 else
262                         ; /* Ignore unknown classes. */
263         }
264         /* PLATFORM POLICY BEGIN ------------------------------------- */
265         /* We have a chance to do things on a blank disk here */
266         if (platform == p_sparc64 && d->chunks->part->part == NULL) {
267                 hd = d->bios_hd;
268                 sc = d->bios_sect;
269                 o = d->chunks->size / (hd * sc);
270                 o *= (hd * sc);
271                 o -= 2 * hd * sc;
272                 if (Add_Chunk(d, 0, o, name, freebsd, 0, 0, "-")) {
273                         DPRINT(("Failed to add 'freebsd' chunk"));
274                 }
275         }
276         /* PLATFORM POLICY END --------------------------------------- */
277
278         return (d);
279         i = 0;
280 }