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

📄 tfs.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	and a power hit occurred.  Refer to notes in tfsadd() for details.
 *	There are a few cases to be covered here...
 *	1. there is no stale file; so there is nothing to do.
 *	2. there is a stale file, but no other file with the same name...
 *		In this case, the stale file must be copied to another file (with the
 *		TFS_NSTALE flag set) and the stale file is deleted.
 *	3. there is stale file and another file with the same name...
 *		In this case, the stale file is simply deleted because the other file
 *		with the same name is newer.
 */ 
static void
tfsstalecheck(void)
{
	int		err;
	ulong	flags;
	TDEV	*tdp;
	TFILE	*tfp, *tfpa;
	char	buf[16];

	tfpa = (TFILE *)0;
	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		tfp = (TFILE *)tdp->start;
		tfpa = (TFILE *)0;
		while(validtfshdr(tfp)) {
			if (TFS_FILEEXISTS(tfp)) {
				if (tfpa) {
					if (!strcmp(TFS_NAME(tfp),TFS_NAME(tfpa))) {
						_tfsunlink(TFS_NAME(tfpa));
						return;
					}
				}
				else if (TFS_STALE(tfp)) {
					tfpa = tfp;
				}
			}
			tfp = nextfp(tfp,tdp);
		}
		if (tfpa)
			break;
	}
	if (tfpa) {
		char	name[TFSNAMESIZE+1];

		strcpy(name,TFS_NAME(tfpa));
		printf("TFS stale fixup (%s)...\n",name);
		if (pollConsole("ok?")) {
			printf("aborted\n");
			return;
		}
		flags = TFS_FLAGS(tfpa) | TFS_NSTALE;
		err = tfsadd(TFS_NAME(tfpa),TFS_INFO(tfpa),tfsflagsbtoa(flags,buf),
			(char *)(TFS_BASE(tfpa)),TFS_SIZE(tfpa));

		/* If rewrite was successful, then remove the stale one;
		 * else, leave it there and report the error.
		 */
		if (err == TFS_OKAY) {
			_tfsunlink(TFS_NAME(tfpa));
		}
		else {
			printf("TFS stalecheck(%s) error: %s\n",name,tfserrmsg(err));
		}
	}
}

/* tfsdevtblinit():
 *	Transfer the information in tfsdevtbl (in tfsdev.h) to tfsDeviceTbl[].
 *	In most cases, this will be a simple copy.  If the device flag is set
 *	to indicate that the initalization is dynamic, then use the flash 
 *	ops to retrieve the information from the specified bank.
 *
 *	For dynamic configuration, the "start" member of the tfsdev structure
 *	must be set in tfsdev.h and the "devinfo & TFS_DEVINFO_BANKMASK" area
 *	must contain the number of the last flash bank that is to be part of
 *	the TFS device.  Typically this value is the same bank number as the
 *	starting bank, but it could span across multiple contiguous banks
 *	if the hardware is set up that way.
 *
 *	To support the use of top-boot devices, plus the TFS requirement that
 *	the SPARE sector be at-least as large as any other sector in the device,
 *	this code will automatically step down the sector list until it finds
 *	the first large sector below all the small ones usually at the top of
 *	a top-boot device.  The call to lastlargesector() takes care of this.
 *
 *	NOTE:
 *	 This dynamic configuration assumes that the end of the TFS space is
 *	 just below the beginning of the spare space.
 *
 */
void
tfsdevtblinit(void)
{
	int		i, startsector, endsector, bank;
	TDEV	*tDp, *tdp;

	for(i=0;i<TFSDEVTOT;i++) {
		if (alt_tfsdevtbl[i].prefix != (char *)0xffffffff)
			tdp = &alt_tfsdevtbl[i];
		else
			tdp = &tfsdevtbl[i];

		tDp = &tfsDeviceTbl[i];
		*tDp = *tdp;
		if (i == TFSDEVTOT-1)
			break;

		if (tdp->devinfo & TFS_DEVINFO_DYNAMIC) {
			bank = tDp->devinfo & TFS_DEVINFO_BANKMASK;

			/* The spare sector may not be the last sector in the device...
			 * device.  Especially if the device is TopBoot type.
			 */
			if (lastlargesector(bank,&endsector,
				(int *)&tDp->sparesize,(uchar **)&tDp->spare) == -1)
				break;

			tDp->end = tDp->spare - 1;
			if (addrtosector((uchar *)tDp->start,&startsector,0,0) == -1)
				break;
			tDp->sectorcount = endsector - startsector;
		}
	}
}

/* tfsstartup():
 *	Called at system startup to get things properly initialized.
 */
