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

📄 nfs.c

📁 u-boot-1.1.6 for mini2440开发板。 支持网络下载
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * NFS support driver - based on etherboot and U-BOOT's tftp.c * * Masami Komiya <mkomiya@sonare.it> 2004 * *//* NOTE: the NFS code is heavily inspired by the NetBSD netboot code (read: * large portions are copied verbatim) as distributed in OSKit 0.97.  A few * changes were necessary to adapt the code to Etherboot and to fix several * inconsistencies.  Also the RPC message preparation is done "by hand" to * avoid adding netsprintf() which I find hard to understand and use.  *//* NOTE 2: Etherboot does not care about things beyond the kernel image, so * it loads the kernel image off the boot server (ARP_SERVER) and does not * access the client root disk (root-path in dhcpd.conf), which would use * ARP_ROOTSERVER.  The root disk is something the operating system we are * about to load needs to use.	This is different from the OSKit 0.97 logic.  *//* NOTE 3: Symlink handling introduced by Anselm M Hoffmeister, 2003-July-14 * If a symlink is encountered, it is followed as far as possible (recursion * possible, maximum 16 steps). There is no clearing of ".."'s inside the * path, so please DON'T DO THAT. thx. */#include <common.h>#include <command.h>#include <net.h>#include <malloc.h>#include "nfs.h"#include "bootp.h"/*#define NFS_DEBUG*/#if ((CONFIG_COMMANDS & CFG_CMD_NET) && (CONFIG_COMMANDS & CFG_CMD_NFS))#define HASHES_PER_LINE 65	/* Number of "loading" hashes per line	*/#define NFS_TIMEOUT 60static int fs_mounted = 0;static unsigned long rpc_id = 0;static int nfs_offset = -1;static int nfs_len;static char dirfh[NFS_FHSIZE];	/* file handle of directory */static char filefh[NFS_FHSIZE]; /* file handle of kernel image */static int	NfsDownloadState;static IPaddr_t NfsServerIP;static int	NfsSrvMountPort;static int	NfsSrvNfsPort;static int	NfsOurPort;static int	NfsTimeoutCount;static int	NfsState;#define STATE_PRCLOOKUP_PROG_MOUNT_REQ	1#define STATE_PRCLOOKUP_PROG_NFS_REQ	2#define STATE_MOUNT_REQ			3#define STATE_UMOUNT_REQ		4#define STATE_LOOKUP_REQ		5#define STATE_READ_REQ			6#define STATE_READLINK_REQ		7static char default_filename[64];static char *nfs_filename;static char *nfs_path;static char nfs_path_buff[2048];static __inline__ intstore_block (uchar * src, unsigned offset, unsigned len){	ulong newsize = offset + len;#ifdef CFG_DIRECT_FLASH_NFS	int i, rc = 0;	for (i=0; i<CFG_MAX_FLASH_BANKS; i++) {		/* start address in flash? */		if (load_addr + offset >= flash_info[i].start[0]) {			rc = 1;			break;		}	}	if (rc) { /* Flash is destination for this packet */		rc = flash_write ((uchar *)src, (ulong)(load_addr+offset), len);		if (rc) {			flash_perror (rc);			return -1;		}	} else#endif /* CFG_DIRECT_FLASH_NFS */	{		(void)memcpy ((void *)(load_addr + offset), src, len);	}	if (NetBootFileXferSize < (offset+len))		NetBootFileXferSize = newsize;	return 0;}static char*basename (char *path){	char *fname;	fname = path + strlen(path) - 1;	while (fname >= path) {		if (*fname == '/') {			fname++;			break;		}		fname--;	}	return fname;}static char*dirname (char *path){	char *fname;	fname = basename (path);	--fname;	*fname = '\0';	return path;}/**************************************************************************RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries**************************************************************************/static long *rpc_add_credentials (long *p){	int hl;	int hostnamelen;	char hostname[256];	strcpy (hostname, "");	hostnamelen=strlen (hostname);	/* Here's the executive summary on authentication requirements of the	 * various NFS server implementations:	Linux accepts both AUTH_NONE	 * and AUTH_UNIX authentication (also accepts an empty hostname field	 * in the AUTH_UNIX scheme).  *BSD refuses AUTH_NONE, but accepts	 * AUTH_UNIX (also accepts an empty hostname field in the AUTH_UNIX	 * scheme).  To be safe, use AUTH_UNIX and pass the hostname if we have	 * it (if the BOOTP/DHCP reply didn't give one, just use an empty	 * hostname).  */	hl = (hostnamelen + 3) & ~3;	/* Provide an AUTH_UNIX credential.  */	*p++ = htonl(1);		/* AUTH_UNIX */	*p++ = htonl(hl+20);		/* auth length */	*p++ = htonl(0);		/* stamp */	*p++ = htonl(hostnamelen);	/* hostname string */	if (hostnamelen & 3) {		*(p + hostnamelen / 4) = 0; /* add zero padding */	}	memcpy (p, hostname, hostnamelen);	p += hl / 4;	*p++ = 0;			/* uid */	*p++ = 0;			/* gid */	*p++ = 0;			/* auxiliary gid list */	/* Provide an AUTH_NONE verifier.  */	*p++ = 0;			/* AUTH_NONE */	*p++ = 0;			/* auth length */	return p;}/**************************************************************************RPC_LOOKUP - Lookup RPC Port numbers**************************************************************************/static voidrpc_req (int rpc_prog, int rpc_proc, uint32_t *data, int datalen){	struct rpc_t pkt;	unsigned long id;	uint32_t *p;	int pktlen;	int sport;	id = ++rpc_id;	pkt.u.call.id = htonl(id);	pkt.u.call.type = htonl(MSG_CALL);	pkt.u.call.rpcvers = htonl(2);	/* use RPC version 2 */	pkt.u.call.prog = htonl(rpc_prog);	pkt.u.call.vers = htonl(2);	/* portmapper is version 2 */	pkt.u.call.proc = htonl(rpc_proc);	p = (uint32_t *)&(pkt.u.call.data);	if (datalen)		memcpy ((char *)p, (char *)data, datalen*sizeof(uint32_t));	pktlen = (char *)p + datalen*sizeof(uint32_t) - (char *)&pkt;	memcpy ((char *)NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE, (char *)&pkt, pktlen);	if (rpc_prog == PROG_PORTMAP)		sport = SUNRPC_PORT;	else if (rpc_prog == PROG_MOUNT)		sport = NfsSrvMountPort;	else		sport = NfsSrvNfsPort;	NetSendUDPPacket (NetServerEther, NfsServerIP, sport, NfsOurPort, pktlen);}/**************************************************************************RPC_LOOKUP - Lookup RPC Port numbers**************************************************************************/static voidrpc_lookup_req (int prog, int ver){	uint32_t data[16];	data[0] = 0; data[1] = 0;	/* auth credential */	data[2] = 0; data[3] = 0;	/* auth verifier */	data[4] = htonl(prog);	data[5] = htonl(ver);	data[6] = htonl(17);	/* IP_UDP */	data[7] = 0;	rpc_req (PROG_PORTMAP, PORTMAP_GETPORT, data, 8);}/**************************************************************************NFS_MOUNT - Mount an NFS Filesystem**************************************************************************/static voidnfs_mount_req (char *path){	uint32_t data[1024];	uint32_t *p;	int len;	int pathlen;	pathlen = strlen (path);	p = &(data[0]);	p = (uint32_t *)rpc_add_credentials((long *)p);	*p++ = htonl(pathlen);	if (pathlen & 3) *(p + pathlen / 4) = 0;	memcpy (p, path, pathlen);	p += (pathlen + 3) / 4;	len = (uint32_t *)p - (uint32_t *)&(data[0]);	rpc_req (PROG_MOUNT, MOUNT_ADDENTRY, data, len);}/**************************************************************************NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server**************************************************************************/static voidnfs_umountall_req (void){	uint32_t data[1024];	uint32_t *p;	int len;	if ((NfsSrvMountPort == -1) || (!fs_mounted)) {		/* Nothing mounted, nothing to umount */		return;	}	p = &(data[0]);	p = (uint32_t *)rpc_add_credentials ((long *)p);	len = (uint32_t *)p - (uint32_t *)&(data[0]);	rpc_req (PROG_MOUNT, MOUNT_UMOUNTALL, data, len);}/*************************************************************************** * NFS_READLINK (AH 2003-07-14) * This procedure is called when read of the first block fails - * this probably happens when it's a directory or a symlink * In case of successful readlink(), the dirname is manipulated, * so that inside the nfs() function a recursion can be done. **************************************************************************/static voidnfs_readlink_req (void){	uint32_t data[1024];	uint32_t *p;	int len;	p = &(data[0]);	p = (uint32_t *)rpc_add_credentials ((long *)p);	memcpy (p, filefh, NFS_FHSIZE);	p += (NFS_FHSIZE / 4);	len = (uint32_t *)p - (uint32_t *)&(data[0]);	rpc_req (PROG_NFS, NFS_READLINK, data, len);}/**************************************************************************NFS_LOOKUP - Lookup Pathname**************************************************************************/static voidnfs_lookup_req (char *fname){	uint32_t data[1024];	uint32_t *p;	int len;	int fnamelen;	fnamelen = strlen (fname);	p = &(data[0]);	p = (uint32_t *)rpc_add_credentials ((long *)p);	memcpy (p, dirfh, NFS_FHSIZE);	p += (NFS_FHSIZE / 4);	*p++ = htonl(fnamelen);	if (fnamelen & 3) *(p + fnamelen / 4) = 0;	memcpy (p, fname, fnamelen);	p += (fnamelen + 3) / 4;	len = (uint32_t *)p - (uint32_t *)&(data[0]);	rpc_req (PROG_NFS, NFS_LOOKUP, data, len);}/**************************************************************************NFS_READ - Read File on NFS Server**************************************************************************/static voidnfs_read_req (int offset, int readlen){	uint32_t data[1024];	uint32_t *p;	int len;	p = &(data[0]);	p = (uint32_t *)rpc_add_credentials ((long *)p);	memcpy (p, filefh, NFS_FHSIZE);	p += (NFS_FHSIZE / 4);	*p++ = htonl(offset);	*p++ = htonl(readlen);	*p++ = 0;	len = (uint32_t *)p - (uint32_t *)&(data[0]);	rpc_req (PROG_NFS, NFS_READ, data, len);}/**************************************************************************RPC request dispatcher**************************************************************************/static voidNfsSend (void){#ifdef NFS_DEBUG	printf ("%s\n", __FUNCTION__);#endif	switch (NfsState) {	case STATE_PRCLOOKUP_PROG_MOUNT_REQ:		rpc_lookup_req (PROG_MOUNT, 1);		break;	case STATE_PRCLOOKUP_PROG_NFS_REQ:		rpc_lookup_req (PROG_NFS, 2);		break;	case STATE_MOUNT_REQ:		nfs_mount_req (nfs_path);		break;	case STATE_UMOUNT_REQ:		nfs_umountall_req ();		break;	case STATE_LOOKUP_REQ:		nfs_lookup_req (nfs_filename);		break;	case STATE_READ_REQ:		nfs_read_req (nfs_offset, nfs_len);		break;	case STATE_READLINK_REQ:		nfs_readlink_req ();		break;	}}/**************************************************************************Handlers for the reply from server**************************************************************************/

⌨️ 快捷键说明

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