Remove unneeded tls_get_curthread() call.
[dragonfly.git] / lib / libdisk / rules.c
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@login.dknet.dk> 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  * $FreeBSD: src/lib/libdisk/rules.c,v 1.16.2.4 2001/05/13 20:16:32 jkh Exp $
10  * $DragonFly: src/lib/libdisk/Attic/rules.c,v 1.4 2005/03/13 15:10:03 swildner Exp $
11  *
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <sys/types.h>
19 #include <sys/diskslice.h>
20 #include <sys/disklabel.h>
21 #include <sys/diskmbr.h>
22 #include "libdisk.h"
23
24 int
25 Track_Aligned(struct disk *d, u_long offset)
26 {
27         if (!d->bios_sect)
28                 return 1;
29         if (offset % d->bios_sect)
30                 return 0;
31         return 1;
32 }
33
34 u_long
35 Prev_Track_Aligned(struct disk *d, u_long offset)
36 {
37         if (!d->bios_sect)
38                 return offset;
39         return (offset / d->bios_sect) * d->bios_sect;
40 }
41
42 u_long
43 Next_Track_Aligned(struct disk *d, u_long offset)
44 {
45         if (!d->bios_sect)
46                 return offset;
47         return Prev_Track_Aligned(d, offset + d->bios_sect-1);
48 }
49
50 int
51 Cyl_Aligned(struct disk *d, u_long offset)
52 {
53         if (!d->bios_sect || !d->bios_hd)
54                 return 1;
55         if (offset % (d->bios_sect * d->bios_hd))
56                 return 0;
57         return 1;
58 }
59
60 u_long
61 Prev_Cyl_Aligned(struct disk *d, u_long offset)
62 {
63         if (!d->bios_sect || !d->bios_hd)
64                 return offset;
65         return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd;
66 }
67
68 u_long
69 Next_Cyl_Aligned(struct disk *d, u_long offset)
70 {
71         if (!d->bios_sect || !d->bios_hd)
72                 return offset;
73         return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1);
74 }
75
76 /*
77  *  Rule#0:
78  *      Chunks of type 'whole' can have max NDOSPART children.
79  *      Only one of them can have the "active" flag
80  */
81 void
82 Rule_000(struct disk *d, struct chunk *c, char *msg)
83 {
84         int i=0,j=0;
85         struct chunk *c1;
86
87         if (c->type != whole)
88                 return;
89         for (c1 = c->part; c1; c1 = c1->next) {
90                 if (c1->type != unused) continue;
91                 if (c1->flags & CHUNK_ACTIVE)
92                         j++;
93                 i++;
94         }
95         if (i > NDOSPART)
96                 sprintf(msg + strlen(msg),
97         "%d is too many children of the 'whole' chunk.  Max is %d\n",
98                         i, NDOSPART);
99         if (j > 1)
100                 sprintf(msg + strlen(msg),
101         "Too many active children of 'whole'");
102 }
103
104 /*
105  * Rule#1:
106  *      All children of 'whole' and 'extended'  must be track-aligned.
107  *      Exception: the end can be unaligned if it matches the end of 'whole'
108  */
109 void
110 Rule_001(struct disk *d, struct chunk *c, char *msg)
111 {
112         int i;
113         struct chunk *c1;
114
115         if (c->type != whole && c->type != extended)
116                 return;
117         for (i = 0, c1 = c->part; c1; c1 = c1->next) {
118                 if (c1->type == unused) continue;
119                 c1->flags |= CHUNK_ALIGN;
120                 if (!Track_Aligned(d, c1->offset))
121                         sprintf(msg + strlen(msg),
122                     "chunk '%s' [%ld..%ld] does not start on a track boundary\n",
123                                 c1->name, c1->offset, c1->end);
124                 if ((c->type == whole || c->end == c1->end)
125                     || Cyl_Aligned(d, c1->end + 1))
126                         ;
127                 else
128                         sprintf(msg + strlen(msg),
129                     "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n",
130                                 c1->name, c1->offset, c1->end);
131         }
132 }
133
134 /*
135  * Rule#2:
136  *      Max one 'fat' as child of 'whole'
137  */
138 void
139 Rule_002(struct disk *d, struct chunk *c, char *msg)
140 {
141         int i;
142         struct chunk *c1;
143
144         if (c->type != whole)
145                 return;
146         for (i = 0, c1 = c->part; c1; c1 = c1->next) {
147                 if (c1->type != fat)
148                         continue;
149                 i++;
150         }
151         if (i > 1) {
152                 sprintf(msg + strlen(msg),
153                     "Max one 'fat' allowed as child of 'whole'\n");
154         }
155 }
156
157 /*
158  * Rule#3:
159  *      Max one extended as child of 'whole'
160  */
161 void
162 Rule_003(struct disk *d, struct chunk *c, char *msg)
163 {
164         int i;
165         struct chunk *c1;
166
167         if (c->type != whole)
168                 return;
169         for (i = 0, c1 = c->part; c1; c1 = c1->next) {
170                 if (c1->type != extended)
171                         continue;
172                 i++;
173         }
174         if (i > 1) {
175                 sprintf(msg + strlen(msg),
176                     "Max one 'extended' allowed as child of 'whole'\n");
177         }
178 }
179
180 /*
181  * Rule#4:
182  *      Max seven 'part' as children of 'freebsd'
183  *      Max one CHUNK_IS_ROOT child per 'freebsd'
184  */
185 void
186 Rule_004(struct disk *d, struct chunk *c, char *msg)
187 {
188         int i=0,k=0;
189         struct chunk *c1;
190
191         if (c->type != freebsd)
192                 return;
193
194         for (c1 = c->part; c1; c1 = c1->next) {
195                 if (c1->type != part)
196                         continue;
197                 if (c1->flags & CHUNK_IS_ROOT)
198                         k++;
199                 i++;
200         }
201         if (i > 7) {
202                 sprintf(msg + strlen(msg),
203                     "Max seven partitions per freebsd slice\n");
204         }
205         if (k > 1) {
206                 sprintf(msg + strlen(msg),
207                     "Max one root partition child per freebsd slice\n");
208         }
209 }
210
211 void
212 Check_Chunk(struct disk *d, struct chunk *c, char *msg)
213 {
214         Rule_000(d, c, msg);
215         Rule_001(d, c, msg);
216         Rule_002(d, c, msg);
217         Rule_003(d, c, msg);
218         Rule_004(d, c, msg);
219         if (c->part)
220                 Check_Chunk(d, c->part, msg);
221         if (c->next)
222                 Check_Chunk(d, c->next, msg);
223 }
224
225 char *
226 CheckRules(struct disk *d)
227 {
228         char msg[BUFSIZ];
229
230         *msg = '\0';
231         Check_Chunk(d, d->chunks, msg);
232         if (*msg)
233                 return strdup(msg);
234         return 0;
235 }
236
237 char *
238 ChunkCanBeRoot(struct chunk *c)
239 {
240         struct chunk *c1;
241         struct disk *d = c->disk;
242         char msg[BUFSIZ];
243
244         *msg = '\0';
245         for (c1 = d->chunks->part; ; ) {
246                 for (; c1; c1 = c1->next)
247                         if (c1->offset <= c->offset && c1->end >= c->end)
248                                 break;
249                 if (!c1) {
250                         strcat(msg,
251 "Internal trouble, cannot find this chunk in the chunk-tree\n");
252                         return strdup(msg);
253                 }
254                 if (c1->type == freebsd)
255                         break;
256                 c1 = c1->part;
257         }
258
259         if (c1->type != freebsd) {
260                 strcat(msg,
261 "The root partition must be in a FreeBSD slice, otherwise\n");
262                 strcat(msg,
263 "the kernel cannot be booted from it\n");
264                 return strdup(msg);
265         }
266
267         return NULL;
268 }