rules.c revision 63030
11558Srgrimes/* 21558Srgrimes * ---------------------------------------------------------------------------- 31558Srgrimes * "THE BEER-WARE LICENSE" (Revision 42): 41558Srgrimes * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you 51558Srgrimes * can do whatever you want with this stuff. If we meet some day, and you think 61558Srgrimes * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 71558Srgrimes * ---------------------------------------------------------------------------- 81558Srgrimes * 91558Srgrimes * $FreeBSD: head/lib/libdisk/rules.c 63030 2000-07-12 18:05:18Z jhb $ 101558Srgrimes * 111558Srgrimes */ 121558Srgrimes 131558Srgrimes#include <stdio.h> 141558Srgrimes#include <stdlib.h> 151558Srgrimes#include <unistd.h> 161558Srgrimes#include <string.h> 171558Srgrimes#include <sys/types.h> 181558Srgrimes#include <sys/diskslice.h> 191558Srgrimes#include <sys/disklabel.h> 201558Srgrimes#include <err.h> 211558Srgrimes#include "libdisk.h" 221558Srgrimes 231558Srgrimesint 241558SrgrimesTrack_Aligned(struct disk *d, u_long offset) 251558Srgrimes{ 261558Srgrimes if (!d->bios_sect) 271558Srgrimes return 1; 281558Srgrimes if (offset % d->bios_sect) 291558Srgrimes return 0; 301558Srgrimes return 1; 3136997Scharnier} 321558Srgrimes 3336997Scharnieru_long 3436997ScharnierPrev_Track_Aligned(struct disk *d, u_long offset) 3550476Speter{ 361558Srgrimes if (!d->bios_sect) 371558Srgrimes return offset; 381558Srgrimes return (offset / d->bios_sect) * d->bios_sect; 3971787Sphk} 401558Srgrimes 411558Srgrimesu_long 4298542SmckusickNext_Track_Aligned(struct disk *d, u_long offset) 4398542Smckusick{ 441558Srgrimes if (!d->bios_sect) 451558Srgrimes return offset; 461558Srgrimes return Prev_Track_Aligned(d,offset + d->bios_sect-1); 47103949Smike} 481558Srgrimes 491558Srgrimesint 501558SrgrimesCyl_Aligned(struct disk *d, u_long offset) 511558Srgrimes{ 5290742Siedowse if (!d->bios_sect || !d->bios_hd) 53217769Smckusick return 1; 541558Srgrimes if (offset % (d->bios_sect * d->bios_hd)) 551558Srgrimes return 0; 561558Srgrimes return 1; 571558Srgrimes} 581558Srgrimes 5992837Simpu_long 6092837SimpPrev_Cyl_Aligned(struct disk *d, u_long offset) 611558Srgrimes{ 621558Srgrimes if (!d->bios_sect || !d->bios_hd) 631558Srgrimes return offset; 641558Srgrimes return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd; 651558Srgrimes} 661558Srgrimes 671558Srgrimesu_long 681558SrgrimesNext_Cyl_Aligned(struct disk *d, u_long offset) 691558Srgrimes{ 701558Srgrimes if (!d->bios_sect || !d->bios_hd) 711558Srgrimes return offset; 721558Srgrimes return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1); 731558Srgrimes} 7492837Simp 751558Srgrimes/* 761558Srgrimes * Rule#0: 7792837Simp * Chunks of type 'whole' can have max NDOSPART children. 781558Srgrimes * Only one of them can have the "active" flag 791558Srgrimes */ 801558Srgrimesvoid 811558SrgrimesRule_000(struct disk *d, struct chunk *c, char *msg) 821558Srgrimes{ 831558Srgrimes#ifdef PC98 841558Srgrimes int i=0; 851558Srgrimes#else 861558Srgrimes int i=0,j=0; 8792837Simp#endif 881558Srgrimes struct chunk *c1; 891558Srgrimes 901558Srgrimes if (c->type != whole) 911558Srgrimes return; 921558Srgrimes for (c1=c->part; c1; c1=c1->next) { 931558Srgrimes if (c1->type != unused) continue; 941558Srgrimes#ifndef PC98 951558Srgrimes if (c1->flags & CHUNK_ACTIVE) 961558Srgrimes j++; 971558Srgrimes#endif 981558Srgrimes i++; 991558Srgrimes } 1001558Srgrimes if (i > NDOSPART) 1011558Srgrimes sprintf(msg+strlen(msg), 1021558Srgrimes "%d is too many children of the 'whole' chunk. Max is %d\n", 1031558Srgrimes i, NDOSPART); 1041558Srgrimes#ifndef PC98 1051558Srgrimes if (j > 1) 1061558Srgrimes sprintf(msg+strlen(msg), 1071558Srgrimes "Too many active children of 'whole'"); 1081558Srgrimes#endif 1091558Srgrimes} 1101558Srgrimes 1111558Srgrimes/* 1121558Srgrimes * Rule#1: 1131558Srgrimes * All children of 'whole' and 'extended' must be track-aligned. 1141558Srgrimes * Exception: the end can be unaligned if it matches the end of 'whole' 1151558Srgrimes */ 1161558Srgrimesvoid 11783083SruRule_001(struct disk *d, struct chunk *c, char *msg) 1181558Srgrimes{ 1191558Srgrimes int i; 1201558Srgrimes struct chunk *c1; 1211558Srgrimes 1221558Srgrimes if (c->type != whole && c->type != extended) 1231558Srgrimes return; 12492837Simp for (i=0, c1=c->part; c1; c1=c1->next) { 1251558Srgrimes if (c1->type == unused) continue; 1261558Srgrimes c1->flags |= CHUNK_ALIGN; 1271558Srgrimes#ifdef PC98 1281558Srgrimes if (!Cyl_Aligned(d,c1->offset)) 1291558Srgrimes#else 1301558Srgrimes if (!Track_Aligned(d,c1->offset)) 1311558Srgrimes#endif 13271750Sphk sprintf(msg+strlen(msg), 1331558Srgrimes#ifdef PC98 1341558Srgrimes "chunk '%s' [%ld..%ld] does not start on a cylinder boundary\n", 1351558Srgrimes#else 1361558Srgrimes "chunk '%s' [%ld..%ld] does not start on a track boundary\n", 1371558Srgrimes#endif 1381558Srgrimes c1->name,c1->offset,c1->end); 1391558Srgrimes if ((c->type == whole || c->end == c1->end) 1401558Srgrimes || Cyl_Aligned(d,c1->end+1)) 1411558Srgrimes ; 1421558Srgrimes else 1431558Srgrimes sprintf(msg+strlen(msg), 1441558Srgrimes "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n", 1451558Srgrimes c1->name,c1->offset,c1->end); 1461558Srgrimes } 1471558Srgrimes} 1481558Srgrimes 1491558Srgrimes/* 15092837Simp * Rule#2: 1511558Srgrimes * Max one 'fat' as child of 'whole' 1521558Srgrimes */ 1531558Srgrimesvoid 1541558SrgrimesRule_002(struct disk *d, struct chunk *c, char *msg) 1551558Srgrimes{ 1561558Srgrimes#ifndef PC98 1571558Srgrimes int i; 15883083Sru struct chunk *c1; 1591558Srgrimes 1601558Srgrimes if (c->type != whole) 16192837Simp return; 1621558Srgrimes for (i=0, c1=c->part; c1; c1=c1->next) { 16383083Sru if (c1->type != fat) 16483083Sru continue; 1651558Srgrimes i++; 16683083Sru } 1671558Srgrimes if (i > 1) { 1681558Srgrimes sprintf(msg+strlen(msg), 16983083Sru "Max one 'fat' allowed as child of 'whole'\n"); 17083083Sru } 1711558Srgrimes#endif 1721558Srgrimes} 17383083Sru 17483083Sru/* 17583083Sru * Rule#3: 17683083Sru * Max one extended as child of 'whole' 17783083Sru */ 1781558Srgrimesvoid 17983083SruRule_003(struct disk *d, struct chunk *c, char *msg) 1801558Srgrimes{ 1811558Srgrimes#ifndef PC98 1821558Srgrimes int i; 18383083Sru struct chunk *c1; 1841558Srgrimes 1851558Srgrimes if (c->type != whole) 1861558Srgrimes return; 1871558Srgrimes for (i=0, c1=c->part; c1; c1=c1->next) { 1881558Srgrimes if (c1->type != extended) 18992837Simp continue; 1901558Srgrimes i++; 19190743Siedowse } 192129556Simp if (i > 1) { 193161000Srse sprintf(msg+strlen(msg), 19490743Siedowse "Max one 'extended' allowed as child of 'whole'\n"); 1951558Srgrimes } 196130753Siedowse#endif 197129556Simp} 198129556Simp 199130753Siedowse/* 200130753Siedowse * Rule#4: 201130753Siedowse * Max seven 'part' as children of 'freebsd' 202130753Siedowse * Max one CHUNK_IS_ROOT child per 'freebsd' 203129556Simp */ 204129556Simpvoid 205129556SimpRule_004(struct disk *d, struct chunk *c, char *msg) 206129556Simp{ 207129556Simp int i=0,k=0; 208129556Simp struct chunk *c1; 209129556Simp 21090743Siedowse if (c->type != freebsd) 211161000Srse return; 212161025Smarck 213129556Simp for (c1=c->part; c1; c1=c1->next) { 214161017Smarck if (c1->type != part) 215161017Smarck continue; 216129556Simp if (c1->flags & CHUNK_IS_ROOT) 217129556Simp k++; 218129556Simp i++; 219129556Simp } 220161017Smarck if (i > 7) { 221161000Srse sprintf(msg+strlen(msg), 222129556Simp "Max seven partitions per freebsd slice\n"); 2231558Srgrimes } 2241558Srgrimes if (k > 1) { 2251558Srgrimes sprintf(msg+strlen(msg), 22690742Siedowse "Max one root partition child per freebsd slice\n"); 22790742Siedowse } 22890742Siedowse} 2291558Srgrimes 23092837Simpvoid 23190742SiedowseCheck_Chunk(struct disk *d, struct chunk *c, char *msg) 23290742Siedowse{ 23390742Siedowse Rule_000(d,c,msg); 23490742Siedowse Rule_001(d,c,msg); 23590742Siedowse Rule_002(d,c,msg); 2361558Srgrimes Rule_003(d,c,msg); 2371558Srgrimes Rule_004(d,c,msg); 2381558Srgrimes if (c->part) 2391558Srgrimes Check_Chunk(d,c->part,msg); 2401558Srgrimes if (c->next) 2411558Srgrimes Check_Chunk(d,c->next,msg); 2421558Srgrimes} 2431558Srgrimes 2441558Srgrimeschar * 245120323SpsCheckRules(struct disk *d) 246141965Sobrien{ 2471558Srgrimes char msg[BUFSIZ]; 2481558Srgrimes 249139422Sobrien *msg = '\0'; 250139422Sobrien Check_Chunk(d,d->chunks,msg); 251139422Sobrien if (*msg) 2521558Srgrimes return strdup(msg); 2531558Srgrimes return 0; 2541558Srgrimes} 2551558Srgrimes 2561558Srgrimeschar * 2571558SrgrimesChunkCanBeRoot(struct chunk *c) 258141965Sobrien{ 2591558Srgrimes struct chunk *c1; 2601558Srgrimes struct disk *d = c->disk; 2611558Srgrimes char msg[BUFSIZ]; 2621558Srgrimes 2631558Srgrimes *msg = '\0'; 2641558Srgrimes for (c1=d->chunks->part;;) { 2651558Srgrimes for (; c1; c1=c1->next) 2661558Srgrimes if (c1->offset <= c->offset && c1->end >= c->end) 2671558Srgrimes break; 2681558Srgrimes if (!c1) { 2691558Srgrimes strcat(msg, 2701558Srgrimes"Internal trouble, cannot find this chunk in the chunk-tree\n"); 2711558Srgrimes return strdup(msg); 2721558Srgrimes } 2731558Srgrimes if (c1->type == freebsd) 2741558Srgrimes break; 2751558Srgrimes c1 = c1->part; 2761558Srgrimes } 2771558Srgrimes 2781558Srgrimes#ifndef PC98 2791558Srgrimes if (c1->type != freebsd) { 2801558Srgrimes strcat(msg, 2811558Srgrimes"The root partition must be in a FreeBSD slice, otherwise\n"); 2821558Srgrimes strcat(msg, 2831558Srgrimes"the kernel cannot be booted from it\n"); 2841558Srgrimes return strdup(msg); 2851558Srgrimes } 2861558Srgrimes#endif 28792837Simp 2881558Srgrimes return NULL; 28986473Siedowse} 2901558Srgrimes