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

📄 nfsroot.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
	oldfs = get_fs();	set_fs(get_ds());	iov.iov_base = buf;	iov.iov_len = size;	msg.msg_name = NULL;	msg.msg_iov = &iov;	msg.msg_iovlen = 1;	msg.msg_control = NULL;	result = sock->ops->sendmsg(sock, &msg, size, 0, 0);	set_fs(oldfs);	return (result != size);}/* *  Try to receive UDP packet. */static inline int root_recv_udp(struct socket *sock, void *buf, int size){	u32 oldfs;	int result;	struct msghdr msg;	struct iovec iov;	oldfs = get_fs();	set_fs(get_ds());	iov.iov_base = buf;	iov.iov_len = size;	msg.msg_name = NULL;	msg.msg_iov = &iov;	msg.msg_iovlen = 1;	msg.msg_control = NULL;	msg.msg_namelen = 0;	result = sock->ops->recvmsg(sock, &msg, size, O_NONBLOCK, 0, &msg.msg_namelen);	set_fs(oldfs);	return result;}/* *  Initialize BOOTP extension fields in the request. */static void root_bootp_init_ext(u8 *e){	*e++ = 99;		/* RFC1048 Magic Cookie */	*e++ = 130;	*e++ = 83;	*e++ = 99;	*e++ = 1;		/* Subnet mask request */	*e++ = 4;	e += 4;	*e++ = 3;		/* Default gateway request */	*e++ = 4;	e += 4;	*e++ = 12;		/* Host name request */	*e++ = 32;	e += 32;	*e++ = 40;		/* NIS Domain name request */	*e++ = 32;	e += 32;	*e++ = 17;		/* Boot path */	*e++ = 32;	e += 32;	*e = 255;		/* End of the list */}/* *  Deinitialize the BOOTP mechanism. */static void root_bootp_close(void){	if (bootp_xmit_fd != -1)		sys_close(bootp_xmit_fd);	if (bootp_recv_fd != -1)		sys_close(bootp_recv_fd);	root_del_bootp_route();	root_free_bootp();}/* *  Initialize the BOOTP mechanism. */static int root_bootp_open(void){	struct open_dev *openp;	struct device *dev, *best_dev;	/*	 * Select the best interface for BOOTP. We try to select a first	 * Ethernet-like interface. It's shame I know no simple way how to send	 * BOOTP's to all interfaces, but it doesn't apply to usual diskless	 * stations as they don't have multiple interfaces.	 */	best_dev = NULL;	for (openp = open_base; openp != NULL; openp = openp->next) {		dev = openp->dev;		if (dev->flags & IFF_BROADCAST) {			if (!best_dev ||			   ((best_dev->flags & IFF_NOARP) && !(dev->flags & IFF_NOARP)))				best_dev = dev;			}		}	if (!best_dev) {		printk(KERN_ERR "BOOTP: This cannot happen!\n");		return -1;	}	bootp_dev = best_dev;	/* Allocate memory for BOOTP packets */	if (root_alloc_bootp())		return -1;	/* Construct BOOTP request */	memset(xmit_bootp, 0, sizeof(struct bootp_pkt));	xmit_bootp->op = BOOTP_REQUEST;	get_random_bytes(&xmit_bootp->xid, sizeof(xmit_bootp->xid));	xmit_bootp->htype = best_dev->type;	xmit_bootp->hlen = best_dev->addr_len;	memcpy(xmit_bootp->hw_addr, best_dev->dev_addr, best_dev->addr_len);	root_bootp_init_ext(xmit_bootp->vendor_area);#ifdef NFSROOT_BOOTP_DEBUG	{		int x;		printk(KERN_NOTICE "BOOTP: XID=%08x, DE=%s, HT=%02x, HL=%02x, HA=",			xmit_bootp->xid,			best_dev->name,			xmit_bootp->htype,			xmit_bootp->hlen);		for(x=0; x<xmit_bootp->hlen; x++)			printk("%02x", xmit_bootp->hw_addr[x]);		printk("\n");	}#endif	/* Create default route to that interface */	if (root_add_bootp_route())		return -1;	/* Open the sockets */	if (root_open_udp_sock(&bootp_xmit_fd, &bootp_xmit_sock) ||	    root_open_udp_sock(&bootp_recv_fd, &bootp_recv_sock))		return -1;	/* Bind/connect the sockets */	((struct sock *) bootp_xmit_sock->data) -> broadcast = 1;	((struct sock *) bootp_xmit_sock->data) -> reuse = 1;	((struct sock *) bootp_recv_sock->data) -> reuse = 1;	if (root_bind_udp_sock(bootp_recv_sock, INADDR_ANY, 68) ||	    root_bind_udp_sock(bootp_xmit_sock, INADDR_ANY, 68) ||	    root_connect_udp_sock(bootp_xmit_sock, INADDR_BROADCAST, 67))		return -1;	return 0;}/* *  Send BOOTP request. */static int root_bootp_send(u32 jiffies){	xmit_bootp->secs = htons(jiffies / HZ);	return root_send_udp(bootp_xmit_sock, xmit_bootp, sizeof(struct bootp_pkt));}/* *  Copy BOOTP-supplied string if not already set. */static int root_bootp_string(char *dest, char *src, int len, int max){	if (*dest || !len)		return 0;	if (len > max-1)		len = max-1;	strncpy(dest, src, len);	dest[len] = '\0';	return 1;}/* *  Process BOOTP extension. */static void root_do_bootp_ext(u8 *ext){#ifdef NFSROOT_BOOTP_DEBUG	u8 *c;	printk("BOOTP: Got extension %02x",*ext);	for(c=ext+2; c<ext+2+ext[1]; c++)		printk(" %02x", *c);	printk("\n");#endif	switch (*ext++) {		case 1:		/* Subnet mask */			if (netmask.sin_addr.s_addr == INADDR_NONE)				memcpy(&netmask.sin_addr.s_addr, ext+1, 4);			break;		case 3:		/* Default gateway */			if (gateway.sin_addr.s_addr == INADDR_NONE)				memcpy(&gateway.sin_addr.s_addr, ext+1, 4);			break;		case 12:	/* Host name */			root_bootp_string(system_utsname.nodename, ext+1, *ext, __NEW_UTS_LEN);			break;		case 40:	/* NIS Domain name */			root_bootp_string(system_utsname.domainname, ext+1, *ext, __NEW_UTS_LEN);			break;		case 17:	/* Root path */			root_bootp_string(nfs_path, ext+1, *ext, NFS_MAXPATHLEN);			break;	}}/* *  Receive BOOTP request. */static void root_bootp_recv(void){	int len;	u8 *ext, *end, *opt;	len = root_recv_udp(bootp_recv_sock, recv_bootp, sizeof(struct bootp_pkt));	if (len < 0)		return;	/* Check consistency of incoming packet */	if (len < 300 ||			/* See RFC 1542:2.1 */	    recv_bootp->op != BOOTP_REPLY ||	    recv_bootp->htype != xmit_bootp->htype ||	    recv_bootp->hlen != xmit_bootp->hlen ||	    recv_bootp->xid != xmit_bootp->xid) {#ifdef NFSROOT_BOOTP_DEBUG		printk("?");#endif		return;		}	/* Record BOOTP packet arrival in the global variables */	cli();	if (pkt_arrived) {		sti();		return;	}	pkt_arrived = ARRIVED_BOOTP;	sti();	root_dev = bootp_dev;	/* Extract basic fields */	myaddr.sin_addr.s_addr = recv_bootp->your_ip;	if (server.sin_addr.s_addr==INADDR_NONE)		server.sin_addr.s_addr = recv_bootp->server_ip;	/* Parse extensions */	if (recv_bootp->vendor_area[0] == 99 &&	/* Check magic cookie */	    recv_bootp->vendor_area[1] == 130 &&	    recv_bootp->vendor_area[2] == 83 &&	    recv_bootp->vendor_area[3] == 99) {		ext = &recv_bootp->vendor_area[4];		end = (u8 *) recv_bootp + len;		while (ext < end && *ext != 255) {			if (*ext == 0)		/* Padding */				ext++;			else {				opt = ext;				ext += ext[1] + 2;				if (ext <= end)					root_do_bootp_ext(opt);			}		}	}}#endif/***************************************************************************			Dynamic configuration of IP. ***************************************************************************/#ifdef CONFIG_RNFS_DYNAMIC/* *  Determine client and server IP numbers and appropriate device by using *  the RARP and BOOTP protocols. */static int root_auto_config(void){	int retries;	unsigned long timeout, jiff;	unsigned long start_jiffies;	/*	 * If neither BOOTP nor RARP was selected, return with an error. This	 * routine gets only called when some pieces of information are mis-	 * sing, and without BOOTP and RARP we are not able to get that in-	 * formation.	 */	if (!bootp_flag && !rarp_flag) {		printk(KERN_ERR "Root-NFS: Neither RARP nor BOOTP selected.\n");		return -1;	}#ifdef CONFIG_RNFS_BOOTP	if (bootp_flag && !bootp_dev_count) {		printk(KERN_ERR "Root-NFS: No suitable device for BOOTP found.\n");		bootp_flag = 0;	}#else	bootp_flag = 0;#endif#ifdef CONFIG_RNFS_RARP	if (rarp_flag && !rarp_dev_count) {		printk(KERN_ERR "Root-NFS: No suitable device for RARP found.\n");		rarp_flag = 0;	}#else	rarp_flag = 0;#endif	if (!bootp_flag && !rarp_flag)		/* Error message already printed */		return -1;	/*	 * Setup RARP and BOOTP protocols	 */#ifdef CONFIG_RNFS_RARP	if (rarp_flag)		root_rarp_open();#endif#ifdef CONFIG_RNFS_BOOTP	if (bootp_flag && root_bootp_open() < 0) {		root_bootp_close();		return -1;	}#endif	/*	 * Send requests and wait, until we get an answer. This loop	 * seems to be a terrible waste of CPU time, but actually there is	 * only one process running at all, so we don't need to use any	 * scheduler functions.	 * [Actually we could now, but the nothing else running note still 	 *  applies.. - AC]	 */	printk(KERN_NOTICE "Sending %s%s%s requests...",		bootp_flag ? "BOOTP" : "",		bootp_flag && rarp_flag ? " and " : "",		rarp_flag ? "RARP" : "");	start_jiffies = jiffies;	retries = CONF_RETRIES;	get_random_bytes(&timeout, sizeof(timeout));	timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned) CONF_TIMEOUT_RANDOM);	for(;;) {#ifdef CONFIG_RNFS_BOOTP		if (bootp_flag && root_bootp_send(jiffies - start_jiffies) < 0) {			printk(" BOOTP failed!\n");			root_bootp_close();			bootp_flag = 0;			if (!rarp_flag)				break;		}#endif#ifdef CONFIG_RNFS_RARP		if (rarp_flag)			root_rarp_send();#endif		printk(".");		jiff = jiffies + timeout;		while (jiffies < jiff && !pkt_arrived)#ifdef CONFIG_RNFS_BOOTP			root_bootp_recv();#else			;#endif		if (pkt_arrived)			break;		if (! --retries) {			printk(" timed out!\n");			break;		}		timeout = timeout CONF_TIMEOUT_MULT;		if (timeout > CONF_TIMEOUT_MAX)			timeout = CONF_TIMEOUT_MAX;	}#ifdef CONFIG_RNFS_RARP	if (rarp_flag)		root_rarp_close();#endif#ifdef CONFIG_RNFS_BOOTP	if (bootp_flag)		root_bootp_close();#endif	if (!pkt_arrived)		return -1;	printk(" OK\n");	printk(KERN_NOTICE "Root-NFS: Got %s answer from %s, ",		(pkt_arrived == ARRIVED_BOOTP) ? "BOOTP" : "RARP",		in_ntoa(server.sin_addr.s_addr));	printk("my address is %s\n", in_ntoa(myaddr.sin_addr.s_addr));	return 0;}#endif/***************************************************************************			     Parsing of options ***************************************************************************//* *  The following integer options are recognized */static struct nfs_int_opts {	char *name;	int  *val;} root_int_opts[] = {	{ "port",	&nfs_port },	{ "rsize",	&nfs_data.rsize },	{ "wsize",	&nfs_data.wsize },	{ "timeo",	&nfs_data.timeo },	{ "retrans",	&nfs_data.retrans },	{ "acregmin",	&nfs_data.acregmin },	{ "acregmax",	&nfs_data.acregmax },	{ "acdirmin",	&nfs_data.acdirmin },	{ "acdirmax",	&nfs_data.acdirmax },	{ NULL,		NULL }};/* *  And now the flag options */static struct nfs_bool_opts {	char *name;	int  and_mask;	int  or_mask;} root_bool_opts[] = {	{ "soft",	~NFS_MOUNT_SOFT,	NFS_MOUNT_SOFT },	{ "hard",	~NFS_MOUNT_SOFT,	0 },	{ "intr",	~NFS_MOUNT_INTR,	NFS_MOUNT_INTR },	{ "nointr",	~NFS_MOUNT_INTR,	0 },	{ "posix",	~NFS_MOUNT_POSIX,	NFS_MOUNT_POSIX },	{ "noposix",	~NFS_MOUNT_POSIX,	0 },	{ "cto",	~NFS_MOUNT_NOCTO,	0 },	{ "nocto",	~NFS_MOUNT_NOCTO,	NFS_MOUNT_NOCTO },	{ "ac",		~NFS_MOUNT_NOAC,	0 },	{ "noac",	~NFS_MOUNT_NOAC,	NFS_MOUNT_NOAC },	{ NULL,		0,			0 }};/* *  Prepare the NFS data structure and parse any options. This tries to *  set as many values in the nfs_data structure as known right now. */static int root_nfs_name(char *name){	char buf[NFS_MAXPATHLEN];	char *cp, *cq, *options, *val;	int octets = 0;	/* It is possible to override the server IP number here */	cp = cq = name;	while (octets < 4) {		while (*cp >= '0' && *cp <= '9')			cp++;		if (cp == cq || cp - cq > 3)			break;		if (*cp == '.' || octets == 3)			octets++;		if (octets < 4)			cp++;		cq = cp;	}	if (octets == 4 && (*cp == ':' || *cp == '\0')) {		if (*cp == ':')			*cp++ = '\0';		server.sin_addr.s_addr = in_aton(name);		name = cp;	}	/* Clear the nfs_data structure and setup the server hostname */	memset(&nfs_data, 0, sizeof(nfs_data));	strncpy(nfs_data.hostname, in_ntoa(server.sin_addr.s_addr),						sizeof(nfs_data.hostname)-1);	/* Set the name of the directory to mount */	if (nfs_path[0] == '\0' || strncmp(name, "default", 7))		strncpy(buf, name, NFS_MAXPATHLEN);	else		strncpy(buf, nfs_path, NFS_MAXPATHLEN);	if ((options = strchr(buf, ',')))		*options++ = '\0';	if (!strcmp(buf, "default"))		strcpy(buf, NFS_ROOT);	cp = in_ntoa(myaddr.sin_addr.s_addr);	if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {		printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");		return -1;	}	/* update nfs_path with path from nfsroot=... command line parameter */	if (*buf)		sprintf(nfs_path, buf, cp);	/* Set some default values */	nfs_port          = -1;	nfs_data.version  = NFS_MOUNT_VERSION;	nfs_data.flags    = 0;	nfs_data.rsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;	nfs_data.wsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;	nfs_data.timeo    = 7;	nfs_data.retrans  = 3;	nfs_data.acregmin = 3;	nfs_data.acregmax = 60;	nfs_data.acdirmin = 30;	nfs_data.acdirmax = 60;	/* Process any options */	if (options) {		cp = strtok(options, ",");		while (cp) {			if ((val = strchr(cp, '='))) {				struct nfs_int_opts *opts = root_int_opts;				*val++ = '\0';				while (opts->name && strcmp(opts->name, cp))					opts++;				if (opts->name)					*(opts->val) = (int) simple_strtoul(val, NULL, 10);			} else {				struct nfs_bool_opts *opts = root_bool_opts;				while (opts->name && strcmp(opts->name, cp))					opts++;				if (opts->name) {					nfs_data.flags &= opts->and_mask;					nfs_data.flags |= opts->or_mask;				}			}			cp = strtok(NULL, ",");		}	}	return 0;}/* *  Tell the user what's going on. */#ifdef NFSROOT_DEBUGstatic void root_nfs_print(void){#define IN_NTOA(x) (((x) == INADDR_NONE) ? "none" : in_ntoa(x))	printk(KERN_NOTICE "Root-NFS: IP config: dev=%s, ",		root_dev ? root_dev->name : "none");

⌨️ 快捷键说明

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