void
tfsstartup()
{
	static	int beenhere;
	TDEV	*tdp;

	tfsdevtblinit();
	tfsclear((TDEV *)0);

	/* No need to walk through the entire TFS init if it has already
	 * been done...
	 */
	if (beenhere)
		return;

	/* Step through the table looking for RAM-based TFS devices.
	 * If the AUTOINIT flag is set, then initialize that device.
	 */
	for(tdp = tfsDeviceTbl;tdp->prefix != 0;tdp++) {
		if (((tdp->devinfo & TFS_DEVTYPE_MASK) == TFS_DEVTYPE_NVRAM) &&
			(tdp->devinfo & TFS_DEVINFO_AUTOINIT)) {
				_tfsinit(tdp);
		}
	}

	tfsfixup(3,0);
	tfsstalecheck();
	beenhere = 1;
}

/* tfsexec: Treat the file as machine code that is COFF or ELF. */

static int
tfsexec(TFILE *fp,int verbose)
{
	int err, (*entry)();
	long	address;

	err = tfsloadebin(fp,verbose,&address,0,0);
	if (err != TFS_OKAY)
		return(err);

	entry = (int(*)())address;
	entry();			/* Call entrypoint (may not return). */
	return(TFS_OKAY);
}

/* struct tfsran:
	Used by tfsrunboot only.  No need to put this in tfs.h.
 */
struct tfsran {
	char name[TFSNAMESIZE+1];
};

/* tfsrunboot():
 *	This function is called at monitor startup.  It scans the list of
 *	files built by tfsreorder() and executes each file in the list that has
 *	the BRUN flag set.  As each file is run its name is added to the
 *	ranlist[] table.
 *	
 *	After each file is run, there is a check made to see if the flash has
 *	been modified.  If yes, then tfsreorder() is run again and we start 
 *	over at the top of the list of files organized by tfsreorder().  As
 *	we step through the tfsAlist[] array, if the file has a BRUN flag set
 *	but it is already in the ranlist[] table, it is not run again.
 *	   
 *	This scheme allows a file in the initial list of BRUN files to modify
 *	the file list without confusing the list of files that are to be run.
 *	Files (even new BRUN files) can be added to the list by some other BRUN
 *	file, and these new files will be run.
 */
int
tfsrunboot(void)
{
	static	struct	tfsran *ranlist;
	char	*argv[2];
	int		rancnt, aidx, ridx, err, fmodcnt;

	/* The argv[] array is used by tfsrun(); argv[0] is name of file to be
	 * executed, argv[1] must be nulled to indicate no command line args
	 * passed to the BRUN file/script.
	 */
	argv[1] = (char *)0;

	/* Keep a local copy of tfsFmodCount so that we can determine if flash
	 * was modified by one of the BRUN files executed.
	 */
	fmodcnt = tfsFmodCount;

	/* Create list of file pointers (tfsAlist[]) in alphabetical order
	 * based on name...
	 */
	if ((err = tfsreorder()) < 0) {
		printf("tfsrunboot() reorder1: %s\n",tfserrmsg(err));
		return(-1);
	}

	/* Clear the ranlist pointer. This pointer is the base address of a
	 * list of file names that have	been run.
	 */
	rancnt = 0;
	ranlist = (struct tfsran *)0;

restartloop:
	for (aidx=0;tfsAlist[aidx];aidx++) {
		char	fname[TFSNAMESIZE+1];
		int		alreadyran;
		TFILE	*fp;
		struct	tfsran *rp;

		fp = tfsAlist[aidx];
		strcpy(fname,TFS_NAME(fp));

		/* If the file has no BRUN flag set, just continue.  If a BRUN flag
		 * is set, then see if the file has already been run.  If yes, then
		 * just continue; else run the file.
		 */
		alreadyran = 0;
		if (fp->flags & (TFS_BRUN | TFS_QRYBRUN)) {
			for(ridx=0;ridx<rancnt;ridx++) {
				if (!strcmp(ranlist[ridx].name,fname)) {
					alreadyran = 1;
					break;
				}
			}
		}
		else
			continue;			/* No BRUN flag set. */

		if (alreadyran) {		/* BRUN flag set, but file has already		*/
			continue;			/* been run.								*/
		}

		err = TFS_OKAY;
		argv[0] = fname;

		/* At this point we know the file is a BRUN type, so just see if
		 * the query should precede the run...
		 */
		if (fp->flags & TFS_QRYBRUN) {
			int pollval;
			char query[TFSNAMESIZE+8];

			sprintf(query,"%s?",fname);
			pollval = pollConsole(query);
#ifdef TFS_AUTOBOOT_CANCEL_CHAR
			if (pollval == (int)TFS_AUTOBOOT_CANCEL_CHAR)
				continue;
#else
			if (pollval)
				continue;
#endif
		}
		/* Increase the size of the ranlist[] table and add the file that
		 * is about to be run to that list...
		 */
		rancnt++;
		rp = (struct tfsran*)realloc((char *)ranlist,
			rancnt*sizeof(struct tfsran));

		if (!rp) {
			if (ranlist)
				free((char *)ranlist);
			printf("tfsrunboot() runlist realloc failure\n");
			return(-1);
		}

		ranlist = rp;
		strcpy(ranlist[rancnt-1].name,fname);

		/* Run the executable...
		 */
		if (fp->flags & TFS_BRUN) {
			err = tfsrun_abortableautoboot(argv,0);
		}
		else {
			err = tfsrun(argv,0);
		}
	
		if (err != TFS_OKAY)
			printf("%s: %s\n",fname,tfserrmsg(err));

		/* If flash has been modified, then we must re-run tfsreorder() and
		 * start over...
		 */
		if (fmodcnt != tfsFmodCount) {
			if ((err = tfsreorder()) < 0) {
				printf("tfsrunboot() reorder2: %s\n",tfserrmsg(err));
				return(err);
			}
			fmodcnt = tfsFmodCount;
			goto restartloop;
		}
	}
	if (ranlist)
		free((char *)ranlist);
	return(rancnt);
}

