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), 48*3468a491SDavid 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), 52*3468a491SDavid 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 134*3468a491SDavid du Colombier static char *nvrfile = nil, *cputype = nil; 135*3468a491SDavid 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*3468a491SDavid du Colombier char *nvrlen, *nvroff, *v[2]; 1416822557bSDavid du Colombier int fd, i, safeoff, safelen; 1429a747e4fSDavid du Colombier 143*3468a491SDavid du Colombier if (nvrfile == nil) 144d3c05884SDavid du Colombier nvrfile = getenv("nvram"); 145*3468a491SDavid 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 */ 159d3c05884SDavid du Colombier i = gettokens(nvrfile, v, nelem(v), "!"); 1608deabd96SDavid du Colombier if (i < 1) { 1618deabd96SDavid du Colombier i = 1; 1628deabd96SDavid du Colombier v[0] = ""; 1638deabd96SDavid du Colombier v[1] = nil; 1648deabd96SDavid du Colombier } 165d3c05884SDavid du Colombier fd = open(v[0], ORDWR); 166340a6d68SDavid du Colombier if (fd < 0) 167340a6d68SDavid du Colombier fd = open(v[0], OREAD); 168d3c05884SDavid du Colombier safelen = sizeof(Nvrsafe); 169d3c05884SDavid du Colombier if(strstr(v[0], "/9fat") == nil) 170d3c05884SDavid du Colombier safeoff = 0; 171d3c05884SDavid du Colombier nvrlen = getenv("nvrlen"); 172d3c05884SDavid du Colombier if(nvrlen != nil) 173d3c05884SDavid du Colombier safelen = atoi(nvrlen); 174d3c05884SDavid du Colombier nvroff = getenv("nvroff"); 1756822557bSDavid du Colombier if(nvroff != nil) 176d3c05884SDavid du Colombier if(strcmp(nvroff, "dos") == 0) 177d3c05884SDavid du Colombier safeoff = -1; 178d3c05884SDavid du Colombier else 179d3c05884SDavid du Colombier safeoff = atoi(nvroff); 180d3c05884SDavid du Colombier if(safeoff < 0 && fd >= 0){ 181d3c05884SDavid du Colombier safelen = 512; 182d3c05884SDavid du Colombier safeoff = finddosfile(fd, i == 2? v[1]: "plan9.nvr"); 1836822557bSDavid du Colombier if(safeoff < 0){ /* didn't find plan9.nvr? */ 184d3c05884SDavid du Colombier close(fd); 185d3c05884SDavid du Colombier fd = -1; 186d3c05884SDavid du Colombier } 187d3c05884SDavid du Colombier } 188d3c05884SDavid du Colombier free(nvroff); 1896822557bSDavid du Colombier free(nvrlen); 1906822557bSDavid du Colombier }else 1919a747e4fSDavid du Colombier for(i=0; i<nelem(nvtab); i++){ 1929a747e4fSDavid du Colombier if(strcmp(cputype, nvtab[i].cputype) != 0) 1939a747e4fSDavid du Colombier continue; 1949a747e4fSDavid du Colombier if((fd = open(nvtab[i].file, ORDWR)) < 0) 1959a747e4fSDavid du Colombier continue; 1969a747e4fSDavid du Colombier safeoff = nvtab[i].off; 1979a747e4fSDavid du Colombier safelen = nvtab[i].len; 1989a747e4fSDavid du Colombier if(safeoff == -1){ 1999a747e4fSDavid du Colombier safeoff = finddosfile(fd, "plan9.nvr"); 2006822557bSDavid du Colombier if(safeoff < 0){ /* didn't find plan9.nvr? */ 2019a747e4fSDavid du Colombier close(fd); 2029a747e4fSDavid du Colombier fd = -1; 2039a747e4fSDavid du Colombier continue; 2049a747e4fSDavid du Colombier } 2059a747e4fSDavid du Colombier } 2069a747e4fSDavid du Colombier break; 2079a747e4fSDavid du Colombier } 2086822557bSDavid du Colombier locp->fd = fd; 2096822557bSDavid du Colombier locp->safelen = safelen; 2106822557bSDavid du Colombier locp->safeoff = safeoff; 211d3c05884SDavid du Colombier } 2129a747e4fSDavid du Colombier 2136822557bSDavid du Colombier /* 2146822557bSDavid du Colombier * get key info out of nvram. since there isn't room in the PC's nvram use 2156822557bSDavid du Colombier * a disk partition there. 2166822557bSDavid du Colombier */ 2176822557bSDavid du Colombier int 2186822557bSDavid du Colombier readnvram(Nvrsafe *safep, int flag) 2196822557bSDavid du Colombier { 2206822557bSDavid du Colombier int err; 2216822557bSDavid du Colombier char buf[512], in[128]; /* 512 for floppy i/o */ 2226822557bSDavid du Colombier Nvrsafe *safe; 2236822557bSDavid du Colombier Nvrwhere loc; 2246822557bSDavid du Colombier 2256822557bSDavid du Colombier err = 0; 22607b9f4d0SDavid du Colombier safe = (Nvrsafe*)buf; 2276822557bSDavid du Colombier memset(&loc, 0, sizeof loc); 2286822557bSDavid du Colombier findnvram(&loc); 2296822557bSDavid du Colombier if (loc.safelen < 0) 2306822557bSDavid du Colombier loc.safelen = sizeof *safe; 2316822557bSDavid du Colombier else if (loc.safelen > sizeof buf) 2326822557bSDavid du Colombier loc.safelen = sizeof buf; 2336822557bSDavid du Colombier if (loc.safeoff < 0) { 2346822557bSDavid du Colombier fprint(2, "readnvram: couldn't find nvram\n"); 2356822557bSDavid du Colombier if(!(flag&NVwritemem)) 2366822557bSDavid du Colombier memset(safep, 0, sizeof(*safep)); 23707b9f4d0SDavid du Colombier safe = safep; 23807b9f4d0SDavid du Colombier /* 23907b9f4d0SDavid du Colombier * allow user to type the data for authentication, 24007b9f4d0SDavid du Colombier * even if there's no nvram to store it in. 24107b9f4d0SDavid du Colombier */ 2426822557bSDavid du Colombier } 2436822557bSDavid du Colombier 2446822557bSDavid du Colombier if(flag&NVwritemem) 2456822557bSDavid du Colombier safe = safep; 2466822557bSDavid du Colombier else { 2476822557bSDavid du Colombier memset(safep, 0, sizeof(*safep)); 248*3468a491SDavid du Colombier if(loc.fd < 0) 249*3468a491SDavid du Colombier fprint(2, "can't open %s: %r\n", nvrfile); 250*3468a491SDavid du Colombier else if (seek(loc.fd, loc.safeoff, 0) < 0) 251*3468a491SDavid du Colombier fprint(2, "can't seek %s to %d: %r\n", 252*3468a491SDavid du Colombier nvrfile, loc.safeoff); 253*3468a491SDavid du Colombier else if (read(loc.fd, buf, loc.safelen) != loc.safelen){ 2549a747e4fSDavid du Colombier err = 1; 2559a747e4fSDavid du Colombier if(flag&(NVwrite|NVwriteonerr)) 256*3468a491SDavid du Colombier fprint(2, "can't read %d bytes from %s: %r\n", 257*3468a491SDavid du Colombier loc.safelen, nvrfile); 2586822557bSDavid du Colombier /* start from scratch */ 2599a747e4fSDavid du Colombier memset(safep, 0, sizeof(*safep)); 2609a747e4fSDavid du Colombier safe = safep; 2619a747e4fSDavid du Colombier }else{ 2626822557bSDavid du Colombier *safep = *safe; /* overwrite arg with data read */ 2639a747e4fSDavid du Colombier safe = safep; 2649a747e4fSDavid du Colombier 2656822557bSDavid du Colombier /* verify data read */ 2666822557bSDavid du Colombier err |= check(safe->machkey, DESKEYLEN, safe->machsum, 2676822557bSDavid du Colombier "bad nvram key"); 2686822557bSDavid du Colombier // err |= check(safe->config, CONFIGLEN, safe->configsum, 2696822557bSDavid du Colombier // "bad secstore key"); 2706822557bSDavid du Colombier err |= check(safe->authid, ANAMELEN, safe->authidsum, 2716822557bSDavid du Colombier "bad authentication id"); 2726822557bSDavid du Colombier err |= check(safe->authdom, DOMLEN, safe->authdomsum, 2736822557bSDavid du Colombier "bad authentication domain"); 2745fe11e25SDavid du Colombier if(err == 0) 2755fe11e25SDavid du Colombier if(safe->authid[0]==0 || safe->authdom[0]==0){ 2765fe11e25SDavid du Colombier fprint(2, "empty nvram authid or authdom\n"); 2775fe11e25SDavid du Colombier err = 1; 2785fe11e25SDavid du Colombier } 2799a747e4fSDavid du Colombier } 2806822557bSDavid du Colombier } 2819a747e4fSDavid du Colombier 2826822557bSDavid du Colombier if((flag&(NVwrite|NVwritemem)) || (err && (flag&NVwriteonerr))){ 2836822557bSDavid du Colombier if (!(flag&NVwritemem)) { 2846822557bSDavid du Colombier readcons("authid", nil, 0, safe->authid, 2856822557bSDavid du Colombier sizeof safe->authid); 2866822557bSDavid du Colombier readcons("authdom", nil, 0, safe->authdom, 2876822557bSDavid du Colombier sizeof safe->authdom); 28801a344a2SDavid du Colombier readcons("secstore key", nil, 1, safe->config, 28901a344a2SDavid du Colombier sizeof safe->config); 2909a747e4fSDavid du Colombier for(;;){ 2916822557bSDavid du Colombier if(readcons("password", nil, 1, in, sizeof in) 2926822557bSDavid du Colombier == nil) 2939a747e4fSDavid du Colombier goto Out; 2949a747e4fSDavid du Colombier if(passtokey(safe->machkey, in)) 2959a747e4fSDavid du Colombier break; 2969a747e4fSDavid du Colombier } 2976822557bSDavid du Colombier } 2986822557bSDavid du Colombier 2996822557bSDavid du Colombier // safe->authsum = nvcsum(safe->authkey, DESKEYLEN); 3009a747e4fSDavid du Colombier safe->machsum = nvcsum(safe->machkey, DESKEYLEN); 3019a747e4fSDavid du Colombier safe->configsum = nvcsum(safe->config, CONFIGLEN); 3026822557bSDavid du Colombier safe->authidsum = nvcsum(safe->authid, sizeof safe->authid); 3036822557bSDavid du Colombier safe->authdomsum = nvcsum(safe->authdom, sizeof safe->authdom); 304208510e1SDavid du Colombier 3056822557bSDavid du Colombier *(Nvrsafe*)buf = *safe; 3066822557bSDavid du Colombier if(loc.fd < 0 3076822557bSDavid du Colombier || seek(loc.fd, loc.safeoff, 0) < 0 3086822557bSDavid du Colombier || write(loc.fd, buf, loc.safelen) != loc.safelen){ 3099a747e4fSDavid du Colombier fprint(2, "can't write key to nvram: %r\n"); 3109a747e4fSDavid du Colombier err = 1; 3119a747e4fSDavid du Colombier }else 3129a747e4fSDavid du Colombier err = 0; 3139a747e4fSDavid du Colombier } 3149a747e4fSDavid du Colombier Out: 3156822557bSDavid du Colombier if (loc.fd >= 0) 3166822557bSDavid du Colombier close(loc.fd); 3179a747e4fSDavid du Colombier return err? -1: 0; 3189a747e4fSDavid du Colombier } 3199a747e4fSDavid du Colombier 3209a747e4fSDavid du Colombier typedef struct Dosboot Dosboot; 3219a747e4fSDavid du Colombier struct Dosboot{ 3229a747e4fSDavid du Colombier uchar magic[3]; /* really an xx86 JMP instruction */ 3239a747e4fSDavid du Colombier uchar version[8]; 3249a747e4fSDavid du Colombier uchar sectsize[2]; 3259a747e4fSDavid du Colombier uchar clustsize; 3269a747e4fSDavid du Colombier uchar nresrv[2]; 3279a747e4fSDavid du Colombier uchar nfats; 3289a747e4fSDavid du Colombier uchar rootsize[2]; 3299a747e4fSDavid du Colombier uchar volsize[2]; 3309a747e4fSDavid du Colombier uchar mediadesc; 3319a747e4fSDavid du Colombier uchar fatsize[2]; 3329a747e4fSDavid du Colombier uchar trksize[2]; 3339a747e4fSDavid du Colombier uchar nheads[2]; 3349a747e4fSDavid du Colombier uchar nhidden[4]; 3359a747e4fSDavid du Colombier uchar bigvolsize[4]; 3369a747e4fSDavid du Colombier uchar driveno; 3379a747e4fSDavid du Colombier uchar reserved0; 3389a747e4fSDavid du Colombier uchar bootsig; 3399a747e4fSDavid du Colombier uchar volid[4]; 3409a747e4fSDavid du Colombier uchar label[11]; 3419a747e4fSDavid du Colombier uchar type[8]; 3429a747e4fSDavid du Colombier }; 3439a747e4fSDavid du Colombier #define GETSHORT(p) (((p)[1]<<8) | (p)[0]) 3449a747e4fSDavid du Colombier #define GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p))) 3459a747e4fSDavid du Colombier 3469a747e4fSDavid du Colombier typedef struct Dosdir Dosdir; 3479a747e4fSDavid du Colombier struct Dosdir 3489a747e4fSDavid du Colombier { 3499a747e4fSDavid du Colombier char name[8]; 3509a747e4fSDavid du Colombier char ext[3]; 3519a747e4fSDavid du Colombier uchar attr; 3529a747e4fSDavid du Colombier uchar reserved[10]; 3539a747e4fSDavid du Colombier uchar time[2]; 3549a747e4fSDavid du Colombier uchar date[2]; 3559a747e4fSDavid du Colombier uchar start[2]; 3569a747e4fSDavid du Colombier uchar length[4]; 3579a747e4fSDavid du Colombier }; 3589a747e4fSDavid du Colombier 3599a747e4fSDavid du Colombier static char* 3609a747e4fSDavid du Colombier dosparse(char *from, char *to, int len) 3619a747e4fSDavid du Colombier { 3629a747e4fSDavid du Colombier char c; 3639a747e4fSDavid du Colombier 3649a747e4fSDavid du Colombier memset(to, ' ', len); 3659a747e4fSDavid du Colombier if(from == 0) 3669a747e4fSDavid du Colombier return 0; 3679a747e4fSDavid du Colombier while(len-- > 0){ 3689a747e4fSDavid du Colombier c = *from++; 3699a747e4fSDavid du Colombier if(c == '.') 3709a747e4fSDavid du Colombier return from; 3719a747e4fSDavid du Colombier if(c == 0) 3729a747e4fSDavid du Colombier break; 3739a747e4fSDavid du Colombier if(c >= 'a' && c <= 'z') 3749a747e4fSDavid du Colombier *to++ = c + 'A' - 'a'; 3759a747e4fSDavid du Colombier else 3769a747e4fSDavid du Colombier *to++ = c; 3779a747e4fSDavid du Colombier } 3789a747e4fSDavid du Colombier return 0; 3799a747e4fSDavid du Colombier } 3809a747e4fSDavid du Colombier 3819a747e4fSDavid du Colombier /* 3829a747e4fSDavid du Colombier * return offset of first file block 3839a747e4fSDavid du Colombier * 3849a747e4fSDavid du Colombier * This is a very simplistic dos file system. It only 3859a747e4fSDavid du Colombier * works on floppies, only looks in the root, and only 3869a747e4fSDavid du Colombier * returns a pointer to the first block of a file. 3879a747e4fSDavid du Colombier * 3889a747e4fSDavid du Colombier * This exists for cpu servers that have no hard disk 3899a747e4fSDavid du Colombier * or nvram to store the key on. 3909a747e4fSDavid du Colombier * 3919a747e4fSDavid du Colombier * Please don't make this any smarter: it stays resident 3929a747e4fSDavid du Colombier * and I'ld prefer not to waste the space on something that 3939a747e4fSDavid du Colombier * runs only at boottime -- presotto. 3949a747e4fSDavid du Colombier */ 3959a747e4fSDavid du Colombier static long 3969a747e4fSDavid du Colombier finddosfile(int fd, char *file) 3979a747e4fSDavid du Colombier { 3989a747e4fSDavid du Colombier uchar secbuf[512]; 3999a747e4fSDavid du Colombier char name[8]; 4009a747e4fSDavid du Colombier char ext[3]; 4019a747e4fSDavid du Colombier Dosboot *b; 4029a747e4fSDavid du Colombier Dosdir *root, *dp; 4039a747e4fSDavid du Colombier int nroot, sectsize, rootoff, rootsects, n; 4049a747e4fSDavid du Colombier 4059a747e4fSDavid du Colombier /* dos'ize file name */ 4069a747e4fSDavid du Colombier file = dosparse(file, name, 8); 4079a747e4fSDavid du Colombier dosparse(file, ext, 3); 4089a747e4fSDavid du Colombier 4099a747e4fSDavid du Colombier /* read boot block, check for sanity */ 4109a747e4fSDavid du Colombier b = (Dosboot*)secbuf; 4119a747e4fSDavid du Colombier if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf)) 4129a747e4fSDavid du Colombier return -1; 4139a747e4fSDavid du Colombier if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90) 4149a747e4fSDavid du Colombier return -1; 4159a747e4fSDavid du Colombier sectsize = GETSHORT(b->sectsize); 4169a747e4fSDavid du Colombier if(sectsize != 512) 4179a747e4fSDavid du Colombier return -1; 4189a747e4fSDavid du Colombier rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize; 4199a747e4fSDavid du Colombier if(seek(fd, rootoff, 0) < 0) 4209a747e4fSDavid du Colombier return -1; 4219a747e4fSDavid du Colombier nroot = GETSHORT(b->rootsize); 4229a747e4fSDavid du Colombier rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize; 4239a747e4fSDavid du Colombier if(rootsects <= 0 || rootsects > 64) 4249a747e4fSDavid du Colombier return -1; 4259a747e4fSDavid du Colombier 4269a747e4fSDavid du Colombier /* 4279a747e4fSDavid du Colombier * read root. it is contiguous to make stuff like 4289a747e4fSDavid du Colombier * this easier 4299a747e4fSDavid du Colombier */ 4309a747e4fSDavid du Colombier root = malloc(rootsects*sectsize); 4319a747e4fSDavid du Colombier if(read(fd, root, rootsects*sectsize) != rootsects*sectsize) 4329a747e4fSDavid du Colombier return -1; 4339a747e4fSDavid du Colombier n = -1; 4349a747e4fSDavid du Colombier for(dp = root; dp < &root[nroot]; dp++) 4359a747e4fSDavid du Colombier if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){ 4369a747e4fSDavid du Colombier n = GETSHORT(dp->start); 4379a747e4fSDavid du Colombier break; 4389a747e4fSDavid du Colombier } 4399a747e4fSDavid du Colombier free(root); 4409a747e4fSDavid du Colombier 4419a747e4fSDavid du Colombier if(n < 0) 4429a747e4fSDavid du Colombier return -1; 4439a747e4fSDavid du Colombier 4449a747e4fSDavid du Colombier /* 4459a747e4fSDavid du Colombier * dp->start is in cluster units, not sectors. The first 4469a747e4fSDavid du Colombier * cluster is cluster 2 which starts immediately after the 4479a747e4fSDavid du Colombier * root directory 4489a747e4fSDavid du Colombier */ 4499a747e4fSDavid du Colombier return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize; 4509a747e4fSDavid du Colombier } 4519a747e4fSDavid du Colombier 452