19a747e4fSDavid du Colombier #include <u.h> 29a747e4fSDavid du Colombier #include <libc.h> 39a747e4fSDavid du Colombier #include <authsrv.h> 49a747e4fSDavid du Colombier 59a747e4fSDavid du Colombier static long finddosfile(int, char*); 69a747e4fSDavid du Colombier 79a747e4fSDavid du Colombier static int 89a747e4fSDavid du Colombier check(void *x, int len, uchar sum, char *msg) 99a747e4fSDavid du Colombier { 109a747e4fSDavid du Colombier if(nvcsum(x, len) == sum) 119a747e4fSDavid du Colombier return 0; 129a747e4fSDavid du Colombier memset(x, 0, len); 139a747e4fSDavid du Colombier fprint(2, "%s\n", msg); 149a747e4fSDavid du Colombier return 1; 159a747e4fSDavid du Colombier } 169a747e4fSDavid du Colombier 179a747e4fSDavid du Colombier /* 189a747e4fSDavid du Colombier * get key info out of nvram. since there isn't room in the PC's nvram use 199a747e4fSDavid du Colombier * a disk partition there. 209a747e4fSDavid du Colombier */ 219a747e4fSDavid du Colombier static struct { 229a747e4fSDavid du Colombier char *cputype; 239a747e4fSDavid du Colombier char *file; 249a747e4fSDavid du Colombier int off; 259a747e4fSDavid du Colombier int len; 269a747e4fSDavid du Colombier } nvtab[] = { 279a747e4fSDavid du Colombier "sparc", "#r/nvram", 1024+850, sizeof(Nvrsafe), 289a747e4fSDavid du Colombier "pc", "#S/sdC0/nvram", 0, sizeof(Nvrsafe), 299a747e4fSDavid du Colombier "pc", "#S/sdC0/9fat", -1, sizeof(Nvrsafe), 30dc5a79c1SDavid du Colombier "pc", "#S/sdC1/nvram", 0, sizeof(Nvrsafe), 31dc5a79c1SDavid du Colombier "pc", "#S/sdC1/9fat", -1, sizeof(Nvrsafe), 3222a0222bSDavid du Colombier "pc", "#S/sdD0/nvram", 0, sizeof(Nvrsafe), 3322a0222bSDavid du Colombier "pc", "#S/sdD0/9fat", -1, sizeof(Nvrsafe), 340aa8dc3cSDavid du Colombier "pc", "#S/sdE0/nvram", 0, sizeof(Nvrsafe), 350aa8dc3cSDavid du Colombier "pc", "#S/sdE0/9fat", -1, sizeof(Nvrsafe), 360aa8dc3cSDavid du Colombier "pc", "#S/sdF0/nvram", 0, sizeof(Nvrsafe), 370aa8dc3cSDavid du Colombier "pc", "#S/sdF0/9fat", -1, sizeof(Nvrsafe), 389a747e4fSDavid du Colombier "pc", "#S/sd00/nvram", 0, sizeof(Nvrsafe), 399a747e4fSDavid du Colombier "pc", "#S/sd00/9fat", -1, sizeof(Nvrsafe), 40d3c05884SDavid du Colombier "pc", "#S/sd01/nvram", 0, sizeof(Nvrsafe), 41d3c05884SDavid du Colombier "pc", "#S/sd01/9fat", -1, sizeof(Nvrsafe), 429a747e4fSDavid du Colombier "pc", "#f/fd0disk", -1, 512, /* 512: #f requires whole sector reads */ 439a747e4fSDavid du Colombier "pc", "#f/fd1disk", -1, 512, 449a747e4fSDavid du Colombier "mips", "#r/nvram", 1024+900, sizeof(Nvrsafe), 45dc5a79c1SDavid du Colombier "power", "#F/flash/flash0", 0x440000, sizeof(Nvrsafe), 469a747e4fSDavid du Colombier "power", "#r/nvram", 4352, sizeof(Nvrsafe), /* OK for MTX-604e */ 472cca75a1SDavid du Colombier "power", "/nvram", 0, sizeof(Nvrsafe), /* OK for Ucu */ 48208510e1SDavid du Colombier "arm", "#F/flash/flash0", 0x100000, sizeof(Nvrsafe), 499a747e4fSDavid du Colombier "debug", "/tmp/nvram", 0, sizeof(Nvrsafe), 509a747e4fSDavid du Colombier }; 519a747e4fSDavid du Colombier 529a747e4fSDavid du Colombier static char* 539a747e4fSDavid du Colombier readcons(char *prompt, char *def, int raw, char *buf, int nbuf) 549a747e4fSDavid du Colombier { 559a747e4fSDavid du Colombier int fdin, fdout, ctl, n, m; 569a747e4fSDavid du Colombier char line[10]; 579a747e4fSDavid du Colombier 589a747e4fSDavid du Colombier fdin = open("/dev/cons", OREAD); 599a747e4fSDavid du Colombier if(fdin < 0) 609a747e4fSDavid du Colombier fdin = 0; 619a747e4fSDavid du Colombier fdout = open("/dev/cons", OWRITE); 629a747e4fSDavid du Colombier if(fdout < 0) 639a747e4fSDavid du Colombier fdout = 1; 649a747e4fSDavid du Colombier if(def != nil) 659a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 669a747e4fSDavid du Colombier else 679a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 689a747e4fSDavid du Colombier if(raw){ 699a747e4fSDavid du Colombier ctl = open("/dev/consctl", OWRITE); 709a747e4fSDavid du Colombier if(ctl >= 0) 719a747e4fSDavid du Colombier write(ctl, "rawon", 5); 729a747e4fSDavid du Colombier } else 739a747e4fSDavid du Colombier ctl = -1; 749a747e4fSDavid du Colombier 759a747e4fSDavid du Colombier m = 0; 769a747e4fSDavid du Colombier for(;;){ 779a747e4fSDavid du Colombier n = read(fdin, line, 1); 789a747e4fSDavid du Colombier if(n == 0){ 799a747e4fSDavid du Colombier close(ctl); 809a747e4fSDavid du Colombier werrstr("readcons: EOF"); 819a747e4fSDavid du Colombier return nil; 829a747e4fSDavid du Colombier } 839a747e4fSDavid du Colombier if(n < 0){ 849a747e4fSDavid du Colombier close(ctl); 859a747e4fSDavid du Colombier werrstr("can't read cons"); 869a747e4fSDavid du Colombier return nil; 879a747e4fSDavid du Colombier } 889a747e4fSDavid du Colombier if(line[0] == 0x7f) 899a747e4fSDavid du Colombier exits(0); 909a747e4fSDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){ 919a747e4fSDavid du Colombier if(raw){ 929a747e4fSDavid du Colombier write(ctl, "rawoff", 6); 939a747e4fSDavid du Colombier write(fdout, "\n", 1); 949a747e4fSDavid du Colombier close(ctl); 959a747e4fSDavid du Colombier } 969a747e4fSDavid du Colombier buf[m] = '\0'; 979a747e4fSDavid du Colombier if(buf[0]=='\0' && def) 989a747e4fSDavid du Colombier strcpy(buf, def); 999a747e4fSDavid du Colombier return buf; 1009a747e4fSDavid du Colombier } 1019a747e4fSDavid du Colombier if(line[0] == '\b'){ 1029a747e4fSDavid du Colombier if(m > 0) 1039a747e4fSDavid du Colombier m--; 1049a747e4fSDavid du Colombier }else if(line[0] == 0x15){ /* ^U: line kill */ 1059a747e4fSDavid du Colombier m = 0; 1069a747e4fSDavid du Colombier if(def != nil) 1079a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 1089a747e4fSDavid du Colombier else 1099a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 1109a747e4fSDavid du Colombier }else{ 1119a747e4fSDavid du Colombier if(m >= nbuf-1){ 1129a747e4fSDavid du Colombier fprint(fdout, "line too long\n"); 1139a747e4fSDavid du Colombier m = 0; 1149a747e4fSDavid du Colombier if(def != nil) 1159a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 1169a747e4fSDavid du Colombier else 1179a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 1189a747e4fSDavid du Colombier }else 1199a747e4fSDavid du Colombier buf[m++] = line[0]; 1209a747e4fSDavid du Colombier } 1219a747e4fSDavid du Colombier } 1229a747e4fSDavid du Colombier } 1239a747e4fSDavid du Colombier 1246822557bSDavid du Colombier typedef struct { 1256822557bSDavid du Colombier int fd; 1266822557bSDavid du Colombier int safeoff; 1276822557bSDavid du Colombier int safelen; 1286822557bSDavid du Colombier } Nvrwhere; 1299a747e4fSDavid du Colombier 1306822557bSDavid du Colombier /* returns with *locp filled in and locp->fd open, if possible */ 1316822557bSDavid du Colombier static void 1326822557bSDavid du Colombier findnvram(Nvrwhere *locp) 1339a747e4fSDavid du Colombier { 1346822557bSDavid du Colombier char *cputype, *nvrfile, *nvrlen, *nvroff, *v[2]; 1356822557bSDavid du Colombier int fd, i, safeoff, safelen; 1369a747e4fSDavid du Colombier 137d3c05884SDavid du Colombier nvrfile = getenv("nvram"); 1389a747e4fSDavid du Colombier cputype = getenv("cputype"); 1399a747e4fSDavid du Colombier if(cputype == nil) 1406822557bSDavid du Colombier cputype = strdup("mips"); 1419a747e4fSDavid du Colombier if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0) 1426822557bSDavid du Colombier cputype = strdup("pc"); 1439a747e4fSDavid du Colombier 1449a747e4fSDavid du Colombier fd = -1; 1459a747e4fSDavid du Colombier safeoff = -1; 1469a747e4fSDavid du Colombier safelen = -1; 147d3c05884SDavid du Colombier if(nvrfile != nil){ 148d3c05884SDavid du Colombier /* accept device and device!file */ 149d3c05884SDavid du Colombier i = gettokens(nvrfile, v, nelem(v), "!"); 150d3c05884SDavid du Colombier fd = open(v[0], ORDWR); 151d3c05884SDavid du Colombier safelen = sizeof(Nvrsafe); 152d3c05884SDavid du Colombier if(strstr(v[0], "/9fat") == nil) 153d3c05884SDavid du Colombier safeoff = 0; 154d3c05884SDavid du Colombier nvrlen = getenv("nvrlen"); 155d3c05884SDavid du Colombier if(nvrlen != nil) 156d3c05884SDavid du Colombier safelen = atoi(nvrlen); 157d3c05884SDavid du Colombier nvroff = getenv("nvroff"); 1586822557bSDavid du Colombier if(nvroff != nil) 159d3c05884SDavid du Colombier if(strcmp(nvroff, "dos") == 0) 160d3c05884SDavid du Colombier safeoff = -1; 161d3c05884SDavid du Colombier else 162d3c05884SDavid du Colombier safeoff = atoi(nvroff); 163d3c05884SDavid du Colombier if(safeoff < 0 && fd >= 0){ 164d3c05884SDavid du Colombier safelen = 512; 165d3c05884SDavid du Colombier safeoff = finddosfile(fd, i == 2? v[1]: "plan9.nvr"); 1666822557bSDavid du Colombier if(safeoff < 0){ /* didn't find plan9.nvr? */ 167d3c05884SDavid du Colombier close(fd); 168d3c05884SDavid du Colombier fd = -1; 169d3c05884SDavid du Colombier } 170d3c05884SDavid du Colombier } 171d3c05884SDavid du Colombier free(nvroff); 1726822557bSDavid du Colombier free(nvrlen); 1736822557bSDavid du Colombier free(nvrfile); 1746822557bSDavid du Colombier }else 1759a747e4fSDavid du Colombier for(i=0; i<nelem(nvtab); i++){ 1769a747e4fSDavid du Colombier if(strcmp(cputype, nvtab[i].cputype) != 0) 1779a747e4fSDavid du Colombier continue; 1789a747e4fSDavid du Colombier if((fd = open(nvtab[i].file, ORDWR)) < 0) 1799a747e4fSDavid du Colombier continue; 1809a747e4fSDavid du Colombier safeoff = nvtab[i].off; 1819a747e4fSDavid du Colombier safelen = nvtab[i].len; 1829a747e4fSDavid du Colombier if(safeoff == -1){ 1839a747e4fSDavid du Colombier safeoff = finddosfile(fd, "plan9.nvr"); 1846822557bSDavid du Colombier if(safeoff < 0){ /* didn't find plan9.nvr? */ 1859a747e4fSDavid du Colombier close(fd); 1869a747e4fSDavid du Colombier fd = -1; 1879a747e4fSDavid du Colombier continue; 1889a747e4fSDavid du Colombier } 1899a747e4fSDavid du Colombier } 1909a747e4fSDavid du Colombier break; 1919a747e4fSDavid du Colombier } 1926822557bSDavid du Colombier free(cputype); 1936822557bSDavid du Colombier locp->fd = fd; 1946822557bSDavid du Colombier locp->safelen = safelen; 1956822557bSDavid du Colombier locp->safeoff = safeoff; 196d3c05884SDavid du Colombier } 1979a747e4fSDavid du Colombier 1986822557bSDavid du Colombier /* 1996822557bSDavid du Colombier * get key info out of nvram. since there isn't room in the PC's nvram use 2006822557bSDavid du Colombier * a disk partition there. 2016822557bSDavid du Colombier */ 2026822557bSDavid du Colombier int 2036822557bSDavid du Colombier readnvram(Nvrsafe *safep, int flag) 2046822557bSDavid du Colombier { 2056822557bSDavid du Colombier int err; 2066822557bSDavid du Colombier char buf[512], in[128]; /* 512 for floppy i/o */ 2076822557bSDavid du Colombier Nvrsafe *safe; 2086822557bSDavid du Colombier Nvrwhere loc; 2096822557bSDavid du Colombier 2106822557bSDavid du Colombier err = 0; 211*07b9f4d0SDavid du Colombier safe = (Nvrsafe*)buf; 2126822557bSDavid du Colombier memset(&loc, 0, sizeof loc); 2136822557bSDavid du Colombier findnvram(&loc); 2146822557bSDavid du Colombier if (loc.safelen < 0) 2156822557bSDavid du Colombier loc.safelen = sizeof *safe; 2166822557bSDavid du Colombier else if (loc.safelen > sizeof buf) 2176822557bSDavid du Colombier loc.safelen = sizeof buf; 2186822557bSDavid du Colombier if (loc.safeoff < 0) { 2196822557bSDavid du Colombier fprint(2, "readnvram: couldn't find nvram\n"); 2206822557bSDavid du Colombier if(!(flag&NVwritemem)) 2216822557bSDavid du Colombier memset(safep, 0, sizeof(*safep)); 222*07b9f4d0SDavid du Colombier safe = safep; 223*07b9f4d0SDavid du Colombier /* 224*07b9f4d0SDavid du Colombier * allow user to type the data for authentication, 225*07b9f4d0SDavid du Colombier * even if there's no nvram to store it in. 226*07b9f4d0SDavid du Colombier */ 2276822557bSDavid du Colombier } 2286822557bSDavid du Colombier 2296822557bSDavid du Colombier if(flag&NVwritemem) 2306822557bSDavid du Colombier safe = safep; 2316822557bSDavid du Colombier else { 2326822557bSDavid du Colombier memset(safep, 0, sizeof(*safep)); 2336822557bSDavid du Colombier if(loc.fd < 0 2346822557bSDavid du Colombier || seek(loc.fd, loc.safeoff, 0) < 0 2356822557bSDavid du Colombier || read(loc.fd, buf, loc.safelen) != loc.safelen){ 2369a747e4fSDavid du Colombier err = 1; 2379a747e4fSDavid du Colombier if(flag&(NVwrite|NVwriteonerr)) 2383ff48bf5SDavid du Colombier fprint(2, "can't read nvram: %r\n"); 2396822557bSDavid du Colombier /* start from scratch */ 2409a747e4fSDavid du Colombier memset(safep, 0, sizeof(*safep)); 2419a747e4fSDavid du Colombier safe = safep; 2429a747e4fSDavid du Colombier }else{ 2436822557bSDavid du Colombier *safep = *safe; /* overwrite arg with data read */ 2449a747e4fSDavid du Colombier safe = safep; 2459a747e4fSDavid du Colombier 2466822557bSDavid du Colombier /* verify data read */ 2476822557bSDavid du Colombier err |= check(safe->machkey, DESKEYLEN, safe->machsum, 2486822557bSDavid du Colombier "bad nvram key"); 2496822557bSDavid du Colombier // err |= check(safe->config, CONFIGLEN, safe->configsum, 2506822557bSDavid du Colombier // "bad secstore key"); 2516822557bSDavid du Colombier err |= check(safe->authid, ANAMELEN, safe->authidsum, 2526822557bSDavid du Colombier "bad authentication id"); 2536822557bSDavid du Colombier err |= check(safe->authdom, DOMLEN, safe->authdomsum, 2546822557bSDavid du Colombier "bad authentication domain"); 2555fe11e25SDavid du Colombier if(err == 0) 2565fe11e25SDavid du Colombier if(safe->authid[0]==0 || safe->authdom[0]==0){ 2575fe11e25SDavid du Colombier fprint(2, "empty nvram authid or authdom\n"); 2585fe11e25SDavid du Colombier err = 1; 2595fe11e25SDavid du Colombier } 2609a747e4fSDavid du Colombier } 2616822557bSDavid du Colombier } 2629a747e4fSDavid du Colombier 2636822557bSDavid du Colombier if((flag&(NVwrite|NVwritemem)) || (err && (flag&NVwriteonerr))){ 2646822557bSDavid du Colombier if (!(flag&NVwritemem)) { 2656822557bSDavid du Colombier readcons("authid", nil, 0, safe->authid, 2666822557bSDavid du Colombier sizeof safe->authid); 2676822557bSDavid du Colombier readcons("authdom", nil, 0, safe->authdom, 2686822557bSDavid du Colombier sizeof safe->authdom); 2696822557bSDavid du Colombier readcons("secstore key (or fs config)", nil, 1, 2706822557bSDavid du Colombier safe->config, sizeof safe->config); 2719a747e4fSDavid du Colombier for(;;){ 2726822557bSDavid du Colombier if(readcons("password", nil, 1, in, sizeof in) 2736822557bSDavid du Colombier == nil) 2749a747e4fSDavid du Colombier goto Out; 2759a747e4fSDavid du Colombier if(passtokey(safe->machkey, in)) 2769a747e4fSDavid du Colombier break; 2779a747e4fSDavid du Colombier } 2786822557bSDavid du Colombier } 2796822557bSDavid du Colombier 2806822557bSDavid du Colombier // safe->authsum = nvcsum(safe->authkey, DESKEYLEN); 2819a747e4fSDavid du Colombier safe->machsum = nvcsum(safe->machkey, DESKEYLEN); 2829a747e4fSDavid du Colombier safe->configsum = nvcsum(safe->config, CONFIGLEN); 2836822557bSDavid du Colombier safe->authidsum = nvcsum(safe->authid, sizeof safe->authid); 2846822557bSDavid du Colombier safe->authdomsum = nvcsum(safe->authdom, sizeof safe->authdom); 285208510e1SDavid du Colombier 2866822557bSDavid du Colombier *(Nvrsafe*)buf = *safe; 2876822557bSDavid du Colombier if(loc.fd < 0 2886822557bSDavid du Colombier || seek(loc.fd, loc.safeoff, 0) < 0 2896822557bSDavid du Colombier || write(loc.fd, buf, loc.safelen) != loc.safelen){ 2909a747e4fSDavid du Colombier fprint(2, "can't write key to nvram: %r\n"); 2919a747e4fSDavid du Colombier err = 1; 2929a747e4fSDavid du Colombier }else 2939a747e4fSDavid du Colombier err = 0; 2949a747e4fSDavid du Colombier } 2959a747e4fSDavid du Colombier Out: 2966822557bSDavid du Colombier if (loc.fd >= 0) 2976822557bSDavid du Colombier close(loc.fd); 2989a747e4fSDavid du Colombier return err? -1: 0; 2999a747e4fSDavid du Colombier } 3009a747e4fSDavid du Colombier 3019a747e4fSDavid du Colombier typedef struct Dosboot Dosboot; 3029a747e4fSDavid du Colombier struct Dosboot{ 3039a747e4fSDavid du Colombier uchar magic[3]; /* really an xx86 JMP instruction */ 3049a747e4fSDavid du Colombier uchar version[8]; 3059a747e4fSDavid du Colombier uchar sectsize[2]; 3069a747e4fSDavid du Colombier uchar clustsize; 3079a747e4fSDavid du Colombier uchar nresrv[2]; 3089a747e4fSDavid du Colombier uchar nfats; 3099a747e4fSDavid du Colombier uchar rootsize[2]; 3109a747e4fSDavid du Colombier uchar volsize[2]; 3119a747e4fSDavid du Colombier uchar mediadesc; 3129a747e4fSDavid du Colombier uchar fatsize[2]; 3139a747e4fSDavid du Colombier uchar trksize[2]; 3149a747e4fSDavid du Colombier uchar nheads[2]; 3159a747e4fSDavid du Colombier uchar nhidden[4]; 3169a747e4fSDavid du Colombier uchar bigvolsize[4]; 3179a747e4fSDavid du Colombier uchar driveno; 3189a747e4fSDavid du Colombier uchar reserved0; 3199a747e4fSDavid du Colombier uchar bootsig; 3209a747e4fSDavid du Colombier uchar volid[4]; 3219a747e4fSDavid du Colombier uchar label[11]; 3229a747e4fSDavid du Colombier uchar type[8]; 3239a747e4fSDavid du Colombier }; 3249a747e4fSDavid du Colombier #define GETSHORT(p) (((p)[1]<<8) | (p)[0]) 3259a747e4fSDavid du Colombier #define GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p))) 3269a747e4fSDavid du Colombier 3279a747e4fSDavid du Colombier typedef struct Dosdir Dosdir; 3289a747e4fSDavid du Colombier struct Dosdir 3299a747e4fSDavid du Colombier { 3309a747e4fSDavid du Colombier char name[8]; 3319a747e4fSDavid du Colombier char ext[3]; 3329a747e4fSDavid du Colombier uchar attr; 3339a747e4fSDavid du Colombier uchar reserved[10]; 3349a747e4fSDavid du Colombier uchar time[2]; 3359a747e4fSDavid du Colombier uchar date[2]; 3369a747e4fSDavid du Colombier uchar start[2]; 3379a747e4fSDavid du Colombier uchar length[4]; 3389a747e4fSDavid du Colombier }; 3399a747e4fSDavid du Colombier 3409a747e4fSDavid du Colombier static char* 3419a747e4fSDavid du Colombier dosparse(char *from, char *to, int len) 3429a747e4fSDavid du Colombier { 3439a747e4fSDavid du Colombier char c; 3449a747e4fSDavid du Colombier 3459a747e4fSDavid du Colombier memset(to, ' ', len); 3469a747e4fSDavid du Colombier if(from == 0) 3479a747e4fSDavid du Colombier return 0; 3489a747e4fSDavid du Colombier while(len-- > 0){ 3499a747e4fSDavid du Colombier c = *from++; 3509a747e4fSDavid du Colombier if(c == '.') 3519a747e4fSDavid du Colombier return from; 3529a747e4fSDavid du Colombier if(c == 0) 3539a747e4fSDavid du Colombier break; 3549a747e4fSDavid du Colombier if(c >= 'a' && c <= 'z') 3559a747e4fSDavid du Colombier *to++ = c + 'A' - 'a'; 3569a747e4fSDavid du Colombier else 3579a747e4fSDavid du Colombier *to++ = c; 3589a747e4fSDavid du Colombier } 3599a747e4fSDavid du Colombier return 0; 3609a747e4fSDavid du Colombier } 3619a747e4fSDavid du Colombier 3629a747e4fSDavid du Colombier /* 3639a747e4fSDavid du Colombier * return offset of first file block 3649a747e4fSDavid du Colombier * 3659a747e4fSDavid du Colombier * This is a very simplistic dos file system. It only 3669a747e4fSDavid du Colombier * works on floppies, only looks in the root, and only 3679a747e4fSDavid du Colombier * returns a pointer to the first block of a file. 3689a747e4fSDavid du Colombier * 3699a747e4fSDavid du Colombier * This exists for cpu servers that have no hard disk 3709a747e4fSDavid du Colombier * or nvram to store the key on. 3719a747e4fSDavid du Colombier * 3729a747e4fSDavid du Colombier * Please don't make this any smarter: it stays resident 3739a747e4fSDavid du Colombier * and I'ld prefer not to waste the space on something that 3749a747e4fSDavid du Colombier * runs only at boottime -- presotto. 3759a747e4fSDavid du Colombier */ 3769a747e4fSDavid du Colombier static long 3779a747e4fSDavid du Colombier finddosfile(int fd, char *file) 3789a747e4fSDavid du Colombier { 3799a747e4fSDavid du Colombier uchar secbuf[512]; 3809a747e4fSDavid du Colombier char name[8]; 3819a747e4fSDavid du Colombier char ext[3]; 3829a747e4fSDavid du Colombier Dosboot *b; 3839a747e4fSDavid du Colombier Dosdir *root, *dp; 3849a747e4fSDavid du Colombier int nroot, sectsize, rootoff, rootsects, n; 3859a747e4fSDavid du Colombier 3869a747e4fSDavid du Colombier /* dos'ize file name */ 3879a747e4fSDavid du Colombier file = dosparse(file, name, 8); 3889a747e4fSDavid du Colombier dosparse(file, ext, 3); 3899a747e4fSDavid du Colombier 3909a747e4fSDavid du Colombier /* read boot block, check for sanity */ 3919a747e4fSDavid du Colombier b = (Dosboot*)secbuf; 3929a747e4fSDavid du Colombier if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf)) 3939a747e4fSDavid du Colombier return -1; 3949a747e4fSDavid du Colombier if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90) 3959a747e4fSDavid du Colombier return -1; 3969a747e4fSDavid du Colombier sectsize = GETSHORT(b->sectsize); 3979a747e4fSDavid du Colombier if(sectsize != 512) 3989a747e4fSDavid du Colombier return -1; 3999a747e4fSDavid du Colombier rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize; 4009a747e4fSDavid du Colombier if(seek(fd, rootoff, 0) < 0) 4019a747e4fSDavid du Colombier return -1; 4029a747e4fSDavid du Colombier nroot = GETSHORT(b->rootsize); 4039a747e4fSDavid du Colombier rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize; 4049a747e4fSDavid du Colombier if(rootsects <= 0 || rootsects > 64) 4059a747e4fSDavid du Colombier return -1; 4069a747e4fSDavid du Colombier 4079a747e4fSDavid du Colombier /* 4089a747e4fSDavid du Colombier * read root. it is contiguous to make stuff like 4099a747e4fSDavid du Colombier * this easier 4109a747e4fSDavid du Colombier */ 4119a747e4fSDavid du Colombier root = malloc(rootsects*sectsize); 4129a747e4fSDavid du Colombier if(read(fd, root, rootsects*sectsize) != rootsects*sectsize) 4139a747e4fSDavid du Colombier return -1; 4149a747e4fSDavid du Colombier n = -1; 4159a747e4fSDavid du Colombier for(dp = root; dp < &root[nroot]; dp++) 4169a747e4fSDavid du Colombier if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){ 4179a747e4fSDavid du Colombier n = GETSHORT(dp->start); 4189a747e4fSDavid du Colombier break; 4199a747e4fSDavid du Colombier } 4209a747e4fSDavid du Colombier free(root); 4219a747e4fSDavid du Colombier 4229a747e4fSDavid du Colombier if(n < 0) 4239a747e4fSDavid du Colombier return -1; 4249a747e4fSDavid du Colombier 4259a747e4fSDavid du Colombier /* 4269a747e4fSDavid du Colombier * dp->start is in cluster units, not sectors. The first 4279a747e4fSDavid du Colombier * cluster is cluster 2 which starts immediately after the 4289a747e4fSDavid du Colombier * root directory 4299a747e4fSDavid du Colombier */ 4309a747e4fSDavid du Colombier return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize; 4319a747e4fSDavid du Colombier } 4329a747e4fSDavid du Colombier 433