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), 42875fbba1SDavid du Colombier "pc", "#S/sd10/nvram", 0, sizeof(Nvrsafe), 43875fbba1SDavid du Colombier "pc", "#S/sd10/9fat", -1, sizeof(Nvrsafe), 449a747e4fSDavid du Colombier "pc", "#f/fd0disk", -1, 512, /* 512: #f requires whole sector reads */ 459a747e4fSDavid du Colombier "pc", "#f/fd1disk", -1, 512, 469a747e4fSDavid du Colombier "mips", "#r/nvram", 1024+900, sizeof(Nvrsafe), 47dc5a79c1SDavid du Colombier "power", "#F/flash/flash0", 0x440000, sizeof(Nvrsafe), 483468a491SDavid du Colombier "power", "#F/flash/flash", 0x440000, sizeof(Nvrsafe), 499a747e4fSDavid du Colombier "power", "#r/nvram", 4352, sizeof(Nvrsafe), /* OK for MTX-604e */ 502cca75a1SDavid du Colombier "power", "/nvram", 0, sizeof(Nvrsafe), /* OK for Ucu */ 51208510e1SDavid du Colombier "arm", "#F/flash/flash0", 0x100000, sizeof(Nvrsafe), 523468a491SDavid du Colombier "arm", "#F/flash/flash", 0x100000, sizeof(Nvrsafe), 539a747e4fSDavid du Colombier "debug", "/tmp/nvram", 0, sizeof(Nvrsafe), 549a747e4fSDavid du Colombier }; 559a747e4fSDavid du Colombier 569a747e4fSDavid du Colombier static char* 579a747e4fSDavid du Colombier readcons(char *prompt, char *def, int raw, char *buf, int nbuf) 589a747e4fSDavid du Colombier { 599a747e4fSDavid du Colombier int fdin, fdout, ctl, n, m; 609a747e4fSDavid du Colombier char line[10]; 619a747e4fSDavid du Colombier 629a747e4fSDavid du Colombier fdin = open("/dev/cons", OREAD); 639a747e4fSDavid du Colombier if(fdin < 0) 649a747e4fSDavid du Colombier fdin = 0; 659a747e4fSDavid du Colombier fdout = open("/dev/cons", OWRITE); 669a747e4fSDavid du Colombier if(fdout < 0) 679a747e4fSDavid du Colombier fdout = 1; 689a747e4fSDavid du Colombier if(def != nil) 699a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 709a747e4fSDavid du Colombier else 719a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 729a747e4fSDavid du Colombier if(raw){ 739a747e4fSDavid du Colombier ctl = open("/dev/consctl", OWRITE); 749a747e4fSDavid du Colombier if(ctl >= 0) 759a747e4fSDavid du Colombier write(ctl, "rawon", 5); 769a747e4fSDavid du Colombier } else 779a747e4fSDavid du Colombier ctl = -1; 789a747e4fSDavid du Colombier 799a747e4fSDavid du Colombier m = 0; 809a747e4fSDavid du Colombier for(;;){ 819a747e4fSDavid du Colombier n = read(fdin, line, 1); 829a747e4fSDavid du Colombier if(n == 0){ 839a747e4fSDavid du Colombier close(ctl); 849a747e4fSDavid du Colombier werrstr("readcons: EOF"); 859a747e4fSDavid du Colombier return nil; 869a747e4fSDavid du Colombier } 879a747e4fSDavid du Colombier if(n < 0){ 889a747e4fSDavid du Colombier close(ctl); 899a747e4fSDavid du Colombier werrstr("can't read cons"); 909a747e4fSDavid du Colombier return nil; 919a747e4fSDavid du Colombier } 929a747e4fSDavid du Colombier if(line[0] == 0x7f) 939a747e4fSDavid du Colombier exits(0); 949a747e4fSDavid du Colombier if(n == 0 || line[0] == '\n' || line[0] == '\r'){ 959a747e4fSDavid du Colombier if(raw){ 969a747e4fSDavid du Colombier write(ctl, "rawoff", 6); 979a747e4fSDavid du Colombier write(fdout, "\n", 1); 989a747e4fSDavid du Colombier close(ctl); 999a747e4fSDavid du Colombier } 1009a747e4fSDavid du Colombier buf[m] = '\0'; 1019a747e4fSDavid du Colombier if(buf[0]=='\0' && def) 1029a747e4fSDavid du Colombier strcpy(buf, def); 1039a747e4fSDavid du Colombier return buf; 1049a747e4fSDavid du Colombier } 1059a747e4fSDavid du Colombier if(line[0] == '\b'){ 1069a747e4fSDavid du Colombier if(m > 0) 1079a747e4fSDavid du Colombier m--; 1089a747e4fSDavid du Colombier }else if(line[0] == 0x15){ /* ^U: line kill */ 1099a747e4fSDavid du Colombier m = 0; 1109a747e4fSDavid du Colombier if(def != nil) 1119a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 1129a747e4fSDavid du Colombier else 1139a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 1149a747e4fSDavid du Colombier }else{ 1159a747e4fSDavid du Colombier if(m >= nbuf-1){ 1169a747e4fSDavid du Colombier fprint(fdout, "line too long\n"); 1179a747e4fSDavid du Colombier m = 0; 1189a747e4fSDavid du Colombier if(def != nil) 1199a747e4fSDavid du Colombier fprint(fdout, "%s[%s]: ", prompt, def); 1209a747e4fSDavid du Colombier else 1219a747e4fSDavid du Colombier fprint(fdout, "%s: ", prompt); 1229a747e4fSDavid du Colombier }else 1239a747e4fSDavid du Colombier buf[m++] = line[0]; 1249a747e4fSDavid du Colombier } 1259a747e4fSDavid du Colombier } 1269a747e4fSDavid du Colombier } 1279a747e4fSDavid du Colombier 1286822557bSDavid du Colombier typedef struct { 1296822557bSDavid du Colombier int fd; 1306822557bSDavid du Colombier int safeoff; 1316822557bSDavid du Colombier int safelen; 1326822557bSDavid du Colombier } Nvrwhere; 1339a747e4fSDavid du Colombier 1343468a491SDavid du Colombier static char *nvrfile = nil, *cputype = nil; 1353468a491SDavid du Colombier 1366822557bSDavid du Colombier /* returns with *locp filled in and locp->fd open, if possible */ 1376822557bSDavid du Colombier static void 1386822557bSDavid du Colombier findnvram(Nvrwhere *locp) 1399a747e4fSDavid du Colombier { 140*98bee55eSDavid du Colombier char *nvrlen, *nvroff, *nvrcopy, *v[2]; 1416822557bSDavid du Colombier int fd, i, safeoff, safelen; 1429a747e4fSDavid du Colombier 1433468a491SDavid du Colombier if (nvrfile == nil) 144d3c05884SDavid du Colombier nvrfile = getenv("nvram"); 1453468a491SDavid du Colombier if (cputype == nil) 1469a747e4fSDavid du Colombier cputype = getenv("cputype"); 1479a747e4fSDavid du Colombier if(cputype == nil) 1486822557bSDavid du Colombier cputype = strdup("mips"); 1498deabd96SDavid du Colombier if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0) { 1508deabd96SDavid du Colombier free(cputype); 1516822557bSDavid du Colombier cputype = strdup("pc"); 1528deabd96SDavid du Colombier } 1539a747e4fSDavid du Colombier 1549a747e4fSDavid du Colombier fd = -1; 1559a747e4fSDavid du Colombier safeoff = -1; 1569a747e4fSDavid du Colombier safelen = -1; 1578deabd96SDavid du Colombier if(nvrfile != nil && *nvrfile != '\0'){ 158d3c05884SDavid du Colombier /* accept device and device!file */ 159*98bee55eSDavid du Colombier nvrcopy = strdup(nvrfile); 160*98bee55eSDavid du Colombier i = gettokens(nvrcopy, v, nelem(v), "!"); 1618deabd96SDavid du Colombier if (i < 1) { 1628deabd96SDavid du Colombier i = 1; 1638deabd96SDavid du Colombier v[0] = ""; 1648deabd96SDavid du Colombier v[1] = nil; 1658deabd96SDavid du Colombier } 166d3c05884SDavid du Colombier fd = open(v[0], ORDWR); 167340a6d68SDavid du Colombier if (fd < 0) 168340a6d68SDavid du Colombier fd = open(v[0], OREAD); 169d3c05884SDavid du Colombier safelen = sizeof(Nvrsafe); 170d3c05884SDavid du Colombier if(strstr(v[0], "/9fat") == nil) 171d3c05884SDavid du Colombier safeoff = 0; 172d3c05884SDavid du Colombier nvrlen = getenv("nvrlen"); 173d3c05884SDavid du Colombier if(nvrlen != nil) 174d3c05884SDavid du Colombier safelen = atoi(nvrlen); 175d3c05884SDavid du Colombier nvroff = getenv("nvroff"); 1766822557bSDavid du Colombier if(nvroff != nil) 177d3c05884SDavid du Colombier if(strcmp(nvroff, "dos") == 0) 178d3c05884SDavid du Colombier safeoff = -1; 179d3c05884SDavid du Colombier else 180d3c05884SDavid du Colombier safeoff = atoi(nvroff); 181d3c05884SDavid du Colombier if(safeoff < 0 && fd >= 0){ 182d3c05884SDavid du Colombier safelen = 512; 183d3c05884SDavid du Colombier safeoff = finddosfile(fd, i == 2? v[1]: "plan9.nvr"); 1846822557bSDavid du Colombier if(safeoff < 0){ /* didn't find plan9.nvr? */ 185d3c05884SDavid du Colombier close(fd); 186d3c05884SDavid du Colombier fd = -1; 187d3c05884SDavid du Colombier } 188d3c05884SDavid du Colombier } 189*98bee55eSDavid du Colombier free(nvrcopy); 190d3c05884SDavid du Colombier free(nvroff); 1916822557bSDavid du Colombier free(nvrlen); 192*98bee55eSDavid du Colombier }else{ 1939a747e4fSDavid du Colombier for(i=0; i<nelem(nvtab); i++){ 1949a747e4fSDavid du Colombier if(strcmp(cputype, nvtab[i].cputype) != 0) 1959a747e4fSDavid du Colombier continue; 1969a747e4fSDavid du Colombier if((fd = open(nvtab[i].file, ORDWR)) < 0) 1979a747e4fSDavid du Colombier continue; 1989a747e4fSDavid du Colombier safeoff = nvtab[i].off; 1999a747e4fSDavid du Colombier safelen = nvtab[i].len; 2009a747e4fSDavid du Colombier if(safeoff == -1){ 2019a747e4fSDavid du Colombier safeoff = finddosfile(fd, "plan9.nvr"); 2026822557bSDavid du Colombier if(safeoff < 0){ /* didn't find plan9.nvr? */ 2039a747e4fSDavid du Colombier close(fd); 2049a747e4fSDavid du Colombier fd = -1; 2059a747e4fSDavid du Colombier continue; 2069a747e4fSDavid du Colombier } 2079a747e4fSDavid du Colombier } 208*98bee55eSDavid du Colombier nvrfile = strdup(nvtab[i].file); 2099a747e4fSDavid du Colombier break; 2109a747e4fSDavid du Colombier } 211*98bee55eSDavid du Colombier if(i >= nelem(nvtab)) /* tried them all? */ 212*98bee55eSDavid du Colombier werrstr(""); /* ignore failed opens */ 213*98bee55eSDavid du Colombier } 2146822557bSDavid du Colombier locp->fd = fd; 2156822557bSDavid du Colombier locp->safelen = safelen; 2166822557bSDavid du Colombier locp->safeoff = safeoff; 217d3c05884SDavid du Colombier } 2189a747e4fSDavid du Colombier 2196822557bSDavid du Colombier /* 2206822557bSDavid du Colombier * get key info out of nvram. since there isn't room in the PC's nvram use 2216822557bSDavid du Colombier * a disk partition there. 2226822557bSDavid du Colombier */ 2236822557bSDavid du Colombier int 2246822557bSDavid du Colombier readnvram(Nvrsafe *safep, int flag) 2256822557bSDavid du Colombier { 2266822557bSDavid du Colombier int err; 2276822557bSDavid du Colombier char buf[512], in[128]; /* 512 for floppy i/o */ 2286822557bSDavid du Colombier Nvrsafe *safe; 2296822557bSDavid du Colombier Nvrwhere loc; 2306822557bSDavid du Colombier 2316822557bSDavid du Colombier err = 0; 23207b9f4d0SDavid du Colombier safe = (Nvrsafe*)buf; 2336822557bSDavid du Colombier memset(&loc, 0, sizeof loc); 2346822557bSDavid du Colombier findnvram(&loc); 2356822557bSDavid du Colombier if (loc.safelen < 0) 2366822557bSDavid du Colombier loc.safelen = sizeof *safe; 2376822557bSDavid du Colombier else if (loc.safelen > sizeof buf) 2386822557bSDavid du Colombier loc.safelen = sizeof buf; 2396822557bSDavid du Colombier if (loc.safeoff < 0) { 240*98bee55eSDavid du Colombier fprint(2, "readnvram: can't find nvram\n"); 2416822557bSDavid du Colombier if(!(flag&NVwritemem)) 2426822557bSDavid du Colombier memset(safep, 0, sizeof(*safep)); 24307b9f4d0SDavid du Colombier safe = safep; 24407b9f4d0SDavid du Colombier /* 24507b9f4d0SDavid du Colombier * allow user to type the data for authentication, 24607b9f4d0SDavid du Colombier * even if there's no nvram to store it in. 24707b9f4d0SDavid du Colombier */ 2486822557bSDavid du Colombier } 2496822557bSDavid du Colombier 2506822557bSDavid du Colombier if(flag&NVwritemem) 2516822557bSDavid du Colombier safe = safep; 2526822557bSDavid du Colombier else { 2536822557bSDavid du Colombier memset(safep, 0, sizeof(*safep)); 254*98bee55eSDavid du Colombier werrstr(""); 2552ce711d4SDavid du Colombier if(loc.fd < 0 2562ce711d4SDavid du Colombier || seek(loc.fd, loc.safeoff, 0) < 0 2572ce711d4SDavid du Colombier || read(loc.fd, buf, loc.safelen) != loc.safelen){ 2582ce711d4SDavid du Colombier err = 1; 2592ce711d4SDavid du Colombier if(flag&(NVwrite|NVwriteonerr)) 260*98bee55eSDavid du Colombier if(loc.fd < 0 && nvrfile != nil) 2613468a491SDavid du Colombier fprint(2, "can't open %s: %r\n", nvrfile); 262*98bee55eSDavid du Colombier else if(loc.fd < 0){ 263*98bee55eSDavid du Colombier /* this will have been printed above */ 264*98bee55eSDavid du Colombier // fprint(2, "can't find nvram: %r\n"); 265*98bee55eSDavid du Colombier }else if (seek(loc.fd, loc.safeoff, 0) < 0) 2663468a491SDavid du Colombier fprint(2, "can't seek %s to %d: %r\n", 2673468a491SDavid du Colombier nvrfile, loc.safeoff); 2682ce711d4SDavid du Colombier else 2693468a491SDavid du Colombier fprint(2, "can't read %d bytes from %s: %r\n", 2703468a491SDavid du Colombier loc.safelen, nvrfile); 2716822557bSDavid du Colombier /* start from scratch */ 2729a747e4fSDavid du Colombier memset(safep, 0, sizeof(*safep)); 2739a747e4fSDavid du Colombier safe = safep; 2749a747e4fSDavid du Colombier }else{ 2756822557bSDavid du Colombier *safep = *safe; /* overwrite arg with data read */ 2769a747e4fSDavid du Colombier safe = safep; 2779a747e4fSDavid du Colombier 2786822557bSDavid du Colombier /* verify data read */ 2796822557bSDavid du Colombier err |= check(safe->machkey, DESKEYLEN, safe->machsum, 280*98bee55eSDavid du Colombier "bad authentication password"); 2816822557bSDavid du Colombier // err |= check(safe->config, CONFIGLEN, safe->configsum, 282*98bee55eSDavid du Colombier // "bad secstore password"); 2836822557bSDavid du Colombier err |= check(safe->authid, ANAMELEN, safe->authidsum, 2846822557bSDavid du Colombier "bad authentication id"); 2856822557bSDavid du Colombier err |= check(safe->authdom, DOMLEN, safe->authdomsum, 2866822557bSDavid du Colombier "bad authentication domain"); 2875fe11e25SDavid du Colombier if(err == 0) 2885fe11e25SDavid du Colombier if(safe->authid[0]==0 || safe->authdom[0]==0){ 2895fe11e25SDavid du Colombier fprint(2, "empty nvram authid or authdom\n"); 2905fe11e25SDavid du Colombier err = 1; 2915fe11e25SDavid du Colombier } 2929a747e4fSDavid du Colombier } 2936822557bSDavid du Colombier } 2949a747e4fSDavid du Colombier 2956822557bSDavid du Colombier if((flag&(NVwrite|NVwritemem)) || (err && (flag&NVwriteonerr))){ 2966822557bSDavid du Colombier if (!(flag&NVwritemem)) { 2976822557bSDavid du Colombier readcons("authid", nil, 0, safe->authid, 2986822557bSDavid du Colombier sizeof safe->authid); 2996822557bSDavid du Colombier readcons("authdom", nil, 0, safe->authdom, 3006822557bSDavid du Colombier sizeof safe->authdom); 3019a747e4fSDavid du Colombier for(;;){ 302*98bee55eSDavid du Colombier if(readcons("auth password", nil, 1, in, 303*98bee55eSDavid du Colombier sizeof in) == nil) 3049a747e4fSDavid du Colombier goto Out; 3059a747e4fSDavid du Colombier if(passtokey(safe->machkey, in)) 3069a747e4fSDavid du Colombier break; 3079a747e4fSDavid du Colombier } 308*98bee55eSDavid du Colombier readcons("secstore password", nil, 1, safe->config, 309*98bee55eSDavid du Colombier sizeof safe->config); 3106822557bSDavid du Colombier } 3116822557bSDavid du Colombier 3126822557bSDavid du Colombier // safe->authsum = nvcsum(safe->authkey, DESKEYLEN); 3139a747e4fSDavid du Colombier safe->machsum = nvcsum(safe->machkey, DESKEYLEN); 3149a747e4fSDavid du Colombier safe->configsum = nvcsum(safe->config, CONFIGLEN); 3156822557bSDavid du Colombier safe->authidsum = nvcsum(safe->authid, sizeof safe->authid); 3166822557bSDavid du Colombier safe->authdomsum = nvcsum(safe->authdom, sizeof safe->authdom); 317208510e1SDavid du Colombier 3186822557bSDavid du Colombier *(Nvrsafe*)buf = *safe; 319*98bee55eSDavid du Colombier werrstr(""); 3206822557bSDavid du Colombier if(loc.fd < 0 3216822557bSDavid du Colombier || seek(loc.fd, loc.safeoff, 0) < 0 3226822557bSDavid du Colombier || write(loc.fd, buf, loc.safelen) != loc.safelen){ 3239a747e4fSDavid du Colombier fprint(2, "can't write key to nvram: %r\n"); 3249a747e4fSDavid du Colombier err = 1; 3259a747e4fSDavid du Colombier }else 3269a747e4fSDavid du Colombier err = 0; 3279a747e4fSDavid du Colombier } 3289a747e4fSDavid du Colombier Out: 3296822557bSDavid du Colombier if (loc.fd >= 0) 3306822557bSDavid du Colombier close(loc.fd); 3319a747e4fSDavid du Colombier return err? -1: 0; 3329a747e4fSDavid du Colombier } 3339a747e4fSDavid du Colombier 3349a747e4fSDavid du Colombier typedef struct Dosboot Dosboot; 3359a747e4fSDavid du Colombier struct Dosboot{ 3369a747e4fSDavid du Colombier uchar magic[3]; /* really an xx86 JMP instruction */ 3379a747e4fSDavid du Colombier uchar version[8]; 3389a747e4fSDavid du Colombier uchar sectsize[2]; 3399a747e4fSDavid du Colombier uchar clustsize; 3409a747e4fSDavid du Colombier uchar nresrv[2]; 3419a747e4fSDavid du Colombier uchar nfats; 3429a747e4fSDavid du Colombier uchar rootsize[2]; 3439a747e4fSDavid du Colombier uchar volsize[2]; 3449a747e4fSDavid du Colombier uchar mediadesc; 3459a747e4fSDavid du Colombier uchar fatsize[2]; 3469a747e4fSDavid du Colombier uchar trksize[2]; 3479a747e4fSDavid du Colombier uchar nheads[2]; 3489a747e4fSDavid du Colombier uchar nhidden[4]; 3499a747e4fSDavid du Colombier uchar bigvolsize[4]; 3509a747e4fSDavid du Colombier uchar driveno; 3519a747e4fSDavid du Colombier uchar reserved0; 3529a747e4fSDavid du Colombier uchar bootsig; 3539a747e4fSDavid du Colombier uchar volid[4]; 3549a747e4fSDavid du Colombier uchar label[11]; 3559a747e4fSDavid du Colombier uchar type[8]; 3569a747e4fSDavid du Colombier }; 3579a747e4fSDavid du Colombier #define GETSHORT(p) (((p)[1]<<8) | (p)[0]) 3589a747e4fSDavid du Colombier #define GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p))) 3599a747e4fSDavid du Colombier 3609a747e4fSDavid du Colombier typedef struct Dosdir Dosdir; 3619a747e4fSDavid du Colombier struct Dosdir 3629a747e4fSDavid du Colombier { 3639a747e4fSDavid du Colombier char name[8]; 3649a747e4fSDavid du Colombier char ext[3]; 3659a747e4fSDavid du Colombier uchar attr; 3669a747e4fSDavid du Colombier uchar reserved[10]; 3679a747e4fSDavid du Colombier uchar time[2]; 3689a747e4fSDavid du Colombier uchar date[2]; 3699a747e4fSDavid du Colombier uchar start[2]; 3709a747e4fSDavid du Colombier uchar length[4]; 3719a747e4fSDavid du Colombier }; 3729a747e4fSDavid du Colombier 3739a747e4fSDavid du Colombier static char* 3749a747e4fSDavid du Colombier dosparse(char *from, char *to, int len) 3759a747e4fSDavid du Colombier { 3769a747e4fSDavid du Colombier char c; 3779a747e4fSDavid du Colombier 3789a747e4fSDavid du Colombier memset(to, ' ', len); 3799a747e4fSDavid du Colombier if(from == 0) 3809a747e4fSDavid du Colombier return 0; 3819a747e4fSDavid du Colombier while(len-- > 0){ 3829a747e4fSDavid du Colombier c = *from++; 3839a747e4fSDavid du Colombier if(c == '.') 3849a747e4fSDavid du Colombier return from; 3859a747e4fSDavid du Colombier if(c == 0) 3869a747e4fSDavid du Colombier break; 3879a747e4fSDavid du Colombier if(c >= 'a' && c <= 'z') 3889a747e4fSDavid du Colombier *to++ = c + 'A' - 'a'; 3899a747e4fSDavid du Colombier else 3909a747e4fSDavid du Colombier *to++ = c; 3919a747e4fSDavid du Colombier } 3929a747e4fSDavid du Colombier return 0; 3939a747e4fSDavid du Colombier } 3949a747e4fSDavid du Colombier 3959a747e4fSDavid du Colombier /* 3969a747e4fSDavid du Colombier * return offset of first file block 3979a747e4fSDavid du Colombier * 3989a747e4fSDavid du Colombier * This is a very simplistic dos file system. It only 3999a747e4fSDavid du Colombier * works on floppies, only looks in the root, and only 4009a747e4fSDavid du Colombier * returns a pointer to the first block of a file. 4019a747e4fSDavid du Colombier * 4029a747e4fSDavid du Colombier * This exists for cpu servers that have no hard disk 4039a747e4fSDavid du Colombier * or nvram to store the key on. 4049a747e4fSDavid du Colombier * 4059a747e4fSDavid du Colombier * Please don't make this any smarter: it stays resident 4069a747e4fSDavid du Colombier * and I'ld prefer not to waste the space on something that 4079a747e4fSDavid du Colombier * runs only at boottime -- presotto. 4089a747e4fSDavid du Colombier */ 4099a747e4fSDavid du Colombier static long 4109a747e4fSDavid du Colombier finddosfile(int fd, char *file) 4119a747e4fSDavid du Colombier { 4129a747e4fSDavid du Colombier uchar secbuf[512]; 4139a747e4fSDavid du Colombier char name[8]; 4149a747e4fSDavid du Colombier char ext[3]; 4159a747e4fSDavid du Colombier Dosboot *b; 4169a747e4fSDavid du Colombier Dosdir *root, *dp; 4179a747e4fSDavid du Colombier int nroot, sectsize, rootoff, rootsects, n; 4189a747e4fSDavid du Colombier 4199a747e4fSDavid du Colombier /* dos'ize file name */ 4209a747e4fSDavid du Colombier file = dosparse(file, name, 8); 4219a747e4fSDavid du Colombier dosparse(file, ext, 3); 4229a747e4fSDavid du Colombier 4239a747e4fSDavid du Colombier /* read boot block, check for sanity */ 4249a747e4fSDavid du Colombier b = (Dosboot*)secbuf; 4259a747e4fSDavid du Colombier if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf)) 4269a747e4fSDavid du Colombier return -1; 4279a747e4fSDavid du Colombier if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90) 4289a747e4fSDavid du Colombier return -1; 4299a747e4fSDavid du Colombier sectsize = GETSHORT(b->sectsize); 4309a747e4fSDavid du Colombier if(sectsize != 512) 4319a747e4fSDavid du Colombier return -1; 4329a747e4fSDavid du Colombier rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize; 4339a747e4fSDavid du Colombier if(seek(fd, rootoff, 0) < 0) 4349a747e4fSDavid du Colombier return -1; 4359a747e4fSDavid du Colombier nroot = GETSHORT(b->rootsize); 4369a747e4fSDavid du Colombier rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize; 4379a747e4fSDavid du Colombier if(rootsects <= 0 || rootsects > 64) 4389a747e4fSDavid du Colombier return -1; 4399a747e4fSDavid du Colombier 4409a747e4fSDavid du Colombier /* 4419a747e4fSDavid du Colombier * read root. it is contiguous to make stuff like 4429a747e4fSDavid du Colombier * this easier 4439a747e4fSDavid du Colombier */ 4449a747e4fSDavid du Colombier root = malloc(rootsects*sectsize); 4459a747e4fSDavid du Colombier if(read(fd, root, rootsects*sectsize) != rootsects*sectsize) 4469a747e4fSDavid du Colombier return -1; 4479a747e4fSDavid du Colombier n = -1; 4489a747e4fSDavid du Colombier for(dp = root; dp < &root[nroot]; dp++) 4499a747e4fSDavid du Colombier if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){ 4509a747e4fSDavid du Colombier n = GETSHORT(dp->start); 4519a747e4fSDavid du Colombier break; 4529a747e4fSDavid du Colombier } 4539a747e4fSDavid du Colombier free(root); 4549a747e4fSDavid du Colombier 4559a747e4fSDavid du Colombier if(n < 0) 4569a747e4fSDavid du Colombier return -1; 4579a747e4fSDavid du Colombier 4589a747e4fSDavid du Colombier /* 4599a747e4fSDavid du Colombier * dp->start is in cluster units, not sectors. The first 4609a747e4fSDavid du Colombier * cluster is cluster 2 which starts immediately after the 4619a747e4fSDavid du Colombier * root directory 4629a747e4fSDavid du Colombier */ 4639a747e4fSDavid du Colombier return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize; 4649a747e4fSDavid du Colombier } 4659a747e4fSDavid du Colombier 466