rules.c revision 53749
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 53749 1999-11-27 14:33:30Z phk $ 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 for (c1=c->part; c1; c1=c1->next) { 197 if (c1->type != part) 198 continue; 199 if (c1->flags & CHUNK_IS_ROOT) { 200 k++; 201 if (c1->flags & CHUNK_PAST_1024) 202 sprintf(msg+strlen(msg), 203 "Root filesystem extends past cylinder 1024, and cannot be booted from\n"); 204 } 205 i++; 206 } 207 if (i > 7) { 208 sprintf(msg+strlen(msg), 209 "Max seven partitions per freebsd slice\n"); 210 } 211 if (k > 1) { 212 sprintf(msg+strlen(msg), 213 "Max one root partition child per freebsd slice\n"); 214 } 215} 216 217void 218Check_Chunk(struct disk *d, struct chunk *c, char *msg) 219{ 220 Rule_000(d,c,msg); 221 Rule_001(d,c,msg); 222 Rule_002(d,c,msg); 223 Rule_003(d,c,msg); 224 Rule_004(d,c,msg); 225 if (c->part) 226 Check_Chunk(d,c->part,msg); 227 if (c->next) 228 Check_Chunk(d,c->next,msg); 229 230 if (c->end >= 1024*d->bios_hd*d->bios_sect) 231 c->flags |= CHUNK_PAST_1024; 232 else 233 c->flags &= ~CHUNK_PAST_1024; 234} 235 236char * 237CheckRules(struct disk *d) 238{ 239 char msg[BUFSIZ]; 240 241 *msg = '\0'; 242 Check_Chunk(d,d->chunks,msg); 243 if (*msg) 244 return strdup(msg); 245 return 0; 246} 247 248char * 249ChunkCanBeRoot(struct chunk *c) 250{ 251 struct chunk *c1; 252 struct disk *d = c->disk; 253 char msg[BUFSIZ]; 254 255 *msg = '\0'; 256 if (c->flags & CHUNK_PAST_1024) { 257 strcat(msg, 258"The root partition must end before cylinder 1024 seen from\n"); 259 strcat(msg, 260"the BIOS' point of view, or it cannot be booted from.\n"); 261 return strdup(msg); 262 } 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 if (c1->type != freebsd) { 278 strcat(msg, 279"The root partition must be in a FreeBSD slice, otherwise\n"); 280 strcat(msg, 281"the kernel cannot be booted from it\n"); 282 return strdup(msg); 283 } 284 285 return NULL; 286} 287