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