rules.c revision 21673
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: head/lib/libdisk/rules.c 21673 1997-01-14 07:20:47Z jkh $ 10 * 11 */ 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 <err.h> 21#include "libdisk.h" 22 23int 24Track_Aligned(struct disk *d, u_long offset) 25{ 26 if (!d->bios_sect) 27 return 1; 28 if (offset % d->bios_sect) 29 return 0; 30 return 1; 31} 32 33u_long 34Prev_Track_Aligned(struct disk *d, u_long offset) 35{ 36 if (!d->bios_sect) 37 return offset; 38 return (offset / d->bios_sect) * d->bios_sect; 39} 40 41u_long 42Next_Track_Aligned(struct disk *d, u_long offset) 43{ 44 if (!d->bios_sect) 45 return offset; 46 return Prev_Track_Aligned(d,offset + d->bios_sect-1); 47} 48 49int 50Cyl_Aligned(struct disk *d, u_long offset) 51{ 52 if (!d->bios_sect || !d->bios_hd) 53 return 1; 54 if (offset % (d->bios_sect * d->bios_hd)) 55 return 0; 56 return 1; 57} 58 59u_long 60Prev_Cyl_Aligned(struct disk *d, u_long offset) 61{ 62 if (!d->bios_sect || !d->bios_hd) 63 return offset; 64 return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd; 65} 66 67u_long 68Next_Cyl_Aligned(struct disk *d, u_long offset) 69{ 70 if (!d->bios_sect || !d->bios_hd) 71 return offset; 72 return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1); 73} 74 75/* 76 * Rule#0: 77 * Chunks of type 'whole' can have max NDOSPART children. 78 * Only one of them can have the "active" flag 79 */ 80void 81Rule_000(struct disk *d, struct chunk *c, char *msg) 82{ 83 int i=0,j=0; 84 struct chunk *c1; 85 86 if (c->type != whole) 87 return; 88 for (c1=c->part; c1; c1=c1->next) { 89 if (c1->type != unused) continue; 90 if (c1->flags & CHUNK_ACTIVE) 91 j++; 92 i++; 93 } 94 if (i > NDOSPART) 95 sprintf(msg+strlen(msg), 96 "%d is too many children of the 'whole' chunk. Max is %d\n", 97 i, NDOSPART); 98 if (j > 1) 99 sprintf(msg+strlen(msg), 100 "Too many active children of 'whole'"); 101} 102 103/* 104 * Rule#1: 105 * All children of 'whole' and 'extended' must be track-aligned. 106 * Exception: the end can be unaligned if it matches the end of 'whole' 107 */ 108void 109Rule_001(struct disk *d, struct chunk *c, char *msg) 110{ 111 int i; 112 struct chunk *c1; 113 114 if (c->type != whole && c->type != extended) 115 return; 116 for (i=0, c1=c->part; c1; c1=c1->next) { 117 if (c1->type == unused) continue; 118 c1->flags |= CHUNK_ALIGN; 119 if (!Track_Aligned(d,c1->offset)) 120 sprintf(msg+strlen(msg), 121 "chunk '%s' [%ld..%ld] does not start on a track boundary\n", 122 c1->name,c1->offset,c1->end); 123 if ((c->type == whole || c->end == c1->end) 124 || Cyl_Aligned(d,c1->end+1)) 125 ; 126 else 127 sprintf(msg+strlen(msg), 128 "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n", 129 c1->name,c1->offset,c1->end); 130 } 131} 132 133/* 134 * Rule#2: 135 * Max one 'fat' as child of 'whole' 136 */ 137void 138Rule_002(struct disk *d, struct chunk *c, char *msg) 139{ 140 int i; 141 struct chunk *c1; 142 143 if (c->type != whole) 144 return; 145 for (i=0, c1=c->part; c1; c1=c1->next) { 146 if (c1->type != fat) 147 continue; 148 i++; 149 } 150 if (i > 1) { 151 sprintf(msg+strlen(msg), 152 "Max one 'fat' allowed as child of 'whole'\n"); 153 } 154} 155 156/* 157 * Rule#3: 158 * Max one extended as child of 'whole' 159 */ 160void 161Rule_003(struct disk *d, struct chunk *c, char *msg) 162{ 163 int i; 164 struct chunk *c1; 165 166 if (c->type != whole) 167 return; 168 for (i=0, c1=c->part; c1; c1=c1->next) { 169 if (c1->type != extended) 170 continue; 171 i++; 172 } 173 if (i > 1) { 174 sprintf(msg+strlen(msg), 175 "Max one 'extended' allowed as child of 'whole'\n"); 176 } 177} 178 179/* 180 * Rule#4: 181 * Max seven 'part' as children of 'freebsd' 182 * Max one CHUNK_IS_ROOT child per 'freebsd' 183 * If Bad144, space for table must exist. 184 * If Bad144 & root, bad144 table must be inside 1024 185 */ 186void 187Rule_004(struct disk *d, struct chunk *c, char *msg) 188{ 189 int i=0,k=0; 190 struct chunk *c1; 191 u_long l; 192 193 if (c->type != freebsd) 194 return; 195 196 if (c->flags & CHUNK_BAD144) { 197 l = c->end - 127 - d->bios_sect + 1; 198 for (c1=c->part; c1; c1=c1->next) { 199 if (c1->end < l || c1->type == unused) 200 continue; 201 sprintf(msg+strlen(msg), 202 "Blocks %lu to %lu are needed for bad144 information, but isn't unused.\n", 203 l, c->end); 204 break; 205 } 206 if (c->flags & CHUNK_PAST_1024) { 207 for (c1=c->part; c1; c1=c1->next) { 208 if (c1->flags & CHUNK_IS_ROOT) { 209 sprintf(msg+strlen(msg), 210 "You have assigned root to a slice which uses bad144, and\n extends past the first 1023 cylinders, and thus cannot be booted from.\n"); 211 break; 212 } 213 } 214 } 215 } 216 217 for (c1=c->part; c1; c1=c1->next) { 218 if (c1->type != part) 219 continue; 220 if (c1->flags & CHUNK_IS_ROOT) { 221 k++; 222 if (c1->flags & CHUNK_PAST_1024) 223 sprintf(msg+strlen(msg), 224 "Root filesystem extends past cylinder 1024, and cannot be booted from\n"); 225 } 226 i++; 227 } 228 if (i > 7) { 229 sprintf(msg+strlen(msg), 230 "Max seven partitions per freebsd slice\n"); 231 } 232 if (k > 1) { 233 sprintf(msg+strlen(msg), 234 "Max one root partition child per freebsd slice\n"); 235 } 236} 237 238void 239Check_Chunk(struct disk *d, struct chunk *c, char *msg) 240{ 241 Rule_000(d,c,msg); 242 Rule_001(d,c,msg); 243 Rule_002(d,c,msg); 244 Rule_003(d,c,msg); 245 Rule_004(d,c,msg); 246 if (c->part) 247 Check_Chunk(d,c->part,msg); 248 if (c->next) 249 Check_Chunk(d,c->next,msg); 250 251 if (c->end >= 1024*d->bios_hd*d->bios_sect) 252 c->flags |= CHUNK_PAST_1024; 253 else 254 c->flags &= ~CHUNK_PAST_1024; 255} 256 257char * 258CheckRules(struct disk *d) 259{ 260 char msg[BUFSIZ]; 261 262 *msg = '\0'; 263 Check_Chunk(d,d->chunks,msg); 264 if (*msg) 265 return strdup(msg); 266 return 0; 267} 268 269char * 270ChunkCanBeRoot(struct chunk *c) 271{ 272 struct chunk *c1; 273 struct disk *d = c->disk; 274 char msg[BUFSIZ]; 275 276 *msg = '\0'; 277 if (c->flags & CHUNK_PAST_1024) { 278 strcat(msg, 279"The root partition must end before cylinder 1024 seen from\n"); 280 strcat(msg, 281"the BIOS' point of view, or it cannot be booted from.\n"); 282 return strdup(msg); 283 } 284 for (c1=d->chunks->part;;) { 285 for (; c1; c1=c1->next) 286 if (c1->offset <= c->offset && c1->end >= c->end) 287 break; 288 if (!c1) { 289 strcat(msg, 290"Internal trouble, cannot find this chunk in the chunk-tree\n"); 291 return strdup(msg); 292 } 293 if (c1->type == freebsd) 294 break; 295 c1 = c1->part; 296 } 297 298 if (c1->type != freebsd) { 299 strcat(msg, 300"The root partition must be in a FreeBSD slice, otherwise\n"); 301 strcat(msg, 302"the kernel cannot be booted from it\n"); 303 return strdup(msg); 304 } 305 306 if ((c1->flags & CHUNK_BAD144) && (c1->flags & CHUNK_PAST_1024)) { 307 strcat(msg, 308"This partition is unsuitable for root, because the FreeBSD slice\n"); 309 strcat(msg, 310"it is inside has bad144 enabled, but the badblock data lives past\n"); 311 strcat(msg, 312"the 1024th cylinder, and the bootblocks cannot get to it there.\n"); 313 return strdup(msg); 314 } 315 return NULL; 316} 317