/* tfsreorder():
 *	Populate the tfsAlist[] array with the list of currently active file
 *	pointers, but put in alphabetical (lexicographical using strcmp()) order
 *	based on the filename.
 *	Note that after each file addition/deletion, this must be re-run.
 */
int
tfsreorder(void)
{
	TFILE	*fp;
	TDEV	*tdp;
	int		i, j, tot;

	/* Determine how many valid files exist, and create tfsAlist array:
	 */
	tot = 0;

	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		fp = (TFILE *)tdp->start;
		while(validtfshdr(fp)) {
			if (TFS_FILEEXISTS(fp))
				tot++;
			fp = nextfp(fp,tdp);
		}
	}

	/* If tfsAlist already exists, and is already big enough, then
	 * don't do any allocation; otherwise, create the array with one extra
	 * slot for a NULL pointer used elsewhere as an end-of-list indicator.
	 */
	if (tot > tfsAlistSize) {
		tfsAlist = (TFILE **)realloc((char *)tfsAlist,
			(tot+1) * sizeof(TFILE **));
		if (!tfsAlist) {
			tfsAlistSize = 0;
			return(TFSERR_MEMFAIL);
		}
		tfsAlistSize = tot;
	}

	/* Clear the entire table (plus the extra one at the end):
	 */
	for(i=0;i<=tot;i++)
		tfsAlist[i] = (TFILE *)0;

	/* Populate tfsAlist[] with a pointer to each active file
	 * in flash as they exist in memory...
	 */
	i = 0;

	for(tdp=tfsDeviceTbl;tdp->start != TFSEOT;tdp++) {
		fp = (TFILE *)tdp->start;
		while(validtfshdr(fp)) {
			if (TFS_FILEEXISTS(fp)) {
				tfsAlist[i++] = fp;
			}
			fp = nextfp(fp,tdp);
		}
	}

	/* Now run a bubble sort on that list based on the lexicographical
	 * ordering returned by strcmp...
	 */
	for(i=1;i<tot;++i) {
		for(j=tot-1;j>=i;--j) {
			if (strcmp(TFS_NAME(tfsAlist[j-1]),TFS_NAME(tfsAlist[j])) > 0) {
				fp = tfsAlist[j-1];
				tfsAlist[j-1] = tfsAlist[j];
				tfsAlist[j] = fp;
			}
		}
	}
	return(tot);
}

/* tfsheadroom():
 * Based on the current offset into the file specified by the incoming
 * descriptor, return the gap between the current offset and the end
 * of the file.
 */
static long
tfsheadroom(int fd)
{
	struct tfsdat *tdat;

	if ((fd < 0) || (fd >= TFS_MAXOPEN))
		return(TFSERR_BADARG);

	tdat = &tfsSlots[fd];
	if (tdat->flagmode & TFS_RDONLY)
		return(tdat->hdr.filsize - tdat->offset);
	else
		return(tdat->hwp - tdat->offset);
}

/* tfstell():
 *	Return the offset into the file that is specified by the incoming
 *	descriptor.
 *	MONLIB NOTICE: this function is accessible through monlib.c.
 */
long
tfstell(int fd)
{
	if ((fd < 0) || (fd >= TFS_MAXOPEN))
		return(TFSERR_BADARG);
	return(tfsSlots[fd].offset);
}

/* tfscompare():
 *	Compare the content of the file specified by tfp with the content pointed
 *	to by the remaining arguments.  If identical, return 0; else return -1.
 */
static int
tfscompare(TFILE *tfp,char *name, char *info, char *flags, uchar *src, int size)
{
	ulong bflags;

	/* Compare size, name, info field, flags and data:
	 */

	/* Size...
	 */
	if (TFS_SIZE(tfp) != size)
		return(-1);

	/* Name...
	 */
	if (strcmp(name,TFS_NAME(tfp)))
		return(-1);

⌨️ 快捷键说明

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