rules.c revision 104674
175584Sru/* 275584Sru * ---------------------------------------------------------------------------- 375584Sru * "THE BEER-WARE LICENSE" (Revision 42): 4104862Sru * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 575584Sru * can do whatever you want with this stuff. If we meet some day, and you think 675584Sru * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 775584Sru * ---------------------------------------------------------------------------- 875584Sru */ 975584Sru 1075584Sru#include <sys/cdefs.h> 1175584Sru__FBSDID("$FreeBSD: head/lib/libdisk/rules.c 104674 2002-10-08 12:13:19Z nyan $"); 1275584Sru 1375584Sru#include <stdio.h> 1475584Sru#include <stdlib.h> 1575584Sru#include <unistd.h> 1675584Sru#include <string.h> 1775584Sru#include <sys/types.h> 1875584Sru#include <sys/diskslice.h> 1975584Sru#include <sys/disklabel.h> 2075584Sru#ifdef PC98 2175584Sru#include <sys/diskpc98.h> 2275584Sru#else 2375584Sru#include <sys/diskmbr.h> 2475584Sru#endif 2575584Sru#include "libdisk.h" 2675584Sru 2775584Sruint 2875584SruTrack_Aligned(struct disk *d, u_long offset) 2975584Sru{ 3075584Sru if (!d->bios_sect) 3175584Sru return 1; 3275584Sru if (offset % d->bios_sect) 3375584Sru return 0; 3475584Sru return 1; 3575584Sru} 3675584Sru 3775584Sruu_long 3875584SruPrev_Track_Aligned(struct disk *d, u_long offset) 3975584Sru{ 4075584Sru if (!d->bios_sect) 4175584Sru return offset; 4275584Sru return (offset / d->bios_sect) * d->bios_sect; 4375584Sru} 4475584Sru 4575584Sruu_long 4675584SruNext_Track_Aligned(struct disk *d, u_long offset) 4775584Sru{ 4875584Sru if (!d->bios_sect) 4975584Sru return offset; 5075584Sru return Prev_Track_Aligned(d, offset + d->bios_sect-1); 5175584Sru} 5275584Sru 5375584Sruint 5475584SruCyl_Aligned(struct disk *d, u_long offset) 5575584Sru{ 5675584Sru if (!d->bios_sect || !d->bios_hd) 5775584Sru return 1; 5875584Sru if (offset % (d->bios_sect * d->bios_hd)) 5975584Sru return 0; 6075584Sru return 1; 6175584Sru} 6275584Sru 6375584Sruu_long 6475584SruPrev_Cyl_Aligned(struct disk *d, u_long offset) 6575584Sru{ 6675584Sru if (!d->bios_sect || !d->bios_hd) 6775584Sru return offset; 6875584Sru return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd; 6975584Sru} 7075584Sru 7175584Sruu_long 7275584SruNext_Cyl_Aligned(struct disk *d, u_long offset) 7375584Sru{ 7475584Sru if (!d->bios_sect || !d->bios_hd) 7575584Sru return offset; 7675584Sru return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1); 7775584Sru} 7875584Sru 7975584Sru/* 80104862Sru * Rule#0: 8175584Sru * Chunks of type 'whole' can have max NDOSPART children. 8275584Sru * Only one of them can have the "active" flag 8375584Sru */ 8475584Sruvoid 8575584SruRule_000(struct disk *d, struct chunk *c, char *msg) 8675584Sru{ 8775584Sru#ifdef PC98 8875584Sru int i=0; 8975584Sru#else 9075584Sru int i=0,j=0; 9175584Sru#endif 9275584Sru struct chunk *c1; 9375584Sru 9475584Sru if (c->type != whole) 9575584Sru return; 9675584Sru for (c1 = c->part; c1; c1 = c1->next) { 9775584Sru if (c1->type != unused) continue; 9875584Sru#ifndef PC98 9975584Sru if (c1->flags & CHUNK_ACTIVE) 10075584Sru j++; 10175584Sru#endif 10275584Sru i++; 10375584Sru } 10475584Sru if (i > NDOSPART) 10575584Sru sprintf(msg + strlen(msg), 10675584Sru "%d is too many children of the 'whole' chunk. Max is %d\n", 10775584Sru i, NDOSPART); 10875584Sru#ifndef PC98 10975584Sru if (j > 1) 11075584Sru sprintf(msg + strlen(msg), 11175584Sru "Too many active children of 'whole'"); 11275584Sru#endif 11375584Sru} 11475584Sru 11575584Sru/* 11675584Sru * Rule#1: 117104862Sru * All children of 'whole' and 'extended' must be track-aligned. 11875584Sru * Exception: the end can be unaligned if it matches the end of 'whole' 11975584Sru */ 12075584Sruvoid 12175584SruRule_001(struct disk *d, struct chunk *c, char *msg) 12275584Sru{ 12375584Sru int i; 12475584Sru struct chunk *c1; 12575584Sru 12675584Sru if (c->type != whole && c->type != extended) 12775584Sru return; 12875584Sru for (i = 0, c1 = c->part; c1; c1 = c1->next) { 129114402Sru if (c1->type == unused) continue; 13075584Sru c1->flags |= CHUNK_ALIGN; 13175584Sru#ifdef PC98 13275584Sru if (!Cyl_Aligned(d, c1->offset)) 13375584Sru#else 13475584Sru if (!Track_Aligned(d, c1->offset)) 135104862Sru#endif 13675584Sru sprintf(msg + strlen(msg), 13775584Sru#ifdef PC98 13875584Sru "chunk '%s' [%ld..%ld] does not start on a cylinder boundary\n", 139104862Sru#else 14075584Sru "chunk '%s' [%ld..%ld] does not start on a track boundary\n", 14175584Sru#endif 14275584Sru c1->name, c1->offset, c1->end); 14375584Sru if ((c->type == whole || c->end == c1->end) 14475584Sru || Cyl_Aligned(d, c1->end + 1)) 14575584Sru ; 14675584Sru else 14775584Sru sprintf(msg + strlen(msg), 14875584Sru "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n", 14975584Sru c1->name, c1->offset, c1->end); 15075584Sru } 15175584Sru} 15275584Sru 15375584Sru/* 15475584Sru * Rule#2: 15575584Sru * Max one 'fat' as child of 'whole' 15675584Sru */ 15775584Sruvoid 15875584SruRule_002(struct disk *d, struct chunk *c, char *msg) 15975584Sru{ 16075584Sru#ifndef PC98 16175584Sru int i; 16275584Sru struct chunk *c1; 16375584Sru 16475584Sru if (c->type != whole) 16575584Sru return; 16675584Sru for (i = 0, c1 = c->part; c1; c1 = c1->next) { 16775584Sru if (c1->type != fat) 16875584Sru continue; 16975584Sru i++; 17075584Sru } 17175584Sru if (i > 1) { 17275584Sru sprintf(msg + strlen(msg), 173104862Sru "Max one 'fat' allowed as child of 'whole'\n"); 17475584Sru } 17575584Sru#endif 17675584Sru} 17775584Sru 17875584Sru/* 17975584Sru * Rule#3: 18075584Sru * Max one extended as child of 'whole' 18175584Sru */ 18275584Sruvoid 18375584SruRule_003(struct disk *d, struct chunk *c, char *msg) 18475584Sru{ 18575584Sru#ifndef PC98 18675584Sru int i; 18775584Sru struct chunk *c1; 18875584Sru 18975584Sru if (c->type != whole) 19075584Sru return; 19175584Sru for (i = 0, c1 = c->part; c1; c1 = c1->next) { 19275584Sru if (c1->type != extended) 19375584Sru continue; 19475584Sru i++; 19575584Sru } 19675584Sru if (i > 1) { 19775584Sru sprintf(msg + strlen(msg), 19875584Sru "Max one 'extended' allowed as child of 'whole'\n"); 19975584Sru } 20075584Sru#endif 20175584Sru} 20275584Sru 20375584Sru/* 20475584Sru * Rule#4: 205104862Sru * Max seven 'part' as children of 'freebsd' 20675584Sru * Max one CHUNK_IS_ROOT child per 'freebsd' 20775584Sru */ 20875584Sruvoid 20975584SruRule_004(struct disk *d, struct chunk *c, char *msg) 21075584Sru{ 21175584Sru int i=0,k=0; 21275584Sru struct chunk *c1; 21375584Sru 214 if (c->type != freebsd) 215 return; 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 i++; 223 } 224 if (i > 7) { 225 sprintf(msg + strlen(msg), 226 "Max seven partitions per freebsd slice\n"); 227 } 228 if (k > 1) { 229 sprintf(msg + strlen(msg), 230 "Max one root partition child per freebsd slice\n"); 231 } 232} 233 234void 235Check_Chunk(struct disk *d, struct chunk *c, char *msg) 236{ 237 Rule_000(d, c, msg); 238 Rule_001(d, c, msg); 239 Rule_002(d, c, msg); 240 Rule_003(d, c, msg); 241 Rule_004(d, c, msg); 242 if (c->part) 243 Check_Chunk(d, c->part, msg); 244 if (c->next) 245 Check_Chunk(d, c->next, msg); 246} 247 248char * 249CheckRules(struct disk *d) 250{ 251 char msg[BUFSIZ]; 252 253 *msg = '\0'; 254 Check_Chunk(d, d->chunks, msg); 255 if (*msg) 256 return strdup(msg); 257 return 0; 258} 259 260char * 261ChunkCanBeRoot(struct chunk *c) 262{ 263 struct chunk *c1; 264 struct disk *d = c->disk; 265 char msg[BUFSIZ]; 266 267 *msg = '\0'; 268 for (c1 = d->chunks->part; ; ) { 269 for (; c1; c1 = c1->next) 270 if (c1->offset <= c->offset && c1->end >= c->end) 271 break; 272 if (!c1) { 273 strcat(msg, 274"Internal trouble, cannot find this chunk in the chunk-tree\n"); 275 return strdup(msg); 276 } 277 if (c1->type == freebsd) 278 break; 279 c1 = c1->part; 280 } 281 282#ifndef PC98 283 if (c1->type != freebsd) { 284 strcat(msg, 285"The root partition must be in a FreeBSD slice, otherwise\n"); 286 strcat(msg, 287"the kernel cannot be booted from it\n"); 288 return strdup(msg); 289 } 290#endif 291 292 return NULL; 293} 294