⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readnvram.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <authsrv.h>static long	finddosfile(int, char*);static intcheck(void *x, int len, uchar sum, char *msg){	if(nvcsum(x, len) == sum)		return 0;	memset(x, 0, len);	fprint(2, "%s\n", msg);	return 1;}/* *  get key info out of nvram.  since there isn't room in the PC's nvram use *  a disk partition there. */static struct {	char *cputype;	char *file;	int off;	int len;} nvtab[] = {	"sparc", "#r/nvram", 1024+850, sizeof(Nvrsafe),	"pc", "#S/sdC0/nvram", 0, sizeof(Nvrsafe),	"pc", "#S/sdC0/9fat", -1, sizeof(Nvrsafe),	"pc", "#S/sdC1/nvram", 0, sizeof(Nvrsafe),	"pc", "#S/sdC1/9fat", -1, sizeof(Nvrsafe),	"pc", "#S/sdD0/nvram", 0, sizeof(Nvrsafe),	"pc", "#S/sdD0/9fat", -1, sizeof(Nvrsafe),	"pc", "#S/sdE0/nvram", 0, sizeof(Nvrsafe),	"pc", "#S/sdE0/9fat", -1, sizeof(Nvrsafe),	"pc", "#S/sdF0/nvram", 0, sizeof(Nvrsafe),	"pc", "#S/sdF0/9fat", -1, sizeof(Nvrsafe),	"pc", "#S/sd00/nvram", 0, sizeof(Nvrsafe),	"pc", "#S/sd00/9fat", -1, sizeof(Nvrsafe),	"pc", "#S/sd01/nvram", 0, sizeof(Nvrsafe),	"pc", "#S/sd01/9fat", -1, sizeof(Nvrsafe),	"pc", "#f/fd0disk", -1, 512,	/* 512: #f requires whole sector reads */	"pc", "#f/fd1disk", -1, 512,	"mips", "#r/nvram", 1024+900, sizeof(Nvrsafe),	"power", "#F/flash/flash0", 0x440000, sizeof(Nvrsafe),	"power", "#r/nvram", 4352, sizeof(Nvrsafe),	/* OK for MTX-604e */	"power", "/nvram", 0, sizeof(Nvrsafe),	/* OK for Ucu */	"debug", "/tmp/nvram", 0, sizeof(Nvrsafe),};static char*readcons(char *prompt, char *def, int raw, char *buf, int nbuf){	int fdin, fdout, ctl, n, m;	char line[10];	fdin = open("/dev/cons", OREAD);	if(fdin < 0)		fdin = 0;	fdout = open("/dev/cons", OWRITE);	if(fdout < 0)		fdout = 1;	if(def != nil)		fprint(fdout, "%s[%s]: ", prompt, def);	else		fprint(fdout, "%s: ", prompt);	if(raw){		ctl = open("/dev/consctl", OWRITE);		if(ctl >= 0)			write(ctl, "rawon", 5);	} else		ctl = -1;	m = 0;	for(;;){		n = read(fdin, line, 1);		if(n == 0){			close(ctl);			werrstr("readcons: EOF");			return nil;		}		if(n < 0){			close(ctl);			werrstr("can't read cons");			return nil;		}		if(line[0] == 0x7f)			exits(0);		if(n == 0 || line[0] == '\n' || line[0] == '\r'){			if(raw){				write(ctl, "rawoff", 6);				write(fdout, "\n", 1);				close(ctl);			}			buf[m] = '\0';			if(buf[0]=='\0' && def)				strcpy(buf, def);			return buf;		}		if(line[0] == '\b'){			if(m > 0)				m--;		}else if(line[0] == 0x15){	/* ^U: line kill */			m = 0;			if(def != nil)				fprint(fdout, "%s[%s]: ", prompt, def);			else				fprint(fdout, "%s: ", prompt);		}else{			if(m >= nbuf-1){				fprint(fdout, "line too long\n");				m = 0;				if(def != nil)					fprint(fdout, "%s[%s]: ", prompt, def);				else					fprint(fdout, "%s: ", prompt);			}else				buf[m++] = line[0];		}	}}/* *  get key info out of nvram.  since there isn't room in the PC's nvram use *  a disk partition there. */intreadnvram(Nvrsafe *safep, int flag){	char buf[1024], in[128], *cputype, *nvrfile, *nvrlen, *nvroff, *v[2];	int fd, err, i, safeoff, safelen;	Nvrsafe *safe;	err = 0;	memset(safep, 0, sizeof(*safep));	nvrfile = getenv("nvram");	cputype = getenv("cputype");	if(cputype == nil)		cputype = "mips";	if(strcmp(cputype, "386")==0 || strcmp(cputype, "alpha")==0)		cputype = "pc";	safe = (Nvrsafe*)buf;	fd = -1;	safeoff = -1;	safelen = -1;	if(nvrfile != nil){		/* accept device and device!file */		i = gettokens(nvrfile, v, nelem(v), "!");		fd = open(v[0], ORDWR);		safelen = sizeof(Nvrsafe);		if(strstr(v[0], "/9fat") == nil)			safeoff = 0;		nvrlen = getenv("nvrlen");		if(nvrlen != nil)			safelen = atoi(nvrlen);		nvroff = getenv("nvroff");		if(nvroff != nil){			if(strcmp(nvroff, "dos") == 0)				safeoff = -1;			else				safeoff = atoi(nvroff);		}		if(safeoff < 0 && fd >= 0){			safelen = 512;			safeoff = finddosfile(fd, i == 2 ? v[1] : "plan9.nvr");			if(safeoff < 0){				close(fd);				fd = -1;			}		}		free(nvrfile);		if(nvrlen != nil)			free(nvrlen);		if(nvroff != nil)			free(nvroff);	}else{		for(i=0; i<nelem(nvtab); i++){			if(strcmp(cputype, nvtab[i].cputype) != 0)				continue;			if((fd = open(nvtab[i].file, ORDWR)) < 0)				continue;			safeoff = nvtab[i].off;			safelen = nvtab[i].len;			if(safeoff == -1){				safeoff = finddosfile(fd, "plan9.nvr");				if(safeoff < 0){					close(fd);					fd = -1;					continue;				}			}			break;		}	}	if(fd < 0	|| seek(fd, safeoff, 0) < 0	|| read(fd, buf, safelen) != safelen){		err = 1;		if(flag&(NVwrite|NVwriteonerr))			fprint(2, "can't read nvram: %r\n");		memset(safep, 0, sizeof(*safep));		safe = safep;	}else{		*safep = *safe;		safe = safep;		err |= check(safe->machkey, DESKEYLEN, safe->machsum, "bad nvram key");//		err |= check(safe->config, CONFIGLEN, safe->configsum, "bad secstore key");		err |= check(safe->authid, ANAMELEN, safe->authidsum, "bad authentication id");		err |= check(safe->authdom, DOMLEN, safe->authdomsum, "bad authentication domain");		if(err == 0)		if(safe->authid[0]==0 || safe->authdom[0]==0){			fprint(2, "empty nvram authid or authdom\n");			err = 1;		}	}	if((flag&NVwrite) || (err && (flag&NVwriteonerr))){		readcons("authid", nil, 0, safe->authid, sizeof(safe->authid));		readcons("authdom", nil, 0, safe->authdom, sizeof(safe->authdom));		readcons("secstore key", nil, 1, safe->config, sizeof(safe->config));		for(;;){			if(readcons("password", nil, 1, in, sizeof in) == nil)				goto Out;			if(passtokey(safe->machkey, in))				break;		}		safe->machsum = nvcsum(safe->machkey, DESKEYLEN);		safe->configsum = nvcsum(safe->config, CONFIGLEN);		safe->authidsum = nvcsum(safe->authid, sizeof(safe->authid));		safe->authdomsum = nvcsum(safe->authdom, sizeof(safe->authdom));		*(Nvrsafe*)buf = *safe;		if(seek(fd, safeoff, 0) < 0		|| write(fd, buf, safelen) != safelen){			fprint(2, "can't write key to nvram: %r\n");			err = 1;		}else			err = 0;	}Out:	close(fd);	return err ? -1 : 0;}typedef struct Dosboot	Dosboot;struct Dosboot{	uchar	magic[3];	/* really an xx86 JMP instruction */	uchar	version[8];	uchar	sectsize[2];	uchar	clustsize;	uchar	nresrv[2];	uchar	nfats;	uchar	rootsize[2];	uchar	volsize[2];	uchar	mediadesc;	uchar	fatsize[2];	uchar	trksize[2];	uchar	nheads[2];	uchar	nhidden[4];	uchar	bigvolsize[4];	uchar	driveno;	uchar	reserved0;	uchar	bootsig;	uchar	volid[4];	uchar	label[11];	uchar	type[8];};#define	GETSHORT(p) (((p)[1]<<8) | (p)[0])#define	GETLONG(p) ((GETSHORT((p)+2) << 16) | GETSHORT((p)))typedef struct Dosdir	Dosdir;struct Dosdir{	char	name[8];	char	ext[3];	uchar	attr;	uchar	reserved[10];	uchar	time[2];	uchar	date[2];	uchar	start[2];	uchar	length[4];};static char*dosparse(char *from, char *to, int len){	char c;	memset(to, ' ', len);	if(from == 0)		return 0;	while(len-- > 0){		c = *from++;		if(c == '.')			return from;		if(c == 0)			break;		if(c >= 'a' && c <= 'z')			*to++ = c + 'A' - 'a';		else			*to++ = c;	}	return 0;}/* *  return offset of first file block * *  This is a very simplistic dos file system.  It only *  works on floppies, only looks in the root, and only *  returns a pointer to the first block of a file. * *  This exists for cpu servers that have no hard disk *  or nvram to store the key on. * *  Please don't make this any smarter: it stays resident *  and I'ld prefer not to waste the space on something that *  runs only at boottime -- presotto. */static longfinddosfile(int fd, char *file){	uchar secbuf[512];	char name[8];	char ext[3];	Dosboot	*b;	Dosdir *root, *dp;	int nroot, sectsize, rootoff, rootsects, n;	/* dos'ize file name */	file = dosparse(file, name, 8);	dosparse(file, ext, 3);	/* read boot block, check for sanity */	b = (Dosboot*)secbuf;	if(read(fd, secbuf, sizeof(secbuf)) != sizeof(secbuf))		return -1;	if(b->magic[0] != 0xEB || b->magic[1] != 0x3C || b->magic[2] != 0x90)		return -1;	sectsize = GETSHORT(b->sectsize);	if(sectsize != 512)		return -1;	rootoff = (GETSHORT(b->nresrv) + b->nfats*GETSHORT(b->fatsize)) * sectsize;	if(seek(fd, rootoff, 0) < 0)		return -1;	nroot = GETSHORT(b->rootsize);	rootsects = (nroot*sizeof(Dosdir)+sectsize-1)/sectsize;	if(rootsects <= 0 || rootsects > 64)		return -1;	/* 	 *  read root. it is contiguous to make stuff like	 *  this easier	 */	root = malloc(rootsects*sectsize);	if(read(fd, root, rootsects*sectsize) != rootsects*sectsize)		return -1;	n = -1;	for(dp = root; dp < &root[nroot]; dp++)		if(memcmp(name, dp->name, 8) == 0 && memcmp(ext, dp->ext, 3) == 0){			n = GETSHORT(dp->start);			break;		}	free(root);	if(n < 0)		return -1;	/*	 *  dp->start is in cluster units, not sectors.  The first	 *  cluster is cluster 2 which starts immediately after the	 *  root directory	 */	return rootoff + rootsects*sectsize + (n-2)*sectsize*b->clustsize;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -